QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
SimpleMissionItem.cc
Go to the documentation of this file.
1#include "SimpleMissionItem.h"
2#include "JsonParsing.h"
6#include "SettingsManager.h"
7#include "AppSettings.h"
9#include "SpeedSection.h"
10#include "MultiVehicleManager.h"
11#include "CameraSection.h"
12#include "Vehicle.h"
13#include "QGCMath.h"
14
15#include <QtCore/QStringList>
16#include <QtCore/QJsonArray>
17
18FactMetaData* SimpleMissionItem::_altitudeMetaData = nullptr;
19FactMetaData* SimpleMissionItem::_commandMetaData = nullptr;
20FactMetaData* SimpleMissionItem::_defaultParamMetaData = nullptr;
21FactMetaData* SimpleMissionItem::_frameMetaData = nullptr;
22FactMetaData* SimpleMissionItem::_latitudeMetaData = nullptr;
23FactMetaData* SimpleMissionItem::_longitudeMetaData = nullptr;
24
25SimpleMissionItem::SimpleMissionItem(PlanMasterController* masterController, bool flyView, bool forLoad)
26 : VisualMissionItem (masterController, flyView)
27 , _supportedCommandFact (0, "Command:", FactMetaData::valueTypeUint32)
28 , _altitudeFact (0, "Altitude", FactMetaData::valueTypeDouble)
29 , _amslAltAboveTerrainFact (0, "Alt above terrain", FactMetaData::valueTypeDouble)
30 , _param1MetaData (FactMetaData::valueTypeDouble)
31 , _param2MetaData (FactMetaData::valueTypeDouble)
32 , _param3MetaData (FactMetaData::valueTypeDouble)
33 , _param4MetaData (FactMetaData::valueTypeDouble)
34 , _param5MetaData (FactMetaData::valueTypeDouble)
35 , _param6MetaData (FactMetaData::valueTypeDouble)
36 , _param7MetaData (FactMetaData::valueTypeDouble)
37{
38 _editorQml = QStringLiteral("qrc:/qml/QGroundControl/PlanView/SimpleItemEditor.qml");
39
40 _setupMetaData();
41
42 if (!forLoad) {
43 // We are are going to load the SimpleItem right after this then don't connnect up signalling until after load is done
44 _connectSignals();
45 _updateOptionalSections();
46 _setDefaultsForCommand();
47 _rebuildFacts();
48 setDirty(false);
49 }
50}
51
52SimpleMissionItem::SimpleMissionItem(PlanMasterController* masterController, bool flyView, const MissionItem& missionItem)
53 : VisualMissionItem (masterController, flyView)
54 , _missionItem (missionItem)
55 , _supportedCommandFact (0, "Command:", FactMetaData::valueTypeUint32)
56 , _altitudeFact (0, "Altitude", FactMetaData::valueTypeDouble)
57 , _amslAltAboveTerrainFact (0, "Alt above terrain", FactMetaData::valueTypeDouble)
58 , _param1MetaData (FactMetaData::valueTypeDouble)
59 , _param2MetaData (FactMetaData::valueTypeDouble)
60 , _param3MetaData (FactMetaData::valueTypeDouble)
61 , _param4MetaData (FactMetaData::valueTypeDouble)
62 , _param5MetaData (FactMetaData::valueTypeDouble)
63 , _param6MetaData (FactMetaData::valueTypeDouble)
64 , _param7MetaData (FactMetaData::valueTypeDouble)
65{
66 _editorQml = QStringLiteral("qrc:/qml/QGroundControl/PlanView/SimpleItemEditor.qml");
67
68 struct MavFrame2AltFrame_s {
69 MAV_FRAME mavFrame;
71 };
72
73 const struct MavFrame2AltFrame_s rgMavFrame2AltFrame[] = {
74 { MAV_FRAME_GLOBAL_TERRAIN_ALT, QGroundControlQmlGlobal::AltitudeFrameTerrain },
76 { MAV_FRAME_GLOBAL_RELATIVE_ALT, QGroundControlQmlGlobal::AltitudeFrameRelative },
77 };
79 for (size_t i=0; i<sizeof(rgMavFrame2AltFrame)/sizeof(rgMavFrame2AltFrame[0]); i++) {
80 const MavFrame2AltFrame_s& pMavFrame2AltFrame = rgMavFrame2AltFrame[i];
81 if (pMavFrame2AltFrame.mavFrame == missionItem.frame()) {
82 _altitudeFrame = pMavFrame2AltFrame.altFrame;
83 break;
84 }
85 }
86
88 _altitudeFact.setRawValue(specifiesAltitude() ? _missionItem._param7Fact.rawValue() : qQNaN());
89 _amslAltAboveTerrainFact.setRawValue(qQNaN());
90
91 // In flyView we skip some of the intialization to save memory
92 if (!_flyView) {
93 _setupMetaData();
94 }
95 _connectSignals();
96 _updateOptionalSections();
97 if (!_flyView) {
98 _rebuildFacts();
99 }
100
101 // Signal coordinate changed to kick off terrain query
103
104 setDirty(false);
105}
106
107void SimpleMissionItem::_connectSignals(void)
108{
109 // Connect to change signals to track dirty state
110 connect(&_missionItem._param1Fact, &Fact::valueChanged, this, &SimpleMissionItem::_setDirty);
111 connect(&_missionItem._param2Fact, &Fact::valueChanged, this, &SimpleMissionItem::_setDirty);
112 connect(&_missionItem._param3Fact, &Fact::valueChanged, this, &SimpleMissionItem::_setDirty);
113 connect(&_missionItem._param4Fact, &Fact::valueChanged, this, &SimpleMissionItem::_setDirty);
114 connect(&_missionItem._param5Fact, &Fact::valueChanged, this, &SimpleMissionItem::_setDirty);
115 connect(&_missionItem._param6Fact, &Fact::valueChanged, this, &SimpleMissionItem::_setDirty);
116 connect(&_missionItem._param7Fact, &Fact::valueChanged, this, &SimpleMissionItem::_setDirty);
117 connect(&_missionItem._frameFact, &Fact::valueChanged, this, &SimpleMissionItem::_setDirty);
118 connect(&_missionItem._commandFact, &Fact::valueChanged, this, &SimpleMissionItem::_setDirty);
119 connect(&_missionItem, &MissionItem::sequenceNumberChanged, this, &SimpleMissionItem::_setDirty);
120 connect(this, &SimpleMissionItem::altitudeFrameChanged, this, &SimpleMissionItem::_setDirty);
121
122 connect(&_altitudeFact, &Fact::valueChanged, this, &SimpleMissionItem::_altitudeChanged);
123 connect(this, &SimpleMissionItem::altitudeFrameChanged, this, &SimpleMissionItem::_altitudeFrameChanged);
124 connect(this, &SimpleMissionItem::terrainAltitudeChanged, this, &SimpleMissionItem::_terrainAltChanged);
125
127 connect(this, &SimpleMissionItem::cameraSectionChanged, this, &SimpleMissionItem::_setDirty);
128 connect(this, &SimpleMissionItem::cameraSectionChanged, this, &SimpleMissionItem::_updateLastSequenceNumber);
129
130 connect(&_missionItem._param7Fact, &Fact::valueChanged, this, &SimpleMissionItem::_amslEntryAltChanged);
134
136
137 // These are coordinate lat/lon values, they must emit coordinateChanged signal
138 connect(&_missionItem._param5Fact, &Fact::valueChanged, this, &SimpleMissionItem::_sendCoordinateChanged);
139 connect(&_missionItem._param6Fact, &Fact::valueChanged, this, &SimpleMissionItem::_sendCoordinateChanged);
140
141 connect(&_missionItem._param1Fact, &Fact::valueChanged, this, &SimpleMissionItem::_possibleAdditionalTimeDelayChanged);
142 connect(&_missionItem._param4Fact, &Fact::valueChanged, this, &SimpleMissionItem::_possibleVehicleYawChanged);
143
144 // For NAV_LOITER_X commands, they must emit a radiusChanged signal
145 connect(&_missionItem._param2Fact, &Fact::valueChanged, this, &SimpleMissionItem::_possibleRadiusChanged);
146 connect(&_missionItem._param3Fact, &Fact::valueChanged, this, &SimpleMissionItem::_possibleRadiusChanged);
147
148 // Exit coordinate is the same as entrance coordinate
151
152 // The following changes may also change friendlyEditAllowed
153 connect(&_missionItem._autoContinueFact, &Fact::valueChanged, this, &SimpleMissionItem::_sendFriendlyEditAllowedChanged);
154 connect(&_missionItem._commandFact, &Fact::valueChanged, this, &SimpleMissionItem::_sendFriendlyEditAllowedChanged);
155 connect(&_missionItem._frameFact, &Fact::valueChanged, this, &SimpleMissionItem::_sendFriendlyEditAllowedChanged);
156
157 // A command change triggers a number of other changes as well.
158 connect(&_missionItem._commandFact, &Fact::valueChanged, this, &SimpleMissionItem::_setDefaultsForCommand);
159 connect(&_missionItem._commandFact, &Fact::valueChanged, this, &SimpleMissionItem::commandNameChanged);
160 connect(&_missionItem._commandFact, &Fact::valueChanged, this, &SimpleMissionItem::commandDescriptionChanged);
161 connect(&_missionItem._commandFact, &Fact::valueChanged, this, &SimpleMissionItem::abbreviationChanged);
162 connect(&_missionItem._commandFact, &Fact::valueChanged, this, &SimpleMissionItem::specifiesCoordinateChanged);
163 connect(&_missionItem._commandFact, &Fact::valueChanged, this, &SimpleMissionItem::specifiesAltitudeOnlyChanged);
164 connect(&_missionItem._commandFact, &Fact::valueChanged, this, &SimpleMissionItem::isStandaloneCoordinateChanged);
165 connect(&_missionItem._commandFact, &Fact::valueChanged, this, &SimpleMissionItem::isLandCommandChanged);
166 connect(&_missionItem._commandFact, &Fact::valueChanged, this, &SimpleMissionItem::isLoiterItemChanged);
167 connect(&_missionItem._commandFact, &Fact::valueChanged, this, &SimpleMissionItem::showLoiterRadiusChanged);
168
169 // Whenever these properties change the ui model changes as well
170 connect(this, &SimpleMissionItem::commandChanged, this, &SimpleMissionItem::_rebuildFacts);
171 connect(this, &SimpleMissionItem::rawEditChanged, this, &SimpleMissionItem::_rebuildFacts);
172 connect(this, &SimpleMissionItem::previousVTOLModeChanged,this, &SimpleMissionItem::_rebuildFacts);
173
174 // The following changes must signal currentVTOLModeChanged to cause a MissionController recalc
175 connect(this, &SimpleMissionItem::commandChanged, this, &SimpleMissionItem::_signalIfVTOLTransitionCommand);
176 connect(&_missionItem._param1Fact, &Fact::valueChanged, this, &SimpleMissionItem::_signalIfVTOLTransitionCommand);
177
178 // These fact signals must alway signal out through SimpleMissionItem signals
179 connect(&_missionItem._commandFact, &Fact::valueChanged, this, &SimpleMissionItem::_sendCommandChanged);
180
181 // Propogate signals from MissionItem up to SimpleMissionItem
184
187}
188
189void SimpleMissionItem::_setupMetaData(void)
190{
191 QStringList enumStrings;
192 QVariantList enumValues;
193
194 if (!_altitudeMetaData) {
195 _altitudeMetaData = new FactMetaData(FactMetaData::valueTypeDouble);
196 _altitudeMetaData->setRawUnits("m");
197 _altitudeMetaData->setRawIncrement(1);
198 _altitudeMetaData->setDecimalPlaces(1);
199 _altitudeMetaData->setRawUserMin(0.0);
200 _altitudeMetaData->setRawUserMax(121.92); // 400 feet
201
202 enumStrings.clear();
203 enumValues.clear();
204 for (const MAV_CMD command: MissionCommandTree::instance()->allCommandIds()) {
205 enumStrings.append(MissionCommandTree::instance()->rawName(command));
206 enumValues.append(QVariant((int)command));
207 }
208 _commandMetaData = new FactMetaData(FactMetaData::valueTypeUint32);
209 _commandMetaData->setEnumInfo(enumStrings, enumValues);
210
211 _defaultParamMetaData = new FactMetaData(FactMetaData::valueTypeDouble);
212 _defaultParamMetaData->setDecimalPlaces(7);
213
214 enumStrings.clear();
215 enumValues.clear();
216 for (size_t i=0; i<sizeof(_rgMavFrameInfo)/sizeof(_rgMavFrameInfo[0]); i++) {
217 const struct EnumInfo_s* mavFrameInfo = &_rgMavFrameInfo[i];
218
219 enumStrings.append(mavFrameInfo->label);
220 enumValues.append(QVariant(mavFrameInfo->frame));
221 }
222 _frameMetaData = new FactMetaData(FactMetaData::valueTypeUint32);
223 _frameMetaData->setEnumInfo(enumStrings, enumValues);
224
225 _latitudeMetaData = new FactMetaData(FactMetaData::valueTypeDouble);
226 _latitudeMetaData->setRawUnits("deg");
227 _latitudeMetaData->setDecimalPlaces(7);
228
229 _longitudeMetaData = new FactMetaData(FactMetaData::valueTypeDouble);
230 _longitudeMetaData->setRawUnits("deg");
231 _longitudeMetaData->setDecimalPlaces(7);
232
233 }
234
235 _missionItem._commandFact.setMetaData(_commandMetaData);
236 _missionItem._frameFact.setMetaData(_frameMetaData);
237 _altitudeFact.setMetaData(_altitudeMetaData);
238 _amslAltAboveTerrainFact.setMetaData(_altitudeMetaData);
239}
240
244
245void SimpleMissionItem::save(QJsonArray& missionItems)
246{
247 QList<MissionItem*> items;
248
249 appendMissionItems(items, this);
250
251 for (int i=0; i<items.count(); i++) {
252 MissionItem* item = items[i];
253 QJsonObject saveObject;
254 item->save(saveObject);
255 if (i == 0) {
256 // This is the main simple item, save the alt/terrain data
257 if (specifiesAltitude()) {
258 saveObject[_jsonAltitudeModeKey] = _altitudeFrame;
259 saveObject[_jsonAltitudeKey] = _altitudeFact.rawValue().toDouble();
260 saveObject[_jsonAMSLAltAboveTerrainKey] = _amslAltAboveTerrainFact.rawValue().toDouble();
261 }
262 }
263 missionItems.append(saveObject);
264 item->deleteLater();
265 }
266}
267
268bool SimpleMissionItem::load(QTextStream &loadStream)
269{
270 bool success;
271 if ((success = _missionItem.load(loadStream))) {
272 if (specifiesAltitude()) {
274 _altitudeFact.setRawValue(_missionItem._param7Fact.rawValue());
275 _amslAltAboveTerrainFact.setRawValue(qQNaN());
276 }
277 _connectSignals();
278 _updateOptionalSections();
279 _rebuildFacts();
280 setDirty(false);
281 }
282
283 return success;
284}
285
286bool SimpleMissionItem::load(const QJsonObject& json, int sequenceNumber, QString& errorString)
287{
288 if (!_missionItem.load(json, sequenceNumber, errorString)) {
289 return false;
290 }
291
292 if (specifiesAltitude()) {
293 if (json.contains(_jsonAltitudeModeKey) || json.contains(_jsonAltitudeKey) || json.contains(_jsonAMSLAltAboveTerrainKey)) {
294 QList<JsonParsing::KeyValidateInfo> keyInfoList = {
295 { _jsonAltitudeModeKey, QJsonValue::Double, true },
296 { _jsonAltitudeKey, QJsonValue::Double, true },
297 { _jsonAMSLAltAboveTerrainKey, QJsonValue::Null, true },
298 };
299 if (!JsonParsing::validateKeys(json, keyInfoList, errorString)) {
300 return false;
301 }
302
303 _altitudeFrame = (QGroundControlQmlGlobal::AltitudeFrame)(int)json[_jsonAltitudeModeKey].toDouble();
304 _altitudeFact.setRawValue(JsonParsing::possibleNaNJsonValue(json[_jsonAltitudeKey]));
305 _amslAltAboveTerrainFact.setRawValue(JsonParsing::possibleNaNJsonValue(json[_jsonAMSLAltAboveTerrainKey]));
306 } else {
308 _altitudeFact.setRawValue(_missionItem._param7Fact.rawValue());
309 _amslAltAboveTerrainFact.setRawValue(qQNaN());
310 }
311 }
312
313 _connectSignals();
314 _updateOptionalSections();
315 _rebuildFacts();
316 setDirty(false);
317
318 return true;
319}
320
322{
324 if (uiInfo) {
325 return uiInfo->isStandaloneCoordinate();
326 } else {
327 return false;
328 }
329}
330
332{
334 if (uiInfo) {
335 return uiInfo->specifiesCoordinate();
336 } else {
337 return false;
338 }
339}
340
342{
344 if (uiInfo) {
345 return uiInfo->specifiesAltitudeOnly();
346 } else {
347 return false;
348 }
349}
350
352{
354 if (uiInfo) {
355 return uiInfo->description();
356 } else {
357 qWarning() << "Should not ask for command description on unknown command";
358 return commandName();
359 }
360}
361
363{
365 if (uiInfo) {
366 return uiInfo->friendlyName();
367 } else {
368 qWarning() << "Request for command name on unknown command";
369 return tr("Unknown: %1").arg(command());
370 }
371}
372
374{
375 if (homePosition())
376 return tr("L");
377
378 switch(command()) {
379 case MAV_CMD_NAV_TAKEOFF:
380 return tr("Takeoff");
381 case MAV_CMD_NAV_LAND:
382 return tr("Land");
383 case MAV_CMD_NAV_VTOL_TAKEOFF:
384 return tr("Transition Direction");
385 case MAV_CMD_NAV_VTOL_LAND:
386 return tr("VTOL Land");
387 case MAV_CMD_DO_SET_ROI:
388 case MAV_CMD_DO_SET_ROI_LOCATION:
389 return tr("ROI");
390 case MAV_CMD_NAV_LOITER_TIME:
391 case MAV_CMD_NAV_LOITER_TURNS:
392 case MAV_CMD_NAV_LOITER_UNLIM:
393 case MAV_CMD_NAV_LOITER_TO_ALT:
394 return tr("Loiter");
395 default:
396 return QString();
397 }
398}
399
400void SimpleMissionItem::_rebuildTextFieldFacts(void)
401{
402 _textFieldFacts.clear();
403 _textFieldFactsAdvanced.clear();
404
405 if (rawEdit()) {
406 _missionItem._param1Fact.setName("Param1");
407 _missionItem._param1Fact.setMetaData(_defaultParamMetaData);
408 _textFieldFacts.append(&_missionItem._param1Fact);
409 _missionItem._param2Fact.setName("Param2");
410 _missionItem._param2Fact.setMetaData(_defaultParamMetaData);
411 _textFieldFacts.append(&_missionItem._param2Fact);
412 _missionItem._param3Fact.setName("Param3");
413 _missionItem._param3Fact.setMetaData(_defaultParamMetaData);
414 _textFieldFacts.append(&_missionItem._param3Fact);
415 _missionItem._param4Fact.setName("Param4");
416 _missionItem._param4Fact.setMetaData(_defaultParamMetaData);
417 _textFieldFacts.append(&_missionItem._param4Fact);
418 _missionItem._param5Fact.setName("Lat/X");
419 _missionItem._param5Fact.setMetaData(_defaultParamMetaData);
420 _textFieldFacts.append(&_missionItem._param5Fact);
421 _missionItem._param6Fact.setName("Lon/Y");
422 _missionItem._param6Fact.setMetaData(_defaultParamMetaData);
423 _textFieldFacts.append(&_missionItem._param6Fact);
424 _missionItem._param7Fact.setName("Alt/Z");
425 _missionItem._param7Fact.setMetaData(_defaultParamMetaData);
426 _textFieldFacts.append(&_missionItem._param7Fact);
427 } else {
428 _ignoreDirtyChangeSignals = true;
429
430 MAV_CMD command;
432 command = MAV_CMD_NAV_LAST;
433 } else {
434 command = _missionItem.command();
435 }
436
437 Fact* rgParamFacts[7] = { &_missionItem._param1Fact, &_missionItem._param2Fact, &_missionItem._param3Fact, &_missionItem._param4Fact, &_missionItem._param5Fact, &_missionItem._param6Fact, &_missionItem._param7Fact };
438 FactMetaData* rgParamMetaData[7] = { &_param1MetaData, &_param2MetaData, &_param3MetaData, &_param4MetaData, &_param5MetaData, &_param6MetaData, &_param7MetaData };
439
441
442 if (uiInfo) {
443 for (int i=1; i<=7; i++) {
444 bool showUI;
445 const MissionCmdParamInfo* paramInfo = uiInfo->getParamInfo(i, showUI);
446
447 if (showUI && paramInfo && paramInfo->enumStrings().count() == 0 && !paramInfo->nanUnchanged()) {
448 Fact* paramFact = rgParamFacts[i-1];
449 FactMetaData* paramMetaData = rgParamMetaData[i-1];
450
451 paramFact->setName(paramInfo->label());
452 paramMetaData->setDecimalPlaces(paramInfo->decimalPlaces());
453 paramMetaData->setRawUnits(paramInfo->units());
454 paramMetaData->setRawDefaultValue(paramInfo->defaultValue());
455 paramMetaData->setRawMin(paramInfo->min());
456 paramMetaData->setRawMax(paramInfo->max());
457 const double userMin = paramInfo->userMin();
458 const double userMax = paramInfo->userMax();
459 // if user min/max are NaN, we leave them unchanged (invalid)
460 if (!qIsNaN(userMin)) {
461 paramMetaData->setRawUserMin(userMin);
462 }
463 if (!qIsNaN(userMax)) {
464 paramMetaData->setRawUserMax(userMax);
465 }
466 paramFact->setMetaData(paramMetaData);
467 if (paramInfo->advanced()) {
468 _textFieldFactsAdvanced.append(paramFact);
469 } else {
470 _textFieldFacts.append(paramFact);
471 }
472 }
473 }
474 }
475
476 _ignoreDirtyChangeSignals = false;
477 }
478}
479
480void SimpleMissionItem::_rebuildNaNFacts(void)
481{
482 _nanFacts.clear();
483 _nanFactsAdvanced.clear();
484
485 if (!rawEdit()) {
486 _ignoreDirtyChangeSignals = true;
487
488 MAV_CMD command;
490 command = MAV_CMD_NAV_LAST;
491 } else {
492 command = _missionItem.command();
493 }
494
495 Fact* rgParamFacts[7] = { &_missionItem._param1Fact, &_missionItem._param2Fact, &_missionItem._param3Fact, &_missionItem._param4Fact, &_missionItem._param5Fact, &_missionItem._param6Fact, &_missionItem._param7Fact };
496 FactMetaData* rgParamMetaData[7] = { &_param1MetaData, &_param2MetaData, &_param3MetaData, &_param4MetaData, &_param5MetaData, &_param6MetaData, &_param7MetaData };
497
499
500 if (uiInfo) {
501 for (int i=1; i<=7; i++) {
502 bool showUI;
503 const MissionCmdParamInfo* paramInfo = uiInfo->getParamInfo(i, showUI);
504
505 if (showUI && paramInfo && paramInfo->nanUnchanged()) {
506 // Show hide Heading field on waypoint based on vehicle yaw to next waypoint setting. This needs to come from the actual vehicle if it exists
507 // and not _controllerVehicle which is always offline.
509 if (!firmwareVehicle) {
510 firmwareVehicle = _controllerVehicle;
511 }
512
513 Fact* paramFact = rgParamFacts[i-1];
514 FactMetaData* paramMetaData = rgParamMetaData[i-1];
515
516 paramFact->setName(paramInfo->label());
517 paramMetaData->setDecimalPlaces(paramInfo->decimalPlaces());
518 paramMetaData->setRawUnits(paramInfo->units());
519 paramMetaData->setRawDefaultValue(paramInfo->defaultValue());
520 paramMetaData->setRawMin(paramInfo->min());
521 paramMetaData->setRawMax(paramInfo->max());
522 const double userMin = paramInfo->userMin();
523 const double userMax = paramInfo->userMax();
524 // if user min/max are NaN, we leave them unchanged (invalid)
525 if (!qIsNaN(userMin)) {
526 paramMetaData->setRawUserMin(userMin);
527 }
528 if (!qIsNaN(userMax)) {
529 paramMetaData->setRawUserMax(userMax);
530 }
531 paramFact->setMetaData(paramMetaData);
532 if (paramInfo->advanced()) {
533 _nanFactsAdvanced.append(paramFact);
534 } else {
535 _nanFacts.append(paramFact);
536 }
537 }
538 }
539 }
540
541 _ignoreDirtyChangeSignals = false;
542 }
543}
544
549
551{
553 if (uiInfo) {
554 return uiInfo->isLoiterCommand();
555 } else {
556 return false;
557 }
558}
559
561{
562 const MissionCommandUIInfo *uiInfo =
564 _controllerVehicle, _previousVTOLMode, MAV_CMD_NAV_LOITER_TIME);
565 bool showUI;
566 uiInfo->getParamInfo(3, showUI);
567
568 if (isLoiterItem() && command() == MAV_CMD_NAV_LOITER_TIME && !showUI) {
569 // Don't show the radius of MAV_CMD_NAV_LOITER_TIME items if the
570 // firmware doesn't support specifying it
571 return false;
572 }
573
575}
576
578{
579 if (isLoiterItem()) {
580 return command() == MAV_CMD_NAV_LOITER_TO_ALT ? missionItem().param2() : missionItem().param3();
581 } else {
582 return qQNaN();
583 }
584}
585
586void SimpleMissionItem::_rebuildComboBoxFacts(void)
587{
588 _comboboxFacts.clear();
589 _comboboxFactsAdvanced.clear();
590
591 if (rawEdit()) {
592 _comboboxFacts.append(&_missionItem._commandFact);
593 _comboboxFacts.append(&_missionItem._frameFact);
594 } else {
595 _ignoreDirtyChangeSignals = true;
596
597 Fact* rgParamFacts[7] = { &_missionItem._param1Fact, &_missionItem._param2Fact, &_missionItem._param3Fact, &_missionItem._param4Fact, &_missionItem._param5Fact, &_missionItem._param6Fact, &_missionItem._param7Fact };
598 FactMetaData* rgParamMetaData[7] = { &_param1MetaData, &_param2MetaData, &_param3MetaData, &_param4MetaData, &_param5MetaData, &_param6MetaData, &_param7MetaData };
599
600 MAV_CMD command;
602 command = MAV_CMD_NAV_LAST;
603 } else {
604 command = (MAV_CMD)this->command();
605 }
606
607 for (int i=1; i<=7; i++) {
608 bool showUI;
610
611 if (showUI && paramInfo && paramInfo->enumStrings().count() != 0) {
612 Fact* paramFact = rgParamFacts[i-1];
613 FactMetaData* paramMetaData = rgParamMetaData[i-1];
614
615 paramFact->setName(paramInfo->label());
616 paramMetaData->setDecimalPlaces(paramInfo->decimalPlaces());
617 paramMetaData->setEnumInfo(paramInfo->enumStrings(), paramInfo->enumValues());
618 paramMetaData->setRawUnits(paramInfo->units());
619 paramMetaData->setRawDefaultValue(paramInfo->defaultValue());
620 paramMetaData->setRawMin(paramInfo->min());
621 paramMetaData->setRawMax(paramInfo->max());
622 const double userMin = paramInfo->userMin();
623 const double userMax = paramInfo->userMax();
624 // if user min/max are NaN, we leave them unchanged (invalid)
625 if (!qIsNaN(userMin)) {
626 paramMetaData->setRawUserMin(userMin);
627 }
628 if (!qIsNaN(userMax)) {
629 paramMetaData->setRawUserMax(userMax);
630 }
631 paramFact->setMetaData(paramMetaData);
632 if (paramInfo->advanced()) {
633 _comboboxFactsAdvanced.append(paramFact);
634 } else {
635 _comboboxFacts.append(paramFact);
636 }
637 }
638 }
639
640 _ignoreDirtyChangeSignals = false;
641 }
642}
643
644void SimpleMissionItem::_rebuildFacts(void)
645{
646 // Reset param metadata to defaults so stale min/max from a previous command
647 // does not cause setRawMin/setRawMax to spuriously reject sentinel values.
648 const FactMetaData kDefaultDouble(FactMetaData::valueTypeDouble);
649 _param1MetaData = kDefaultDouble;
650 _param2MetaData = kDefaultDouble;
651 _param3MetaData = kDefaultDouble;
652 _param4MetaData = kDefaultDouble;
653 _param5MetaData = kDefaultDouble;
654 _param6MetaData = kDefaultDouble;
655 _param7MetaData = kDefaultDouble;
656
657 _rebuildTextFieldFacts();
658 _rebuildNaNFacts();
659 _rebuildComboBoxFacts();
660}
661
663{
665 if (uiInfo && uiInfo->friendlyEdit()) {
666 if (!_missionItem.autoContinue()) {
667 return false;
668 }
669
670 if (specifiesAltitude()) {
671 MAV_FRAME frame = _missionItem.frame();
672 switch (frame) {
673 case MAV_FRAME_GLOBAL:
674 case MAV_FRAME_GLOBAL_RELATIVE_ALT:
675 case MAV_FRAME_GLOBAL_TERRAIN_ALT:
676 return true;
677 default:
678 return false;
679 }
680 }
681
682 return true;
683 }
684
685 return false;
686}
687
689{
690 return _rawEdit || !friendlyEditAllowed();
691}
692
694{
695 if (this->rawEdit() != rawEdit) {
696 _rawEdit = rawEdit;
697 emit rawEditChanged(this->rawEdit());
698 }
699}
700
702{
703 if (!_homePositionSpecialCase || (_dirty != dirty)) {
704 _dirty = dirty;
705 if (!dirty) {
706 _cameraSection->setDirty(false);
707 _speedSection->setDirty(false);
708 }
709 emit dirtyChanged(dirty);
710 }
711}
712
713void SimpleMissionItem::_setDirty(void)
714{
715 if (!_ignoreDirtyChangeSignals) {
716 setDirty(true);
717 }
718}
719
720void SimpleMissionItem::_sendCoordinateChanged(void)
721{
723}
724
725void SimpleMissionItem::_altitudeFrameChanged(void)
726{
727 switch (_altitudeFrame) {
729 _missionItem.setFrame(MAV_FRAME_GLOBAL_TERRAIN_ALT);
730 break;
732 // Terrain altitudes are Absolute
733 _missionItem.setFrame(MAV_FRAME_GLOBAL);
734 // Clear any old calculated values
735 _missionItem._param7Fact.setRawValue(qQNaN());
736 _amslAltAboveTerrainFact.setRawValue(qQNaN());
737 break;
739 _missionItem.setFrame(MAV_FRAME_GLOBAL);
740 break;
742 _missionItem.setFrame(MAV_FRAME_GLOBAL_RELATIVE_ALT);
743 break;
745 qWarning() << "Internal Error SimpleMissionItem::_altitudeFrameChanged: Invalid altitudeFrame == AltitudeFrameNone";
746 break;
748 qWarning() << "Internal Error SimpleMissionItem::_altitudeFrameChanged: Invalid altitudeFrame == AltitudeFrameMixed";
749 break;
750 }
751
752 // We always call _altitudeChanged to make sure that param7 is always setup correctly on mode change
753 _altitudeChanged();
754}
755
756void SimpleMissionItem::_altitudeChanged(void)
757{
758 if (!specifiesAltitude()) {
759 return;
760 }
761
763 _amslAltAboveTerrainFact.setRawValue(qQNaN());
764 _terrainAltChanged();
765 }
766
768 _missionItem._param7Fact.setRawValue(_altitudeFact.rawValue());
769 }
770}
771
772void SimpleMissionItem::_terrainAltChanged(void)
773{
774 if (!specifiesAltitude()) {
775 // We don't need terrain data
776 return;
777 }
778
780 if (qIsNaN(terrainAltitude())) {
781 // Set NaNs to signal we are waiting on terrain data
783 _missionItem._param7Fact.setRawValue(qQNaN());
784 }
785 _amslAltAboveTerrainFact.setRawValue(qQNaN());
786 } else {
787 double newAboveTerrain = terrainAltitude() + _altitudeFact.rawValue().toDouble();
788 double oldAboveTerrain = _amslAltAboveTerrainFact.rawValue().toDouble();
789 if (!QGC::fuzzyCompare(newAboveTerrain, oldAboveTerrain)) {
791 _missionItem._param7Fact.setRawValue(newAboveTerrain);
792 }
793 _amslAltAboveTerrainFact.setRawValue(newAboveTerrain);
794 }
795 }
797 }
798}
799
801{
802 if (_wizardMode) {
803 return NotReadyForSaveData;
804 }
805
806 bool terrainReady = !specifiesAltitude() || !qIsNaN(_missionItem._param7Fact.rawValue().toDouble());
807 return terrainReady ? ReadyForSave : NotReadyForSaveTerrain;
808}
809
810void SimpleMissionItem::_setDefaultsForCommand(void)
811{
812 // First reset params 1-4 to 0, we leave 5-7 alone to preserve any previous location information on command change
813 _missionItem._param1Fact.setRawValue(0);
814 _missionItem._param2Fact.setRawValue(0);
815 _missionItem._param3Fact.setRawValue(0);
816 _missionItem._param4Fact.setRawValue(0);
817
819 // No need to carry across previous lat/lon
820 _missionItem._param5Fact.setRawValue(0);
821 _missionItem._param6Fact.setRawValue(0);
822 } else if ((specifiesCoordinate() || isStandaloneCoordinate()) && _missionItem._param5Fact.rawValue().toDouble() == 0 && _missionItem._param6Fact.rawValue().toDouble() == 0) {
823 // We switched from a command without a coordinate to a command with a coordinate. Use the hint.
824 _missionItem._param5Fact.setRawValue(_mapCenterHint.latitude());
825 _missionItem._param6Fact.setRawValue(_mapCenterHint.longitude());
826 }
827
828 // Set global defaults first, then if there are param defaults they will get reset
831 _amslAltAboveTerrainFact.setRawValue(qQNaN());
832 if (specifiesAltitude()) {
833 double defaultAlt = SettingsManager::instance()->appSettings()->defaultMissionItemAltitude()->rawValue().toDouble();
834 _altitudeFact.setRawValue(defaultAlt);
835 _missionItem._param7Fact.setRawValue(defaultAlt);
836 // Note that setAltitudeFrame will also set MAV_FRAME correctly through signalling
837 // Takeoff items always use relative alt since that is the highest quality data to base altitude from
839 } else {
840 _altitudeFact.setRawValue(0);
841 _missionItem._param7Fact.setRawValue(0);
842 _missionItem.setFrame(MAV_FRAME_MISSION);
843 }
844
845 MAV_CMD command = static_cast<MAV_CMD>(this->command());
847 if (uiInfo) {
848 for (int i=1; i<=7; i++) {
849 bool showUI;
850 const MissionCmdParamInfo* paramInfo = uiInfo->getParamInfo(i, showUI);
851 if (paramInfo) {
852 Fact* rgParamFacts[7] = { &_missionItem._param1Fact, &_missionItem._param2Fact, &_missionItem._param3Fact, &_missionItem._param4Fact, &_missionItem._param5Fact, &_missionItem._param6Fact, &_missionItem._param7Fact };
853 rgParamFacts[paramInfo->param()-1]->setRawValue(paramInfo->defaultValue());
854 }
855 }
856 }
857
858 if (command == MAV_CMD_NAV_WAYPOINT) {
859 // We default all acceptance radius to 0. This allows flight controller to be in control of
860 // accept radius.
861 _missionItem.setParam2(0);
862 } else if ((uiInfo && uiInfo->isLandCommand()) || command == MAV_CMD_DO_SET_ROI_LOCATION) {
863 _altitudeFact.setRawValue(0);
864 _missionItem.setParam7(0);
865 }
866
867 _missionItem.setAutoContinue(true);
868 setRawEdit(false);
869}
870
871void SimpleMissionItem::_sendCommandChanged(void)
872{
873 emit commandChanged(command());
874}
875
876void SimpleMissionItem::_sendFriendlyEditAllowedChanged(void)
877{
879}
880
882{
884 return uiInfo ? uiInfo->category() : QString();
885}
886
888{
889 if (static_cast<MAV_CMD>(command) != _missionItem.command()) {
890 _missionItem.setCommand(static_cast<MAV_CMD>(command));
891 _updateOptionalSections();
892 }
893}
894
896{
897 if (isLoiterItem()) {
898 const MAV_CMD command = static_cast<MAV_CMD>(this->command());
899 if (command == MAV_CMD_NAV_LOITER_TO_ALT)
900 _missionItem.setParam2(radius);
901 else
902 _missionItem.setParam3(radius);
903 }
904}
905
906void SimpleMissionItem::setCoordinate(const QGeoCoordinate& coordinate)
907{
908 // We only use lat/lon from coordinate. This keeps param7 and the altitude value which is kept to the side in sync.
909 if (_missionItem.param5() != coordinate.latitude() || _missionItem.param6() != coordinate.longitude()) {
910 _missionItem.setParam5(coordinate.latitude());
911 _missionItem.setParam6(coordinate.longitude());
912 }
913}
914
916{
917 if (_missionItem.sequenceNumber() != sequenceNumber) {
918 _missionItem.setSequenceNumber(sequenceNumber);
920 // This is too likely to ignore
921 emit abbreviationChanged();
922 }
923}
924
926{
927 if (_speedSection->specifyFlightSpeed()) {
928 return _speedSection->flightSpeed()->rawValue().toDouble();
929 } else {
931 }
932}
933
935{
936 return _cameraSection->available() ? _cameraSection->specifiedGimbalYaw() : missionItem().specifiedGimbalYaw();
937}
938
940{
941 return _cameraSection->available() ? _cameraSection->specifiedGimbalPitch() : missionItem().specifiedGimbalPitch();
942}
943
945{
946 return command() == MAV_CMD_NAV_WAYPOINT ? missionItem().param4() : qQNaN();
947}
948
949void SimpleMissionItem::_possibleVehicleYawChanged(void)
950{
951 if (command() == MAV_CMD_NAV_WAYPOINT) {
953 }
954}
955
956bool SimpleMissionItem::scanForSections(QmlObjectListModel* visualItems, int scanIndex, PlanMasterController* /*masterController*/)
957{
958 bool sectionFound = false;
959
960 if (_cameraSection->available()) {
961 sectionFound |= _cameraSection->scanForSection(visualItems, scanIndex);
962 }
963 if (_speedSection->available()) {
964 sectionFound |= _speedSection->scanForSection(visualItems, scanIndex);
965 }
966
967 return sectionFound;
968}
969
970void SimpleMissionItem::_updateOptionalSections(void)
971{
972 // Remove previous sections
973 if (_cameraSection) {
974 _cameraSection->deleteLater();
975 _cameraSection = nullptr;
976 }
977 if (_speedSection) {
978 _speedSection->deleteLater();
979 _speedSection = nullptr;
980 }
981
982 // Add new sections
983
984 _cameraSection = new CameraSection(_masterController, this);
985 _speedSection = new SpeedSection(_masterController, this);
986 if (static_cast<MAV_CMD>(command()) == MAV_CMD_NAV_WAYPOINT) {
987 _cameraSection->setAvailable(true);
988 _speedSection->setAvailable(true);
989 }
990
991 connect(_cameraSection, &CameraSection::dirtyChanged, this, &SimpleMissionItem::_sectionDirtyChanged);
992 connect(_cameraSection, &CameraSection::itemCountChanged, this, &SimpleMissionItem::_updateLastSequenceNumber);
997
998 connect(_speedSection, &SpeedSection::dirtyChanged, this, &SimpleMissionItem::_sectionDirtyChanged);
999 connect(_speedSection, &SpeedSection::itemCountChanged, this, &SimpleMissionItem::_updateLastSequenceNumber);
1001
1002 emit cameraSectionChanged(_cameraSection);
1003 emit speedSectionChanged(_speedSection);
1005}
1006
1008{
1009 return sequenceNumber() + (_cameraSection ? _cameraSection->itemCount() : 0) + (_speedSection ? _speedSection->itemCount() : 0);
1010}
1011
1012void SimpleMissionItem::_updateLastSequenceNumber(void)
1013{
1015}
1016
1017void SimpleMissionItem::_sectionDirtyChanged(bool dirty)
1018{
1019 if (dirty) {
1020 setDirty(true);
1021 }
1022}
1023
1024void SimpleMissionItem::appendMissionItems(QList<MissionItem*>& items, QObject* missionItemParent)
1025{
1026 int seqNum = sequenceNumber();
1027
1028 items.append(new MissionItem(missionItem(), missionItemParent));
1029 seqNum++;
1030
1031 _cameraSection->appendSectionItems(items, missionItemParent, seqNum);
1032 _speedSection->appendSectionItems(items, missionItemParent, seqNum);
1033}
1034
1036{
1037 MAV_CMD command = static_cast<MAV_CMD>(this->command());
1039
1040 if (uiInfo && (uiInfo->specifiesCoordinate() || uiInfo->specifiesAltitudeOnly())) {
1041 switch (static_cast<MAV_CMD>(this->command())) {
1042 case MAV_CMD_NAV_LAND:
1043 case MAV_CMD_NAV_VTOL_LAND:
1044 // Leave alone
1045 break;
1046 default:
1047 _altitudeFact.setRawValue(newAltitude);
1048 break;
1049 }
1050 }
1051}
1052
1054{
1055 VisualMissionItem::setMissionFlightStatus(missionFlightStatus);
1056
1057 // If speed and/or gimbal are not specifically set on this item. Then use the flight status values as initial defaults should a user turn them on.
1058 if (_speedSection->available() && !_speedSection->specifyFlightSpeed() && !QGC::fuzzyCompare(_speedSection->flightSpeed()->rawValue().toDouble(), missionFlightStatus.vehicleSpeed)) {
1059 _speedSection->flightSpeed()->setRawValue(missionFlightStatus.vehicleSpeed);
1060 }
1061 if (_cameraSection->available() && !_cameraSection->specifyGimbal()) {
1062 if (!qIsNaN(missionFlightStatus.gimbalYaw) && !QGC::fuzzyCompare(_cameraSection->gimbalYaw()->rawValue().toDouble(), missionFlightStatus.gimbalYaw)) {
1063 _cameraSection->gimbalYaw()->setRawValue(missionFlightStatus.gimbalYaw);
1064 }
1065 if (!qIsNaN(missionFlightStatus.gimbalPitch) && !QGC::fuzzyCompare(_cameraSection->gimbalPitch()->rawValue().toDouble(), missionFlightStatus.gimbalPitch)) {
1066 _cameraSection->gimbalPitch()->setRawValue(missionFlightStatus.gimbalPitch);
1067 }
1068 }
1069}
1070
1072{
1073 if (altitudeFrame != _altitudeFrame) {
1074 _altitudeFrame = altitudeFrame;
1075 emit altitudeFrameChanged();
1076 }
1077}
1078
1080{
1081 switch (command()) {
1082 case MAV_CMD_NAV_WAYPOINT:
1083 case MAV_CMD_CONDITION_DELAY:
1084 case MAV_CMD_NAV_DELAY:
1085 return missionItem().param1();
1086 default:
1087 return 0;
1088 }
1089}
1090
1091void SimpleMissionItem::_possibleAdditionalTimeDelayChanged(void)
1092{
1093 switch (command()) {
1094 case MAV_CMD_NAV_WAYPOINT:
1095 case MAV_CMD_CONDITION_DELAY:
1096 case MAV_CMD_NAV_DELAY:
1098 break;
1099 }
1100
1101 return;
1102}
1103
1105{
1106 return MissionCommandTree::instance()->isLandCommand(static_cast<MAV_CMD>(this->command()));
1107}
1108
1109QGeoCoordinate SimpleMissionItem::coordinate(void) const
1110{
1111 if (qIsNaN(_missionItem.param5()) || qIsNaN(_missionItem.param6())) {
1112 return QGeoCoordinate();
1113 } else {
1114 return QGeoCoordinate(_missionItem.param5(), _missionItem.param6());
1115 }
1116}
1117
1119{
1120 return _missionItem.param7();
1121}
1122
1124{
1125 switch (_altitudeFrame) {
1127 return _missionItem.param7() + _terrainAltitude;
1130 return _missionItem.param7();
1132 return _missionItem.param7() + _masterController->missionController()->plannedHomePosition().altitude();
1134 qWarning() << "Internal Error SimpleMissionItem::amslEntryAlt: Invalid altitudeFrame:AltitudeFrameNone";
1135 return qQNaN();
1137 qWarning() << "Internal Error SimpleMissionItem::amslEntryAlt: Invalid altitudeFrame:AltitudeFrameMixed";
1138 return qQNaN();
1139 }
1140
1141 qWarning() << "Internal Error SimpleMissionItem::amslEntryAlt: Invalid altitudeFrame:" << _altitudeFrame;
1142 return qQNaN();
1143}
1144
1145void SimpleMissionItem::_signalIfVTOLTransitionCommand(void)
1146{
1147 if (mavCommand() == MAV_CMD_DO_VTOL_TRANSITION) {
1148 // This will cause a MissionController recalc
1150 }
1151}
1152
1153void SimpleMissionItem::_possibleRadiusChanged(void)
1154{
1155 if (isLoiterItem()) {
1157 }
1158}
QString errorString
bool scanForSection(QmlObjectListModel *visualItems, int scanIndex) override
double specifiedGimbalPitch(void) const
void appendSectionItems(QList< MissionItem * > &items, QObject *missionItemParent, int &seqNum) override
void specifiedGimbalYawChanged(double gimbalYaw)
double specifiedGimbalYaw(void) const
Fact * gimbalPitch(void)
Fact * gimbalYaw(void)
void specifiedGimbalPitchChanged(double gimbalPitch)
bool specifyGimbal(void) const
bool available(void) const override
int itemCount(void) const override
void setDirty(bool dirty) override
void setAvailable(bool available) override
Holds the meta data associated with a Fact.
void setRawUnits(const QString &rawUnits)
void setDecimalPlaces(int decimalPlaces)
void setRawUserMin(const QVariant &rawUserMin)
void setRawUserMax(const QVariant &rawUserMax)
void setRawMin(const QVariant &rawMin)
void setRawDefaultValue(const QVariant &rawDefaultValue)
void setEnumInfo(const QStringList &strings, const QVariantList &values)
void setRawMax(const QVariant &rawMax)
void setRawIncrement(double increment)
A Fact is used to hold a single value within the system.
Definition Fact.h:17
void setName(const QString &name)
Generally you should not change the name of a fact. But if you know what you are doing,...
Definition Fact.h:177
void setMetaData(FactMetaData *metaData, bool setDefaultFromMetaData=false)
Definition Fact.cc:713
void setRawValue(const QVariant &value)
Definition Fact.cc:134
QVariant rawValue() const
Value after translation.
Definition Fact.h:85
void valueChanged(const QVariant &value)
This signal is only meant for use by the QT property system. It should not be connected to by client ...
UI Information associated with a mission command (MAV_CMD) parameter.
bool advanced(void) const
int decimalPlaces(void) const
QString label(void) const
QString units(void) const
QVariantList enumValues(void) const
QStringList enumStrings(void) const
double userMin(void) const
double defaultValue(void) const
double max(void) const
double userMax(void) const
bool nanUnchanged(void) const
double min(void) const
Manages a hierarchy of MissionCommandUIInfo.
bool isLandCommand(MAV_CMD command) const
static MissionCommandTree * instance()
const MissionCommandUIInfo * getUIInfo(Vehicle *vehicle, QGCMAVLink::VehicleClass_t vtolMode, MAV_CMD command)
UI Information associated with a mission command (MAV_CMD)
bool isLoiterCommand(void) const
QString category(void) const
QString description(void) const
QString friendlyName(void) const
bool specifiesCoordinate(void) const
const MissionCmdParamInfo * getParamInfo(int index, bool &showUI) const
bool isStandaloneCoordinate(void) const
bool specifiesAltitudeOnly(void) const
bool friendlyEdit(void) const
void plannedHomePositionChanged(QGeoCoordinate plannedHomePosition)
QGeoCoordinate plannedHomePosition(void) const
double specifiedGimbalPitch(void) const
MAV_CMD command(void) const
Definition MissionItem.h:49
double specifiedFlightSpeed(void) const
void specifiedFlightSpeedChanged(double flightSpeed)
void setFrame(MAV_FRAME frame)
double param5(void) const
Definition MissionItem.h:58
void setParam7(double param7)
double specifiedGimbalYaw(void) const
void setAutoContinue(bool autoContinue)
bool relativeAltitude(void) const
Definition MissionItem.h:90
void setParam6(double param6)
double param7(void) const
Definition MissionItem.h:60
MAV_FRAME frame(void) const
Definition MissionItem.h:52
void save(QJsonObject &json) const
void setParam3(double param3)
bool autoContinue(void) const
Definition MissionItem.h:53
bool isCurrentItem(void) const
Definition MissionItem.h:50
double param3(void) const
Definition MissionItem.h:56
double param6(void) const
Definition MissionItem.h:59
double param1(void) const
Definition MissionItem.h:54
void setParam2(double param2)
int sequenceNumber(void) const
Definition MissionItem.h:51
double param4(void) const
Definition MissionItem.h:57
void setSequenceNumber(int sequenceNumber)
double param2(void) const
Definition MissionItem.h:55
void sequenceNumberChanged(int sequenceNumber)
bool load(QTextStream &loadStream)
void setParam5(double param5)
void setCommand(MAV_CMD command)
static MultiVehicleManager * instance()
Vehicle * activeVehicle() const
Master controller for mission, fence, rally.
MissionController * missionController(void)
void append(QObject *object)
Caller maintains responsibility for object ownership and deletion.
void clear() override final
void dirtyChanged(bool dirty)
void itemCountChanged(int itemCount)
void availableChanged(bool available)
static SettingsManager * instance()
AppSettings * appSettings() const
bool specifiesCoordinate(void) const final
void setSequenceNumber(int sequenceNumber) final
bool specifiesAltitudeOnly(void) const final
ReadyForSaveState readyForSaveState(void) const final
double editableAlt(void) const final
bool rawEdit(void) const
bool dirty(void) const override
bool friendlyEditAllowed(void) const
void rawEditChanged(bool rawEdit)
void speedSectionChanged(QObject *cameraSection)
void commandChanged(int command)
bool isStandaloneCoordinate(void) const final
void applyNewAltitude(double newAltitude) final
Adjust the altitude of the item if appropriate to the new altitude.
void appendMissionItems(QList< MissionItem * > &items, QObject *missionItemParent) final
void isLoiterItemChanged(void)
SimpleMissionItem(PlanMasterController *masterController, bool flyView, bool forLoad)
void friendlyEditAllowedChanged(bool friendlyEditAllowed)
int sequenceNumber(void) const final
void loiterRadiusChanged(double loiterRadius)
void showLoiterRadiusChanged(void)
bool scanForSections(QmlObjectListModel *visualItems, int scanIndex, PlanMasterController *masterController)
bool showLoiterRadius(void) const
void altitudeFrameChanged(void)
QString abbreviation(void) const final
double specifiedVehicleYaw(void) override
int lastSequenceNumber(void) const final
void setRadius(double loiterRadius)
MAV_CMD mavCommand(void) const
double amslEntryAlt(void) const final
bool specifiesAltitude(void) const
bool isLandCommand(void) const final
QGeoCoordinate coordinate(void) const final
virtual bool load(QTextStream &loadStream)
QString commandDescription(void) const final
double loiterRadius(void) const
QString commandName(void) const final
void setCoordinate(const QGeoCoordinate &coordinate) override
void setCommand(int command)
double specifiedFlightSpeed(void) override
bool isLoiterItem(void) const
int command(void) const
void setAltitudeFrame(QGroundControlQmlGlobal::AltitudeFrame altitudeFrame)
double specifiedGimbalYaw(void) override
MissionItem & missionItem(void)
~SimpleMissionItem()
true: raw item editing with all params
double specifiedGimbalPitch(void) override
void cameraSectionChanged(QObject *cameraSection)
QGroundControlQmlGlobal::AltitudeFrame altitudeFrame(void) const
void setDirty(bool dirty) final
void setRawEdit(bool rawEdit)
void save(QJsonArray &missionItems) final
QString category(void) const
void setMissionFlightStatus(MissionFlightStatus_t &missionFlightStatus) final
double additionalTimeDelay(void) const final
Fact * flightSpeed(void)
void setAvailable(bool available) override
int itemCount(void) const override
void specifiedFlightSpeedChanged(double flightSpeed)
void appendSectionItems(QList< MissionItem * > &items, QObject *missionItemParent, int &seqNum) override
bool specifyFlightSpeed(void) const
void setDirty(bool dirty) override
bool available(void) const override
bool scanForSection(QmlObjectListModel *visualItems, int scanIndex) override
bool vtol() const
Definition Vehicle.cc:1761
bool fixedWing() const
Definition Vehicle.cc:1736
PlanMasterController * _masterController
void specifiedVehicleYawChanged(void)
bool _homePositionSpecialCase
true: This item is being used as a ui home position indicator
void abbreviationChanged(void)
virtual bool isTakeoffItem(void) const
void amslExitAltChanged(double alt)
QString _editorQml
Qml resource for editing item.
void terrainAltitudeChanged(double terrainAltitude)
void specifiesAltitudeOnlyChanged(void)
void lastSequenceNumberChanged(int sequenceNumber)
void commandNameChanged(void)
void entryCoordinateChanged(const QGeoCoordinate &entryCoordinate)
void specifiesCoordinateChanged(void)
void coordinateChanged(const QGeoCoordinate &coordinate)
QGCMAVLinkTypes::VehicleClass_t _previousVTOLMode
Generic == unknown.
void readyForSaveStateChanged(void)
void specifiedFlightSpeedChanged(void)
void currentVTOLModeChanged(void)
Signals that this item has changed the VTOL mode (MAV_CMD_DO_VTOL_TRANSITION)
bool homePosition(void) const
< Flight path cumalative horizontal distance from home point to this item
void commandDescriptionChanged(void)
MissionController * _missionController
void specifiedGimbalYawChanged(void)
void isStandaloneCoordinateChanged(void)
void amslEntryAltChanged(double alt)
void specifiedGimbalPitchChanged(void)
double _terrainAltitude
Altitude of terrain at coordinate position, NaN for not known.
bool _wizardMode
true: Item editor is showing wizard completion panel
void _amslEntryAltChanged(void)
void dirtyChanged(bool dirty)
void isLandCommandChanged(void)
void previousVTOLModeChanged(void)
void sequenceNumberChanged(int sequenceNumber)
void exitCoordinateChanged(const QGeoCoordinate &exitCoordinate)
void additionalTimeDelayChanged(void)
void wizardModeChanged(bool wizardMode)
virtual void setMissionFlightStatus(MissionFlightStatus_t &missionFlightStatus)
double terrainAltitude(void) const
bool validateKeys(const QJsonObject &jsonObject, const QList< KeyValidateInfo > &keyInfo, QString &errorString)
Validates that all required keys are present and that listed keys have the expected type.
double possibleNaNJsonValue(const QJsonValue &value)
Returns NaN if the value is null, or the value converted to double otherwise.
bool fuzzyCompare(double value1, double value2)
Returns true if the two values are equal or close. Correctly handles 0 and NaN values.
Definition QGCMath.cc:109
double gimbalPitch
NaN signals pitch was never changed.
double vehicleSpeed
Either cruise or hover speed based on vehicle type and vtol state.
double gimbalYaw
NaN signals yaw was never changed.