Newer
Older
_flightDistanceFact.setRawValue(0);
{
_flightTimeFact.setRawValue((double)_flightTimer.elapsed() / 1000.0);
}
disconnect(_missionManager, &MissionManager::newMissionItemsAvailable, this, &Vehicle::_firstMissionLoadComplete);
disconnect(_geoFenceManager, &GeoFenceManager::loadComplete, this, &Vehicle::_firstGeoFenceLoadComplete);
disconnect(_rallyPointManager, &RallyPointManager::loadComplete, this, &Vehicle::_firstRallyPointLoadComplete);
_initialPlanRequestComplete = true;
emit initialPlanRequestCompleteChanged(true);
void Vehicle::_parametersReady(bool parametersReady)
{
// Try to set current unix time to the vehicle
_sendQGCTimeToVehicle();
// Send time twice, more likely to get to the vehicle on a noisy link
_sendQGCTimeToVehicle();
disconnect(_parameterManager, &ParameterManager::parametersReadyChanged, this, &Vehicle::_parametersReady);
void Vehicle::_sendQGCTimeToVehicle()
{
mavlink_message_t msg;
mavlink_system_time_t cmd;
// Timestamp of the master clock in microseconds since UNIX epoch.
cmd.time_unix_usec = QDateTime::currentDateTime().currentMSecsSinceEpoch()*1000;
// Timestamp of the component clock since boot time in milliseconds (Not necessary).
cmd.time_boot_ms = 0;
mavlink_msg_system_time_encode_chan(_mavlink->getSystemId(),
vehicleLinkManager()->primaryLink()->mavlinkChannel(),
sendMessageOnLinkThreadSafe(vehicleLinkManager()->primaryLink(), msg);
void Vehicle::_imageReady(UASInterface*)
{
if(_uas)
{
QImage img = _uas->getImage();
_toolbox->imageProvider()->setImage(&img, _id);
_flowImageIndex++;
emit flowImageIndexChanged();
}
}
void Vehicle::_remoteControlRSSIChanged(uint8_t rssi)
{
//-- 0 <= rssi <= 100 - 255 means "invalid/unknown"
if(rssi > 100) { // Anything over 100 doesn't make sense
if(_rcRSSI != 255) {
_rcRSSI = 255;
emit rcRSSIChanged(_rcRSSI);
}
return;
}
//-- Initialize it
if(_rcRSSIstore == 255.) {
_rcRSSIstore = (double)rssi;
// Low pass to git rid of jitter
_rcRSSIstore = (_rcRSSIstore * 0.9f) + ((float)rssi * 0.1);
uint8_t filteredRSSI = (uint8_t)ceil(_rcRSSIstore);
if(_rcRSSIstore < 0.1) {
filteredRSSI = 0;
}
if(_rcRSSI != filteredRSSI) {
_rcRSSI = filteredRSSI;
emit rcRSSIChanged(_rcRSSI);
}
}
void Vehicle::virtualTabletJoystickValue(double roll, double pitch, double yaw, double thrust)
// The following if statement prevents the virtualTabletJoystick from sending values if the standard joystick is enabled
static_cast<float>(roll),
static_cast<float>(pitch),
static_cast<float>(yaw),
static_cast<float>(thrust),
0);
_toolbox->audioOutput()->say(text.toLower());
return QGCMAVLink::isFixedWing(vehicleType());
return QGCMAVLink::isSub(vehicleType());
return QGCMAVLink::isMultiRotor(vehicleType());
bool Vehicle::supportsThrottleModeCenterZero() const
{
return _firmwarePlugin->supportsThrottleModeCenterZero();
}
bool Vehicle::supportsNegativeThrust()
Gus Grubba
committed
return _firmwarePlugin->supportsNegativeThrust(this);
bool Vehicle::supportsRadio() const
{
return _firmwarePlugin->supportsRadio();
}
bool Vehicle::supportsJSButton() const
{
return _firmwarePlugin->supportsJSButton();
}
bool Vehicle::supportsMotorInterference() const
{
return _firmwarePlugin->supportsMotorInterference();
}
bool Vehicle::supportsTerrainFrame() const
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
QString Vehicle::vehicleTypeName() const {
static QMap<int, QString> typeNames = {
{ MAV_TYPE_GENERIC, tr("Generic micro air vehicle" )},
{ MAV_TYPE_FIXED_WING, tr("Fixed wing aircraft")},
{ MAV_TYPE_QUADROTOR, tr("Quadrotor")},
{ MAV_TYPE_COAXIAL, tr("Coaxial helicopter")},
{ MAV_TYPE_HELICOPTER, tr("Normal helicopter with tail rotor.")},
{ MAV_TYPE_ANTENNA_TRACKER, tr("Ground installation")},
{ MAV_TYPE_GCS, tr("Operator control unit / ground control station")},
{ MAV_TYPE_AIRSHIP, tr("Airship, controlled")},
{ MAV_TYPE_FREE_BALLOON, tr("Free balloon, uncontrolled")},
{ MAV_TYPE_ROCKET, tr("Rocket")},
{ MAV_TYPE_GROUND_ROVER, tr("Ground rover")},
{ MAV_TYPE_SURFACE_BOAT, tr("Surface vessel, boat, ship")},
{ MAV_TYPE_SUBMARINE, tr("Submarine")},
{ MAV_TYPE_HEXAROTOR, tr("Hexarotor")},
{ MAV_TYPE_OCTOROTOR, tr("Octorotor")},
{ MAV_TYPE_TRICOPTER, tr("Octorotor")},
{ MAV_TYPE_FLAPPING_WING, tr("Flapping wing")},
{ MAV_TYPE_KITE, tr("Flapping wing")},
{ MAV_TYPE_ONBOARD_CONTROLLER, tr("Onboard companion controller")},
{ MAV_TYPE_VTOL_DUOROTOR, tr("Two-rotor VTOL using control surfaces in vertical operation in addition. Tailsitter")},
{ MAV_TYPE_VTOL_QUADROTOR, tr("Quad-rotor VTOL using a V-shaped quad config in vertical operation. Tailsitter")},
{ MAV_TYPE_VTOL_TILTROTOR, tr("Tiltrotor VTOL")},
{ MAV_TYPE_VTOL_RESERVED2, tr("VTOL reserved 2")},
{ MAV_TYPE_VTOL_RESERVED3, tr("VTOL reserved 3")},
{ MAV_TYPE_VTOL_RESERVED4, tr("VTOL reserved 4")},
{ MAV_TYPE_VTOL_RESERVED5, tr("VTOL reserved 5")},
{ MAV_TYPE_GIMBAL, tr("Onboard gimbal")},
{ MAV_TYPE_ADSB, tr("Onboard ADSB peripheral")},
};
return typeNames[_vehicleType];
}
/// Returns the string to speak to identify the vehicle
QString Vehicle::_vehicleIdSpeech()
if (_toolbox->multiVehicleManager()->vehicles()->count() > 1) {
return tr("Vehicle %1 ").arg(id());
void Vehicle::_handleFlightModeChanged(const QString& flightMode)
_say(tr("%1 %2 flight mode").arg(_vehicleIdSpeech()).arg(flightMode));
emit guidedModeChanged(_firmwarePlugin->isGuidedMode(this));
}
void Vehicle::_announceArmedChanged(bool armed)
{
_say(QString("%1 %2").arg(_vehicleIdSpeech()).arg(armed ? tr("armed") : tr("disarmed")));
if(armed) {
//-- Keep track of armed coordinates
_armedPosition = _coordinate;
emit armedPositionChanged();
}
void Vehicle::_setFlying(bool flying)
_flying = flying;
emit flyingChanged(flying);
}
}
void Vehicle::_setLanding(bool landing)
{
if (armed() && _landing != landing) {
_landing = landing;
emit landingChanged(landing);
}
}
bool Vehicle::guidedModeSupported() const
return _firmwarePlugin->isCapable(this, FirmwarePlugin::GuidedModeCapability);
bool Vehicle::pauseVehicleSupported() const
return _firmwarePlugin->isCapable(this, FirmwarePlugin::PauseVehicleCapability);
}
bool Vehicle::orbitModeSupported() const
{
return _firmwarePlugin->isCapable(this, FirmwarePlugin::OrbitModeCapability);
bool Vehicle::roiModeSupported() const
{
return _firmwarePlugin->isCapable(this, FirmwarePlugin::ROIModeCapability);
}
bool Vehicle::takeoffVehicleSupported() const
{
return _firmwarePlugin->isCapable(this, FirmwarePlugin::TakeoffVehicleCapability);
}
QString Vehicle::gotoFlightMode() const
{
return _firmwarePlugin->gotoFlightMode();
}
return;
}
_firmwarePlugin->guidedModeLand(this);
}
void Vehicle::guidedModeTakeoff(double altitudeRelative)
_firmwarePlugin->guidedModeTakeoff(this, altitudeRelative);
double Vehicle::minimumTakeoffAltitude()
{
return _firmwarePlugin->minimumTakeoffAltitude(this);
}
{
_firmwarePlugin->startMission(this);
}
void Vehicle::guidedModeGotoLocation(const QGeoCoordinate& gotoCoord)
{
if (!guidedModeSupported()) {
if (!coordinate().isValid()) {
return;
}
double maxDistance = _settingsManager->flyViewSettings()->maxGoToLocationDistance()->rawValue().toDouble();
if (coordinate().distanceTo(gotoCoord) > maxDistance) {
qgcApp()->showAppMessage(QString("New location is too far. Must be less than %1 %2.").arg(qRound(FactMetaData::metersToAppSettingsHorizontalDistanceUnits(maxDistance).toDouble())).arg(FactMetaData::appSettingsHorizontalDistanceUnitsString()));
_firmwarePlugin->guidedModeGotoLocation(this, gotoCoord);
}
void Vehicle::guidedModeChangeAltitude(double altitudeChange)
_firmwarePlugin->guidedModeChangeAltitude(this, altitudeChange);
void Vehicle::guidedModeOrbit(const QGeoCoordinate& centerCoord, double radius, double amslAltitude)
qgcApp()->showAppMessage(QStringLiteral("Orbit mode not supported by Vehicle."));
defaultComponentId(),
MAV_CMD_DO_ORBIT,
MAV_FRAME_GLOBAL,
true, // show error if fails
static_cast<float>(radius),
static_cast<float>(qQNaN()), // Use default velocity
0, // Vehicle points to center
static_cast<float>(qQNaN()), // reserved
centerCoord.latitude(), centerCoord.longitude(), static_cast<float>(amslAltitude));
defaultComponentId(),
MAV_CMD_DO_ORBIT,
true, // show error if fails
static_cast<float>(radius),
static_cast<float>(qQNaN()), // Use default velocity
0, // Vehicle points to center
static_cast<float>(qQNaN()), // reserved
static_cast<float>(centerCoord.latitude()),
static_cast<float>(centerCoord.longitude()),
static_cast<float>(amslAltitude));
void Vehicle::guidedModeROI(const QGeoCoordinate& centerCoord)
{
if (!roiModeSupported()) {
qgcApp()->showAppMessage(QStringLiteral("ROI mode not supported by Vehicle."));
return;
}
if (capabilityBits() & MAV_PROTOCOL_CAPABILITY_COMMAND_INT) {
sendMavCommandInt(
defaultComponentId(),
MAV_CMD_DO_SET_ROI_LOCATION,
MAV_FRAME_GLOBAL,
true, // show error if fails
static_cast<float>(qQNaN()), // Empty
static_cast<float>(qQNaN()), // Empty
static_cast<float>(qQNaN()), // Empty
static_cast<float>(qQNaN()), // Empty
centerCoord.latitude(),
centerCoord.longitude(),
static_cast<float>(centerCoord.altitude()));
defaultComponentId(),
MAV_CMD_DO_SET_ROI_LOCATION,
true, // show error if fails
static_cast<float>(qQNaN()), // Empty
static_cast<float>(qQNaN()), // Empty
static_cast<float>(qQNaN()), // Empty
static_cast<float>(qQNaN()), // Empty
static_cast<float>(centerCoord.latitude()),
static_cast<float>(centerCoord.longitude()),
static_cast<float>(centerCoord.altitude()));
void Vehicle::stopGuidedModeROI()
{
if (!roiModeSupported()) {
qgcApp()->showAppMessage(QStringLiteral("ROI mode not supported by Vehicle."));
return;
}
if (capabilityBits() & MAV_PROTOCOL_CAPABILITY_COMMAND_INT) {
sendMavCommandInt(
defaultComponentId(),
MAV_CMD_DO_SET_ROI_NONE,
MAV_FRAME_GLOBAL,
true, // show error if fails
static_cast<float>(qQNaN()), // Empty
static_cast<float>(qQNaN()), // Empty
static_cast<float>(qQNaN()), // Empty
static_cast<float>(qQNaN()), // Empty
static_cast<double>(qQNaN()), // Empty
static_cast<double>(qQNaN()), // Empty
static_cast<float>(qQNaN())); // Empty
defaultComponentId(),
MAV_CMD_DO_SET_ROI_NONE,
true, // show error if fails
static_cast<float>(qQNaN()), // Empty
static_cast<float>(qQNaN()), // Empty
static_cast<float>(qQNaN()), // Empty
static_cast<float>(qQNaN()), // Empty
static_cast<float>(qQNaN()), // Empty
static_cast<float>(qQNaN()), // Empty
static_cast<float>(qQNaN())); // Empty
qgcApp()->showAppMessage(QStringLiteral("Pause not supported by vehicle."));
return;
}
_firmwarePlugin->pauseVehicle(this);
}
Danny Schrader
committed
void Vehicle::abortLanding(double climbOutAltitude)
{
defaultComponentId(),
MAV_CMD_DO_GO_AROUND,
true, // show error if fails
static_cast<float>(climbOutAltitude));
}
{
return _firmwarePlugin->isGuidedMode(this);
}
void Vehicle::setGuidedMode(bool guidedMode)
{
return _firmwarePlugin->setGuidedMode(this, guidedMode);
}
_defaultComponentId,
MAV_CMD_COMPONENT_ARM_DISARM,
true, // show error if fails
0.0f,
21196.0f); // Magic number for emergency stop
void Vehicle::setCurrentMissionSequence(int seq)
{
if (!_firmwarePlugin->sendHomePositionToVehicle()) {
seq--;
}
mavlink_message_t msg;
static_cast<uint8_t>(_mavlink->getSystemId()),
static_cast<uint8_t>(_mavlink->getComponentId()),
vehicleLinkManager()->primaryLink()->mavlinkChannel(),
&msg,
static_cast<uint8_t>(id()),
_compID,
static_cast<uint16_t>(seq));
sendMessageOnLinkThreadSafe(vehicleLinkManager()->primaryLink(), msg);
void Vehicle::sendMavCommand(int compId, MAV_CMD command, bool showError, float param1, float param2, float param3, float param4, float param5, float param6, float param7)
_sendMavCommandWorker(false, // commandInt
false, // requestMessage
showError,
nullptr, // resultHandler
nullptr, // resultHandlerData
compId,
command,
MAV_FRAME_GLOBAL,
param1, param2, param3, param4, param5, param6, param7);
Don Gagne
committed
void Vehicle::sendCommand(int compId, int command, bool showError, double param1, double param2, double param3, double param4, double param5, double param6, double param7)
{
sendMavCommand(
compId, static_cast<MAV_CMD>(command),
showError,
static_cast<float>(param1),
static_cast<float>(param2),
static_cast<float>(param3),
static_cast<float>(param4),
static_cast<float>(param5),
static_cast<float>(param6),
static_cast<float>(param7));
}
void Vehicle::sendMavCommandWithHandler(MavCmdResultHandler resultHandler, void *resultHandlerData, int compId, MAV_CMD command, float param1, float param2, float param3, float param4, float param5, float param6, float param7)
_sendMavCommandWorker(false, // commandInt
false, // requestMessage,
false, // showError
resultHandler,
resultHandlerData,
compId,
command,
MAV_FRAME_GLOBAL,
param1, param2, param3, param4, param5, param6, param7);
}
void Vehicle::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)
{
_sendMavCommandWorker(true, // commandInt
false, // requestMessage
showError,
nullptr, // resultHandler
nullptr, // resultHandlerData
compId,
command,
frame,
param1, param2, param3, param4, param5, param6, param7);
Don Gagne
committed
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
int Vehicle::_findMavCommandListEntryIndex(int targetCompId, MAV_CMD command)
{
for (int i=0; i<_mavCommandList.count(); i++) {
const MavCommandListEntry_t& entry = _mavCommandList[i];
if (entry.targetCompId == targetCompId && entry.command == command) {
return i;
}
}
return -1;
}
bool Vehicle::_sendMavCommandShouldRetry(MAV_CMD command)
{
switch (command) {
#ifdef QT_DEBUG
// These MockLink command should be retried so we can create unit tests to test retry code
case MockLink::MAV_CMD_MOCKLINK_ALWAYS_RESULT_ACCEPTED:
case MockLink::MAV_CMD_MOCKLINK_ALWAYS_RESULT_FAILED:
case MockLink::MAV_CMD_MOCKLINK_SECOND_ATTEMPT_RESULT_ACCEPTED:
case MockLink::MAV_CMD_MOCKLINK_SECOND_ATTEMPT_RESULT_FAILED:
case MockLink::MAV_CMD_MOCKLINK_NO_RESPONSE:
return true;
#endif
// In general we should not retry any commands. This is for safety reasons. For example you don't want an ARM command
// to timeout with no response over a noisy link twice and then suddenly have the third try work 6 seconds later. At that
// point the user could have walked up to the vehicle to see what is going wrong.
//
// We do retry commands which are part of the initial vehicle connect sequence. This makes this process work better over noisy
// links where commands could be lost. Also these commands tend to just be requesting status so if they end up being delayed
// there are no safety concerns that could occur.
case MAV_CMD_REQUEST_AUTOPILOT_CAPABILITIES:
case MAV_CMD_REQUEST_PROTOCOL_VERSION:
case MAV_CMD_REQUEST_MESSAGE:
case MAV_CMD_PREFLIGHT_STORAGE:
return true;
default:
return false;
}
}
void Vehicle::_sendMavCommandWorker(bool commandInt, bool requestMessage, bool showError, MavCmdResultHandler resultHandler, void* resultHandlerData, int targetCompId, MAV_CMD command, MAV_FRAME frame, float param1, float param2, float param3, float param4, float param5, float param6, float param7)
Don Gagne
committed
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
int entryIndex = _findMavCommandListEntryIndex(targetCompId, command);
if (entryIndex != -1 || targetCompId == MAV_COMP_ID_ALL) {
bool compIdAll = targetCompId == MAV_COMP_ID_ALL;
QString rawCommandName = _toolbox->missionCommandTree()->rawName(command);
qCDebug(VehicleLog) << QStringLiteral("_sendMavCommandWorker failing %1").arg(compIdAll ? "MAV_COMP_ID_ALL not supportded" : "duplicate command") << rawCommandName;
// If we send multiple versions of the same command to a component there is no way to discern which COMMAND_ACK we get back goes with which.
// Because of this we fail in that case.
MavCmdResultFailureCode_t failureCode = compIdAll ? MavCmdResultCommandResultOnly : MavCmdResultFailureDuplicateCommand;
if (resultHandler) {
(*resultHandler)(resultHandlerData, targetCompId, MAV_RESULT_FAILED, failureCode);
} else {
emit mavCommandResult(_id, targetCompId, command, MAV_RESULT_FAILED, failureCode);
}
if (showError) {
qgcApp()->showAppMessage(tr("Unabled to send command: %1. %2").arg(compIdAll ? tr("Internal error") : tr("Waiting on previous response to same command.")));
}
return;
}
Don Gagne
committed
MavCommandListEntry_t entry;
entry.useCommandInt = commandInt;
entry.targetCompId = targetCompId;
entry.command = command;
entry.frame = frame;
entry.showError = showError;
entry.requestMessage = requestMessage;
entry.resultHandler = resultHandler;
entry.resultHandlerData = resultHandlerData;
entry.rgParam[0] = param1;
entry.rgParam[1] = param2;
entry.rgParam[2] = param3;
entry.rgParam[3] = param4;
entry.rgParam[4] = param5;
entry.rgParam[5] = param6;
entry.rgParam[6] = param7;
Don Gagne
committed
entry.maxTries = _sendMavCommandShouldRetry(command) ? _mavCommandMaxRetryCount : 1;
entry.ackTimeoutMSecs = _vehicleLinkManager->primaryLink()->linkConfiguration()->isHighLatency() ? _mavCommandAckTimeoutMSecsHighLatency : _mavCommandAckTimeoutMSecs;
entry.elapsedTimer.start();
Don Gagne
committed
_mavCommandList.append(entry);
_sendMavCommandFromList(_mavCommandList.last());
Don Gagne
committed
void Vehicle::_sendMavCommandFromList(MavCommandListEntry_t& commandEntry)
Don Gagne
committed
QString rawCommandName = _toolbox->missionCommandTree()->rawName(commandEntry.command);
Don Gagne
committed
if (++commandEntry.tryCount > commandEntry.maxTries) {
qCDebug(VehicleLog) << "_sendMavCommandFromList giving up after max retries" << rawCommandName;
if (commandEntry.resultHandler) {
(*commandEntry.resultHandler)(commandEntry.resultHandlerData, commandEntry.targetCompId, MAV_RESULT_FAILED, MavCmdResultFailureNoResponseToCommand);
Don Gagne
committed
emit mavCommandResult(_id, commandEntry.targetCompId, commandEntry.command, MAV_RESULT_FAILED, MavCmdResultFailureNoResponseToCommand);
Don Gagne
committed
if (commandEntry.showError) {
qgcApp()->showAppMessage(tr("Vehicle did not respond to command: %1").arg(rawCommandName));
Don Gagne
committed
_mavCommandList.removeAt(_findMavCommandListEntryIndex(commandEntry.targetCompId, commandEntry.command));
return;
}
Don Gagne
committed
if (commandEntry.tryCount > 1 && !px4Firmware() && commandEntry.command == MAV_CMD_START_RX_PAIR) {
// The implementation of this command comes from the IO layer and is shared across stacks. So for other firmwares
// we aren't really sure whether they are correct or not.
return;
Don Gagne
committed
if (commandEntry.requestMessage) {
RequestMessageInfo_t* pInfo = static_cast<RequestMessageInfo_t*>(commandEntry.resultHandlerData);
_waitForMavlinkMessage(_requestMessageWaitForMessageResultHandler, pInfo, pInfo->msgId, 1000);
}
Don Gagne
committed
qCDebug(VehicleLog) << "_sendMavCommandFromList command:tryCount" << rawCommandName << commandEntry.tryCount;
Don Gagne
committed
if (commandEntry.useCommandInt) {
mavlink_command_int_t cmd;
memset(&cmd, 0, sizeof(cmd));
cmd.target_system = _id;
Don Gagne
committed
cmd.target_component = commandEntry.targetCompId;
cmd.command = commandEntry.command;
cmd.frame = commandEntry.frame;
cmd.param1 = commandEntry.rgParam[0];
cmd.param2 = commandEntry.rgParam[1];
cmd.param3 = commandEntry.rgParam[2];
cmd.param4 = commandEntry.rgParam[3];
cmd.x = commandEntry.rgParam[4] * qPow(10.0, 7.0);
cmd.y = commandEntry.rgParam[5] * qPow(10.0, 7.0);
cmd.z = commandEntry.rgParam[6];
mavlink_msg_command_int_encode_chan(_mavlink->getSystemId(),
_mavlink->getComponentId(),
vehicleLinkManager()->primaryLink()->mavlinkChannel(),
&msg,
&cmd);
} else {
mavlink_command_long_t cmd;
memset(&cmd, 0, sizeof(cmd));
cmd.target_system = _id;
Don Gagne
committed
cmd.target_component = commandEntry.targetCompId;
cmd.command = commandEntry.command;
Don Gagne
committed
cmd.param1 = commandEntry.rgParam[0];
cmd.param2 = commandEntry.rgParam[1];
cmd.param3 = commandEntry.rgParam[2];
cmd.param4 = commandEntry.rgParam[3];
cmd.param5 = commandEntry.rgParam[4];
cmd.param6 = commandEntry.rgParam[5];
cmd.param7 = commandEntry.rgParam[6];
mavlink_msg_command_long_encode_chan(_mavlink->getSystemId(),
_mavlink->getComponentId(),
vehicleLinkManager()->primaryLink()->mavlinkChannel(),
sendMessageOnLinkThreadSafe(vehicleLinkManager()->primaryLink(), msg);
Don Gagne
committed
void Vehicle::_sendMavCommandResponseTimeoutCheck(void)
Don Gagne
committed
if (_mavCommandList.isEmpty()) {
return;
}
// Walk the list backwards since _sendMavCommandFromList can remove entries
for (int i=_mavCommandList.count()-1; i>=0; i--) {
MavCommandListEntry_t& commandEntry = _mavCommandList[i];
if (commandEntry.elapsedTimer.elapsed() > commandEntry.ackTimeoutMSecs) {
// Try sending command again
_sendMavCommandFromList(commandEntry);
}
void Vehicle::_handleCommandAck(mavlink_message_t& message)
{
mavlink_command_ack_t ack;
mavlink_msg_command_ack_decode(&message, &ack);
QString rawCommandName =_toolbox->missionCommandTree()->rawName(static_cast<MAV_CMD>(ack.command));
qCDebug(VehicleLog) << QStringLiteral("_handleCommandAck command(%1) result(%2)").arg(rawCommandName).arg(QGCMAVLink::mavResultToString(static_cast<MAV_RESULT>(ack.result)));
if (ack.command == MAV_CMD_DO_SET_ROI_LOCATION) {
if (ack.result == MAV_RESULT_ACCEPTED) {
_isROIEnabled = true;
emit isROIEnabledChanged();
}
}
if (ack.command == MAV_CMD_DO_SET_ROI_NONE) {
if (ack.result == MAV_RESULT_ACCEPTED) {
_isROIEnabled = false;
emit isROIEnabledChanged();
}
}
if (ack.command == MAV_CMD_FLASH_BOOTLOADER && ack.result == MAV_RESULT_ACCEPTED) {
Don Gagne
committed
int entryIndex = _findMavCommandListEntryIndex(message.compid, static_cast<MAV_CMD>(ack.command));
if (entryIndex != -1) {
const MavCommandListEntry_t& commandEntry = _mavCommandList[entryIndex];
if (commandEntry.command == ack.command) {
if (commandEntry.requestMessage) {
RequestMessageInfo_t* pInfo = static_cast<RequestMessageInfo_t*>(commandEntry.resultHandlerData);
pInfo->commandAckReceived = true;
if (ack.result == MAV_RESULT_ACCEPTED) {
if (pInfo->messageReceived) {
delete pInfo;
} else {
_waitForMavlinkMessageTimeoutActive = true;
_waitForMavlinkMessageElapsed.restart();
}
Don Gagne
committed
if (pInfo->messageReceived) {
qCWarning(VehicleLog) << "Internal Error: _handleCommandAck for requestMessage with result failure, but message already received";
} else {
_waitForMavlinkMessageClear();
(*commandEntry.resultHandler)(commandEntry.resultHandlerData, message.compid, static_cast<MAV_RESULT>(ack.result), MavCmdResultCommandResultOnly);
}
Don Gagne
committed
if (commandEntry.resultHandler) {
(*commandEntry.resultHandler)(commandEntry.resultHandlerData, message.compid, static_cast<MAV_RESULT>(ack.result), MavCmdResultCommandResultOnly);
Don Gagne
committed
if (commandEntry.showError) {
switch (ack.result) {
case MAV_RESULT_TEMPORARILY_REJECTED:
qgcApp()->showAppMessage(tr("%1 command temporarily rejected").arg(rawCommandName));
break;
case MAV_RESULT_DENIED:
qgcApp()->showAppMessage(tr("%1 command denied").arg(rawCommandName));
break;
case MAV_RESULT_UNSUPPORTED:
qgcApp()->showAppMessage(tr("%1 command not supported").arg(rawCommandName));
break;
case MAV_RESULT_FAILED:
qgcApp()->showAppMessage(tr("%1 command failed").arg(rawCommandName));
break;
default:
// Do nothing
break;
}
Don Gagne
committed
emit mavCommandResult(_id, message.compid, ack.command, ack.result, MavCmdResultCommandResultOnly);
Don Gagne
committed
_mavCommandList.removeAt(entryIndex);
return;
Don Gagne
committed
qCDebug(VehicleLog) << "_handleCommandAck Ack not in list" << rawCommandName;
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
void Vehicle::_waitForMavlinkMessage(WaitForMavlinkMessageResultHandler resultHandler, void* resultHandlerData, int messageId, int timeoutMsecs)
{
qCDebug(VehicleLog) << "_waitForMavlinkMessage msg:timeout" << messageId << timeoutMsecs;
_waitForMavlinkMessageResultHandler = resultHandler;
_waitForMavlinkMessageResultHandlerData = resultHandlerData;
_waitForMavlinkMessageId = messageId;
_waitForMavlinkMessageTimeoutActive = false;
_waitForMavlinkMessageTimeoutMsecs = timeoutMsecs;
}
void Vehicle::_waitForMavlinkMessageClear(void)
{
qCDebug(VehicleLog) << "_waitForMavlinkMessageClear";
_waitForMavlinkMessageResultHandler = nullptr;
_waitForMavlinkMessageResultHandlerData = nullptr;
_waitForMavlinkMessageId = 0;
}
void Vehicle::_waitForMavlinkMessageMessageReceived(const mavlink_message_t& message)
{
if (_waitForMavlinkMessageId != 0) {
if (_waitForMavlinkMessageId == message.msgid) {
WaitForMavlinkMessageResultHandler resultHandler = _waitForMavlinkMessageResultHandler;
void* resultHandlerData = _waitForMavlinkMessageResultHandlerData;
qCDebug(VehicleLog) << "_waitForMavlinkMessageMessageReceived message received" << _waitForMavlinkMessageId;
_waitForMavlinkMessageClear();
(*resultHandler)(resultHandlerData, false /* noResponseFromVehicle */, message);
} else if (_waitForMavlinkMessageTimeoutActive && _waitForMavlinkMessageElapsed.elapsed() > _waitForMavlinkMessageTimeoutMsecs) {
WaitForMavlinkMessageResultHandler resultHandler = _waitForMavlinkMessageResultHandler;
void* resultHandlerData = _waitForMavlinkMessageResultHandlerData;
qCDebug(VehicleLog) << "_waitForMavlinkMessageMessageReceived message timed out" << _waitForMavlinkMessageId;
_waitForMavlinkMessageClear();
(*resultHandler)(resultHandlerData, true /* noResponseFromVehicle */, message);
void Vehicle::requestMessage(RequestMessageResultHandler resultHandler, void* resultHandlerData, int compId, int messageId, float param1, float param2, float param3, float param4, float param5)
{
RequestMessageInfo_t* pInfo = new RequestMessageInfo_t;
pInfo->msgId = messageId;
pInfo->compId = compId;
pInfo->resultHandler = resultHandler;
pInfo->resultHandlerData = resultHandlerData;
_sendMavCommandWorker(false, // commandInt
true, // requestMessage,
false, // showError
_requestMessageCmdResultHandler,
Don Gagne
committed
pInfo, // resultHandlerData
compId,
MAV_CMD_REQUEST_MESSAGE,
MAV_FRAME_GLOBAL,
messageId,
param1, param2, param3, param4, param5, 0);
}
Don Gagne
committed
void Vehicle::_requestMessageCmdResultHandler(void* resultHandlerData, int /*compId*/, MAV_RESULT result, MavCmdResultFailureCode_t failureCode)
{
RequestMessageInfo_t* pInfo = static_cast<RequestMessageInfo_t*>(resultHandlerData);
pInfo->commandAckReceived = true;
if (result != MAV_RESULT_ACCEPTED) {
Don Gagne
committed
mavlink_message_t message;
RequestMessageResultHandlerFailureCode_t requestMessageFailureCode;
switch (failureCode) {
case Vehicle::MavCmdResultCommandResultOnly:
requestMessageFailureCode = RequestMessageFailureCommandError;
break;
case Vehicle::MavCmdResultFailureNoResponseToCommand:
requestMessageFailureCode = RequestMessageFailureCommandNotAcked;
break;
case Vehicle::MavCmdResultFailureDuplicateCommand:
requestMessageFailureCode = RequestMessageFailureDuplicateCommand;
break;
}
(*pInfo->resultHandler)(pInfo->resultHandlerData, result, requestMessageFailureCode, message);
}
if (pInfo->messageReceived) {
delete pInfo;
}
}
void Vehicle::_requestMessageWaitForMessageResultHandler(void* resultHandlerData, bool noResponsefromVehicle, const mavlink_message_t& message)
{
RequestMessageInfo_t* pInfo = static_cast<RequestMessageInfo_t*>(resultHandlerData);
pInfo->messageReceived = true;
(*pInfo->resultHandler)(pInfo->resultHandlerData, noResponsefromVehicle ? MAV_RESULT_FAILED : MAV_RESULT_ACCEPTED, noResponsefromVehicle ? RequestMessageFailureMessageNotReceived : RequestMessageNoFailure, message);
}
void Vehicle::setPrearmError(const QString& prearmError)
{
_prearmError = prearmError;
emit prearmErrorChanged(_prearmError);
if (!_prearmError.isEmpty()) {
_prearmErrorTimer.start();
}
}
void Vehicle::_prearmErrorTimeout()
void Vehicle::setFirmwareVersion(int majorVersion, int minorVersion, int patchVersion, FIRMWARE_VERSION_TYPE versionType)
{
_firmwareMajorVersion = majorVersion;
_firmwareMinorVersion = minorVersion;
_firmwarePatchVersion = patchVersion;
_firmwareVersionType = versionType;
emit firmwareVersionChanged();
}
void Vehicle::setFirmwareCustomVersion(int majorVersion, int minorVersion, int patchVersion)
{
_firmwareCustomMajorVersion = majorVersion;
_firmwareCustomMinorVersion = minorVersion;
_firmwareCustomPatchVersion = patchVersion;
emit firmwareCustomVersionChanged();
QString Vehicle::firmwareVersionTypeString() const
{
switch (_firmwareVersionType) {
case FIRMWARE_VERSION_TYPE_DEV:
return QStringLiteral("dev");
case FIRMWARE_VERSION_TYPE_ALPHA:
return QStringLiteral("alpha");
case FIRMWARE_VERSION_TYPE_BETA:
return QStringLiteral("beta");
case FIRMWARE_VERSION_TYPE_RC:
return QStringLiteral("rc");
case FIRMWARE_VERSION_TYPE_OFFICIAL:
default:
return QStringLiteral("");
}
Don Gagne
committed
void Vehicle::_rebootCommandResultHandler(void* resultHandlerData, int /*compId*/, MAV_RESULT commandResult, MavCmdResultFailureCode_t failureCode)
Vehicle* vehicle = static_cast<Vehicle*>(resultHandlerData);
if (commandResult != MAV_RESULT_ACCEPTED) {
Don Gagne
committed
switch (failureCode) {
case MavCmdResultCommandResultOnly:
qCDebug(VehicleLog) << QStringLiteral("MAV_CMD_PREFLIGHT_REBOOT_SHUTDOWN error(%1)").arg(commandResult);
Don Gagne
committed
break;
case MavCmdResultFailureNoResponseToCommand:
qCDebug(VehicleLog) << "MAV_CMD_PREFLIGHT_REBOOT_SHUTDOWN failed: no response from vehicle";
break;
case MavCmdResultFailureDuplicateCommand:
qCDebug(VehicleLog) << "MAV_CMD_PREFLIGHT_REBOOT_SHUTDOWN failed: duplicate command";
break;
}
qgcApp()->showAppMessage(tr("Vehicle reboot failed."));
} else {
vehicle->closeVehicle();
}
}
void Vehicle::rebootVehicle()
{
sendMavCommandWithHandler(_rebootCommandResultHandler, this, _defaultComponentId, MAV_CMD_PREFLIGHT_REBOOT_SHUTDOWN, 1);
void Vehicle::startCalibration(Vehicle::CalibrationType calType)
{
float param1 = 0;