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

mavlink / MAVSDK / 12385035894

18 Dec 2024 02:13AM UTC coverage: 43.594% (+4.9%) from 38.708%
12385035894

push

github

web-flow
Merge pull request #2386 from mavlink/pr-multiple-cameras

camera: support multiple cameras within one instance

1407 of 2127 new or added lines in 47 files covered. (66.15%)

48 existing lines in 8 files now uncovered.

13974 of 32055 relevant lines covered (43.59%)

290.15 hits per line

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

42.27
/src/mavsdk/core/system_impl.cpp
1
#include "system.h"
2
#include "mavsdk_impl.h"
3
#include "mavlink_include.h"
4
#include "system_impl.h"
5
#include "server_component_impl.h"
6
#include "plugin_impl_base.h"
7
#include "px4_custom_mode.h"
8
#include "ardupilot_custom_mode.h"
9
#include "callback_list.tpp"
10
#include "unused.h"
11
#include <cassert>
12
#include <cstdlib>
13
#include <functional>
14
#include <future>
15
#include <utility>
16

17
namespace mavsdk {
18

19
template class CallbackList<bool>;
20
template class CallbackList<ComponentType>;
21
template class CallbackList<ComponentType, uint8_t>;
22

23
SystemImpl::SystemImpl(MavsdkImpl& mavsdk_impl) :
86✔
24
    _mavsdk_impl(mavsdk_impl),
86✔
25
    _command_sender(*this),
86✔
26
    _timesync(*this),
86✔
27
    _ping(*this),
86✔
28
    _mission_transfer_client(
172✔
29
        _mavsdk_impl.default_server_component_impl().sender(),
86✔
30
        _mavlink_message_handler,
86✔
31
        _mavsdk_impl.timeout_handler,
86✔
32
        [this]() { return timeout_s(); },
1✔
33
        [this]() { return autopilot(); }),
1✔
34
    _mavlink_request_message(
86✔
35
        *this, _command_sender, _mavlink_message_handler, _mavsdk_impl.timeout_handler),
86✔
36
    _mavlink_ftp_client(*this),
86✔
37
    _mavlink_component_metadata(*this)
172✔
38
{
39
    _system_thread = new std::thread(&SystemImpl::system_thread, this);
86✔
40
}
86✔
41

42
SystemImpl::~SystemImpl()
86✔
43
{
44
    _should_exit = true;
86✔
45
    _mavlink_message_handler.unregister_all(this);
86✔
46

47
    unregister_timeout_handler(_heartbeat_timeout_cookie);
86✔
48

49
    if (_system_thread != nullptr) {
86✔
50
        _system_thread->join();
86✔
51
        delete _system_thread;
86✔
52
        _system_thread = nullptr;
86✔
53
    }
54
}
86✔
55

56
void SystemImpl::init(uint8_t system_id, uint8_t comp_id)
86✔
57
{
58
    _target_address.system_id = system_id;
86✔
59
    // We use this as a default.
60
    _target_address.component_id = MAV_COMP_ID_AUTOPILOT1;
86✔
61

62
    _mavlink_message_handler.register_one(
86✔
63
        MAVLINK_MSG_ID_HEARTBEAT,
64
        [this](const mavlink_message_t& message) { process_heartbeat(message); },
198✔
65
        this);
66

67
    _mavlink_message_handler.register_one(
86✔
68
        MAVLINK_MSG_ID_STATUSTEXT,
69
        [this](const mavlink_message_t& message) { process_statustext(message); },
3✔
70
        this);
71

72
    _mavlink_message_handler.register_one(
86✔
73
        MAVLINK_MSG_ID_AUTOPILOT_VERSION,
74
        [this](const mavlink_message_t& message) { process_autopilot_version(message); },
33✔
75
        this);
76

77
    add_new_component(comp_id);
86✔
78
}
86✔
79

80
bool SystemImpl::is_connected() const
44✔
81
{
82
    return _connected;
44✔
83
}
84

85
void SystemImpl::register_mavlink_message_handler(
357✔
86
    uint16_t msg_id, const MavlinkMessageHandler::Callback& callback, const void* cookie)
87
{
88
    _mavlink_message_handler.register_one(msg_id, callback, cookie);
357✔
89
}
357✔
90

UNCOV
91
void SystemImpl::register_mavlink_message_handler_with_compid(
×
92
    uint16_t msg_id,
93
    uint8_t component_id,
94
    const MavlinkMessageHandler::Callback& callback,
95
    const void* cookie)
96
{
UNCOV
97
    _mavlink_message_handler.register_one_with_component_id(msg_id, component_id, callback, cookie);
×
UNCOV
98
}
×
99

100
void SystemImpl::unregister_mavlink_message_handler(uint16_t msg_id, const void* cookie)
×
101
{
102
    _mavlink_message_handler.unregister_one(msg_id, cookie);
×
103
}
×
104

105
void SystemImpl::unregister_all_mavlink_message_handlers(const void* cookie)
356✔
106
{
107
    _mavlink_message_handler.unregister_all(cookie);
356✔
108
}
356✔
109

110
void SystemImpl::update_component_id_messages_handler(
×
111
    uint16_t msg_id, uint8_t component_id, const void* cookie)
112
{
113
    _mavlink_message_handler.update_component_id(msg_id, component_id, cookie);
×
114
}
×
115

116
TimeoutHandler::Cookie
117
SystemImpl::register_timeout_handler(const std::function<void()>& callback, double duration_s)
993✔
118
{
119
    return _mavsdk_impl.timeout_handler.add(callback, duration_s);
993✔
120
}
121

122
void SystemImpl::refresh_timeout_handler(TimeoutHandler::Cookie cookie)
111✔
123
{
124
    _mavsdk_impl.timeout_handler.refresh(cookie);
111✔
125
}
112✔
126

127
void SystemImpl::unregister_timeout_handler(TimeoutHandler::Cookie cookie)
1,029✔
128
{
129
    _mavsdk_impl.timeout_handler.remove(cookie);
1,029✔
130
}
1,029✔
131

132
double SystemImpl::timeout_s() const
979✔
133
{
134
    return _mavsdk_impl.timeout_s();
979✔
135
}
136

137
void SystemImpl::enable_timesync()
×
138
{
139
    _timesync.enable();
×
140
}
×
141

142
System::IsConnectedHandle
143
SystemImpl::subscribe_is_connected(const System::IsConnectedCallback& callback)
×
144
{
145
    std::lock_guard<std::mutex> lock(_connection_mutex);
×
146
    return _is_connected_callbacks.subscribe(callback);
×
147
}
×
148

149
void SystemImpl::unsubscribe_is_connected(System::IsConnectedHandle handle)
×
150
{
151
    _is_connected_callbacks.unsubscribe(handle);
×
152
}
×
153

154
void SystemImpl::process_mavlink_message(mavlink_message_t& message)
1,888✔
155
{
156
    _mavlink_message_handler.process_message(message);
1,888✔
157
}
1,889✔
158

159
CallEveryHandler::Cookie
160
SystemImpl::add_call_every(std::function<void()> callback, float interval_s)
28✔
161
{
162
    return _mavsdk_impl.call_every_handler.add(
56✔
163
        std::move(callback), static_cast<double>(interval_s));
28✔
164
}
165

166
void SystemImpl::change_call_every(float interval_s, CallEveryHandler::Cookie cookie)
×
167
{
168
    _mavsdk_impl.call_every_handler.change(static_cast<double>(interval_s), cookie);
×
169
}
×
170

171
void SystemImpl::reset_call_every(CallEveryHandler::Cookie cookie)
×
172
{
173
    _mavsdk_impl.call_every_handler.reset(cookie);
×
174
}
×
175

176
void SystemImpl::remove_call_every(CallEveryHandler::Cookie cookie)
28✔
177
{
178
    _mavsdk_impl.call_every_handler.remove(cookie);
28✔
179
}
28✔
180

181
void SystemImpl::register_statustext_handler(
1✔
182
    std::function<void(const MavlinkStatustextHandler::Statustext&)> callback, void* cookie)
183
{
184
    std::lock_guard<std::mutex> lock(_statustext_handler_callbacks_mutex);
1✔
185
    _statustext_handler_callbacks.push_back(StatustextCallback{std::move(callback), cookie});
1✔
186
}
1✔
187

188
void SystemImpl::unregister_statustext_handler(void* cookie)
1✔
189
{
190
    std::lock_guard<std::mutex> lock(_statustext_handler_callbacks_mutex);
1✔
191
    _statustext_handler_callbacks.erase(std::remove_if(
1✔
192
        _statustext_handler_callbacks.begin(),
193
        _statustext_handler_callbacks.end(),
194
        [&](const auto& entry) { return entry.cookie == cookie; }));
1✔
195
}
1✔
196

197
void SystemImpl::process_heartbeat(const mavlink_message_t& message)
198✔
198
{
199
    mavlink_heartbeat_t heartbeat;
198✔
200
    mavlink_msg_heartbeat_decode(&message, &heartbeat);
198✔
201

202
    if (heartbeat.autopilot == MAV_AUTOPILOT_PX4) {
198✔
203
        _autopilot = Autopilot::Px4;
×
204
    } else if (heartbeat.autopilot == MAV_AUTOPILOT_ARDUPILOTMEGA) {
198✔
205
        _autopilot = Autopilot::ArduPilot;
×
206
    }
207

208
    // Only set the vehicle type if the heartbeat is from an autopilot component
209
    // This check only works if the MAV_TYPE::MAV_TYPE_ENUM_END is actually the
210
    // last enumerator.
211
    if (MAV_TYPE::MAV_TYPE_ENUM_END < heartbeat.type) {
198✔
212
        LogErr() << "type received in HEARTBEAT was not recognized";
×
213
    } else {
214
        const auto new_vehicle_type = static_cast<MAV_TYPE>(heartbeat.type);
198✔
215
        if (heartbeat.autopilot != MAV_AUTOPILOT_INVALID && _vehicle_type != new_vehicle_type &&
198✔
216
            new_vehicle_type != MAV_TYPE_GENERIC) {
217
            LogWarn() << "Vehicle type changed (new type: " << static_cast<unsigned>(heartbeat.type)
×
218
                      << ", old type: " << static_cast<unsigned>(_vehicle_type) << ")";
×
219
            _vehicle_type = new_vehicle_type;
×
220
        }
221
    }
222

223
    if (message.compid == MavlinkCommandSender::DEFAULT_COMPONENT_ID_AUTOPILOT) {
198✔
224
        _armed = (heartbeat.base_mode & MAV_MODE_FLAG_SAFETY_ARMED) != 0;
72✔
225
        _hitl_enabled = (heartbeat.base_mode & MAV_MODE_FLAG_HIL_ENABLED) != 0;
72✔
226
    }
227
    if (heartbeat.base_mode & MAV_MODE_FLAG_CUSTOM_MODE_ENABLED) {
198✔
228
        _flight_mode =
×
229
            to_flight_mode_from_custom_mode(_autopilot, _vehicle_type, heartbeat.custom_mode);
230
    }
231

232
    set_connected();
198✔
233
}
197✔
234

235
void SystemImpl::process_statustext(const mavlink_message_t& message)
3✔
236
{
237
    mavlink_statustext_t statustext;
3✔
238
    mavlink_msg_statustext_decode(&message, &statustext);
3✔
239

240
    const auto maybe_result = _statustext_handler.process(statustext);
3✔
241

242
    if (maybe_result.has_value()) {
3✔
243
        LogDebug() << "MAVLink: "
6✔
244
                   << MavlinkStatustextHandler::severity_str(maybe_result.value().severity) << ": "
6✔
245
                   << maybe_result.value().text;
9✔
246

247
        std::lock_guard<std::mutex> lock(_statustext_handler_callbacks_mutex);
3✔
248
        for (const auto& entry : _statustext_handler_callbacks) {
6✔
249
            entry.callback(maybe_result.value());
3✔
250
        }
251
    }
3✔
252
}
3✔
253

254
void SystemImpl::process_autopilot_version(const mavlink_message_t& message)
33✔
255
{
256
    mavlink_autopilot_version_t autopilot_version;
33✔
257
    mavlink_msg_autopilot_version_decode(&message, &autopilot_version);
33✔
258

259
    _mission_transfer_client.set_int_messages_supported(
33✔
260
        autopilot_version.capabilities & MAV_PROTOCOL_CAPABILITY_MISSION_INT);
33✔
261
}
33✔
262

263
void SystemImpl::heartbeats_timed_out()
×
264
{
265
    LogInfo() << "heartbeats timed out";
×
266
    set_disconnected();
×
267
}
×
268

269
void SystemImpl::system_thread()
86✔
270
{
271
    SteadyTimePoint last_ping_time{};
86✔
272

273
    while (!_should_exit) {
9,834✔
274
        {
275
            std::lock_guard<std::mutex> lock(_mavlink_parameter_clients_mutex);
9,629✔
276
            for (auto& entry : _mavlink_parameter_clients) {
10,373✔
277
                entry.parameter_client->do_work();
734✔
278
            }
279
        }
9,703✔
280
        _command_sender.do_work();
9,740✔
281
        _timesync.do_work();
9,720✔
282
        _mission_transfer_client.do_work();
9,716✔
283
        _mavlink_ftp_client.do_work();
9,690✔
284

285
        if (_mavsdk_impl.time.elapsed_since_s(last_ping_time) >= SystemImpl::_ping_interval_s) {
9,707✔
286
            if (_connected && _autopilot != Autopilot::ArduPilot) {
96✔
287
                _ping.run_once();
10✔
288
            }
289
            last_ping_time = _mavsdk_impl.time.steady_time();
96✔
290
        }
291

292
        if (_connected) {
9,672✔
293
            // Work fairly fast if we're connected.
294
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
9,541✔
295
        } else {
296
            // Be less aggressive when unconnected.
297
            std::this_thread::sleep_for(std::chrono::milliseconds(100));
94✔
298
        }
299
    }
300
}
86✔
301

302
std::string SystemImpl::component_name(uint8_t component_id)
87✔
303
{
304
    switch (component_id) {
87✔
305
        case MAV_COMP_ID_AUTOPILOT1:
33✔
306
            return "Autopilot";
33✔
307
        case MAV_COMP_ID_CAMERA:
9✔
308
            return "Camera 1";
9✔
309
        case MAV_COMP_ID_CAMERA2:
×
310
            return "Camera 2";
×
311
        case MAV_COMP_ID_CAMERA3:
×
312
            return "Camera 3";
×
313
        case MAV_COMP_ID_CAMERA4:
×
314
            return "Camera 4";
×
315
        case MAV_COMP_ID_CAMERA5:
×
316
            return "Camera 5";
×
317
        case MAV_COMP_ID_CAMERA6:
×
318
            return "Camera 6";
×
319
        case MAV_COMP_ID_GIMBAL:
×
320
            return "Gimbal";
×
321
        case MAV_COMP_ID_MISSIONPLANNER:
43✔
322
            return "Ground station";
43✔
323
        case MAV_COMP_ID_ONBOARD_COMPUTER:
1✔
324
            return "Companion Computer";
1✔
325
        case MAV_COMP_ID_WINCH:
×
326
            return "Winch";
×
327
        default:
1✔
328
            return "Unsupported component";
1✔
329
    }
330
}
331

332
ComponentType SystemImpl::component_type(uint8_t component_id)
174✔
333
{
334
    switch (component_id) {
174✔
335
        case MAV_COMP_ID_AUTOPILOT1:
66✔
336
            return ComponentType::Autopilot;
66✔
337
        case MAV_COMP_ID_MISSIONPLANNER:
86✔
338
            return ComponentType::GroundStation;
86✔
339
        case MAV_COMP_ID_ONBOARD_COMPUTER:
2✔
340
        case MAV_COMP_ID_ONBOARD_COMPUTER2:
341
        case MAV_COMP_ID_ONBOARD_COMPUTER3:
342
        case MAV_COMP_ID_ONBOARD_COMPUTER4:
343
            return ComponentType::CompanionComputer;
2✔
344
        case MAV_COMP_ID_CAMERA:
18✔
345
        case MAV_COMP_ID_CAMERA2:
346
        case MAV_COMP_ID_CAMERA3:
347
        case MAV_COMP_ID_CAMERA4:
348
        case MAV_COMP_ID_CAMERA5:
349
        case MAV_COMP_ID_CAMERA6:
350
            return ComponentType::Camera;
18✔
351
        case MAV_COMP_ID_GIMBAL:
×
352
            return ComponentType::Gimbal;
×
353
        case MAV_COMP_ID_ODID_TXRX_1:
×
354
        case MAV_COMP_ID_ODID_TXRX_2:
355
        case MAV_COMP_ID_ODID_TXRX_3:
356
            return ComponentType::RemoteId;
×
357
        default:
2✔
358
            return ComponentType::Custom;
2✔
359
    }
360
}
361

362
void SystemImpl::add_new_component(uint8_t component_id)
1,888✔
363
{
364
    if (component_id == 0) {
1,888✔
365
        return;
×
366
    }
367

368
    auto res_pair = _components.insert(component_id);
1,888✔
369
    if (res_pair.second) {
1,888✔
370
        std::lock_guard<std::mutex> lock(_component_discovered_callback_mutex);
87✔
371
        _component_discovered_callbacks.queue(
87✔
372
            component_type(component_id), [this](const auto& func) { call_user_callback(func); });
×
373
        _component_discovered_id_callbacks.queue(
87✔
374
            component_type(component_id), component_id, [this](const auto& func) {
×
375
                call_user_callback(func);
×
376
            });
×
377
        LogDebug() << "Component " << component_name(component_id) << " (" << int(component_id)
348✔
378
                   << ") added.";
348✔
379
    }
87✔
380
}
381

382
size_t SystemImpl::total_components() const
×
383
{
384
    return _components.size();
×
385
}
386

387
System::ComponentDiscoveredHandle
388
SystemImpl::subscribe_component_discovered(const System::ComponentDiscoveredCallback& callback)
×
389
{
390
    std::lock_guard<std::mutex> lock(_component_discovered_callback_mutex);
×
391
    const auto handle = _component_discovered_callbacks.subscribe(callback);
×
392

393
    if (total_components() > 0) {
×
394
        for (const auto& elem : _components) {
×
395
            _component_discovered_callbacks.queue(
×
396
                component_type(elem), [this](const auto& func) { call_user_callback(func); });
×
397
        }
398
    }
399
    return handle;
×
400
}
×
401

402
void SystemImpl::unsubscribe_component_discovered(System::ComponentDiscoveredHandle handle)
×
403
{
404
    std::lock_guard<std::mutex> lock(_component_discovered_callback_mutex);
×
405
    _component_discovered_callbacks.unsubscribe(handle);
×
406
}
×
407

408
System::ComponentDiscoveredIdHandle
409
SystemImpl::subscribe_component_discovered_id(const System::ComponentDiscoveredIdCallback& callback)
×
410
{
411
    std::lock_guard<std::mutex> lock(_component_discovered_callback_mutex);
×
412
    const auto handle = _component_discovered_id_callbacks.subscribe(callback);
×
413

414
    if (total_components() > 0) {
×
415
        for (const auto& elem : _components) {
×
416
            _component_discovered_id_callbacks.queue(
×
417
                component_type(elem), elem, [this](const auto& func) { call_user_callback(func); });
×
418
        }
419
    }
420
    return handle;
×
421
}
×
422

423
void SystemImpl::unsubscribe_component_discovered_id(System::ComponentDiscoveredIdHandle handle)
×
424
{
425
    std::lock_guard<std::mutex> lock(_component_discovered_callback_mutex);
×
426
    _component_discovered_id_callbacks.unsubscribe(handle);
×
427
}
×
428

429
bool SystemImpl::is_standalone() const
×
430
{
431
    return !has_autopilot();
×
432
}
433

434
bool SystemImpl::has_autopilot() const
152✔
435
{
436
    return get_autopilot_id() != uint8_t(0);
152✔
437
}
438

439
bool SystemImpl::is_autopilot(uint8_t comp_id)
×
440
{
441
    return comp_id == MAV_COMP_ID_AUTOPILOT1;
×
442
}
443

444
bool SystemImpl::is_camera(uint8_t comp_id)
9✔
445
{
446
    return (comp_id >= MAV_COMP_ID_CAMERA) && (comp_id <= MAV_COMP_ID_CAMERA6);
9✔
447
}
448

449
bool SystemImpl::has_camera(int camera_id) const
9✔
450
{
451
    int camera_comp_id = (camera_id == -1) ? camera_id : (MAV_COMP_ID_CAMERA + camera_id);
9✔
452

453
    if (camera_comp_id == -1) { // Check whether the system has any camera.
9✔
454
        if (std::any_of(_components.begin(), _components.end(), is_camera)) {
9✔
455
            return true;
9✔
456
        }
457
    } else { // Look for the camera whose id is `camera_id`.
458
        for (auto compid : _components) {
×
459
            if (compid == camera_comp_id) {
×
460
                return true;
×
461
            }
462
        }
463
    }
464
    return false;
×
465
}
466

467
bool SystemImpl::has_gimbal() const
×
468
{
469
    return get_gimbal_id() == MAV_COMP_ID_GIMBAL;
×
470
}
471

472
bool SystemImpl::send_message(mavlink_message_t& message)
×
473
{
474
    return _mavsdk_impl.send_message(message);
×
475
}
476

477
bool SystemImpl::queue_message(
679✔
478
    std::function<mavlink_message_t(MavlinkAddress mavlink_address, uint8_t channel)> fun)
479
{
480
    return _mavsdk_impl.default_server_component_impl().queue_message(fun);
679✔
481
}
482

483
void SystemImpl::send_autopilot_version_request()
33✔
484
{
485
    mavlink_request_message().request(
33✔
486
        MAVLINK_MSG_ID_AUTOPILOT_VERSION, MAV_COMP_ID_AUTOPILOT1, nullptr);
487
}
33✔
488

489
void SystemImpl::set_connected()
197✔
490
{
491
    bool enable_needed = false;
197✔
492
    {
493
        std::lock_guard<std::mutex> lock(_connection_mutex);
197✔
494

495
        if (!_connected) {
198✔
496
            if (!_components.empty()) {
86✔
497
                LogDebug() << "Discovered " << _components.size() << " component(s)";
86✔
498
            }
499

500
            _connected = true;
86✔
501

502
            // We call this later to avoid deadlocks on creating the server components.
503
            _mavsdk_impl.call_user_callback([this]() {
172✔
504
                // Send a heartbeat back immediately.
505
                _mavsdk_impl.start_sending_heartbeats();
506
            });
507

508
            _heartbeat_timeout_cookie =
86✔
509
                register_timeout_handler([this] { heartbeats_timed_out(); }, HEARTBEAT_TIMEOUT_S);
86✔
510

511
            enable_needed = true;
86✔
512

513
            _is_connected_callbacks.queue(
86✔
514
                true, [this](const auto& func) { _mavsdk_impl.call_user_callback(func); });
×
515

516
        } else if (_connected) {
112✔
517
            refresh_timeout_handler(_heartbeat_timeout_cookie);
112✔
518
        }
519
        // If not yet connected there is nothing to do/
520
    }
198✔
521

522
    if (enable_needed) {
197✔
523
        _mavsdk_impl.notify_on_discover();
86✔
524

525
        if (has_autopilot()) {
86✔
526
            send_autopilot_version_request();
33✔
527
        }
528

529
        std::lock_guard<std::mutex> lock(_plugin_impls_mutex);
86✔
530
        for (auto plugin_impl : _plugin_impls) {
86✔
531
            plugin_impl->enable();
×
532
        }
533
    }
86✔
534
}
197✔
535

536
void SystemImpl::set_disconnected()
×
537
{
538
    {
539
        std::lock_guard<std::mutex> lock(_connection_mutex);
×
540

541
        // This might not be needed because this is probably called from the triggered
542
        // timeout anyway, but it should also do no harm.
543
        // unregister_timeout_handler(_heartbeat_timeout_cookie);
544
        //_heartbeat_timeout_cookie = nullptr;
545

546
        _connected = false;
×
547
        _is_connected_callbacks.queue(
×
548
            false, [this](const auto& func) { _mavsdk_impl.call_user_callback(func); });
×
549
    }
×
550
    _mavsdk_impl.notify_on_timeout();
×
551

552
    _mavsdk_impl.stop_sending_heartbeats();
×
553

554
    {
555
        std::lock_guard<std::mutex> lock(_plugin_impls_mutex);
×
556
        for (auto plugin_impl : _plugin_impls) {
×
557
            plugin_impl->disable();
×
558
        }
559
    }
×
560
}
×
561

562
uint8_t SystemImpl::get_system_id() const
669✔
563
{
564
    return _target_address.system_id;
669✔
565
}
566

567
std::vector<uint8_t> SystemImpl::component_ids() const
×
568
{
569
    return std::vector<uint8_t>{_components.begin(), _components.end()};
×
570
}
571

572
void SystemImpl::set_system_id(uint8_t system_id)
×
573
{
574
    _target_address.system_id = system_id;
×
575
}
×
576

577
uint8_t SystemImpl::get_own_system_id() const
1,312✔
578
{
579
    return _mavsdk_impl.get_own_system_id();
1,312✔
580
}
581

582
uint8_t SystemImpl::get_own_component_id() const
1,294✔
583
{
584
    return _mavsdk_impl.get_own_component_id();
1,294✔
585
}
586

587
MAV_TYPE SystemImpl::get_vehicle_type() const
×
588
{
589
    return _vehicle_type;
×
590
}
591

592
uint8_t SystemImpl::get_own_mav_type() const
×
593
{
594
    return _mavsdk_impl.get_mav_type();
×
595
}
596

597
MavlinkParameterClient::Result SystemImpl::set_param(
×
598
    const std::string& name,
599
    ParamValue value,
600
    std::optional<uint8_t> maybe_component_id,
601
    bool extended)
602
{
603
    return param_sender(maybe_component_id ? maybe_component_id.value() : 1, extended)
×
604
        ->set_param(name, value);
×
605
}
606

607
MavlinkParameterClient::Result SystemImpl::set_param_float(
2✔
608
    const std::string& name, float value, std::optional<uint8_t> maybe_component_id, bool extended)
609
{
610
    return param_sender(maybe_component_id ? maybe_component_id.value() : 1, extended)
2✔
611
        ->set_param_float(name, value);
4✔
612
}
613

614
MavlinkParameterClient::Result SystemImpl::set_param_int(
2✔
615
    const std::string& name,
616
    int32_t value,
617
    std::optional<uint8_t> maybe_component_id,
618
    bool extended)
619
{
620
    return param_sender(maybe_component_id ? maybe_component_id.value() : 1, extended)
2✔
621
        ->set_param_int(name, value);
4✔
622
}
623

624
MavlinkParameterClient::Result SystemImpl::set_param_custom(
2✔
625
    const std::string& name, const std::string& value, std::optional<uint8_t> maybe_component_id)
626
{
627
    return param_sender(maybe_component_id.has_value() ? maybe_component_id.value() : 1, true)
4✔
628
        ->set_param_custom(name, value);
4✔
629
}
630

631
std::pair<MavlinkParameterClient::Result, std::map<std::string, ParamValue>>
632
SystemImpl::get_all_params(std::optional<uint8_t> maybe_component_id, bool extended)
4✔
633
{
634
    return param_sender(maybe_component_id ? maybe_component_id.value() : 1, extended)
4✔
635
        ->get_all_params();
8✔
636
}
637

638
void SystemImpl::set_param_async(
3✔
639
    const std::string& name,
640
    ParamValue value,
641
    const SetParamCallback& callback,
642
    const void* cookie,
643
    std::optional<uint8_t> maybe_component_id,
644
    bool extended)
645
{
646
    param_sender(maybe_component_id ? maybe_component_id.value() : 1, extended)
3✔
647
        ->set_param_async(name, value, callback, cookie);
6✔
648
}
3✔
649

650
void SystemImpl::set_param_float_async(
×
651
    const std::string& name,
652
    float value,
653
    const SetParamCallback& callback,
654
    const void* cookie,
655
    std::optional<uint8_t> maybe_component_id,
656
    bool extended)
657
{
658
    param_sender(maybe_component_id ? maybe_component_id.value() : 1, extended)
×
659
        ->set_param_float_async(name, value, callback, cookie);
×
660
}
×
661

662
void SystemImpl::set_param_int_async(
×
663
    const std::string& name,
664
    int32_t value,
665
    const SetParamCallback& callback,
666
    const void* cookie,
667
    std::optional<uint8_t> maybe_component_id,
668
    bool extended)
669
{
670
    param_sender(maybe_component_id ? maybe_component_id.value() : 1, extended)
×
671
        ->set_param_int_async(name, value, callback, cookie);
×
672
}
×
673

674
std::pair<MavlinkParameterClient::Result, float> SystemImpl::get_param_float(
5✔
675
    const std::string& name, std::optional<uint8_t> maybe_component_id, bool extended)
676
{
677
    return param_sender(maybe_component_id ? maybe_component_id.value() : 1, extended)
5✔
678
        ->get_param_float(name);
10✔
679
}
680

681
std::pair<MavlinkParameterClient::Result, int> SystemImpl::get_param_int(
5✔
682
    const std::string& name, std::optional<uint8_t> maybe_component_id, bool extended)
683
{
684
    return param_sender(maybe_component_id ? maybe_component_id.value() : 1, extended)
5✔
685
        ->get_param_int(name);
10✔
686
}
687

688
std::pair<MavlinkParameterClient::Result, std::string>
689
SystemImpl::get_param_custom(const std::string& name, std::optional<uint8_t> maybe_component_id)
4✔
690
{
691
    return param_sender(maybe_component_id ? maybe_component_id.value() : 1, true)
8✔
692
        ->get_param_custom(name);
8✔
693
}
694

695
void SystemImpl::get_param_async(
×
696
    const std::string& name,
697
    ParamValue value,
698
    const GetParamAnyCallback& callback,
699
    const void* cookie,
700
    std::optional<uint8_t> maybe_component_id,
701
    bool extended)
702
{
703
    param_sender(maybe_component_id ? maybe_component_id.value() : 1, extended)
×
704
        ->get_param_async(name, value, callback, cookie);
×
705
}
×
706

707
void SystemImpl::get_param_float_async(
×
708
    const std::string& name,
709
    const GetParamFloatCallback& callback,
710
    const void* cookie,
711
    std::optional<uint8_t> maybe_component_id,
712
    bool extended)
713
{
714
    param_sender(maybe_component_id ? maybe_component_id.value() : 1, extended)
×
715
        ->get_param_float_async(name, callback, cookie);
×
716
}
×
717

718
void SystemImpl::get_param_int_async(
×
719
    const std::string& name,
720
    const GetParamIntCallback& callback,
721
    const void* cookie,
722
    std::optional<uint8_t> maybe_component_id,
723
    bool extended)
724
{
725
    param_sender(maybe_component_id ? maybe_component_id.value() : 1, extended)
×
726
        ->get_param_int_async(name, callback, cookie);
×
727
}
×
728

729
void SystemImpl::get_param_custom_async(
×
730
    const std::string& name, const GetParamCustomCallback& callback, const void* cookie)
731
{
732
    param_sender(1, false)->get_param_custom_async(name, callback, cookie);
×
733
}
×
734

735
void SystemImpl::cancel_all_param(const void* cookie)
9✔
736
{
737
    UNUSED(cookie);
9✔
738
    // FIXME: this currently crashes on destruction
739
    // param_sender(1, false)->cancel_all_param(cookie);
740
}
9✔
741

742
MavlinkCommandSender::Result
743
SystemImpl::set_flight_mode(FlightMode system_mode, uint8_t component_id)
×
744
{
745
    std::pair<MavlinkCommandSender::Result, MavlinkCommandSender::CommandLong> result =
×
746
        make_command_flight_mode(system_mode, component_id);
×
747

748
    if (result.first != MavlinkCommandSender::Result::Success) {
×
749
        return result.first;
×
750
    }
751

752
    return send_command(result.second);
×
753
}
754

755
void SystemImpl::set_flight_mode_async(
×
756
    FlightMode system_mode, const CommandResultCallback& callback, uint8_t component_id)
757
{
758
    std::pair<MavlinkCommandSender::Result, MavlinkCommandSender::CommandLong> result =
×
759
        make_command_flight_mode(system_mode, component_id);
×
760

761
    if (result.first != MavlinkCommandSender::Result::Success) {
×
762
        if (callback) {
×
763
            callback(result.first, NAN);
×
764
        }
765
        return;
×
766
    }
767

768
    send_command_async(result.second, callback);
×
769
}
770

771
std::pair<MavlinkCommandSender::Result, MavlinkCommandSender::CommandLong>
772
SystemImpl::make_command_flight_mode(FlightMode flight_mode, uint8_t component_id)
×
773
{
774
    if (_autopilot == Autopilot::ArduPilot) {
×
775
        return make_command_ardupilot_mode(flight_mode, component_id);
×
776
    } else {
777
        return make_command_px4_mode(flight_mode, component_id);
×
778
    }
779
}
780

781
std::pair<MavlinkCommandSender::Result, MavlinkCommandSender::CommandLong>
782
SystemImpl::make_command_ardupilot_mode(FlightMode flight_mode, uint8_t component_id)
×
783
{
784
    const uint8_t flag_safety_armed = is_armed() ? MAV_MODE_FLAG_SAFETY_ARMED : 0;
×
785
    const uint8_t flag_hitl_enabled = _hitl_enabled ? MAV_MODE_FLAG_HIL_ENABLED : 0;
×
786
    const uint8_t mode_type =
×
787
        MAV_MODE_FLAG_CUSTOM_MODE_ENABLED | flag_safety_armed | flag_hitl_enabled;
×
788

789
    MavlinkCommandSender::CommandLong command{};
×
790

791
    command.command = MAV_CMD_DO_SET_MODE;
×
792
    command.params.maybe_param1 = static_cast<float>(mode_type);
×
793

794
    switch (_vehicle_type) {
×
795
        case MAV_TYPE::MAV_TYPE_SURFACE_BOAT:
×
796
        case MAV_TYPE::MAV_TYPE_GROUND_ROVER: {
797
            const auto new_mode = flight_mode_to_ardupilot_rover_mode(flight_mode);
×
798
            if (new_mode == ardupilot::RoverMode::Unknown) {
×
799
                LogErr() << "Cannot translate flight mode to ArduPilot Rover mode.";
×
800
                MavlinkCommandSender::CommandLong empty_command{};
×
801
                return std::make_pair<>(MavlinkCommandSender::Result::UnknownError, empty_command);
×
802
            } else {
803
                command.params.maybe_param2 = static_cast<float>(new_mode);
×
804
            }
805
            break;
×
806
        }
807
        case MAV_TYPE::MAV_TYPE_FIXED_WING:
×
808
        case MAV_TYPE::MAV_TYPE_VTOL_TAILSITTER_DUOROTOR:
809
        case MAV_TYPE::MAV_TYPE_VTOL_TAILSITTER_QUADROTOR:
810
        case MAV_TYPE::MAV_TYPE_VTOL_TILTROTOR:
811
        case MAV_TYPE::MAV_TYPE_VTOL_FIXEDROTOR:
812
        case MAV_TYPE::MAV_TYPE_VTOL_TAILSITTER:
813
        case MAV_TYPE::MAV_TYPE_VTOL_TILTWING: {
814
            const auto new_mode = flight_mode_to_ardupilot_plane_mode(flight_mode);
×
815
            if (new_mode == ardupilot::PlaneMode::Unknown) {
×
816
                LogErr() << "Cannot translate flight mode to ArduPilot Plane mode.";
×
817
                MavlinkCommandSender::CommandLong empty_command{};
×
818
                return std::make_pair<>(MavlinkCommandSender::Result::UnknownError, empty_command);
×
819
            } else {
820
                command.params.maybe_param2 = static_cast<float>(new_mode);
×
821
            }
822
            break;
×
823
        }
824

825
        case MAV_TYPE::MAV_TYPE_QUADROTOR:
×
826
        case MAV_TYPE::MAV_TYPE_COAXIAL:
827
        case MAV_TYPE::MAV_TYPE_HELICOPTER:
828
        case MAV_TYPE::MAV_TYPE_HEXAROTOR:
829
        case MAV_TYPE::MAV_TYPE_OCTOROTOR:
830
        case MAV_TYPE::MAV_TYPE_TRICOPTER:
831
        case MAV_TYPE::MAV_TYPE_DODECAROTOR:
832
        case MAV_TYPE::MAV_TYPE_DECAROTOR: {
833
            const auto new_mode = flight_mode_to_ardupilot_copter_mode(flight_mode);
×
834
            if (new_mode == ardupilot::CopterMode::Unknown) {
×
835
                LogErr() << "Cannot translate flight mode to ArduPilot Copter mode.";
×
836
                MavlinkCommandSender::CommandLong empty_command{};
×
837
                return std::make_pair<>(MavlinkCommandSender::Result::UnknownError, empty_command);
×
838
            } else {
839
                command.params.maybe_param2 = static_cast<float>(new_mode);
×
840
            }
841
            break;
×
842
        }
843

844
        default:
×
845
            LogErr() << "Cannot translate flight mode to ArduPilot mode, for MAV_TYPE: "
×
846
                     << _vehicle_type;
×
847
            MavlinkCommandSender::CommandLong empty_command{};
×
848
            return std::make_pair<>(MavlinkCommandSender::Result::UnknownError, empty_command);
×
849
    }
850
    command.target_component_id = component_id;
×
851

852
    return std::make_pair<>(MavlinkCommandSender::Result::Success, command);
×
853
}
854
ardupilot::RoverMode SystemImpl::flight_mode_to_ardupilot_rover_mode(FlightMode flight_mode)
×
855
{
856
    switch (flight_mode) {
×
857
        case FlightMode::Mission:
×
858
            return ardupilot::RoverMode::Auto;
×
859
        case FlightMode::Acro:
×
860
            return ardupilot::RoverMode::Acro;
×
861
        case FlightMode::Hold:
×
862
            return ardupilot::RoverMode::Hold;
×
863
        case FlightMode::ReturnToLaunch:
×
864
            return ardupilot::RoverMode::RTL;
×
865
        case FlightMode::Manual:
×
866
            return ardupilot::RoverMode::Manual;
×
867
        case FlightMode::FollowMe:
×
868
            return ardupilot::RoverMode::Follow;
×
869
        case FlightMode::Offboard:
×
870
            return ardupilot::RoverMode::Guided;
×
871
        case FlightMode::Unknown:
×
872
        case FlightMode::Ready:
873
        case FlightMode::Takeoff:
874
        case FlightMode::Land:
875
        case FlightMode::Altctl:
876
        case FlightMode::Posctl:
877
        case FlightMode::Rattitude:
878
        case FlightMode::Stabilized:
879
        default:
880
            return ardupilot::RoverMode::Unknown;
×
881
    }
882
}
883
ardupilot::CopterMode SystemImpl::flight_mode_to_ardupilot_copter_mode(FlightMode flight_mode)
×
884
{
885
    switch (flight_mode) {
×
886
        case FlightMode::Mission:
×
887
            return ardupilot::CopterMode::Auto;
×
888
        case FlightMode::Acro:
×
889
            return ardupilot::CopterMode::Acro;
×
890
        case FlightMode::Hold:
×
891
            return ardupilot::CopterMode::Loiter;
×
892
        case FlightMode::ReturnToLaunch:
×
893
            return ardupilot::CopterMode::Rtl;
×
894
        case FlightMode::Land:
×
895
            return ardupilot::CopterMode::Land;
×
896
        case FlightMode::Manual:
×
897
            return ardupilot::CopterMode::Stabilize;
×
898
        case FlightMode::FollowMe:
×
899
            return ardupilot::CopterMode::Follow;
×
900
        case FlightMode::Offboard:
×
901
            return ardupilot::CopterMode::Guided;
×
902
        case FlightMode::Altctl:
×
903
            return ardupilot::CopterMode::AltHold;
×
904
        case FlightMode::Posctl:
×
905
            return ardupilot::CopterMode::PosHold;
×
906
        case FlightMode::Stabilized:
×
907
            return ardupilot::CopterMode::Stabilize;
×
908
        case FlightMode::Unknown:
×
909
        case FlightMode::Ready:
910
        case FlightMode::Takeoff:
911
        case FlightMode::Rattitude:
912
        default:
913
            return ardupilot::CopterMode::Unknown;
×
914
    }
915
}
916
ardupilot::PlaneMode SystemImpl::flight_mode_to_ardupilot_plane_mode(FlightMode flight_mode)
×
917
{
918
    switch (flight_mode) {
×
919
        case FlightMode::Mission:
×
920
            return ardupilot::PlaneMode::Auto;
×
921
        case FlightMode::Acro:
×
922
            return ardupilot::PlaneMode::Acro;
×
923
        case FlightMode::Hold:
×
924
            return ardupilot::PlaneMode::Loiter;
×
925
        case FlightMode::ReturnToLaunch:
×
926
            return ardupilot::PlaneMode::Rtl;
×
927
        case FlightMode::Manual:
×
928
            return ardupilot::PlaneMode::Manual;
×
929
        case FlightMode::FBWA:
×
930
            return ardupilot::PlaneMode::Fbwa;
×
931
        case FlightMode::Stabilized:
×
932
            return ardupilot::PlaneMode::Stabilize;
×
933
        case FlightMode::Offboard:
×
934
            return ardupilot::PlaneMode::Guided;
×
935
        case FlightMode::Unknown:
×
936
            return ardupilot::PlaneMode::Unknown;
×
937
        default:
×
938
            return ardupilot::PlaneMode::Unknown;
×
939
    }
940
}
941

942
std::pair<MavlinkCommandSender::Result, MavlinkCommandSender::CommandLong>
943
SystemImpl::make_command_px4_mode(FlightMode flight_mode, uint8_t component_id)
×
944
{
945
    const uint8_t flag_safety_armed = is_armed() ? MAV_MODE_FLAG_SAFETY_ARMED : 0;
×
946
    const uint8_t flag_hitl_enabled = _hitl_enabled ? MAV_MODE_FLAG_HIL_ENABLED : 0;
×
947

948
    const uint8_t mode = MAV_MODE_FLAG_CUSTOM_MODE_ENABLED | flag_safety_armed | flag_hitl_enabled;
×
949

950
    // Note: the safety flag is not needed in future versions of the PX4 Firmware
951
    //       but want to be rather safe than sorry.
952
    uint8_t custom_mode = px4::PX4_CUSTOM_MAIN_MODE_AUTO;
×
953
    uint8_t custom_sub_mode = 0;
×
954

955
    switch (flight_mode) {
×
956
        case FlightMode::Hold:
×
957
            custom_sub_mode = px4::PX4_CUSTOM_SUB_MODE_AUTO_LOITER;
×
958
            break;
×
959
        case FlightMode::ReturnToLaunch:
×
960
            custom_sub_mode = px4::PX4_CUSTOM_SUB_MODE_AUTO_RTL;
×
961
            break;
×
962
        case FlightMode::Takeoff:
×
963
            custom_sub_mode = px4::PX4_CUSTOM_SUB_MODE_AUTO_TAKEOFF;
×
964
            break;
×
965
        case FlightMode::Land:
×
966
            custom_sub_mode = px4::PX4_CUSTOM_SUB_MODE_AUTO_LAND;
×
967
            break;
×
968
        case FlightMode::Mission:
×
969
            custom_sub_mode = px4::PX4_CUSTOM_SUB_MODE_AUTO_MISSION;
×
970
            break;
×
971
        case FlightMode::FollowMe:
×
972
            custom_sub_mode = px4::PX4_CUSTOM_SUB_MODE_AUTO_FOLLOW_TARGET;
×
973
            break;
×
974
        case FlightMode::Offboard:
×
975
            custom_mode = px4::PX4_CUSTOM_MAIN_MODE_OFFBOARD;
×
976
            break;
×
977
        case FlightMode::Manual:
×
978
            custom_mode = px4::PX4_CUSTOM_MAIN_MODE_MANUAL;
×
979
            break;
×
980
        case FlightMode::Posctl:
×
981
            custom_mode = px4::PX4_CUSTOM_MAIN_MODE_POSCTL;
×
982
            break;
×
983
        case FlightMode::Altctl:
×
984
            custom_mode = px4::PX4_CUSTOM_MAIN_MODE_ALTCTL;
×
985
            break;
×
986
        case FlightMode::Rattitude:
×
987
            custom_mode = px4::PX4_CUSTOM_MAIN_MODE_RATTITUDE;
×
988
            break;
×
989
        case FlightMode::Acro:
×
990
            custom_mode = px4::PX4_CUSTOM_MAIN_MODE_ACRO;
×
991
            break;
×
992
        case FlightMode::Stabilized:
×
993
            custom_mode = px4::PX4_CUSTOM_MAIN_MODE_STABILIZED;
×
994
            break;
×
995
        default:
×
996
            LogErr() << "Unknown Flight mode.";
×
997
            MavlinkCommandSender::CommandLong empty_command{};
×
998
            return std::make_pair<>(MavlinkCommandSender::Result::UnknownError, empty_command);
×
999
    }
1000

1001
    MavlinkCommandSender::CommandLong command{};
×
1002

1003
    command.command = MAV_CMD_DO_SET_MODE;
×
1004
    command.params.maybe_param1 = static_cast<float>(mode);
×
1005
    command.params.maybe_param2 = static_cast<float>(custom_mode);
×
1006
    command.params.maybe_param3 = static_cast<float>(custom_sub_mode);
×
1007
    command.target_component_id = component_id;
×
1008

1009
    return std::make_pair<>(MavlinkCommandSender::Result::Success, command);
×
1010
}
1011

1012
FlightMode SystemImpl::get_flight_mode() const
7✔
1013
{
1014
    return _flight_mode;
7✔
1015
}
1016

1017
void SystemImpl::receive_float_param(
×
1018
    MavlinkParameterClient::Result result, ParamValue value, const GetParamFloatCallback& callback)
1019
{
1020
    if (callback) {
×
1021
        if (result == MavlinkParameterClient::Result::Success) {
×
1022
            callback(result, value.get<float>());
×
1023
        } else {
1024
            callback(result, NAN);
×
1025
        }
1026
    }
1027
}
×
1028

1029
void SystemImpl::receive_int_param(
×
1030
    MavlinkParameterClient::Result result, ParamValue value, const GetParamIntCallback& callback)
1031
{
1032
    if (callback) {
×
1033
        if (result == MavlinkParameterClient::Result::Success) {
×
1034
            callback(result, value.get<int32_t>());
×
1035
        } else {
1036
            callback(result, 0);
×
1037
        }
1038
    }
1039
}
×
1040

1041
uint8_t SystemImpl::get_autopilot_id() const
197✔
1042
{
1043
    for (auto compid : _components)
257✔
1044
        if (compid == MavlinkCommandSender::DEFAULT_COMPONENT_ID_AUTOPILOT) {
200✔
1045
            return compid;
140✔
1046
        }
1047
    // FIXME: Not sure what should be returned if autopilot is not found
1048
    return uint8_t(0);
57✔
1049
}
1050

1051
std::vector<uint8_t> SystemImpl::get_camera_ids() const
×
1052
{
1053
    std::vector<uint8_t> camera_ids{};
×
1054

1055
    for (auto compid : _components)
×
1056
        if (compid >= MAV_COMP_ID_CAMERA && compid <= MAV_COMP_ID_CAMERA6) {
×
1057
            camera_ids.push_back(compid);
×
1058
        }
1059
    return camera_ids;
×
1060
}
1061

1062
uint8_t SystemImpl::get_gimbal_id() const
×
1063
{
1064
    for (auto compid : _components)
×
1065
        if (compid == MAV_COMP_ID_GIMBAL) {
×
1066
            return compid;
×
1067
        }
1068
    return uint8_t(0);
×
1069
}
1070

1071
MavlinkCommandSender::Result SystemImpl::send_command(MavlinkCommandSender::CommandLong& command)
5✔
1072
{
1073
    if (_target_address.system_id == 0 && _components.empty()) {
5✔
1074
        return MavlinkCommandSender::Result::NoSystem;
×
1075
    }
1076
    command.target_system_id = get_system_id();
5✔
1077
    return _command_sender.send_command(command);
5✔
1078
}
1079

1080
MavlinkCommandSender::Result SystemImpl::send_command(MavlinkCommandSender::CommandInt& command)
×
1081
{
1082
    if (_target_address.system_id == 0 && _components.empty()) {
×
1083
        return MavlinkCommandSender::Result::NoSystem;
×
1084
    }
1085
    command.target_system_id = get_system_id();
×
1086
    return _command_sender.send_command(command);
×
1087
}
1088

1089
void SystemImpl::send_command_async(
7✔
1090
    MavlinkCommandSender::CommandLong command, const CommandResultCallback& callback)
1091
{
1092
    if (_target_address.system_id == 0 && _components.empty()) {
7✔
1093
        if (callback) {
×
1094
            callback(MavlinkCommandSender::Result::NoSystem, NAN);
×
1095
        }
1096
        return;
×
1097
    }
1098
    command.target_system_id = get_system_id();
7✔
1099

1100
    _command_sender.queue_command_async(command, callback);
7✔
1101
}
1102

1103
void SystemImpl::send_command_async(
×
1104
    MavlinkCommandSender::CommandInt command, const CommandResultCallback& callback)
1105
{
1106
    if (_target_address.system_id == 0 && _components.empty()) {
×
1107
        if (callback) {
×
1108
            callback(MavlinkCommandSender::Result::NoSystem, NAN);
×
1109
        }
1110
        return;
×
1111
    }
1112
    command.target_system_id = get_system_id();
×
1113

1114
    _command_sender.queue_command_async(command, callback);
×
1115
}
1116

1117
MavlinkCommandSender::Result
1118
SystemImpl::set_msg_rate(uint16_t message_id, double rate_hz, uint8_t component_id)
×
1119
{
1120
    MavlinkCommandSender::CommandLong command =
×
1121
        make_command_msg_rate(message_id, rate_hz, component_id);
×
1122
    return send_command(command);
×
1123
}
1124

1125
void SystemImpl::set_msg_rate_async(
1✔
1126
    uint16_t message_id,
1127
    double rate_hz,
1128
    const CommandResultCallback& callback,
1129
    uint8_t component_id)
1130
{
1131
    MavlinkCommandSender::CommandLong command =
1✔
1132
        make_command_msg_rate(message_id, rate_hz, component_id);
1✔
1133
    send_command_async(command, callback);
1✔
1134
}
1✔
1135

1136
MavlinkCommandSender::CommandLong
1137
SystemImpl::make_command_msg_rate(uint16_t message_id, double rate_hz, uint8_t component_id)
1✔
1138
{
1139
    MavlinkCommandSender::CommandLong command{};
1✔
1140

1141
    // 0 to request default rate, -1 to stop stream
1142

1143
    float interval_us = 0.0f;
1✔
1144

1145
    if (rate_hz > 0) {
1✔
1146
        interval_us = 1e6f / static_cast<float>(rate_hz);
1✔
1147
    } else if (rate_hz < 0) {
×
1148
        interval_us = -1.0f;
×
1149
    }
1150

1151
    command.command = MAV_CMD_SET_MESSAGE_INTERVAL;
1✔
1152
    command.params.maybe_param1 = static_cast<float>(message_id);
1✔
1153
    command.params.maybe_param2 = interval_us;
1✔
1154
    command.target_component_id = component_id;
1✔
1155

1156
    return command;
1✔
1157
}
1158

1159
void SystemImpl::register_plugin(PluginImplBase* plugin_impl)
45✔
1160
{
1161
    assert(plugin_impl);
45✔
1162

1163
    plugin_impl->init();
45✔
1164

1165
    {
1166
        std::lock_guard<std::mutex> lock(_plugin_impls_mutex);
45✔
1167
        _plugin_impls.push_back(plugin_impl);
45✔
1168
    }
45✔
1169

1170
    // If we're connected already, let's enable it straightaway.
1171
    if (_connected) {
45✔
1172
        plugin_impl->enable();
45✔
1173
    }
1174
}
45✔
1175

1176
void SystemImpl::unregister_plugin(PluginImplBase* plugin_impl)
45✔
1177
{
1178
    assert(plugin_impl);
45✔
1179

1180
    plugin_impl->disable();
45✔
1181
    plugin_impl->deinit();
45✔
1182

1183
    // Remove first, so it won't get enabled/disabled anymore.
1184
    {
1185
        std::lock_guard<std::mutex> lock(_plugin_impls_mutex);
45✔
1186
        auto found = std::find(_plugin_impls.begin(), _plugin_impls.end(), plugin_impl);
45✔
1187
        if (found != _plugin_impls.end()) {
45✔
1188
            _plugin_impls.erase(found);
45✔
1189
        }
1190
    }
45✔
1191
}
45✔
1192

1193
void SystemImpl::call_user_callback_located(
811✔
1194
    const std::string& filename, const int linenumber, const std::function<void()>& func)
1195
{
1196
    _mavsdk_impl.call_user_callback_located(filename, linenumber, func);
811✔
1197
}
811✔
1198

1199
void SystemImpl::param_changed(const std::string& name)
×
1200
{
1201
    std::lock_guard<std::mutex> lock(_param_changed_callbacks_mutex);
×
1202

1203
    for (auto& callback : _param_changed_callbacks) {
×
1204
        callback.second(name);
×
1205
    }
1206
}
×
1207

1208
void SystemImpl::register_param_changed_handler(
×
1209
    const ParamChangedCallback& callback, const void* cookie)
1210
{
1211
    if (!callback) {
×
1212
        LogErr() << "No callback for param_changed_handler supplied.";
×
1213
        return;
×
1214
    }
1215

1216
    if (!cookie) {
×
1217
        LogErr() << "No callback for param_changed_handler supplied.";
×
1218
        return;
×
1219
    }
1220

1221
    std::lock_guard<std::mutex> lock(_param_changed_callbacks_mutex);
×
1222

1223
    _param_changed_callbacks[cookie] = callback;
×
1224
}
×
1225

1226
void SystemImpl::unregister_param_changed_handler(const void* cookie)
×
1227
{
1228
    std::lock_guard<std::mutex> lock(_param_changed_callbacks_mutex);
×
1229

1230
    auto it = _param_changed_callbacks.find(cookie);
×
1231
    if (it == _param_changed_callbacks.end()) {
×
1232
        LogWarn() << "param_changed_handler for cookie not found";
×
1233
        return;
×
1234
    }
1235
    _param_changed_callbacks.erase(it);
×
1236
}
×
1237

1238
Time& SystemImpl::get_time()
231✔
1239
{
1240
    return _mavsdk_impl.time;
231✔
1241
}
1242

1243
void SystemImpl::subscribe_param_float(
×
1244
    const std::string& name,
1245
    const MavlinkParameterClient::ParamFloatChangedCallback& callback,
1246
    const void* cookie)
1247
{
1248
    param_sender(1, false)->subscribe_param_float_changed(name, callback, cookie);
×
1249
}
×
1250

1251
void SystemImpl::subscribe_param_int(
×
1252
    const std::string& name,
1253
    const MavlinkParameterClient::ParamIntChangedCallback& callback,
1254
    const void* cookie)
1255
{
1256
    param_sender(1, false)->subscribe_param_int_changed(name, callback, cookie);
×
1257
}
×
1258
void SystemImpl::subscribe_param_custom(
×
1259
    const std::string& name,
1260
    const MavlinkParameterClient::ParamCustomChangedCallback& callback,
1261
    const void* cookie)
1262
{
1263
    param_sender(1, false)->subscribe_param_custom_changed(name, callback, cookie);
×
1264
}
×
1265

1266
MavlinkParameterClient* SystemImpl::param_sender(uint8_t component_id, bool extended)
79✔
1267
{
1268
    std::lock_guard<std::mutex> lock(_mavlink_parameter_clients_mutex);
79✔
1269

1270
    for (auto& entry : _mavlink_parameter_clients) {
81✔
1271
        if (entry.component_id == component_id && entry.extended == extended) {
71✔
1272
            return entry.parameter_client.get();
69✔
1273
        }
1274
    }
1275

1276
    _mavlink_parameter_clients.push_back(
30✔
1277
        {std::make_unique<MavlinkParameterClient>(
1278
             _mavsdk_impl.default_server_component_impl().sender(),
10✔
1279
             _mavlink_message_handler,
10✔
1280
             _mavsdk_impl.timeout_handler,
10✔
1281
             [this]() { return timeout_s(); },
73✔
1282
             [this]() { return autopilot(); },
32✔
1283
             get_system_id(),
20✔
1284
             component_id,
1285
             extended),
1286
         component_id,
1287
         extended});
1288

1289
    return _mavlink_parameter_clients.back().parameter_client.get();
10✔
1290
}
79✔
1291

1292
} // 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

© 2025 Coveralls, Inc