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 , _orientationCalDownSideDone (false)
20 , _orientationCalUpsideDownSideDone (false)
21 , _orientationCalLeftSideDone (false)
22 , _orientationCalRightSideDone (false)
23 , _orientationCalNoseDownSideDone (false)
24 , _orientationCalTailDownSideDone (false)
25 , _orientationCalDownSideVisible (false)
26 , _orientationCalUpsideDownSideVisible (false)
27 , _orientationCalLeftSideVisible (false)
28 , _orientationCalRightSideVisible (false)
29 , _orientationCalNoseDownSideVisible (false)
30 , _orientationCalTailDownSideVisible (false)
31 , _orientationCalDownSideInProgress (false)
32 , _orientationCalUpsideDownSideInProgress (false)
33 , _orientationCalLeftSideInProgress (false)
34 , _orientationCalRightSideInProgress (false)
35 , _orientationCalNoseDownSideInProgress (false)
36 , _orientationCalTailDownSideInProgress (false)
37 , _orientationCalDownSideRotate (false)
38 , _orientationCalUpsideDownSideRotate (false)
39 , _orientationCalLeftSideRotate (false)
40 , _orientationCalRightSideRotate (false)
41 , _orientationCalNoseDownSideRotate (false)
42 , _orientationCalTailDownSideRotate (false)
43 , _unknownFirmwareVersion (false)
44 , _waitingForCancel (false)
45{
46 connect(_vehicle, &Vehicle::sensorsParametersResetAck, this, &SensorsComponentController::_handleParametersReset);
47
48}
49
51{
53 if (sharedLink) {
54 return sharedLink->linkConfiguration()->type() == LinkConfiguration::TypeUdp;
55 } else {
56 return false;
57 }
58}
59
61void SensorsComponentController::_appendStatusLog(const QString& text)
62{
63 if (!_statusLog) {
64 qWarning() << "Internal error";
65 return;
66 }
67
68 QString varText = text;
69 QMetaObject::invokeMethod(_statusLog,
70 "append",
71 Q_ARG(QString, varText));
72}
73
74void SensorsComponentController::_startLogCalibration(void)
75{
76 _unknownFirmwareVersion = false;
77 _hideAllCalAreas();
78
79 connect(_vehicle, &Vehicle::textMessageReceived, this, &SensorsComponentController::_handleUASTextMessage);
80}
81
82void SensorsComponentController::_startVisualCalibration(void)
83{
84 _resetInternalState();
85
86 _progressBar->setProperty("value", 0);
87}
88
89void SensorsComponentController::_resetInternalState(void)
90{
91 _orientationCalDownSideDone = true;
92 _orientationCalUpsideDownSideDone = true;
93 _orientationCalLeftSideDone = true;
94 _orientationCalRightSideDone = true;
95 _orientationCalTailDownSideDone = true;
96 _orientationCalNoseDownSideDone = true;
97 _orientationCalDownSideInProgress = false;
98 _orientationCalUpsideDownSideInProgress = false;
99 _orientationCalLeftSideInProgress = false;
100 _orientationCalRightSideInProgress = false;
101 _orientationCalNoseDownSideInProgress = false;
102 _orientationCalTailDownSideInProgress = false;
103 _orientationCalDownSideRotate = false;
104 _orientationCalUpsideDownSideRotate = false;
105 _orientationCalLeftSideRotate = false;
106 _orientationCalRightSideRotate = false;
107 _orientationCalNoseDownSideRotate = false;
108 _orientationCalTailDownSideRotate = false;
109
113}
114
115void SensorsComponentController::_stopCalibration(SensorsComponentController::StopCalibrationCode code)
116{
117 disconnect(_vehicle, &Vehicle::textMessageReceived, this, &SensorsComponentController::_handleUASTextMessage);
118
119 if (code == StopCalibrationSuccess) {
120 _resetInternalState();
121
122 _progressBar->setProperty("value", 1);
123 } else {
124 _progressBar->setProperty("value", 0);
125 }
126
127 _waitingForCancel = false;
129
130 _refreshParams();
131
132 switch (code) {
133 case StopCalibrationSuccess:
134 _orientationCalAreaHelpText->setProperty("text", tr("Calibration complete"));
135 if (!_airspeedCalInProgress && !_levelCalInProgress) {
136 emit resetStatusTextArea();
137 }
138 if (_magCalInProgress) {
139 emit magCalComplete();
140 }
141 break;
142
143 case StopCalibrationCancelled:
144 emit resetStatusTextArea();
145 _hideAllCalAreas();
146 break;
147
148 default:
149 // Assume failed
150 _hideAllCalAreas();
151 QGC::showAppMessage(tr("Calibration failed. Calibration log will be displayed."));
152 break;
153 }
154
155 _magCalInProgress = false;
156 _accelCalInProgress = false;
157 _gyroCalInProgress = false;
158 _airspeedCalInProgress = false;
159 _levelCalInProgress = false;
160
162}
163
169
175
181
187
193
194void SensorsComponentController::_handleUASTextMessage(int uasId, int compId, int severity, QString text, const QString &description)
195{
196 Q_UNUSED(compId);
197 Q_UNUSED(severity);
198 Q_UNUSED(description);
199
200 if (uasId != _vehicle->id()) {
201 return;
202 }
203
204 // Needed for level horizon calibration
205 text.replace("&lt;", "<");
206 text.replace("&gt;", ">");
207
208 if (text.contains("progress <")) {
209 QString percent = text.split("<").last().split(">").first();
210 bool ok;
211 int p = percent.toInt(&ok);
212 if (ok) {
213 if (_progressBar) {
214 _progressBar->setProperty("value", (float)(p / 100.0));
215 } else {
216 qWarning() << "Internal error";
217 }
218 }
219 return;
220 }
221
222 _appendStatusLog(text);
223 qCDebug(SensorsComponentControllerLog) << text;
224
225 if (_unknownFirmwareVersion) {
226 // We don't know how to do visual cal with the version of firwmare
227 return;
228 }
229
230 // All calibration messages start with [cal]
231 QString calPrefix("[cal] ");
232 if (!text.startsWith(calPrefix)) {
233 return;
234 }
235 text = text.right(text.length() - calPrefix.length());
236
237 QString calStartPrefix("calibration started: ");
238 if (text.startsWith(calStartPrefix)) {
239 text = text.right(text.length() - calStartPrefix.length());
240
241 // Split version number and cal type
242 QStringList parts = text.split(" ");
243 if (parts.count() != 2 && parts[0].toInt() != _supportedFirmwareCalVersion) {
244 _unknownFirmwareVersion = true;
245 QString msg = tr("Unsupported calibration firmware version, using log");
246 _appendStatusLog(msg);
247 qDebug() << msg;
248 return;
249 }
250
251 _startVisualCalibration();
252
253 text = parts[1];
254 if (text == "accel" || text == "mag" || text == "gyro") {
255 // Reset all progress indication
256 _orientationCalDownSideDone = false;
257 _orientationCalUpsideDownSideDone = false;
258 _orientationCalLeftSideDone = false;
259 _orientationCalRightSideDone = false;
260 _orientationCalTailDownSideDone = false;
261 _orientationCalNoseDownSideDone = false;
262 _orientationCalDownSideInProgress = false;
263 _orientationCalUpsideDownSideInProgress = false;
264 _orientationCalLeftSideInProgress = false;
265 _orientationCalRightSideInProgress = false;
266 _orientationCalNoseDownSideInProgress = false;
267 _orientationCalTailDownSideInProgress = false;
268
269 // Reset all visibility
270 _orientationCalDownSideVisible = false;
271 _orientationCalUpsideDownSideVisible = false;
272 _orientationCalLeftSideVisible = false;
273 _orientationCalRightSideVisible = false;
274 _orientationCalTailDownSideVisible = false;
275 _orientationCalNoseDownSideVisible = false;
276
277 _orientationCalAreaHelpText->setProperty("text", tr("Place your vehicle into one of the Incomplete orientations shown below and hold it still"));
278
279 if (text == "accel") {
280 _accelCalInProgress = true;
281 _orientationCalDownSideVisible = true;
282 _orientationCalUpsideDownSideVisible = true;
283 _orientationCalLeftSideVisible = true;
284 _orientationCalRightSideVisible = true;
285 _orientationCalTailDownSideVisible = true;
286 _orientationCalNoseDownSideVisible = true;
287 } else if (text == "mag") {
288
289 // Work out what the autopilot is configured to
290 int sides = 0;
291
293 // Read the requested calibration directions off the system
295 } else {
296 // There is no valid setting, default to all six sides
297 sides = (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2) | (1 << 1) | (1 << 0);
298 }
299
300 _magCalInProgress = true;
301 _orientationCalTailDownSideVisible = ((sides & (1 << 0)) > 0);
302 _orientationCalNoseDownSideVisible = ((sides & (1 << 1)) > 0);
303 _orientationCalLeftSideVisible = ((sides & (1 << 2)) > 0);
304 _orientationCalRightSideVisible = ((sides & (1 << 3)) > 0);
305 _orientationCalUpsideDownSideVisible = ((sides & (1 << 4)) > 0);
306 _orientationCalDownSideVisible = ((sides & (1 << 5)) > 0);
307 } else if (text == "gyro") {
308 _gyroCalInProgress = true;
309 _orientationCalDownSideVisible = true;
310 } else {
311 qWarning() << "Unknown calibration message type" << text;
312 }
316 _updateAndEmitShowOrientationCalArea(true);
317 } else if (text == "airspeed") {
318 _airspeedCalInProgress = true;
319 } else if (text == "level") {
320 _levelCalInProgress = true;
321 }
323 return;
324 }
325
326 if (text.endsWith("orientation detected")) {
327 QString side = text.section(" ", 0, 0);
328 qCDebug(SensorsComponentControllerLog) << "Side started" << side;
329
330 if (side == "down") {
331 _orientationCalDownSideInProgress = true;
332 if (_magCalInProgress) {
333 _orientationCalDownSideRotate = true;
334 }
335 } else if (side == "up") {
336 _orientationCalUpsideDownSideInProgress = true;
337 if (_magCalInProgress) {
338 _orientationCalUpsideDownSideRotate = true;
339 }
340 } else if (side == "left") {
341 _orientationCalLeftSideInProgress = true;
342 if (_magCalInProgress) {
343 _orientationCalLeftSideRotate = true;
344 }
345 } else if (side == "right") {
346 _orientationCalRightSideInProgress = true;
347 if (_magCalInProgress) {
348 _orientationCalRightSideRotate = true;
349 }
350 } else if (side == "front") {
351 _orientationCalNoseDownSideInProgress = true;
352 if (_magCalInProgress) {
353 _orientationCalNoseDownSideRotate = true;
354 }
355 } else if (side == "back") {
356 _orientationCalTailDownSideInProgress = true;
357 if (_magCalInProgress) {
358 _orientationCalTailDownSideRotate = true;
359 }
360 }
361
362 if (_magCalInProgress) {
363 _orientationCalAreaHelpText->setProperty("text", tr("Rotate the vehicle continuously as shown in the diagram until marked as Completed"));
364 } else {
365 _orientationCalAreaHelpText->setProperty("text", tr("Hold still in the current orientation"));
366 }
367
370 return;
371 }
372
373 if (text.endsWith("side done, rotate to a different side")) {
374 QString side = text.section(" ", 0, 0);
375 qCDebug(SensorsComponentControllerLog) << "Side finished" << side;
376
377 if (side == "down") {
378 _orientationCalDownSideInProgress = false;
379 _orientationCalDownSideDone = true;
380 _orientationCalDownSideRotate = false;
381 } else if (side == "up") {
382 _orientationCalUpsideDownSideInProgress = false;
383 _orientationCalUpsideDownSideDone = true;
384 _orientationCalUpsideDownSideRotate = false;
385 } else if (side == "left") {
386 _orientationCalLeftSideInProgress = false;
387 _orientationCalLeftSideDone = true;
388 _orientationCalLeftSideRotate = false;
389 } else if (side == "right") {
390 _orientationCalRightSideInProgress = false;
391 _orientationCalRightSideDone = true;
392 _orientationCalRightSideRotate = false;
393 } else if (side == "front") {
394 _orientationCalNoseDownSideInProgress = false;
395 _orientationCalNoseDownSideDone = true;
396 _orientationCalNoseDownSideRotate = false;
397 } else if (side == "back") {
398 _orientationCalTailDownSideInProgress = false;
399 _orientationCalTailDownSideDone = true;
400 _orientationCalTailDownSideRotate = false;
401 }
402
403 _orientationCalAreaHelpText->setProperty("text", tr("Place you vehicle into one of the orientations shown below and hold it still"));
404
408 return;
409 }
410
411 if (text.endsWith("side already completed")) {
412 _orientationCalAreaHelpText->setProperty("text", tr("Orientation already completed, place you vehicle into one of the incomplete orientations shown below and hold it still"));
413 return;
414 }
415
416 QString calCompletePrefix("calibration done:");
417 if (text.startsWith(calCompletePrefix)) {
418 _stopCalibration(StopCalibrationSuccess);
419 return;
420 }
421
422 if (text.startsWith("calibration cancelled")) {
423 _stopCalibration(_waitingForCancel ? StopCalibrationCancelled : StopCalibrationFailed);
424 return;
425 }
426
427 if (text.startsWith("calibration failed")) {
428 _stopCalibration(StopCalibrationFailed);
429 return;
430 }
431}
432
433void SensorsComponentController::_refreshParams(void)
434{
435 QStringList fastRefreshList;
436
437 // We ask for a refresh on these first so that the rotation combo show up as fast as possible
438 fastRefreshList << "CAL_MAG0_ID" << "CAL_MAG1_ID" << "CAL_MAG2_ID" << "CAL_MAG0_ROT" << "CAL_MAG1_ROT" << "CAL_MAG2_ROT";
439 for (const QString &paramName : std::as_const(fastRefreshList)) {
441 }
442
443 // Now ask for all to refresh
446}
447
448void SensorsComponentController::_updateAndEmitShowOrientationCalArea(bool show)
449{
450 _showOrientationCalArea = show;
452}
453
454void SensorsComponentController::_hideAllCalAreas(void)
455{
456 _updateAndEmitShowOrientationCalArea(false);
457}
458
460{
461 // The firmware doesn't allow us to cancel calibration. The best we can do is wait
462 // for it to timeout.
463 _waitingForCancel = true;
465 _vehicle->stopCalibration(true /* showError */);
466}
467
468void SensorsComponentController::_handleParametersReset(bool success)
469{
470 if (success) {
471 QGC::showAppMessage(tr("Reset successful"));
472
473 QTimer::singleShot(1000, this, [this]() {
474 _refreshParams();
475 });
476 }
477 else {
478 QGC::showAppMessage(tr("Reset failed"));
479 }
480}
481
483{
484 auto compId = _vehicle->defaultComponentId();
485
486 _vehicle->sendMavCommand(compId,
487 MAV_CMD_PREFLIGHT_STORAGE,
488 true, // showError
489 3, // Reset factory parameters
490 -1); // Don't do anything with mission storage
491}
std::shared_ptr< LinkInterface > SharedLinkInterfacePtr
#define QGC_LOGGING_CATEGORY(name, categoryStr)
QVariant rawValue() const
Value after translation.
Definition Fact.h:85
bool parameterExists(int componentId, const QString &paramName) const
Fact * getParameter(int componentId, const QString &paramName)
void refreshParametersPrefix(int componentId, const QString &namePrefix)
Request a refresh on all parameters that begin with the specified prefix.
static constexpr int defaultComponentId
void refreshParameter(int componentId, const QString &paramName)
Request a refresh on the specific parameter.
Sensors Component MVC Controller for SensorsComponent.qml.
void orientationCalSidesVisibleChanged(void)
void waitingForCancelChanged(void)
void orientationCalSidesInProgressChanged(void)
void orientationCalSidesDoneChanged(void)
void orientationCalSidesRotateChanged(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:2146
void textMessageReceived(int sysid, int componentid, int severity, QString text, QString description)
VehicleLinkManager * vehicleLinkManager()
Definition Vehicle.h:575
void sensorsParametersResetAck(bool success)
int id() const
Definition Vehicle.h:425
int defaultComponentId() const
Definition Vehicle.h:670
ParameterManager * parameterManager()
Definition Vehicle.h:573
void startCalibration(QGCMAVLink::CalibrationType calType)
Definition Vehicle.cc:2325
void stopCalibration(bool showError)
Definition Vehicle.cc:2405
void showAppMessage(const QString &message, const QString &title)
Modal application message. Queued if the UI isn't ready yet.
Definition AppMessages.cc:9