QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
SensorsComponentController.cc
Go to the documentation of this file.
2#include "AppMessages.h"
3#include "ParameterManager.h"
4#include "Vehicle.h"
7
8QGC_LOGGING_CATEGORY(SensorsComponentControllerLog, "AutoPilotPlugins.SensorsComponentController")
9
11 : _statusLog (nullptr)
12 , _progressBar (nullptr)
13 , _showOrientationCalArea (false)
14 , _gyroCalInProgress (false)
15 , _magCalInProgress (false)
16 , _accelCalInProgress (false)
17 , _airspeedCalInProgress (false)
18 , _levelCalInProgress (false)
19 , _orientationCalDownSideVisible (false)
20 , _orientationCalUpsideDownSideVisible (false)
21 , _orientationCalLeftSideVisible (false)
22 , _orientationCalRightSideVisible (false)
23 , _orientationCalNoseDownSideVisible (false)
24 , _orientationCalTailDownSideVisible (false)
25 , _orientationCalDownSideState (SideCalStateIdle)
26 , _orientationCalUpsideDownSideState (SideCalStateIdle)
27 , _orientationCalLeftSideState (SideCalStateIdle)
28 , _orientationCalRightSideState (SideCalStateIdle)
29 , _orientationCalNoseDownSideState (SideCalStateIdle)
30 , _orientationCalTailDownSideState (SideCalStateIdle)
31 , _unknownFirmwareVersion (false)
32 , _waitingForCancel (false)
33{
34 connect(_vehicle, &Vehicle::sensorsParametersResetAck, this, &SensorsComponentController::_handleParametersReset);
35
36}
37
39{
41 if (sharedLink) {
42 return sharedLink->linkConfiguration()->type() == LinkConfiguration::TypeUdp;
43 } else {
44 return false;
45 }
46}
47
49void SensorsComponentController::_appendStatusLog(const QString& text)
50{
51 if (!_statusLog) {
52 qWarning() << "Internal error";
53 return;
54 }
55
56 QString varText = text;
57 QMetaObject::invokeMethod(_statusLog,
58 "append",
59 Q_ARG(QString, varText));
60}
61
62void SensorsComponentController::_startLogCalibration(void)
63{
64 _unknownFirmwareVersion = false;
65 _hideAllCalAreas();
66
67 connect(_vehicle, &Vehicle::textMessageReceived, this, &SensorsComponentController::_handleUASTextMessage);
68}
69
70void SensorsComponentController::_startVisualCalibration(void)
71{
72 _setAllSidesState(SideCalStateIncomplete);
73
74 _progressBar->setProperty("value", 0);
75}
76
81{
82 if (calibrationActive()) {
83 return;
84 }
85 _setAllSidesState(SideCalStateIdle);
86}
87
88void SensorsComponentController::_setAllSidesState(SideCalState state)
89{
90 _orientationCalDownSideState = state;
91 _orientationCalUpsideDownSideState = state;
92 _orientationCalLeftSideState = state;
93 _orientationCalRightSideState = state;
94 _orientationCalTailDownSideState = state;
95 _orientationCalNoseDownSideState = state;
96
98}
99
100void SensorsComponentController::_stopCalibration(SensorsComponentController::StopCalibrationCode code)
101{
102 disconnect(_vehicle, &Vehicle::textMessageReceived, this, &SensorsComponentController::_handleUASTextMessage);
103
104 if (code == StopCalibrationSuccess) {
105 _setAllSidesState(SideCalStateCompleted);
106
107 _progressBar->setProperty("value", 1);
108 } else {
109 // Calibration results are discarded: return any partially completed sides
110 // to the neutral idle preview state
111 _setAllSidesState(SideCalStateIdle);
112
113 _progressBar->setProperty("value", 0);
114 }
115
116 _waitingForCancel = false;
118
119 _refreshParams();
120
121 switch (code) {
122 case StopCalibrationSuccess:
123 _orientationCalAreaHelpText->setProperty("text", tr("Calibration complete"));
124 if (!_airspeedCalInProgress && !_levelCalInProgress) {
125 emit resetStatusTextArea();
126 }
127 if (_magCalInProgress) {
129 emit magCalComplete();
130 }
131 break;
132
133 case StopCalibrationCancelled:
134 emit resetStatusTextArea();
135 _hideAllCalAreas();
136 break;
137
138 default:
139 // Assume failed
140 _hideAllCalAreas();
141 QGC::showAppMessage(tr("Calibration failed. Calibration log will be displayed."));
142 break;
143 }
144
145 _magCalInProgress = false;
146 _accelCalInProgress = false;
147 _gyroCalInProgress = false;
148 _airspeedCalInProgress = false;
149 _levelCalInProgress = false;
150
152}
153
159
165
171
177
183
184void SensorsComponentController::_handleUASTextMessage(int uasId, int compId, int severity, QString text, const QString &description)
185{
186 Q_UNUSED(compId);
187 Q_UNUSED(severity);
188 Q_UNUSED(description);
189
190 if (uasId != _vehicle->id()) {
191 return;
192 }
193
194 // Needed for level horizon calibration
195 text.replace("&lt;", "<");
196 text.replace("&gt;", ">");
197
198 if (text.contains("progress <")) {
199 QString percent = text.split("<").last().split(">").first();
200 bool ok;
201 int p = percent.toInt(&ok);
202 if (ok) {
203 if (_progressBar) {
204 _progressBar->setProperty("value", (float)(p / 100.0));
205 } else {
206 qWarning() << "Internal error";
207 }
208 }
209 return;
210 }
211
212 _appendStatusLog(text);
213 qCDebug(SensorsComponentControllerLog) << text;
214
215 if (_unknownFirmwareVersion) {
216 // We don't know how to do visual cal with the version of firwmare
217 return;
218 }
219
220 // All calibration messages start with [cal]
221 QString calPrefix("[cal] ");
222 if (!text.startsWith(calPrefix)) {
223 return;
224 }
225 text = text.right(text.length() - calPrefix.length());
226
227 QString calStartPrefix("calibration started: ");
228 if (text.startsWith(calStartPrefix)) {
229 text = text.right(text.length() - calStartPrefix.length());
230
231 // Split version number and cal type
232 QStringList parts = text.split(" ");
233 if (parts.count() != 2 && parts[0].toInt() != _supportedFirmwareCalVersion) {
234 _unknownFirmwareVersion = true;
235 QString msg = tr("Unsupported calibration firmware version, using log");
236 _appendStatusLog(msg);
237 qDebug() << msg;
238 return;
239 }
240
241 _startVisualCalibration();
242
243 text = parts[1];
244 if (text == "accel" || text == "mag" || text == "gyro") {
245 // _startVisualCalibration() above reset all side indicators to Incomplete
246
247 // Reset all visibility
248 _orientationCalDownSideVisible = false;
249 _orientationCalUpsideDownSideVisible = false;
250 _orientationCalLeftSideVisible = false;
251 _orientationCalRightSideVisible = false;
252 _orientationCalTailDownSideVisible = false;
253 _orientationCalNoseDownSideVisible = false;
254
255 _orientationCalAreaHelpText->setProperty("text", tr("Place your vehicle into one of the Incomplete orientations shown below and hold it still"));
256
257 if (text == "accel") {
258 _accelCalInProgress = true;
259 _orientationCalDownSideVisible = true;
260 _orientationCalUpsideDownSideVisible = true;
261 _orientationCalLeftSideVisible = true;
262 _orientationCalRightSideVisible = true;
263 _orientationCalTailDownSideVisible = true;
264 _orientationCalNoseDownSideVisible = true;
265 } else if (text == "mag") {
266
267 // Work out what the autopilot is configured to
268 int sides = 0;
269
271 // Read the requested calibration directions off the system
273 } else {
274 // There is no valid setting, default to all six sides
275 sides = (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2) | (1 << 1) | (1 << 0);
276 }
277
278 _magCalInProgress = true;
279 _orientationCalTailDownSideVisible = ((sides & (1 << 0)) > 0);
280 _orientationCalNoseDownSideVisible = ((sides & (1 << 1)) > 0);
281 _orientationCalLeftSideVisible = ((sides & (1 << 2)) > 0);
282 _orientationCalRightSideVisible = ((sides & (1 << 3)) > 0);
283 _orientationCalUpsideDownSideVisible = ((sides & (1 << 4)) > 0);
284 _orientationCalDownSideVisible = ((sides & (1 << 5)) > 0);
285 } else if (text == "gyro") {
286 _gyroCalInProgress = true;
287 _orientationCalDownSideVisible = true;
288 } else {
289 qWarning() << "Unknown calibration message type" << text;
290 }
292 _updateAndEmitShowOrientationCalArea(true);
293 } else if (text == "airspeed") {
294 _airspeedCalInProgress = true;
295 } else if (text == "level") {
296 _levelCalInProgress = true;
297 }
299 return;
300 }
301
302 if (text.endsWith("orientation detected")) {
303 QString side = text.section(" ", 0, 0);
304 qCDebug(SensorsComponentControllerLog) << "Side started" << side;
305
306 if (side == "down") {
307 _orientationCalDownSideState = SideCalStateInProgress;
308 } else if (side == "up") {
309 _orientationCalUpsideDownSideState = SideCalStateInProgress;
310 } else if (side == "left") {
311 _orientationCalLeftSideState = SideCalStateInProgress;
312 } else if (side == "right") {
313 _orientationCalRightSideState = SideCalStateInProgress;
314 } else if (side == "front") {
315 _orientationCalNoseDownSideState = SideCalStateInProgress;
316 } else if (side == "back") {
317 _orientationCalTailDownSideState = SideCalStateInProgress;
318 }
319
320 if (_magCalInProgress) {
321 _orientationCalAreaHelpText->setProperty("text", tr("Rotate the vehicle continuously as shown in the diagram until marked as Completed"));
322 } else {
323 _orientationCalAreaHelpText->setProperty("text", tr("Hold still in the current orientation"));
324 }
325
327 return;
328 }
329
330 if (text.endsWith("side done, rotate to a different side")) {
331 QString side = text.section(" ", 0, 0);
332 qCDebug(SensorsComponentControllerLog) << "Side finished" << side;
333
334 if (side == "down") {
335 _orientationCalDownSideState = SideCalStateCompleted;
336 } else if (side == "up") {
337 _orientationCalUpsideDownSideState = SideCalStateCompleted;
338 } else if (side == "left") {
339 _orientationCalLeftSideState = SideCalStateCompleted;
340 } else if (side == "right") {
341 _orientationCalRightSideState = SideCalStateCompleted;
342 } else if (side == "front") {
343 _orientationCalNoseDownSideState = SideCalStateCompleted;
344 } else if (side == "back") {
345 _orientationCalTailDownSideState = SideCalStateCompleted;
346 }
347
348 _orientationCalAreaHelpText->setProperty("text", tr("Place you vehicle into one of the orientations shown below and hold it still"));
349
351 return;
352 }
353
354 if (text.endsWith("side already completed")) {
355 _orientationCalAreaHelpText->setProperty("text", tr("Orientation already completed, place you vehicle into one of the incomplete orientations shown below and hold it still"));
356 return;
357 }
358
359 QString calCompletePrefix("calibration done:");
360 if (text.startsWith(calCompletePrefix)) {
361 _stopCalibration(StopCalibrationSuccess);
362 return;
363 }
364
365 if (text.startsWith("calibration cancelled")) {
366 _stopCalibration(_waitingForCancel ? StopCalibrationCancelled : StopCalibrationFailed);
367 return;
368 }
369
370 if (text.startsWith("calibration failed")) {
371 _stopCalibration(StopCalibrationFailed);
372 return;
373 }
374}
375
376void SensorsComponentController::_refreshParams(void)
377{
379 QStringLiteral("CAL_MAG0_ID"), QStringLiteral("CAL_MAG1_ID"), QStringLiteral("CAL_MAG2_ID"),
380 QStringLiteral("CAL_MAG0_ROT"), QStringLiteral("CAL_MAG1_ROT"), QStringLiteral("CAL_MAG2_ROT"),
381 QStringLiteral("CAL_*"),
382 QStringLiteral("SENS_*"),
383 }, false /* notifyFailure */);
384}
385
386void SensorsComponentController::_updateAndEmitShowOrientationCalArea(bool show)
387{
388 _showOrientationCalArea = show;
390}
391
392void SensorsComponentController::_hideAllCalAreas(void)
393{
394 _updateAndEmitShowOrientationCalArea(false);
395}
396
398{
399 // The firmware doesn't allow us to cancel calibration. The best we can do is wait
400 // for it to timeout.
401 _waitingForCancel = true;
403 _vehicle->stopCalibration(true /* showError */);
404}
405
406void SensorsComponentController::_handleParametersReset(bool success)
407{
408 if (success) {
409 QGC::showAppMessage(tr("Reset successful"));
410
411 QTimer::singleShot(1000, this, [this]() {
412 _refreshParams();
413 });
414 }
415 else {
416 QGC::showAppMessage(tr("Reset failed"));
417 }
418}
419
421{
422 auto compId = _vehicle->defaultComponentId();
423
424 _vehicle->sendMavCommand(compId,
425 MAV_CMD_PREFLIGHT_STORAGE,
426 true, // showError
427 3, // Reset factory parameters
428 -1); // Don't do anything with mission storage
429}
std::shared_ptr< LinkInterface > SharedLinkInterfacePtr
#define QGC_LOGGING_CATEGORY(name, categoryStr)
QVariant rawValue() const
Definition Fact.h:87
bool parameterExists(int componentId, const QString &paramName) const
Fact * getParameter(int componentId, const QString &paramName)
void bulkRefresh(int componentId, const QStringList &names, bool notifyFailure=true)
static constexpr int defaultComponentId
Sensors Component MVC Controller for SensorsComponent.qml.
void orientationCalSidesVisibleChanged(void)
void waitingForCancelChanged(void)
@ SideCalStateIncomplete
Calibration running, side not yet calibrated.
@ SideCalStateInProgress
Side actively being calibrated.
@ SideCalStateIdle
No calibration data to show (neutral preview)
@ SideCalStateCompleted
Side calibration complete.
void orientationCalSidesStateChanged(void)
void calibrationActiveChanged(void)
void showOrientationCalAreaChanged(void)
WeakLinkInterfacePtr primaryLink() const
void sendMavCommand(int compId, MAV_CMD command, bool showError, float param1=0.0f, float param2=0.0f, float param3=0.0f, float param4=0.0f, float param5=0.0f, float param6=0.0f, float param7=0.0f)
Definition Vehicle.cc:2173
void textMessageReceived(int sysid, int componentid, int severity, QString text, QString description)
VehicleLinkManager * vehicleLinkManager()
Definition Vehicle.h:597
void sensorsParametersResetAck(bool success)
void setRebootRequired()
Latches rebootRequired until the vehicle reboots.
Definition Vehicle.cc:2355
int id() const
Definition Vehicle.h:443
int defaultComponentId() const
Definition Vehicle.h:700
ParameterManager * parameterManager()
Definition Vehicle.h:595
void startCalibration(QGCMAVLink::CalibrationType calType)
Definition Vehicle.cc:2408
void stopCalibration(bool showError)
Definition Vehicle.cc:2488
void showAppMessage(const QString &message, const QString &title)
Modal application message. Queued if the UI isn't ready yet.
Definition AppMessages.cc:9