QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
MockLinkGimbal.h
Go to the documentation of this file.
1#pragma once
2
3#include "MAVLinkLib.h"
4
5#include <QtCore/QList>
6#include <QtCore/QMutex>
7
8#include <cmath>
9
10class MockLink;
11
28{
29public:
31 enum class DeltaYawMode {
32 Legacy,
33 Unknown,
34 Explicit,
35 };
36
39 float pitchDeg = NAN;
40 float yawDeg = NAN;
41 float pitchRateDegS = NAN;
42 float yawRateDegS = NAN;
43 uint32_t flags = 0;
44 uint8_t deviceId = 0;
45 int count = 0;
46 };
47
50 float pitchRateDegS = NAN;
51 float yawRateDegS = NAN;
52 uint32_t flags = 0;
53 int count = 0;
54 };
55
58 Accept,
59 Nack,
60 Silent,
61 };
62
63 explicit MockLinkGimbal(
64 MockLink *mockLink,
65 bool hasRollAxis = true,
66 bool hasPitchAxis = true,
67 bool hasYawAxis = true,
68 bool hasYawFollow = true,
69 bool hasYawLock = true,
70 bool hasRetract = true,
71 bool hasNeutral = true,
72 uint8_t gimbalDeviceId = MAV_COMP_ID_GIMBAL);
73 ~MockLinkGimbal() = default;
74
76 void run1HzTasks();
77
81
82 // Test APIs. All are safe to call from the test thread while the worker runs 1Hz tasks.
83
85 void setAttitudeDeg(float rollDeg, float pitchDeg, float yawDeg);
87 void setDeltaYawDeg(float deltaYawDeg);
90 void setYawInEarthFrame(bool earthFrame);
92 void setPrimaryControl(uint8_t sysid, uint8_t compid);
96
98 void sendGimbalManagerInformationWithDeviceId(uint8_t deviceIdField);
99 void sendGimbalManagerStatusWithDeviceId(uint8_t deviceIdField);
100 void sendGimbalDeviceAttitudeStatusFrom(uint8_t sourceCompid, uint8_t deviceIdField);
101
104 void setIgnoreStatusIntervalRequests(int count);
106 QList<int> statusIntervalRequests() const;
107
110 bool yawLock() const;
111 uint8_t gimbalDeviceId() const { return _gimbalDeviceId; }
112
113private:
116 bool _handleSetMessageInterval(const mavlink_command_long_t &request);
117
120 bool _handleRequestMessage(const mavlink_command_long_t &request);
121
124 bool _handleGimbalManagerPitchYaw(const mavlink_command_long_t &request);
125
128 bool _handleGimbalManagerConfigure(const mavlink_command_long_t &request, uint8_t senderSysid, uint8_t senderCompid);
129
130 void _handleGimbalManagerSetAttitude(const mavlink_message_t &msg);
131
132 void _sendGimbalManagerStatus();
133 void _sendGimbalManagerStatus(uint8_t deviceIdField);
134 void _sendGimbalDeviceAttitudeStatus();
135 void _sendGimbalDeviceAttitudeStatus(uint8_t sourceCompid, uint8_t deviceIdField);
136 void _sendGimbalManagerInformation();
137 void _sendGimbalManagerInformation(uint8_t deviceIdField);
138 void _sendGimbalDeviceInformation();
139 void _sendCommandAck(uint16_t command, uint8_t result, uint8_t sourceCompId);
140
142 static void _applyControlPair(float sysidValue, float compidValue, uint8_t senderSysid, uint8_t senderCompid,
143 uint8_t &targetSysid, uint8_t &targetCompid);
145 static void _applyControlField(float value, uint8_t senderValue, uint8_t &target);
146
148 uint8_t _attitudeSourceCompid() const { return (_gimbalDeviceId <= 6) ? static_cast<uint8_t>(MAV_COMP_ID_AUTOPILOT1) : _gimbalDeviceId; }
149 uint8_t _attitudeDeviceIdField() const { return (_gimbalDeviceId <= 6) ? _gimbalDeviceId : 0; }
150
151 static constexpr int kDefaultIntervalUs = 1000000; // 1 Hz default
152 static constexpr const char* kVendorName = "MockVendor";
153 static constexpr const char* kModelName = "MockGimbal";
154
155 MockLink *_mockLink = nullptr;
156 const uint8_t _gimbalDeviceId = MAV_COMP_ID_GIMBAL;
158 int _ignoreStatusIntervalRequests = 0;
159 QList<int> _statusIntervalRequests;
160 int _managerStatusIntervalUs = 0; // 0 = disabled
161 int _deviceAttitudeStatusIntervalUs = 0; // 0 = disabled by default
162 qint64 _managerStatusLastSentMs = 0;
163 qint64 _deviceAttitudeStatusLastSentMs = 0;
164
165 // Simulated gimbal attitude (degrees)
166 float _roll = 0.0f;
167 float _pitch = 0.0f;
168 float _yaw = 0.0f;
169 bool _manualControl = false; // true when under external control command
170 bool _yawLock = false;
171 bool _yawInEarthFrame = false;
172 DeltaYawMode _deltaYawMode = DeltaYawMode::Unknown;
173 float _deltaYawDeg = 0.0f;
174 PitchYawCommand _lastPitchYawCommand;
175 SetAttitudeCommand _lastSetAttitudeCommand;
180 mutable QMutex _stateMutex;
181
182 // Gimbal manager configuration
183 uint8_t _gimbalManagerSysidPrimary = 0; // System ID for primary control
184 uint8_t _gimbalManagerCompidPrimary = 0; // Component ID for primary control
185 uint8_t _gimbalManagerSysidSecondary = 0; // System ID for secondary control
186 uint8_t _gimbalManagerCompidSecondary = 0; // Component ID for secondary control
187
188 // Gimbal capability flags
189 bool _hasRollAxis = true;
190 bool _hasPitchAxis = true;
191 bool _hasYawAxis = true;
192 bool _hasYawFollow = true;
193 bool _hasYawLock = true;
194 bool _hasRetract = true;
195 bool _hasNeutral = true;
196};
struct __mavlink_message mavlink_message_t
struct __mavlink_command_long_t mavlink_command_long_t
Simulates MAVLink Gimbal Manager Protocol for MockLink.
DeltaYawMode
Controls how GIMBAL_DEVICE_ATTITUDE_STATUS.delta_yaw and the yaw frame flags are reported.
@ Legacy
No YAW_IN_*_FRAME flag, delta_yaw = 0 (pre-extension firmware wire image)
@ Unknown
Frame flag set, delta_yaw = NaN.
@ Explicit
Frame flag set, delta_yaw = value from setDeltaYawDeg()
void sendGimbalDeviceAttitudeStatusNow()
Sends GIMBAL_DEVICE_ATTITUDE_STATUS immediately instead of waiting for the 1Hz worker.
uint8_t gimbalDeviceId() const
SetAttitudeCommand lastSetAttitudeCommand() const
QList< int > statusIntervalRequests() const
Every GIMBAL_MANAGER_STATUS interval value (us) received, in order.
~MockLinkGimbal()=default
bool yawLock() const
void setDeltaYawDeg(float deltaYawDeg)
void setInformationResponse(InformationResponse response)
void sendGimbalManagerStatusWithDeviceId(uint8_t deviceIdField)
void run1HzTasks()
Send periodic gimbal status messages (call from 1Hz tasks)
void setPrimaryControl(uint8_t sysid, uint8_t compid)
Overrides who holds primary control as reported in GIMBAL_MANAGER_STATUS.
bool handleMavlinkMessage(const mavlink_message_t &msg)
void sendGimbalManagerInformationWithDeviceId(uint8_t deviceIdField)
Raw sends with protocol-violating field overrides, for exercising QGC's rejection paths.
void setDeltaYawMode(DeltaYawMode mode)
void setAttitudeDeg(float rollDeg, float pitchDeg, float yawDeg)
Pins gimbal attitude (degrees) and disables the automatic oscillation.
void setYawInEarthFrame(bool earthFrame)
void sendGimbalManagerStatusNow()
void setIgnoreStatusIntervalRequests(int count)
The first count MAV_CMD_SET_MESSAGE_INTERVAL requests for GIMBAL_MANAGER_STATUS are ACKed but not hon...
PitchYawCommand lastPitchYawCommand() const
InformationResponse
How the manager answers MAV_CMD_REQUEST_MESSAGE(GIMBAL_MANAGER_INFORMATION)
@ Silent
Swallow the request, no ACK, no message.
@ Nack
ACK with MAV_RESULT_UNSUPPORTED, no message.
@ Accept
ACK and send the message.
void sendGimbalDeviceAttitudeStatusFrom(uint8_t sourceCompid, uint8_t deviceIdField)
Last MAV_CMD_DO_GIMBAL_MANAGER_PITCHYAW received (angles in degrees, rates in deg/s)
Last GIMBAL_MANAGER_SET_ATTITUDE received (rates in deg/s)