17#elif defined(Q_OS_ANDROID)
22#include <QtCore/QApplicationStatic>
23#include <QtCore/QTimer>
31 , _gcsHeartbeatTimer(new QTimer(this))
35 qCDebug(MultiVehicleManagerLog) <<
this;
40 qCDebug(MultiVehicleManagerLog) <<
this;
45 return _multiVehicleManagerInstance();
58 _gcsHeartbeatTimer->setInterval(kGCSHeartbeatRateMSecs);
59 _gcsHeartbeatTimer->setSingleShot(
false);
60 (void) connect(_gcsHeartbeatTimer, &QTimer::timeout,
this, &MultiVehicleManager::_sendGCSHeartbeat);
61 _gcsHeartbeatTimer->start();
66void MultiVehicleManager::_vehicleHeartbeatInfo(
LinkInterface* link,
int vehicleId,
int componentId,
int vehicleFirmwareType,
int vehicleType)
68 if (componentId != MAV_COMP_ID_AUTOPILOT1) {
70 qCDebug(MultiVehicleManagerLog) <<
"Ignoring heartbeat from unknown component port:vehicleId:componentId:fwType:vehicleType"
74 << vehicleFirmwareType
82 if ((vehicleType == MAV_TYPE_GENERIC) && (vehicleFirmwareType == MAV_AUTOPILOT_ARDUPILOTMEGA)) {
83 vehicleType = MAV_TYPE_QUADROTOR;
86 switch (vehicleType) {
88 case MAV_TYPE_ONBOARD_CONTROLLER:
101 if (_ignoreVehicleIds.contains(vehicleId) ||
getVehicleById(vehicleId) || (vehicleId == 0)) {
105 qCDebug(MultiVehicleManagerLog) <<
"Adding new vehicle link:vehicleId:componentId:vehicleFirmwareType:vehicleType "
109 << vehicleFirmwareType
113 QGC::showAppMessage(tr(
"Warning: A vehicle is using the same system id as %1: %2").arg(QCoreApplication::applicationName()).arg(vehicleId));
116 Vehicle *
const vehicle =
new Vehicle(link, vehicleId, componentId, (MAV_AUTOPILOT)vehicleFirmwareType, (MAV_TYPE)vehicleType,
this);
120 _vehicles->
append(vehicle);
129 if (_vehicles->
count() > 1) {
135#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
136 if (_vehicles->
count() == 1) {
137 qCDebug(MultiVehicleManagerLog) <<
"keepScreenOn";
138 #if defined(Q_OS_ANDROID)
140 #elif defined(Q_OS_IOS)
141 MobileScreenMgr::setKeepScreenOn(
true);
147void MultiVehicleManager::_deleteVehiclePhase1(
Vehicle *vehicle)
149 qCDebug(MultiVehicleManagerLog) << Q_FUNC_INFO << vehicle;
152 for (
int i = 0; i < _vehicles->
count(); i++) {
153 if (_vehicles->
get(i) == vehicle) {
161 qCWarning(MultiVehicleManagerLog) <<
"Vehicle not found in map!";
167 _setActiveVehicleAvailable(
false);
168 _setParameterReadyVehicleAvailable(
false);
171#if defined(Q_OS_ANDROID) || defined (Q_OS_IOS)
172 if (_vehicles->
count() == 0) {
173 qCDebug(MultiVehicleManagerLog) <<
"restoreScreenOn";
174 #if defined(Q_OS_ANDROID)
176 #elif defined(Q_OS_IOS)
177 MobileScreenMgr::setKeepScreenOn(
false);
188 QTimer::singleShot(20,
this, [
this, vehicle]() {
189 _deleteVehiclePhase2(vehicle);
193void MultiVehicleManager::_deleteVehiclePhase2(
Vehicle *vehicle)
195 qCDebug(MultiVehicleManagerLog) << Q_FUNC_INFO << vehicle;
200 Vehicle *newActiveVehicle =
nullptr;
201 if (_vehicles->
count() > 0) {
202 newActiveVehicle = qobject_cast<Vehicle*>(_vehicles->
get(0));
205 _setActiveVehicle(newActiveVehicle);
207 if (_activeVehicle) {
208 _setActiveVehicleAvailable(
true);
210 _setParameterReadyVehicleAvailable(
true);
214 vehicle->deleteLater();
219 qCDebug(MultiVehicleManagerLog) << Q_FUNC_INFO << vehicle;
221 if (vehicle != _activeVehicle) {
222 if (_activeVehicle) {
228 _setActiveVehicleAvailable(
false);
229 _setParameterReadyVehicleAvailable(
false);
232 QTimer::singleShot(20,
this, [
this, vehicle]() {
233 _setActiveVehiclePhase2(vehicle);
238void MultiVehicleManager::_setActiveVehiclePhase2(
Vehicle *vehicle)
240 qCDebug(MultiVehicleManagerLog) << Q_FUNC_INFO << vehicle;
242 _setActiveVehicle(vehicle);
244 if (_activeVehicle) {
245 _setActiveVehicleAvailable(
true);
248 _setParameterReadyVehicleAvailable(
true);
253void MultiVehicleManager::_vehicleParametersReadyChanged(
bool parametersReady)
255 ParameterManager *
const paramMgr = qobject_cast<ParameterManager*>(sender());
260 if (paramMgr->
vehicle() == _activeVehicle) {
261 _setParameterReadyVehicleAvailable(parametersReady);
265void MultiVehicleManager::_sendGCSHeartbeat()
278 if (linkConfiguration->isHighLatency()) {
283 (void) mavlink_msg_heartbeat_pack_chan(
289 MAV_AUTOPILOT_INVALID,
290 MAV_MODE_MANUAL_ARMED,
301 if(!_vehicleSelected(vehicleId)) {
303 _selectedVehicles->
append(vehicle);
310 for (
int i = 0; i < _selectedVehicles->
count(); i++) {
311 Vehicle *
const vehicle = qobject_cast<Vehicle*>(_selectedVehicles->
get(i));
312 if (vehicle->
id() == vehicleId) {
321 _selectedVehicles->
clear();
324bool MultiVehicleManager::_vehicleSelected(
int vehicleId)
326 for (
int i = 0; i < _selectedVehicles->
count(); i++) {
327 Vehicle *
const vehicle = qobject_cast<Vehicle*>(_selectedVehicles->
get(i));
328 if (vehicle->
id() == vehicleId) {
337 for (
int i = 0; i < _vehicles->
count(); i++) {
338 Vehicle *
const vehicle = qobject_cast<Vehicle*>(_vehicles->
get(i));
339 if (vehicle->
id() == vehicleId) {
347void MultiVehicleManager::_setActiveVehicle(
Vehicle *vehicle)
349 if (vehicle != _activeVehicle) {
350 _activeVehicle = vehicle;
355void MultiVehicleManager::_setActiveVehicleAvailable(
bool activeVehicleAvailable)
363void MultiVehicleManager::_setParameterReadyVehicleAvailable(
bool parametersReady)
365 if (parametersReady != _parameterReadyVehicleAvailable) {
366 _parameterReadyVehicleAvailable = parametersReady;
std::shared_ptr< LinkConfiguration > SharedLinkConfigurationPtr
std::shared_ptr< LinkInterface > SharedLinkInterfacePtr
Q_APPLICATION_STATIC(MultiVehicleManager, _multiVehicleManagerInstance)
struct __mavlink_message mavlink_message_t
#define QGC_LOGGING_CATEGORY(name, categoryStr)
The link interface defines the interface for all links used to communicate with the ground station ap...
uint8_t mavlinkChannel() const
void sendMessageThreadSafe(mavlink_message_t &message)
virtual bool isConnected() const =0
SharedLinkConfigurationPtr linkConfiguration()
static LinkManager * instance()
QList< SharedLinkInterfacePtr > links()
static int getComponentId()
void vehicleHeartbeatInfo(LinkInterface *link, int vehicleId, int componentId, int vehicleFirmwareType, int vehicleType)
static MAVLinkProtocol * instance()
bool activeVehicleAvailable() const
static MultiVehicleManager * instance()
void activeVehicleAvailableChanged(bool activeVehicleAvailable)
Q_INVOKABLE void deselectAllVehicles()
Q_INVOKABLE void selectVehicle(int vehicleId)
void vehicleAdded(Vehicle *vehicle)
Q_INVOKABLE void deselectVehicle(int vehicleId)
void vehicleRemoved(Vehicle *vehicle)
void parameterReadyVehicleAvailableChanged(bool parameterReadyVehicleAvailable)
void activeVehicleChanged(Vehicle *activeVehicle)
Q_INVOKABLE Vehicle * getVehicleById(int vehicleId) const
void setActiveVehicle(Vehicle *vehicle)
void parametersReadyChanged(bool parametersReady)
bool parametersReady() const
virtual QGCOptions * options()
static QGCCorePlugin * instance()
virtual bool multiVehicleEnabled() const
void append(QObject *object)
Caller maintains responsibility for object ownership and deletion.
Q_INVOKABLE QObject * get(int index)
QObject * removeAt(int index)
int count() const override final
void clear() override final
FirmwareUpgradeSettings * firmwareUpgradeSettings() const
static SettingsManager * instance()
void allLinksRemoved(Vehicle *vehicle)
VehicleLinkManager * vehicleLinkManager()
static const MAV_AUTOPILOT MAV_AUTOPILOT_TRACK
static const MAV_TYPE MAV_TYPE_TRACK
ParameterManager * parameterManager()
void setKeepScreenOn(bool on)
void showAppMessage(const QString &message, const QString &title)
Modal application message. Queued if the UI isn't ready yet.