Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework Vehicle Joystick Handling #10758

Merged
merged 1 commit into from
Aug 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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()) {
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