3#include <QtCore/QRegularExpression>
4#include <QtCore/QRegularExpressionMatch>
5#include <QtNetwork/QTcpSocket>
37 _setModeEnumToModeStringMapping({
52 updateAvailableFlightModes(modeList);
74 }
else if (vehicle->
vtol()) {
77 }
else if (vehicle->
sub()) {
81 return (capabilities & available) == capabilities;
87 QStringList flightModesList;
90 flightModesList += mode.mode_name;
93 return flightModesList;
100 if (base_mode & MAV_MODE_FLAG_CUSTOM_MODE_ENABLED) {
114 if (
flightMode.compare(mode.mode_name, Qt::CaseInsensitive) == 0){
115 *base_mode = MAV_MODE_FLAG_CUSTOM_MODE_ENABLED;
116 *custom_mode = mode.custom_mode;
123 qCWarning(APMFirmwarePluginLog) <<
"Unknown flight Mode" <<
flightMode;
131 if (!
qgcApp() ||
qgcApp()->thread() != QThread::currentThread()) {
132 qCCritical(APMFirmwarePluginLog) <<
"Parameter re-encoding requires the application thread";
137 mavlink_param_value_t paramValue;
140 (void) memset(¶mValue, 0,
sizeof(paramValue));
145 mavlink_msg_param_value_decode(message, ¶mValue);
147 switch (paramValue.param_type) {
148 case MAV_PARAM_TYPE_UINT8:
149 paramUnion.param_uint8 =
static_cast<uint8_t
>(paramValue.param_value);
151 case MAV_PARAM_TYPE_INT8:
152 paramUnion.param_int8 =
static_cast<int8_t
>(paramValue.param_value);
154 case MAV_PARAM_TYPE_UINT16:
155 paramUnion.param_uint16 =
static_cast<uint16_t
>(paramValue.param_value);
157 case MAV_PARAM_TYPE_INT16:
158 paramUnion.param_int16 =
static_cast<int16_t
>(paramValue.param_value);
160 case MAV_PARAM_TYPE_UINT32:
161 paramUnion.param_uint32 =
static_cast<uint32_t
>(paramValue.param_value);
163 case MAV_PARAM_TYPE_INT32:
164 paramUnion.param_int32 =
static_cast<int32_t
>(paramValue.param_value);
166 case MAV_PARAM_TYPE_REAL32:
167 paramUnion.param_float = paramValue.param_value;
170 qCCritical(APMFirmwarePluginLog) <<
"Invalid/Unsupported data type used in parameter:" << paramValue.param_type;
173 paramValue.param_value = paramUnion.param_float;
176 const uint8_t channel = _reencodeMavlinkChannel();
177 QMutexLocker reencode_lock{&_reencodeMavlinkChannelMutex()};
180 mavlinkStatusReEncode->flags |= MAVLINK_STATUS_FLAG_IN_MAVLINK1;
182 (void) mavlink_msg_param_value_encode_chan(
193 mavlink_param_set_t paramSet;
196 (void) memset(¶mSet, 0,
sizeof(paramSet));
201 mavlink_msg_param_set_decode(message, ¶mSet);
203 if (!_ardupilotComponentMap[paramSet.target_system][paramSet.target_component]) {
208 paramUnion.param_float = paramSet.param_value;
210 switch (paramSet.param_type) {
211 case MAV_PARAM_TYPE_UINT8:
212 paramSet.param_value = paramUnion.param_uint8;
214 case MAV_PARAM_TYPE_INT8:
215 paramSet.param_value = paramUnion.param_int8;
217 case MAV_PARAM_TYPE_UINT16:
218 paramSet.param_value = paramUnion.param_uint16;
220 case MAV_PARAM_TYPE_INT16:
221 paramSet.param_value = paramUnion.param_int16;
223 case MAV_PARAM_TYPE_UINT32:
224 paramSet.param_value = paramUnion.param_uint32;
226 case MAV_PARAM_TYPE_INT32:
227 paramSet.param_value = paramUnion.param_int32;
229 case MAV_PARAM_TYPE_REAL32:
233 qCCritical(APMFirmwarePluginLog) <<
"Invalid/Unsupported data type used in parameter:" << paramSet.param_type;
236 _adjustOutgoingMavlinkMutex.lock();
237 mavlink_msg_param_set_encode_chan(
244 _adjustOutgoingMavlinkMutex.unlock();
253 if (messageText.contains(
"Place vehicle") || messageText.contains(
"Calibration successful")) {
254 _adjustCalibrationMessageSeverity(message);
258 static const QRegularExpression APM_FRAME_REXP(
"^Frame: (\\S*)");
259 const QRegularExpressionMatch match = APM_FRAME_REXP.match(messageText);
260 if (match.hasMatch()) {
261 static const QSet<QString> coaxialFrames = {
"Y6",
"OCTA_QUAD",
"COAX",
"QUAD/PLUS"};
262 const QString frameType = match.captured(1);
271 mavlink_heartbeat_t heartbeat{};
272 mavlink_msg_heartbeat_decode(message, &heartbeat);
274 if (message->compid == MAV_COMP_ID_AUTOPILOT1) {
275 bool underway =
false;
278 if (vehicle->
armed() && ((heartbeat.system_status == MAV_STATE_ACTIVE) || (heartbeat.system_status == MAV_STATE_CRITICAL) || (heartbeat.system_status == MAV_STATE_EMERGENCY))) {
286 _ardupilotComponentMap[message->sysid][message->compid] = heartbeat.autopilot == MAV_AUTOPILOT_ARDUPILOTMEGA;
289 _ardupilotComponentMap[message->sysid][MAV_COMP_ID_UDP_BRIDGE] =
false;
297 if (message->msgid == MAVLINK_MSG_ID_HEARTBEAT) {
299 _handleIncomingHeartbeat(vehicle, message);
300 }
else if (message->msgid == MAVLINK_MSG_ID_BATTERY_STATUS && instanceData) {
301 instanceData->lastBatteryStatusTime = QTime::currentTime();
302 }
else if (message->msgid == MAVLINK_MSG_ID_HOME_POSITION && instanceData) {
303 instanceData->lastHomePositionTime = QTime::currentTime();
306 if (_ardupilotComponentMap[vehicle->
id()][message->compid]) {
307 switch (message->msgid) {
308 case MAVLINK_MSG_ID_PARAM_VALUE:
309 _handleIncomingParamValue(vehicle, message);
311 case MAVLINK_MSG_ID_STATUSTEXT:
312 return _handleIncomingStatusText(vehicle, message);
313 case MAVLINK_MSG_ID_RC_CHANNELS:
314 _handleRCChannels(vehicle, message);
316 case MAVLINK_MSG_ID_RC_CHANNELS_RAW:
317 _handleRCChannelsRaw(vehicle, message);
324 const int reinitStreamsTimeoutSecs = 10;
325 if (instanceData && ((instanceData->lastBatteryStatusTime.secsTo(QTime::currentTime()) > reinitStreamsTimeoutSecs) || (instanceData->lastHomePositionTime.secsTo(QTime::currentTime()) > reinitStreamsTimeoutSecs))) {
334 switch (message->msgid) {
335 case MAVLINK_MSG_ID_PARAM_SET:
336 _handleOutgoingParamSetThreadSafe(vehicle, outgoingLink, message);
345 if (!
qgcApp() ||
qgcApp()->thread() != QThread::currentThread()) {
346 qCCritical(APMFirmwarePluginLog) <<
"Status text re-encoding requires the application thread";
350 const uint8_t channel = _reencodeMavlinkChannel();
351 QMutexLocker reencode_lock{&_reencodeMavlinkChannelMutex()};
353 mavlinkStatusReEncode->flags |= MAVLINK_STATUS_FLAG_IN_MAVLINK1;
355 mavlink_statustext_t statusText{};
356 mavlink_msg_statustext_decode(message, &statusText);
358 statusText.severity = MAV_SEVERITY_INFO;
360 (void) mavlink_msg_statustext_encode_chan(
369void APMFirmwarePlugin::_adjustCalibrationMessageSeverity(
mavlink_message_t *message)
const
371 if (!
qgcApp() ||
qgcApp()->thread() != QThread::currentThread()) {
372 qCCritical(APMFirmwarePluginLog) <<
"Status text re-encoding requires the application thread";
375 mavlink_statustext_t statusText{};
376 mavlink_msg_statustext_decode(message, &statusText);
379 const uint8_t channel = _reencodeMavlinkChannel();
380 QMutexLocker reencode_lock{&_reencodeMavlinkChannelMutex()};
383 mavlinkStatusReEncode->flags |= MAVLINK_STATUS_FLAG_IN_MAVLINK1;
384 statusText.severity = MAV_SEVERITY_INFO;
386 (void) mavlink_msg_statustext_encode_chan(
401 instanceData->lastBatteryStatusTime = instanceData->lastHomePositionTime = QTime::currentTime();
409 struct StreamInfo_s {
410 MAV_DATA_STREAM mavStream;
414 const StreamInfo_s rgStreamInfo[] = {
415 { MAV_DATA_STREAM_RAW_SENSORS, streamRates->streamRateRawSensors()->rawValue().toInt() },
416 { MAV_DATA_STREAM_EXTENDED_STATUS, streamRates->streamRateExtendedStatus()->rawValue().toInt() },
417 { MAV_DATA_STREAM_RC_CHANNELS, streamRates->streamRateRCChannels()->rawValue().toInt() },
418 { MAV_DATA_STREAM_POSITION, streamRates->streamRatePosition()->rawValue().toInt() },
419 { MAV_DATA_STREAM_EXTRA1, streamRates->streamRateExtra1()->rawValue().toInt() },
420 { MAV_DATA_STREAM_EXTRA2, streamRates->streamRateExtra2()->rawValue().toInt() },
421 { MAV_DATA_STREAM_EXTRA3, streamRates->streamRateExtra3()->rawValue().toInt() },
424 for (
size_t i = 0; i < std::size(rgStreamInfo); i++) {
425 const StreamInfo_s &streamInfo = rgStreamInfo[i];
427 if (streamInfo.streamRate >= 0) {
428 vehicle->
requestDataStream(streamInfo.mavStream,
static_cast<uint16_t
>(streamInfo.streamRate));
439 vehicle->
sendMavCommand(MAV_COMP_ID_AUTOPILOT1, MAV_CMD_SET_MESSAGE_INTERVAL,
false , MAVLINK_MSG_ID_HOME_POSITION, 1000000 );
443 vehicle->
sendMavCommand(MAV_COMP_ID_AUTOPILOT1, MAV_CMD_SET_MESSAGE_INTERVAL,
false , MAVLINK_MSG_ID_EXTENDED_SYS_STATE, 1000000 );
445 instanceData->lastBatteryStatusTime = instanceData->lastHomePositionTime = QTime::currentTime();
448APMFirmwarePlugin::FirmwareParameterHeader APMFirmwarePlugin::_parseParamsHeader(
const QString &filePath)
450 APMFirmwarePlugin::FirmwareParameterHeader data{};
452 QFile file(filePath);
453 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
457 QTextStream stream(&file);
458 while (!stream.atEnd()) {
459 const QString
line = stream.readLine();
462 if (!
line.startsWith(
'#')) {
466 using namespace Qt::StringLiterals;
468 static const QRegularExpression reStack(uR
"(^#\s*Stack:\s*(.+)\s*$)"_s);
469 auto match = reStack.match(line);
470 if (match.hasMatch()) {
471 const QString firmwareTypeStr = match.captured(1).trimmed();
473 data.firmwareType = firmwareType;
477 static const QRegularExpression reVehicle(uR
"(^#\s*Vehicle:\s*(.+)\s*$)"_s);
478 match = reVehicle.match(line);
479 if (match.hasMatch()) {
480 const QString vehicleTypeStr = match.captured(1).trimmed();
482 data.vehicleType = vehicleType;
486 static const QRegularExpression reVersion(uR
"(^#\s*Version:\s*([0-9]+(?:\.[0-9]+){0,2})(?:\s+([A-Za-z0-9]+))?\s*$)"_s);
487 match = reVersion.match(line);
488 if (match.hasMatch()) {
489 const QString versionNumber = match.captured(1).trimmed();
490 data.versionNumber = QVersionNumber::fromString(versionNumber);
492 const QString versionType = match.captured(2).trimmed();
493 if (versionType.isEmpty()) {
494 data.versionType = FIRMWARE_VERSION_TYPE_OFFICIAL;
501 static const QRegularExpression reGit(uR
"(^#\s*Git Revision:\s*([0-9a-fA-F]+)\s*$)"_s);
502 match = reGit.match(line);
503 if (match.hasMatch()) {
504 data.gitRevision = match.captured(1).trimmed();
516 const APMFirmwarePlugin::FirmwareParameterHeader offlineParameterHeader = _parseParamsHeader(offlineParameterFile);
517 if (offlineParameterHeader.vehicleType != MAV_TYPE_GENERIC) {
518 vehicle->
setFirmwareVersion(offlineParameterHeader.versionNumber.majorVersion(), offlineParameterHeader.versionNumber.minorVersion(), offlineParameterHeader.versionNumber.microVersion());
525 _soloVideoHandshake();
531 QList<MAV_CMD> supportedCommands = {
532 MAV_CMD_NAV_WAYPOINT,
533 MAV_CMD_NAV_LOITER_UNLIM, MAV_CMD_NAV_LOITER_TURNS, MAV_CMD_NAV_LOITER_TIME,
534 MAV_CMD_NAV_RETURN_TO_LAUNCH,
535 MAV_CMD_NAV_CONTINUE_AND_CHANGE_ALT,
536 MAV_CMD_NAV_LOITER_TO_ALT,
537 MAV_CMD_NAV_SPLINE_WAYPOINT,
538 MAV_CMD_NAV_GUIDED_ENABLE,
540 MAV_CMD_CONDITION_DELAY, MAV_CMD_CONDITION_DISTANCE, MAV_CMD_CONDITION_YAW,
543 MAV_CMD_DO_CHANGE_SPEED,
545 MAV_CMD_DO_SET_RELAY, MAV_CMD_DO_REPEAT_RELAY,
546 MAV_CMD_DO_SET_SERVO, MAV_CMD_DO_REPEAT_SERVO,
547 MAV_CMD_DO_LAND_START,
549 MAV_CMD_DO_DIGICAM_CONFIGURE, MAV_CMD_DO_DIGICAM_CONTROL,
550 MAV_CMD_DO_MOUNT_CONTROL,
551 MAV_CMD_DO_GIMBAL_MANAGER_PITCHYAW,
552 MAV_CMD_DO_SET_CAM_TRIGG_DIST,
553 MAV_CMD_IMAGE_START_CAPTURE, MAV_CMD_IMAGE_STOP_CAPTURE, MAV_CMD_VIDEO_START_CAPTURE, MAV_CMD_VIDEO_STOP_CAPTURE,
554 MAV_CMD_DO_FENCE_ENABLE,
555 MAV_CMD_DO_PARACHUTE,
556 MAV_CMD_DO_INVERTED_FLIGHT,
558 MAV_CMD_DO_GUIDED_LIMITS,
559 MAV_CMD_DO_AUTOTUNE_ENABLE,
562 QList<MAV_CMD> vtolCommands = {
563 MAV_CMD_NAV_VTOL_TAKEOFF, MAV_CMD_NAV_VTOL_LAND, MAV_CMD_DO_VTOL_TRANSITION,
566 QList<MAV_CMD> flightCommands = {
567 MAV_CMD_NAV_LAND, MAV_CMD_NAV_TAKEOFF,
571 supportedCommands += vtolCommands;
572 supportedCommands += flightCommands;
575 supportedCommands += vtolCommands;
576 supportedCommands += flightCommands;
578 supportedCommands += flightCommands;
582 supportedCommands.append(MAV_CMD_CONDITION_GATE);
585 return supportedCommands;
590 switch (vehicleClass) {
592 return QStringLiteral(
":/json/APM-MavCmdInfoCommon.json");
594 return QStringLiteral(
":/json/APM-MavCmdInfoFixedWing.json");
596 return QStringLiteral(
":/json/APM-MavCmdInfoMultiRotor.json");
598 return QStringLiteral(
":/json/APM-MavCmdInfoVTOL.json");
600 return QStringLiteral(
":/json/APM-MavCmdInfoSub.json");
602 return QStringLiteral(
":/json/APM-MavCmdInfoRover.json");
604 qCWarning(APMFirmwarePluginLog) <<
"APMFirmwarePlugin::missionCommandOverrides called with bad VehicleClass_t:" << vehicleClass;
616 uint64_t hobbsTimeSeconds = 0;
620 hobbsTimeSeconds =
static_cast<uint64_t
>(factFltTime->
rawValue().toUInt());
621 qCDebug(APMFirmwarePluginLog) <<
"Hobbs Meter raw Ardupilot(s):" <<
"(" << hobbsTimeSeconds <<
")";
624 const int hours = hobbsTimeSeconds / 3600;
625 const int minutes = (hobbsTimeSeconds % 3600) / 60;
626 const int seconds = hobbsTimeSeconds % 60;
627 const QString timeStr = QString::asprintf(
"%04d:%02d:%02d", hours, minutes, seconds);
628 qCDebug(APMFirmwarePluginLog) <<
"Hobbs Meter string:" << timeStr;
643 if (_toolIndicatorList.isEmpty()) {
648 _toolIndicatorList.append(QVariant::fromValue(QUrl::fromUserInput(
"qrc:/qml/QGroundControl/FirmwarePlugin/APM/APMSupportForwardingIndicator.qml")));
651 return _toolIndicatorList;
679void APMFirmwarePlugin::_soloVideoHandshake()
681 QTcpSocket *
const socket =
new QTcpSocket(
this);
683 (void) QObject::connect(socket, &QAbstractSocket::errorOccurred,
this, &APMFirmwarePlugin::_artooSocketError);
684 socket->connectToHost(_artooIP, _artooVideoHandshakePort);
687void APMFirmwarePlugin::_artooSocketError(QAbstractSocket::SocketError socketError)
694 switch (vehicleClass) {
696 return QStringLiteral(
"Copter");
699 return QStringLiteral(
"Plane");
701 return QStringLiteral(
"Rover");
703 return QStringLiteral(
"Sub");
705 qCWarning(APMFirmwarePluginLog) << Q_FUNC_INFO <<
"called with bad VehicleClass_t:" << vehicleClass;
714 const QString vehicleName = _vehicleClassToString(vehicleClass);
715 if (vehicleName.isEmpty()) {
716 qCWarning(APMFirmwarePluginLog) << Q_FUNC_INFO <<
"called with bad VehicleClass_t:" << vehicleClass;
724 while ((currMajor >= 4) && (currMinor > 0)) {
725 const QString file = QStringLiteral(
":/FirmwarePlugin/APM/APMParameterFactMetaData.%1.%2.%3.json").arg(vehicleName).arg(currMajor).arg(currMinor);
726 if (QFileInfo::exists(file)) {
730 if (currMinor == 0) {
737 for (
int i = 0; i < 10; i++) {
738 const QString file = QStringLiteral(
":/FirmwarePlugin/APM/APMParameterFactMetaData.%1.%2.%3.json").arg(vehicleName).arg(4).arg(i);
739 if (QFileInfo::exists(file)) {
744 qCWarning(APMFirmwarePluginLog) << Q_FUNC_INFO <<
"Meta Data File Not Found";
769 auto *vehicle = data->vehicle;
772 if (instanceData->MAV_CMD_DO_REPOSITION_supported ||
773 instanceData->MAV_CMD_DO_REPOSITION_unsupported) {
778 instanceData->MAV_CMD_DO_REPOSITION_supported = (ack.result == MAV_RESULT_ACCEPTED);
779 instanceData->MAV_CMD_DO_REPOSITION_unsupported = (ack.result == MAV_RESULT_UNSUPPORTED);
800 if (instanceData->MAV_CMD_DO_REPOSITION_supported || !instanceData->MAV_CMD_DO_REPOSITION_unsupported) {
815 float yawParam = NAN;
816 if (forwardFlightLoiterRadius > 0) {
818 }
else if (forwardFlightLoiterRadius < 0) {
825 MAV_CMD_DO_REPOSITION,
828 MAV_DO_REPOSITION_FLAGS_CHANGE_MODE,
829 static_cast<float>(abs(forwardFlightLoiterRadius)),
831 gotoCoord.latitude(),
832 gotoCoord.longitude(),
836 if (instanceData->MAV_CMD_DO_REPOSITION_supported) {
844 QGeoCoordinate coordWithAltitude = gotoCoord;
868 if (abs(altitudeChange) < 0.01) {
878 mavlink_set_position_target_local_ned_t cmd{};
880 (void) memset(&cmd, 0,
sizeof(cmd));
882 cmd.target_system =
static_cast<uint8_t
>(vehicle->
id());
884 cmd.coordinate_frame = MAV_FRAME_LOCAL_OFFSET_NED;
885 cmd.type_mask = 0xFFF8;
888 cmd.z =
static_cast<float>(-(altitudeChange));
890 mavlink_msg_set_position_target_local_ned_encode_chan(
893 sharedLink->mavlinkChannel(),
932 MAV_CMD_DO_CHANGE_SPEED,
935 static_cast<float>(groundspeed),
944 _guidedModeTakeoff(vehicle, altitudeRel);
954 const float degrees = vehicle->
coordinate().azimuthTo(headingCoord);
957 float diff = degrees - currentHeading;
960 }
else if (diff > 180) {
964 const int8_t direction = (diff > 0) ? 1 : -1;
967 float maxYawRate = 0.f;
968 static const QString maxYawRateParam = QStringLiteral(
"ATC_RATE_Y_MAX");
970 const Fact* maxYawRateFact =
972 if (maxYawRateFact) {
973 maxYawRate = maxYawRateFact->
rawValue().toFloat();
979 MAV_CMD_CONDITION_YAW,
990 double minTakeoffAlt = 0;
995 if (vehicle->
vtol()) {
1015 if (minTakeoffAlt == 0) {
1019 return minTakeoffAlt;
1022bool APMFirmwarePlugin::_guidedModeTakeoff(
Vehicle *vehicle,
double altitudeRel)
const
1030 if (qIsNaN(vehicleAltitudeAMSL)) {
1036 if (!qIsNaN(altitudeRel) && altitudeRel > takeoffAltRel) {
1037 takeoffAltRel = altitudeRel;
1052 MAV_CMD_NAV_TAKEOFF,
1054 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
1055 static_cast<float>(takeoffAltRel)
1070 QGC::showAppMessage(tr(
"Unable to start takeoff: Vehicle failed to change to Takeoff mode."));
1085 QGC::showAppMessage(tr(
"Unable to start mission: Vehicle failed to change to Auto mode."));
1096 QGC::showAppMessage(tr(
"Unable to start mission: Vehicle failed to change to Auto mode."));
1106 if (!vehicle->
armed()) {
1108 QGC::showAppMessage(tr(
"Unable to start mission: Vehicle failed to change to Guided mode."));
1122QString APMFirmwarePlugin::_getLatestVersionFileUrl(
Vehicle *vehicle)
const
1124 const static QString baseUrl(
"http://firmware.ardupilot.org/%1/stable/Pixhawk1/git-version.txt");
1126 if (qobject_cast<ArduPlaneFirmwarePlugin*>(vehicle->
firmwarePlugin())) {
1127 return baseUrl.arg(
"Plane");
1128 }
else if (qobject_cast<ArduRoverFirmwarePlugin*>(vehicle->
firmwarePlugin())) {
1129 return baseUrl.arg(
"Rover");
1130 }
else if (qobject_cast<ArduSubFirmwarePlugin*>(vehicle->
firmwarePlugin())) {
1131 return baseUrl.arg(
"Sub");
1132 }
else if (qobject_cast<ArduCopterFirmwarePlugin*>(vehicle->
firmwarePlugin())) {
1133 return baseUrl.arg(
"Copter");
1135 qCWarning(APMFirmwarePluginLog) <<
"APMFirmwarePlugin::_getLatestVersionFileUrl Unknown vehicle firmware type" << vehicle->
vehicleType();
1144 mavlink_rc_channels_t channels{};
1146 mavlink_msg_rc_channels_decode(message, &channels);
1149 if (channels.rssi && (channels.rssi != 255)) {
1150 channels.rssi =
static_cast<uint8_t
>((
static_cast<double>(channels.rssi) / 254.0) * 100.0);
1152 mavlink_msg_rc_channels_encode_chan(
1155 sharedLink->mavlinkChannel(),
1166 mavlink_rc_channels_raw_t channels{};
1168 mavlink_msg_rc_channels_raw_decode(message, &channels);
1170 if (channels.rssi) {
1171 channels.rssi =
static_cast<uint8_t
>((
static_cast<double>(channels.rssi) / 255.0) * 100.0);
1173 mavlink_msg_rc_channels_raw_encode_chan(
1176 sharedLink->mavlinkChannel(),
1186 static bool sentOnce =
false;
1195 static bool sentOnce =
false;
1198 qCWarning(APMFirmwarePluginLog) <<
"estimateCapabilities" << estimationCapabilities;
1199 QGC::showAppMessage(tr(
"Follow failed: Ground station cannot provide required position information."));
1209 const mavlink_global_position_int_t globalPositionInt = {
1210 static_cast<uint32_t
>(
qgcApp()->msecsSinceBoot()),
1213 static_cast<int32_t
>(vehicle->
homePosition().altitude() * 1000),
1214 static_cast<int32_t
>(0),
1222 (void) mavlink_msg_global_position_int_encode_chan(
1225 sharedLink->mavlinkChannel(),
1232uint8_t APMFirmwarePlugin::_reencodeMavlinkChannel()
1240 static QMutex _channelMutex{};
1241 _channelMutex.lock();
1246 _channelMutex.unlock();
1250QMutex &APMFirmwarePlugin::_reencodeMavlinkChannelMutex()
1252 static QMutex _mutex{};
1258 const QString airspeedMax(
"AIRSPEED_MAX");
1261 const Fact* airspeedFact =
1264 return airspeedFact->
rawValue().toDouble();
1273 const QString airspeedMin(
"AIRSPEED_MIN");
1276 const Fact* airspeedFact =
1279 return airspeedFact->
rawValue().toDouble();
1296 MAV_CMD_DO_CHANGE_SPEED,
1299 static_cast<float>(airspeed_equiv),
1305void APMFirmwarePlugin::_setBaroGndTemp(
Vehicle* vehicle, qreal temp)
1311 const QString bareGndTemp(
"BARO_GND_TEMP");
1319void APMFirmwarePlugin::_setBaroAltOffset(
Vehicle* vehicle, qreal offset)
1325 const QString baroAltOffset(
"BARO_ALT_OFFSET");
1333#define ALT_METERS (145366.45 * 0.3048)
1334#define ALT_EXP (1. / 5.225)
1335#define SEA_PRESSURE 101325.
1336#define CELSIUS_TO_KELVIN(celsius) (celsius + 273.15)
1337#define ALT_OFFSET_P(pressure) (1. - pow((pressure / SEA_PRESSURE), ALT_EXP))
1338#define ALT_OFFSET_PT(pressure,temperature) ((ALT_OFFSET_P(pressure) * CELSIUS_TO_KELVIN(temperature)) / 0.0065)
1342 const qreal alt1 = ALT_OFFSET_PT(atmospheric1, temperature1);
1343 const qreal alt2 = ALT_OFFSET_PT(atmospheric2, temperature2);
1344 const qreal offset = alt1 - alt2;
1350 const qreal alt1 = ALT_OFFSET_P(atmospheric1) * ALT_METERS;
1351 const qreal alt2 = ALT_OFFSET_P(atmospheric2) * ALT_METERS;
1352 const qreal offset = alt1 - alt2;
1359 const QMetaObject::Connection baroPressureUpdater = QObject::connect(
1361 [vehicle](qreal pressure, qreal temperature) {
1362 if (!vehicle || !vehicle->
airborne()) {
1366 if (qFuzzyIsNull(pressure)) {
1371 if (qFuzzyIsNull(initialPressure)) {
1378 if (!qFuzzyIsNull(temperature) && !qFuzzyIsNull(initialTemperature)) {
1384 APMFirmwarePlugin::_setBaroAltOffset(vehicle, offset);
1387 const QMetaObject::Connection baroTempUpdater =
1389 vehicle, [vehicle](qreal temperature) {
1390 if (!vehicle || !vehicle->
airborne()) {
1394 if (qFuzzyIsNull(temperature)) {
1398 APMFirmwarePlugin::_setBaroGndTemp(vehicle, temperature);
1401 return QPair<QMetaObject::Connection,QMetaObject::Connection>(baroPressureUpdater, baroTempUpdater);
1411 bool result =
false;
1413 if (updaters.first) {
1414 result |= QObject::disconnect(updaters.first);
1417 if (updaters.second) {
1418 result |= QObject::disconnect(updaters.second);
1426 if (indicatorName ==
"Battery") {
1427 return QVariant::fromValue(QUrl::fromUserInput(
"qrc:/qml/QGroundControl/FirmwarePlugin/APM/APMBatteryIndicator.qml"));
1428 }
else if (indicatorName ==
"FlightMode" && vehicle->
multiRotor()) {
1429 return QVariant::fromValue(QUrl::fromUserInput(
"qrc:/qml/QGroundControl/FirmwarePlugin/APM/APMFlightModeIndicator.qml"));
static void _MAV_CMD_DO_REPOSITION_ResultHandler(void *resultHandlerData, int, const mavlink_command_ack_t &ack, Vehicle::MavCmdResultFailureCode_t)
QList< FirmwareFlightMode > FlightModeList
std::shared_ptr< LinkInterface > SharedLinkInterfacePtr
mavlink_status_t * mavlink_get_channel_status(uint8_t chan)
struct __mavlink_message mavlink_message_t
#define QGC_LOGGING_CATEGORY(name, categoryStr)
struct __mavlink_command_ack_t mavlink_command_ack_t
struct param_union mavlink_param_union_t
This is the AutoPilotPlugin implementation for the MAV_AUTOPILOT_ARDUPILOT type.
This is the base class for all stack specific APM firmware plugins.
bool isGuidedMode(const Vehicle *vehicle) const override
Returns whether the vehicle is in guided mode or not.
QVariant expandedToolbarIndicatorSource(const Vehicle *vehicle, const QString &indicatorName) const override
void setGuidedMode(Vehicle *vehicle, bool guidedMode) const override
Set guided flight mode.
QString flightMode(uint8_t base_mode, uint32_t custom_mode) const override
QString rtlFlightMode() const override
Returns the flight mode for RTL.
bool setFlightMode(const QString &flightMode, uint8_t *base_mode, uint32_t *custom_mode) const override
static qreal calcAltOffsetPT(uint32_t atmospheric1, qreal temperature1, uint32_t atmospheric2, qreal temperature2)
QString getHobbsMeter(Vehicle *vehicle) const override
gets hobbs meter from autopilot. This should be reimplmeented for each firmware
void sendGCSMotionReport(Vehicle *vehicle, const FollowMe::GCSMotionReport &motionReport, uint8_t estimatationCapabilities) const override
Sends the appropriate mavlink message for follow me support.
bool fixedWingAirSpeedLimitsAvailable(Vehicle *vehicle) const override
bool guidedModeGotoLocation(Vehicle *vehicle, const QGeoCoordinate &gotoCoord, double forwardFlightLoiterRadius) const override
static QPair< QMetaObject::Connection, QMetaObject::Connection > startCompensatingBaro(Vehicle *vehicle)
void startMission(Vehicle *vehicle) const override
Command the vehicle to start the mission.
virtual void initializeStreamRates(Vehicle *vehicle)
const QString _guidedFlightMode
QString missionCommandOverrides(QGCMAVLink::VehicleClass_t vehicleClass) const override
void guidedModeChangeGroundSpeedMetersSecond(Vehicle *vehicle, double speed) const override
void guidedModeChangeHeading(Vehicle *vehicle, const QGeoCoordinate &headingCoord) const override
Command vehicle to rotate towards specified location.
virtual ~APMFirmwarePlugin()
bool hasGripper(const Vehicle *vehicle) const override
double minimumTakeoffAltitudeMeters(Vehicle *vehicle) const override
QStringList flightModes(Vehicle *vehicle) const override
void guidedModeRTL(Vehicle *vehicle, bool smartRTL) const override
Command vehicle to return to launch.
bool adjustIncomingMavlinkMessage(Vehicle *vehicle, mavlink_message_t *message) override
static bool stopCompensatingBaro(const Vehicle *vehicle, QPair< QMetaObject::Connection, QMetaObject::Connection > updaters)
void guidedModeTakeoff(Vehicle *vehicle, double altitudeRel) const override
Command vehicle to takeoff from current location to the specified height.
double minimumEquivalentAirspeed(Vehicle *vehicle) const override
void startTakeoff(Vehicle *vehicle) const override
Command the vehicle to start a takeoff.
void adjustOutgoingMavlinkMessageThreadSafe(Vehicle *vehicle, LinkInterface *outgoingLink, mavlink_message_t *message) override
ParameterMetaData * _createParameterMetaData() override
QString smartRTLFlightMode() const override
Returns the flight mode for Smart RTL.
const QString _autoFlightMode
double maximumEquivalentAirspeed(Vehicle *vehicle) const override
QString missionFlightMode() const override
Returns the flight mode for running missions.
void guidedModeChangeAltitude(Vehicle *vehicle, double altitudeChange, bool pauseVehicle) override
bool mulirotorSpeedLimitsAvailable(Vehicle *vehicle) const override
QList< MAV_CMD > supportedMissionCommands(QGCMAVLink::VehicleClass_t vehicleClass) const override
List of supported mission commands. Empty list for all commands supported.
const QString _smartRtlFlightMode
double maximumHorizontalSpeedMultirotorMetersSecond(Vehicle *vehicle) const override
bool isCapable(const Vehicle *vehicle, FirmwareCapabilities capabilities) const override
void guidedModeChangeEquivalentAirspeedMetersSecond(Vehicle *vehicle, double airspeed_equiv) const override
static qreal calcAltOffsetP(uint32_t atmospheric1, uint32_t atmospheric2)
AutoPilotPlugin * autopilotPlugin(Vehicle *vehicle) const override
virtual QString guidedFlightMode() const
const QVariantList & toolIndicators(const Vehicle *vehicle) override
QString _internalParameterMetaDataFile(const Vehicle *vehicle) const override
void pauseVehicle(Vehicle *vehicle) const override
void initializeVehicle(Vehicle *vehicle) override
Called when Vehicle is first created to perform any firmware specific setup.
const QString _rtlFlightMode
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.
void setRawValue(const QVariant &value)
QVariant rawValue() const
The FirmwarePlugin class represents the methods and objects which are specific to a certain Firmware ...
virtual QString pauseFlightMode() const
Returns The flight mode which indicates the vehicle is paused.
FlightModeList _flightModeList
virtual double minimumEquivalentAirspeed(Vehicle *) const
virtual const QVariantList & toolIndicators(const Vehicle *vehicle)
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.
@ 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
virtual uint32_t _convertToCustomFlightModeEnum(uint32_t val) const
bool _armVehicleAndValidate(Vehicle *vehicle) const
virtual QString takeOffFlightMode() const
Returns the flight mode for TakeOff.
FlightModeCustomModeMap _modeEnumToString
virtual QString offlineEditingParamFile(Vehicle *) const
Return the resource file which contains the set of params loaded for offline editing.
virtual double maximumHorizontalSpeedMultirotorMetersSecond(Vehicle *) const
virtual double minimumTakeoffAltitudeMeters(Vehicle *) const
The link interface defines the interface for all links used to communicate with the ground station ap...
uint8_t mavlinkChannel() const
uint8_t allocateMavlinkChannel()
static LinkManager * instance()
static constexpr uint8_t invalidMavlinkChannel()
static int getComponentId()
static MAVLinkProtocol * instance()
void writeArduPilotGuidedMissionItem(const QGeoCoordinate &gotoCoord, bool altChangeOnly)
bool parameterExists(int componentId, const QString ¶mName) const
Fact * getParameter(int componentId, const QString ¶mName)
static constexpr int defaultComponentId
static VehicleClass_t vehicleClass(MAV_TYPE mavType)
static MAV_AUTOPILOT firmwareTypeFromString(const QString &firmwareTypeStr)
static constexpr const VehicleClass_t VehicleClassSub
static constexpr const VehicleClass_t VehicleClassFixedWing
static constexpr const VehicleClass_t VehicleClassMultiRotor
static MAV_TYPE vehicleTypeFromString(const QString &vehicleStr)
static constexpr const VehicleClass_t VehicleClassRoverBoat
static constexpr const VehicleClass_t VehicleClassVTOL
static FIRMWARE_VERSION_TYPE firmwareVersionTypeFromString(const QString &typeStr)
static QGCAmbientTemperature * instance()
void temperatureUpdated(qreal temperature)
static QGCPressure * instance()
void pressureUpdated(qreal pressure, qreal temperature)
static SettingsManager * instance()
APMMavlinkStreamRateSettings * apmMavlinkStreamRateSettings() const
static QString getMessageText(const mavlink_message_t &message)
Fact * altitudeRelative()
WeakLinkInterfacePtr primaryLink() const
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)
qreal getInitialGCSPressure() const
QString flightMode() const
void requestDataStream(MAV_DATA_STREAM stream, uint16_t rate, bool sendMultiple=true)
QGeoCoordinate homePosition()
void setFirmwarePluginInstanceData(FirmwarePluginInstanceData *firmwarePluginInstanceData)
MAV_TYPE vehicleType() const
VehicleLinkManager * vehicleLinkManager()
FirmwarePlugin * firmwarePlugin()
Provides access to the Firmware Plugin for this Vehicle.
qreal getInitialGCSTemperature() const
int firmwareMinorVersion() const
bool isOfflineEditingVehicle() const
bool sendMessageOnLinkThreadSafe(LinkInterface *link, mavlink_message_t message)
void _setUnderway(bool underway)
int defaultComponentId() const
ParameterManager * parameterManager()
void setFirmwareVersion(int majorVersion, int minorVersion, int patchVersion, FIRMWARE_VERSION_TYPE versionType=FIRMWARE_VERSION_TYPE_OFFICIAL)
QGeoCoordinate coordinate()
void sendMavCommandIntWithHandler(const MavCmdAckHandlerInfo_t *ackHandlerInfo, int compId, MAV_CMD command, MAV_FRAME frame, float param1=0.0f, float param2=0.0f, float param3=0.0f, float param4=0.0f, double param5=0.0f, double param6=0.0f, float param7=0.0f)
class FirmwarePluginInstanceData * firmwarePluginInstanceData()
int firmwareMajorVersion() const
MissionManager * missionManager()
static constexpr const char * videoSource3DRSolo
QByteArray line(std::string_view command)
command as one CR/LF-terminated line.
void showAppMessage(const QString &message, const QString &title)
Modal application message. Queued if the UI isn't ready yet.
static constexpr VehicleClass_t VehicleClassGeneric
Callback info bundle for sendMavCommandWithHandler.
MavCmdResultHandler resultHandler
nullptr for no handler
MavCmdResultFailureCode_t