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) {
128 emit magCalComplete();
129 }
130 break;
131
132 case StopCalibrationCancelled:
133 emit resetStatusTextArea();
134 _hideAllCalAreas();
135 break;
136
137 default:
138 // Assume failed
139 _hideAllCalAreas();
140 QGC::showAppMessage(tr("Calibration failed. Calibration log will be displayed."));
141 break;
142 }
143
144 _magCalInProgress = false;
145 _accelCalInProgress = false;
146 _gyroCalInProgress = false;
147 _airspeedCalInProgress = false;
148 _levelCalInProgress = false;
149
151}
152
158
164
170
176
182
183void SensorsComponentController::_handleUASTextMessage(int uasId, int compId, int severity, QString text, const QString &description)
184{
185 Q_UNUSED(compId);
186 Q_UNUSED(severity);
187 Q_UNUSED(description);
188
189 if (uasId != _vehicle->id()) {
190 return;
191 }
192
193 // Needed for level horizon calibration
194 text.replace("&lt;", "<");
195 text.replace("&gt;", ">");
196
197 if (text.contains("progress <")) {
198 QString percent = text.split("<").last().split(">").first();
199 bool ok;
200 int p = percent.toInt(&ok);
201 if (ok) {
202 if (_progressBar) {
203 _progressBar->setProperty("value", (float)(p / 100.0));
204 } else {
205 qWarning() << "Internal error";
206 }
207 }
208 return;
209 }
210
211 _appendStatusLog(text);
212 qCDebug(SensorsComponentControllerLog) << text;
213
214 if (_unknownFirmwareVersion) {
215 // We don't know how to do visual cal with the version of firwmare
216 return;
217 }
218
219 // All calibration messages start with [cal]
220 QString calPrefix("[cal] ");
221 if (!text.startsWith(calPrefix)) {
222 return;
223 }
224 text = text.right(text.length() - calPrefix.length());
225
226 QString calStartPrefix("calibration started: ");
227 if (text.startsWith(calStartPrefix)) {
228 text = text.right(text.length() - calStartPrefix.length());
229
230 // Split version number and cal type
231 QStringList parts = text.split(" ");
232 if (parts.count() != 2 && parts[0].toInt() != _supportedFirmwareCalVersion) {
233 _unknownFirmwareVersion = true;
234 QString msg = tr("Unsupported calibration firmware version, using log");
235 _appendStatusLog(msg);
236 qDebug() << msg;
237 return;
238 }
239
240 _startVisualCalibration();
241
242 text = parts[1];
243 if (text == "accel" || text == "mag" || text == "gyro") {
244 // _startVisualCalibration() above reset all side indicators to Incomplete
245
246 // Reset all visibility
247 _orientationCalDownSideVisible = false;
248 _orientationCalUpsideDownSideVisible = false;
249 _orientationCalLeftSideVisible = false;
250 _orientationCalRightSideVisible = false;
251 _orientationCalTailDownSideVisible = false;
252 _orientationCalNoseDownSideVisible = false;
253
254 _orientationCalAreaHelpText->setProperty("text", tr("Place your vehicle into one of the Incomplete orientations shown below and hold it still"));
255
256 if (text == "accel") {
257 _accelCalInProgress = true;
258 _orientationCalDownSideVisible = true;
259 _orientationCalUpsideDownSideVisible = true;
260 _orientationCalLeftSideVisible = true;
261 _orientationCalRightSideVisible = true;
262 _orientationCalTailDownSideVisible = true;
263 _orientationCalNoseDownSideVisible = true;
264 } else if (text == "mag") {
265
266 // Work out what the autopilot is configured to
267 int sides = 0;
268
270 // Read the requested calibration directions off the system
272 } else {
273 // There is no valid setting, default to all six sides
274 sides = (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2) | (1 << 1) | (1 << 0);
275 }
276
277 _magCalInProgress = true;
278 _orientationCalTailDownSideVisible = ((sides & (1 << 0)) > 0);
279 _orientationCalNoseDownSideVisible = ((sides & (1 << 1)) > 0);
280 _orientationCalLeftSideVisible = ((sides & (1 << 2)) > 0);
281 _orientationCalRightSideVisible = ((sides & (1 << 3)) > 0);
282 _orientationCalUpsideDownSideVisible = ((sides & (1 << 4)) > 0);
283 _orientationCalDownSideVisible = ((sides & (1 << 5)) > 0);
284 } else if (text == "gyro") {
285 _gyroCalInProgress = true;
286 _orientationCalDownSideVisible = true;
287 } else {
288 qWarning() << "Unknown calibration message type" << text;
289 }
291 _updateAndEmitShowOrientationCalArea(true);
292 } else if (text == "airspeed") {
293 _airspeedCalInProgress = true;
294 } else if (text == "level") {
295 _levelCalInProgress = true;
296 }
298 return;
299 }
300
301 if (text.endsWith("orientation detected")) {
302 QString side = text.section(" ", 0, 0);
303 qCDebug(SensorsComponentControllerLog) << "Side started" << side;
304
305 if (side == "down") {
306 _orientationCalDownSideState = SideCalStateInProgress;
307 } else if (side == "up") {
308 _orientationCalUpsideDownSideState = SideCalStateInProgress;
309 } else if (side == "left") {
310 _orientationCalLeftSideState = SideCalStateInProgress;
311 } else if (side == "right") {
312 _orientationCalRightSideState = SideCalStateInProgress;
313 } else if (side == "front") {
314 _orientationCalNoseDownSideState = SideCalStateInProgress;
315 } else if (side == "back") {
316 _orientationCalTailDownSideState = SideCalStateInProgress;
317 }
318
319 if (_magCalInProgress) {
320 _orientationCalAreaHelpText->setProperty("text", tr("Rotate the vehicle continuously as shown in the diagram until marked as Completed"));
321 } else {
322 _orientationCalAreaHelpText->setProperty("text", tr("Hold still in the current orientation"));
323 }
324
326 return;
327 }
328
329 if (text.endsWith("side done, rotate to a different side")) {
330 QString side = text.section(" ", 0, 0);
331 qCDebug(SensorsComponentControllerLog) << "Side finished" << side;
332
333 if (side == "down") {
334 _orientationCalDownSideState = SideCalStateCompleted;
335 } else if (side == "up") {
336 _orientationCalUpsideDownSideState = SideCalStateCompleted;
337 } else if (side == "left") {
338 _orientationCalLeftSideState = SideCalStateCompleted;
339 } else if (side == "right") {
340 _orientationCalRightSideState = SideCalStateCompleted;
341 } else if (side == "front") {
342 _orientationCalNoseDownSideState = SideCalStateCompleted;
343 } else if (side == "back") {
344 _orientationCalTailDownSideState = SideCalStateCompleted;
345 }
346
347 _orientationCalAreaHelpText->setProperty("text", tr("Place you vehicle into one of the orientations shown below and hold it still"));
348
350 return;
351 }
352
353 if (text.endsWith("side already completed")) {
354 _orientationCalAreaHelpText->setProperty("text", tr("Orientation already completed, place you vehicle into one of the incomplete orientations shown below and hold it still"));
355 return;
356 }
357
358 QString calCompletePrefix("calibration done:");
359 if (text.startsWith(calCompletePrefix)) {
360 _stopCalibration(StopCalibrationSuccess);
361 return;
362 }
363
364 if (text.startsWith("calibration cancelled")) {
365 _stopCalibration(_waitingForCancel ? StopCalibrationCancelled : StopCalibrationFailed);
366 return;
367 }
368
369 if (text.startsWith("calibration failed")) {
370 _stopCalibration(StopCalibrationFailed);
371 return;
372 }
373}
374
375void SensorsComponentController::_refreshParams(void)
376{
378 QStringLiteral("CAL_MAG0_ID"), QStringLiteral("CAL_MAG1_ID"), QStringLiteral("CAL_MAG2_ID"),
379 QStringLiteral("CAL_MAG0_ROT"), QStringLiteral("CAL_MAG1_ROT"), QStringLiteral("CAL_MAG2_ROT"),
380 QStringLiteral("CAL_*"),
381 QStringLiteral("SENS_*"),
382 }, false /* notifyFailure */);
383}
384
385void SensorsComponentController::_updateAndEmitShowOrientationCalArea(bool show)
386{
387 _showOrientationCalArea = show;
389}
390
391void SensorsComponentController::_hideAllCalAreas(void)
392{
393 _updateAndEmitShowOrientationCalArea(false);
394}
395
397{
398 // The firmware doesn't allow us to cancel calibration. The best we can do is wait
399 // for it to timeout.
400 _waitingForCancel = true;
402 _vehicle->stopCalibration(true /* showError */);
403}
404
405void SensorsComponentController::_handleParametersReset(bool success)
406{
407 if (success) {
408 QGC::showAppMessage(tr("Reset successful"));
409
410 QTimer::singleShot(1000, this, [this]() {
411 _refreshParams();
412 });
413 }
414 else {
415 QGC::showAppMessage(tr("Reset failed"));
416 }
417}
418
420{
421 auto compId = _vehicle->defaultComponentId();
422
423 _vehicle->sendMavCommand(compId,
424 MAV_CMD_PREFLIGHT_STORAGE,
425 true, // showError
426 3, // Reset factory parameters
427 -1); // Don't do anything with mission storage
428}
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 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:2144
void textMessageReceived(int sysid, int componentid, int severity, QString text, QString description)
VehicleLinkManager * vehicleLinkManager()
Definition Vehicle.h:579
void sensorsParametersResetAck(bool success)
int id() const
Definition Vehicle.h:429
int defaultComponentId() const
Definition Vehicle.h:682
ParameterManager * parameterManager()
Definition Vehicle.h:577
void startCalibration(QGCMAVLink::CalibrationType calType)
Definition Vehicle.cc:2328
void stopCalibration(bool showError)
Definition Vehicle.cc:2408
void showAppMessage(const QString &message, const QString &title)
Modal application message. Queued if the UI isn't ready yet.
Definition AppMessages.cc:9