Line data Source code
1 : #include "AP_Vehicle_config.h"
2 :
3 : #if AP_VEHICLE_ENABLED
4 :
5 : #include "AP_Vehicle.h"
6 : #include <AP_InertialSensor/AP_InertialSensor_rate_config.h>
7 :
8 : #include <AP_BLHeli/AP_BLHeli.h>
9 : #include <AP_Common/AP_FWVersion.h>
10 : #include <AP_Arming/AP_Arming.h>
11 : #include <AP_Frsky_Telem/AP_Frsky_Parameters.h>
12 : #include <AP_Logger/AP_Logger.h>
13 : #include <AP_Mission/AP_Mission.h>
14 : #include <AP_OSD/AP_OSD.h>
15 : #include <SRV_Channel/SRV_Channel.h>
16 : #include <AP_Motors/AP_Motors.h>
17 : #include <AR_Motors/AP_MotorsUGV.h>
18 : #include <AP_CheckFirmware/AP_CheckFirmware.h>
19 : #include <GCS_MAVLink/GCS.h>
20 : #if CONFIG_HAL_BOARD == HAL_BOARD_CHIBIOS
21 : #include <AP_HAL_ChibiOS/sdcard.h>
22 : #include <AP_HAL_ChibiOS/hwdef/common/stm32_util.h>
23 : #endif
24 : #include <AP_DDS/AP_DDS_Client.h>
25 : #if HAL_WITH_IO_MCU
26 : #include <AP_IOMCU/AP_IOMCU.h>
27 : extern AP_IOMCU iomcu;
28 : #endif
29 : #include <AP_Scripting/AP_Scripting.h>
30 : #include <SITL/SITL.h>
31 :
32 : #define SCHED_TASK(func, rate_hz, max_time_micros, prio) SCHED_TASK_CLASS(AP_Vehicle, &vehicle, func, rate_hz, max_time_micros, prio)
33 :
34 : /*
35 : 2nd group of parameters
36 : */
37 : const AP_Param::GroupInfo AP_Vehicle::var_info[] = {
38 :
39 : // 1: RunCam
40 :
41 : #if HAL_GYROFFT_ENABLED
42 : // @Group: FFT_
43 : // @Path: ../AP_GyroFFT/AP_GyroFFT.cpp
44 : AP_SUBGROUPINFO(gyro_fft, "FFT_", 2, AP_Vehicle, AP_GyroFFT),
45 : #endif
46 :
47 : #if HAL_VISUALODOM_ENABLED
48 : // @Group: VISO
49 : // @Path: ../AP_VisualOdom/AP_VisualOdom.cpp
50 : AP_SUBGROUPINFO(visual_odom, "VISO", 3, AP_Vehicle, AP_VisualOdom),
51 : #endif
52 :
53 : #if AP_VIDEOTX_ENABLED
54 : // @Group: VTX_
55 : // @Path: ../AP_VideoTX/AP_VideoTX.cpp
56 : AP_SUBGROUPINFO(vtx, "VTX_", 4, AP_Vehicle, AP_VideoTX),
57 : #endif
58 :
59 : #if HAL_MSP_ENABLED
60 : // @Group: MSP
61 : // @Path: ../AP_MSP/AP_MSP.cpp
62 : AP_SUBGROUPINFO(msp, "MSP", 5, AP_Vehicle, AP_MSP),
63 : #endif
64 :
65 : #if HAL_WITH_FRSKY_TELEM_BIDIRECTIONAL
66 : // @Group: FRSKY_
67 : // @Path: ../AP_Frsky_Telem/AP_Frsky_Parameters.cpp
68 : AP_SUBGROUPINFO(frsky_parameters, "FRSKY_", 6, AP_Vehicle, AP_Frsky_Parameters),
69 : #endif
70 :
71 : #if HAL_GENERATOR_ENABLED
72 : // @Group: GEN_
73 : // @Path: ../AP_Generator/AP_Generator.cpp
74 : AP_SUBGROUPINFO(generator, "GEN_", 7, AP_Vehicle, AP_Generator),
75 : #endif
76 :
77 : #if AP_EXTERNAL_AHRS_ENABLED
78 : // @Group: EAHRS
79 : // @Path: ../AP_ExternalAHRS/AP_ExternalAHRS.cpp
80 : AP_SUBGROUPINFO(externalAHRS, "EAHRS", 8, AP_Vehicle, AP_ExternalAHRS),
81 : #endif
82 :
83 : #if HAL_EFI_ENABLED
84 : // @Group: EFI
85 : // @Path: ../AP_EFI/AP_EFI.cpp
86 : AP_SUBGROUPINFO(efi, "EFI", 9, AP_Vehicle, AP_EFI),
87 : #endif
88 :
89 : #if AP_AIRSPEED_ENABLED
90 : // @Group: ARSPD
91 : // @Path: ../AP_Airspeed/AP_Airspeed.cpp
92 : AP_SUBGROUPINFO(airspeed, "ARSPD", 10, AP_Vehicle, AP_Airspeed),
93 : #endif
94 :
95 : #if AP_CUSTOMROTATIONS_ENABLED
96 : // @Group: CUST_ROT
97 : // @Path: ../AP_CustomRotations/AP_CustomRotations.cpp
98 : AP_SUBGROUPINFO(custom_rotations, "CUST_ROT", 11, AP_Vehicle, AP_CustomRotations),
99 : #endif
100 :
101 : #if HAL_WITH_ESC_TELEM
102 : // @Group: ESC_TLM
103 : // @Path: ../AP_ESC_Telem/AP_ESC_Telem.cpp
104 : AP_SUBGROUPINFO(esc_telem, "ESC_TLM", 12, AP_Vehicle, AP_ESC_Telem),
105 : #endif
106 :
107 : #if AP_AIS_ENABLED
108 : // @Group: AIS_
109 : // @Path: ../AP_AIS/AP_AIS.cpp
110 : AP_SUBGROUPINFO(ais, "AIS_", 13, AP_Vehicle, AP_AIS),
111 : #endif
112 :
113 : #if AP_FENCE_ENABLED
114 : // @Group: FENCE_
115 : // @Path: ../AC_Fence/AC_Fence.cpp
116 : AP_SUBGROUPINFO(fence, "FENCE_", 14, AP_Vehicle, AC_Fence),
117 : #endif
118 :
119 : #if AP_OPENDRONEID_ENABLED
120 : // @Group: DID_
121 : // @Path: ../AP_OpenDroneID/AP_OpenDroneID.cpp
122 : AP_SUBGROUPINFO(opendroneid, "DID_", 15, AP_Vehicle, AP_OpenDroneID),
123 : #endif
124 :
125 : #if AP_TEMPERATURE_SENSOR_ENABLED
126 : // @Group: TEMP
127 : // @Path: ../AP_TemperatureSensor/AP_TemperatureSensor.cpp
128 : AP_SUBGROUPINFO(temperature_sensor, "TEMP", 16, AP_Vehicle, AP_TemperatureSensor),
129 : #endif
130 :
131 : #if HAL_NMEA_OUTPUT_ENABLED
132 : // @Group: NMEA_
133 : // @Path: ../AP_NMEA_Output/AP_NMEA_Output.cpp
134 : AP_SUBGROUPINFO(nmea, "NMEA_", 17, AP_Vehicle, AP_NMEA_Output),
135 : #endif
136 :
137 : #if AP_DDS_ENABLED
138 : // @Group: DDS
139 : // @Path: ../AP_DDS/AP_DDS_Client.cpp
140 : AP_SUBGROUPPTR(dds_client, "DDS", 18, AP_Vehicle, AP_DDS_Client),
141 : #endif
142 :
143 : #if AP_KDECAN_ENABLED
144 : // @Group: KDE_
145 : // @Path: ../AP_KDECAN/AP_KDECAN.cpp
146 : AP_SUBGROUPINFO(kdecan, "KDE_", 19, AP_Vehicle, AP_KDECAN),
147 : #endif
148 :
149 : #if APM_BUILD_COPTER_OR_HELI || APM_BUILD_TYPE(APM_BUILD_ArduPlane) || APM_BUILD_TYPE(APM_BUILD_Rover)
150 : // @Param: FLTMODE_GCSBLOCK
151 : // @DisplayName: Flight mode block from GCS
152 : // @Description: Bitmask of flight modes to disable for GCS selection. Mode can still be accessed via RC or failsafe.
153 : // @Bitmask{Copter}: 0:Stabilize
154 : // @Bitmask{Copter}: 1:Acro
155 : // @Bitmask{Copter}: 2:AltHold
156 : // @Bitmask{Copter}: 3:Auto
157 : // @Bitmask{Copter}: 4:Guided
158 : // @Bitmask{Copter}: 5:Loiter
159 : // @Bitmask{Copter}: 6:Circle
160 : // @Bitmask{Copter}: 7:Drift
161 : // @Bitmask{Copter}: 8:Sport
162 : // @Bitmask{Copter}: 9:Flip
163 : // @Bitmask{Copter}: 10:AutoTune
164 : // @Bitmask{Copter}: 11:PosHold
165 : // @Bitmask{Copter}: 12:Brake
166 : // @Bitmask{Copter}: 13:Throw
167 : // @Bitmask{Copter}: 14:Avoid_ADSB
168 : // @Bitmask{Copter}: 15:Guided_NoGPS
169 : // @Bitmask{Copter}: 16:Smart_RTL
170 : // @Bitmask{Copter}: 17:FlowHold
171 : // @Bitmask{Copter}: 18:Follow
172 : // @Bitmask{Copter}: 19:ZigZag
173 : // @Bitmask{Copter}: 20:SystemID
174 : // @Bitmask{Copter}: 21:Heli_Autorotate
175 : // @Bitmask{Copter}: 22:Auto RTL
176 : // @Bitmask{Copter}: 23:Turtle
177 : // @Bitmask{Plane}: 0:Manual
178 : // @Bitmask{Plane}: 1:Circle
179 : // @Bitmask{Plane}: 2:Stabilize
180 : // @Bitmask{Plane}: 3:Training
181 : // @Bitmask{Plane}: 4:ACRO
182 : // @Bitmask{Plane}: 5:FBWA
183 : // @Bitmask{Plane}: 6:FBWB
184 : // @Bitmask{Plane}: 7:CRUISE
185 : // @Bitmask{Plane}: 8:AUTOTUNE
186 : // @Bitmask{Plane}: 9:Auto
187 : // @Bitmask{Plane}: 10:Loiter
188 : // @Bitmask{Plane}: 11:Takeoff
189 : // @Bitmask{Plane}: 12:AVOID_ADSB
190 : // @Bitmask{Plane}: 13:Guided
191 : // @Bitmask{Plane}: 14:THERMAL
192 : // @Bitmask{Plane}: 15:QSTABILIZE
193 : // @Bitmask{Plane}: 16:QHOVER
194 : // @Bitmask{Plane}: 17:QLOITER
195 : // @Bitmask{Plane}: 18:QACRO
196 : // @Bitmask{Plane}: 19:QAUTOTUNE
197 : // @Bitmask{Plane}: 20:Loiter to QLand
198 : // @Bitmask{Plane}: 21:Autoland
199 : // @Bitmask{Rover}: 0:Manual
200 : // @Bitmask{Rover}: 1:Acro
201 : // @Bitmask{Rover}: 2:Steering
202 : // @Bitmask{Rover}: 3:Loiter
203 : // @Bitmask{Rover}: 4:Follow
204 : // @Bitmask{Rover}: 5:Simple
205 : // @Bitmask{Rover}: 6:Circle
206 : // @Bitmask{Rover}: 7:Auto
207 : // @Bitmask{Rover}: 8:RTL
208 : // @Bitmask{Rover}: 9:SmartRTL
209 : // @Bitmask{Rover}: 10:Guided
210 : // @Bitmask{Rover}: 11:Dock
211 : // @User: Standard
212 : AP_GROUPINFO("FLTMODE_GCSBLOCK", 20, AP_Vehicle, flight_mode_GCS_block, 0),
213 : #endif // APM_BUILD_COPTER_OR_HELI || APM_BUILD_TYPE(APM_BUILD_ArduPlane) || APM_BUILD_TYPE(APM_BUILD_Rover)
214 :
215 :
216 : #if AP_NETWORKING_ENABLED
217 : // @Group: NET_
218 : // @Path: ../AP_Networking/AP_Networking.cpp
219 : AP_SUBGROUPINFO(networking, "NET_", 21, AP_Vehicle, AP_Networking),
220 :
221 : /*
222 : the NET_Pn_ parameters need to be in AP_Vehicle as otherwise we
223 : are too deep in the parameter tree
224 : */
225 :
226 : #if AP_NETWORKING_REGISTER_PORT_ENABLED
227 : #if AP_NETWORKING_NUM_PORTS > 0
228 : // @Group: NET_P1_
229 : // @Path: ../AP_Networking/AP_Networking_port.cpp
230 : AP_SUBGROUPINFO(networking.ports[0], "NET_P1_", 22, AP_Vehicle, AP_Networking::Port),
231 : #endif
232 :
233 : #if AP_NETWORKING_NUM_PORTS > 1
234 : // @Group: NET_P2_
235 : // @Path: ../AP_Networking/AP_Networking_port.cpp
236 : AP_SUBGROUPINFO(networking.ports[1], "NET_P2_", 23, AP_Vehicle, AP_Networking::Port),
237 : #endif
238 :
239 : #if AP_NETWORKING_NUM_PORTS > 2
240 : // @Group: NET_P3_
241 : // @Path: ../AP_Networking/AP_Networking_port.cpp
242 : AP_SUBGROUPINFO(networking.ports[2], "NET_P3_", 24, AP_Vehicle, AP_Networking::Port),
243 : #endif
244 :
245 : #if AP_NETWORKING_NUM_PORTS > 3
246 : // @Group: NET_P4_
247 : // @Path: ../AP_Networking/AP_Networking_port.cpp
248 : AP_SUBGROUPINFO(networking.ports[3], "NET_P4_", 25, AP_Vehicle, AP_Networking::Port),
249 : #endif
250 : #endif // AP_NETWORKING_REGISTER_PORT_ENABLED
251 : #endif // AP_NETWORKING_ENABLED
252 :
253 : #if AP_FILTER_ENABLED
254 : // @Group: FILT
255 : // @Path: ../Filter/AP_Filter.cpp
256 : AP_SUBGROUPINFO(filters, "FILT", 26, AP_Vehicle, AP_Filters),
257 : #endif
258 :
259 : #if AP_STATS_ENABLED
260 : // @Group: STAT
261 : // @Path: ../AP_Stats/AP_Stats.cpp
262 : AP_SUBGROUPINFO(stats, "STAT", 27, AP_Vehicle, AP_Stats),
263 : #endif
264 :
265 : #if AP_SCRIPTING_ENABLED
266 : // @Group: SCR_
267 : // @Path: ../AP_Scripting/AP_Scripting.cpp
268 : AP_SUBGROUPINFO(scripting, "SCR_", 28, AP_Vehicle, AP_Scripting),
269 : #endif
270 :
271 : #if HAL_LOGGING_ENABLED
272 : // @Group: LOG
273 : // @Path: ../AP_Logger/AP_Logger.cpp
274 : AP_SUBGROUPINFO(logger, "LOG", 29, AP_Vehicle, AP_Logger),
275 : #endif
276 :
277 : #if AP_GRIPPER_ENABLED
278 : // @Group: GRIP_
279 : // @Path: ../AP_Gripper/AP_Gripper.cpp
280 : AP_SUBGROUPINFO(gripper, "GRIP_", 30, AP_Vehicle, AP_Gripper),
281 : #endif
282 :
283 : #if AP_SERIALMANAGER_ENABLED
284 : // @Group: SERIAL
285 : // @Path: ../AP_SerialManager/AP_SerialManager.cpp
286 : AP_SUBGROUPINFO(serial_manager, "SERIAL", 31, AP_Vehicle, AP_SerialManager),
287 : #endif
288 :
289 : #if AP_RPM_ENABLED
290 : // @Group: RPM
291 : // @Path: ../AP_RPM/AP_RPM.cpp
292 : AP_SUBGROUPINFO(rpm_sensor, "RPM", 32, AP_Vehicle, AP_RPM),
293 : #endif
294 :
295 : #if AP_BEACON_ENABLED
296 : // @Group: BCN
297 : // @Path: ../AP_Beacon/AP_Beacon.cpp
298 : AP_SUBGROUPINFO(beacon, "BCN", 33, AP_Vehicle, AP_Beacon),
299 : #endif // AP_BEACON_ENABLED
300 :
301 : AP_GROUPEND
302 : };
303 :
304 : // reference to the vehicle. using AP::vehicle() here does not work on clang
305 : #if APM_BUILD_TYPE(APM_BUILD_UNKNOWN) || APM_BUILD_TYPE(APM_BUILD_AP_Periph)
306 : AP_Vehicle& vehicle = *AP_Vehicle::get_singleton();
307 : #else
308 : extern AP_Vehicle& vehicle;
309 : #endif
310 :
311 : /*
312 : setup is called when the sketch starts
313 : */
314 2094 : void AP_Vehicle::setup()
315 : {
316 : // load the default values of variables listed in var_info[]
317 2094 : AP_Param::setup_sketch_defaults();
318 :
319 : #if AP_SERIALMANAGER_ENABLED
320 : // initialise serial port
321 2094 : serial_manager.init_console();
322 : #endif
323 :
324 2094 : DEV_PRINTF("\n\nInit %s"
325 : "\n\nFree RAM: %u\n",
326 : AP::fwversion().fw_string,
327 : (unsigned)hal.util->available_memory());
328 :
329 : #if AP_CHECK_FIRMWARE_ENABLED
330 2094 : check_firmware_print();
331 : #endif
332 :
333 : // validate the static parameter table, then load persistent
334 : // values from storage:
335 2094 : AP_Param::check_var_info();
336 2094 : load_parameters();
337 :
338 : #if CONFIG_HAL_BOARD == HAL_BOARD_CHIBIOS
339 : if (AP_BoardConfig::get_sdcard_slowdown() != 0) {
340 : // user wants the SDcard slower, we need to remount
341 : sdcard_stop();
342 : sdcard_retry();
343 : }
344 : #endif
345 :
346 : #if AP_SCHEDULER_ENABLED
347 : // initialise the main loop scheduler
348 : const AP_Scheduler::Task *tasks;
349 : uint8_t task_count;
350 : uint32_t log_bit;
351 2094 : get_scheduler_tasks(tasks, task_count, log_bit);
352 2094 : AP::scheduler().init(tasks, task_count, log_bit);
353 :
354 : // time per loop - this gets updated in the main loop() based on
355 : // actual loop rate
356 2094 : G_Dt = scheduler.get_loop_period_s();
357 : #endif
358 :
359 : // this is here for Plane; its failsafe_check method requires the
360 : // RC channels to be set as early as possible for maximum
361 : // survivability.
362 2094 : set_control_channels();
363 :
364 : #if HAL_GCS_ENABLED
365 : // initialise serial manager as early as sensible to get
366 : // diagnostic output during boot process. We have to initialise
367 : // the GCS singleton first as it sets the global mavlink system ID
368 : // which may get used very early on.
369 2094 : gcs().init();
370 : #endif
371 :
372 : #if AP_SERIALMANAGER_ENABLED
373 : #if HAL_WITH_IO_MCU
374 : if (BoardConfig.io_enabled()) {
375 : serial_manager.set_protocol_and_baud(HAL_UART_IOMCU_IDX, AP_SerialManager::SerialProtocol_IOMCU, 0);
376 : }
377 : #endif
378 : // initialise serial ports
379 2094 : serial_manager.init();
380 : #endif
381 : #if HAL_GCS_ENABLED
382 2094 : gcs().setup_console();
383 : #endif
384 :
385 : #if AP_SCRIPTING_ENABLED
386 : #if AP_SCRIPTING_SERIALDEVICE_ENABLED
387 : // must be done now so ports are registered and drivers get set up properly
388 : // (in particular mavlink which checks during init_ardupilot())
389 2094 : scripting.init_serialdevice_ports();
390 : #endif
391 : #endif
392 :
393 : #if AP_NETWORKING_ENABLED
394 2094 : networking.init();
395 : #endif
396 :
397 : #if AP_SCHEDULER_ENABLED
398 : // Register scheduler_delay_cb, which will run anytime you have
399 : // more than 5ms remaining in your call to hal.scheduler->delay
400 2094 : hal.scheduler->register_delay_callback(scheduler_delay_callback, 5);
401 : #endif
402 :
403 : #if AP_EXTERNAL_AHRS_ENABLED
404 : // call externalAHRS init before init_ardupilot to allow for external sensors
405 2094 : externalAHRS.init();
406 : #endif
407 :
408 : #if HAL_GENERATOR_ENABLED
409 2094 : generator.init();
410 : #endif
411 :
412 : #if AP_STATS_ENABLED
413 : // initialise stats module
414 2094 : stats.init();
415 : #endif
416 :
417 2094 : BoardConfig.init();
418 :
419 : #if HAL_CANMANAGER_ENABLED
420 2094 : can_mgr.init();
421 : #endif
422 :
423 : #if HAL_MSP_ENABLED
424 : // call MSP init before init_ardupilot to allow for MSP sensors
425 2094 : msp.init();
426 : #endif
427 :
428 : #if HAL_LOGGING_ENABLED
429 2094 : logger.init(get_log_bitmask(), get_log_structures(), get_num_log_structures());
430 : #endif
431 :
432 : // init cargo gripper
433 : #if AP_GRIPPER_ENABLED
434 2094 : AP::gripper().init();
435 : #endif
436 :
437 : // init beacons used for non-gps position estimation
438 : #if AP_BEACON_ENABLED
439 2094 : beacon.init();
440 : #endif // AP_BEACON_ENABLED
441 :
442 : // init_ardupilot is where the vehicle does most of its initialisation.
443 2094 : init_ardupilot();
444 :
445 : #if AP_SCRIPTING_ENABLED
446 2086 : scripting.init();
447 : #endif // AP_SCRIPTING_ENABLED
448 :
449 : #if AP_AIRSPEED_ENABLED
450 2086 : airspeed.init();
451 2086 : if (airspeed.enabled()) {
452 699 : airspeed.calibrate(true);
453 : }
454 : #if APM_BUILD_TYPE(APM_BUILD_ArduPlane)
455 : else {
456 1 : GCS_SEND_TEXT(MAV_SEVERITY_INFO, "No airspeed sensor");
457 : }
458 : #endif
459 : #endif // AP_AIRSPEED_ENABLED
460 :
461 :
462 : #if AP_SRV_CHANNELS_ENABLED
463 2086 : AP::srv().init();
464 : #endif
465 :
466 : // gyro FFT needs to be initialized really late
467 : #if HAL_GYROFFT_ENABLED
468 : #if AP_SCHEDULER_ENABLED
469 2086 : gyro_fft.init(AP::scheduler().get_loop_rate_hz());
470 : #else
471 : gyro_fft.init(1000);
472 : #endif
473 : #endif
474 : #if HAL_HOTT_TELEM_ENABLED
475 2086 : hott_telem.init();
476 : #endif
477 : #if HAL_VISUALODOM_ENABLED
478 : // init library used for visual position estimation
479 2086 : visual_odom.init();
480 : #endif
481 :
482 : #if AP_VIDEOTX_ENABLED
483 2086 : vtx.init();
484 : #endif
485 :
486 : #if AP_SMARTAUDIO_ENABLED
487 2086 : smartaudio.init();
488 : #endif
489 :
490 : #if AP_TRAMP_ENABLED
491 2086 : tramp.init();
492 : #endif
493 :
494 : #if AP_PARAM_KEY_DUMP
495 : AP_Param::show_all(hal.console, true);
496 : #endif
497 :
498 2086 : send_watchdog_reset_statustext();
499 :
500 : #if AP_OPENDRONEID_ENABLED
501 2086 : opendroneid.init();
502 : #endif
503 :
504 : // init EFI monitoring
505 : #if HAL_EFI_ENABLED
506 2086 : efi.init();
507 : #endif
508 :
509 : #if AP_TEMPERATURE_SENSOR_ENABLED
510 2086 : temperature_sensor.init();
511 : #endif
512 :
513 : #if AP_KDECAN_ENABLED
514 2086 : kdecan.init();
515 : #endif
516 :
517 : #if AP_AIS_ENABLED
518 2086 : ais.init();
519 : #endif
520 :
521 : #if HAL_NMEA_OUTPUT_ENABLED
522 2086 : nmea.init();
523 : #endif
524 :
525 : #if AP_FENCE_ENABLED
526 2086 : fence.init();
527 2086 : fence_init();
528 : #endif
529 :
530 : #if AP_CUSTOMROTATIONS_ENABLED
531 2086 : custom_rotations.init();
532 : #endif
533 :
534 : #if AP_FILTER_ENABLED
535 2086 : filters.init();
536 : #endif
537 :
538 : #if HAL_WITH_ESC_TELEM && HAL_GYROFFT_ENABLED
539 68838 : for (uint8_t i = 0; i<ESC_TELEM_MAX_ESCS; i++) {
540 66752 : esc_noise[i].set_cutoff_frequency(2);
541 : }
542 : #endif
543 :
544 : #if AP_RPM_ENABLED
545 2086 : rpm_sensor.init();
546 : #endif
547 :
548 : #if AP_ARMING_ENABLED
549 2086 : AP::arming().init();
550 : #endif
551 :
552 : // invalidate count in case an enable parameter changed during
553 : // initialisation
554 2086 : AP_Param::invalidate_count();
555 :
556 2086 : GCS_SEND_TEXT(MAV_SEVERITY_INFO, "ArduPilot Ready");
557 :
558 : #if AP_DDS_ENABLED
559 : if (!init_dds_client()) {
560 : GCS_SEND_TEXT(MAV_SEVERITY_ERROR, "%s Failed to Initialize", AP_DDS_Client::msg_prefix);
561 : }
562 : #endif
563 :
564 : #if AP_IBUS_TELEM_ENABLED
565 2086 : ibus_telem.init();
566 : #endif
567 2086 : }
568 :
569 41686254 : void AP_Vehicle::loop()
570 : {
571 : #if AP_SCHEDULER_ENABLED
572 41686254 : scheduler.loop();
573 41684622 : G_Dt = scheduler.get_loop_period_s();
574 : #else
575 : hal.scheduler->delay(1);
576 : G_Dt = 0.001;
577 : #endif
578 :
579 41684622 : if (!done_safety_init) {
580 : /*
581 : disable safety if requested. This is delayed till after the
582 : first loop has run to ensure that all servos have received
583 : an update for their initial values. Otherwise we may end up
584 : briefly driving a servo to a position out of the configured
585 : range which could damage hardware
586 : */
587 2086 : done_safety_init = true;
588 2086 : BoardConfig.init_safety();
589 :
590 : // send RC output mode info if available
591 : char banner_msg[50];
592 2086 : if (hal.rcout->get_output_mode_banner(banner_msg, sizeof(banner_msg))) {
593 0 : GCS_SEND_TEXT(MAV_SEVERITY_INFO, "%s", banner_msg);
594 : }
595 : }
596 41684622 : const uint32_t new_internal_errors = AP::internalerror().errors();
597 41684622 : if(_last_internal_errors != new_internal_errors) {
598 1 : LOGGER_WRITE_ERROR(LogErrorSubsystem::INTERNAL_ERROR, LogErrorCode::INTERNAL_ERRORS_DETECTED);
599 1 : GCS_SEND_TEXT(MAV_SEVERITY_CRITICAL, "Internal Errors 0x%x", (unsigned)new_internal_errors);
600 1 : _last_internal_errors = new_internal_errors;
601 : }
602 41684622 : }
603 :
604 : #if AP_SCHEDULER_ENABLED
605 : /*
606 : scheduler table - all regular tasks apart from the fast_loop()
607 : should be listed here.
608 :
609 : All entries in this table must be ordered by priority.
610 :
611 : This table is interleaved with the table presnet in each of the
612 : vehicles to determine the order in which tasks are run. Convenience
613 : methods SCHED_TASK and SCHED_TASK_CLASS are provided to build
614 : entries in this structure:
615 :
616 : SCHED_TASK arguments:
617 : - name of static function to call
618 : - rate (in Hertz) at which the function should be called
619 : - expected time (in MicroSeconds) that the function should take to run
620 : - priority (0 through 255, lower number meaning higher priority)
621 :
622 : SCHED_TASK_CLASS arguments:
623 : - class name of method to be called
624 : - instance on which to call the method
625 : - method to call on that instance
626 : - rate (in Hertz) at which the method should be called
627 : - expected time (in MicroSeconds) that the method should take to run
628 : - priority (0 through 255, lower number meaning higher priority)
629 :
630 : */
631 : const AP_Scheduler::Task AP_Vehicle::scheduler_tasks[] = {
632 : #if HAL_GYROFFT_ENABLED
633 : FAST_TASK_CLASS(AP_GyroFFT, &vehicle.gyro_fft, sample_gyros),
634 : #endif
635 : #if AP_BEACON_ENABLED
636 : SCHED_TASK_CLASS(AP_Beacon, &vehicle.beacon, update, 400, 200, 24),
637 : #endif // AP_BEACON_ENABLED
638 : #if AP_AIRSPEED_ENABLED
639 : SCHED_TASK_CLASS(AP_Airspeed, &vehicle.airspeed, update, 10, 100, 41), // NOTE: the priority number here should be right before Plane's calc_airspeed_errors
640 : #endif
641 : #if COMPASS_CAL_ENABLED
642 : SCHED_TASK_CLASS(Compass, &vehicle.compass, cal_update, 100, 200, 75),
643 : #endif
644 : SCHED_TASK_CLASS(AP_Notify, &vehicle.notify, update, 50, 300, 78),
645 : #if HAL_NMEA_OUTPUT_ENABLED
646 : SCHED_TASK_CLASS(AP_NMEA_Output, &vehicle.nmea, update, 50, 50, 180),
647 : #endif
648 : #if HAL_GYROFFT_ENABLED
649 : SCHED_TASK_CLASS(AP_GyroFFT, &vehicle.gyro_fft, update, 400, 50, 205),
650 : SCHED_TASK_CLASS(AP_GyroFFT, &vehicle.gyro_fft, update_parameters, 1, 50, 210),
651 : #endif
652 : #if AP_INERTIALSENSOR_HARMONICNOTCH_ENABLED && !AP_INERTIALSENSOR_FAST_SAMPLE_WINDOW_ENABLED
653 : SCHED_TASK(update_dynamic_notch_at_specified_rate, LOOP_RATE, 200, 215),
654 : #endif
655 : #if AP_VIDEOTX_ENABLED
656 : SCHED_TASK_CLASS(AP_VideoTX, &vehicle.vtx, update, 2, 100, 220),
657 : #endif
658 : #if AP_TRAMP_ENABLED
659 : SCHED_TASK_CLASS(AP_Tramp, &vehicle.tramp, update, 50, 50, 225),
660 : #endif
661 : SCHED_TASK(send_watchdog_reset_statustext, 0.1, 20, 225),
662 : #if HAL_WITH_ESC_TELEM
663 : // This update function is responsible for checking timeouts and invalidating the ESC telemetry data.
664 : // Be mindful of this if you are planning to reduce the frequency from 100Hz.
665 : SCHED_TASK_CLASS(AP_ESC_Telem, &vehicle.esc_telem, update, 100, 50, 230),
666 : #endif
667 : #if AP_SERVO_TELEM_ENABLED
668 : SCHED_TASK_CLASS(AP_Servo_Telem, &vehicle.servo_telem, update, 50, 50, 231),
669 : #endif
670 : #if HAL_GENERATOR_ENABLED
671 : SCHED_TASK_CLASS(AP_Generator, &vehicle.generator, update, 10, 50, 235),
672 : #endif
673 : #if AP_OPENDRONEID_ENABLED
674 : SCHED_TASK_CLASS(AP_OpenDroneID, &vehicle.opendroneid, update, 10, 50, 236),
675 : #endif
676 : #if AP_NETWORKING_ENABLED
677 : SCHED_TASK_CLASS(AP_Networking, &vehicle.networking, update, 10, 50, 238),
678 : #endif
679 : #if AP_RPM_ENABLED
680 : SCHED_TASK_CLASS(AP_RPM, &vehicle.rpm_sensor, update, 50, 100, 239),
681 : #endif
682 : #if OSD_ENABLED
683 : SCHED_TASK(publish_osd_info, 1, 10, 240),
684 : #endif
685 : #if AP_TEMPERATURE_SENSOR_ENABLED
686 : SCHED_TASK_CLASS(AP_TemperatureSensor, &vehicle.temperature_sensor, update, 5, 50, 242),
687 : #endif
688 : #if HAL_INS_ACCELCAL_ENABLED
689 : SCHED_TASK(accel_cal_update, 10, 100, 245),
690 : #endif
691 : #if AP_FENCE_ENABLED
692 : SCHED_TASK_CLASS(AC_Fence, &vehicle.fence, update, 10, 100, 248),
693 : #endif
694 : #if AP_AIS_ENABLED
695 : SCHED_TASK_CLASS(AP_AIS, &vehicle.ais, update, 5, 100, 249),
696 : #endif
697 : #if HAL_EFI_ENABLED
698 : SCHED_TASK_CLASS(AP_EFI, &vehicle.efi, update, 50, 200, 250),
699 : #endif
700 : #if AP_GRIPPER_ENABLED
701 : SCHED_TASK_CLASS(AP_Gripper, &vehicle.gripper, update, 10, 75, 251),
702 : #endif
703 : SCHED_TASK(one_Hz_update, 1, 100, 252),
704 : #if HAL_WITH_ESC_TELEM && HAL_GYROFFT_ENABLED
705 : SCHED_TASK(check_motor_noise, 5, 50, 252),
706 : #endif
707 : #if AP_FILTER_ENABLED
708 : SCHED_TASK_CLASS(AP_Filters, &vehicle.filters, update, 1, 100, 252),
709 : #endif
710 : #if AP_STATS_ENABLED
711 : SCHED_TASK_CLASS(AP_Stats, &vehicle.stats, update, 1, 100, 252),
712 : #endif
713 : #if AP_ARMING_ENABLED
714 : SCHED_TASK(update_arming, 1, 50, 253),
715 : #endif
716 : };
717 :
718 2094 : void AP_Vehicle::get_common_scheduler_tasks(const AP_Scheduler::Task*& tasks, uint8_t& num_tasks)
719 : {
720 2094 : tasks = scheduler_tasks;
721 2094 : num_tasks = ARRAY_SIZE(scheduler_tasks);
722 2094 : }
723 :
724 : /*
725 : * a delay() callback that processes MAVLink packets. We set this as the
726 : * callback in long running library initialisation routines to allow
727 : * MAVLink to process packets while waiting for the initialisation to
728 : * complete
729 : */
730 2415404 : void AP_Vehicle::scheduler_delay_callback()
731 : {
732 : #if APM_BUILD_TYPE(APM_BUILD_Replay)
733 : // compass.init() delays, so we end up here.
734 : return;
735 : #endif
736 :
737 : static uint32_t last_1hz, last_50hz, last_5s;
738 :
739 : #if HAL_LOGGING_ENABLED
740 2415404 : AP_Logger &logger = AP::logger();
741 :
742 : // don't allow potentially expensive logging calls:
743 2415404 : logger.EnableWrites(false);
744 : #endif
745 :
746 2415404 : const uint32_t tnow = AP_HAL::millis();
747 2415404 : if (tnow - last_1hz > 1000) {
748 3963 : last_1hz = tnow;
749 3963 : GCS_SEND_MESSAGE(MSG_HEARTBEAT);
750 3963 : GCS_SEND_MESSAGE(MSG_SYS_STATUS);
751 : }
752 2415404 : if (tnow - last_50hz > 20) {
753 220858 : last_50hz = tnow;
754 : #if HAL_GCS_ENABLED
755 220858 : gcs().update_receive();
756 220858 : gcs().update_send();
757 : #endif
758 220858 : _singleton->notify.update();
759 : }
760 2415404 : if (tnow - last_5s > 5000) {
761 108 : last_5s = tnow;
762 108 : if (AP_BoardConfig::in_config_error()) {
763 24 : GCS_SEND_TEXT(MAV_SEVERITY_CRITICAL, "Config Error: fix problem then reboot");
764 : } else {
765 84 : GCS_SEND_TEXT(MAV_SEVERITY_INFO, "Initialising ArduPilot");
766 : }
767 : }
768 :
769 : #if HAL_LOGGING_ENABLED
770 2415404 : logger.EnableWrites(true);
771 : #endif
772 2415404 : }
773 : #endif // AP_SCHEDULER_ENABLED
774 :
775 : // if there's been a watchdog reset, notify the world via a statustext:
776 16242 : void AP_Vehicle::send_watchdog_reset_statustext()
777 : {
778 16242 : if (!hal.util->was_watchdog_reset()) {
779 16239 : return;
780 : }
781 3 : const AP_HAL::Util::PersistentData &pd = hal.util->last_persistent_data;
782 : (void)pd; // in case !HAL_GCS_ENABLED
783 3 : GCS_SEND_TEXT(MAV_SEVERITY_CRITICAL,
784 : "WDG: T%d SL%u FL%u FT%u FA%x FTP%u FLR%x FICSR%u MM%u MC%u IE%u IEC%u TN:%.4s",
785 : pd.scheduler_task,
786 : pd.semaphore_line,
787 : pd.fault_line,
788 : pd.fault_type,
789 : (unsigned)pd.fault_addr,
790 : pd.fault_thd_prio,
791 : (unsigned)pd.fault_lr,
792 : (unsigned)pd.fault_icsr,
793 : pd.last_mavlink_msgid,
794 : pd.last_mavlink_cmd,
795 : (unsigned)pd.internal_errors,
796 : (unsigned)pd.internal_error_count,
797 : pd.thread_name4
798 : );
799 : }
800 :
801 8327 : bool AP_Vehicle::is_crashed() const
802 : {
803 : #if AP_ARMING_ENABLED
804 8327 : if (AP::arming().is_armed()) {
805 3620 : return false;
806 : }
807 4707 : return AP::arming().last_disarm_method() == AP_Arming::Method::CRASH;
808 : #else
809 : return false;
810 : #endif
811 : }
812 :
813 : #if AP_INERTIALSENSOR_HARMONICNOTCH_ENABLED
814 : // update the harmonic notch filter for throttle based notch
815 67072 : void AP_Vehicle::update_throttle_notch(AP_InertialSensor::HarmonicNotch ¬ch)
816 : {
817 : #if APM_BUILD_TYPE(APM_BUILD_ArduPlane) || APM_BUILD_COPTER_OR_HELI || APM_BUILD_TYPE(APM_BUILD_Rover)
818 67072 : const float ref_freq = notch.params.center_freq_hz();
819 67072 : const float ref = notch.params.reference();
820 :
821 : #if APM_BUILD_TYPE(APM_BUILD_ArduPlane) || APM_BUILD_COPTER_OR_HELI
822 67072 : const AP_Motors* motors = AP::motors();
823 67072 : if (motors == nullptr) {
824 0 : notch.update_freq_hz(0);
825 0 : return;
826 : }
827 67072 : const float motors_throttle = MAX(0,motors->get_throttle_out());
828 : // set the harmonic notch filter frequency scaled on measured frequency
829 67072 : if (notch.params.hasOption(HarmonicNotchFilterParams::Options::DynamicHarmonic)) {
830 : float notches[INS_MAX_NOTCHES];
831 43293 : uint8_t motor_num = 0;
832 1428669 : for (uint8_t i = 0; i < AP_MOTORS_MAX_NUM_MOTORS; i++) {
833 1385376 : float motor_throttle = 0;
834 1385376 : if (motors->get_thrust(i, motor_throttle)) {
835 175072 : notches[motor_num] = ref_freq * sqrtf(MAX(0, motor_throttle) / ref);
836 175072 : motor_num++;
837 : }
838 1385376 : if (motor_num >= INS_MAX_NOTCHES) {
839 0 : break;
840 : }
841 : }
842 43293 : notch.update_frequencies_hz(motor_num, notches);
843 : } else
844 : #else // APM_BUILD_Rover
845 0 : const AP_MotorsUGV *motors = AP::motors_ugv();
846 0 : const float motors_throttle = motors != nullptr ? abs(motors->get_throttle() * 0.01f) : 0;
847 : #endif
848 : {
849 23779 : float throttle_freq = ref_freq * sqrtf(MAX(0,motors_throttle) / ref);
850 :
851 23779 : notch.update_freq_hz(throttle_freq);
852 : }
853 :
854 : #endif
855 0 : }
856 :
857 : // update the harmonic notch filter center frequency dynamically
858 50037877 : void AP_Vehicle::update_dynamic_notch(AP_InertialSensor::HarmonicNotch ¬ch)
859 : {
860 : #if APM_BUILD_TYPE(APM_BUILD_ArduPlane)||APM_BUILD_COPTER_OR_HELI||APM_BUILD_TYPE(APM_BUILD_Rover)
861 47595007 : if (!notch.params.enabled()) {
862 47168376 : return;
863 : }
864 426631 : const float ref_freq = notch.params.center_freq_hz();
865 426631 : const float ref = notch.params.reference();
866 426631 : if (is_zero(ref)) {
867 14717 : notch.update_freq_hz(ref_freq);
868 14717 : return;
869 : }
870 :
871 411914 : switch (notch.params.tracking_mode()) {
872 62338 : case HarmonicNotchDynamicMode::UpdateThrottle: // throttle based tracking
873 : // set the harmonic notch filter frequency approximately scaled on motor rpm implied by throttle
874 62338 : update_throttle_notch(notch);
875 62338 : break;
876 :
877 : #if AP_RPM_ENABLED
878 0 : case HarmonicNotchDynamicMode::UpdateRPM: // rpm sensor based tracking
879 : case HarmonicNotchDynamicMode::UpdateRPM2: {
880 0 : uint8_t sensor = (notch.params.tracking_mode()==HarmonicNotchDynamicMode::UpdateRPM?0:1);
881 : float rpm;
882 0 : if (rpm_sensor.get_rpm(sensor, rpm)) {
883 : // set the harmonic notch filter frequency from the main rotor rpm
884 0 : notch.update_freq_hz(rpm * ref * (1.0/60));
885 : } else {
886 0 : notch.update_freq_hz(0);
887 : }
888 0 : break;
889 : }
890 : #endif // AP_RPM_ENABLED
891 : #if HAL_WITH_ESC_TELEM
892 228532 : case HarmonicNotchDynamicMode::UpdateBLHeli: // BLHeli based tracking
893 : // set the harmonic notch filter frequency scaled on measured frequency
894 228532 : if (notch.params.hasOption(HarmonicNotchFilterParams::Options::DynamicHarmonic)) {
895 : float notches[INS_MAX_NOTCHES];
896 : // ESC telemetry will return 0 for missing data, but only after 1s
897 151157 : const uint8_t num_notches = AP::esc_telem().get_motor_frequencies_hz(INS_MAX_NOTCHES, notches);
898 151157 : if (num_notches > 0) {
899 146423 : notch.update_frequencies_hz(num_notches, notches);
900 : } else { // throttle fallback
901 4734 : update_throttle_notch(notch);
902 : }
903 : } else {
904 77375 : notch.update_freq_hz(AP::esc_telem().get_average_motor_frequency_hz() * ref);
905 : }
906 228532 : break;
907 : #endif
908 : #if HAL_GYROFFT_ENABLED
909 97351 : case HarmonicNotchDynamicMode::UpdateGyroFFT: // FFT based tracking
910 : // set the harmonic notch filter frequency scaled on measured frequency
911 97351 : if (notch.params.hasOption(HarmonicNotchFilterParams::Options::DynamicHarmonic)) {
912 : float notches[INS_MAX_NOTCHES];
913 44424 : const uint8_t peaks = gyro_fft.get_weighted_noise_center_frequencies_hz(notch.num_dynamic_notches, notches);
914 :
915 44424 : if (peaks > 0) {
916 26255 : notch.set_inactive(false);
917 26255 : notch.update_frequencies_hz(peaks, notches);
918 : } else { // since FFT can be used post-filter it is better to disable the notch when there is no data
919 18169 : notch.set_inactive(true);
920 : }
921 : } else {
922 52927 : float center_freq = gyro_fft.get_weighted_noise_center_freq_hz();
923 52927 : notch.update_freq_hz(center_freq);
924 : }
925 97351 : break;
926 : #endif
927 23693 : case HarmonicNotchDynamicMode::Fixed: // static
928 : default:
929 23693 : notch.update_freq_hz(ref_freq);
930 23693 : break;
931 : }
932 : #endif // APM_BUILD_TYPE(APM_BUILD_ArduPlane)||APM_BUILD_COPTER_OR_HELI||APM_BUILD_TYPE(APM_BUILD_Rover)
933 2442870 : }
934 :
935 : // run notch update at either loop rate or 200Hz
936 41569286 : void AP_Vehicle::update_dynamic_notch_at_specified_rate()
937 : {
938 166277144 : for (auto ¬ch : ins.harmonic_notches) {
939 124707858 : if (notch.params.hasOption(HarmonicNotchFilterParams::Options::LoopRateUpdate)) {
940 43020 : update_dynamic_notch(notch);
941 : } else {
942 : // decimated update at 200Hz
943 124664838 : const uint32_t now = AP_HAL::millis();
944 124664838 : const uint8_t i = ¬ch - &ins.harmonic_notches[0];
945 124664838 : if (now - _last_notch_update_ms[i] > 5) {
946 49562530 : _last_notch_update_ms[i] = now;
947 49562530 : update_dynamic_notch(notch);
948 : }
949 : }
950 : }
951 41569286 : }
952 : #endif // AP_INERTIALSENSOR_HARMONICNOTCH_ENABLED
953 :
954 3 : void AP_Vehicle::notify_no_such_mode(uint8_t mode_number)
955 : {
956 3 : GCS_SEND_TEXT(MAV_SEVERITY_WARNING,"No such mode %u", mode_number);
957 3 : LOGGER_WRITE_ERROR(LogErrorSubsystem::FLIGHT_MODE, LogErrorCode(mode_number));
958 3 : }
959 :
960 : // reboot the vehicle in an orderly manner, doing various cleanups and
961 : // flashing LEDs as appropriate
962 1639 : void AP_Vehicle::reboot(bool hold_in_bootloader)
963 : {
964 1639 : if (should_zero_rc_outputs_on_reboot()) {
965 69 : SRV_Channels::zero_rc_outputs();
966 : }
967 :
968 : // Notify might want to blink some LEDs:
969 1639 : AP_Notify::flags.firmware_update = 1;
970 1639 : notify.update();
971 :
972 : // force safety on
973 1639 : hal.rcout->force_safety_on();
974 :
975 : // flush pending parameter writes
976 1639 : AP_Param::flush();
977 :
978 : // do not process incoming mavlink messages while we delay:
979 1639 : hal.scheduler->register_delay_callback(nullptr, 5);
980 :
981 : #if CONFIG_HAL_BOARD == HAL_BOARD_SITL
982 : // need to ensure the ack goes out:
983 1639 : hal.serial(0)->flush();
984 : #endif
985 :
986 : // delay to give the ACK a chance to get out, the LEDs to flash,
987 : // the IO board safety to be forced on, the parameters to flush, ...
988 1639 : hal.scheduler->delay(200);
989 :
990 : #if HAL_WITH_IO_MCU
991 : iomcu.soft_reboot();
992 : #endif
993 :
994 1639 : hal.scheduler->reboot(hold_in_bootloader);
995 0 : }
996 :
997 : #if OSD_ENABLED
998 149217 : void AP_Vehicle::publish_osd_info()
999 : {
1000 : #if AP_MISSION_ENABLED
1001 149217 : AP_OSD *osd = AP::osd();
1002 149217 : if (osd == nullptr) {
1003 16660 : return;
1004 : }
1005 : AP_OSD::NavInfo nav_info;
1006 147515 : if(!get_wp_distance_m(nav_info.wp_distance)) {
1007 14958 : return;
1008 : }
1009 : float wp_bearing_deg;
1010 132557 : if (!get_wp_bearing_deg(wp_bearing_deg)) {
1011 0 : return;
1012 : }
1013 132557 : nav_info.wp_bearing = (int32_t)wp_bearing_deg * 100; // OSD expects cd
1014 132557 : if (!get_wp_crosstrack_error_m(nav_info.wp_xtrack_error)) {
1015 0 : return;
1016 : }
1017 132557 : nav_info.wp_number = AP::mission().get_current_nav_index();
1018 132557 : osd->set_nav_info(nav_info);
1019 : #endif
1020 : }
1021 : #endif
1022 :
1023 1934 : void AP_Vehicle::get_osd_attitude_rad(float &roll, float &pitch, float &yaw)
1024 : {
1025 : #if AP_AHRS_ENABLED
1026 : // Take semaphore as this can be called from a thread
1027 1934 : WITH_SEMAPHORE(ahrs.get_semaphore());
1028 :
1029 1934 : roll = ahrs.get_roll_rad();
1030 1934 : pitch = ahrs.get_pitch_rad();
1031 1934 : yaw = ahrs.get_yaw_rad();
1032 : #else
1033 : roll = 0.0;
1034 : pitch = 0.0;
1035 : yaw = 0.0;
1036 : #endif
1037 1934 : }
1038 :
1039 : #if HAL_INS_ACCELCAL_ENABLED
1040 :
1041 : #ifndef HAL_CAL_ALWAYS_REBOOT
1042 : // allow for forced reboot after accelcal
1043 : #define HAL_CAL_ALWAYS_REBOOT 0
1044 : #endif
1045 :
1046 : /*
1047 : update accel cal
1048 : */
1049 1504089 : void AP_Vehicle::accel_cal_update()
1050 : {
1051 1504089 : if (hal.util->get_soft_armed()) {
1052 1004810 : return;
1053 : }
1054 499279 : ins.acal_update();
1055 :
1056 : #if AP_AHRS_ENABLED
1057 : // check if new trim values, and set them
1058 499279 : Vector3f trim_rad;
1059 499279 : if (ins.get_new_trim(trim_rad)) {
1060 1 : ahrs.set_trim(trim_rad);
1061 : }
1062 : #endif
1063 :
1064 : #if HAL_CAL_ALWAYS_REBOOT
1065 : if (ins.accel_cal_requires_reboot() &&
1066 : !hal.util->get_soft_armed()) {
1067 : hal.scheduler->delay(1000);
1068 : hal.scheduler->reboot();
1069 : }
1070 : #endif
1071 : }
1072 : #endif // HAL_INS_ACCELCAL_ENABLED
1073 :
1074 : #if AP_ARMING_ENABLED
1075 : // call the arming library's update function
1076 149217 : void AP_Vehicle::update_arming()
1077 : {
1078 149217 : AP::arming().update();
1079 149217 : }
1080 : #endif
1081 :
1082 : /*
1083 : one Hz checks common to all vehicles
1084 : */
1085 149217 : void AP_Vehicle::one_Hz_update(void)
1086 : {
1087 149217 : one_Hz_counter++;
1088 :
1089 : /*
1090 : every 10s check if using a 2M firmware on a 1M board
1091 : */
1092 149217 : if (one_Hz_counter % 10U == 0) {
1093 : #if defined(BOARD_CHECK_F427_USE_1M) && (HAL_PROGRAM_SIZE_LIMIT_KB>1024)
1094 : if (!hal.util->get_soft_armed() && check_limit_flash_1M()) {
1095 : GCS_SEND_TEXT(MAV_SEVERITY_CRITICAL, BOARD_CHECK_F427_USE_1M);
1096 : }
1097 : #endif
1098 : }
1099 :
1100 : /*
1101 : every 30s check if using a 1M firmware on a 2M board
1102 : */
1103 149217 : if (one_Hz_counter % 30U == 0) {
1104 : #if defined(BOARD_CHECK_F427_USE_1M) && (HAL_PROGRAM_SIZE_LIMIT_KB<=1024)
1105 : if (!hal.util->get_soft_armed() && !check_limit_flash_1M()) {
1106 : GCS_SEND_TEXT(MAV_SEVERITY_INFO, BOARD_CHECK_F427_USE_2M);
1107 : }
1108 : #endif
1109 : }
1110 :
1111 : #if AP_SCRIPTING_ENABLED
1112 149217 : scripting.update();
1113 : #endif
1114 :
1115 : #if HAL_LOGGING_ENABLED && HAL_UART_STATS_ENABLED
1116 : // Log data rates of physical and virtual serial ports
1117 149217 : hal.util->uart_log();
1118 : #if AP_SERIALMANAGER_REGISTER_ENABLED
1119 149217 : serial_manager.registered_ports_log();
1120 : #endif
1121 : #endif
1122 :
1123 : #if HAL_GCS_ENABLED
1124 : // Check if available modes have changed
1125 149217 : const uint32_t available_mode_enabled_mask = get_available_mode_enabled_mask();
1126 149217 : if (available_mode_enabled_mask != last_available_mode_enabled_mask) {
1127 1930 : if (last_available_mode_enabled_mask != 0) {
1128 : // Last value is only zero at init, track changes after that
1129 26 : gcs().available_modes_changed();
1130 : }
1131 1930 : last_available_mode_enabled_mask = available_mode_enabled_mask;
1132 : }
1133 : #endif
1134 :
1135 149217 : }
1136 :
1137 751641 : void AP_Vehicle::check_motor_noise()
1138 : {
1139 : #if HAL_GYROFFT_ENABLED && HAL_WITH_ESC_TELEM
1140 751641 : if (!hal.util->get_soft_armed() || !gyro_fft.check_esc_noise() || !gyro_fft.using_post_filter_samples()) {
1141 751317 : return;
1142 : }
1143 : #if AP_INERTIALSENSOR_HARMONICNOTCH_ENABLED
1144 324 : if (ins.has_fft_notch()) {
1145 0 : return;
1146 : }
1147 : #endif
1148 :
1149 : float esc_data[ESC_TELEM_MAX_ESCS];
1150 324 : const uint8_t numf = AP::esc_telem().get_motor_frequencies_hz(ESC_TELEM_MAX_ESCS, esc_data);
1151 324 : bool output_error = false;
1152 :
1153 1620 : for (uint8_t i = 0; i<numf; i++) {
1154 1296 : if (is_zero(esc_data[i])) {
1155 94 : continue;
1156 : }
1157 1202 : float energy = gyro_fft.has_noise_at_frequency_hz(esc_data[i]);
1158 1202 : energy = esc_noise[i].apply(energy, 0.2f);
1159 1202 : if (energy > 40.0f && AP_HAL::millis() - last_motor_noise_ms > 5000) {
1160 8 : GCS_SEND_TEXT(MAV_SEVERITY_WARNING, "Noise %.fdB on motor %u at %.fHz", energy, i+1, esc_data[i]);
1161 8 : output_error = true;
1162 : }
1163 : }
1164 :
1165 324 : if (output_error) {
1166 6 : last_motor_noise_ms = AP_HAL::millis();
1167 : }
1168 : #endif
1169 0 : }
1170 :
1171 : #if HAL_WITH_ESC_TELEM && (APM_BUILD_COPTER_OR_HELI || APM_BUILD_TYPE(APM_BUILD_ArduPlane))
1172 353204 : bool AP_Vehicle::motors_takeoff_check(float rpm_min, float rpm_max)
1173 : {
1174 353204 : auto motors = AP::motors();
1175 :
1176 : // Allow takeoff if check is disabled or if no motor class is present
1177 353204 : if (rpm_min <= 0 || motors == nullptr) {
1178 343513 : return true;
1179 : }
1180 :
1181 : // clear warning timer when disarmed
1182 9691 : uint32_t now_ms = AP_HAL::millis();
1183 9691 : if (!motors->armed()) {
1184 6158 : takeoff_check_state.warning_ms = now_ms;
1185 6158 : return false;
1186 : }
1187 :
1188 : // check ESCs are sending RPM at expected level
1189 3533 : uint32_t motor_mask = motors->get_motor_mask();
1190 3533 : const bool telem_active = AP::esc_telem().is_telemetry_active(motor_mask);
1191 3533 : const bool rpm_adequate = AP::esc_telem().are_motors_running(motor_mask, rpm_min, rpm_max);
1192 :
1193 : // if RPM is at the expected level clear block
1194 3533 : if (telem_active && rpm_adequate) {
1195 164 : return true;
1196 : }
1197 :
1198 : // warn the user every 2 seconds that telemetry is inactive or rpm is inadequate
1199 3369 : if (now_ms - takeoff_check_state.warning_ms > 2000) {
1200 14 : takeoff_check_state.warning_ms = now_ms;
1201 14 : const char* prefix_str = "Takeoff blocked:";
1202 14 : if (!telem_active) {
1203 0 : gcs().send_text(MAV_SEVERITY_CRITICAL, "%s waiting for ESC RPM", prefix_str);
1204 14 : } else if (!rpm_adequate) {
1205 14 : gcs().send_text(MAV_SEVERITY_CRITICAL, "%s ESC RPM out of range", prefix_str);
1206 : }
1207 : }
1208 3369 : return false;
1209 : }
1210 : #endif // HAL_WITH_ESC_TELEM && (APM_BUILD_COPTER_OR_HELI || APM_BUILD_TYPE(APM_BUILD_ArduPlane))
1211 :
1212 : #if AP_DDS_ENABLED
1213 : bool AP_Vehicle::init_dds_client()
1214 : {
1215 : dds_client = NEW_NOTHROW AP_DDS_Client();
1216 : if (dds_client == nullptr) {
1217 : return false;
1218 : }
1219 : return dds_client->start();
1220 : }
1221 : #endif // AP_DDS_ENABLED
1222 :
1223 : // Check if this mode can be entered from the GCS
1224 : #if APM_BUILD_COPTER_OR_HELI || APM_BUILD_TYPE(APM_BUILD_ArduPlane) || APM_BUILD_TYPE(APM_BUILD_Rover)
1225 1654613 : bool AP_Vehicle::block_GCS_mode_change(uint8_t mode_num, const uint8_t *mode_list, uint8_t mode_list_length) const
1226 : {
1227 1654613 : if (mode_list == nullptr) {
1228 0 : return false;
1229 : }
1230 :
1231 17935605 : for (uint8_t i = 0; i < mode_list_length; i++) {
1232 : // Find index of mode
1233 17772265 : if (mode_list[i] == mode_num) {
1234 1491273 : const uint32_t mask = 1U << i;
1235 1491273 : return (uint32_t(flight_mode_GCS_block) & mask) != 0;
1236 : }
1237 : }
1238 :
1239 163340 : return false;
1240 : }
1241 : #endif
1242 :
1243 : #if AP_FENCE_ENABLED
1244 2086 : void AP_Vehicle::fence_init()
1245 : {
1246 2086 : hal.scheduler->register_io_process(FUNCTOR_BIND_MEMBER(&AP_Vehicle::fence_checks_async, void));
1247 2086 : }
1248 : #endif // AP_FENCE_ENABLED
1249 :
1250 : AP_Vehicle *AP_Vehicle::_singleton = nullptr;
1251 :
1252 42587813 : AP_Vehicle *AP_Vehicle::get_singleton()
1253 : {
1254 42587813 : return _singleton;
1255 : }
1256 :
1257 : namespace AP {
1258 :
1259 42465416 : AP_Vehicle *vehicle()
1260 : {
1261 42465416 : return AP_Vehicle::get_singleton();
1262 : }
1263 :
1264 : };
1265 :
1266 : #endif // AP_VEHICLE_ENABLED
|