Skip to content

Commit

Permalink
Rework Vehicle Joystick Handling
Browse files Browse the repository at this point in the history
This fixes a number of issues with the way joysticks were handled
in a multi vehicle context. I reworked the way vehicle determine
to enable and capture the joystick input, as well as seperating
setJoystickEnable from saveJoystick to seperate runtime and saved
state.
  • Loading branch information
JMare committed Aug 9, 2023
1 parent 72c0f4e commit 529925f
Show file tree
Hide file tree
Showing 8 changed files with 89 additions and 41 deletions.
13 changes: 12 additions & 1 deletion src/Joystick/Joystick.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

#include <QSettings>

QGC_LOGGING_CATEGORY(JoystickLog, "JoystickLog")
// JoystickLog Category declaration moved to QGCLoggingCategory.cc to allow access in Vehicle
QGC_LOGGING_CATEGORY(JoystickValuesLog, "JoystickValuesLog")

const char* Joystick::_settingsGroup = "Joysticks";
Expand Down Expand Up @@ -128,6 +128,7 @@ Joystick::Joystick(const QString& name, int axisCount, int buttonCount, int hatC
_updateTXModeSettingsKey(_multiVehicleManager->activeVehicle());
_loadSettings();
connect(_multiVehicleManager, &MultiVehicleManager::activeVehicleChanged, this, &Joystick::_activeVehicleChanged);
connect(qgcApp()->toolbox()->multiVehicleManager()->vehicles(), &QmlObjectListModel::countChanged, this, &Joystick::_vehicleCountChanged);

_customMavCommands = JoystickMavCommand::load("JoystickMavCommands.json");
}
Expand Down Expand Up @@ -226,6 +227,16 @@ void Joystick::_activeVehicleChanged(Vehicle* activeVehicle)
}
}

void Joystick::_vehicleCountChanged(int count)
{
if(count == 0)
{
// then the last vehicle has been deleted
qCDebug(JoystickLog) << "Stopping joystick thread due to last active vehicle deletion";
this->stopPolling();
}
}

void Joystick::_loadSettings()
{
QSettings settings;
Expand Down
4 changes: 3 additions & 1 deletion src/Joystick/Joystick.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
#include "MultiVehicleManager.h"
#include "JoystickMavCommand.h"

Q_DECLARE_LOGGING_CATEGORY(JoystickLog)
// JoystickLog Category declaration moved to QGCLoggingCategory.cc to allow access in Vehicle
Q_DECLARE_LOGGING_CATEGORY(JoystickValuesLog)
Q_DECLARE_METATYPE(GRIPPER_ACTIONS)

Expand Down Expand Up @@ -370,4 +370,6 @@ class Joystick : public QThread

private slots:
void _activeVehicleChanged(Vehicle* activeVehicle);
void _vehicleCountChanged(int count);

};
2 changes: 2 additions & 0 deletions src/QGCLoggingCategory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ QGC_LOGGING_CATEGORY(GuidedActionsControllerLog, "GuidedActionsControllerLog"
QGC_LOGGING_CATEGORY(ADSBVehicleManagerLog, "ADSBVehicleManagerLog")
QGC_LOGGING_CATEGORY(LocalizationLog, "LocalizationLog")
QGC_LOGGING_CATEGORY(VideoAllLog, kVideoAllLogCategory)
QGC_LOGGING_CATEGORY(JoystickLog, "JoystickLog")


QGCLoggingCategoryRegister* _instance = nullptr;
const char* QGCLoggingCategoryRegister::_filterRulesSettingsGroup = "LoggingFilters";
Expand Down
1 change: 1 addition & 0 deletions src/QGCLoggingCategory.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ Q_DECLARE_LOGGING_CATEGORY(GuidedActionsControllerLog)
Q_DECLARE_LOGGING_CATEGORY(ADSBVehicleManagerLog)
Q_DECLARE_LOGGING_CATEGORY(LocalizationLog)
Q_DECLARE_LOGGING_CATEGORY(VideoAllLog) // turns on all individual QGC video logs
Q_DECLARE_LOGGING_CATEGORY(JoystickLog)

/// @def QGC_LOGGING_CATEGORY
/// This is a QGC specific replacement for Q_LOGGING_CATEGORY. It will register the category name into a
Expand Down
95 changes: 61 additions & 34 deletions src/Vehicle/Vehicle.cc
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,7 @@ Vehicle::Vehicle(LinkInterface* link,
{
_linkManager = _toolbox->linkManager();

connect(_joystickManager, &JoystickManager::activeJoystickChanged, this, &Vehicle::_loadSettings);
connect(qgcApp()->toolbox()->multiVehicleManager(), &MultiVehicleManager::activeVehicleAvailableChanged, this, &Vehicle::_activeVehicleAvailableChanged);
connect(_joystickManager, &JoystickManager::activeJoystickChanged, this, &Vehicle::_loadJoystickSettings);
connect(qgcApp()->toolbox()->multiVehicleManager(), &MultiVehicleManager::activeVehicleChanged, this, &Vehicle::_activeVehicleChanged);

_mavlink = _toolbox->mavlinkProtocol();
Expand Down Expand Up @@ -475,6 +474,9 @@ void Vehicle::_commonInit()
_settingsManager->videoSettings()->videoSource()->setRawValue(VideoSettings::videoSourceUDPH264);
_settingsManager->videoSettings()->lowLatencyMode()->setRawValue(true);
}

// enable Joystick if appropriate
_loadJoystickSettings();
}

Vehicle::~Vehicle()
Expand All @@ -489,10 +491,6 @@ Vehicle::~Vehicle()

delete _mav;
_mav = nullptr;

if (_joystickManager) {
_startJoystick(false);
}
}

void Vehicle::prepareDelete()
Expand Down Expand Up @@ -2082,41 +2080,45 @@ void Vehicle::resetErrorLevelMessages()
}
}

void Vehicle::_loadSettings()
// this function called in three cases:
// 1. On constructor of vehicle, to see if we should enable a joystick
// 2. When there is a new active joystick
// 3. When the active joystick is disconnected (even if there isnt a new one)
void Vehicle::_loadJoystickSettings()
{
QSettings settings;
settings.beginGroup(QString(_settingsGroup).arg(_id));
// Joystick enabled is a global setting so first make sure there are any joysticks connected
if (_toolbox->joystickManager()->joysticks().count()) {
static const bool _useButtonsOnly = qgcApp()->toolbox()->corePlugin()->options()->joystickUseButtonsOnly();

if (!_useButtonsOnly && _toolbox->joystickManager()->activeJoystick()) {
qCDebug(JoystickLog) << "Vehicle " << this->id() << " Notified of an active joystick. Loading setting joystickenabled: " << settings.value(_joystickEnabledSettingsKey, false).toBool();
setJoystickEnabled(settings.value(_joystickEnabledSettingsKey, false).toBool());
_startJoystick(true);
}
}

void Vehicle::_activeVehicleAvailableChanged(bool isActiveVehicleAvailable)
{
// if there is no longer an active vehicle, disconnect the joystick
if(!isActiveVehicleAvailable) {
else if(_useButtonsOnly)
{
// in a build with _useButtonsOnly set, joystickenable should always be left false
// this prevents the sticks from doing anything
qCDebug(JoystickLog) << "Vehicle " << this->id() << " Skipping Load of Joystick Settings because QCC Options useButtonsOnly is set";
setJoystickEnabled(false);
}
}

void Vehicle::_activeVehicleChanged(Vehicle *newActiveVehicle)
{
if(newActiveVehicle == this) {
// this vehicle is the newly active vehicle
setJoystickEnabled(true);
else
{
qCDebug(JoystickLog) << "Vehicle " << this->id() << " Notified that there is no active joystick";
setJoystickEnabled(false);
}
}

void Vehicle::_saveSettings()
// This is called from the UI when a deliberate action is taken to enable or disable the joystick
// This save allows the joystick enable state to persist restarts, disconnections of the joystick etc
void Vehicle::saveJoystickSettings()
{
QSettings settings;
settings.beginGroup(QString(_settingsGroup).arg(_id));

// The joystick enabled setting should only be changed if a joystick is present
// since the checkbox can only be clicked if one is present
if (_toolbox->joystickManager()->joysticks().count()) {
qCDebug(JoystickLog) << "Vehicle " << this->id() << " Saving setting joystickenabled: " << _joystickEnabled;
settings.setValue(_joystickEnabledSettingsKey, _joystickEnabled);
}
}
Expand All @@ -2128,25 +2130,50 @@ bool Vehicle::joystickEnabled() const

void Vehicle::setJoystickEnabled(bool enabled)
{
if (enabled){
qCDebug(JoystickLog) << "Vehicle " << this->id() << " Joystick Enabled";
}
else {
qCDebug(JoystickLog) << "Vehicle " << this->id() << " Joystick Disabled";
}

// _joystickEnabled is the runtime state - it determines whether a vehicle is using joystick data when it is active
_joystickEnabled = enabled;
_startJoystick(_joystickEnabled);
_saveSettings();

// if we are the active vehicle, call start polling on the active joystick
// This routes the joystick signals to this vehicle
// We do this even if we are disabling the joystick
// because it will trigger disconnection of the signals
if (_toolbox->multiVehicleManager()->activeVehicle() == this){
_captureJoystick();
}

emit joystickEnabledChanged(_joystickEnabled);
}

void Vehicle::_startJoystick(bool start)
void Vehicle::_activeVehicleChanged(Vehicle *newActiveVehicle)
{
// the new active vehicle should always capture the joystick
// even if the new active vehicle has joystick disabled
// capturing the joystick will stop the joystick data going to the inactive vehicle
if (newActiveVehicle == this){
qCDebug(JoystickLog) << "Vehicle " << this->id() << " is the new active vehicle";
_captureJoystick();
}
}

// tells the active joystick where to send data
void Vehicle::_captureJoystick()
{
Joystick* joystick = _joystickManager->activeJoystick();
if (joystick) {
if (start) {
joystick->startPolling(this);
} else {
joystick->stopPolling();
joystick->wait(500);
}

if(joystick){
qCDebug(JoystickLog) << "Vehicle " << this->id() << " Capture Joystick";
joystick->startPolling(this);
}
}


QGeoCoordinate Vehicle::homePosition()
{
return _homePosition;
Expand Down
9 changes: 5 additions & 4 deletions src/Vehicle/Vehicle.h
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,9 @@ class Vehicle : public FactGroup
/// Set home from flight map coordinate
Q_INVOKABLE void doSetHome(const QGeoCoordinate& coord);

/// Save the joystick enable setting to the settings group
Q_INVOKABLE void saveJoystickSettings(void);

bool isInitialConnectComplete() const;
bool guidedModeSupported () const;
bool pauseVehicleSupported () const;
Expand Down Expand Up @@ -1031,11 +1034,9 @@ private slots:
void _gotProgressUpdate (float progressValue);

private:
void _loadSettings ();
void _activeVehicleAvailableChanged (bool isActiveVehicleAvailable);
void _loadJoystickSettings ();
void _activeVehicleChanged (Vehicle* newActiveVehicle);
void _saveSettings ();
void _startJoystick (bool start);
void _captureJoystick ();
void _handlePing (LinkInterface* link, mavlink_message_t& message);
void _handleHomePosition (mavlink_message_t& message);
void _handleHeartbeat (mavlink_message_t& message);
Expand Down
1 change: 1 addition & 0 deletions src/VehicleSetup/JoystickConfigController.cc
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,7 @@ void JoystickConfigController::_writeCalibration()
Vehicle* vehicle = qgcApp()->toolbox()->multiVehicleManager()->activeVehicle();
if (vehicle) {
vehicle->setJoystickEnabled(true);
vehicle->saveJoystickSettings();
}
}

Expand Down
5 changes: 4 additions & 1 deletion src/VehicleSetup/JoystickConfigGeneral.qml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,10 @@ Item {
QGCCheckBox {
id: enabledSwitch
enabled: _activeJoystick ? _activeJoystick.calibrated : false
onClicked: globals.activeVehicle.joystickEnabled = checked
onClicked: {
globals.activeVehicle.joystickEnabled = checked
globals.activeVehicle.saveJoystickSettings()
}
Component.onCompleted: {
checked = globals.activeVehicle.joystickEnabled
}
Expand Down

0 comments on commit 529925f

Please sign in to comment.