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