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::rawValueChanged, this, &SimpleMissionItem::_setDirty);
111 connect(&_missionItem._param2Fact, &Fact::rawValueChanged, this, &SimpleMissionItem::_setDirty);
112 connect(&_missionItem._param3Fact, &Fact::rawValueChanged, this, &SimpleMissionItem::_setDirty);
113 connect(&_missionItem._param4Fact, &Fact::rawValueChanged, this, &SimpleMissionItem::_setDirty);
114 connect(&_missionItem._param5Fact, &Fact::rawValueChanged, this, &SimpleMissionItem::_setDirty);
115 connect(&_missionItem._param6Fact, &Fact::rawValueChanged, this, &SimpleMissionItem::_setDirty);
116 connect(&_missionItem._param7Fact, &Fact::rawValueChanged, this, &SimpleMissionItem::_setDirty);
117 connect(&_missionItem._frameFact, &Fact::rawValueChanged, this, &SimpleMissionItem::_setDirty);
118 connect(&_missionItem._commandFact, &Fact::rawValueChanged, this, &SimpleMissionItem::_setDirty);
119 connect(&_missionItem, &MissionItem::sequenceNumberChanged, this, &SimpleMissionItem::_setDirty);
120 connect(this, &SimpleMissionItem::altitudeFrameChanged, this, &SimpleMissionItem::_setDirty);
121
122 connect(&_altitudeFact, &Fact::rawValueChanged, 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
317 // Terrain-frame AMSL altitude, and calculated AMSL missing from the plan file, need a terrain query
318 const bool calcMissingAmsl =
319 (_altitudeFrame == QGroundControlQmlGlobal::AltitudeFrameCalcAboveTerrain) && qIsNaN(_missionItem.param7());
320 if (specifiesAltitude() && ((_altitudeFrame == QGroundControlQmlGlobal::AltitudeFrameTerrain) || calcMissingAmsl)) {
322 }
323
324 setDirty(false);
325
326 return true;
327}
328
330{
332 if (uiInfo) {
333 return uiInfo->isStandaloneCoordinate();
334 } else {
335 return false;
336 }
337}
338
340{
342 if (uiInfo) {
343 return uiInfo->specifiesCoordinate();
344 } else {
345 return false;
346 }
347}
348
350{
352 if (uiInfo) {
353 return uiInfo->specifiesAltitudeOnly();
354 } else {
355 return false;
356 }
357}
358
360{
362 if (uiInfo) {
363 return uiInfo->description();
364 } else {
365 qWarning() << "Should not ask for command description on unknown command";
366 return commandName();
367 }
368}
369
371{
373 if (uiInfo) {
374 return uiInfo->friendlyName();
375 } else {
376 qWarning() << "Request for command name on unknown command";
377 return tr("Unknown: %1").arg(command());
378 }
379}
380
382{
383 if (homePosition())
384 return tr("L");
385
386 switch(command()) {
387 case MAV_CMD_NAV_TAKEOFF:
388 return tr("Takeoff");
389 case MAV_CMD_NAV_LAND:
390 return tr("Land");
391 case MAV_CMD_NAV_VTOL_TAKEOFF:
392 return tr("Transition Direction");
393 case MAV_CMD_NAV_VTOL_LAND:
394 return tr("VTOL Land");
395 case MAV_CMD_DO_SET_ROI:
396 case MAV_CMD_DO_SET_ROI_LOCATION:
397 return tr("ROI");
398 case MAV_CMD_NAV_LOITER_TIME:
399 case MAV_CMD_NAV_LOITER_TURNS:
400 case MAV_CMD_NAV_LOITER_UNLIM:
401 case MAV_CMD_NAV_LOITER_TO_ALT:
402 return tr("Loiter");
403 default:
404 return QString();
405 }
406}
407
408void SimpleMissionItem::_rebuildTextFieldFacts(void)
409{
410 _textFieldFacts.clear();
411 _textFieldFactsAdvanced.clear();
412
413 if (rawEdit()) {
414 _missionItem._param1Fact.setName("Param1");
415 _missionItem._param1Fact.setMetaData(_defaultParamMetaData);
416 _textFieldFacts.append(&_missionItem._param1Fact);
417 _missionItem._param2Fact.setName("Param2");
418 _missionItem._param2Fact.setMetaData(_defaultParamMetaData);
419 _textFieldFacts.append(&_missionItem._param2Fact);
420 _missionItem._param3Fact.setName("Param3");
421 _missionItem._param3Fact.setMetaData(_defaultParamMetaData);
422 _textFieldFacts.append(&_missionItem._param3Fact);
423 _missionItem._param4Fact.setName("Param4");
424 _missionItem._param4Fact.setMetaData(_defaultParamMetaData);
425 _textFieldFacts.append(&_missionItem._param4Fact);
426 _missionItem._param5Fact.setName("Lat/X");
427 _missionItem._param5Fact.setMetaData(_defaultParamMetaData);
428 _textFieldFacts.append(&_missionItem._param5Fact);
429 _missionItem._param6Fact.setName("Lon/Y");
430 _missionItem._param6Fact.setMetaData(_defaultParamMetaData);
431 _textFieldFacts.append(&_missionItem._param6Fact);
432 _missionItem._param7Fact.setName("Alt/Z");
433 _missionItem._param7Fact.setMetaData(_defaultParamMetaData);
434 _textFieldFacts.append(&_missionItem._param7Fact);
435 } else {
436 _ignoreDirtyChangeSignals = true;
437
438 MAV_CMD command;
440 command = MAV_CMD_NAV_LAST;
441 } else {
442 command = _missionItem.command();
443 }
444
445 Fact* rgParamFacts[7] = { &_missionItem._param1Fact, &_missionItem._param2Fact, &_missionItem._param3Fact, &_missionItem._param4Fact, &_missionItem._param5Fact, &_missionItem._param6Fact, &_missionItem._param7Fact };
446 FactMetaData* rgParamMetaData[7] = { &_param1MetaData, &_param2MetaData, &_param3MetaData, &_param4MetaData, &_param5MetaData, &_param6MetaData, &_param7MetaData };
447
449
450 if (uiInfo) {
451 for (int i=1; i<=7; i++) {
452 bool showUI;
453 const MissionCmdParamInfo* paramInfo = uiInfo->getParamInfo(i, showUI);
454
455 if (showUI && paramInfo && paramInfo->enumStrings().count() == 0 && !paramInfo->nanUnchanged()) {
456 Fact* paramFact = rgParamFacts[i-1];
457 FactMetaData* paramMetaData = rgParamMetaData[i-1];
458
459 paramFact->setName(paramInfo->label());
460 paramMetaData->setDecimalPlaces(paramInfo->decimalPlaces());
461 paramMetaData->setRawUnits(paramInfo->units());
462 paramMetaData->setRawDefaultValue(paramInfo->defaultValue());
463 paramMetaData->setRawMin(paramInfo->min());
464 paramMetaData->setRawMax(paramInfo->max());
465 const double userMin = paramInfo->userMin();
466 const double userMax = paramInfo->userMax();
467 // if user min/max are NaN, we leave them unchanged (invalid)
468 if (!qIsNaN(userMin)) {
469 paramMetaData->setRawUserMin(userMin);
470 }
471 if (!qIsNaN(userMax)) {
472 paramMetaData->setRawUserMax(userMax);
473 }
474 paramFact->setMetaData(paramMetaData);
475 if (paramInfo->advanced()) {
476 _textFieldFactsAdvanced.append(paramFact);
477 } else {
478 _textFieldFacts.append(paramFact);
479 }
480 }
481 }
482 }
483
484 _ignoreDirtyChangeSignals = false;
485 }
486}
487
488void SimpleMissionItem::_rebuildNaNFacts(void)
489{
490 _nanFacts.clear();
491 _nanFactsAdvanced.clear();
492
493 if (!rawEdit()) {
494 _ignoreDirtyChangeSignals = true;
495
496 MAV_CMD command;
498 command = MAV_CMD_NAV_LAST;
499 } else {
500 command = _missionItem.command();
501 }
502
503 Fact* rgParamFacts[7] = { &_missionItem._param1Fact, &_missionItem._param2Fact, &_missionItem._param3Fact, &_missionItem._param4Fact, &_missionItem._param5Fact, &_missionItem._param6Fact, &_missionItem._param7Fact };
504 FactMetaData* rgParamMetaData[7] = { &_param1MetaData, &_param2MetaData, &_param3MetaData, &_param4MetaData, &_param5MetaData, &_param6MetaData, &_param7MetaData };
505
507
508 if (uiInfo) {
509 for (int i=1; i<=7; i++) {
510 bool showUI;
511 const MissionCmdParamInfo* paramInfo = uiInfo->getParamInfo(i, showUI);
512
513 if (showUI && paramInfo && paramInfo->nanUnchanged()) {
514 // 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
515 // and not _controllerVehicle which is always offline.
517 if (!firmwareVehicle) {
518 firmwareVehicle = _controllerVehicle;
519 }
520
521 Fact* paramFact = rgParamFacts[i-1];
522 FactMetaData* paramMetaData = rgParamMetaData[i-1];
523
524 paramFact->setName(paramInfo->label());
525 paramMetaData->setDecimalPlaces(paramInfo->decimalPlaces());
526 paramMetaData->setRawUnits(paramInfo->units());
527 paramMetaData->setRawDefaultValue(paramInfo->defaultValue());
528 paramMetaData->setRawMin(paramInfo->min());
529 paramMetaData->setRawMax(paramInfo->max());
530 const double userMin = paramInfo->userMin();
531 const double userMax = paramInfo->userMax();
532 // if user min/max are NaN, we leave them unchanged (invalid)
533 if (!qIsNaN(userMin)) {
534 paramMetaData->setRawUserMin(userMin);
535 }
536 if (!qIsNaN(userMax)) {
537 paramMetaData->setRawUserMax(userMax);
538 }
539 paramFact->setMetaData(paramMetaData);
540 if (paramInfo->advanced()) {
541 _nanFactsAdvanced.append(paramFact);
542 } else {
543 _nanFacts.append(paramFact);
544 }
545 }
546 }
547 }
548
549 _ignoreDirtyChangeSignals = false;
550 }
551}
552
557
559{
561 if (uiInfo) {
562 return uiInfo->isLoiterCommand();
563 } else {
564 return false;
565 }
566}
567
569{
570 const MissionCommandUIInfo *uiInfo =
572 _controllerVehicle, _previousVTOLMode, MAV_CMD_NAV_LOITER_TIME);
573 bool showUI;
574 uiInfo->getParamInfo(3, showUI);
575
576 if (isLoiterItem() && command() == MAV_CMD_NAV_LOITER_TIME && !showUI) {
577 // Don't show the radius of MAV_CMD_NAV_LOITER_TIME items if the
578 // firmware doesn't support specifying it
579 return false;
580 }
581
583}
584
586{
587 if (isLoiterItem()) {
588 return command() == MAV_CMD_NAV_LOITER_TO_ALT ? missionItem().param2() : missionItem().param3();
589 } else {
590 return qQNaN();
591 }
592}
593
594void SimpleMissionItem::_rebuildComboBoxFacts(void)
595{
596 _comboboxFacts.clear();
597 _comboboxFactsAdvanced.clear();
598
599 if (rawEdit()) {
600 _comboboxFacts.append(&_missionItem._commandFact);
601 _comboboxFacts.append(&_missionItem._frameFact);
602 } else {
603 _ignoreDirtyChangeSignals = true;
604
605 Fact* rgParamFacts[7] = { &_missionItem._param1Fact, &_missionItem._param2Fact, &_missionItem._param3Fact, &_missionItem._param4Fact, &_missionItem._param5Fact, &_missionItem._param6Fact, &_missionItem._param7Fact };
606 FactMetaData* rgParamMetaData[7] = { &_param1MetaData, &_param2MetaData, &_param3MetaData, &_param4MetaData, &_param5MetaData, &_param6MetaData, &_param7MetaData };
607
608 MAV_CMD command;
610 command = MAV_CMD_NAV_LAST;
611 } else {
612 command = (MAV_CMD)this->command();
613 }
614
615 for (int i=1; i<=7; i++) {
616 bool showUI;
618
619 if (showUI && paramInfo && paramInfo->enumStrings().count() != 0) {
620 Fact* paramFact = rgParamFacts[i-1];
621 FactMetaData* paramMetaData = rgParamMetaData[i-1];
622
623 paramFact->setName(paramInfo->label());
624 paramMetaData->setDecimalPlaces(paramInfo->decimalPlaces());
625 paramMetaData->setEnumInfo(paramInfo->enumStrings(), paramInfo->enumValues());
626 paramMetaData->setRawUnits(paramInfo->units());
627 paramMetaData->setRawDefaultValue(paramInfo->defaultValue());
628 paramMetaData->setRawMin(paramInfo->min());
629 paramMetaData->setRawMax(paramInfo->max());
630 const double userMin = paramInfo->userMin();
631 const double userMax = paramInfo->userMax();
632 // if user min/max are NaN, we leave them unchanged (invalid)
633 if (!qIsNaN(userMin)) {
634 paramMetaData->setRawUserMin(userMin);
635 }
636 if (!qIsNaN(userMax)) {
637 paramMetaData->setRawUserMax(userMax);
638 }
639 paramFact->setMetaData(paramMetaData);
640 if (paramInfo->advanced()) {
641 _comboboxFactsAdvanced.append(paramFact);
642 } else {
643 _comboboxFacts.append(paramFact);
644 }
645 }
646 }
647
648 _ignoreDirtyChangeSignals = false;
649 }
650}
651
652void SimpleMissionItem::_rebuildFacts(void)
653{
654 // Reset param metadata to defaults so stale min/max from a previous command
655 // does not cause setRawMin/setRawMax to spuriously reject sentinel values.
656 const FactMetaData kDefaultDouble(FactMetaData::valueTypeDouble);
657 _param1MetaData = kDefaultDouble;
658 _param2MetaData = kDefaultDouble;
659 _param3MetaData = kDefaultDouble;
660 _param4MetaData = kDefaultDouble;
661 _param5MetaData = kDefaultDouble;
662 _param6MetaData = kDefaultDouble;
663 _param7MetaData = kDefaultDouble;
664
665 _rebuildTextFieldFacts();
666 _rebuildNaNFacts();
667 _rebuildComboBoxFacts();
668}
669
671{
673 if (uiInfo && uiInfo->friendlyEdit()) {
674 if (!_missionItem.autoContinue()) {
675 return false;
676 }
677
678 if (specifiesAltitude()) {
679 MAV_FRAME frame = _missionItem.frame();
680 switch (frame) {
681 case MAV_FRAME_GLOBAL:
682 case MAV_FRAME_GLOBAL_RELATIVE_ALT:
683 case MAV_FRAME_GLOBAL_TERRAIN_ALT:
684 return true;
685 default:
686 return false;
687 }
688 }
689
690 return true;
691 }
692
693 return false;
694}
695
697{
698 return _rawEdit || !friendlyEditAllowed();
699}
700
702{
703 if (this->rawEdit() != rawEdit) {
704 _rawEdit = rawEdit;
705 emit rawEditChanged(this->rawEdit());
706 }
707}
708
710{
711 if (!_homePositionSpecialCase || (_dirty != dirty)) {
712 _dirty = dirty;
713 if (!dirty) {
714 _cameraSection->setDirty(false);
715 _speedSection->setDirty(false);
716 }
717 emit dirtyChanged(dirty);
718 }
719}
720
721void SimpleMissionItem::_setDirty(void)
722{
723 if (!_ignoreDirtyChangeSignals) {
724 setDirty(true);
725 }
726}
727
728void SimpleMissionItem::_sendCoordinateChanged(void)
729{
731}
732
733void SimpleMissionItem::_altitudeFrameChanged(void)
734{
735 switch (_altitudeFrame) {
737 _missionItem.setFrame(MAV_FRAME_GLOBAL_TERRAIN_ALT);
738 break;
740 // Terrain altitudes are Absolute
741 _missionItem.setFrame(MAV_FRAME_GLOBAL);
742 // Clear any old calculated values
743 _missionItem._param7Fact.setRawValue(qQNaN());
744 _amslAltAboveTerrainFact.setRawValue(qQNaN());
745 break;
747 _missionItem.setFrame(MAV_FRAME_GLOBAL);
748 break;
750 _missionItem.setFrame(MAV_FRAME_GLOBAL_RELATIVE_ALT);
751 break;
753 qWarning() << "Internal Error SimpleMissionItem::_altitudeFrameChanged: Invalid altitudeFrame == AltitudeFrameNone";
754 break;
756 qWarning() << "Internal Error SimpleMissionItem::_altitudeFrameChanged: Invalid altitudeFrame == AltitudeFrameMixed";
757 break;
758 }
759
760 // We always call _altitudeChanged to make sure that param7 is always setup correctly on mode change
761 _altitudeChanged();
762}
763
764void SimpleMissionItem::_altitudeChanged(void)
765{
766 if (!specifiesAltitude()) {
767 return;
768 }
769
771 _amslAltAboveTerrainFact.setRawValue(qQNaN());
772 _terrainAltChanged();
773 }
774
776 _missionItem._param7Fact.setRawValue(_altitudeFact.rawValue());
777 }
778}
779
780void SimpleMissionItem::_terrainAltChanged(void)
781{
782 if (!specifiesAltitude()) {
783 // We don't need terrain data
784 return;
785 }
786
788 if (qIsNaN(terrainAltitude())) {
789 // Set NaNs to signal we are waiting on terrain data
791 _missionItem._param7Fact.setRawValue(qQNaN());
792 }
793 _amslAltAboveTerrainFact.setRawValue(qQNaN());
794 } else {
795 double newAboveTerrain = terrainAltitude() + _altitudeFact.rawValue().toDouble();
796 double oldAboveTerrain = _amslAltAboveTerrainFact.rawValue().toDouble();
797 if (!QGC::fuzzyCompare(newAboveTerrain, oldAboveTerrain)) {
799 _missionItem._param7Fact.setRawValue(newAboveTerrain);
800 }
801 _amslAltAboveTerrainFact.setRawValue(newAboveTerrain);
802 }
803 }
805 }
806}
807
809{
810 if (_wizardMode) {
811 return NotReadyForSaveData;
812 }
813
814 bool terrainReady = !specifiesAltitude() || !qIsNaN(_missionItem._param7Fact.rawValue().toDouble());
815 return terrainReady ? ReadyForSave : NotReadyForSaveTerrain;
816}
817
818void SimpleMissionItem::_setDefaultsForCommand(void)
819{
820 // First reset params 1-4 to 0, we leave 5-7 alone to preserve any previous location information on command change
821 _missionItem._param1Fact.setRawValue(0);
822 _missionItem._param2Fact.setRawValue(0);
823 _missionItem._param3Fact.setRawValue(0);
824 _missionItem._param4Fact.setRawValue(0);
825
827 // No need to carry across previous lat/lon
828 _missionItem._param5Fact.setRawValue(0);
829 _missionItem._param6Fact.setRawValue(0);
830 } else if ((specifiesCoordinate() || isStandaloneCoordinate()) && _missionItem._param5Fact.rawValue().toDouble() == 0 && _missionItem._param6Fact.rawValue().toDouble() == 0) {
831 // We switched from a command without a coordinate to a command with a coordinate. Use the hint.
832 _missionItem._param5Fact.setRawValue(_mapCenterHint.latitude());
833 _missionItem._param6Fact.setRawValue(_mapCenterHint.longitude());
834 }
835
836 // Set global defaults first, then if there are param defaults they will get reset
839 _amslAltAboveTerrainFact.setRawValue(qQNaN());
840 if (specifiesAltitude()) {
841 double defaultAlt = SettingsManager::instance()->appSettings()->defaultMissionItemAltitude()->rawValue().toDouble();
842 _altitudeFact.setRawValue(defaultAlt);
843 _missionItem._param7Fact.setRawValue(defaultAlt);
844 // Note that setAltitudeFrame will also set MAV_FRAME correctly through signalling
845 // Takeoff items always use relative alt since that is the highest quality data to base altitude from
847 } else {
848 _altitudeFact.setRawValue(0);
849 _missionItem._param7Fact.setRawValue(0);
850 _missionItem.setFrame(MAV_FRAME_MISSION);
851 }
852
853 MAV_CMD command = static_cast<MAV_CMD>(this->command());
855 if (uiInfo) {
856 for (int i=1; i<=7; i++) {
857 bool showUI;
858 const MissionCmdParamInfo* paramInfo = uiInfo->getParamInfo(i, showUI);
859 if (paramInfo) {
860 Fact* rgParamFacts[7] = { &_missionItem._param1Fact, &_missionItem._param2Fact, &_missionItem._param3Fact, &_missionItem._param4Fact, &_missionItem._param5Fact, &_missionItem._param6Fact, &_missionItem._param7Fact };
861 rgParamFacts[paramInfo->param()-1]->setRawValue(paramInfo->defaultValue());
862 }
863 }
864 }
865
866 if (command == MAV_CMD_NAV_WAYPOINT) {
867 // We default all acceptance radius to 0. This allows flight controller to be in control of
868 // accept radius.
869 _missionItem.setParam2(0);
870 } else if ((uiInfo && uiInfo->isLandCommand()) || command == MAV_CMD_DO_SET_ROI_LOCATION) {
871 _altitudeFact.setRawValue(0);
872 _missionItem.setParam7(0);
873 }
874
875 _missionItem.setAutoContinue(true);
876 setRawEdit(false);
877}
878
879void SimpleMissionItem::_sendCommandChanged(void)
880{
881 emit commandChanged(command());
882}
883
884void SimpleMissionItem::_sendFriendlyEditAllowedChanged(void)
885{
887}
888
890{
892 return uiInfo ? uiInfo->category() : QString();
893}
894
896{
897 if (static_cast<MAV_CMD>(command) != _missionItem.command()) {
898 _missionItem.setCommand(static_cast<MAV_CMD>(command));
899 _updateOptionalSections();
900 }
901}
902
904{
905 if (isLoiterItem()) {
906 const MAV_CMD command = static_cast<MAV_CMD>(this->command());
907 if (command == MAV_CMD_NAV_LOITER_TO_ALT)
908 _missionItem.setParam2(radius);
909 else
910 _missionItem.setParam3(radius);
911 }
912}
913
914void SimpleMissionItem::setCoordinate(const QGeoCoordinate& coordinate)
915{
916 // We only use lat/lon from coordinate. This keeps param7 and the altitude value which is kept to the side in sync.
917 if (_missionItem.param5() != coordinate.latitude() || _missionItem.param6() != coordinate.longitude()) {
918 _missionItem.setParam5(coordinate.latitude());
919 _missionItem.setParam6(coordinate.longitude());
920 }
921}
922
924{
925 if (_missionItem.sequenceNumber() != sequenceNumber) {
926 _missionItem.setSequenceNumber(sequenceNumber);
928 // This is too likely to ignore
929 emit abbreviationChanged();
930 }
931}
932
934{
935 if (_speedSection->specifyFlightSpeed()) {
936 return _speedSection->flightSpeed()->rawValue().toDouble();
937 } else {
939 }
940}
941
943{
944 return _cameraSection->available() ? _cameraSection->specifiedGimbalYaw() : missionItem().specifiedGimbalYaw();
945}
946
948{
949 return _cameraSection->available() ? _cameraSection->specifiedGimbalPitch() : missionItem().specifiedGimbalPitch();
950}
951
953{
954 return command() == MAV_CMD_NAV_WAYPOINT ? missionItem().param4() : qQNaN();
955}
956
957void SimpleMissionItem::_possibleVehicleYawChanged(void)
958{
959 if (command() == MAV_CMD_NAV_WAYPOINT) {
961 }
962}
963
964bool SimpleMissionItem::scanForSections(QmlObjectListModel* visualItems, int scanIndex, PlanMasterController* /*masterController*/)
965{
966 bool sectionFound = false;
967
968 if (_cameraSection->available()) {
969 sectionFound |= _cameraSection->scanForSection(visualItems, scanIndex);
970 }
971 if (_speedSection->available()) {
972 sectionFound |= _speedSection->scanForSection(visualItems, scanIndex);
973 }
974
975 return sectionFound;
976}
977
978void SimpleMissionItem::_updateOptionalSections(void)
979{
980 // Remove previous sections
981 if (_cameraSection) {
982 _cameraSection->deleteLater();
983 _cameraSection = nullptr;
984 }
985 if (_speedSection) {
986 _speedSection->deleteLater();
987 _speedSection = nullptr;
988 }
989
990 // Add new sections
991
992 _cameraSection = new CameraSection(_masterController, this);
993 _speedSection = new SpeedSection(_masterController, this);
994 if (static_cast<MAV_CMD>(command()) == MAV_CMD_NAV_WAYPOINT) {
995 _cameraSection->setAvailable(true);
996 _speedSection->setAvailable(true);
997 }
998
999 connect(_cameraSection, &CameraSection::dirtyChanged, this, &SimpleMissionItem::_sectionDirtyChanged);
1000 connect(_cameraSection, &CameraSection::itemCountChanged, this, &SimpleMissionItem::_updateLastSequenceNumber);
1005
1006 connect(_speedSection, &SpeedSection::dirtyChanged, this, &SimpleMissionItem::_sectionDirtyChanged);
1007 connect(_speedSection, &SpeedSection::itemCountChanged, this, &SimpleMissionItem::_updateLastSequenceNumber);
1009
1010 emit cameraSectionChanged(_cameraSection);
1011 emit speedSectionChanged(_speedSection);
1013}
1014
1016{
1017 return sequenceNumber() + (_cameraSection ? _cameraSection->itemCount() : 0) + (_speedSection ? _speedSection->itemCount() : 0);
1018}
1019
1020void SimpleMissionItem::_updateLastSequenceNumber(void)
1021{
1023}
1024
1025void SimpleMissionItem::_sectionDirtyChanged(bool dirty)
1026{
1027 if (dirty) {
1028 setDirty(true);
1029 }
1030}
1031
1032void SimpleMissionItem::appendMissionItems(QList<MissionItem*>& items, QObject* missionItemParent)
1033{
1034 int seqNum = sequenceNumber();
1035
1036 items.append(new MissionItem(missionItem(), missionItemParent));
1037 seqNum++;
1038
1039 _cameraSection->appendSectionItems(items, missionItemParent, seqNum);
1040 _speedSection->appendSectionItems(items, missionItemParent, seqNum);
1041}
1042
1044{
1045 MAV_CMD command = static_cast<MAV_CMD>(this->command());
1047
1048 if (uiInfo && (uiInfo->specifiesCoordinate() || uiInfo->specifiesAltitudeOnly())) {
1049 switch (static_cast<MAV_CMD>(this->command())) {
1050 case MAV_CMD_NAV_LAND:
1051 case MAV_CMD_NAV_VTOL_LAND:
1052 // Leave alone
1053 break;
1054 default:
1055 _altitudeFact.setRawValue(newAltitude);
1056 break;
1057 }
1058 }
1059}
1060
1062{
1063 VisualMissionItem::setMissionFlightStatus(missionFlightStatus);
1064
1065 // 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.
1066 if (_speedSection->available() && !_speedSection->specifyFlightSpeed() && !QGC::fuzzyCompare(_speedSection->flightSpeed()->rawValue().toDouble(), missionFlightStatus.vehicleSpeed)) {
1067 _speedSection->flightSpeed()->setRawValue(missionFlightStatus.vehicleSpeed);
1068 }
1069 if (_cameraSection->available() && !_cameraSection->specifyGimbal()) {
1070 if (!qIsNaN(missionFlightStatus.gimbalYaw) && !QGC::fuzzyCompare(_cameraSection->gimbalYaw()->rawValue().toDouble(), missionFlightStatus.gimbalYaw)) {
1071 _cameraSection->gimbalYaw()->setRawValue(missionFlightStatus.gimbalYaw);
1072 }
1073 if (!qIsNaN(missionFlightStatus.gimbalPitch) && !QGC::fuzzyCompare(_cameraSection->gimbalPitch()->rawValue().toDouble(), missionFlightStatus.gimbalPitch)) {
1074 _cameraSection->gimbalPitch()->setRawValue(missionFlightStatus.gimbalPitch);
1075 }
1076 }
1077}
1078
1080{
1081 if (altitudeFrame != _altitudeFrame) {
1082 _altitudeFrame = altitudeFrame;
1083 emit altitudeFrameChanged();
1084 }
1085}
1086
1088{
1089 switch (command()) {
1090 case MAV_CMD_NAV_WAYPOINT:
1091 case MAV_CMD_CONDITION_DELAY:
1092 case MAV_CMD_NAV_DELAY:
1093 return missionItem().param1();
1094 default:
1095 return 0;
1096 }
1097}
1098
1099void SimpleMissionItem::_possibleAdditionalTimeDelayChanged(void)
1100{
1101 switch (command()) {
1102 case MAV_CMD_NAV_WAYPOINT:
1103 case MAV_CMD_CONDITION_DELAY:
1104 case MAV_CMD_NAV_DELAY:
1106 break;
1107 }
1108
1109 return;
1110}
1111
1113{
1114 return MissionCommandTree::instance()->isLandCommand(static_cast<MAV_CMD>(this->command()));
1115}
1116
1117QGeoCoordinate SimpleMissionItem::coordinate(void) const
1118{
1119 if (qIsNaN(_missionItem.param5()) || qIsNaN(_missionItem.param6())) {
1120 return QGeoCoordinate();
1121 } else {
1122 return QGeoCoordinate(_missionItem.param5(), _missionItem.param6());
1123 }
1124}
1125
1127{
1128 return _missionItem.param7();
1129}
1130
1132{
1133 switch (_altitudeFrame) {
1135 return _missionItem.param7() + _terrainAltitude;
1138 return _missionItem.param7();
1140 return _missionItem.param7() + _masterController->missionController()->plannedHomePosition().altitude();
1142 qWarning() << "Internal Error SimpleMissionItem::amslEntryAlt: Invalid altitudeFrame:AltitudeFrameNone";
1143 return qQNaN();
1145 qWarning() << "Internal Error SimpleMissionItem::amslEntryAlt: Invalid altitudeFrame:AltitudeFrameMixed";
1146 return qQNaN();
1147 }
1148
1149 qWarning() << "Internal Error SimpleMissionItem::amslEntryAlt: Invalid altitudeFrame:" << _altitudeFrame;
1150 return qQNaN();
1151}
1152
1153void SimpleMissionItem::_signalIfVTOLTransitionCommand(void)
1154{
1155 if (mavCommand() == MAV_CMD_DO_VTOL_TRANSITION) {
1156 // This will cause a MissionController recalc
1158 }
1159}
1160
1161void SimpleMissionItem::_possibleRadiusChanged(void)
1162{
1163 if (isLoiterItem()) {
1165 }
1166}
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:15
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:178
void setMetaData(FactMetaData *metaData, bool setDefaultFromMetaData=false)
Definition Fact.cc:742
void rawValueChanged(const QVariant &value)
void setRawValue(const QVariant &value)
Definition Fact.cc:135
QVariant rawValue() const
Definition Fact.h:87
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
QString commandDescription(void) const override
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
QString commandName(void) const override
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)
double loiterRadius(void) const
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:1780
bool fixedWing() const
Definition Vehicle.cc:1755
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:71
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.