QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
PX4FirmwarePlugin.cc
Go to the documentation of this file.
1#include "PX4FirmwarePlugin.h"
2#include "ParameterMetaData.h"
4#include "AppMessages.h"
7#include "SettingsManager.h"
8#include "PlanViewSettings.h"
9#include "ParameterManager.h"
10#include "Vehicle.h"
11
12#include <QtCore/QString>
13
14#include "px4_custom_mode.h"
15
16QGC_LOGGING_CATEGORY(PX4FirmwarePluginLog, "FirmwarePlugin.PX4FirmwarePlugin")
17
20 , versionNotified(false)
21{
22
23}
24
26{
27 const QString manualFlightModeName = tr("Manual");
28 const QString acroFlightModeName = tr("Acro");
29 const QString stabilizedFlightModeName = tr("Stabilized");
30 const QString rattitudeFlightModeName = tr("Rattitude");
31 const QString altCtlFlightModeName = tr("Altitude");
32 const QString posCtlFlightModeName = tr("Position");
33 const QString offboardFlightModeName = tr("Offboard");
34 const QString readyFlightModeName = tr("Ready");
35 const QString takeoffFlightModeName = tr("Takeoff");
36 const QString holdFlightModeName = tr("Hold");
37 const QString missionFlightModeName = tr("Mission");
38 const QString rtlFlightModeName = tr("Return");
39 const QString landingFlightModeName = tr("Land");
40 const QString preclandFlightModeName = tr("Precision Land");
41 const QString followMeFlightModeName = tr("Follow Me");
42 const QString simpleFlightModeName = tr("Simple");
43 const QString orbitFlightModeName = tr("Orbit");
44 const QString slowFlightModeName = tr("Position Slow");
45 const QString altitudeCruiseFlightModeName = tr("Altitude Cruise");
46 const QString terminationFlightModeName = tr("Termination");
47 const QString vtolTakeoffFlightModeName = tr("VTOL Takeoff");
48 const QString guidedCourseFlightModeName = tr("Guided Course");
49
51 { PX4CustomMode::MANUAL, manualFlightModeName },
52 { PX4CustomMode::STABILIZED, stabilizedFlightModeName },
53 { PX4CustomMode::ACRO, acroFlightModeName },
54 { PX4CustomMode::RATTITUDE, rattitudeFlightModeName },
55 { PX4CustomMode::ALTCTL, altCtlFlightModeName },
56 { PX4CustomMode::OFFBOARD, offboardFlightModeName },
57 { PX4CustomMode::SIMPLE, simpleFlightModeName },
58 { PX4CustomMode::POSCTL_POSCTL, posCtlFlightModeName },
59 { PX4CustomMode::POSCTL_ORBIT, orbitFlightModeName },
60 { PX4CustomMode::POSCTL_SLOW, slowFlightModeName },
61 { PX4CustomMode::ALTITUDE_CRUISE, altitudeCruiseFlightModeName },
62 { PX4CustomMode::TERMINATION, terminationFlightModeName },
63 { PX4CustomMode::AUTO_LOITER, holdFlightModeName },
64 { PX4CustomMode::AUTO_MISSION, missionFlightModeName },
65 { PX4CustomMode::AUTO_RTL, rtlFlightModeName },
66 { PX4CustomMode::AUTO_FOLLOW_TARGET, followMeFlightModeName },
67 { PX4CustomMode::AUTO_LAND, landingFlightModeName },
68 { PX4CustomMode::AUTO_PRECLAND, preclandFlightModeName },
69 { PX4CustomMode::AUTO_READY, readyFlightModeName },
70 { PX4CustomMode::AUTO_TAKEOFF, takeoffFlightModeName },
71 { PX4CustomMode::AUTO_VTOL_TAKEOFF, vtolTakeoffFlightModeName },
72 { PX4CustomMode::AUTO_GUIDED_COURSE, guidedCourseFlightModeName },
73 });
74
75 static FlightModeList availableFlightModes = {
76 // Mode Name Custom Mode CanBeSet adv
77 { manualFlightModeName, PX4CustomMode::MANUAL, true, true },
78 { stabilizedFlightModeName, PX4CustomMode::STABILIZED, true, true },
79 { acroFlightModeName, PX4CustomMode::ACRO, true, true },
80 { rattitudeFlightModeName, PX4CustomMode::RATTITUDE, true, false},
81 { altCtlFlightModeName, PX4CustomMode::ALTCTL, true, false},
82 { offboardFlightModeName, PX4CustomMode::OFFBOARD, true, true },
83 { simpleFlightModeName, PX4CustomMode::SIMPLE, false, false},
84 { posCtlFlightModeName, PX4CustomMode::POSCTL_POSCTL, true, false},
85 { slowFlightModeName, PX4CustomMode::POSCTL_SLOW, true, true },
86 { altitudeCruiseFlightModeName, PX4CustomMode::ALTITUDE_CRUISE, true, true },
87 { orbitFlightModeName, PX4CustomMode::POSCTL_ORBIT, false, true },
88 { holdFlightModeName, PX4CustomMode::AUTO_LOITER, true, true },
89 { missionFlightModeName, PX4CustomMode::AUTO_MISSION, true, true },
90 { rtlFlightModeName, PX4CustomMode::AUTO_RTL, true, true },
91 { followMeFlightModeName, PX4CustomMode::AUTO_FOLLOW_TARGET, false, true },
92 { landingFlightModeName, PX4CustomMode::AUTO_LAND, false, true },
93 { preclandFlightModeName, PX4CustomMode::AUTO_PRECLAND, true, true },
94 { readyFlightModeName, PX4CustomMode::AUTO_READY, false, false},
95 { takeoffFlightModeName, PX4CustomMode::AUTO_TAKEOFF, false, false},
96 { vtolTakeoffFlightModeName, PX4CustomMode::AUTO_VTOL_TAKEOFF, false, true },
97 { terminationFlightModeName, PX4CustomMode::TERMINATION, false, true },
98 { guidedCourseFlightModeName, PX4CustomMode::AUTO_GUIDED_COURSE, false, true },
99 };
100
101 updateAvailableFlightModes(availableFlightModes);
102}
103
107
109{
110 return new PX4AutoPilotPlugin(vehicle, vehicle);
111}
112
113QStringList PX4FirmwarePlugin::flightModes(Vehicle* vehicle) const
114{
115 QStringList flightModesList;
116
117 for (auto &mode : _flightModeList) {
118 if (mode.canBeSet){
119 bool fw = (vehicle->fixedWing() && mode.fixedWing);
120 bool mc = (vehicle->multiRotor() && mode.multiRotor);
121
122 // show all modes for generic, vtol, etc
123 bool other = !vehicle->fixedWing() && !vehicle->multiRotor();
124 if (fw || mc || other) {
125 flightModesList += mode.mode_name;
126 }
127 }
128 }
129
130 return flightModesList;
131}
132
133QString PX4FirmwarePlugin::flightMode(uint8_t base_mode, uint32_t custom_mode) const
134{
135 QString flightMode = "Unknown";
136
137 if (base_mode & MAV_MODE_FLAG_CUSTOM_MODE_ENABLED) {
138 return _modeEnumToString.value(custom_mode, tr("Unknown %1:%2").arg(base_mode).arg(custom_mode));
139 }
140
141 return flightMode;
142}
143
144bool PX4FirmwarePlugin::setFlightMode(const QString& flightMode, uint8_t* base_mode, uint32_t* custom_mode) const
145{
146 *base_mode = 0;
147 *custom_mode = 0;
148
149 bool found = false;
150
151 for (auto &mode: _flightModeList){
152 if(flightMode.compare(mode.mode_name, Qt::CaseInsensitive) == 0){
153 *base_mode = MAV_MODE_FLAG_CUSTOM_MODE_ENABLED;
154 *custom_mode = mode.custom_mode;
155 found = true;
156 break;
157 }
158 }
159
160 if (!found) {
161 qCWarning(PX4FirmwarePluginLog) << "Unknown flight Mode" << flightMode;
162 }
163
164 return found;
165}
166
167bool PX4FirmwarePlugin::isCapable(const Vehicle *vehicle, FirmwareCapabilities capabilities) const
168{
170 //-- This is arbitrary until I find how to really tell if ROI is avaiable
171 if (vehicle->multiRotor()) {
173 }
174 if (vehicle->multiRotor() || vehicle->vtol()) {
176 }
177 if (vehicle->fixedWing()) {
179 }
180 return (capabilities & available) == capabilities;
181}
182
187
189{
190 // PX4 stack does not want home position sent in the first position.
191 // Subsequent sequence numbers must be adjusted.
192 return false;
193}
194
196{
197 QList<MAV_CMD> supportedCommands = {
198 MAV_CMD_NAV_WAYPOINT,
199 MAV_CMD_NAV_LOITER_UNLIM, MAV_CMD_NAV_LOITER_TIME,
200 MAV_CMD_NAV_RETURN_TO_LAUNCH,
201 MAV_CMD_DO_JUMP,
202 MAV_CMD_DO_DIGICAM_CONTROL,
203 MAV_CMD_DO_SET_CAM_TRIGG_DIST,
204 MAV_CMD_DO_SET_SERVO,
205 MAV_CMD_DO_SET_ACTUATOR,
206 MAV_CMD_DO_CHANGE_SPEED,
207 MAV_CMD_DO_SET_HOME,
208 MAV_CMD_DO_LAND_START,
209 MAV_CMD_DO_SET_ROI_LOCATION, MAV_CMD_DO_SET_ROI_WPNEXT_OFFSET, MAV_CMD_DO_SET_ROI_NONE,
210 MAV_CMD_DO_MOUNT_CONFIGURE,
211 MAV_CMD_DO_MOUNT_CONTROL,
212 MAV_CMD_SET_CAMERA_MODE,
213 MAV_CMD_IMAGE_START_CAPTURE, MAV_CMD_IMAGE_STOP_CAPTURE, MAV_CMD_VIDEO_START_CAPTURE, MAV_CMD_VIDEO_STOP_CAPTURE,
214 MAV_CMD_NAV_DELAY,
215 MAV_CMD_CONDITION_YAW,
216 MAV_CMD_NAV_LOITER_TO_ALT,
217 MAV_CMD_DO_GRIPPER
218 };
219
220 QList<MAV_CMD> vtolCommands = {
221 MAV_CMD_DO_VTOL_TRANSITION, MAV_CMD_NAV_VTOL_TAKEOFF, MAV_CMD_NAV_VTOL_LAND,
222 };
223
224 QList<MAV_CMD> flightCommands = {
225 MAV_CMD_NAV_LAND, MAV_CMD_NAV_TAKEOFF,
226 };
227
228 if (vehicleClass == QGCMAVLink::VehicleClassGeneric) {
229 supportedCommands += vtolCommands;
230 supportedCommands += flightCommands;
231 }
232 if (vehicleClass == QGCMAVLink::VehicleClassVTOL) {
233 supportedCommands += vtolCommands;
234 supportedCommands += flightCommands;
235 } else if (vehicleClass == QGCMAVLink::VehicleClassFixedWing || vehicleClass == QGCMAVLink::VehicleClassMultiRotor) {
236 supportedCommands += flightCommands;
237 }
238
239 if (SettingsManager::instance()->planViewSettings()->useConditionGate()->rawValue().toBool()) {
240 supportedCommands.append(MAV_CMD_CONDITION_GATE);
241 }
242
243 return supportedCommands;
244}
245
247{
248 switch (vehicleClass) {
250 return QStringLiteral(":/json/PX4-MavCmdInfoCommon.json");
252 return QStringLiteral(":/json/PX4-MavCmdInfoFixedWing.json");
254 return QStringLiteral(":/json/PX4-MavCmdInfoMultiRotor.json");
256 return QStringLiteral(":/json/PX4-MavCmdInfoVTOL.json");
258 return QStringLiteral(":/json/PX4-MavCmdInfoSub.json");
260 return QStringLiteral(":/json/PX4-MavCmdInfoRover.json");
261 default:
262 qCWarning(PX4FirmwarePluginLog) << "PX4FirmwarePlugin::missionCommandOverrides called with bad VehicleClass_t:" << vehicleClass;
263 return QString();
264 }
265}
266
271
273{
274 vehicle->sendMavCommand(vehicle->defaultComponentId(),
275 MAV_CMD_DO_REPOSITION,
276 true, // show error if failed
277 -1.0f,
278 MAV_DO_REPOSITION_FLAGS_CHANGE_MODE,
279 0.0f,
280 NAN,
281 NAN,
282 NAN,
283 NAN);
284}
285
286void PX4FirmwarePlugin::guidedModeRTL(Vehicle* vehicle, bool smartRTL) const
287{
288 Q_UNUSED(smartRTL);
290}
291
296
297void PX4FirmwarePlugin::_mavCommandResult(int vehicleId, int component, int command, int result, int failureCode)
298{
299 Q_UNUSED(vehicleId); Q_UNUSED(component); Q_UNUSED(failureCode);
300
301 auto* vehicle = qobject_cast<Vehicle*>(sender());
302 if (!vehicle) {
303 qCWarning(PX4FirmwarePluginLog) << "Dynamic cast failed!";
304 return;
305 }
306
307 if (command == MAV_CMD_NAV_TAKEOFF && result == MAV_RESULT_ACCEPTED) {
308 // Now that we are in takeoff mode we can arm the vehicle which will cause it to takeoff.
309 // We specifically don't retry arming if it fails. This way we don't fight with the user if
310 // They are trying to disarm.
311 disconnect(vehicle, &Vehicle::mavCommandResult, this, &PX4FirmwarePlugin::_mavCommandResult);
312 if (!vehicle->armed()) {
313 vehicle->setArmedShowError(true);
314 }
315 }
316}
317
318void PX4FirmwarePlugin::guidedModeTakeoff(Vehicle* vehicle, double takeoffAltRel) const
319{
320 double vehicleAltitudeAMSL = vehicle->altitudeAMSL()->rawValue().toDouble();
321 if (qIsNaN(vehicleAltitudeAMSL)) {
322 QGC::showAppMessage(tr("Unable to takeoff, vehicle position not known."));
323 return;
324 }
325
326 double takeoffAltAMSL = takeoffAltRel + vehicleAltitudeAMSL;
327
328 connect(vehicle, &Vehicle::mavCommandResult, this, &PX4FirmwarePlugin::_mavCommandResult);
329 vehicle->sendMavCommand(
330 vehicle->defaultComponentId(),
331 MAV_CMD_NAV_TAKEOFF,
332 true, // show error is fails
333 NAN, // No pitch requested
334 NAN, // param 2 unused
335 0, // param 3 takeoff flags
336 NAN, NAN, NAN, // No yaw, lat, lon
337 static_cast<float>(takeoffAltAMSL)); // AMSL altitude
338}
339
341{
342 QString speedParam("MPC_XY_VEL_MAX");
343
345 return vehicle->parameterManager()->getParameter(ParameterManager::defaultComponentId, speedParam)->rawValue().toDouble();
346 }
347
349}
350
352{
353 QString airspeedMax("FW_AIRSPD_MAX");
354
356 return vehicle->parameterManager()->getParameter(ParameterManager::defaultComponentId, airspeedMax)->rawValue().toDouble();
357 }
358
360}
361
363{
364 QString airspeedMin("FW_AIRSPD_MIN");
365
367 return vehicle->parameterManager()->getParameter(ParameterManager::defaultComponentId, airspeedMin)->rawValue().toDouble();
368 }
369
371}
372
377
383
384bool PX4FirmwarePlugin::guidedModeGotoLocation(Vehicle* vehicle, const QGeoCoordinate& gotoCoord, double forwardFlightLoiterRadius) const
385{
386 // PX4 doesn't support setting the forward flight loiter radius of
387 // MAV_CMD_DO_REPOSITION
388 Q_UNUSED(forwardFlightLoiterRadius)
389
390 if (qIsNaN(vehicle->altitudeAMSL()->rawValue().toDouble())) {
391 QGC::showAppMessage(tr("Unable to go to location, vehicle position not known."));
392 return false;
393 }
394
395 if (vehicle->capabilityBits() & MAV_PROTOCOL_CAPABILITY_COMMAND_INT) {
396 vehicle->sendMavCommandInt(vehicle->defaultComponentId(),
397 MAV_CMD_DO_REPOSITION,
398 MAV_FRAME_GLOBAL,
399 true, // show error is fails
400 -1.0f,
401 MAV_DO_REPOSITION_FLAGS_CHANGE_MODE,
402 0.0f,
403 NAN,
404 gotoCoord.latitude(),
405 gotoCoord.longitude(),
406 vehicle->altitudeAMSL()->rawValue().toFloat());
407 } else {
408 vehicle->sendMavCommand(vehicle->defaultComponentId(),
409 MAV_CMD_DO_REPOSITION,
410 true, // show error is fails
411 -1.0f,
412 MAV_DO_REPOSITION_FLAGS_CHANGE_MODE,
413 0.0f,
414 NAN,
415 static_cast<float>(gotoCoord.latitude()),
416 static_cast<float>(gotoCoord.longitude()),
417 vehicle->altitudeAMSL()->rawValue().toFloat());
418 }
419
420 return true;
421}
422
428
429static void _pauseVehicleThenChangeAltResultHandler(void* resultHandlerData, int /*compId*/, const mavlink_command_ack_t& ack, Vehicle::MavCmdResultFailureCode_t failureCode)
430{
431 if (ack.result != MAV_RESULT_ACCEPTED) {
432 switch (failureCode) {
434 qCDebug(PX4FirmwarePluginLog) << QStringLiteral("MAV_CMD_DO_REPOSITION error(%1)").arg(ack.result);
435 break;
437 qCDebug(PX4FirmwarePluginLog) << "MAV_CMD_DO_REPOSITION no response from vehicle";
438 break;
440 qCDebug(PX4FirmwarePluginLog) << "Internal Error: MAV_CMD_DO_REPOSITION could not be sent due to duplicate command";
441 break;
442 }
443 }
444
445 PauseVehicleThenChangeAltData_t* pData = static_cast<PauseVehicleThenChangeAltData_t*>(resultHandlerData);
446 pData->plugin->_changeAltAfterPause(resultHandlerData, ack.result == MAV_RESULT_ACCEPTED /* pauseSucceeded */);
447}
448
449void PX4FirmwarePlugin::_changeAltAfterPause(void* resultHandlerData, bool pauseSucceeded)
450{
451 PauseVehicleThenChangeAltData_t* pData = static_cast<PauseVehicleThenChangeAltData_t*>(resultHandlerData);
452
453 if (pauseSucceeded) {
454 pData->vehicle->sendMavCommand(
455 pData->vehicle->defaultComponentId(),
456 MAV_CMD_DO_REPOSITION,
457 true, // show error is fails
458 -1.0f, // Don't change groundspeed
459 MAV_DO_REPOSITION_FLAGS_CHANGE_MODE,
460 0.0f, // Reserved
461 qQNaN(), qQNaN(), qQNaN(), // No change to yaw, lat, lon
462 static_cast<float>(pData->newAMSLAlt));
463 } else {
464 QGC::showAppMessage(tr("Unable to pause vehicle."));
465 }
466
467 delete pData;
468}
469
470void PX4FirmwarePlugin::guidedModeChangeAltitude(Vehicle* vehicle, double altitudeChange, bool pauseVehicle)
471{
472 if (!vehicle->homePosition().isValid()) {
473 QGC::showAppMessage(tr("Unable to change altitude, home position unknown."));
474 return;
475 }
476 if (qIsNaN(vehicle->homePosition().altitude())) {
477 QGC::showAppMessage(tr("Unable to change altitude, home position altitude unknown."));
478 return;
479 }
480
481 double currentAltRel = vehicle->altitudeRelative()->rawValue().toDouble();
482 double newAltRel = currentAltRel + altitudeChange;
483
485 resultData->plugin = this;
486 resultData->vehicle = vehicle;
487 resultData->newAMSLAlt = vehicle->homePosition().altitude() + newAltRel;
488
489 if (pauseVehicle) {
490 Vehicle::MavCmdAckHandlerInfo_t handlerInfo = {};
492 handlerInfo.resultHandlerData = resultData;
493
495 &handlerInfo,
496 vehicle->defaultComponentId(),
497 MAV_CMD_DO_REPOSITION,
498 -1.0f, // Don't change groundspeed
499 MAV_DO_REPOSITION_FLAGS_CHANGE_MODE,
500 0.0f, // Reserved
501 qQNaN(), qQNaN(), qQNaN(), qQNaN()); // No change to yaw, lat, lon, alt
502 } else {
503 _changeAltAfterPause(resultData, true /* pauseSucceeded */);
504 }
505}
506
508{
509
510 vehicle->sendMavCommand(
511 vehicle->defaultComponentId(),
512 MAV_CMD_DO_CHANGE_SPEED,
513 true, // show error is fails
514 1, // 0: airspeed, 1: groundspeed
515 static_cast<float>(groundspeed), // groundspeed setpoint
516 -1, // throttle
517 0, // 0: absolute speed, 1: relative to current
518 NAN, NAN,NAN); // param 5-7 unused
519}
520
522{
523
524 vehicle->sendMavCommand(
525 vehicle->defaultComponentId(),
526 MAV_CMD_DO_CHANGE_SPEED,
527 true, // show error is fails
528 0, // 0: airspeed, 1: groundspeed
529 static_cast<float>(airspeed_equiv), // groundspeed setpoint
530 -1, // throttle
531 0, // 0: absolute speed, 1: relative to current
532 NAN, NAN,NAN); // param 5-7 unused
533}
534
535void PX4FirmwarePlugin::guidedModeChangeHeading(Vehicle* vehicle, const QGeoCoordinate &headingCoord) const
536{
538 QGC::showAppMessage(tr("Vehicle does not support guided rotate"));
539 return;
540 }
541
542 const float radians = qDegreesToRadians(vehicle->coordinate().azimuthTo(headingCoord));
543
544 vehicle->sendMavCommand(
545 vehicle->defaultComponentId(),
546 MAV_CMD_DO_REPOSITION,
547 true,
548 -1.0f, // no change in ground speed
549 MAV_DO_REPOSITION_FLAGS_CHANGE_MODE, // switch to guided mode
550 0.0f, // reserved
551 radians, // change heading
552 NAN, NAN, NAN // no change lat, lon, alt
553 );
554}
555
557{
559 if (!_armVehicleAndValidate(vehicle)) {
560 QGC::showAppMessage(tr("Unable to start takeoff: Vehicle rejected arming."));
561 return;
562 }
563 } else {
564 QGC::showAppMessage(tr("Unable to start takeoff: Vehicle not changing to %1 flight mode.").arg(takeOffFlightMode()));
565 }
566}
567
569{
571 if (!_armVehicleAndValidate(vehicle)) {
572 QGC::showAppMessage(tr("Unable to start mission: Vehicle rejected arming."));
573 return;
574 }
575 } else {
576 QGC::showAppMessage(tr("Unable to start mission: Vehicle not changing to %1 flight mode.").arg(missionFlightMode()));
577 }
578}
579
580void PX4FirmwarePlugin::setGuidedMode(Vehicle* vehicle, bool guidedMode) const
581{
582 if (guidedMode) {
584 } else {
585 pauseVehicle(vehicle);
586 }
587}
588
593
598
603
608
613
618
623
628
633
634bool PX4FirmwarePlugin::isGuidedMode(const Vehicle* vehicle) const
635{
636 // Not supported by generic vehicle
637 return (vehicle->flightMode() == pauseFlightMode() || vehicle->flightMode() == takeOffFlightMode() || vehicle->flightMode() == landFlightMode());
638}
639
641{
642 //-- Don't process messages to/from UDP Bridge. It doesn't suffer from these issues
643 if (message->compid == MAV_COMP_ID_UDP_BRIDGE) {
644 return true;
645 }
646
647 switch (message->msgid) {
648 case MAVLINK_MSG_ID_AUTOPILOT_VERSION:
649 _handleAutopilotVersion(vehicle, message);
650 break;
651 }
652
653 return true;
654}
655
656void PX4FirmwarePlugin::_handleAutopilotVersion(Vehicle* vehicle, mavlink_message_t* message)
657{
658 Q_UNUSED(vehicle);
659
660 auto* instanceData = qobject_cast<PX4FirmwarePluginInstanceData*>(vehicle->firmwarePluginInstanceData());
661 if (!instanceData->versionNotified) {
662 bool notifyUser = false;
663 int supportedMajorVersion = 1;
664 int supportedMinorVersion = 4;
665 int supportedPatchVersion = 1;
666
667 mavlink_autopilot_version_t version;
668 mavlink_msg_autopilot_version_decode(message, &version);
669
670 if (version.flight_sw_version != 0) {
671 int majorVersion, minorVersion, patchVersion;
672
673 majorVersion = (version.flight_sw_version >> (8*3)) & 0xFF;
674 minorVersion = (version.flight_sw_version >> (8*2)) & 0xFF;
675 patchVersion = (version.flight_sw_version >> (8*1)) & 0xFF;
676
677 if (majorVersion < supportedMajorVersion) {
678 notifyUser = true;
679 } else if (majorVersion == supportedMajorVersion) {
680 if (minorVersion < supportedMinorVersion) {
681 notifyUser = true;
682 } else if (minorVersion == supportedMinorVersion) {
683 notifyUser = patchVersion < supportedPatchVersion;
684 }
685 }
686 } else {
687 notifyUser = true;
688 }
689
690 if (notifyUser) {
691 instanceData->versionNotified = true;
692 QGC::showAppMessage(tr("QGroundControl supports PX4 Pro firmware Version %1.%2.%3 and above. You are using a version prior to that which will lead to unpredictable results. Please upgrade your firmware.").arg(supportedMajorVersion).arg(supportedMinorVersion).arg(supportedPatchVersion));
693 }
694 }
695}
696
697uint32_t PX4FirmwarePlugin::highLatencyCustomModeTo32Bits(uint16_t hlCustomMode) const
698{
699 union px4_custom_mode px4_cm;
700 px4_cm.data = 0;
701 px4_cm.custom_mode_hl = hlCustomMode;
702
703 return px4_cm.data;
704}
705
706QString PX4FirmwarePlugin::_getLatestVersionFileUrl(Vehicle* vehicle) const
707{
708 Q_UNUSED(vehicle);
709 return QStringLiteral("https://api.github.com/repos/PX4/Firmware/releases");
710}
711
712QString PX4FirmwarePlugin::_versionRegex() const
713{
714 return QStringLiteral("v([0-9,\\.]*) Stable");
715}
716
718{
719 return ((vehicle->vehicleType() == MAV_TYPE_GROUND_ROVER) || (vehicle->vehicleType() == MAV_TYPE_SUBMARINE));
720}
721
723{
724 static const char* HOOBS_HI = "LND_FLIGHT_T_HI";
725 static const char* HOOBS_LO = "LND_FLIGHT_T_LO";
726 uint64_t hobbsTimeSeconds = 0;
727
732 hobbsTimeSeconds = ((uint64_t)factHi->rawValue().toUInt() << 32 | (uint64_t)factLo->rawValue().toUInt()) / 1000000;
733 qCDebug(PX4FirmwarePluginLog) << "Hobbs Meter raw PX4:" << "(" << factHi->rawValue().toUInt() << factLo->rawValue().toUInt() << ")";
734 }
735
736 int hours = hobbsTimeSeconds / 3600;
737 int minutes = (hobbsTimeSeconds % 3600) / 60;
738 int seconds = hobbsTimeSeconds % 60;
739 QString timeStr = QString::asprintf("%04d:%02d:%02d", hours, minutes, seconds);
740 qCDebug(PX4FirmwarePluginLog) << "Hobbs Meter string:" << timeStr;
741 return timeStr;
742}
743
744bool PX4FirmwarePlugin::hasGripper(const Vehicle* vehicle) const
745{
746 if(vehicle->parameterManager()->parameterExists(ParameterManager::defaultComponentId, QStringLiteral("PD_GRIPPER_EN"))) {
747 bool _hasGripper = (vehicle->parameterManager()->getParameter(ParameterManager::defaultComponentId, QStringLiteral("PD_GRIPPER_EN"))->rawValue().toInt()) != 0 ? true : false;
748 return _hasGripper;
749 }
750 return false;
751}
752
754{
755 for(auto &mode: modeList){
756 PX4CustomMode::Mode cMode = static_cast<PX4CustomMode::Mode>(mode.custom_mode);
757
758 // Update Multi Rotor
759 switch (cMode) {
778 mode.multiRotor = true;
779 break;
784 mode.multiRotor = false;
785 break;
786 }
787
788 // Update Fixed Wing
789 switch (cMode){
795 mode.fixedWing = false;
796 break;
814 mode.fixedWing = true;
815 break;
816 }
817 }
818 _updateFlightModeList(modeList);
819}
820
821QVariant PX4FirmwarePlugin::expandedToolbarIndicatorSource(const Vehicle* /*vehicle*/, const QString& indicatorName) const
822{
823 if (indicatorName == "Battery") {
824 return QVariant::fromValue(QUrl::fromUserInput("qrc:/qml/QGroundControl/FirmwarePlugin/PX4/PX4BatteryIndicator.qml"));
825 } else if (indicatorName == "FlightMode") {
826 return QVariant::fromValue(QUrl::fromUserInput("qrc:/qml/QGroundControl/FirmwarePlugin/PX4/PX4FlightModeIndicator.qml"));
827 } else if (indicatorName == "MainStatus") {
828 return QVariant::fromValue(QUrl::fromUserInput("qrc:/qml/QGroundControl/FirmwarePlugin/PX4/PX4MainStatusIndicator.qml"));
829 }
830
831 return QVariant();
832}
QList< FirmwareFlightMode > FlightModeList
static void _pauseVehicleThenChangeAltResultHandler(void *resultHandlerData, int, const mavlink_command_ack_t &ack, Vehicle::MavCmdResultFailureCode_t failureCode)
struct __mavlink_message mavlink_message_t
#define QGC_LOGGING_CATEGORY(name, categoryStr)
struct __mavlink_command_ack_t mavlink_command_ack_t
The AutoPilotPlugin class is an abstract base class which represents the methods and objects which ar...
A Fact is used to hold a single value within the system.
Definition Fact.h:17
QVariant rawValue() const
Definition Fact.h:90
void _setModeEnumToModeStringMapping(FlightModeCustomModeMap enumToString)
FlightModeList _flightModeList
virtual double minimumEquivalentAirspeed(Vehicle *) const
FirmwareCapabilities
Set of optional capabilites which firmware may support.
@ ChangeHeadingCapability
Vehicle supports changing heading at current location.
@ GuidedTakeoffCapability
Vehicle supports guided takeoff.
@ TakeoffVehicleCapability
Vehicle supports taking off.
@ GuidedModeCapability
Vehicle supports guided mode commands.
@ OrbitModeCapability
Vehicle supports orbit mode.
@ SetFlightModeCapability
FirmwarePlugin::setFlightMode method is supported.
@ ROIModeCapability
Vehicle supports ROI (both in Fly guided mode and from Plan creation)
@ PauseVehicleCapability
Vehicle supports pausing at current location.
virtual double maximumEquivalentAirspeed(Vehicle *) const
bool _setFlightModeAndValidate(Vehicle *vehicle, const QString &flightMode) const
void _updateFlightModeList(FlightModeList &flightModeList)
bool _armVehicleAndValidate(Vehicle *vehicle) const
FlightModeCustomModeMap _modeEnumToString
virtual double maximumHorizontalSpeedMultirotorMetersSecond(Vehicle *) const
void initializeVehicle(Vehicle *vehicle) override
Called when Vehicle is first created to perform any firmware specific setup.
bool isCapable(const Vehicle *vehicle, FirmwareCapabilities capabilities) const override
bool adjustIncomingMavlinkMessage(Vehicle *vehicle, mavlink_message_t *message) override
void setGuidedMode(Vehicle *vehicle, bool guidedMode) const override
Set guided flight mode.
QString gotoFlightMode(void) const override
Returns the flight mode which the vehicle will be in if it is performing a goto location.
QList< MAV_CMD > supportedMissionCommands(QGCMAVLink::VehicleClass_t vehicleClass) const override
List of supported mission commands. Empty list for all commands supported.
bool guidedModeGotoLocation(Vehicle *vehicle, const QGeoCoordinate &gotoCoord, double forwardFlightLoiterRadius) const override
QString flightMode(uint8_t base_mode, uint32_t custom_mode) const override
QString takeOffFlightMode(void) const override
Returns the flight mode for TakeOff.
QString pauseFlightMode(void) const override
Returns The flight mode which indicates the vehicle is paused.
bool sendHomePositionToVehicle(void) const override
bool setFlightMode(const QString &flightMode, uint8_t *base_mode, uint32_t *custom_mode) const override
void startMission(Vehicle *vehicle) const override
Command the vehicle to start the mission.
void updateAvailableFlightModes(FlightModeList &modeList) override
Update Available flight modes received from vehicle.
ParameterMetaData * _createParameterMetaData() final
QString takeControlFlightMode(void) const override
Returns the flight mode to use when the operator wants to take back control from autonomouse flight.
bool fixedWingAirSpeedLimitsAvailable(Vehicle *vehicle) const override
QString missionFlightMode(void) const override
Returns the flight mode for running missions.
void pauseVehicle(Vehicle *vehicle) const override
QString landFlightMode(void) const override
Returns the flight mode for Land.
QString rtlFlightMode(void) const override
Returns the flight mode for RTL.
void guidedModeRTL(Vehicle *vehicle, bool smartRTL) const override
Command vehicle to return to launch.
void guidedModeChangeHeading(Vehicle *vehicle, const QGeoCoordinate &headingCoord) const override
Command vehicle to rotate towards specified location.
uint32_t highLatencyCustomModeTo32Bits(uint16_t hlCustomMode) const override
Convert from HIGH_LATENCY2.custom_mode value to correct 32 bit value.
void startTakeoff(Vehicle *vehicle) const override
Command the vehicle to start a takeoff.
double maximumHorizontalSpeedMultirotorMetersSecond(Vehicle *vehicle) const override
QStringList flightModes(Vehicle *vehicle) const override
QString getHobbsMeter(Vehicle *vehicle) const override
gets hobbs meter from autopilot. This should be reimplmeented for each firmware
bool isGuidedMode(const Vehicle *vehicle) const override
Returns whether the vehicle is in guided mode or not.
void guidedModeTakeoff(Vehicle *vehicle, double takeoffAltRel) const override
Command vehicle to takeoff from current location to the specified height.
QVariant expandedToolbarIndicatorSource(const Vehicle *vehicle, const QString &indicatorName) const override
double minimumEquivalentAirspeed(Vehicle *vehicle) const override
QString followFlightMode(void) const override
Returns the flight mode which the vehicle will be for follow me.
void guidedModeChangeEquivalentAirspeedMetersSecond(Vehicle *vehicle, double airspeed_equiv) const override
bool supportsNegativeThrust(Vehicle *vehicle) const override
bool mulirotorSpeedLimitsAvailable(Vehicle *vehicle) const override
QString missionCommandOverrides(QGCMAVLink::VehicleClass_t vehicleClass) const override
double maximumEquivalentAirspeed(Vehicle *vehicle) const override
void guidedModeChangeAltitude(Vehicle *vehicle, double altitudeRel, bool pauseVehicle) override
QString stabilizedFlightMode(void) const override
Returns the flight mode for Stabilized.
void _changeAltAfterPause(void *resultHandlerData, bool pauseSucceeded)
AutoPilotPlugin * autopilotPlugin(Vehicle *vehicle) const override
bool hasGripper(const Vehicle *vehicle) const override
void guidedModeChangeGroundSpeedMetersSecond(Vehicle *vehicle, double groundspeed) const override
void guidedModeLand(Vehicle *vehicle) const override
Command vehicle to land at current location.
bool parameterExists(int componentId, const QString &paramName) const
Fact * getParameter(int componentId, const QString &paramName)
static constexpr int defaultComponentId
static SettingsManager * instance()
void sendMavCommand(int compId, MAV_CMD command, bool showError, float param1=0.0f, float param2=0.0f, float param3=0.0f, float param4=0.0f, float param5=0.0f, float param6=0.0f, float param7=0.0f)
Definition Vehicle.cc:2140
QString flightMode() const
Definition Vehicle.cc:1462
bool vtol() const
Definition Vehicle.cc:1757
QGeoCoordinate homePosition()
Definition Vehicle.cc:1428
bool multiRotor() const
Definition Vehicle.cc:1752
void setFirmwarePluginInstanceData(FirmwarePluginInstanceData *firmwarePluginInstanceData)
Definition Vehicle.cc:2524
uint64_t capabilityBits() const
Definition Vehicle.h:709
MAV_TYPE vehicleType() const
Definition Vehicle.h:432
void sendMavCommandInt(int compId, MAV_CMD command, MAV_FRAME frame, bool showError, float param1, float param2, float param3, float param4, double param5, double param6, float param7)
Definition Vehicle.cc:2169
int defaultComponentId() const
Definition Vehicle.h:682
ParameterManager * parameterManager()
Definition Vehicle.h:577
bool fixedWing() const
Definition Vehicle.cc:1732
QGeoCoordinate coordinate()
Definition Vehicle.h:413
void mavCommandResult(int vehicleId, int targetComponent, int command, int ackResult, int failureCode)
class FirmwarePluginInstanceData * firmwarePluginInstanceData()
Definition Vehicle.h:697
void sendMavCommandWithHandler(const MavCmdAckHandlerInfo_t *ackHandlerInfo, int compId, MAV_CMD command, float param1=0.0f, float param2=0.0f, float param3=0.0f, float param4=0.0f, float param5=0.0f, float param6=0.0f, float param7=0.0f)
Sends the command and calls the callback with the result.
Definition Vehicle.cc:2164
void showAppMessage(const QString &message, const QString &title)
Modal application message. Queued if the UI isn't ready yet.
Definition AppMessages.cc:9
static constexpr VehicleClass_t VehicleClassGeneric
Callback info bundle for sendMavCommandWithHandler.
MavCmdResultHandler resultHandler
nullptr for no handler
@ MavCmdResultFailureDuplicateCommand
Unable to send command since duplicate is already being waited on for response.
@ MavCmdResultCommandResultOnly
commandResult specifies full success/fail info
@ MavCmdResultFailureNoResponseToCommand
No response from vehicle to command.
uint16_t custom_mode_hl