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
e7c88789
Commit
e7c88789
authored
Feb 12, 2016
by
Don Gagne
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Correctly handle large numbers of waypoints
parent
4aff4121
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
16000 additions
and
162 deletions
+16000
-162
MissionEditor.qml
src/MissionEditor/MissionEditor.qml
+24
-7
MissionController.cc
src/MissionManager/MissionController.cc
+34
-30
MissionController.h
src/MissionManager/MissionController.h
+3
-3
MissionItemEditor.qml
src/QmlControls/MissionItemEditor.qml
+114
-122
100Waypoints.mission
test/100Waypoints.mission
+1607
-0
100Waypoints.waypoints copy.txt
test/100Waypoints.waypoints copy.txt
+101
-0
800Waypoints.mission
test/800Waypoints.mission
+13271
-0
800Waypoints.waypoints.txt
test/800Waypoints.waypoints.txt
+830
-0
MissionPlanner.waypoints.txt
test/MissionPlanner.waypoints.txt
+16
-0
No files found.
src/MissionEditor/MissionEditor.qml
View file @
e7c88789
...
...
@@ -383,8 +383,7 @@ QGCView {
spacing
:
_margin
/
2
orientation
:
ListView
.
Vertical
model
:
controller
.
missionItems
property
real
_maxItemHeight
:
0
cacheBuffer
:
height
*
2
delegate
:
MissionItemEditor
{
missionItem
:
object
...
...
@@ -399,11 +398,6 @@ QGCView {
controller
.
removeMissionItem
(
object
.
sequenceNumber
)
}
onRemoveAll
:
{
itemDragger
.
clearItem
()
controller
.
removeAllMissionItems
()
}
onInsert
:
{
controller
.
insertMissionItem
(
editorMap
.
center
,
i
)
setCurrentItem
(
i
)
...
...
@@ -601,6 +595,20 @@ QGCView {
}
}
Component
{
id
:
removeAllPromptDialog
QGCViewMessage
{
message
:
"
Are you sure you want to delete all mission items?
"
function
accept
()
{
itemDragger
.
clearItem
()
controller
.
removeAllMissionItems
()
hideDialog
()
}
}
}
Component
{
id
:
syncDropDownComponent
...
...
@@ -671,6 +679,15 @@ QGCView {
}
}
}
QGCButton
{
text
:
"
Remove all
"
onClicked
:
{
syncButton
.
hideDropDown
()
_root
.
showDialog
(
removeAllPromptDialog
,
"
Delete all
"
,
_root
.
showDialogDefaultWidth
,
StandardButton
.
Yes
|
StandardButton
.
No
)
}
}
/*
FIXME: autoSync is temporarily disconnected since it's still buggy
...
...
src/MissionManager/MissionController.cc
View file @
e7c88789
...
...
@@ -72,7 +72,7 @@ void MissionController::start(bool editMode)
// We start with an empty mission
_missionItems
=
new
QmlObjectListModel
(
this
);
_addPlannedHomePosition
(
false
/* addToCenter */
);
_addPlannedHomePosition
(
_missionItems
,
false
/* addToCenter */
);
_initAllMissionItems
();
}
...
...
@@ -94,7 +94,7 @@ void MissionController::_newMissionItemsAvailableFromVehicle(void)
qCDebug
(
MissionControllerLog
)
<<
"loading from vehicle count"
<<
_missionItems
->
count
();
if
(
!
_activeVehicle
->
firmwarePlugin
()
->
sendHomePositionToVehicle
()
||
_missionItems
->
count
()
==
0
)
{
_addPlannedHomePosition
(
true
/* addToCenter */
);
_addPlannedHomePosition
(
_missionItems
,
true
/* addToCenter */
);
}
_missionItemsRequested
=
false
;
...
...
@@ -176,14 +176,16 @@ void MissionController::removeMissionItem(int index)
void
MissionController
::
removeAllMissionItems
(
void
)
{
if
(
_missionItems
)
{
while
(
_missionItems
->
count
()
!=
1
)
{
removeMissionItem
(
_missionItems
->
count
()
-
1
);
}
QmlObjectListModel
*
oldItems
=
_missionItems
;
_missionItems
=
new
QmlObjectListModel
(
this
);
_addPlannedHomePosition
(
_missionItems
,
false
/* addToCenter */
);
_initAllMissionItems
();
oldItems
->
deleteLater
();
}
}
#ifndef __mobile__
bool
MissionController
::
_loadJsonMissionFile
(
const
QByteArray
&
bytes
,
QString
&
errorString
)
bool
MissionController
::
_loadJsonMissionFile
(
const
QByteArray
&
bytes
,
Q
mlObjectListModel
*
missionItems
,
Q
String
&
errorString
)
{
QJsonParseError
jsonParseError
;
QJsonDocument
jsonDoc
(
QJsonDocument
::
fromJson
(
bytes
,
&
jsonParseError
));
...
...
@@ -219,7 +221,7 @@ bool MissionController::_loadJsonMissionFile(const QByteArray& bytes, QString& e
MissionItem
*
item
=
new
MissionItem
(
_activeVehicle
,
this
);
if
(
item
->
load
(
itemValue
.
toObject
(),
errorString
))
{
_
missionItems
->
append
(
item
);
missionItems
->
append
(
item
);
}
else
{
return
false
;
}
...
...
@@ -230,12 +232,12 @@ bool MissionController::_loadJsonMissionFile(const QByteArray& bytes, QString& e
MissionItem
*
item
=
new
MissionItem
(
_activeVehicle
,
this
);
if
(
item
->
load
(
json
[
_jsonPlannedHomePositionKey
].
toObject
(),
errorString
))
{
_
missionItems
->
insert
(
0
,
item
);
missionItems
->
insert
(
0
,
item
);
}
else
{
return
false
;
}
}
else
{
_addPlannedHomePosition
(
true
/* addToCenter */
);
_addPlannedHomePosition
(
missionItems
,
true
/* addToCenter */
);
}
return
true
;
...
...
@@ -243,7 +245,7 @@ bool MissionController::_loadJsonMissionFile(const QByteArray& bytes, QString& e
#endif
#ifndef __mobile__
bool
MissionController
::
_loadTextMissionFile
(
QTextStream
&
stream
,
QString
&
errorString
)
bool
MissionController
::
_loadTextMissionFile
(
QTextStream
&
stream
,
Q
mlObjectListModel
*
missionItems
,
Q
String
&
errorString
)
{
bool
addPlannedHomePosition
=
false
;
...
...
@@ -267,7 +269,7 @@ bool MissionController::_loadTextMissionFile(QTextStream& stream, QString& error
MissionItem
*
item
=
new
MissionItem
(
_activeVehicle
,
this
);
if
(
item
->
load
(
stream
))
{
_
missionItems
->
append
(
item
);
missionItems
->
append
(
item
);
}
else
{
errorString
=
QStringLiteral
(
"The mission file is corrupted."
);
return
false
;
...
...
@@ -278,12 +280,12 @@ bool MissionController::_loadTextMissionFile(QTextStream& stream, QString& error
return
false
;
}
if
(
addPlannedHomePosition
||
_
missionItems
->
count
()
==
0
)
{
_addPlannedHomePosition
(
true
/* addToCenter */
);
if
(
addPlannedHomePosition
||
missionItems
->
count
()
==
0
)
{
_addPlannedHomePosition
(
missionItems
,
true
/* addToCenter */
);
// Update sequence numbers in DO_JUMP commands to take into account added home position
for
(
int
i
=
1
;
i
<
_
missionItems
->
count
();
i
++
)
{
MissionItem
*
item
=
qobject_cast
<
MissionItem
*>
(
_
missionItems
->
get
(
i
));
for
(
int
i
=
1
;
i
<
missionItems
->
count
();
i
++
)
{
MissionItem
*
item
=
qobject_cast
<
MissionItem
*>
(
missionItems
->
get
(
i
));
if
(
item
->
command
()
==
MavlinkQmlSingleton
::
MAV_CMD_DO_JUMP
)
{
// Home is in position 0
item
->
setParam1
((
int
)
item
->
param1
()
+
1
);
...
...
@@ -305,11 +307,7 @@ void MissionController::loadMissionFromFile(void)
return
;
}
if
(
_missionItems
)
{
_deinitAllMissionItems
();
_missionItems
->
deleteLater
();
}
_missionItems
=
new
QmlObjectListModel
(
this
);
QmlObjectListModel
*
newMissionItems
=
new
QmlObjectListModel
(
this
);
QFile
file
(
filename
);
...
...
@@ -322,19 +320,25 @@ void MissionController::loadMissionFromFile(void)
QString
firstLine
=
stream
.
readLine
();
if
(
firstLine
.
contains
(
QRegExp
(
"QGC.*WPL"
)))
{
stream
.
seek
(
0
);
_loadTextMissionFile
(
stream
,
errorString
);
_loadTextMissionFile
(
stream
,
newMissionItems
,
errorString
);
}
else
{
_loadJsonMissionFile
(
bytes
,
errorString
);
_loadJsonMissionFile
(
bytes
,
newMissionItems
,
errorString
);
}
}
if
(
!
errorString
.
isEmpty
())
{
_missionItems
->
clear
()
;
delete
newMissionItems
;
qgcApp
()
->
showMessage
(
errorString
);
return
;
}
if
(
_missionItems
)
{
_deinitAllMissionItems
();
_missionItems
->
deleteLater
();
}
_missionItems
=
newMissionItems
;
if
(
_missionItems
->
count
()
==
0
)
{
_addPlannedHomePosition
(
true
/* addToCenter */
);
_addPlannedHomePosition
(
_missionItems
,
true
/* addToCenter */
);
}
_initAllMissionItems
();
...
...
@@ -786,21 +790,21 @@ double MissionController::_normalizeLon(double lon)
}
/// Add the home position item to the front of the list
void
MissionController
::
_addPlannedHomePosition
(
bool
addToCenter
)
void
MissionController
::
_addPlannedHomePosition
(
QmlObjectListModel
*
missionItems
,
bool
addToCenter
)
{
MissionItem
*
homeItem
=
new
MissionItem
(
_activeVehicle
,
this
);
_
missionItems
->
insert
(
0
,
homeItem
);
missionItems
->
insert
(
0
,
homeItem
);
if
(
_
missionItems
->
count
()
>
1
&&
addToCenter
)
{
MissionItem
*
item
=
qobject_cast
<
MissionItem
*>
(
_
missionItems
->
get
(
1
));
if
(
missionItems
->
count
()
>
1
&&
addToCenter
)
{
MissionItem
*
item
=
qobject_cast
<
MissionItem
*>
(
missionItems
->
get
(
1
));
double
north
=
_normalizeLat
(
item
->
coordinate
().
latitude
());
double
south
=
north
;
double
east
=
_normalizeLon
(
item
->
coordinate
().
longitude
());
double
west
=
east
;
for
(
int
i
=
2
;
i
<
_
missionItems
->
count
();
i
++
)
{
item
=
qobject_cast
<
MissionItem
*>
(
_
missionItems
->
get
(
i
));
for
(
int
i
=
2
;
i
<
missionItems
->
count
();
i
++
)
{
item
=
qobject_cast
<
MissionItem
*>
(
missionItems
->
get
(
i
));
double
lat
=
_normalizeLat
(
item
->
coordinate
().
latitude
());
double
lon
=
_normalizeLon
(
item
->
coordinate
().
longitude
());
...
...
src/MissionManager/MissionController.h
View file @
e7c88789
...
...
@@ -94,12 +94,12 @@ private:
void
_calcPrevWaypointValues
(
double
homeAlt
,
MissionItem
*
currentItem
,
MissionItem
*
prevItem
,
double
*
azimuth
,
double
*
distance
,
double
*
altDifference
);
bool
_findLastAltitude
(
double
*
lastAltitude
);
bool
_findLastAcceptanceRadius
(
double
*
lastAcceptanceRadius
);
void
_addPlannedHomePosition
(
bool
addToCenter
);
void
_addPlannedHomePosition
(
QmlObjectListModel
*
missionItems
,
bool
addToCenter
);
double
_normalizeLat
(
double
lat
);
double
_normalizeLon
(
double
lon
);
#ifndef __mobile__
bool
_loadJsonMissionFile
(
const
QByteArray
&
bytes
,
QString
&
errorString
);
bool
_loadTextMissionFile
(
QTextStream
&
stream
,
QString
&
errorString
);
bool
_loadJsonMissionFile
(
const
QByteArray
&
bytes
,
Q
mlObjectListModel
*
missionItems
,
Q
String
&
errorString
);
bool
_loadTextMissionFile
(
QTextStream
&
stream
,
Q
mlObjectListModel
*
missionItems
,
Q
String
&
errorString
);
#endif
private:
...
...
src/QmlControls/MissionItemEditor.qml
View file @
e7c88789
...
...
@@ -20,7 +20,6 @@ Rectangle {
signal
clicked
signal
remove
signal
removeAll
signal
insert
(
int
i
)
signal
moveHomeToMapCenter
...
...
@@ -32,22 +31,123 @@ Rectangle {
readonly
property
real
_margin
:
ScreenTools
.
defaultFontPixelWidth
/
2
readonly
property
real
_radius
:
ScreenTools
.
defaultFontPixelWidth
/
2
property
bool
_showValues
:
missionItem
.
isCurrentItem
QGCPalette
{
id
:
qgcPal
colorGroupEnabled
:
enabled
}
Component
{
id
:
deleteAllPromptDialog
id
:
valuesComponent
QGCViewMessage
{
message
:
"
Are you sure you want to delete all mission items?
"
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
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
function
accept
()
{
removeAll
()
hideDialog
()
}
}
}
Item
{
...
...
@@ -56,7 +156,7 @@ Rectangle {
anchors.top
:
parent
.
top
anchors.left
:
parent
.
left
anchors.right
:
parent
.
right
height
:
valuesRect
.
visible
?
valuesRect
.
y
+
valuesRect
.
height
:
valuesRect
.
y
height
:
_showValues
?
valuesLoader
.
y
+
valuesLoader
.
height
:
valuesLoader
.
y
MouseArea
{
anchors.fill
:
parent
...
...
@@ -99,12 +199,6 @@ Rectangle {
onTriggered
:
remove
()
}
MenuItem
{
text
:
"
Delete all
"
onTriggered
:
qgcView
.
showDialog
(
deleteAllPromptDialog
,
"
Delete all
"
,
qgcView
.
showDialogDefaultWidth
,
StandardButton
.
Yes
|
StandardButton
.
No
)
}
MenuSeparator
{
}
MenuItem
{
...
...
@@ -157,115 +251,13 @@ Rectangle {
color
:
qgcPal
.
buttonText
}
Rectangle
{
id
:
values
Rect
Loader
{
id
:
values
Loader
anchors.topMargin
:
_margin
anchors.top
:
commandPicker
.
bottom
anchors.left
:
parent
.
left
anchors.right
:
parent
.
right
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
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
sourceComponent
:
_showValues
?
valuesComponent
:
undefined
}
}
// Item
}
// Rectangle
test/100Waypoints.mission
0 → 100644
View file @
e7c88789
{
"MAV_AUTOPILOT": 3,
"groundStation": "QGroundControl",
"items": [
{
"autoContinue": true,
"command": 22,
"coordinate": [
0,
0,
30
],
"frame": 2,
"id": 1,
"param1": 20,
"param2": 0,
"param3": 0,
"param4": 0,
"type": "missionItem"
},
{
"autoContinue": true,
"command": 16,
"coordinate": [
34.469586999999997,
-112.534801,
90
],
"frame": 3,
"id": 2,
"param1": 0,
"param2": 0,
"param3": 0,
"param4": 0,
"type": "missionItem"
},
{
"autoContinue": true,
"command": 206,
"coordinate": [
0,
0,
0
],
"frame": 2,
"id": 3,
"param1": 21.059999000000001,
"param2": 0,
"param3": 0,
"param4": 0,
"type": "missionItem"
},
{
"autoContinue": true,
"command": 16,
"coordinate": [
34.462736,
-112.53540099999999,
90
],
"frame": 3,
"id": 4,
"param1": 0,
"param2": 0,
"param3": 0,
"param4": 0,
"type": "missionItem"
},
{
"autoContinue": true,
"command": 16,
"coordinate": [
34.462833000000003,
-112.535104,
90
],
"frame": 3,
"id": 5,
"param1": 0,
"param2": 0,
"param3": 0,
"param4": 0,
"type": "missionItem"
},
{
"autoContinue": true,
"command": 16,
"coordinate": [
34.484993000000003,
-112.533163,
90
],
"frame": 3,
"id": 6,
"param1": 0,
"param2": 0,
"param3": 0,
"param4": 0,
"type": "missionItem"
},
{
"autoContinue": true,
"command": 16,
"coordinate": [
34.500399000000002,
-112.531524,
90
],
"frame": 3,
"id": 7,
"param1": 0,
"param2": 0,
"param3": 0,
"param4": 0,
"type": "missionItem"
},
{
"autoContinue": true,
"command": 16,
"coordinate": [
34.46293,
-112.534807,
90
],
"frame": 3,
"id": 8,
"param1": 0,
"param2": 0,
"param3": 0,
"param4": 0,
"type": "missionItem"
},
{
"autoContinue": true,
"command": 16,
"coordinate": [
34.463026999999997,
-112.53451,
90
],
"frame": 3,
"id": 9,
"param1": 0,
"param2": 0,
"param3": 0,
"param4": 0,
"type": "missionItem"
},
{
"autoContinue": true,
"command": 16,
"coordinate": [
34.515805,
-112.529884,
90
],
"frame": 3,
"id": 10,
"param1": 0,
"param2": 0,
"param3": 0,
"param4": 0,
"type": "missionItem"
},
{
"autoContinue": true,
"command": 16,
"coordinate": [
34.531210999999999,
-112.528244,
90
],
"frame": 3,
"id": 11,
"param1": 0,
"param2": 0,
"param3": 0,
"param4": 0,
"type": "missionItem"
},
{
"autoContinue": true,
"command": 16,
"coordinate": [
34.463124000000001,
-112.53421299999999,
90
],
"frame": 3,
"id": 12,
"param1": 0,
"param2": 0,
"param3": 0,
"param4": 0,
"type": "missionItem"
},
{
"autoContinue": true,
"command": 16,
"coordinate": [
34.463220999999997,
-112.533916,
90
],
"frame": 3,
"id": 13,
"param1": 0,
"param2": 0,
"param3": 0,
"param4": 0,
"type": "missionItem"
},
{
"autoContinue": true,
"command": 16,
"coordinate": [
34.546616,
-112.52660400000001,