2019-12-18 18:35:32 -04:00
|
|
|
#include "AP_Vehicle.h"
|
|
|
|
|
2020-06-09 17:14:25 -03:00
|
|
|
#include <AP_BLHeli/AP_BLHeli.h>
|
2020-01-16 06:40:52 -04:00
|
|
|
#include <AP_Common/AP_FWVersion.h>
|
2020-07-15 23:52:11 -03:00
|
|
|
#include <AP_Arming/AP_Arming.h>
|
2020-09-10 09:54:10 -03:00
|
|
|
#include <AP_Frsky_Telem/AP_Frsky_Parameters.h>
|
2020-12-05 14:46:16 -04:00
|
|
|
#include <AP_Mission/AP_Mission.h>
|
|
|
|
#include <AP_OSD/AP_OSD.h>
|
2020-01-16 06:40:52 -04:00
|
|
|
|
2019-12-18 18:35:32 -04:00
|
|
|
#define SCHED_TASK(func, rate_hz, max_time_micros) SCHED_TASK_CLASS(AP_Vehicle, &vehicle, func, rate_hz, max_time_micros)
|
|
|
|
|
|
|
|
/*
|
|
|
|
2nd group of parameters
|
|
|
|
*/
|
|
|
|
const AP_Param::GroupInfo AP_Vehicle::var_info[] = {
|
|
|
|
#if HAL_RUNCAM_ENABLED
|
|
|
|
// @Group: CAM_RC_
|
|
|
|
// @Path: ../AP_Camera/AP_RunCam.cpp
|
|
|
|
AP_SUBGROUPINFO(runcam, "CAM_RC_", 1, AP_Vehicle, AP_RunCam),
|
|
|
|
#endif
|
|
|
|
|
2019-12-30 14:15:48 -04:00
|
|
|
#if HAL_GYROFFT_ENABLED
|
|
|
|
// @Group: FFT_
|
|
|
|
// @Path: ../AP_GyroFFT/AP_GyroFFT.cpp
|
|
|
|
AP_SUBGROUPINFO(gyro_fft, "FFT_", 2, AP_Vehicle, AP_GyroFFT),
|
|
|
|
#endif
|
2020-04-06 01:12:11 -03:00
|
|
|
|
|
|
|
#if HAL_VISUALODOM_ENABLED
|
|
|
|
// @Group: VISO
|
|
|
|
// @Path: ../AP_VisualOdom/AP_VisualOdom.cpp
|
|
|
|
AP_SUBGROUPINFO(visual_odom, "VISO", 3, AP_Vehicle, AP_VisualOdom),
|
|
|
|
#endif
|
2020-05-28 17:50:07 -03:00
|
|
|
// @Group: VTX_
|
|
|
|
// @Path: ../AP_RCTelemetry/AP_VideoTX.cpp
|
|
|
|
AP_SUBGROUPINFO(vtx, "VTX_", 4, AP_Vehicle, AP_VideoTX),
|
|
|
|
|
2020-08-04 17:39:40 -03:00
|
|
|
#if HAL_MSP_ENABLED
|
|
|
|
// @Group: MSP
|
|
|
|
// @Path: ../AP_MSP/AP_MSP.cpp
|
|
|
|
AP_SUBGROUPINFO(msp, "MSP", 5, AP_Vehicle, AP_MSP),
|
|
|
|
#endif
|
|
|
|
|
2020-09-10 09:54:10 -03:00
|
|
|
#if HAL_WITH_FRSKY_TELEM_BIDIRECTIONAL
|
|
|
|
// @Group: FRSKY_
|
|
|
|
// @Path: ../AP_Frsky_Telem/AP_Frsky_Parameters.cpp
|
|
|
|
AP_SUBGROUPINFO(frsky_parameters, "FRSKY_", 6, AP_Vehicle, AP_Frsky_Parameters),
|
|
|
|
#endif
|
|
|
|
|
2020-10-22 14:17:26 -03:00
|
|
|
#if GENERATOR_ENABLED
|
|
|
|
// @Group: GEN_
|
|
|
|
// @Path: ../AP_Generator/AP_Generator.cpp
|
|
|
|
AP_SUBGROUPINFO(generator, "GEN_", 7, AP_Vehicle, AP_Generator),
|
|
|
|
#endif
|
|
|
|
|
2020-12-27 22:06:14 -04:00
|
|
|
#if HAL_EXTERNAL_AHRS_ENABLED
|
|
|
|
// @Group: EAHRS
|
|
|
|
// @Path: ../AP_ExternalAHRS/AP_ExternalAHRS.cpp
|
|
|
|
AP_SUBGROUPINFO(externalAHRS, "EAHRS", 8, AP_Vehicle, AP_ExternalAHRS),
|
|
|
|
#endif
|
2021-02-01 12:26:35 -04:00
|
|
|
|
2019-12-18 18:35:32 -04:00
|
|
|
AP_GROUPEND
|
|
|
|
};
|
|
|
|
|
|
|
|
// reference to the vehicle. using AP::vehicle() here does not work on clang
|
2020-03-08 23:58:28 -03:00
|
|
|
#if APM_BUILD_TYPE(APM_BUILD_UNKNOWN)
|
2019-12-18 18:35:32 -04:00
|
|
|
AP_Vehicle& vehicle = *AP_Vehicle::get_singleton();
|
|
|
|
#else
|
|
|
|
extern AP_Vehicle& vehicle;
|
|
|
|
#endif
|
|
|
|
|
2020-01-16 06:31:20 -04:00
|
|
|
/*
|
|
|
|
setup is called when the sketch starts
|
|
|
|
*/
|
|
|
|
void AP_Vehicle::setup()
|
|
|
|
{
|
|
|
|
// load the default values of variables listed in var_info[]
|
|
|
|
AP_Param::setup_sketch_defaults();
|
|
|
|
|
|
|
|
// initialise serial port
|
|
|
|
serial_manager.init_console();
|
|
|
|
|
|
|
|
hal.console->printf("\n\nInit %s"
|
|
|
|
"\n\nFree RAM: %u\n",
|
|
|
|
AP::fwversion().fw_string,
|
|
|
|
(unsigned)hal.util->available_memory());
|
|
|
|
|
|
|
|
load_parameters();
|
|
|
|
|
|
|
|
// initialise the main loop scheduler
|
|
|
|
const AP_Scheduler::Task *tasks;
|
|
|
|
uint8_t task_count;
|
|
|
|
uint32_t log_bit;
|
|
|
|
get_scheduler_tasks(tasks, task_count, log_bit);
|
|
|
|
AP::scheduler().init(tasks, task_count, log_bit);
|
2020-01-28 19:06:37 -04:00
|
|
|
|
|
|
|
// time per loop - this gets updated in the main loop() based on
|
|
|
|
// actual loop rate
|
|
|
|
G_Dt = scheduler.get_loop_period_s();
|
|
|
|
|
2020-02-11 21:01:17 -04:00
|
|
|
// this is here for Plane; its failsafe_check method requires the
|
|
|
|
// RC channels to be set as early as possible for maximum
|
|
|
|
// survivability.
|
|
|
|
set_control_channels();
|
|
|
|
|
|
|
|
// initialise serial manager as early as sensible to get
|
|
|
|
// diagnostic output during boot process. We have to initialise
|
|
|
|
// the GCS singleton first as it sets the global mavlink system ID
|
|
|
|
// which may get used very early on.
|
|
|
|
gcs().init();
|
|
|
|
|
|
|
|
// initialise serial ports
|
|
|
|
serial_manager.init();
|
|
|
|
gcs().setup_console();
|
|
|
|
|
|
|
|
// Register scheduler_delay_cb, which will run anytime you have
|
|
|
|
// more than 5ms remaining in your call to hal.scheduler->delay
|
|
|
|
hal.scheduler->register_delay_callback(scheduler_delay_callback, 5);
|
|
|
|
|
2020-09-05 01:18:07 -03:00
|
|
|
#if HAL_MSP_ENABLED
|
|
|
|
// call MSP init before init_ardupilot to allow for MSP sensors
|
|
|
|
msp.init();
|
|
|
|
#endif
|
|
|
|
|
2020-12-27 22:06:14 -04:00
|
|
|
#if HAL_EXTERNAL_AHRS_ENABLED
|
|
|
|
// call externalAHRS init before init_ardupilot to allow for external sensors
|
|
|
|
externalAHRS.init();
|
|
|
|
#endif
|
2021-02-01 12:26:35 -04:00
|
|
|
|
2020-01-28 19:06:37 -04:00
|
|
|
// init_ardupilot is where the vehicle does most of its initialisation.
|
|
|
|
init_ardupilot();
|
2020-09-14 21:03:15 -03:00
|
|
|
gcs().send_text(MAV_SEVERITY_INFO, "ArduPilot Ready");
|
2020-02-24 22:42:33 -04:00
|
|
|
|
2019-12-30 14:15:48 -04:00
|
|
|
// gyro FFT needs to be initialized really late
|
|
|
|
#if HAL_GYROFFT_ENABLED
|
|
|
|
gyro_fft.init(AP::scheduler().get_loop_period_us());
|
|
|
|
#endif
|
2020-02-17 21:59:18 -04:00
|
|
|
#if HAL_RUNCAM_ENABLED
|
|
|
|
runcam.init();
|
|
|
|
#endif
|
|
|
|
#if HAL_HOTT_TELEM_ENABLED
|
|
|
|
hott_telem.init();
|
|
|
|
#endif
|
2020-04-06 01:12:11 -03:00
|
|
|
#if HAL_VISUALODOM_ENABLED
|
|
|
|
// init library used for visual position estimation
|
|
|
|
visual_odom.init();
|
|
|
|
#endif
|
2020-05-28 17:50:07 -03:00
|
|
|
vtx.init();
|
2020-02-24 22:42:33 -04:00
|
|
|
|
|
|
|
#if AP_PARAM_KEY_DUMP
|
|
|
|
AP_Param::show_all(hal.console, true);
|
|
|
|
#endif
|
2020-11-05 19:35:35 -04:00
|
|
|
|
|
|
|
send_watchdog_reset_statustext();
|
2020-10-22 14:17:26 -03:00
|
|
|
|
|
|
|
#if GENERATOR_ENABLED
|
|
|
|
generator.init();
|
|
|
|
#endif
|
2020-01-16 06:31:20 -04:00
|
|
|
}
|
|
|
|
|
2020-01-27 21:36:10 -04:00
|
|
|
void AP_Vehicle::loop()
|
|
|
|
{
|
|
|
|
scheduler.loop();
|
|
|
|
G_Dt = scheduler.get_loop_period_s();
|
2020-11-30 23:52:29 -04:00
|
|
|
|
|
|
|
if (!done_safety_init) {
|
|
|
|
/*
|
|
|
|
disable safety if requested. This is delayed till after the
|
|
|
|
first loop has run to ensure that all servos have received
|
|
|
|
an update for their initial values. Otherwise we may end up
|
|
|
|
briefly driving a servo to a position out of the configured
|
|
|
|
range which could damage hardware
|
|
|
|
*/
|
|
|
|
done_safety_init = true;
|
|
|
|
BoardConfig.init_safety();
|
|
|
|
}
|
2020-01-27 21:36:10 -04:00
|
|
|
}
|
|
|
|
|
2020-03-07 06:49:59 -04:00
|
|
|
/*
|
|
|
|
fast loop callback for all vehicles. This will get called at the end of any vehicle-specific fast loop.
|
|
|
|
*/
|
|
|
|
void AP_Vehicle::fast_loop()
|
|
|
|
{
|
|
|
|
#if HAL_GYROFFT_ENABLED
|
|
|
|
gyro_fft.sample_gyros();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2019-12-18 18:35:32 -04:00
|
|
|
/*
|
|
|
|
common scheduler table for fast CPUs - all common vehicle tasks
|
|
|
|
should be listed here, along with how often they should be called (in hz)
|
|
|
|
and the maximum time they are expected to take (in microseconds)
|
|
|
|
*/
|
|
|
|
const AP_Scheduler::Task AP_Vehicle::scheduler_tasks[] = {
|
|
|
|
#if HAL_RUNCAM_ENABLED
|
2019-12-30 14:15:48 -04:00
|
|
|
SCHED_TASK_CLASS(AP_RunCam, &vehicle.runcam, update, 50, 50),
|
|
|
|
#endif
|
|
|
|
#if HAL_GYROFFT_ENABLED
|
2020-03-07 06:49:59 -04:00
|
|
|
SCHED_TASK_CLASS(AP_GyroFFT, &vehicle.gyro_fft, update, 400, 50),
|
2019-12-30 14:15:48 -04:00
|
|
|
SCHED_TASK_CLASS(AP_GyroFFT, &vehicle.gyro_fft, update_parameters, 1, 50),
|
2019-12-18 18:35:32 -04:00
|
|
|
#endif
|
2020-06-09 17:14:25 -03:00
|
|
|
SCHED_TASK(update_dynamic_notch, 200, 200),
|
2020-05-28 17:50:07 -03:00
|
|
|
SCHED_TASK_CLASS(AP_VideoTX, &vehicle.vtx, update, 2, 100),
|
2020-03-25 08:07:50 -03:00
|
|
|
SCHED_TASK(send_watchdog_reset_statustext, 0.1, 20),
|
2020-10-22 14:17:26 -03:00
|
|
|
#if GENERATOR_ENABLED
|
|
|
|
SCHED_TASK_CLASS(AP_Generator, &vehicle.generator, update, 10, 50),
|
|
|
|
#endif
|
2020-12-05 14:46:16 -04:00
|
|
|
#if OSD_ENABLED
|
|
|
|
SCHED_TASK(publish_osd_info, 1, 10),
|
|
|
|
#endif
|
2019-12-18 18:35:32 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
void AP_Vehicle::get_common_scheduler_tasks(const AP_Scheduler::Task*& tasks, uint8_t& num_tasks)
|
|
|
|
{
|
|
|
|
tasks = scheduler_tasks;
|
|
|
|
num_tasks = ARRAY_SIZE(scheduler_tasks);
|
|
|
|
}
|
|
|
|
|
2020-01-15 23:04:41 -04:00
|
|
|
/*
|
|
|
|
* a delay() callback that processes MAVLink packets. We set this as the
|
|
|
|
* callback in long running library initialisation routines to allow
|
|
|
|
* MAVLink to process packets while waiting for the initialisation to
|
|
|
|
* complete
|
|
|
|
*/
|
|
|
|
void AP_Vehicle::scheduler_delay_callback()
|
|
|
|
{
|
2020-03-11 05:47:44 -03:00
|
|
|
#if APM_BUILD_TYPE(APM_BUILD_Replay)
|
|
|
|
// compass.init() delays, so we end up here.
|
|
|
|
return;
|
|
|
|
#endif
|
|
|
|
|
2020-01-15 23:04:41 -04:00
|
|
|
static uint32_t last_1hz, last_50hz, last_5s;
|
|
|
|
|
|
|
|
AP_Logger &logger = AP::logger();
|
|
|
|
|
|
|
|
// don't allow potentially expensive logging calls:
|
|
|
|
logger.EnableWrites(false);
|
|
|
|
|
|
|
|
const uint32_t tnow = AP_HAL::millis();
|
|
|
|
if (tnow - last_1hz > 1000) {
|
|
|
|
last_1hz = tnow;
|
|
|
|
gcs().send_message(MSG_HEARTBEAT);
|
|
|
|
gcs().send_message(MSG_SYS_STATUS);
|
|
|
|
}
|
|
|
|
if (tnow - last_50hz > 20) {
|
|
|
|
last_50hz = tnow;
|
|
|
|
gcs().update_receive();
|
|
|
|
gcs().update_send();
|
|
|
|
_singleton->notify.update();
|
|
|
|
}
|
|
|
|
if (tnow - last_5s > 5000) {
|
|
|
|
last_5s = tnow;
|
2020-10-28 14:47:37 -03:00
|
|
|
if (AP_BoardConfig::in_config_error()) {
|
|
|
|
gcs().send_text(MAV_SEVERITY_CRITICAL, "Config Error: fix problem then reboot");
|
|
|
|
} else {
|
|
|
|
gcs().send_text(MAV_SEVERITY_INFO, "Initialising ArduPilot");
|
|
|
|
}
|
2020-01-15 23:04:41 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
logger.EnableWrites(true);
|
|
|
|
}
|
|
|
|
|
2020-03-25 08:07:50 -03:00
|
|
|
// if there's been a watchdog reset, notify the world via a statustext:
|
|
|
|
void AP_Vehicle::send_watchdog_reset_statustext()
|
|
|
|
{
|
|
|
|
if (!hal.util->was_watchdog_reset()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const AP_HAL::Util::PersistentData &pd = hal.util->last_persistent_data;
|
|
|
|
gcs().send_text(MAV_SEVERITY_CRITICAL,
|
2020-04-28 03:33:45 -03:00
|
|
|
"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",
|
2020-03-25 08:07:50 -03:00
|
|
|
pd.scheduler_task,
|
|
|
|
pd.semaphore_line,
|
|
|
|
pd.fault_line,
|
|
|
|
pd.fault_type,
|
|
|
|
(unsigned)pd.fault_addr,
|
|
|
|
pd.fault_thd_prio,
|
|
|
|
(unsigned)pd.fault_lr,
|
|
|
|
(unsigned)pd.fault_icsr,
|
|
|
|
pd.last_mavlink_msgid,
|
|
|
|
pd.last_mavlink_cmd,
|
|
|
|
(unsigned)pd.internal_errors,
|
2020-04-28 03:33:45 -03:00
|
|
|
(unsigned)pd.internal_error_count,
|
|
|
|
pd.thread_name4
|
2020-03-25 08:07:50 -03:00
|
|
|
);
|
|
|
|
}
|
2020-07-15 23:52:11 -03:00
|
|
|
|
|
|
|
bool AP_Vehicle::is_crashed() const
|
|
|
|
{
|
|
|
|
if (AP::arming().is_armed()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return AP::arming().last_disarm_method() == AP_Arming::Method::CRASH;
|
|
|
|
}
|
2020-03-25 08:07:50 -03:00
|
|
|
|
2020-06-09 17:14:25 -03:00
|
|
|
// @LoggerMessage: FTN
|
|
|
|
// @Description: Filter Tuning Messages
|
|
|
|
// @Field: TimeUS: microseconds since system startup
|
|
|
|
// @Field: NDn: number of active dynamic harmonic notches
|
|
|
|
// @Field: DnF1: dynamic harmonic notch centre frequency for motor 1
|
|
|
|
// @Field: DnF2: dynamic harmonic notch centre frequency for motor 2
|
|
|
|
// @Field: DnF3: dynamic harmonic notch centre frequency for motor 3
|
|
|
|
// @Field: DnF4: dynamic harmonic notch centre frequency for motor 4
|
|
|
|
void AP_Vehicle::write_notch_log_messages() const
|
|
|
|
{
|
|
|
|
const float* notches = ins.get_gyro_dynamic_notch_center_frequencies_hz();
|
|
|
|
AP::logger().Write(
|
|
|
|
"FTN", "TimeUS,NDn,DnF1,DnF2,DnF3,DnF4", "s-zzzz", "F-----", "QBffff", AP_HAL::micros64(), ins.get_num_gyro_dynamic_notch_center_frequencies(),
|
|
|
|
notches[0], notches[1], notches[2], notches[3]);
|
|
|
|
}
|
|
|
|
|
2020-09-27 22:21:52 -03:00
|
|
|
// reboot the vehicle in an orderly manner, doing various cleanups and
|
|
|
|
// flashing LEDs as appropriate
|
|
|
|
void AP_Vehicle::reboot(bool hold_in_bootloader)
|
|
|
|
{
|
|
|
|
if (should_zero_rc_outputs_on_reboot()) {
|
|
|
|
SRV_Channels::zero_rc_outputs();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Notify might want to blink some LEDs:
|
|
|
|
AP_Notify::flags.firmware_update = 1;
|
|
|
|
notify.update();
|
|
|
|
|
|
|
|
// force safety on
|
|
|
|
hal.rcout->force_safety_on();
|
|
|
|
|
|
|
|
// flush pending parameter writes
|
|
|
|
AP_Param::flush();
|
|
|
|
|
|
|
|
// do not process incoming mavlink messages while we delay:
|
|
|
|
hal.scheduler->register_delay_callback(nullptr, 5);
|
|
|
|
|
|
|
|
// delay to give the ACK a chance to get out, the LEDs to flash,
|
|
|
|
// the IO board safety to be forced on, the parameters to flush, ...
|
|
|
|
hal.scheduler->delay(200);
|
|
|
|
|
|
|
|
hal.scheduler->reboot(hold_in_bootloader);
|
|
|
|
}
|
|
|
|
|
2020-12-05 14:46:16 -04:00
|
|
|
#if OSD_ENABLED
|
|
|
|
void AP_Vehicle::publish_osd_info()
|
|
|
|
{
|
|
|
|
AP_Mission *mission = AP::mission();
|
|
|
|
if (mission == nullptr) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
AP_OSD *osd = AP::osd();
|
|
|
|
if (osd == nullptr) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
AP_OSD::NavInfo nav_info;
|
|
|
|
if(!get_wp_distance_m(nav_info.wp_distance)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
float wp_bearing_deg;
|
|
|
|
if (!get_wp_bearing_deg(wp_bearing_deg)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
nav_info.wp_bearing = (int32_t)wp_bearing_deg * 100; // OSD expects cd
|
|
|
|
if (!get_wp_crosstrack_error_m(nav_info.wp_xtrack_error)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
nav_info.wp_number = mission->get_current_nav_index();
|
|
|
|
osd->set_nav_info(nav_info);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2019-10-08 19:36:46 -03:00
|
|
|
AP_Vehicle *AP_Vehicle::_singleton = nullptr;
|
|
|
|
|
|
|
|
AP_Vehicle *AP_Vehicle::get_singleton()
|
|
|
|
{
|
|
|
|
return _singleton;
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace AP {
|
|
|
|
|
|
|
|
AP_Vehicle *vehicle()
|
|
|
|
{
|
|
|
|
return AP_Vehicle::get_singleton();
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|