Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Ardupilot
GitHub Repository: Ardupilot/ardupilot
Path: blob/master/libraries/AP_DroneCAN/AP_DroneCAN.h
9914 views
1
/*
2
* This file is free software: you can redistribute it and/or modify it
3
* under the terms of the GNU General Public License as published by the
4
* Free Software Foundation, either version 3 of the License, or
5
* (at your option) any later version.
6
*
7
* This file is distributed in the hope that it will be useful, but
8
* WITHOUT ANY WARRANTY; without even the implied warranty of
9
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10
* See the GNU General Public License for more details.
11
*
12
* You should have received a copy of the GNU General Public License along
13
* with this program. If not, see <http://www.gnu.org/licenses/>.
14
*
15
* Author: Eugene Shamaev, Siddharth Bharat Purohit
16
*/
17
#pragma once
18
19
#include <AP_HAL/AP_HAL.h>
20
21
#if HAL_ENABLE_DRONECAN_DRIVERS
22
23
#include "AP_Canard_iface.h"
24
#include <AP_CANManager/AP_CANManager.h>
25
#include <AP_HAL/Semaphores.h>
26
#include <AP_Param/AP_Param.h>
27
#include <AP_ESC_Telem/AP_ESC_Telem_Backend.h>
28
#include <SRV_Channel/SRV_Channel_config.h>
29
#include <canard/publisher.h>
30
#include <canard/subscriber.h>
31
#include <canard/service_client.h>
32
#include <canard/service_server.h>
33
#include <stdio.h>
34
#include "AP_DroneCAN_DNA_Server.h"
35
#include <canard.h>
36
#include <dronecan_msgs.h>
37
#include <AP_SerialManager/AP_SerialManager_config.h>
38
#include <AP_Relay/AP_Relay_config.h>
39
#include <AP_Servo_Telem/AP_Servo_Telem_config.h>
40
#include <AP_Mount/AP_Mount_config.h>
41
42
#ifndef DRONECAN_SRV_NUMBER
43
#define DRONECAN_SRV_NUMBER NUM_SERVO_CHANNELS
44
#endif
45
46
#ifndef AP_DRONECAN_SEND_GPS
47
#define AP_DRONECAN_SEND_GPS (HAL_PROGRAM_SIZE_LIMIT_KB > 1024)
48
#endif
49
50
#define AP_DRONECAN_SW_VERS_MAJOR 1
51
#define AP_DRONECAN_SW_VERS_MINOR 0
52
53
#define AP_DRONECAN_HW_VERS_MAJOR 1
54
#define AP_DRONECAN_HW_VERS_MINOR 0
55
56
57
#ifndef AP_DRONECAN_HOBBYWING_ESC_SUPPORT
58
#define AP_DRONECAN_HOBBYWING_ESC_SUPPORT (HAL_PROGRAM_SIZE_LIMIT_KB>1024)
59
#endif
60
61
#ifndef AP_DRONECAN_HIMARK_SERVO_SUPPORT
62
#define AP_DRONECAN_HIMARK_SERVO_SUPPORT (HAL_PROGRAM_SIZE_LIMIT_KB>1024)
63
#endif
64
65
#ifndef AP_DRONECAN_SERIAL_ENABLED
66
#define AP_DRONECAN_SERIAL_ENABLED AP_SERIALMANAGER_REGISTER_ENABLED && (HAL_PROGRAM_SIZE_LIMIT_KB>1024)
67
#endif
68
69
#ifndef AP_DRONECAN_VOLZ_FEEDBACK_ENABLED
70
#define AP_DRONECAN_VOLZ_FEEDBACK_ENABLED 0
71
#endif
72
73
#if AP_DRONECAN_SERIAL_ENABLED
74
#include "AP_DroneCAN_serial.h"
75
#endif
76
77
// fwd-declare callback classes
78
class AP_DroneCAN_DNA_Server;
79
class CANSensor;
80
81
class AP_DroneCAN : public AP_CANDriver, public AP_ESC_Telem_Backend {
82
friend class AP_DroneCAN_DNA_Server;
83
public:
84
AP_DroneCAN(const int driver_index);
85
~AP_DroneCAN();
86
87
static const struct AP_Param::GroupInfo var_info[];
88
89
// Return uavcan from @driver_index or nullptr if it's not ready or doesn't exist
90
static AP_DroneCAN *get_dronecan(uint8_t driver_index);
91
bool prearm_check(char* fail_msg, uint8_t fail_msg_len) const;
92
93
__INITFUNC__ void init(uint8_t driver_index) override;
94
bool add_interface(AP_HAL::CANIface* can_iface) override;
95
96
// add an 11 bit auxillary driver
97
bool add_11bit_driver(CANSensor *sensor) override;
98
99
// handler for outgoing frames for auxillary drivers
100
bool write_aux_frame(AP_HAL::CANFrame &out_frame, const uint32_t timeout_us) override;
101
102
uint8_t get_driver_index() const { return _driver_index; }
103
104
// define string with length structure
105
struct string { uint8_t len; uint8_t data[128]; };
106
107
FUNCTOR_TYPEDEF(ParamGetSetIntCb, bool, AP_DroneCAN*, const uint8_t, const char*, int32_t &);
108
FUNCTOR_TYPEDEF(ParamGetSetFloatCb, bool, AP_DroneCAN*, const uint8_t, const char*, float &);
109
FUNCTOR_TYPEDEF(ParamGetSetStringCb, bool, AP_DroneCAN*, const uint8_t, const char*, string &);
110
FUNCTOR_TYPEDEF(ParamSaveCb, void, AP_DroneCAN*, const uint8_t, bool);
111
112
void send_node_status();
113
114
///// SRV output /////
115
void SRV_push_servos(void);
116
117
///// LED /////
118
bool led_write(uint8_t led_index, uint8_t red, uint8_t green, uint8_t blue);
119
120
// buzzer
121
void set_buzzer_tone(float frequency, float duration_s);
122
123
// Send Reboot command
124
// Note: Do not call this from outside UAVCAN thread context,
125
// you can call this from dronecan callbacks and handlers.
126
// THIS IS NOT A THREAD SAFE API!
127
void send_reboot_request(uint8_t node_id);
128
129
// get or set param value
130
// returns true on success, false on failure
131
// failures occur when waiting on node to respond to previous get or set request
132
bool set_parameter_on_node(uint8_t node_id, const char *name, float value, ParamGetSetFloatCb *cb);
133
bool set_parameter_on_node(uint8_t node_id, const char *name, int32_t value, ParamGetSetIntCb *cb);
134
bool set_parameter_on_node(uint8_t node_id, const char *name, const string &value, ParamGetSetStringCb *cb);
135
bool get_parameter_on_node(uint8_t node_id, const char *name, ParamGetSetFloatCb *cb);
136
bool get_parameter_on_node(uint8_t node_id, const char *name, ParamGetSetIntCb *cb);
137
bool get_parameter_on_node(uint8_t node_id, const char *name, ParamGetSetStringCb *cb);
138
139
// Save parameters
140
bool save_parameters_on_node(uint8_t node_id, ParamSaveCb *cb);
141
142
// options bitmask
143
enum class Options : uint16_t {
144
DNA_CLEAR_DATABASE = (1U<<0),
145
DNA_IGNORE_DUPLICATE_NODE = (1U<<1),
146
CANFD_ENABLED = (1U<<2),
147
DNA_IGNORE_UNHEALTHY_NODE = (1U<<3),
148
USE_ACTUATOR_PWM = (1U<<4),
149
SEND_GNSS = (1U<<5),
150
USE_HIMARK_SERVO = (1U<<6),
151
USE_HOBBYWING_ESC = (1U<<7),
152
ENABLE_STATS = (1U<<8),
153
ENABLE_FLEX_DEBUG = (1U<<9),
154
ALLOW_EXTENDED_AUX = (1U<<10),
155
};
156
157
// check if a option is set
158
bool option_is_set(Options option) const {
159
return (uint16_t(_options.get()) & uint16_t(option)) != 0;
160
}
161
162
// check if a option is set and if it is then reset it to
163
// 0. return true if it was set
164
bool check_and_reset_option(Options option);
165
166
CanardInterface& get_canard_iface() { return canard_iface; }
167
168
Canard::Publisher<uavcan_equipment_indication_LightsCommand> rgb_led{canard_iface};
169
Canard::Publisher<uavcan_equipment_indication_BeepCommand> buzzer{canard_iface};
170
Canard::Publisher<uavcan_equipment_gnss_RTCMStream> rtcm_stream{canard_iface};
171
172
#if HAL_MOUNT_XACTI_ENABLED
173
// xacti specific publishers
174
Canard::Publisher<com_xacti_CopterAttStatus> xacti_copter_att_status{canard_iface};
175
Canard::Publisher<com_xacti_GimbalControlData> xacti_gimbal_control_data{canard_iface};
176
Canard::Publisher<com_xacti_GnssStatus> xacti_gnss_status{canard_iface};
177
#endif // HAL_MOUNT_XACTI_ENABLED
178
179
#if AP_RELAY_DRONECAN_ENABLED
180
// Hardpoint for relay
181
// Needs to be public so relay can edge trigger as well as streaming
182
Canard::Publisher<uavcan_equipment_hardpoint_Command> relay_hardpoint{canard_iface};
183
#endif
184
185
#if AP_SCRIPTING_ENABLED
186
bool get_FlexDebug(uint8_t node_id, uint16_t msg_id, uint32_t &timestamp_us, dronecan_protocol_FlexDebug &msg) const;
187
#endif
188
189
private:
190
void loop(void);
191
192
///// SRV output /////
193
void SRV_send_actuator();
194
void SRV_send_esc();
195
#if AP_DRONECAN_HIMARK_SERVO_SUPPORT
196
void SRV_send_himark();
197
#endif
198
199
//scale servo output appropriately before sending
200
int16_t scale_esc_output(uint8_t idx);
201
202
// SafetyState
203
void safety_state_send();
204
205
// send notify vehicle state
206
void notify_state_send();
207
208
// check for parameter get/set response timeout
209
void check_parameter_callback_timeout();
210
211
// send queued parameter get/set request. called from loop
212
void send_parameter_request();
213
214
// send queued parameter save request. called from loop
215
void send_parameter_save_request();
216
217
// periodic logging
218
void logging();
219
220
// get parameter on a node
221
ParamGetSetIntCb *param_int_cb; // latest get param request callback function (for integers)
222
ParamGetSetFloatCb *param_float_cb; // latest get param request callback function (for floats)
223
ParamGetSetStringCb *param_string_cb; // latest get param request callback function (for strings)
224
bool param_request_sent = true; // true after a param request has been sent, false when queued to be sent
225
uint32_t param_request_sent_ms; // system time that get param request was sent
226
HAL_Semaphore _param_sem; // semaphore protecting this block of variables
227
uint8_t param_request_node_id; // node id of most recent get param request
228
229
// save parameters on a node
230
ParamSaveCb *save_param_cb; // latest save param request callback function
231
bool param_save_request_sent = true; // true after a save param request has been sent, false when queued to be sent
232
HAL_Semaphore _param_save_sem; // semaphore protecting this block of variables
233
uint8_t param_save_request_node_id; // node id of most recent save param request
234
235
// UAVCAN parameters
236
AP_Int8 _dronecan_node;
237
AP_Int32 _servo_bm;
238
AP_Int32 _esc_bm;
239
AP_Int8 _esc_offset;
240
AP_Int16 _servo_rate_hz;
241
AP_Int16 _options;
242
AP_Int16 _notify_state_hz;
243
AP_Int16 _pool_size;
244
AP_Int32 _esc_rv;
245
246
uint32_t *mem_pool;
247
248
uint8_t _driver_index;
249
250
CanardInterface canard_iface;
251
252
AP_DroneCAN_DNA_Server _dna_server;
253
254
char _thread_name[13];
255
bool _initialized;
256
///// SRV output /////
257
struct {
258
uint16_t pulse;
259
bool esc_pending;
260
bool servo_pending;
261
} _SRV_conf[DRONECAN_SRV_NUMBER];
262
263
uint32_t _esc_send_count;
264
uint32_t _srv_send_count;
265
uint32_t _fail_send_count;
266
267
uint32_t _SRV_armed_mask; // mask of servo outputs that are active
268
uint32_t _ESC_armed_mask; // mask of ESC outputs that are active
269
uint32_t _SRV_last_send_us;
270
HAL_Semaphore SRV_sem;
271
272
// last log time
273
uint32_t last_log_ms;
274
275
#if AP_DRONECAN_SEND_GPS
276
// send GNSS Fix and yaw, same thing AP_GPS_DroneCAN would receive
277
void gnss_send_fix();
278
void gnss_send_yaw();
279
280
// GNSS Fix and Status
281
struct {
282
uint32_t last_gps_lib_fix_ms;
283
uint32_t last_send_status_ms;
284
uint32_t last_lib_yaw_time_ms;
285
} _gnss;
286
#endif
287
288
// node status send
289
uint32_t _node_status_last_send_ms;
290
291
// safety status send state
292
uint32_t _last_safety_state_ms;
293
294
// notify vehicle state
295
uint32_t _last_notify_state_ms;
296
uavcan_protocol_NodeStatus node_status_msg;
297
298
#if AP_RELAY_DRONECAN_ENABLED
299
void relay_hardpoint_send();
300
struct {
301
AP_Int16 rate_hz;
302
uint32_t last_send_ms;
303
uint8_t last_index;
304
} _relay;
305
#endif
306
307
#if AP_DRONECAN_SERIAL_ENABLED
308
AP_DroneCAN_Serial serial;
309
#endif
310
311
Canard::Publisher<uavcan_protocol_NodeStatus> node_status{canard_iface};
312
Canard::Publisher<dronecan_protocol_CanStats> can_stats{canard_iface};
313
Canard::Publisher<dronecan_protocol_Stats> protocol_stats{canard_iface};
314
Canard::Publisher<uavcan_equipment_actuator_ArrayCommand> act_out_array{canard_iface};
315
Canard::Publisher<uavcan_equipment_esc_RawCommand> esc_raw{canard_iface};
316
Canard::Publisher<ardupilot_indication_SafetyState> safety_state{canard_iface};
317
Canard::Publisher<uavcan_equipment_safety_ArmingStatus> arming_status{canard_iface};
318
Canard::Publisher<ardupilot_indication_NotifyState> notify_state{canard_iface};
319
320
#if AP_DRONECAN_HIMARK_SERVO_SUPPORT
321
Canard::Publisher<com_himark_servo_ServoCmd> himark_out{canard_iface};
322
#endif
323
324
#if AP_DRONECAN_SEND_GPS
325
Canard::Publisher<uavcan_equipment_gnss_Fix2> gnss_fix2{canard_iface};
326
Canard::Publisher<uavcan_equipment_gnss_Auxiliary> gnss_auxiliary{canard_iface};
327
Canard::Publisher<ardupilot_gnss_Heading> gnss_heading{canard_iface};
328
Canard::Publisher<ardupilot_gnss_Status> gnss_status{canard_iface};
329
#endif
330
// incoming messages
331
Canard::ObjCallback<AP_DroneCAN, ardupilot_indication_Button> safety_button_cb{this, &AP_DroneCAN::handle_button};
332
Canard::Subscriber<ardupilot_indication_Button> safety_button_listener{safety_button_cb, _driver_index};
333
334
Canard::ObjCallback<AP_DroneCAN, ardupilot_equipment_trafficmonitor_TrafficReport> traffic_report_cb{this, &AP_DroneCAN::handle_traffic_report};
335
Canard::Subscriber<ardupilot_equipment_trafficmonitor_TrafficReport> traffic_report_listener{traffic_report_cb, _driver_index};
336
337
#if AP_SERVO_TELEM_ENABLED
338
Canard::ObjCallback<AP_DroneCAN, uavcan_equipment_actuator_Status> actuator_status_cb{this, &AP_DroneCAN::handle_actuator_status};
339
Canard::Subscriber<uavcan_equipment_actuator_Status> actuator_status_listener{actuator_status_cb, _driver_index};
340
#endif
341
342
Canard::ObjCallback<AP_DroneCAN, uavcan_equipment_esc_Status> esc_status_cb{this, &AP_DroneCAN::handle_ESC_status};
343
Canard::Subscriber<uavcan_equipment_esc_Status> esc_status_listener{esc_status_cb, _driver_index};
344
345
#if AP_EXTENDED_ESC_TELEM_ENABLED
346
Canard::ObjCallback<AP_DroneCAN, uavcan_equipment_esc_StatusExtended> esc_status_extended_cb{this, &AP_DroneCAN::handle_esc_ext_status};
347
Canard::Subscriber<uavcan_equipment_esc_StatusExtended> esc_status_extended_listener{esc_status_extended_cb, _driver_index};
348
#endif
349
350
Canard::ObjCallback<AP_DroneCAN, uavcan_protocol_debug_LogMessage> debug_cb{this, &AP_DroneCAN::handle_debug};
351
Canard::Subscriber<uavcan_protocol_debug_LogMessage> debug_listener{debug_cb, _driver_index};
352
353
#if AP_DRONECAN_HIMARK_SERVO_SUPPORT && AP_SERVO_TELEM_ENABLED
354
Canard::ObjCallback<AP_DroneCAN, com_himark_servo_ServoInfo> himark_servo_ServoInfo_cb{this, &AP_DroneCAN::handle_himark_servoinfo};
355
Canard::Subscriber<com_himark_servo_ServoInfo> himark_servo_ServoInfo_cb_listener{himark_servo_ServoInfo_cb, _driver_index};
356
#endif
357
#if AP_DRONECAN_VOLZ_FEEDBACK_ENABLED
358
Canard::ObjCallback<AP_DroneCAN, com_volz_servo_ActuatorStatus> volz_servo_ActuatorStatus_cb{this, &AP_DroneCAN::handle_actuator_status_Volz};
359
Canard::Subscriber<com_volz_servo_ActuatorStatus> volz_servo_ActuatorStatus_listener{volz_servo_ActuatorStatus_cb, _driver_index};
360
#endif
361
362
// param client
363
Canard::ObjCallback<AP_DroneCAN, uavcan_protocol_param_GetSetResponse> param_get_set_res_cb{this, &AP_DroneCAN::handle_param_get_set_response};
364
Canard::Client<uavcan_protocol_param_GetSetResponse> param_get_set_client{canard_iface, param_get_set_res_cb};
365
366
Canard::ObjCallback<AP_DroneCAN, uavcan_protocol_param_ExecuteOpcodeResponse> param_save_res_cb{this, &AP_DroneCAN::handle_param_save_response};
367
Canard::Client<uavcan_protocol_param_ExecuteOpcodeResponse> param_save_client{canard_iface, param_save_res_cb};
368
369
// reboot client
370
void handle_restart_node_response(const CanardRxTransfer& transfer, const uavcan_protocol_RestartNodeResponse& msg) {}
371
Canard::ObjCallback<AP_DroneCAN, uavcan_protocol_RestartNodeResponse> restart_node_res_cb{this, &AP_DroneCAN::handle_restart_node_response};
372
Canard::Client<uavcan_protocol_RestartNodeResponse> restart_node_client{canard_iface, restart_node_res_cb};
373
374
uavcan_protocol_param_ExecuteOpcodeRequest param_save_req;
375
uavcan_protocol_param_GetSetRequest param_getset_req;
376
377
// Node Info Server
378
Canard::ObjCallback<AP_DroneCAN, uavcan_protocol_GetNodeInfoRequest> node_info_req_cb{this, &AP_DroneCAN::handle_node_info_request};
379
Canard::Server<uavcan_protocol_GetNodeInfoRequest> node_info_server{canard_iface, node_info_req_cb};
380
uavcan_protocol_GetNodeInfoResponse node_info_rsp;
381
382
#if AP_SCRIPTING_ENABLED
383
Canard::ObjCallback<AP_DroneCAN, dronecan_protocol_FlexDebug> FlexDebug_cb{this, &AP_DroneCAN::handle_FlexDebug};
384
Canard::Subscriber<dronecan_protocol_FlexDebug> FlexDebug_listener{FlexDebug_cb, _driver_index};
385
#endif
386
387
#if AP_DRONECAN_HOBBYWING_ESC_SUPPORT
388
/*
389
Hobbywing ESC support. Note that we need additional meta-data as
390
the status messages do not have an ESC ID in them, so we need a
391
mapping from node ID
392
*/
393
#define HOBBYWING_MAX_ESC 8
394
struct {
395
uint32_t last_GetId_send_ms;
396
uint8_t thr_chan[HOBBYWING_MAX_ESC];
397
} hobbywing;
398
void hobbywing_ESC_update();
399
400
void SRV_send_esc_hobbywing();
401
Canard::Publisher<com_hobbywing_esc_RawCommand> esc_hobbywing_raw{canard_iface};
402
Canard::Publisher<com_hobbywing_esc_GetEscID> esc_hobbywing_GetEscID{canard_iface};
403
Canard::ObjCallback<AP_DroneCAN, com_hobbywing_esc_GetEscID> esc_hobbywing_GetEscID_cb{this, &AP_DroneCAN::handle_hobbywing_GetEscID};
404
Canard::Subscriber<com_hobbywing_esc_GetEscID> esc_hobbywing_GetEscID_listener{esc_hobbywing_GetEscID_cb, _driver_index};
405
Canard::ObjCallback<AP_DroneCAN, com_hobbywing_esc_StatusMsg1> esc_hobbywing_StatusMSG1_cb{this, &AP_DroneCAN::handle_hobbywing_StatusMsg1};
406
Canard::Subscriber<com_hobbywing_esc_StatusMsg1> esc_hobbywing_StatusMSG1_listener{esc_hobbywing_StatusMSG1_cb, _driver_index};
407
Canard::ObjCallback<AP_DroneCAN, com_hobbywing_esc_StatusMsg2> esc_hobbywing_StatusMSG2_cb{this, &AP_DroneCAN::handle_hobbywing_StatusMsg2};
408
Canard::Subscriber<com_hobbywing_esc_StatusMsg2> esc_hobbywing_StatusMSG2_listener{esc_hobbywing_StatusMSG2_cb, _driver_index};
409
bool hobbywing_find_esc_index(uint8_t node_id, uint8_t &esc_index) const;
410
void handle_hobbywing_GetEscID(const CanardRxTransfer& transfer, const com_hobbywing_esc_GetEscID& msg);
411
void handle_hobbywing_StatusMsg1(const CanardRxTransfer& transfer, const com_hobbywing_esc_StatusMsg1& msg);
412
void handle_hobbywing_StatusMsg2(const CanardRxTransfer& transfer, const com_hobbywing_esc_StatusMsg2& msg);
413
#endif // AP_DRONECAN_HOBBYWING_ESC_SUPPORT
414
415
#if AP_DRONECAN_HIMARK_SERVO_SUPPORT && AP_SERVO_TELEM_ENABLED
416
void handle_himark_servoinfo(const CanardRxTransfer& transfer, const com_himark_servo_ServoInfo &msg);
417
#endif
418
419
// incoming button handling
420
void handle_button(const CanardRxTransfer& transfer, const ardupilot_indication_Button& msg);
421
void handle_traffic_report(const CanardRxTransfer& transfer, const ardupilot_equipment_trafficmonitor_TrafficReport& msg);
422
#if AP_SERVO_TELEM_ENABLED
423
void handle_actuator_status(const CanardRxTransfer& transfer, const uavcan_equipment_actuator_Status& msg);
424
#endif
425
#if AP_DRONECAN_VOLZ_FEEDBACK_ENABLED
426
void handle_actuator_status_Volz(const CanardRxTransfer& transfer, const com_volz_servo_ActuatorStatus& msg);
427
#endif
428
void handle_ESC_status(const CanardRxTransfer& transfer, const uavcan_equipment_esc_Status& msg);
429
#if AP_EXTENDED_ESC_TELEM_ENABLED
430
void handle_esc_ext_status(const CanardRxTransfer& transfer, const uavcan_equipment_esc_StatusExtended& msg);
431
#endif
432
static bool is_esc_data_index_valid(const uint8_t index);
433
void handle_debug(const CanardRxTransfer& transfer, const uavcan_protocol_debug_LogMessage& msg);
434
void handle_param_get_set_response(const CanardRxTransfer& transfer, const uavcan_protocol_param_GetSetResponse& rsp);
435
void handle_param_save_response(const CanardRxTransfer& transfer, const uavcan_protocol_param_ExecuteOpcodeResponse& rsp);
436
void handle_node_info_request(const CanardRxTransfer& transfer, const uavcan_protocol_GetNodeInfoRequest& req);
437
438
#if AP_SCRIPTING_ENABLED
439
void handle_FlexDebug(const CanardRxTransfer& transfer, const dronecan_protocol_FlexDebug& msg);
440
struct FlexDebug {
441
struct FlexDebug *next;
442
uint32_t timestamp_us;
443
uint8_t node_id;
444
dronecan_protocol_FlexDebug msg;
445
} *flexDebug_list;
446
#endif
447
};
448
449
#endif // #if HAL_ENABLE_DRONECAN_DRIVERS
450
451