• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mavlink / MAVSDK / 23911409490

02 Apr 2026 04:40PM UTC coverage: 50.475% (+1.4%) from 49.029%
23911409490

push

github

web-flow
Merge pull request #2833 from bansiesta/v3-cherry-picks

Backport recent main fixes and features to v3

632 of 815 new or added lines in 29 files covered. (77.55%)

34 existing lines in 11 files now uncovered.

19249 of 38136 relevant lines covered (50.47%)

671.0 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

21.73
/src/mavsdk/plugins/telemetry/telemetry_impl.cpp
1
#include "telemetry_impl.h"
2
#include "system.h"
3
#include "math_utils.h"
4
#include "callback_list.tpp"
5

6
#include <cmath>
7
#include <functional>
8
#include <string>
9
#include <array>
10
#include <cassert>
11
#include <unused.h>
12

13
namespace mavsdk {
14

15
template class CallbackList<Telemetry::PositionVelocityNed>;
16
template class CallbackList<Telemetry::Position>;
17
template class CallbackList<bool>;
18
template class CallbackList<Telemetry::StatusText>;
19
template class CallbackList<Telemetry::Quaternion>;
20
template class CallbackList<Telemetry::AngularVelocityBody>;
21
template class CallbackList<Telemetry::GroundTruth>;
22
template class CallbackList<Telemetry::FixedwingMetrics>;
23
template class CallbackList<Telemetry::EulerAngle>;
24
template class CallbackList<Telemetry::VelocityNed>;
25
template class CallbackList<Telemetry::Imu>;
26
template class CallbackList<Telemetry::GpsInfo>;
27
template class CallbackList<Telemetry::RawGps>;
28
template class CallbackList<Telemetry::Battery>;
29
template class CallbackList<Telemetry::FlightMode>;
30
template class CallbackList<Telemetry::Health>;
31
template class CallbackList<Telemetry::VtolState>;
32
template class CallbackList<Telemetry::LandedState>;
33
template class CallbackList<Telemetry::RcStatus>;
34
template class CallbackList<uint64_t>;
35
template class CallbackList<Telemetry::ActuatorControlTarget>;
36
template class CallbackList<Telemetry::ActuatorOutputStatus>;
37
template class CallbackList<Telemetry::Odometry>;
38
template class CallbackList<Telemetry::DistanceSensor>;
39
template class CallbackList<Telemetry::ScaledPressure>;
40
template class CallbackList<Telemetry::Heading>;
41
template class CallbackList<Telemetry::Altitude>;
42
template class CallbackList<Telemetry::Wind>;
43

44
TelemetryImpl::TelemetryImpl(System& system) : PluginImplBase(system)
×
45
{
46
    _system_impl->register_plugin(this);
×
47
}
×
48

49
TelemetryImpl::TelemetryImpl(std::shared_ptr<System> system) : PluginImplBase(std::move(system))
12✔
50
{
51
    _system_impl->register_plugin(this);
12✔
52
}
12✔
53

54
TelemetryImpl::~TelemetryImpl()
24✔
55
{
56
    _system_impl->unregister_plugin(this);
12✔
57
}
24✔
58

59
void TelemetryImpl::init()
12✔
60
{
61
    _system_impl->register_mavlink_message_handler(
12✔
62
        MAVLINK_MSG_ID_LOCAL_POSITION_NED,
63
        [this](const mavlink_message_t& message) { process_position_velocity_ned(message); },
×
64
        this);
65

66
    _system_impl->register_mavlink_message_handler(
12✔
67
        MAVLINK_MSG_ID_GLOBAL_POSITION_INT,
68
        [this](const mavlink_message_t& message) { process_global_position_int(message); },
4✔
69
        this);
70

71
    _system_impl->register_mavlink_message_handler(
12✔
72
        MAVLINK_MSG_ID_HOME_POSITION,
73
        [this](const mavlink_message_t& message) { process_home_position(message); },
×
74
        this);
75

76
    _system_impl->register_mavlink_message_handler(
12✔
77
        MAVLINK_MSG_ID_ATTITUDE,
78
        [this](const mavlink_message_t& message) { process_attitude(message); },
×
79
        this);
80

81
    _system_impl->register_mavlink_message_handler(
12✔
82
        MAVLINK_MSG_ID_ATTITUDE_QUATERNION,
83
        [this](const mavlink_message_t& message) { process_attitude_quaternion(message); },
×
84
        this);
85

86
    _system_impl->register_mavlink_message_handler(
12✔
87
        MAVLINK_MSG_ID_GPS_RAW_INT,
88
        [this](const mavlink_message_t& message) { process_gps_raw_int(message); },
1✔
89
        this);
90

91
    _system_impl->register_mavlink_message_handler(
12✔
92
        MAVLINK_MSG_ID_EXTENDED_SYS_STATE,
93
        [this](const mavlink_message_t& message) { process_extended_sys_state(message); },
×
94
        this);
95

96
    _system_impl->register_mavlink_message_handler(
12✔
97
        MAVLINK_MSG_ID_SYS_STATUS,
98
        [this](const mavlink_message_t& message) { process_sys_status(message); },
2✔
99
        this);
100

101
    _system_impl->register_mavlink_message_handler(
12✔
102
        MAVLINK_MSG_ID_BATTERY_STATUS,
103
        [this](const mavlink_message_t& message) { process_battery_status(message); },
×
104
        this);
105

106
    _system_impl->register_mavlink_message_handler(
12✔
107
        MAVLINK_MSG_ID_HEARTBEAT,
108
        [this](const mavlink_message_t& message) { process_heartbeat(message); },
4✔
109
        this);
110

111
    _system_impl->register_mavlink_message_handler(
12✔
112
        MAVLINK_MSG_ID_RC_CHANNELS,
113
        [this](const mavlink_message_t& message) { process_rc_channels(message); },
1✔
114
        this);
115

116
    _system_impl->register_mavlink_message_handler(
12✔
117
        MAVLINK_MSG_ID_ACTUATOR_CONTROL_TARGET,
118
        [this](const mavlink_message_t& message) { process_actuator_control_target(message); },
×
119
        this);
120

121
    _system_impl->register_mavlink_message_handler(
12✔
122
        MAVLINK_MSG_ID_ACTUATOR_OUTPUT_STATUS,
123
        [this](const mavlink_message_t& message) { process_actuator_output_status(message); },
×
124
        this);
125

126
    _system_impl->register_mavlink_message_handler(
12✔
127
        MAVLINK_MSG_ID_ODOMETRY,
128
        [this](const mavlink_message_t& message) { process_odometry(message); },
×
129
        this);
130

131
    _system_impl->register_mavlink_message_handler(
12✔
132
        MAVLINK_MSG_ID_DISTANCE_SENSOR,
133
        [this](const mavlink_message_t& message) { process_distance_sensor(message); },
×
134
        this);
135

136
    _system_impl->register_mavlink_message_handler(
12✔
137
        MAVLINK_MSG_ID_SCALED_PRESSURE,
138
        [this](const mavlink_message_t& message) { process_scaled_pressure(message); },
×
139
        this);
140

141
    _system_impl->register_mavlink_message_handler(
12✔
142
        MAVLINK_MSG_ID_SYSTEM_TIME,
143
        [this](const mavlink_message_t& message) { process_unix_epoch_time(message); },
×
144
        this);
145

146
    _system_impl->register_mavlink_message_handler(
12✔
147
        MAVLINK_MSG_ID_HIGHRES_IMU,
148
        [this](const mavlink_message_t& message) { process_imu_reading_ned(message); },
×
149
        this);
150

151
    _system_impl->register_mavlink_message_handler(
12✔
152
        MAVLINK_MSG_ID_SCALED_IMU,
153
        [this](const mavlink_message_t& message) { process_scaled_imu(message); },
×
154
        this);
155

156
    _system_impl->register_mavlink_message_handler(
12✔
157
        MAVLINK_MSG_ID_RAW_IMU,
158
        [this](const mavlink_message_t& message) { process_raw_imu(message); },
×
159
        this);
160

161
    _system_impl->register_mavlink_message_handler(
12✔
162
        MAVLINK_MSG_ID_VFR_HUD,
163
        [this](const mavlink_message_t& message) { process_fixedwing_metrics(message); },
×
164
        this);
165

166
    _system_impl->register_mavlink_message_handler(
12✔
167
        MAVLINK_MSG_ID_HIL_STATE_QUATERNION,
168
        [this](const mavlink_message_t& message) { process_ground_truth(message); },
1✔
169
        this);
170

171
    _system_impl->register_mavlink_message_handler(
12✔
172
        MAVLINK_MSG_ID_ALTITUDE,
173
        [this](const mavlink_message_t& message) { process_altitude(message); },
4✔
174
        this);
175

176
    _system_impl->register_mavlink_message_handler(
12✔
177
        MAVLINK_MSG_ID_WIND_COV,
178
        [this](const mavlink_message_t& message) { process_wind(message); },
×
179
        this);
180

181
    _system_impl->register_statustext_handler(
12✔
182
        [this](const MavlinkStatustextHandler::Statustext& statustext) {
3✔
183
            receive_statustext(statustext);
3✔
184
        },
3✔
185
        this);
186
}
12✔
187

188
void TelemetryImpl::deinit()
12✔
189
{
190
    _system_impl->unregister_statustext_handler(this);
12✔
191
    // Use blocking version to ensure any in-flight callbacks complete before destruction.
192
    _system_impl->unregister_all_mavlink_message_handlers_blocking(this);
12✔
193
}
12✔
194

195
void TelemetryImpl::enable()
12✔
196
{
197
    // We're going to retry until we have the Home Position.
198
    _homepos_cookie =
12✔
199
        _system_impl->add_call_every([this]() { request_home_position_again(); }, 2.0f);
24✔
200
}
12✔
201

202
void TelemetryImpl::disable()
12✔
203
{
204
    _system_impl->remove_call_every(_homepos_cookie);
12✔
205
    {
206
        std::lock_guard<std::mutex> lock(_health_mutex);
12✔
207
        _health.is_home_position_ok = false;
12✔
208
    }
12✔
209

210
    // FIXME: this is a race condition where request_home_position_again
211
    //        could still be executing after we have removed it.
212
    std::this_thread::sleep_for(std::chrono::milliseconds(200));
12✔
213
}
12✔
214

215
void TelemetryImpl::request_home_position_again()
12✔
216
{
217
    {
218
        std::lock_guard<std::mutex> lock(_health_mutex);
12✔
219
        if (_health.is_home_position_ok) {
12✔
220
            _system_impl->remove_call_every(_homepos_cookie);
×
221
            return;
×
222
        }
223

224
        _system_impl->mavlink_request_message().request(
12✔
225
            MAVLINK_MSG_ID_HOME_POSITION, MAV_COMP_ID_AUTOPILOT1, nullptr);
226
    }
12✔
227
}
228

229
Telemetry::Result TelemetryImpl::set_rate_position_velocity_ned(double rate_hz)
×
230
{
231
    return telemetry_result_from_command_result(
×
232
        _system_impl->set_msg_rate(MAVLINK_MSG_ID_LOCAL_POSITION_NED, rate_hz));
×
233
}
234

235
Telemetry::Result TelemetryImpl::set_rate_position(double rate_hz)
×
236
{
237
    _position_rate_hz = rate_hz;
×
238
    double max_rate_hz = std::max(_position_rate_hz, _velocity_ned_rate_hz);
×
239

240
    return telemetry_result_from_command_result(
×
241
        _system_impl->set_msg_rate(MAVLINK_MSG_ID_GLOBAL_POSITION_INT, max_rate_hz));
×
242
}
243

244
Telemetry::Result TelemetryImpl::set_rate_home(double rate_hz)
×
245
{
246
    return telemetry_result_from_command_result(
×
247
        _system_impl->set_msg_rate(MAVLINK_MSG_ID_HOME_POSITION, rate_hz));
×
248
}
249

250
Telemetry::Result TelemetryImpl::set_rate_in_air(double rate_hz)
×
251
{
252
    return set_rate_landed_state(rate_hz);
×
253
}
254

255
Telemetry::Result TelemetryImpl::set_rate_vtol_state(double rate_hz)
×
256
{
257
    return set_rate_landed_state(rate_hz);
×
258
}
259

260
Telemetry::Result TelemetryImpl::set_rate_landed_state(double rate_hz)
×
261
{
262
    return telemetry_result_from_command_result(
×
263
        _system_impl->set_msg_rate(MAVLINK_MSG_ID_EXTENDED_SYS_STATE, rate_hz));
×
264
}
265

266
Telemetry::Result TelemetryImpl::set_rate_attitude_quaternion(double rate_hz)
×
267
{
268
    return telemetry_result_from_command_result(
×
269
        _system_impl->set_msg_rate(MAVLINK_MSG_ID_ATTITUDE_QUATERNION, rate_hz));
×
270
}
271

272
Telemetry::Result TelemetryImpl::set_rate_attitude_euler(double rate_hz)
×
273
{
274
    return telemetry_result_from_command_result(
×
275
        _system_impl->set_msg_rate(MAVLINK_MSG_ID_ATTITUDE, rate_hz));
×
276
}
277

278
Telemetry::Result TelemetryImpl::set_rate_velocity_ned(double rate_hz)
×
279
{
280
    _velocity_ned_rate_hz = rate_hz;
×
281
    double max_rate_hz = std::max(_position_rate_hz, _velocity_ned_rate_hz);
×
282

283
    return telemetry_result_from_command_result(
×
284
        _system_impl->set_msg_rate(MAVLINK_MSG_ID_GLOBAL_POSITION_INT, max_rate_hz));
×
285
}
286

287
Telemetry::Result TelemetryImpl::set_rate_imu(double rate_hz)
×
288
{
289
    return telemetry_result_from_command_result(
×
290
        _system_impl->set_msg_rate(MAVLINK_MSG_ID_HIGHRES_IMU, rate_hz));
×
291
}
292

293
Telemetry::Result TelemetryImpl::set_rate_scaled_imu(double rate_hz)
×
294
{
295
    return telemetry_result_from_command_result(
×
296
        _system_impl->set_msg_rate(MAVLINK_MSG_ID_SCALED_IMU, rate_hz));
×
297
}
298

299
Telemetry::Result TelemetryImpl::set_rate_raw_imu(double rate_hz)
×
300
{
301
    return telemetry_result_from_command_result(
×
302
        _system_impl->set_msg_rate(MAVLINK_MSG_ID_RAW_IMU, rate_hz));
×
303
}
304

305
Telemetry::Result TelemetryImpl::set_rate_fixedwing_metrics(double rate_hz)
×
306
{
307
    return telemetry_result_from_command_result(
×
308
        _system_impl->set_msg_rate(MAVLINK_MSG_ID_VFR_HUD, rate_hz));
×
309
}
310

311
Telemetry::Result TelemetryImpl::set_rate_ground_truth(double rate_hz)
×
312
{
313
    return telemetry_result_from_command_result(
×
314
        _system_impl->set_msg_rate(MAVLINK_MSG_ID_HIL_STATE_QUATERNION, rate_hz));
×
315
}
316

317
Telemetry::Result TelemetryImpl::set_rate_gps_info(double rate_hz)
×
318
{
NEW
319
    _gps_info_rate_hz = rate_hz;
×
NEW
320
    double max_rate_hz = std::max(_gps_info_rate_hz, _raw_gps_rate_hz);
×
321
    return telemetry_result_from_command_result(
×
NEW
322
        _system_impl->set_msg_rate(MAVLINK_MSG_ID_GPS_RAW_INT, max_rate_hz));
×
323
}
324

NEW
325
Telemetry::Result TelemetryImpl::set_rate_raw_gps(double rate_hz)
×
326
{
NEW
327
    _raw_gps_rate_hz = rate_hz;
×
NEW
328
    double max_rate_hz = std::max(_gps_info_rate_hz, _raw_gps_rate_hz);
×
NEW
329
    return telemetry_result_from_command_result(
×
NEW
330
        _system_impl->set_msg_rate(MAVLINK_MSG_ID_GPS_RAW_INT, max_rate_hz));
×
331
}
332

333
Telemetry::Result TelemetryImpl::set_rate_battery(double rate_hz)
×
334
{
335
    return telemetry_result_from_command_result(
×
336
        _system_impl->set_msg_rate(MAVLINK_MSG_ID_BATTERY_STATUS, rate_hz));
×
337
}
338

339
Telemetry::Result TelemetryImpl::set_rate_rc_status(double rate_hz)
×
340
{
NEW
341
    _rc_status_rate_hz = rate_hz;
×
342

343
    // On PX4, RC data comes via RC_CHANNELS. On ArduPilot, it comes via SYS_STATUS.
NEW
344
    if (_system_impl->effective_autopilot() == Autopilot::ArduPilot) {
×
NEW
345
        return set_rate_sys_status();
×
346
    }
347

348
    // For PX4 (or unknown), request RC_CHANNELS and also update SYS_STATUS if needed.
NEW
349
    auto result = telemetry_result_from_command_result(
×
NEW
350
        _system_impl->set_msg_rate(MAVLINK_MSG_ID_RC_CHANNELS, rate_hz));
×
NEW
351
    if (result != Telemetry::Result::Success) {
×
NEW
352
        return result;
×
353
    }
NEW
354
    return set_rate_sys_status();
×
355
}
356

NEW
357
Telemetry::Result TelemetryImpl::set_rate_sys_status()
×
358
{
NEW
359
    double max_rate_hz = std::max(_health_rate_hz, _rc_status_rate_hz);
×
NEW
360
    return telemetry_result_from_command_result(
×
NEW
361
        _system_impl->set_msg_rate(MAVLINK_MSG_ID_SYS_STATUS, max_rate_hz));
×
362
}
363

364
Telemetry::Result TelemetryImpl::set_rate_actuator_control_target(double rate_hz)
×
365
{
366
    return telemetry_result_from_command_result(
×
367
        _system_impl->set_msg_rate(MAVLINK_MSG_ID_ACTUATOR_CONTROL_TARGET, rate_hz));
×
368
}
369

370
Telemetry::Result TelemetryImpl::set_rate_actuator_output_status(double rate_hz)
×
371
{
372
    return telemetry_result_from_command_result(
×
373
        _system_impl->set_msg_rate(MAVLINK_MSG_ID_ACTUATOR_OUTPUT_STATUS, rate_hz));
×
374
}
375

376
Telemetry::Result TelemetryImpl::set_rate_odometry(double rate_hz)
×
377
{
378
    return telemetry_result_from_command_result(
×
379
        _system_impl->set_msg_rate(MAVLINK_MSG_ID_ODOMETRY, rate_hz));
×
380
}
381

382
Telemetry::Result TelemetryImpl::set_rate_distance_sensor(double rate_hz)
×
383
{
384
    return telemetry_result_from_command_result(
×
385
        _system_impl->set_msg_rate(MAVLINK_MSG_ID_DISTANCE_SENSOR, rate_hz));
×
386
}
387

388
Telemetry::Result TelemetryImpl::set_rate_scaled_pressure(double rate_hz)
×
389
{
390
    return telemetry_result_from_command_result(
×
391
        _system_impl->set_msg_rate(MAVLINK_MSG_ID_SCALED_PRESSURE, rate_hz));
×
392
}
393

394
Telemetry::Result TelemetryImpl::set_rate_unix_epoch_time(double rate_hz)
×
395
{
396
    return telemetry_result_from_command_result(
×
397
        _system_impl->set_msg_rate(MAVLINK_MSG_ID_SYSTEM_TIME, rate_hz));
×
398
}
399

400
Telemetry::Result TelemetryImpl::set_rate_altitude(double rate_hz)
×
401
{
402
    return telemetry_result_from_command_result(
×
403
        _system_impl->set_msg_rate(MAVLINK_MSG_ID_ALTITUDE, rate_hz));
×
404
}
405

406
Telemetry::Result TelemetryImpl::set_rate_health(double rate_hz)
×
407
{
NEW
408
    _health_rate_hz = rate_hz;
×
NEW
409
    return set_rate_sys_status();
×
410
}
411

412
void TelemetryImpl::set_rate_position_velocity_ned_async(
×
413
    double rate_hz, Telemetry::ResultCallback callback)
414
{
415
    _system_impl->set_msg_rate_async(
×
416
        MAVLINK_MSG_ID_LOCAL_POSITION_NED,
417
        rate_hz,
418
        [callback](MavlinkCommandSender::Result command_result, float) {
×
419
            command_result_callback(command_result, callback);
×
420
        });
×
421
}
×
422

423
void TelemetryImpl::set_rate_position_async(double rate_hz, Telemetry::ResultCallback callback)
×
424
{
425
    _position_rate_hz = rate_hz;
×
426
    double max_rate_hz = std::max(_position_rate_hz, _velocity_ned_rate_hz);
×
427

428
    _system_impl->set_msg_rate_async(
×
429
        MAVLINK_MSG_ID_GLOBAL_POSITION_INT,
430
        max_rate_hz,
431
        [callback](MavlinkCommandSender::Result command_result, float) {
×
432
            command_result_callback(command_result, callback);
×
433
        });
×
434
}
×
435

436
void TelemetryImpl::set_rate_home_async(double rate_hz, Telemetry::ResultCallback callback)
×
437
{
438
    _system_impl->set_msg_rate_async(
×
439
        MAVLINK_MSG_ID_HOME_POSITION,
440
        rate_hz,
441
        [callback](MavlinkCommandSender::Result command_result, float) {
×
442
            command_result_callback(command_result, callback);
×
443
        });
×
444
}
×
445

446
void TelemetryImpl::set_rate_in_air_async(double rate_hz, Telemetry::ResultCallback callback)
×
447
{
448
    set_rate_landed_state_async(rate_hz, callback);
×
449
}
×
450

451
void TelemetryImpl::set_rate_vtol_state_async(double rate_hz, Telemetry::ResultCallback callback)
×
452
{
453
    set_rate_landed_state_async(rate_hz, callback);
×
454
}
×
455

456
void TelemetryImpl::set_rate_landed_state_async(double rate_hz, Telemetry::ResultCallback callback)
×
457
{
458
    _system_impl->set_msg_rate_async(
×
459
        MAVLINK_MSG_ID_EXTENDED_SYS_STATE,
460
        rate_hz,
461
        [callback](MavlinkCommandSender::Result command_result, float) {
×
462
            command_result_callback(command_result, callback);
×
463
        });
×
464
}
×
465

466
void TelemetryImpl::set_rate_altitude_async(double rate_hz, Telemetry::ResultCallback callback)
×
467
{
468
    _system_impl->set_msg_rate_async(
×
469
        MAVLINK_MSG_ID_ALTITUDE,
470
        rate_hz,
471
        [callback](MavlinkCommandSender::Result command_result, float) {
×
472
            command_result_callback(command_result, callback);
×
473
        });
×
474
}
×
475

476
void TelemetryImpl::set_rate_health_async(double rate_hz, Telemetry::ResultCallback callback)
×
477
{
NEW
478
    _health_rate_hz = rate_hz;
×
NEW
479
    double max_rate_hz = std::max(_health_rate_hz, _rc_status_rate_hz);
×
UNCOV
480
    _system_impl->set_msg_rate_async(
×
481
        MAVLINK_MSG_ID_SYS_STATUS,
482
        max_rate_hz,
483
        [callback](MavlinkCommandSender::Result command_result, float) {
×
484
            command_result_callback(command_result, callback);
×
485
        });
×
486
}
×
487

488
void TelemetryImpl::set_rate_attitude_quaternion_async(
×
489
    double rate_hz, Telemetry::ResultCallback callback)
490
{
491
    _system_impl->set_msg_rate_async(
×
492
        MAVLINK_MSG_ID_ATTITUDE_QUATERNION,
493
        rate_hz,
494
        [callback](MavlinkCommandSender::Result command_result, float) {
×
495
            command_result_callback(command_result, callback);
×
496
        });
×
497
}
×
498

499
void TelemetryImpl::set_rate_attitude_euler_async(
×
500
    double rate_hz, Telemetry::ResultCallback callback)
501
{
502
    _system_impl->set_msg_rate_async(
×
503
        MAVLINK_MSG_ID_ATTITUDE,
504
        rate_hz,
505
        [callback](MavlinkCommandSender::Result command_result, float) {
×
506
            command_result_callback(command_result, callback);
×
507
        });
×
508
}
×
509

510
void TelemetryImpl::set_rate_velocity_ned_async(double rate_hz, Telemetry::ResultCallback callback)
×
511
{
512
    _velocity_ned_rate_hz = rate_hz;
×
513
    double max_rate_hz = std::max(_position_rate_hz, _velocity_ned_rate_hz);
×
514

515
    _system_impl->set_msg_rate_async(
×
516
        MAVLINK_MSG_ID_GLOBAL_POSITION_INT,
517
        max_rate_hz,
518
        [callback](MavlinkCommandSender::Result command_result, float) {
×
519
            command_result_callback(command_result, callback);
×
520
        });
×
521
}
×
522

523
void TelemetryImpl::set_rate_imu_async(double rate_hz, Telemetry::ResultCallback callback)
×
524
{
525
    _system_impl->set_msg_rate_async(
×
526
        MAVLINK_MSG_ID_HIGHRES_IMU,
527
        rate_hz,
528
        [callback](MavlinkCommandSender::Result command_result, float) {
×
529
            command_result_callback(command_result, callback);
×
530
        });
×
531
}
×
532

533
void TelemetryImpl::set_rate_scaled_imu_async(double rate_hz, Telemetry::ResultCallback callback)
×
534
{
535
    _system_impl->set_msg_rate_async(
×
536
        MAVLINK_MSG_ID_SCALED_IMU,
537
        rate_hz,
538
        [callback](MavlinkCommandSender::Result command_result, float) {
×
539
            command_result_callback(command_result, callback);
×
540
        });
×
541
}
×
542

543
void TelemetryImpl::set_rate_raw_imu_async(double rate_hz, Telemetry::ResultCallback callback)
×
544
{
545
    _system_impl->set_msg_rate_async(
×
546
        MAVLINK_MSG_ID_RAW_IMU,
547
        rate_hz,
548
        [callback](MavlinkCommandSender::Result command_result, float) {
×
549
            command_result_callback(command_result, callback);
×
550
        });
×
551
}
×
552

553
void TelemetryImpl::set_rate_fixedwing_metrics_async(
×
554
    double rate_hz, Telemetry::ResultCallback callback)
555
{
556
    _system_impl->set_msg_rate_async(
×
557
        MAVLINK_MSG_ID_VFR_HUD,
558
        rate_hz,
559
        [callback](MavlinkCommandSender::Result command_result, float) {
×
560
            command_result_callback(command_result, callback);
×
561
        });
×
562
}
×
563

564
void TelemetryImpl::set_rate_ground_truth_async(double rate_hz, Telemetry::ResultCallback callback)
×
565
{
566
    _system_impl->set_msg_rate_async(
×
567
        MAVLINK_MSG_ID_HIL_STATE_QUATERNION,
568
        rate_hz,
569
        [callback](MavlinkCommandSender::Result command_result, float) {
×
570
            command_result_callback(command_result, callback);
×
571
        });
×
572
}
×
573

574
void TelemetryImpl::set_rate_gps_info_async(double rate_hz, Telemetry::ResultCallback callback)
×
575
{
NEW
576
    _gps_info_rate_hz = rate_hz;
×
NEW
577
    double max_rate_hz = std::max(_gps_info_rate_hz, _raw_gps_rate_hz);
×
UNCOV
578
    _system_impl->set_msg_rate_async(
×
579
        MAVLINK_MSG_ID_GPS_RAW_INT,
580
        max_rate_hz,
NEW
581
        [callback](MavlinkCommandSender::Result command_result, float) {
×
NEW
582
            command_result_callback(command_result, callback);
×
NEW
583
        });
×
NEW
584
}
×
585

NEW
586
void TelemetryImpl::set_rate_raw_gps_async(double rate_hz, Telemetry::ResultCallback callback)
×
587
{
NEW
588
    _raw_gps_rate_hz = rate_hz;
×
NEW
589
    double max_rate_hz = std::max(_gps_info_rate_hz, _raw_gps_rate_hz);
×
NEW
590
    _system_impl->set_msg_rate_async(
×
591
        MAVLINK_MSG_ID_GPS_RAW_INT,
592
        max_rate_hz,
593
        [callback](MavlinkCommandSender::Result command_result, float) {
×
594
            command_result_callback(command_result, callback);
×
595
        });
×
596
}
×
597

598
void TelemetryImpl::set_rate_battery_async(double rate_hz, Telemetry::ResultCallback callback)
×
599
{
600
    _system_impl->set_msg_rate_async(
×
601
        MAVLINK_MSG_ID_BATTERY_STATUS,
602
        rate_hz,
603
        [callback](MavlinkCommandSender::Result command_result, float) {
×
604
            command_result_callback(command_result, callback);
×
605
        });
×
606
}
×
607

608
void TelemetryImpl::set_rate_rc_status_async(double rate_hz, Telemetry::ResultCallback callback)
×
609
{
NEW
610
    _rc_status_rate_hz = rate_hz;
×
NEW
611
    double max_rate_hz = std::max(_health_rate_hz, _rc_status_rate_hz);
×
612

NEW
613
    if (_system_impl->effective_autopilot() == Autopilot::ArduPilot) {
×
614
        // ArduPilot reports RC status via SYS_STATUS
NEW
615
        _system_impl->set_msg_rate_async(
×
616
            MAVLINK_MSG_ID_SYS_STATUS,
617
            max_rate_hz,
NEW
618
            [callback](MavlinkCommandSender::Result command_result, float) {
×
NEW
619
                command_result_callback(command_result, callback);
×
NEW
620
            });
×
621
    } else {
622
        // PX4 reports RC data via RC_CHANNELS
NEW
623
        _system_impl->set_msg_rate_async(
×
624
            MAVLINK_MSG_ID_RC_CHANNELS,
625
            rate_hz,
NEW
626
            [this, callback, max_rate_hz](MavlinkCommandSender::Result command_result, float) {
×
NEW
627
                if (command_result != MavlinkCommandSender::Result::Success) {
×
NEW
628
                    command_result_callback(command_result, callback);
×
NEW
629
                    return;
×
630
                }
631
                // Also update SYS_STATUS rate
NEW
632
                _system_impl->set_msg_rate_async(
×
633
                    MAVLINK_MSG_ID_SYS_STATUS,
634
                    max_rate_hz,
NEW
635
                    [callback](MavlinkCommandSender::Result command_result2, float) {
×
NEW
636
                        command_result_callback(command_result2, callback);
×
NEW
637
                    });
×
638
            });
639
    }
UNCOV
640
}
×
641

642
void TelemetryImpl::set_rate_unix_epoch_time_async(
×
643
    double rate_hz, Telemetry::ResultCallback callback)
644
{
645
    _system_impl->set_msg_rate_async(
×
646
        MAVLINK_MSG_ID_SYSTEM_TIME,
647
        rate_hz,
648
        [callback](MavlinkCommandSender::Result command_result, float) {
×
649
            command_result_callback(command_result, callback);
×
650
        });
×
651
}
×
652

653
void TelemetryImpl::set_rate_actuator_control_target_async(
×
654
    double rate_hz, Telemetry::ResultCallback callback)
655
{
656
    _system_impl->set_msg_rate_async(
×
657
        MAVLINK_MSG_ID_ACTUATOR_CONTROL_TARGET,
658
        rate_hz,
659
        [callback](MavlinkCommandSender::Result command_result, float) {
×
660
            command_result_callback(command_result, callback);
×
661
        });
×
662
}
×
663

664
void TelemetryImpl::set_rate_actuator_output_status_async(
×
665
    double rate_hz, Telemetry::ResultCallback callback)
666
{
667
    _system_impl->set_msg_rate_async(
×
668
        MAVLINK_MSG_ID_ACTUATOR_OUTPUT_STATUS,
669
        rate_hz,
670
        [callback](MavlinkCommandSender::Result command_result, float) {
×
671
            command_result_callback(command_result, callback);
×
672
        });
×
673
}
×
674

675
void TelemetryImpl::set_rate_odometry_async(double rate_hz, Telemetry::ResultCallback callback)
×
676
{
677
    _system_impl->set_msg_rate_async(
×
678
        MAVLINK_MSG_ID_ODOMETRY,
679
        rate_hz,
680
        [callback](MavlinkCommandSender::Result command_result, float) {
×
681
            command_result_callback(command_result, callback);
×
682
        });
×
683
}
×
684

685
void TelemetryImpl::set_rate_distance_sensor_async(
×
686
    double rate_hz, Telemetry::ResultCallback callback)
687
{
688
    _system_impl->set_msg_rate_async(
×
689
        MAVLINK_MSG_ID_DISTANCE_SENSOR,
690
        rate_hz,
691
        [callback](MavlinkCommandSender::Result command_result, float) {
×
692
            command_result_callback(command_result, callback);
×
693
        });
×
694
}
×
695

696
void TelemetryImpl::set_rate_scaled_pressure_async(
×
697
    double rate_hz, Telemetry::ResultCallback callback)
698
{
699
    _system_impl->set_msg_rate_async(
×
700
        MAVLINK_MSG_ID_SCALED_PRESSURE,
701
        rate_hz,
702
        [callback](MavlinkCommandSender::Result command_result, float) {
×
703
            command_result_callback(command_result, callback);
×
704
        });
×
705
}
×
706

707
Telemetry::Result
708
TelemetryImpl::telemetry_result_from_command_result(MavlinkCommandSender::Result command_result)
×
709
{
710
    switch (command_result) {
×
711
        case MavlinkCommandSender::Result::Success:
×
712
            return Telemetry::Result::Success;
×
713
        case MavlinkCommandSender::Result::NoSystem:
×
714
            return Telemetry::Result::NoSystem;
×
715
        case MavlinkCommandSender::Result::ConnectionError:
×
716
            return Telemetry::Result::ConnectionError;
×
717
        case MavlinkCommandSender::Result::Busy:
×
718
            return Telemetry::Result::Busy;
×
719
        case MavlinkCommandSender::Result::Denied:
×
720
            // FALLTHROUGH
721
        case MavlinkCommandSender::Result::TemporarilyRejected:
722
            return Telemetry::Result::CommandDenied;
×
723
        case MavlinkCommandSender::Result::Timeout:
×
724
            return Telemetry::Result::Timeout;
×
725
        case MavlinkCommandSender::Result::Unsupported:
×
726
            return Telemetry::Result::Unsupported;
×
727
        default:
×
728
            return Telemetry::Result::Unknown;
×
729
    }
730
}
731

732
void TelemetryImpl::command_result_callback(
×
733
    MavlinkCommandSender::Result command_result, const Telemetry::ResultCallback& callback)
734
{
735
    Telemetry::Result action_result = telemetry_result_from_command_result(command_result);
×
736

737
    callback(action_result);
×
738
}
×
739

740
void TelemetryImpl::process_position_velocity_ned(const mavlink_message_t& message)
×
741
{
742
    mavlink_local_position_ned_t local_position;
743
    mavlink_msg_local_position_ned_decode(&message, &local_position);
×
744

745
    Telemetry::PositionVelocityNed position_velocity;
×
746
    position_velocity.position.north_m = local_position.x;
×
747
    position_velocity.position.east_m = local_position.y;
×
748
    position_velocity.position.down_m = local_position.z;
×
749
    position_velocity.velocity.north_m_s = local_position.vx;
×
750
    position_velocity.velocity.east_m_s = local_position.vy;
×
751
    position_velocity.velocity.down_m_s = local_position.vz;
×
752

753
    set_position_velocity_ned(position_velocity);
×
754

755
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
756
    _position_velocity_ned_subscriptions.queue(position_velocity_ned(), [this](const auto& func) {
×
757
        _system_impl->call_user_callback(func);
×
758
    });
×
759

760
    set_health_local_position(true);
×
761
}
×
762

763
void TelemetryImpl::process_global_position_int(const mavlink_message_t& message)
4✔
764
{
765
    mavlink_global_position_int_t global_position_int;
766
    mavlink_msg_global_position_int_decode(&message, &global_position_int);
4✔
767

768
    {
769
        Telemetry::Position position;
4✔
770
        position.latitude_deg = global_position_int.lat * 1e-7;
4✔
771
        position.longitude_deg = global_position_int.lon * 1e-7;
4✔
772
        position.absolute_altitude_m = global_position_int.alt * 1e-3f;
4✔
773
        position.relative_altitude_m = global_position_int.relative_alt * 1e-3f;
4✔
774
        set_position(position);
4✔
775
    }
776

777
    {
778
        Telemetry::VelocityNed velocity;
4✔
779
        velocity.north_m_s = global_position_int.vx * 1e-2f;
4✔
780
        velocity.east_m_s = global_position_int.vy * 1e-2f;
4✔
781
        velocity.down_m_s = global_position_int.vz * 1e-2f;
4✔
782
        set_velocity_ned(velocity);
4✔
783
    }
784

785
    {
786
        Telemetry::Heading heading;
4✔
787
        heading.heading_deg = (global_position_int.hdg != std::numeric_limits<uint16_t>::max()) ?
4✔
788
                                  static_cast<double>(global_position_int.hdg) * 1e-2 :
4✔
789
                                  static_cast<double>(NAN);
790
        set_heading(heading);
4✔
791
    }
792

793
    std::lock_guard<std::mutex> lock(_subscription_mutex);
4✔
794
    _position_subscriptions.queue(
4✔
795
        position(), [this](const auto& func) { _system_impl->call_user_callback(func); });
3✔
796

797
    _velocity_ned_subscriptions.queue(
4✔
798
        velocity_ned(), [this](const auto& func) { _system_impl->call_user_callback(func); });
×
799

800
    _heading_subscriptions.queue(
4✔
801
        heading(), [this](const auto& func) { _system_impl->call_user_callback(func); });
×
802
}
4✔
803

804
void TelemetryImpl::process_home_position(const mavlink_message_t& message)
×
805
{
806
    mavlink_home_position_t home_position;
807
    mavlink_msg_home_position_decode(&message, &home_position);
×
808
    Telemetry::Position new_pos;
×
809
    new_pos.latitude_deg = home_position.latitude * 1e-7;
×
810
    new_pos.longitude_deg = home_position.longitude * 1e-7;
×
811
    new_pos.absolute_altitude_m = home_position.altitude * 1e-3f;
×
812
    new_pos.relative_altitude_m = 0.0f; // 0 by definition.
×
813

814
    set_home_position(new_pos);
×
815

816
    set_health_home_position(true);
×
817

818
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
819
    _home_position_subscriptions.queue(
×
820
        home(), [this](const auto& func) { _system_impl->call_user_callback(func); });
×
821
}
×
822

823
void TelemetryImpl::process_attitude(const mavlink_message_t& message)
×
824
{
825
    mavlink_attitude_t attitude;
826
    mavlink_msg_attitude_decode(&message, &attitude);
×
827

828
    Telemetry::EulerAngle euler_angle;
×
829
    euler_angle.roll_deg = to_deg_from_rad(attitude.roll);
×
830
    euler_angle.pitch_deg = to_deg_from_rad(attitude.pitch);
×
831
    euler_angle.yaw_deg = to_deg_from_rad(attitude.yaw);
×
832
    euler_angle.timestamp_us = static_cast<uint64_t>(attitude.time_boot_ms) * 1000;
×
833
    set_attitude_euler(euler_angle);
×
834

835
    Telemetry::AngularVelocityBody angular_velocity_body;
×
836
    angular_velocity_body.roll_rad_s = attitude.rollspeed;
×
837
    angular_velocity_body.pitch_rad_s = attitude.pitchspeed;
×
838
    angular_velocity_body.yaw_rad_s = attitude.yawspeed;
×
839
    set_attitude_angular_velocity_body(angular_velocity_body);
×
840

841
    _attitude_euler_angle_subscriptions.queue(
×
842
        attitude_euler(), [this](const auto& func) { _system_impl->call_user_callback(func); });
×
843

844
    _attitude_angular_velocity_body_subscriptions.queue(
×
845
        attitude_angular_velocity_body(),
846
        [this](const auto& func) { _system_impl->call_user_callback(func); });
×
847
}
×
848

849
void TelemetryImpl::process_attitude_quaternion(const mavlink_message_t& message)
×
850
{
851
    mavlink_attitude_quaternion_t mavlink_attitude_quaternion;
852
    mavlink_msg_attitude_quaternion_decode(&message, &mavlink_attitude_quaternion);
×
853

854
    Telemetry::Quaternion quaternion;
×
855
    quaternion.w = mavlink_attitude_quaternion.q1;
×
856
    quaternion.x = mavlink_attitude_quaternion.q2;
×
857
    quaternion.y = mavlink_attitude_quaternion.q3;
×
858
    quaternion.z = mavlink_attitude_quaternion.q4;
×
859
    quaternion.timestamp_us =
×
860
        static_cast<uint64_t>(mavlink_attitude_quaternion.time_boot_ms) * 1000;
×
861

862
    Telemetry::AngularVelocityBody angular_velocity_body;
×
863
    angular_velocity_body.roll_rad_s = mavlink_attitude_quaternion.rollspeed;
×
864
    angular_velocity_body.pitch_rad_s = mavlink_attitude_quaternion.pitchspeed;
×
865
    angular_velocity_body.yaw_rad_s = mavlink_attitude_quaternion.yawspeed;
×
866

867
    set_attitude_quaternion(quaternion);
×
868

869
    set_attitude_angular_velocity_body(angular_velocity_body);
×
870

871
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
872
    _attitude_quaternion_angle_subscriptions.queue(attitude_quaternion(), [this](const auto& func) {
×
873
        _system_impl->call_user_callback(func);
×
874
    });
×
875

876
    _attitude_angular_velocity_body_subscriptions.queue(
×
877
        attitude_angular_velocity_body(),
878
        [this](const auto& func) { _system_impl->call_user_callback(func); });
×
879
}
×
880

881
void TelemetryImpl::process_altitude(const mavlink_message_t& message)
4✔
882
{
883
    mavlink_altitude_t mavlink_altitude;
884
    mavlink_msg_altitude_decode(&message, &mavlink_altitude);
4✔
885

886
    Telemetry::Altitude new_altitude;
4✔
887
    new_altitude.altitude_monotonic_m = mavlink_altitude.altitude_monotonic;
4✔
888
    new_altitude.altitude_amsl_m = mavlink_altitude.altitude_amsl;
4✔
889
    new_altitude.altitude_local_m = mavlink_altitude.altitude_local;
4✔
890
    new_altitude.altitude_relative_m = mavlink_altitude.altitude_relative;
4✔
891
    new_altitude.altitude_terrain_m = mavlink_altitude.altitude_terrain;
4✔
892
    new_altitude.bottom_clearance_m = mavlink_altitude.bottom_clearance;
4✔
893
    new_altitude.timestamp_us = mavlink_altitude.time_usec;
4✔
894

895
    set_altitude(new_altitude);
4✔
896

897
    std::lock_guard<std::mutex> lock(_subscription_mutex);
4✔
898
    _altitude_subscriptions.queue(
4✔
899
        altitude(), [this](const auto& func) { _system_impl->call_user_callback(func); });
4✔
900
}
4✔
901

902
void TelemetryImpl::process_wind(const mavlink_message_t& message)
×
903
{
904
    __mavlink_wind_cov_t mavlink_wind_cov;
905
    mavlink_msg_wind_cov_decode(&message, &mavlink_wind_cov);
×
906

907
    Telemetry::Wind new_wind;
×
908
    new_wind.wind_x_ned_m_s = mavlink_wind_cov.wind_x;
×
909
    new_wind.wind_y_ned_m_s = mavlink_wind_cov.wind_y;
×
910
    new_wind.wind_z_ned_m_s = mavlink_wind_cov.wind_z;
×
911
    new_wind.horizontal_variability_stddev_m_s = mavlink_wind_cov.var_horiz;
×
912
    new_wind.vertical_variability_stddev_m_s = mavlink_wind_cov.var_vert;
×
913
    new_wind.wind_altitude_msl_m = mavlink_wind_cov.wind_alt;
×
914
    new_wind.horizontal_wind_speed_accuracy_m_s = mavlink_wind_cov.horiz_accuracy;
×
915
    new_wind.vertical_wind_speed_accuracy_m_s = mavlink_wind_cov.vert_accuracy;
×
916

917
    set_wind(new_wind);
×
918

919
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
920
    _wind_subscriptions.queue(
×
921
        wind(), [this](const auto& func) { _system_impl->call_user_callback(func); });
×
922
}
×
923

924
void TelemetryImpl::process_imu_reading_ned(const mavlink_message_t& message)
×
925
{
926
    mavlink_highres_imu_t highres_imu;
927
    mavlink_msg_highres_imu_decode(&message, &highres_imu);
×
928
    Telemetry::Imu new_imu;
×
929
    new_imu.acceleration_frd.forward_m_s2 = highres_imu.xacc;
×
930
    new_imu.acceleration_frd.right_m_s2 = highres_imu.yacc;
×
931
    new_imu.acceleration_frd.down_m_s2 = highres_imu.zacc;
×
932
    new_imu.angular_velocity_frd.forward_rad_s = highres_imu.xgyro;
×
933
    new_imu.angular_velocity_frd.right_rad_s = highres_imu.ygyro;
×
934
    new_imu.angular_velocity_frd.down_rad_s = highres_imu.zgyro;
×
935
    new_imu.magnetic_field_frd.forward_gauss = highres_imu.xmag;
×
936
    new_imu.magnetic_field_frd.right_gauss = highres_imu.ymag;
×
937
    new_imu.magnetic_field_frd.down_gauss = highres_imu.zmag;
×
938
    new_imu.temperature_degc = highres_imu.temperature;
×
939
    new_imu.timestamp_us = highres_imu.time_usec;
×
940

941
    set_imu_reading_ned(new_imu);
×
942

943
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
944
    _imu_reading_ned_subscriptions.queue(
×
945
        imu(), [this](const auto& func) { _system_impl->call_user_callback(func); });
×
946
}
×
947

948
void TelemetryImpl::process_scaled_imu(const mavlink_message_t& message)
×
949
{
950
    mavlink_scaled_imu_t scaled_imu_reading;
951
    mavlink_msg_scaled_imu_decode(&message, &scaled_imu_reading);
×
952
    Telemetry::Imu new_imu;
×
953
    // From mG to m/s^2
954
    new_imu.acceleration_frd.forward_m_s2 = scaled_imu_reading.xacc / 1000.f * 9.81f;
×
955
    new_imu.acceleration_frd.right_m_s2 = scaled_imu_reading.yacc / 1000.f * 9.81f;
×
956
    new_imu.acceleration_frd.down_m_s2 = scaled_imu_reading.zacc / 1000.f * 9.81f;
×
957
    // From mrad to rad
958
    new_imu.angular_velocity_frd.forward_rad_s = scaled_imu_reading.xgyro / 1000.f;
×
959
    new_imu.angular_velocity_frd.right_rad_s = scaled_imu_reading.ygyro / 1000.f;
×
960
    new_imu.angular_velocity_frd.down_rad_s = scaled_imu_reading.zgyro / 1000.f;
×
961
    // From milliGauss to Gauss
962
    new_imu.magnetic_field_frd.forward_gauss = scaled_imu_reading.xmag / 1000.f;
×
963
    new_imu.magnetic_field_frd.right_gauss = scaled_imu_reading.ymag / 1000.f;
×
964
    new_imu.magnetic_field_frd.down_gauss = scaled_imu_reading.zmag / 1000.f;
×
965
    new_imu.temperature_degc = static_cast<float>(scaled_imu_reading.temperature) * 1e-2f;
×
966
    new_imu.timestamp_us = static_cast<uint64_t>(scaled_imu_reading.time_boot_ms) * 1000;
×
967

968
    set_scaled_imu(new_imu);
×
969

970
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
971
    _scaled_imu_subscriptions.queue(
×
972
        scaled_imu(), [this](const auto& func) { _system_impl->call_user_callback(func); });
×
973
}
×
974

975
void TelemetryImpl::process_raw_imu(const mavlink_message_t& message)
×
976
{
977
    mavlink_raw_imu_t raw_imu_reading;
978
    mavlink_msg_raw_imu_decode(&message, &raw_imu_reading);
×
979
    Telemetry::Imu new_imu;
×
980
    new_imu.acceleration_frd.forward_m_s2 = raw_imu_reading.xacc;
×
981
    new_imu.acceleration_frd.right_m_s2 = raw_imu_reading.yacc;
×
982
    new_imu.acceleration_frd.down_m_s2 = raw_imu_reading.zacc;
×
983
    new_imu.angular_velocity_frd.forward_rad_s = raw_imu_reading.xgyro;
×
984
    new_imu.angular_velocity_frd.right_rad_s = raw_imu_reading.ygyro;
×
985
    new_imu.angular_velocity_frd.down_rad_s = raw_imu_reading.zgyro;
×
986
    new_imu.magnetic_field_frd.forward_gauss = raw_imu_reading.xmag;
×
987
    new_imu.magnetic_field_frd.right_gauss = raw_imu_reading.ymag;
×
988
    new_imu.magnetic_field_frd.down_gauss = raw_imu_reading.zmag;
×
989
    new_imu.temperature_degc = static_cast<float>(raw_imu_reading.temperature) * 1e-2f;
×
990
    new_imu.timestamp_us = raw_imu_reading.time_usec;
×
991

992
    set_raw_imu(new_imu);
×
993

994
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
995
    _raw_imu_subscriptions.queue(
×
996
        raw_imu(), [this](const auto& func) { _system_impl->call_user_callback(func); });
×
997
}
×
998

999
void TelemetryImpl::process_gps_raw_int(const mavlink_message_t& message)
1✔
1000
{
1001
    mavlink_gps_raw_int_t gps_raw_int;
1002
    mavlink_msg_gps_raw_int_decode(&message, &gps_raw_int);
1✔
1003

1004
    Telemetry::FixType fix_type;
1005
    switch (gps_raw_int.fix_type) {
1✔
1006
        case 0:
×
1007
            fix_type = Telemetry::FixType::NoGps;
×
1008
            break;
×
1009
        case 1:
×
1010
            fix_type = Telemetry::FixType::NoFix;
×
1011
            break;
×
1012
        case 2:
×
1013
            fix_type = Telemetry::FixType::Fix2D;
×
1014
            break;
×
1015
        case 3:
1✔
1016
            fix_type = Telemetry::FixType::Fix3D;
1✔
1017
            break;
1✔
1018
        case 4:
×
1019
            fix_type = Telemetry::FixType::FixDgps;
×
1020
            break;
×
1021
        case 5:
×
1022
            fix_type = Telemetry::FixType::RtkFloat;
×
1023
            break;
×
1024
        case 6:
×
1025
            fix_type = Telemetry::FixType::RtkFixed;
×
1026
            break;
×
1027

1028
        default:
×
1029
            LogErr() << "Received unknown GPS fix type!";
×
1030
            fix_type = Telemetry::FixType::NoGps;
×
1031
            break;
×
1032
    }
1033

1034
    Telemetry::GpsInfo new_gps_info;
1✔
1035
    new_gps_info.num_satellites = gps_raw_int.satellites_visible;
1✔
1036
    new_gps_info.fix_type = fix_type;
1✔
1037
    set_gps_info(new_gps_info);
1✔
1038

1039
    Telemetry::RawGps raw_gps_info;
1✔
1040
    raw_gps_info.timestamp_us = gps_raw_int.time_usec;
1✔
1041
    raw_gps_info.latitude_deg = gps_raw_int.lat * 1e-7;
1✔
1042
    raw_gps_info.longitude_deg = gps_raw_int.lon * 1e-7;
1✔
1043
    raw_gps_info.absolute_altitude_m = gps_raw_int.alt * 1e-3f;
1✔
1044
    raw_gps_info.hdop = static_cast<float>(gps_raw_int.eph) * 1e-2f;
1✔
1045
    raw_gps_info.vdop = static_cast<float>(gps_raw_int.epv) * 1e-2f;
1✔
1046
    raw_gps_info.velocity_m_s = static_cast<float>(gps_raw_int.vel) * 1e-2f;
1✔
1047
    raw_gps_info.cog_deg = static_cast<float>(gps_raw_int.cog) * 1e-2f;
1✔
1048
    raw_gps_info.altitude_ellipsoid_m = static_cast<float>(gps_raw_int.alt_ellipsoid) * 1e-3f;
1✔
1049
    raw_gps_info.horizontal_uncertainty_m = static_cast<float>(gps_raw_int.h_acc) * 1e-3f;
1✔
1050
    raw_gps_info.vertical_uncertainty_m = static_cast<float>(gps_raw_int.v_acc) * 1e-3f;
1✔
1051
    raw_gps_info.velocity_uncertainty_m_s = static_cast<float>(gps_raw_int.vel_acc) * 1e-3f;
1✔
1052
    raw_gps_info.heading_uncertainty_deg = static_cast<float>(gps_raw_int.hdg_acc) * 1e-5f;
1✔
1053
    raw_gps_info.yaw_deg = static_cast<float>(gps_raw_int.yaw) * 1e-2f;
1✔
1054
    set_raw_gps(raw_gps_info);
1✔
1055

1056
    {
1057
        std::lock_guard<std::mutex> lock(_subscription_mutex);
1✔
1058
        _gps_info_subscriptions.queue(
1✔
1059
            gps_info(), [this](const auto& func) { _system_impl->call_user_callback(func); });
×
1060
        _raw_gps_subscriptions.queue(
1✔
1061
            raw_gps(), [this](const auto& func) { _system_impl->call_user_callback(func); });
×
1062
    }
1✔
1063
}
1✔
1064

1065
void TelemetryImpl::process_ground_truth(const mavlink_message_t& message)
1✔
1066
{
1067
    mavlink_hil_state_quaternion_t hil_state_quaternion;
1068
    mavlink_msg_hil_state_quaternion_decode(&message, &hil_state_quaternion);
1✔
1069

1070
    Telemetry::GroundTruth new_ground_truth;
1✔
1071
    new_ground_truth.latitude_deg = hil_state_quaternion.lat * 1e-7;
1✔
1072
    new_ground_truth.longitude_deg = hil_state_quaternion.lon * 1e-7;
1✔
1073
    new_ground_truth.absolute_altitude_m = hil_state_quaternion.alt * 1e-3f;
1✔
1074
    new_ground_truth.timestamp_us = hil_state_quaternion.time_usec;
1✔
1075

1076
    set_ground_truth(new_ground_truth);
1✔
1077

1078
    std::lock_guard<std::mutex> lock(_subscription_mutex);
1✔
1079
    _ground_truth_subscriptions.queue(
1✔
1080
        ground_truth(), [this](const auto& func) { _system_impl->call_user_callback(func); });
1✔
1081
}
1✔
1082

1083
void TelemetryImpl::process_extended_sys_state(const mavlink_message_t& message)
×
1084
{
1085
    mavlink_extended_sys_state_t extended_sys_state;
1086
    mavlink_msg_extended_sys_state_decode(&message, &extended_sys_state);
×
1087

1088
    {
1089
        Telemetry::LandedState landed_state = to_landed_state(extended_sys_state);
×
1090
        set_landed_state(landed_state);
×
1091

1092
        Telemetry::VtolState vtol_state = to_vtol_state(extended_sys_state);
×
1093
        set_vtol_state(vtol_state);
×
1094
    }
1095

1096
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
1097
    _landed_state_subscriptions.queue(
×
1098
        landed_state(), [this](const auto& func) { _system_impl->call_user_callback(func); });
×
1099

1100
    _vtol_state_subscriptions.queue(
×
1101
        vtol_state(), [this](const auto& func) { _system_impl->call_user_callback(func); });
×
1102

1103
    if (extended_sys_state.landed_state == MAV_LANDED_STATE_IN_AIR ||
×
1104
        extended_sys_state.landed_state == MAV_LANDED_STATE_TAKEOFF ||
×
1105
        extended_sys_state.landed_state == MAV_LANDED_STATE_LANDING) {
×
1106
        set_in_air(true);
×
1107
    } else if (extended_sys_state.landed_state == MAV_LANDED_STATE_ON_GROUND) {
×
1108
        set_in_air(false);
×
1109
    }
1110
    // If landed_state is undefined, we use what we have received last.
1111

1112
    _in_air_subscriptions.queue(
×
1113
        in_air(), [this](const auto& func) { _system_impl->call_user_callback(func); });
×
1114
}
×
1115
void TelemetryImpl::process_fixedwing_metrics(const mavlink_message_t& message)
×
1116
{
1117
    mavlink_vfr_hud_t vfr_hud;
1118
    mavlink_msg_vfr_hud_decode(&message, &vfr_hud);
×
1119

1120
    Telemetry::FixedwingMetrics new_fixedwing_metrics;
×
1121
    new_fixedwing_metrics.airspeed_m_s = vfr_hud.airspeed;
×
1122
    new_fixedwing_metrics.groundspeed_m_s = vfr_hud.groundspeed;
×
1123
    new_fixedwing_metrics.heading_deg = vfr_hud.heading;
×
1124
    new_fixedwing_metrics.throttle_percentage = vfr_hud.throttle * 1e-2f;
×
1125
    new_fixedwing_metrics.absolute_altitude_m = vfr_hud.alt;
×
1126
    new_fixedwing_metrics.climb_rate_m_s = vfr_hud.climb;
×
1127

1128
    set_fixedwing_metrics(new_fixedwing_metrics);
×
1129

1130
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
1131
    _fixedwing_metrics_subscriptions.queue(
×
1132
        fixedwing_metrics(), [this](const auto& func) { _system_impl->call_user_callback(func); });
×
1133
}
×
1134

1135
void TelemetryImpl::process_sys_status(const mavlink_message_t& message)
2✔
1136
{
1137
    mavlink_sys_status_t sys_status;
1138
    mavlink_msg_sys_status_decode(&message, &sys_status);
2✔
1139

1140
    if (!_has_bat_status) {
2✔
1141
        Telemetry::Battery new_battery;
2✔
1142
        new_battery.voltage_v = sys_status.voltage_battery * 1e-3f;
2✔
1143
        new_battery.remaining_percent = sys_status.battery_remaining;
2✔
1144

1145
        set_battery(new_battery);
2✔
1146

1147
        {
1148
            std::lock_guard<std::mutex> lock(_subscription_mutex);
2✔
1149
            _battery_subscriptions.queue(
2✔
1150
                battery(), [this](const auto& func) { _system_impl->call_user_callback(func); });
×
1151
        }
2✔
1152
    }
1153

1154
    const bool rc_ok =
2✔
1155
        sys_status.onboard_control_sensors_health & MAV_SYS_STATUS_SENSOR_RC_RECEIVER;
2✔
1156

1157
    set_rc_status({rc_ok}, std::nullopt);
2✔
1158

1159
    if (sys_status.onboard_control_sensors_present & MAV_SYS_STATUS_SENSOR_3D_GYRO) {
2✔
1160
        set_health_gyrometer_calibration(
×
1161
            sys_status.onboard_control_sensors_health & MAV_SYS_STATUS_SENSOR_3D_GYRO);
×
1162
    }
1163

1164
    // PX4 v1.15.3 and previous has the bug that it doesn't set 3D_ACCEL present.
1165
    // Therefore, we ignore that and look at the health flag only.
1166
    if (sys_status.onboard_control_sensors_present & MAV_SYS_STATUS_SENSOR_3D_ACCEL ||
4✔
1167
        _system_impl->effective_autopilot() == Autopilot::Px4) {
2✔
1168
        set_health_accelerometer_calibration(
×
1169
            sys_status.onboard_control_sensors_health & MAV_SYS_STATUS_SENSOR_3D_ACCEL);
×
1170
    }
1171

1172
    if (sys_status.onboard_control_sensors_present & MAV_SYS_STATUS_SENSOR_3D_MAG) {
2✔
1173
        set_health_magnetometer_calibration(
×
1174
            sys_status.onboard_control_sensors_health & MAV_SYS_STATUS_SENSOR_3D_MAG);
×
1175
    }
1176

1177
    const bool global_position_ok =
1178
        sys_status_present_enabled_health(sys_status, MAV_SYS_STATUS_SENSOR_GPS);
2✔
1179

1180
    // FIXME: There is nothing really set in PX4 for local position from what I can tell,
1181
    //        so the best we can do for now is to set it based on GPS as a fallback.
1182

1183
    const bool local_position_ok =
1184
        global_position_ok ||
2✔
1185
        sys_status_present_enabled_health(sys_status, MAV_SYS_STATUS_SENSOR_OPTICAL_FLOW) ||
4✔
1186
        sys_status_present_enabled_health(sys_status, MAV_SYS_STATUS_SENSOR_VISION_POSITION);
2✔
1187

1188
    set_health_local_position(local_position_ok);
2✔
1189
    set_health_global_position(global_position_ok);
2✔
1190

1191
    set_rc_status({rc_ok}, std::nullopt);
2✔
1192

1193
    std::lock_guard<std::mutex> lock(_subscription_mutex);
2✔
1194
    _rc_status_subscriptions.queue(
2✔
1195
        rc_status(), [this](const auto& func) { _system_impl->call_user_callback(func); });
2✔
1196

1197
    const bool armable = sys_status.onboard_control_sensors_health & MAV_SYS_STATUS_PREARM_CHECK;
2✔
1198
    set_health_armable(armable);
2✔
1199
    _health_all_ok_subscriptions.queue(
4✔
1200
        health_all_ok(), [this](const auto& func) { _system_impl->call_user_callback(func); });
2✔
1201
}
2✔
1202

1203
bool TelemetryImpl::sys_status_present_enabled_health(
6✔
1204
    const mavlink_sys_status_t& sys_status, MAV_SYS_STATUS_SENSOR flag)
1205
{
1206
    // FIXME: it doesn't look like PX4 sets enabled for GPS
1207
    return (sys_status.onboard_control_sensors_present & flag) != 0 &&
6✔
1208
           // (sys_status.onboard_control_sensors_enabled & flag) != 0 &&
1209
           (sys_status.onboard_control_sensors_health & flag) != 0;
6✔
1210
}
1211

1212
void TelemetryImpl::process_battery_status(const mavlink_message_t& message)
×
1213
{
1214
    mavlink_battery_status_t bat_status;
1215
    mavlink_msg_battery_status_decode(&message, &bat_status);
×
1216

1217
    _has_bat_status = true;
×
1218

1219
    Telemetry::Battery new_battery;
×
1220
    new_battery.id = bat_status.id;
×
1221
    new_battery.temperature_degc = (bat_status.temperature == std::numeric_limits<int16_t>::max()) ?
×
1222
                                       static_cast<float>(NAN) :
1223
                                       bat_status.temperature * 1e-2f; // cdegC to degC
×
1224
    new_battery.voltage_v = 0.0f;
×
1225
    for (int i = 0; i < 10; ++i) {
×
1226
        if (bat_status.voltages[i] == std::numeric_limits<uint16_t>::max()) {
×
1227
            break;
×
1228
        }
1229
        new_battery.voltage_v += static_cast<float>(bat_status.voltages[i]) * 1e-3f;
×
1230
    }
1231

1232
    for (int i = 0; i < 4; ++i) {
×
1233
        if (bat_status.voltages_ext[i] == std::numeric_limits<uint16_t>::max()) {
×
1234
            // Some implementations out there set it to UINT16_MAX to signal invalid.
1235
            // That's not up to the spec but we can ignore it nevertheless to be backwards
1236
            // compatible.
1237
            break;
×
1238
        } else if (bat_status.voltages_ext[i] > 1) {
×
1239
            // A value of 1 means 0 mV.
1240
            new_battery.voltage_v += static_cast<float>(bat_status.voltages_ext[i]) * 1e-3f;
×
1241
        }
1242
    }
1243

1244
    new_battery.remaining_percent = bat_status.battery_remaining;
×
1245
    new_battery.current_battery_a = (bat_status.current_battery == -1) ?
×
1246
                                        static_cast<float>(NAN) :
1247
                                        bat_status.current_battery * 1e-2f; // cA to A
×
1248
    new_battery.capacity_consumed_ah = (bat_status.current_consumed == -1) ?
×
1249
                                           static_cast<float>(NAN) :
1250
                                           bat_status.current_consumed * 1e-3f; // mAh to Ah
×
1251
    new_battery.time_remaining_s =
×
1252
        (bat_status.time_remaining == 0 ? static_cast<float>(NAN) : bat_status.time_remaining);
×
1253

1254
    Telemetry::BatteryFunction battery_function;
1255
    switch (bat_status.battery_function) {
×
1256
        case MAV_BATTERY_FUNCTION_ALL:
×
1257
            battery_function = Telemetry::BatteryFunction::All;
×
1258
            break;
×
1259
        case MAV_BATTERY_FUNCTION_PROPULSION:
×
1260
            battery_function = Telemetry::BatteryFunction::Propulsion;
×
1261
            break;
×
1262
        case MAV_BATTERY_FUNCTION_AVIONICS:
×
1263
            battery_function = Telemetry::BatteryFunction::Avionics;
×
1264
            break;
×
1265
        case MAV_BATTERY_FUNCTION_PAYLOAD:
×
1266
            battery_function = Telemetry::BatteryFunction::Payload;
×
1267
            break;
×
1268
        case MAV_BATTERY_FUNCTION_UNKNOWN:
×
1269
        // Fallthrough
1270
        default:
1271
            battery_function = Telemetry::BatteryFunction::Unknown;
×
1272
            break;
×
1273
    }
1274
    new_battery.battery_function = battery_function;
×
1275
    set_battery(new_battery);
×
1276

1277
    {
1278
        std::lock_guard<std::mutex> lock(_subscription_mutex);
×
1279
        _battery_subscriptions.queue(
×
1280
            battery(), [this](const auto& func) { _system_impl->call_user_callback(func); });
×
1281
    }
×
1282
}
×
1283

1284
void TelemetryImpl::process_heartbeat(const mavlink_message_t& message)
4✔
1285
{
1286
    if (message.compid != MAV_COMP_ID_AUTOPILOT1) {
4✔
1287
        return;
×
1288
    }
1289

1290
    mavlink_heartbeat_t heartbeat;
1291
    mavlink_msg_heartbeat_decode(&message, &heartbeat);
4✔
1292

1293
    set_armed(((heartbeat.base_mode & MAV_MODE_FLAG_SAFETY_ARMED) ? true : false));
4✔
1294

1295
    std::lock_guard<std::mutex> lock(_subscription_mutex);
4✔
1296
    _armed_subscriptions.queue(
8✔
1297
        armed(), [this](const auto& func) { _system_impl->call_user_callback(func); });
4✔
1298

1299
    _flight_mode_subscriptions.queue(
8✔
1300
        telemetry_flight_mode_from_flight_mode(_system_impl->get_flight_mode()),
4✔
1301
        [this](const auto& func) { _system_impl->call_user_callback(func); });
×
1302

1303
    _health_subscriptions.queue(
4✔
1304
        health(), [this](const auto& func) { _system_impl->call_user_callback(func); });
×
1305

1306
    _health_all_ok_subscriptions.queue(
8✔
1307
        health_all_ok(), [this](const auto& func) { _system_impl->call_user_callback(func); });
4✔
1308
}
4✔
1309

1310
void TelemetryImpl::receive_statustext(const MavlinkStatustextHandler::Statustext& statustext)
3✔
1311
{
1312
    Telemetry::StatusText new_status_text;
3✔
1313

1314
    switch (statustext.severity) {
3✔
1315
        case MAV_SEVERITY_EMERGENCY:
×
1316
            new_status_text.type = Telemetry::StatusTextType::Emergency;
×
1317
            break;
×
1318
        case MAV_SEVERITY_ALERT:
×
1319
            new_status_text.type = Telemetry::StatusTextType::Alert;
×
1320
            break;
×
1321
        case MAV_SEVERITY_CRITICAL:
×
1322
            new_status_text.type = Telemetry::StatusTextType::Critical;
×
1323
            break;
×
1324
        case MAV_SEVERITY_ERROR:
×
1325
            new_status_text.type = Telemetry::StatusTextType::Error;
×
1326
            break;
×
1327
        case MAV_SEVERITY_WARNING:
×
1328
            new_status_text.type = Telemetry::StatusTextType::Warning;
×
1329
            break;
×
1330
        case MAV_SEVERITY_NOTICE:
×
1331
            new_status_text.type = Telemetry::StatusTextType::Notice;
×
1332
            break;
×
1333
        case MAV_SEVERITY_INFO:
3✔
1334
            new_status_text.type = Telemetry::StatusTextType::Info;
3✔
1335
            break;
3✔
1336
        case MAV_SEVERITY_DEBUG:
×
1337
            new_status_text.type = Telemetry::StatusTextType::Debug;
×
1338
            break;
×
1339
        default:
×
1340
            LogWarn() << "Unknown StatusText severity";
×
1341
            new_status_text.type = Telemetry::StatusTextType::Info;
×
1342
            break;
×
1343
    }
1344

1345
    new_status_text.text = statustext.text;
3✔
1346

1347
    set_status_text(new_status_text);
3✔
1348

1349
    std::lock_guard<std::mutex> lock(_subscription_mutex);
3✔
1350
    _status_text_subscriptions.queue(
9✔
1351
        status_text(), [this](const auto& func) { _system_impl->call_user_callback(func); });
11✔
1352
}
3✔
1353

1354
void TelemetryImpl::process_rc_channels(const mavlink_message_t& message)
1✔
1355
{
1356
    mavlink_rc_channels_t rc_channels;
1357
    mavlink_msg_rc_channels_decode(&message, &rc_channels);
1✔
1358

1359
    if (rc_channels.rssi != std::numeric_limits<uint8_t>::max()) {
1✔
1360
        set_rc_status(std::nullopt, {rc_channels.rssi});
1✔
1361
    }
1362

1363
    std::lock_guard<std::mutex> lock(_subscription_mutex);
1✔
1364
    _rc_status_subscriptions.queue(
1✔
1365
        rc_status(), [this](const auto& func) { _system_impl->call_user_callback(func); });
1✔
1366
}
1✔
1367

1368
void TelemetryImpl::process_unix_epoch_time(const mavlink_message_t& message)
×
1369
{
1370
    mavlink_system_time_t system_time;
1371
    mavlink_msg_system_time_decode(&message, &system_time);
×
1372

1373
    set_unix_epoch_time_us(system_time.time_unix_usec);
×
1374

1375
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
1376
    _unix_epoch_time_subscriptions.queue(
×
1377
        unix_epoch_time(), [this](const auto& func) { _system_impl->call_user_callback(func); });
×
1378
}
×
1379

1380
void TelemetryImpl::process_actuator_control_target(const mavlink_message_t& message)
×
1381
{
1382
    mavlink_set_actuator_control_target_t target;
1383
    mavlink_msg_set_actuator_control_target_decode(&message, &target);
×
1384

1385
    uint32_t group = target.group_mlx;
×
1386
    std::vector<float> controls;
×
1387

1388
    const unsigned control_size = sizeof(target.controls) / sizeof(target.controls[0]);
×
1389
    // Can't use std::copy because target is packed.
1390
    for (std::size_t i = 0; i < control_size; ++i) {
×
1391
        controls.push_back(target.controls[i]);
×
1392
    }
1393

1394
    set_actuator_control_target(group, controls);
×
1395

1396
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
1397
    _actuator_control_target_subscriptions.queue(
×
1398
        actuator_control_target(),
×
1399
        [this](const auto& func) { _system_impl->call_user_callback(func); });
×
1400
}
×
1401

1402
void TelemetryImpl::process_actuator_output_status(const mavlink_message_t& message)
×
1403
{
1404
    mavlink_actuator_output_status_t status;
1405
    mavlink_msg_actuator_output_status_decode(&message, &status);
×
1406

1407
    uint32_t active = status.active;
×
1408
    std::vector<float> actuators;
×
1409

1410
    const unsigned actuators_size = sizeof(status.actuator) / sizeof(status.actuator[0]);
×
1411
    // Can't use std::copy because status is packed.
1412
    for (std::size_t i = 0; i < actuators_size; ++i) {
×
1413
        actuators.push_back(status.actuator[i]);
×
1414
    }
1415

1416
    set_actuator_output_status(active, actuators);
×
1417

1418
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
1419
    _actuator_output_status_subscriptions.queue(actuator_output_status(), [this](const auto& func) {
×
1420
        _system_impl->call_user_callback(func);
×
1421
    });
×
1422
}
×
1423

1424
void TelemetryImpl::process_odometry(const mavlink_message_t& message)
×
1425
{
1426
    mavlink_odometry_t odometry_msg;
1427
    mavlink_msg_odometry_decode(&message, &odometry_msg);
×
1428

1429
    Telemetry::Odometry odometry_struct{};
×
1430

1431
    odometry_struct.time_usec = odometry_msg.time_usec;
×
1432
    odometry_struct.frame_id = static_cast<Telemetry::Odometry::MavFrame>(odometry_msg.frame_id);
×
1433
    odometry_struct.child_frame_id =
×
1434
        static_cast<Telemetry::Odometry::MavFrame>(odometry_msg.child_frame_id);
×
1435

1436
    odometry_struct.position_body.x_m = odometry_msg.x;
×
1437
    odometry_struct.position_body.y_m = odometry_msg.y;
×
1438
    odometry_struct.position_body.z_m = odometry_msg.z;
×
1439

1440
    odometry_struct.q.w = odometry_msg.q[0];
×
1441
    odometry_struct.q.x = odometry_msg.q[1];
×
1442
    odometry_struct.q.y = odometry_msg.q[2];
×
1443
    odometry_struct.q.z = odometry_msg.q[3];
×
1444

1445
    odometry_struct.velocity_body.x_m_s = odometry_msg.vx;
×
1446
    odometry_struct.velocity_body.y_m_s = odometry_msg.vy;
×
1447
    odometry_struct.velocity_body.z_m_s = odometry_msg.vz;
×
1448

1449
    odometry_struct.angular_velocity_body.roll_rad_s = odometry_msg.rollspeed;
×
1450
    odometry_struct.angular_velocity_body.pitch_rad_s = odometry_msg.pitchspeed;
×
1451
    odometry_struct.angular_velocity_body.yaw_rad_s = odometry_msg.yawspeed;
×
1452

1453
    const std::size_t len_pose_covariance =
×
1454
        sizeof(odometry_msg.pose_covariance) / sizeof(odometry_msg.pose_covariance[0]);
1455
    for (std::size_t i = 0; i < len_pose_covariance; ++i) {
×
1456
        odometry_struct.pose_covariance.covariance_matrix.push_back(
×
1457
            odometry_msg.pose_covariance[i]);
×
1458
    }
1459

1460
    const std::size_t len_velocity_covariance =
×
1461
        sizeof(odometry_msg.velocity_covariance) / sizeof(odometry_msg.velocity_covariance[0]);
1462
    for (std::size_t i = 0; i < len_velocity_covariance; ++i) {
×
1463
        odometry_struct.velocity_covariance.covariance_matrix.push_back(
×
1464
            odometry_msg.velocity_covariance[i]);
×
1465
    }
1466

1467
    set_odometry(odometry_struct);
×
1468

1469
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
1470
    _odometry_subscriptions.queue(
×
1471
        odometry(), [this](const auto& func) { _system_impl->call_user_callback(func); });
×
1472
}
×
1473

1474
void TelemetryImpl::process_distance_sensor(const mavlink_message_t& message)
×
1475
{
1476
    mavlink_distance_sensor_t distance_sensor_msg;
1477
    mavlink_msg_distance_sensor_decode(&message, &distance_sensor_msg);
×
1478

1479
    Telemetry::DistanceSensor distance_sensor_struct{};
×
1480

1481
    distance_sensor_struct.minimum_distance_m =
×
1482
        static_cast<float>(distance_sensor_msg.min_distance) * 1e-2f; // cm to m
×
1483
    distance_sensor_struct.maximum_distance_m =
×
1484
        static_cast<float>(distance_sensor_msg.max_distance) * 1e-2f; // cm to m
×
1485
    distance_sensor_struct.current_distance_m =
×
1486
        static_cast<float>(distance_sensor_msg.current_distance) * 1e-2f; // cm to m
×
1487
    distance_sensor_struct.orientation = extractOrientation(distance_sensor_msg);
×
1488

1489
    set_distance_sensor(distance_sensor_struct);
×
1490

1491
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
1492
    _distance_sensor_subscriptions.queue(
×
1493
        distance_sensor(), [this](const auto& func) { _system_impl->call_user_callback(func); });
×
1494
}
×
1495

1496
Telemetry::EulerAngle
1497
TelemetryImpl::extractOrientation(mavlink_distance_sensor_t distance_sensor_msg)
×
1498
{
1499
    MavSensorOrientation orientation =
×
1500
        static_cast<MavSensorOrientation>(distance_sensor_msg.orientation);
×
1501

1502
    Telemetry::EulerAngle euler_angle;
×
1503
    euler_angle.roll_deg = 0;
×
1504
    euler_angle.pitch_deg = 0;
×
1505
    euler_angle.yaw_deg = 0;
×
1506

1507
    switch (orientation) {
×
1508
        case MavSensorOrientation::MAV_SENSOR_ROTATION_YAW_45: {
×
1509
            euler_angle.yaw_deg = 45;
×
1510
            break;
×
1511
        }
1512
        case MavSensorOrientation::MAV_SENSOR_ROTATION_YAW_90: {
×
1513
            euler_angle.yaw_deg = 90;
×
1514
            break;
×
1515
        }
1516
        case MavSensorOrientation::MAV_SENSOR_ROTATION_YAW_135: {
×
1517
            euler_angle.yaw_deg = 135;
×
1518
            break;
×
1519
        }
1520
        case MavSensorOrientation::MAV_SENSOR_ROTATION_YAW_180: {
×
1521
            euler_angle.yaw_deg = 180;
×
1522
            break;
×
1523
        }
1524
        case MavSensorOrientation::MAV_SENSOR_ROTATION_YAW_225: {
×
1525
            euler_angle.yaw_deg = 225;
×
1526
            break;
×
1527
        }
1528
        case MavSensorOrientation::MAV_SENSOR_ROTATION_YAW_270: {
×
1529
            euler_angle.yaw_deg = 270;
×
1530
            break;
×
1531
        }
1532
        case MavSensorOrientation::MAV_SENSOR_ROTATION_YAW_315: {
×
1533
            euler_angle.yaw_deg = 315;
×
1534
            break;
×
1535
        }
1536
        case MavSensorOrientation::MAV_SENSOR_ROTATION_ROLL_180: {
×
1537
            euler_angle.roll_deg = 180;
×
1538
            break;
×
1539
        }
1540
        case MavSensorOrientation::MAV_SENSOR_ROTATION_ROLL_180_YAW_45: {
×
1541
            euler_angle.roll_deg = 180;
×
1542
            euler_angle.yaw_deg = 45;
×
1543
            break;
×
1544
        }
1545
        case MavSensorOrientation::MAV_SENSOR_ROTATION_ROLL_180_YAW_90: {
×
1546
            euler_angle.roll_deg = 180;
×
1547
            euler_angle.yaw_deg = 90;
×
1548
            break;
×
1549
        }
1550
        case MavSensorOrientation::MAV_SENSOR_ROTATION_ROLL_180_YAW_135: {
×
1551
            euler_angle.roll_deg = 180;
×
1552
            euler_angle.yaw_deg = 135;
×
1553
            break;
×
1554
        }
1555
        case MavSensorOrientation::MAV_SENSOR_ROTATION_PITCH_180: {
×
1556
            euler_angle.pitch_deg = 180;
×
1557
            break;
×
1558
        }
1559
        case MavSensorOrientation::MAV_SENSOR_ROTATION_ROLL_180_YAW_225: {
×
1560
            euler_angle.roll_deg = 180;
×
1561
            euler_angle.yaw_deg = 225;
×
1562
            break;
×
1563
        }
1564
        case MavSensorOrientation::MAV_SENSOR_ROTATION_ROLL_180_YAW_270: {
×
1565
            euler_angle.roll_deg = 180;
×
1566
            euler_angle.yaw_deg = 270;
×
1567
            break;
×
1568
        }
1569
        case MavSensorOrientation::MAV_SENSOR_ROTATION_ROLL_180_YAW_315: {
×
1570
            euler_angle.roll_deg = 180;
×
1571
            euler_angle.yaw_deg = 315;
×
1572
            break;
×
1573
        }
1574
        case MavSensorOrientation::MAV_SENSOR_ROTATION_ROLL_90: {
×
1575
            euler_angle.roll_deg = 90;
×
1576
            break;
×
1577
        }
1578
        case MavSensorOrientation::MAV_SENSOR_ROTATION_ROLL_90_YAW_45: {
×
1579
            euler_angle.roll_deg = 90;
×
1580
            euler_angle.yaw_deg = 45;
×
1581
            break;
×
1582
        }
1583
        case MavSensorOrientation::MAV_SENSOR_ROTATION_ROLL_90_YAW_90: {
×
1584
            euler_angle.roll_deg = 90;
×
1585
            euler_angle.yaw_deg = 90;
×
1586
            break;
×
1587
        }
1588
        case MavSensorOrientation::MAV_SENSOR_ROTATION_ROLL_90_YAW_135: {
×
1589
            euler_angle.roll_deg = 90;
×
1590
            euler_angle.yaw_deg = 135;
×
1591
            break;
×
1592
        }
1593
        case MavSensorOrientation::MAV_SENSOR_ROTATION_ROLL_270: {
×
1594
            euler_angle.roll_deg = 270;
×
1595
            break;
×
1596
        }
1597
        case MavSensorOrientation::MAV_SENSOR_ROTATION_ROLL_270_YAW_45: {
×
1598
            euler_angle.roll_deg = 270;
×
1599
            euler_angle.yaw_deg = 45;
×
1600
            break;
×
1601
        }
1602
        case MavSensorOrientation::MAV_SENSOR_ROTATION_ROLL_270_YAW_90: {
×
1603
            euler_angle.roll_deg = 270;
×
1604
            euler_angle.yaw_deg = 90;
×
1605
            break;
×
1606
        }
1607
        case MavSensorOrientation::MAV_SENSOR_ROTATION_ROLL_270_YAW_135: {
×
1608
            euler_angle.roll_deg = 270;
×
1609
            euler_angle.yaw_deg = 135;
×
1610
            break;
×
1611
        }
1612
        case MavSensorOrientation::MAV_SENSOR_ROTATION_PITCH_90: {
×
1613
            euler_angle.pitch_deg = 90;
×
1614
            break;
×
1615
        }
1616
        case MavSensorOrientation::MAV_SENSOR_ROTATION_PITCH_270: {
×
1617
            euler_angle.pitch_deg = 270;
×
1618
            break;
×
1619
        }
1620
        case MavSensorOrientation::MAV_SENSOR_ROTATION_PITCH_180_YAW_90: {
×
1621
            euler_angle.pitch_deg = 180;
×
1622
            euler_angle.yaw_deg = 90;
×
1623
            break;
×
1624
        }
1625
        case MavSensorOrientation::MAV_SENSOR_ROTATION_PITCH_180_YAW_270: {
×
1626
            euler_angle.pitch_deg = 180;
×
1627
            euler_angle.yaw_deg = 270;
×
1628
            break;
×
1629
        }
1630
        case MavSensorOrientation::MAV_SENSOR_ROTATION_ROLL_90_PITCH_90: {
×
1631
            euler_angle.roll_deg = 90;
×
1632
            euler_angle.pitch_deg = 90;
×
1633
            break;
×
1634
        }
1635
        case MavSensorOrientation::MAV_SENSOR_ROTATION_ROLL_180_PITCH_90: {
×
1636
            euler_angle.roll_deg = 180;
×
1637
            euler_angle.pitch_deg = 90;
×
1638
            break;
×
1639
        }
1640
        case MavSensorOrientation::MAV_SENSOR_ROTATION_ROLL_270_PITCH_90: {
×
1641
            euler_angle.roll_deg = 270;
×
1642
            euler_angle.pitch_deg = 90;
×
1643
            break;
×
1644
        }
1645
        case MavSensorOrientation::MAV_SENSOR_ROTATION_ROLL_90_PITCH_180: {
×
1646
            euler_angle.roll_deg = 90;
×
1647
            euler_angle.pitch_deg = 180;
×
1648
            break;
×
1649
        }
1650
        case MavSensorOrientation::MAV_SENSOR_ROTATION_ROLL_270_PITCH_180: {
×
1651
            euler_angle.roll_deg = 270;
×
1652
            euler_angle.pitch_deg = 180;
×
1653
            break;
×
1654
        }
1655
        case MavSensorOrientation::MAV_SENSOR_ROTATION_ROLL_90_PITCH_270: {
×
1656
            euler_angle.roll_deg = 90;
×
1657
            euler_angle.pitch_deg = 270;
×
1658
            break;
×
1659
        }
1660
        case MavSensorOrientation::MAV_SENSOR_ROTATION_ROLL_180_PITCH_270: {
×
1661
            euler_angle.roll_deg = 180;
×
1662
            euler_angle.pitch_deg = 270;
×
1663
            break;
×
1664
        }
1665
        case MavSensorOrientation::MAV_SENSOR_ROTATION_ROLL_270_PITCH_270: {
×
1666
            euler_angle.roll_deg = 270;
×
1667
            euler_angle.pitch_deg = 270;
×
1668
            break;
×
1669
        }
1670
        case MavSensorOrientation::MAV_SENSOR_ROTATION_ROLL_90_PITCH_180_YAW_90: {
×
1671
            euler_angle.roll_deg = 90;
×
1672
            euler_angle.pitch_deg = 180;
×
1673
            euler_angle.yaw_deg = 90;
×
1674
            break;
×
1675
        }
1676
        case MavSensorOrientation::MAV_SENSOR_ROTATION_ROLL_90_YAW_270: {
×
1677
            euler_angle.roll_deg = 90;
×
1678
            euler_angle.yaw_deg = 270;
×
1679
            break;
×
1680
        }
1681
        case MavSensorOrientation::MAV_SENSOR_ROTATION_ROLL_90_PITCH_68_YAW_293: {
×
1682
            euler_angle.roll_deg = 90;
×
1683
            euler_angle.pitch_deg = 68;
×
1684
            euler_angle.yaw_deg = 293;
×
1685
            break;
×
1686
        }
1687
        case MavSensorOrientation::MAV_SENSOR_ROTATION_PITCH_315: {
×
1688
            euler_angle.pitch_deg = 315;
×
1689
            break;
×
1690
        }
1691
        case MavSensorOrientation::MAV_SENSOR_ROTATION_ROLL_90_PITCH_315: {
×
1692
            euler_angle.roll_deg = 90;
×
1693
            euler_angle.pitch_deg = 315;
×
1694
            break;
×
1695
        }
1696
        default: {
×
1697
            euler_angle.roll_deg = 0;
×
1698
            euler_angle.pitch_deg = 0;
×
1699
            euler_angle.yaw_deg = 0;
×
1700
        }
1701
    }
1702

1703
    return euler_angle;
×
1704
}
1705

1706
void TelemetryImpl::process_scaled_pressure(const mavlink_message_t& message)
×
1707
{
1708
    mavlink_scaled_pressure_t scaled_pressure_msg;
1709
    mavlink_msg_scaled_pressure_decode(&message, &scaled_pressure_msg);
×
1710

1711
    Telemetry::ScaledPressure scaled_pressure_struct{};
×
1712

1713
    scaled_pressure_struct.timestamp_us =
×
1714
        static_cast<uint64_t>(scaled_pressure_msg.time_boot_ms) * 1000;
×
1715
    scaled_pressure_struct.absolute_pressure_hpa = scaled_pressure_msg.press_abs;
×
1716
    scaled_pressure_struct.differential_pressure_hpa = scaled_pressure_msg.press_diff;
×
1717
    scaled_pressure_struct.temperature_deg =
×
1718
        static_cast<float>(scaled_pressure_msg.temperature) * 1e-2f;
×
1719
    scaled_pressure_struct.differential_pressure_temperature_deg =
×
1720
        static_cast<float>(scaled_pressure_msg.temperature_press_diff) * 1e-2f;
×
1721

1722
    set_scaled_pressure(scaled_pressure_struct);
×
1723

1724
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
1725
    _scaled_pressure_subscriptions.queue(
×
1726
        scaled_pressure(), [this](const auto& func) { _system_impl->call_user_callback(func); });
×
1727
}
×
1728

1729
Telemetry::LandedState
1730
TelemetryImpl::to_landed_state(mavlink_extended_sys_state_t extended_sys_state)
×
1731
{
1732
    switch (extended_sys_state.landed_state) {
×
1733
        case MAV_LANDED_STATE_IN_AIR:
×
1734
            return Telemetry::LandedState::InAir;
×
1735
        case MAV_LANDED_STATE_TAKEOFF:
×
1736
            return Telemetry::LandedState::TakingOff;
×
1737
        case MAV_LANDED_STATE_LANDING:
×
1738
            return Telemetry::LandedState::Landing;
×
1739
        case MAV_LANDED_STATE_ON_GROUND:
×
1740
            return Telemetry::LandedState::OnGround;
×
1741
        default:
×
1742
            return Telemetry::LandedState::Unknown;
×
1743
    }
1744
}
1745

1746
Telemetry::VtolState TelemetryImpl::to_vtol_state(mavlink_extended_sys_state_t extended_sys_state)
×
1747
{
1748
    switch (extended_sys_state.vtol_state) {
×
1749
        case MAV_VTOL_STATE::MAV_VTOL_STATE_TRANSITION_TO_FW:
×
1750
            return Telemetry::VtolState::TransitionToFw;
×
1751
        case MAV_VTOL_STATE_TRANSITION_TO_MC:
×
1752
            return Telemetry::VtolState::TransitionToMc;
×
1753
        case MAV_VTOL_STATE_MC:
×
1754
            return Telemetry::VtolState::Mc;
×
1755
        case MAV_VTOL_STATE_FW:
×
1756
            return Telemetry::VtolState::Fw;
×
1757
        default:
×
1758
            return Telemetry::VtolState::Undefined;
×
1759
    }
1760
}
1761

1762
Telemetry::FlightMode TelemetryImpl::telemetry_flight_mode_from_flight_mode(FlightMode flight_mode)
4✔
1763
{
1764
    switch (flight_mode) {
4✔
1765
        case FlightMode::Ready:
×
1766
            return Telemetry::FlightMode::Ready;
×
1767
        case FlightMode::Takeoff:
×
1768
            return Telemetry::FlightMode::Takeoff;
×
1769
        case FlightMode::Hold:
×
1770
            return Telemetry::FlightMode::Hold;
×
1771
        case FlightMode::Mission:
×
1772
            return Telemetry::FlightMode::Mission;
×
1773
        case FlightMode::ReturnToLaunch:
×
1774
            return Telemetry::FlightMode::ReturnToLaunch;
×
1775
        case FlightMode::Land:
×
1776
            return Telemetry::FlightMode::Land;
×
1777
        case FlightMode::Offboard:
×
1778
            return Telemetry::FlightMode::Offboard;
×
1779
        case FlightMode::FollowMe:
×
1780
            return Telemetry::FlightMode::FollowMe;
×
1781
        case FlightMode::Manual:
×
1782
            return Telemetry::FlightMode::Manual;
×
1783
        case FlightMode::Posctl:
×
1784
            return Telemetry::FlightMode::Posctl;
×
1785
        case FlightMode::Altctl:
×
1786
            return Telemetry::FlightMode::Altctl;
×
1787
        case FlightMode::Rattitude:
×
1788
            return Telemetry::FlightMode::Rattitude;
×
1789
        case FlightMode::Acro:
×
1790
            return Telemetry::FlightMode::Acro;
×
1791
        case FlightMode::Stabilized:
×
1792
            return Telemetry::FlightMode::Stabilized;
×
1793
        default:
4✔
1794
            return Telemetry::FlightMode::Unknown;
4✔
1795
    }
1796
}
1797

1798
Telemetry::PositionVelocityNed TelemetryImpl::position_velocity_ned() const
×
1799
{
1800
    std::lock_guard<std::mutex> lock(_position_velocity_ned_mutex);
×
1801
    return _position_velocity_ned;
×
1802
}
×
1803

1804
void TelemetryImpl::set_position_velocity_ned(Telemetry::PositionVelocityNed position_velocity_ned)
×
1805
{
1806
    std::lock_guard<std::mutex> lock(_position_velocity_ned_mutex);
×
1807
    _position_velocity_ned = position_velocity_ned;
×
1808
}
×
1809

1810
Telemetry::Position TelemetryImpl::position() const
4✔
1811
{
1812
    std::lock_guard<std::mutex> lock(_position_mutex);
4✔
1813
    return _position;
8✔
1814
}
4✔
1815

1816
void TelemetryImpl::set_position(Telemetry::Position position)
4✔
1817
{
1818
    std::lock_guard<std::mutex> lock(_position_mutex);
4✔
1819
    _position = position;
4✔
1820
}
4✔
1821

1822
Telemetry::Heading TelemetryImpl::heading() const
4✔
1823
{
1824
    std::lock_guard<std::mutex> lock(_heading_mutex);
4✔
1825
    return _heading;
8✔
1826
}
4✔
1827

1828
void TelemetryImpl::set_heading(Telemetry::Heading heading)
4✔
1829
{
1830
    std::lock_guard<std::mutex> lock(_heading_mutex);
4✔
1831
    _heading = heading;
4✔
1832
}
4✔
1833

1834
Telemetry::Altitude TelemetryImpl::altitude() const
5✔
1835
{
1836
    std::lock_guard<std::mutex> lock(_altitude_mutex);
5✔
1837
    return _altitude;
10✔
1838
}
5✔
1839

1840
void TelemetryImpl::set_altitude(Telemetry::Altitude altitude)
4✔
1841
{
1842
    std::lock_guard<std::mutex> lock(_altitude_mutex);
4✔
1843
    _altitude = altitude;
4✔
1844
}
4✔
1845

1846
Telemetry::Wind TelemetryImpl::wind() const
×
1847
{
1848
    std::lock_guard<std::mutex> lock(_wind_mutex);
×
1849
    return _wind;
×
1850
}
×
1851

1852
void TelemetryImpl::set_wind(Telemetry::Wind wind)
×
1853
{
1854
    std::lock_guard<std::mutex> lock(_wind_mutex);
×
1855
    _wind = wind;
×
1856
}
×
1857

1858
Telemetry::Position TelemetryImpl::home() const
×
1859
{
1860
    std::lock_guard<std::mutex> lock(_home_position_mutex);
×
1861
    return _home_position;
×
1862
}
×
1863

1864
void TelemetryImpl::set_home_position(Telemetry::Position home_position)
×
1865
{
1866
    std::lock_guard<std::mutex> lock(_home_position_mutex);
×
1867
    _home_position = home_position;
×
1868
}
×
1869

1870
bool TelemetryImpl::armed() const
4✔
1871
{
1872
    return _armed;
4✔
1873
}
1874

1875
bool TelemetryImpl::in_air() const
×
1876
{
1877
    return _in_air;
×
1878
}
1879

1880
void TelemetryImpl::set_in_air(bool in_air_new)
×
1881
{
1882
    _in_air = in_air_new;
×
1883
}
×
1884

1885
void TelemetryImpl::set_status_text(Telemetry::StatusText status_text)
3✔
1886
{
1887
    std::lock_guard<std::mutex> lock(_status_text_mutex);
3✔
1888
    _status_text = status_text;
3✔
1889
}
3✔
1890

1891
Telemetry::StatusText TelemetryImpl::status_text() const
3✔
1892
{
1893
    std::lock_guard<std::mutex> lock(_status_text_mutex);
3✔
1894
    return _status_text;
3✔
1895
}
3✔
1896

1897
void TelemetryImpl::set_armed(bool armed_new)
4✔
1898
{
1899
    _armed = armed_new;
4✔
1900
}
4✔
1901

1902
Telemetry::Quaternion TelemetryImpl::attitude_quaternion() const
×
1903
{
1904
    std::lock_guard<std::mutex> lock(_attitude_quaternion_mutex);
×
1905
    return _attitude_quaternion;
×
1906
}
×
1907

1908
Telemetry::AngularVelocityBody TelemetryImpl::attitude_angular_velocity_body() const
×
1909
{
1910
    std::lock_guard<std::mutex> lock(_attitude_angular_velocity_body_mutex);
×
1911
    return _attitude_angular_velocity_body;
×
1912
}
×
1913

1914
Telemetry::GroundTruth TelemetryImpl::ground_truth() const
1✔
1915
{
1916
    std::lock_guard<std::mutex> lock(_ground_truth_mutex);
1✔
1917
    return _ground_truth;
2✔
1918
}
1✔
1919

1920
Telemetry::FixedwingMetrics TelemetryImpl::fixedwing_metrics() const
×
1921
{
1922
    std::lock_guard<std::mutex> lock(_fixedwing_metrics_mutex);
×
1923
    return _fixedwing_metrics;
×
1924
}
×
1925

1926
Telemetry::EulerAngle TelemetryImpl::attitude_euler() const
×
1927
{
1928
    std::lock_guard<std::mutex> lock(_attitude_euler_mutex);
×
1929
    return _attitude_euler;
×
1930
}
×
1931

1932
void TelemetryImpl::set_attitude_quaternion(Telemetry::Quaternion quaternion)
×
1933
{
1934
    std::lock_guard<std::mutex> lock(_attitude_quaternion_mutex);
×
1935
    _attitude_quaternion = quaternion;
×
1936
}
×
1937

1938
void TelemetryImpl::set_attitude_euler(Telemetry::EulerAngle euler)
×
1939
{
1940
    std::lock_guard<std::mutex> lock(_attitude_euler_mutex);
×
1941
    _attitude_euler = euler;
×
1942
}
×
1943

1944
void TelemetryImpl::set_attitude_angular_velocity_body(
×
1945
    Telemetry::AngularVelocityBody angular_velocity_body)
1946
{
1947
    std::lock_guard<std::mutex> lock(_attitude_quaternion_mutex);
×
1948
    _attitude_angular_velocity_body = angular_velocity_body;
×
1949
}
×
1950

1951
void TelemetryImpl::set_ground_truth(Telemetry::GroundTruth ground_truth)
1✔
1952
{
1953
    std::lock_guard<std::mutex> lock(_ground_truth_mutex);
1✔
1954
    _ground_truth = ground_truth;
1✔
1955
}
1✔
1956

1957
void TelemetryImpl::set_fixedwing_metrics(Telemetry::FixedwingMetrics fixedwing_metrics)
×
1958
{
1959
    std::lock_guard<std::mutex> lock(_fixedwing_metrics_mutex);
×
1960
    _fixedwing_metrics = fixedwing_metrics;
×
1961
}
×
1962

1963
Telemetry::VelocityNed TelemetryImpl::velocity_ned() const
4✔
1964
{
1965
    std::lock_guard<std::mutex> lock(_velocity_ned_mutex);
4✔
1966
    return _velocity_ned;
8✔
1967
}
4✔
1968

1969
void TelemetryImpl::set_velocity_ned(Telemetry::VelocityNed velocity_ned)
4✔
1970
{
1971
    std::lock_guard<std::mutex> lock(_velocity_ned_mutex);
4✔
1972
    _velocity_ned = velocity_ned;
4✔
1973
}
4✔
1974

1975
Telemetry::Imu TelemetryImpl::imu() const
×
1976
{
1977
    std::lock_guard<std::mutex> lock(_imu_reading_ned_mutex);
×
1978
    return _imu_reading_ned;
×
1979
}
×
1980

1981
void TelemetryImpl::set_imu_reading_ned(Telemetry::Imu imu_reading_ned)
×
1982
{
1983
    std::lock_guard<std::mutex> lock(_imu_reading_ned_mutex);
×
1984
    _imu_reading_ned = imu_reading_ned;
×
1985
}
×
1986

1987
Telemetry::Imu TelemetryImpl::scaled_imu() const
×
1988
{
1989
    std::lock_guard<std::mutex> lock(_scaled_imu_mutex);
×
1990
    return _scaled_imu;
×
1991
}
×
1992

1993
void TelemetryImpl::set_scaled_imu(Telemetry::Imu scaled_imu)
×
1994
{
1995
    std::lock_guard<std::mutex> lock(_scaled_imu_mutex);
×
1996
    _scaled_imu = scaled_imu;
×
1997
}
×
1998

1999
Telemetry::Imu TelemetryImpl::raw_imu() const
×
2000
{
2001
    std::lock_guard<std::mutex> lock(_raw_imu_mutex);
×
2002
    return _raw_imu;
×
2003
}
×
2004

2005
void TelemetryImpl::set_raw_imu(Telemetry::Imu raw_imu)
×
2006
{
2007
    std::lock_guard<std::mutex> lock(_raw_imu_mutex);
×
2008
    _raw_imu = raw_imu;
×
2009
}
×
2010

2011
Telemetry::GpsInfo TelemetryImpl::gps_info() const
1✔
2012
{
2013
    std::lock_guard<std::mutex> lock(_gps_info_mutex);
1✔
2014
    return _gps_info;
2✔
2015
}
1✔
2016

2017
void TelemetryImpl::set_gps_info(Telemetry::GpsInfo gps_info)
1✔
2018
{
2019
    std::lock_guard<std::mutex> lock(_gps_info_mutex);
1✔
2020
    _gps_info = gps_info;
1✔
2021
}
1✔
2022

2023
Telemetry::RawGps TelemetryImpl::raw_gps() const
1✔
2024
{
2025
    std::lock_guard<std::mutex> lock(_raw_gps_mutex);
1✔
2026
    return _raw_gps;
2✔
2027
}
1✔
2028

2029
void TelemetryImpl::set_raw_gps(Telemetry::RawGps raw_gps)
1✔
2030
{
2031
    std::lock_guard<std::mutex> lock(_raw_gps_mutex);
1✔
2032
    _raw_gps = raw_gps;
1✔
2033
}
1✔
2034

2035
Telemetry::Battery TelemetryImpl::battery() const
2✔
2036
{
2037
    std::lock_guard<std::mutex> lock(_battery_mutex);
2✔
2038
    return _battery;
4✔
2039
}
2✔
2040

2041
void TelemetryImpl::set_battery(Telemetry::Battery battery)
2✔
2042
{
2043
    std::lock_guard<std::mutex> lock(_battery_mutex);
2✔
2044
    _battery = battery;
2✔
2045
}
2✔
2046

2047
Telemetry::FlightMode TelemetryImpl::flight_mode() const
×
2048
{
2049
    return telemetry_flight_mode_from_flight_mode(_system_impl->get_flight_mode());
×
2050
}
2051

2052
Telemetry::Health TelemetryImpl::health() const
4✔
2053
{
2054
    std::lock_guard<std::mutex> lock(_health_mutex);
4✔
2055
    return _health;
8✔
2056
}
4✔
2057

2058
bool TelemetryImpl::health_all_ok() const
6✔
2059
{
2060
    std::lock_guard<std::mutex> lock(_health_mutex);
6✔
2061
    if (_health.is_gyrometer_calibration_ok && _health.is_accelerometer_calibration_ok &&
6✔
2062
        _health.is_magnetometer_calibration_ok && _health.is_local_position_ok &&
×
2063
        _health.is_global_position_ok && _health.is_home_position_ok) {
×
2064
        return true;
×
2065
    } else {
2066
        return false;
6✔
2067
    }
2068
}
6✔
2069

2070
Telemetry::RcStatus TelemetryImpl::rc_status() const
3✔
2071
{
2072
    std::lock_guard<std::mutex> lock(_rc_status_mutex);
3✔
2073
    return _rc_status;
6✔
2074
}
3✔
2075

2076
uint64_t TelemetryImpl::unix_epoch_time() const
×
2077
{
2078
    std::lock_guard<std::mutex> lock(_unix_epoch_time_mutex);
×
2079
    return _unix_epoch_time_us;
×
2080
}
×
2081

2082
Telemetry::ActuatorControlTarget TelemetryImpl::actuator_control_target() const
×
2083
{
2084
    std::lock_guard<std::mutex> lock(_actuator_control_target_mutex);
×
2085
    return _actuator_control_target;
×
2086
}
×
2087

2088
Telemetry::ActuatorOutputStatus TelemetryImpl::actuator_output_status() const
×
2089
{
2090
    std::lock_guard<std::mutex> lock(_actuator_output_status_mutex);
×
2091
    return _actuator_output_status;
×
2092
}
×
2093

2094
Telemetry::Odometry TelemetryImpl::odometry() const
×
2095
{
2096
    std::lock_guard<std::mutex> lock(_odometry_mutex);
×
2097
    return _odometry;
×
2098
}
×
2099

2100
Telemetry::DistanceSensor TelemetryImpl::distance_sensor() const
×
2101
{
2102
    std::lock_guard<std::mutex> lock(_distance_sensor_mutex);
×
2103
    return _distance_sensor;
×
2104
}
×
2105

2106
Telemetry::ScaledPressure TelemetryImpl::scaled_pressure() const
×
2107
{
2108
    std::lock_guard<std::mutex> lock(_scaled_pressure_mutex);
×
2109
    return _scaled_pressure;
×
2110
}
×
2111

2112
void TelemetryImpl::set_health_local_position(bool ok)
2✔
2113
{
2114
    std::lock_guard<std::mutex> lock(_health_mutex);
2✔
2115
    _health.is_local_position_ok = ok;
2✔
2116
}
2✔
2117

2118
void TelemetryImpl::set_health_global_position(bool ok)
2✔
2119
{
2120
    std::lock_guard<std::mutex> lock(_health_mutex);
2✔
2121
    _health.is_global_position_ok = ok;
2✔
2122
}
2✔
2123

2124
void TelemetryImpl::set_health_home_position(bool ok)
×
2125
{
2126
    std::lock_guard<std::mutex> lock(_health_mutex);
×
2127
    _health.is_home_position_ok = ok;
×
2128
}
×
2129

2130
void TelemetryImpl::set_health_gyrometer_calibration(bool ok)
×
2131
{
2132
    std::lock_guard<std::mutex> lock(_health_mutex);
×
2133
    _health.is_gyrometer_calibration_ok = ok;
×
2134
}
×
2135

2136
void TelemetryImpl::set_health_accelerometer_calibration(bool ok)
×
2137
{
2138
    std::lock_guard<std::mutex> lock(_health_mutex);
×
2139
    _health.is_accelerometer_calibration_ok = ok;
×
2140
}
×
2141

2142
void TelemetryImpl::set_health_magnetometer_calibration(bool ok)
×
2143
{
2144
    std::lock_guard<std::mutex> lock(_health_mutex);
×
2145
    _health.is_magnetometer_calibration_ok = ok;
×
2146
}
×
2147

2148
void TelemetryImpl::set_health_armable(bool ok)
2✔
2149
{
2150
    std::lock_guard<std::mutex> lock(_health_mutex);
2✔
2151
    _health.is_armable = ok;
2✔
2152
}
2✔
2153

2154
Telemetry::VtolState TelemetryImpl::vtol_state() const
×
2155
{
2156
    std::lock_guard<std::mutex> lock(_vtol_state_mutex);
×
2157
    return _vtol_state;
×
2158
}
×
2159

2160
void TelemetryImpl::set_vtol_state(Telemetry::VtolState vtol_state)
×
2161
{
2162
    std::lock_guard<std::mutex> lock(_vtol_state_mutex);
×
2163
    _vtol_state = vtol_state;
×
2164
}
×
2165

2166
Telemetry::LandedState TelemetryImpl::landed_state() const
×
2167
{
2168
    std::lock_guard<std::mutex> lock(_landed_state_mutex);
×
2169
    return _landed_state;
×
2170
}
×
2171

2172
void TelemetryImpl::set_landed_state(Telemetry::LandedState landed_state)
×
2173
{
2174
    std::lock_guard<std::mutex> lock(_landed_state_mutex);
×
2175
    _landed_state = landed_state;
×
2176
}
×
2177

2178
void TelemetryImpl::set_rc_status(
5✔
2179
    std::optional<bool> maybe_available, std::optional<float> maybe_signal_strength_percent)
2180
{
2181
    std::lock_guard<std::mutex> lock(_rc_status_mutex);
5✔
2182

2183
    if (maybe_available) {
5✔
2184
        _rc_status.is_available = maybe_available.value();
4✔
2185
        if (maybe_available.value()) {
4✔
2186
            _rc_status.was_available_once = true;
2✔
2187
        }
2188
    }
2189

2190
    if (maybe_signal_strength_percent) {
5✔
2191
        _rc_status.signal_strength_percent = maybe_signal_strength_percent.value();
1✔
2192
    }
2193
}
5✔
2194

2195
void TelemetryImpl::set_unix_epoch_time_us(uint64_t time_us)
×
2196
{
2197
    std::lock_guard<std::mutex> lock(_unix_epoch_time_mutex);
×
2198
    _unix_epoch_time_us = time_us;
×
2199
}
×
2200

2201
void TelemetryImpl::set_actuator_control_target(uint8_t group, const std::vector<float>& controls)
×
2202
{
2203
    std::lock_guard<std::mutex> lock(_actuator_control_target_mutex);
×
2204
    _actuator_control_target.group = group;
×
2205
    _actuator_control_target.controls = controls;
×
2206
}
×
2207

2208
void TelemetryImpl::set_actuator_output_status(uint32_t active, const std::vector<float>& actuators)
×
2209
{
2210
    std::lock_guard<std::mutex> lock(_actuator_output_status_mutex);
×
2211
    _actuator_output_status.active = active;
×
2212
    _actuator_output_status.actuator = actuators;
×
2213
}
×
2214

2215
void TelemetryImpl::set_odometry(Telemetry::Odometry& odometry)
×
2216
{
2217
    std::lock_guard<std::mutex> lock(_odometry_mutex);
×
2218
    _odometry = odometry;
×
2219
}
×
2220

2221
void TelemetryImpl::set_distance_sensor(Telemetry::DistanceSensor& distance_sensor)
×
2222
{
2223
    std::lock_guard<std::mutex> lock(_distance_sensor_mutex);
×
2224
    _distance_sensor = distance_sensor;
×
2225
}
×
2226

2227
void TelemetryImpl::set_scaled_pressure(Telemetry::ScaledPressure& scaled_pressure)
×
2228
{
2229
    std::lock_guard<std::mutex> lock(_scaled_pressure_mutex);
×
2230
    _scaled_pressure = scaled_pressure;
×
2231
}
×
2232

2233
Telemetry::PositionVelocityNedHandle TelemetryImpl::subscribe_position_velocity_ned(
×
2234
    const Telemetry::PositionVelocityNedCallback& callback)
2235
{
2236
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2237
    return _position_velocity_ned_subscriptions.subscribe(callback);
×
2238
}
×
2239

2240
void TelemetryImpl::unsubscribe_position_velocity_ned(Telemetry::PositionVelocityNedHandle handle)
×
2241
{
2242
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2243
    _position_velocity_ned_subscriptions.unsubscribe(handle);
×
2244
}
×
2245

2246
Telemetry::PositionHandle
2247
TelemetryImpl::subscribe_position(const Telemetry::PositionCallback& callback)
3✔
2248
{
2249
    std::lock_guard<std::mutex> lock(_subscription_mutex);
3✔
2250
    return _position_subscriptions.subscribe(callback);
3✔
2251
}
3✔
2252

2253
void TelemetryImpl::unsubscribe_position(Telemetry::PositionHandle handle)
3✔
2254
{
2255
    std::lock_guard<std::mutex> lock(_subscription_mutex);
3✔
2256
    _position_subscriptions.unsubscribe(handle);
3✔
2257
}
3✔
2258

2259
Telemetry::HomeHandle TelemetryImpl::subscribe_home(const Telemetry::PositionCallback& callback)
×
2260
{
2261
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2262
    return _home_position_subscriptions.subscribe(callback);
×
2263
}
×
2264

2265
void TelemetryImpl::unsubscribe_home(Telemetry::HomeHandle handle)
×
2266
{
2267
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2268
    _home_position_subscriptions.unsubscribe(handle);
×
2269
}
×
2270

2271
Telemetry::InAirHandle TelemetryImpl::subscribe_in_air(const Telemetry::InAirCallback& callback)
×
2272
{
2273
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2274
    return _in_air_subscriptions.subscribe(callback);
×
2275
}
×
2276

2277
void TelemetryImpl::unsubscribe_in_air(Telemetry::InAirHandle handle)
×
2278
{
2279
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2280
    return _in_air_subscriptions.unsubscribe(handle);
×
2281
}
×
2282

2283
Telemetry::StatusTextHandle
2284
TelemetryImpl::subscribe_status_text(const Telemetry::StatusTextCallback& callback)
2✔
2285
{
2286
    std::lock_guard<std::mutex> lock(_subscription_mutex);
2✔
2287
    return _status_text_subscriptions.subscribe(callback);
2✔
2288
}
2✔
2289

2290
void TelemetryImpl::unsubscribe_status_text(Handle<Telemetry::StatusText> handle)
1✔
2291
{
2292
    std::lock_guard<std::mutex> lock(_subscription_mutex);
1✔
2293
    _status_text_subscriptions.unsubscribe(handle);
1✔
2294
}
1✔
2295

2296
Telemetry::ArmedHandle TelemetryImpl::subscribe_armed(const Telemetry::ArmedCallback& callback)
×
2297
{
2298
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2299
    return _armed_subscriptions.subscribe(callback);
×
2300
}
×
2301

2302
void TelemetryImpl::unsubscribe_armed(Telemetry::ArmedHandle handle)
×
2303
{
2304
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2305
    _armed_subscriptions.unsubscribe(handle);
×
2306
}
×
2307

2308
Telemetry::AttitudeQuaternionHandle
2309
TelemetryImpl::subscribe_attitude_quaternion(const Telemetry::AttitudeQuaternionCallback& callback)
×
2310
{
2311
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2312
    return _attitude_quaternion_angle_subscriptions.subscribe(callback);
×
2313
}
×
2314

2315
void TelemetryImpl::unsubscribe_attitude_quaternion(Telemetry::AttitudeQuaternionHandle handle)
×
2316
{
2317
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2318
    _attitude_quaternion_angle_subscriptions.unsubscribe(handle);
×
2319
}
×
2320

2321
Telemetry::AttitudeEulerHandle
2322
TelemetryImpl::subscribe_attitude_euler(const Telemetry::AttitudeEulerCallback& callback)
×
2323
{
2324
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2325
    return _attitude_euler_angle_subscriptions.subscribe(callback);
×
2326
}
×
2327

2328
void TelemetryImpl::unsubscribe_attitude_euler(Telemetry::AttitudeEulerHandle handle)
×
2329
{
2330
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2331
    _attitude_euler_angle_subscriptions.unsubscribe(handle);
×
2332
}
×
2333

2334
Telemetry::AttitudeAngularVelocityBodyHandle
2335
TelemetryImpl::subscribe_attitude_angular_velocity_body(
×
2336
    const Telemetry::AttitudeAngularVelocityBodyCallback& callback)
2337
{
2338
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2339
    return _attitude_angular_velocity_body_subscriptions.subscribe(callback);
×
2340
}
×
2341

2342
void TelemetryImpl::unsubscribe_attitude_angular_velocity_body(
×
2343
    Telemetry::AttitudeAngularVelocityBodyHandle handle)
2344
{
2345
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2346
    _attitude_angular_velocity_body_subscriptions.unsubscribe(handle);
×
2347
}
×
2348

2349
Telemetry::FixedwingMetricsHandle
2350
TelemetryImpl::subscribe_fixedwing_metrics(const Telemetry::FixedwingMetricsCallback& callback)
×
2351
{
2352
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2353
    return _fixedwing_metrics_subscriptions.subscribe(callback);
×
2354
}
×
2355

2356
void TelemetryImpl::unsubscribe_fixedwing_metrics(Telemetry::FixedwingMetricsHandle handle)
×
2357
{
2358
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2359
    _fixedwing_metrics_subscriptions.unsubscribe(handle);
×
2360
}
×
2361

2362
Telemetry::GroundTruthHandle
2363
TelemetryImpl::subscribe_ground_truth(const Telemetry::GroundTruthCallback& callback)
1✔
2364
{
2365
    std::lock_guard<std::mutex> lock(_subscription_mutex);
1✔
2366
    return _ground_truth_subscriptions.subscribe(callback);
1✔
2367
}
1✔
2368

2369
void TelemetryImpl::unsubscribe_ground_truth(Telemetry::GroundTruthHandle handle)
1✔
2370
{
2371
    std::lock_guard<std::mutex> lock(_subscription_mutex);
1✔
2372
    _ground_truth_subscriptions.unsubscribe(handle);
1✔
2373
}
1✔
2374

2375
Telemetry::VelocityNedHandle
2376
TelemetryImpl::subscribe_velocity_ned(const Telemetry::VelocityNedCallback& callback)
×
2377
{
2378
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2379
    return _velocity_ned_subscriptions.subscribe(callback);
×
2380
}
×
2381

2382
void TelemetryImpl::unsubscribe_velocity_ned(Telemetry::VelocityNedHandle handle)
×
2383
{
2384
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2385
    _velocity_ned_subscriptions.unsubscribe(handle);
×
2386
}
×
2387

2388
Telemetry::ImuHandle TelemetryImpl::subscribe_imu(const Telemetry::ImuCallback& callback)
×
2389
{
2390
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2391
    return _imu_reading_ned_subscriptions.subscribe(callback);
×
2392
}
×
2393

2394
void TelemetryImpl::unsubscribe_imu(Telemetry::ImuHandle handle)
×
2395
{
2396
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2397
    return _imu_reading_ned_subscriptions.unsubscribe(handle);
×
2398
}
×
2399

2400
Telemetry::ScaledImuHandle
2401
TelemetryImpl::subscribe_scaled_imu(const Telemetry::ScaledImuCallback& callback)
×
2402
{
2403
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2404
    return _scaled_imu_subscriptions.subscribe(callback);
×
2405
}
×
2406

2407
void TelemetryImpl::unsubscribe_scaled_imu(Telemetry::ScaledImuHandle handle)
×
2408
{
2409
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2410
    _scaled_imu_subscriptions.unsubscribe(handle);
×
2411
}
×
2412

2413
Telemetry::RawImuHandle TelemetryImpl::subscribe_raw_imu(const Telemetry::RawImuCallback& callback)
×
2414
{
2415
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2416
    return _raw_imu_subscriptions.subscribe(callback);
×
2417
}
×
2418

2419
void TelemetryImpl::unsubscribe_raw_imu(Telemetry::RawImuHandle handle)
×
2420
{
2421
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2422
    _raw_imu_subscriptions.unsubscribe(handle);
×
2423
}
×
2424

2425
Telemetry::GpsInfoHandle
2426
TelemetryImpl::subscribe_gps_info(const Telemetry::GpsInfoCallback& callback)
×
2427
{
2428
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2429
    return _gps_info_subscriptions.subscribe(callback);
×
2430
}
×
2431

2432
void TelemetryImpl::unsubscribe_gps_info(Telemetry::GpsInfoHandle handle)
×
2433
{
2434
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2435
    _gps_info_subscriptions.unsubscribe(handle);
×
2436
}
×
2437

2438
Telemetry::RawGpsHandle TelemetryImpl::subscribe_raw_gps(const Telemetry::RawGpsCallback& callback)
×
2439
{
2440
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2441
    return _raw_gps_subscriptions.subscribe(callback);
×
2442
}
×
2443

2444
void TelemetryImpl::unsubscribe_raw_gps(Telemetry::RawGpsHandle handle)
×
2445
{
2446
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2447
    _raw_gps_subscriptions.unsubscribe(handle);
×
2448
}
×
2449

2450
Telemetry::BatteryHandle
2451
TelemetryImpl::subscribe_battery(const Telemetry::BatteryCallback& callback)
×
2452
{
2453
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2454
    return _battery_subscriptions.subscribe(callback);
×
2455
}
×
2456

2457
void TelemetryImpl::unsubscribe_battery(Telemetry::BatteryHandle handle)
×
2458
{
2459
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2460
    _battery_subscriptions.unsubscribe(handle);
×
2461
}
×
2462

2463
Telemetry::FlightModeHandle
2464
TelemetryImpl::subscribe_flight_mode(const Telemetry::FlightModeCallback& callback)
×
2465
{
2466
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2467
    return _flight_mode_subscriptions.subscribe(callback);
×
2468
}
×
2469

2470
void TelemetryImpl::unsubscribe_flight_mode(Telemetry::FlightModeHandle handle)
×
2471
{
2472
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2473
    _flight_mode_subscriptions.unsubscribe(handle);
×
2474
}
×
2475

2476
Telemetry::HealthHandle TelemetryImpl::subscribe_health(const Telemetry::HealthCallback& callback)
×
2477
{
2478
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2479
    return _health_subscriptions.subscribe(callback);
×
2480
}
×
2481

2482
void TelemetryImpl::unsubscribe_health(Telemetry::HealthHandle handle)
×
2483
{
2484
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2485
    _health_subscriptions.unsubscribe(handle);
×
2486
}
×
2487

2488
Telemetry::HealthAllOkHandle
2489
TelemetryImpl::subscribe_health_all_ok(const Telemetry::HealthAllOkCallback& callback)
×
2490
{
2491
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2492
    return _health_all_ok_subscriptions.subscribe(callback);
×
2493
}
×
2494

2495
void TelemetryImpl::unsubscribe_health_all_ok(Telemetry::HealthAllOkHandle handle)
×
2496
{
2497
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2498
    _health_all_ok_subscriptions.unsubscribe(handle);
×
2499
}
×
2500

2501
Telemetry::VtolStateHandle
2502
TelemetryImpl::subscribe_vtol_state(const Telemetry::VtolStateCallback& callback)
×
2503
{
2504
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2505
    return _vtol_state_subscriptions.subscribe(callback);
×
2506
}
×
2507

2508
void TelemetryImpl::unsubscribe_vtol_state(Telemetry::VtolStateHandle handle)
×
2509
{
2510
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2511
    _vtol_state_subscriptions.unsubscribe(handle);
×
2512
}
×
2513

2514
Telemetry::LandedStateHandle
2515
TelemetryImpl::subscribe_landed_state(const Telemetry::LandedStateCallback& callback)
×
2516
{
2517
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2518
    return _landed_state_subscriptions.subscribe(callback);
×
2519
}
×
2520

2521
void TelemetryImpl::unsubscribe_landed_state(Telemetry::LandedStateHandle handle)
×
2522
{
2523
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2524
    _landed_state_subscriptions.unsubscribe(handle);
×
2525
}
×
2526

2527
Telemetry::RcStatusHandle
2528
TelemetryImpl::subscribe_rc_status(const Telemetry::RcStatusCallback& callback)
3✔
2529
{
2530
    std::lock_guard<std::mutex> lock(_subscription_mutex);
3✔
2531
    return _rc_status_subscriptions.subscribe(callback);
3✔
2532
}
3✔
2533

2534
void TelemetryImpl::unsubscribe_rc_status(Telemetry::RcStatusHandle handle)
3✔
2535
{
2536
    std::lock_guard<std::mutex> lock(_subscription_mutex);
3✔
2537
    _rc_status_subscriptions.unsubscribe(handle);
3✔
2538
}
3✔
2539

2540
Telemetry::UnixEpochTimeHandle
2541
TelemetryImpl::subscribe_unix_epoch_time(const Telemetry::UnixEpochTimeCallback& callback)
×
2542
{
2543
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2544
    return _unix_epoch_time_subscriptions.subscribe(callback);
×
2545
}
×
2546

2547
void TelemetryImpl::unsubscribe_unix_epoch_time(Telemetry::UnixEpochTimeHandle handle)
×
2548
{
2549
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2550
    _unix_epoch_time_subscriptions.unsubscribe(handle);
×
2551
}
×
2552

2553
Telemetry::ActuatorControlTargetHandle TelemetryImpl::subscribe_actuator_control_target(
×
2554
    const Telemetry::ActuatorControlTargetCallback& callback)
2555
{
2556
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2557
    return _actuator_control_target_subscriptions.subscribe(callback);
×
2558
}
×
2559

2560
void TelemetryImpl::unsubscribe_actuator_control_target(
×
2561
    Telemetry::ActuatorControlTargetHandle handle)
2562
{
2563
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2564
    _actuator_control_target_subscriptions.unsubscribe(handle);
×
2565
}
×
2566

2567
Telemetry::ActuatorOutputStatusHandle TelemetryImpl::subscribe_actuator_output_status(
×
2568
    const Telemetry::ActuatorOutputStatusCallback& callback)
2569
{
2570
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2571
    return _actuator_output_status_subscriptions.subscribe(callback);
×
2572
}
×
2573

2574
void TelemetryImpl::unsubscribe_actuator_output_status(Telemetry::ActuatorOutputStatusHandle handle)
×
2575
{
2576
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2577
    _actuator_output_status_subscriptions.unsubscribe(handle);
×
2578
}
×
2579

2580
Telemetry::OdometryHandle
2581
TelemetryImpl::subscribe_odometry(const Telemetry::OdometryCallback& callback)
×
2582
{
2583
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2584
    return _odometry_subscriptions.subscribe(callback);
×
2585
}
×
2586

2587
void TelemetryImpl::unsubscribe_odometry(Telemetry::OdometryHandle handle)
×
2588
{
2589
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2590
    _odometry_subscriptions.unsubscribe(handle);
×
2591
}
×
2592

2593
Telemetry::DistanceSensorHandle
2594
TelemetryImpl::subscribe_distance_sensor(const Telemetry::DistanceSensorCallback& callback)
×
2595
{
2596
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2597
    return _distance_sensor_subscriptions.subscribe(callback);
×
2598
}
×
2599

2600
void TelemetryImpl::unsubscribe_distance_sensor(Telemetry::DistanceSensorHandle handle)
×
2601
{
2602
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2603
    _distance_sensor_subscriptions.unsubscribe(handle);
×
2604
}
×
2605

2606
Telemetry::ScaledPressureHandle
2607
TelemetryImpl::subscribe_scaled_pressure(const Telemetry::ScaledPressureCallback& callback)
×
2608
{
2609
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2610
    return _scaled_pressure_subscriptions.subscribe(callback);
×
2611
}
×
2612

2613
void TelemetryImpl::unsubscribe_scaled_pressure(Telemetry::ScaledPressureHandle handle)
×
2614
{
2615
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2616
    _scaled_pressure_subscriptions.unsubscribe(handle);
×
2617
}
×
2618

2619
Telemetry::HeadingHandle
2620
TelemetryImpl::subscribe_heading(const Telemetry::HeadingCallback& callback)
×
2621
{
2622
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2623
    return _heading_subscriptions.subscribe(callback);
×
2624
}
×
2625

2626
void TelemetryImpl::unsubscribe_heading(Telemetry::HeadingHandle handle)
×
2627
{
2628
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2629
    _heading_subscriptions.unsubscribe(handle);
×
2630
}
×
2631

2632
Telemetry::AltitudeHandle
2633
TelemetryImpl::subscribe_altitude(const Telemetry::AltitudeCallback& callback)
2✔
2634
{
2635
    std::lock_guard<std::mutex> lock(_subscription_mutex);
2✔
2636
    return _altitude_subscriptions.subscribe(callback);
2✔
2637
}
2✔
2638

2639
void TelemetryImpl::unsubscribe_altitude(Telemetry::AltitudeHandle handle)
2✔
2640
{
2641
    std::lock_guard<std::mutex> lock(_subscription_mutex);
2✔
2642
    _altitude_subscriptions.unsubscribe(handle);
2✔
2643
}
2✔
2644

2645
Telemetry::WindHandle TelemetryImpl::subscribe_wind(const Telemetry::WindCallback& callback)
×
2646
{
2647
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2648
    return _wind_subscriptions.subscribe(callback);
×
2649
}
×
2650

2651
void TelemetryImpl::unsubscribe_wind(Telemetry::WindHandle handle)
×
2652
{
2653
    std::lock_guard<std::mutex> lock(_subscription_mutex);
×
2654
    _wind_subscriptions.unsubscribe(handle);
×
2655
}
×
2656

2657
void TelemetryImpl::get_gps_global_origin_async(
×
2658
    const Telemetry::GetGpsGlobalOriginCallback callback)
2659
{
2660
    _system_impl->mavlink_request_message().request(
×
2661
        MAVLINK_MSG_ID_GPS_GLOBAL_ORIGIN,
2662
        MAV_COMP_ID_AUTOPILOT1,
2663
        [this, callback](MavlinkCommandSender::Result result, const mavlink_message_t& message) {
×
2664
            if (result == MavlinkCommandSender::Result::Success) {
×
2665
                mavlink_gps_global_origin_t mavlink_gps_global_origin;
2666
                mavlink_msg_gps_global_origin_decode(&message, &mavlink_gps_global_origin);
×
2667

2668
                Telemetry::GpsGlobalOrigin gps_global_origin;
×
2669
                gps_global_origin.latitude_deg = mavlink_gps_global_origin.latitude * 1e-7;
×
2670
                gps_global_origin.longitude_deg = mavlink_gps_global_origin.longitude * 1e-7;
×
2671
                gps_global_origin.altitude_m = mavlink_gps_global_origin.altitude * 1e-3f;
×
2672
                _system_impl->call_user_callback([callback, gps_global_origin]() {
×
2673
                    callback(Telemetry::Result::Success, gps_global_origin);
2674
                });
2675

2676
            } else {
2677
                _system_impl->call_user_callback([callback, result]() {
×
2678
                    callback(telemetry_result_from_command_result(result), {});
2679
                });
2680
            }
2681
        });
×
2682
}
×
2683

2684
std::pair<Telemetry::Result, Telemetry::GpsGlobalOrigin> TelemetryImpl::get_gps_global_origin()
×
2685
{
2686
    auto prom = std::promise<std::pair<Telemetry::Result, Telemetry::GpsGlobalOrigin>>();
×
2687
    auto fut = prom.get_future();
×
2688

2689
    get_gps_global_origin_async(
×
2690
        [&prom](Telemetry::Result result, Telemetry::GpsGlobalOrigin gps_global_origin) {
×
2691
            prom.set_value(std::make_pair(result, gps_global_origin));
×
2692
        });
×
2693
    return fut.get();
×
2694
}
×
2695

2696
} // namespace mavsdk
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc