QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
JoystickSDL.h
Go to the documentation of this file.
1#pragma once
2
3#include <atomic>
4
5#include <QtGui/QVector3D>
6
7#include "Joystick.h"
8
9struct SDL_Joystick;
11
12struct SDL_Gamepad;
13typedef struct SDL_Gamepad SDL_Gamepad;
14
15struct SDL_Haptic;
16typedef struct SDL_Haptic SDL_Haptic;
17
18class JoystickSDL : public Joystick
19{
20 Q_OBJECT
21
22#ifdef QGC_UNITTEST_BUILD
23 friend class JoystickTest;
24#endif
25 friend class MockJoystick;
26
27public:
28 explicit JoystickSDL(const QString &name, const QList<int> &gamepadAxes, const QList<int> &nonGamepadAxes, int buttonCount, int hatCount, int instanceId, QObject *parent = nullptr);
29 ~JoystickSDL() override;
30
31 // Instance management
32 int instanceId() const { return _instanceId; }
33 void setInstanceId(int instanceId) { _instanceId = instanceId; }
34 bool requiresCalibration() const override { return !isGamepad(); }
35
36 // Haptic and LED
37 bool hasRumble() const override;
38 bool hasRumbleTriggers() const override;
39 bool hasLED() const override;
40 void rumble(quint16 lowFreq, quint16 highFreq, quint32 durationMs) override;
41 void rumbleTriggers(quint16 left, quint16 right, quint32 durationMs) override;
42 void setLED(quint8 red, quint8 green, quint8 blue) override;
43 bool sendEffect(const QByteArray &data) override;
44
45 // Device identity
46 QString guid() const override;
47 quint16 vendorId() const override;
48 quint16 productId() const override;
49 QString serial() const override;
50 QString deviceType() const override;
51 QString path() const override;
52 bool isVirtual() const override;
53 quint16 firmwareVersion() const override;
54 QString connectionType() const override;
55
56 // Player info
57 int playerIndex() const override;
58 void setPlayerIndex(int index) override;
59
60 // Power and battery
61 int batteryPercent() const override;
62 QString powerState() const override;
63
64 // Gamepad type
65 bool isGamepad() const override;
66 QString gamepadType() const override;
67
68 // Control labels
69 QString axisLabel(int axis) const override;
70 QString buttonLabel(int button) const override;
71
72 // Mapping management
73 QString getMapping() const override;
74 bool addMapping(const QString &mapping) override;
75 QVariantMap getAxisBinding(int axis) const override;
76 QVariantMap getButtonBinding(int button) const override;
77
78 // Sensor support
79 bool hasGyroscope() const override;
80 bool hasAccelerometer() const override;
81 bool setGyroscopeEnabled(bool enabled) override;
82 bool setAccelerometerEnabled(bool enabled) override;
83 QVector3D gyroscopeData() const override;
84 QVector3D accelerometerData() const override;
85 float gyroscopeDataRate() const override;
86 float accelerometerDataRate() const override;
87
88 // Touchpad support
89 int touchpadCount() const override;
90 int touchpadFingerCount(int touchpad) const override;
91 QVariantMap getTouchpadFinger(int touchpad, int finger) const override;
92
93 // Trackball support
94 int ballCount() const override;
95 QVariantMap getBall(int ball) const override;
96
97 // Capability queries
98 bool hasButton(int button) const override;
99 bool hasAxis(int axis) const override;
100
101 // Real gamepad type (actual hardware vs mapped type)
102 QString realGamepadType() const override;
103
104 // Type-specific button labels
105 QString buttonLabelForType(int button) const override;
106
107 // Haptic/Force Feedback support
108 bool hasHaptic() const override;
109 int hapticEffectsCount() const override;
110 bool hapticRumbleSupported() const override;
111 [[nodiscard]] bool hapticRumbleInit() override;
112 bool hapticRumblePlay(float strength, quint32 durationMs) override;
113 void hapticRumbleStop() override;
114
115 // Mapping utilities
116 QString getMappingForGUID(const QString &guid) const override;
117
118 // Virtual joystick control
119 bool setVirtualAxis(int axis, int value) override;
120 bool setVirtualButton(int button, bool down) override;
121 bool setVirtualHat(int hat, quint8 value) override;
122 bool setVirtualBall(int ball, int dx, int dy) override;
123 bool setVirtualTouchpad(int touchpad, int finger, bool down, float x, float y, float pressure) override;
124 bool sendVirtualSensorData(int sensorType, float x, float y, float z) override;
125
126 // Properties/Capability detection
127 bool hasMonoLED() const override;
128 bool hasRGBLED() const override;
129 bool hasPlayerLED() const override;
130
131 // Connection state
132 QString connectionState() const override;
133
134 // Initial axis state (for drift detection)
135 QVariantMap getAxisInitialState(int axis) const override;
136
137 // Per-device custom mapping
138 bool setMapping(const QString &mapping) override;
139
140 [[nodiscard]] static bool init();
141 static void shutdown(bool deleteDiscoveryCache = true);
142 static QMap<QString, Joystick*> discover();
143
144private:
145 [[nodiscard]] bool _open() final;
146 void _close() final;
147 bool _update() final;
148
149 bool _getButton(int idx) const final;
150 int _getAxisValue(int idx) const final;
151 bool _getHat(int hat, int idx) const final;
152
153 quint64 _getProperties() const;
154 bool _checkVirtualJoystick(const char *methodName) const;
155 bool _hasGamepadCapability(const char *propertyName) const;
156
157 QList<int> _gamepadAxes;
158 QList<int> _nonGamepadAxes;
159 int _instanceId = -1;
160
161 SDL_Joystick *_sdlJoystick = nullptr;
162 SDL_Gamepad *_sdlGamepad = nullptr;
163 SDL_Haptic *_sdlHaptic = nullptr;
164
165 // Cached sensor data (updated from events)
166 // Note: These are accessed from main thread only (via Qt::QueuedConnection)
167 // but marked atomic for defensive thread safety
168 QVector3D _cachedGyroData;
169 QVector3D _cachedAccelData;
170 std::atomic<bool> _gyroDataCached{false};
171 std::atomic<bool> _accelDataCached{false};
172
173 // Connection state tracking
174 QString _lastConnectionState;
175
176 // Axis drift detection
177 QVector<int> _initialAxisValues;
178 bool _driftWarningEmitted = false;
179
180public:
181 // Called by JoystickManager when sensor events are received
182 void updateCachedGyroData(const QVector3D &data);
183 void updateCachedAccelData(const QVector3D &data);
185
188 Q_INVOKABLE QVariantList detectAxisDrift(int threshold = 8000) const;
189
190signals:
192 void axisDriftDetected(const QVariantList &driftingAxes);
193};
struct SDL_Gamepad SDL_Gamepad
Definition JoystickSDL.h:13
struct SDL_Joystick SDL_Joystick
Definition JoystickSDL.h:10
struct SDL_Haptic SDL_Haptic
Definition JoystickSDL.h:16
QString getMapping() const override
QString powerState() const override
bool isVirtual() const override
int batteryPercent() const override
quint16 vendorId() const override
QVariantMap getTouchpadFinger(int touchpad, int finger) const override
bool addMapping(const QString &mapping) override
QVariantMap getButtonBinding(int button) const override
void rumbleTriggers(quint16 left, quint16 right, quint32 durationMs) override
bool setVirtualButton(int button, bool down) override
QString serial() const override
bool setMapping(const QString &mapping) override
void updateCachedGyroData(const QVector3D &data)
bool setVirtualTouchpad(int touchpad, int finger, bool down, float x, float y, float pressure) override
QVector3D gyroscopeData() const override
void checkConnectionStateChanged()
bool hasAxis(int axis) const override
friend class MockJoystick
Definition JoystickSDL.h:25
bool hasPlayerLED() const override
int playerIndex() const override
bool setVirtualHat(int hat, quint8 value) override
static void shutdown(bool deleteDiscoveryCache=true)
QString deviceType() const override
QString realGamepadType() const override
QVariantMap getBall(int ball) const override
void setPlayerIndex(int index) override
QVariantMap getAxisInitialState(int axis) const override
bool hasGyroscope() const override
bool hasMonoLED() const override
void axisDriftDetected(const QVariantList &driftingAxes)
Emitted when significant axis drift is detected on open.
~JoystickSDL() override
quint16 productId() const override
bool setAccelerometerEnabled(bool enabled) override
QString gamepadType() const override
void rumble(quint16 lowFreq, quint16 highFreq, quint32 durationMs) override
bool setVirtualBall(int ball, int dx, int dy) override
QString axisLabel(int axis) const override
QString getMappingForGUID(const QString &guid) const override
bool setVirtualAxis(int axis, int value) override
static bool init()
static QMap< QString, Joystick * > discover()
bool requiresCalibration() const override
Definition JoystickSDL.h:34
int ballCount() const override
void hapticRumbleStop() override
Q_INVOKABLE QVariantList detectAxisDrift(int threshold=8000) const
bool hasAccelerometer() const override
bool hasRumble() const override
void updateCachedAccelData(const QVector3D &data)
bool hapticRumblePlay(float strength, quint32 durationMs) override
QString buttonLabel(int button) const override
QVector3D accelerometerData() const override
QString connectionState() const override
QString buttonLabelForType(int button) const override
QVariantMap getAxisBinding(int axis) const override
QString connectionType() const override
bool hasButton(int button) const override
QString path() const override
int instanceId() const
Definition JoystickSDL.h:32
void setInstanceId(int instanceId)
Definition JoystickSDL.h:33
QString guid() const override
bool isGamepad() const override
bool hasRumbleTriggers() const override
bool sendVirtualSensorData(int sensorType, float x, float y, float z) override
void setLED(quint8 red, quint8 green, quint8 blue) override
float gyroscopeDataRate() const override
float accelerometerDataRate() const override
bool hasRGBLED() const override
bool hasLED() const override
bool hasHaptic() const override
bool hapticRumbleSupported() const override
bool sendEffect(const QByteArray &data) override
quint16 firmwareVersion() const override
int hapticEffectsCount() const override
int touchpadCount() const override
int touchpadFingerCount(int touchpad) const override
bool hapticRumbleInit() override
bool setGyroscopeEnabled(bool enabled) override
QString name() const
Definition Joystick.h:205
int buttonCount() const
Definition Joystick.h:206