mirror of https://github.com/ArduPilot/ardupilot
Blimp: initial implementation of blimp vehicle type
This commit is contained in:
parent
30ebe6cde9
commit
b98bbcb678
|
@ -0,0 +1,488 @@
|
||||||
|
#include "Blimp.h"
|
||||||
|
|
||||||
|
|
||||||
|
// performs pre-arm checks. expects to be called at 1hz.
|
||||||
|
void AP_Arming_Blimp::update(void)
|
||||||
|
{
|
||||||
|
// perform pre-arm checks & display failures every 30 seconds
|
||||||
|
static uint8_t pre_arm_display_counter = PREARM_DISPLAY_PERIOD/2;
|
||||||
|
pre_arm_display_counter++;
|
||||||
|
bool display_fail = false;
|
||||||
|
if (pre_arm_display_counter >= PREARM_DISPLAY_PERIOD) {
|
||||||
|
display_fail = true;
|
||||||
|
pre_arm_display_counter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre_arm_checks(display_fail);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AP_Arming_Blimp::pre_arm_checks(bool display_failure)
|
||||||
|
{
|
||||||
|
const bool passed = run_pre_arm_checks(display_failure);
|
||||||
|
set_pre_arm_check(passed);
|
||||||
|
return passed;
|
||||||
|
}
|
||||||
|
|
||||||
|
// perform pre-arm checks
|
||||||
|
// return true if the checks pass successfully
|
||||||
|
bool AP_Arming_Blimp::run_pre_arm_checks(bool display_failure)
|
||||||
|
{
|
||||||
|
// exit immediately if already armed
|
||||||
|
if (blimp.motors->armed()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if motor interlock and Emergency Stop aux switches are used
|
||||||
|
// at the same time. This cannot be allowed.
|
||||||
|
if (rc().find_channel_for_option(RC_Channel::AUX_FUNC::MOTOR_INTERLOCK) &&
|
||||||
|
rc().find_channel_for_option(RC_Channel::AUX_FUNC::MOTOR_ESTOP)) {
|
||||||
|
check_failed(display_failure, "Interlock/E-Stop Conflict");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if motor interlock aux switch is in use
|
||||||
|
// if it is, switch needs to be in disabled position to arm
|
||||||
|
// otherwise exit immediately. This check to be repeated,
|
||||||
|
// as state can change at any time.
|
||||||
|
if (blimp.ap.using_interlock && blimp.ap.motor_interlock_switch) {
|
||||||
|
check_failed(display_failure, "Motor Interlock Enabled");
|
||||||
|
}
|
||||||
|
|
||||||
|
// if pre arm checks are disabled run only the mandatory checks
|
||||||
|
if (checks_to_perform == 0) {
|
||||||
|
return mandatory_checks(display_failure);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fence_checks(display_failure)
|
||||||
|
& parameter_checks(display_failure)
|
||||||
|
& motor_checks(display_failure)
|
||||||
|
& pilot_throttle_checks(display_failure)
|
||||||
|
& gcs_failsafe_check(display_failure)
|
||||||
|
& alt_checks(display_failure)
|
||||||
|
& AP_Arming::pre_arm_checks(display_failure);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AP_Arming_Blimp::barometer_checks(bool display_failure)
|
||||||
|
{
|
||||||
|
if (!AP_Arming::barometer_checks(display_failure)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ret = true;
|
||||||
|
// check Baro
|
||||||
|
if ((checks_to_perform == ARMING_CHECK_ALL) || (checks_to_perform & ARMING_CHECK_BARO)) {
|
||||||
|
// Check baro & inav alt are within 1m if EKF is operating in an absolute position mode.
|
||||||
|
// Do not check if intending to operate in a ground relative height mode as EKF will output a ground relative height
|
||||||
|
// that may differ from the baro height due to baro drift.
|
||||||
|
nav_filter_status filt_status = blimp.inertial_nav.get_filter_status();
|
||||||
|
bool using_baro_ref = (!filt_status.flags.pred_horiz_pos_rel && filt_status.flags.pred_horiz_pos_abs);
|
||||||
|
if (using_baro_ref) {
|
||||||
|
if (fabsf(blimp.inertial_nav.get_altitude() - blimp.baro_alt) > PREARM_MAX_ALT_DISPARITY_CM) {
|
||||||
|
check_failed(ARMING_CHECK_BARO, display_failure, "Altitude disparity");
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AP_Arming_Blimp::compass_checks(bool display_failure)
|
||||||
|
{
|
||||||
|
bool ret = AP_Arming::compass_checks(display_failure);
|
||||||
|
|
||||||
|
if ((checks_to_perform == ARMING_CHECK_ALL) || (checks_to_perform & ARMING_CHECK_COMPASS)) {
|
||||||
|
// check compass offsets have been set. AP_Arming only checks
|
||||||
|
// this if learning is off; Blimp *always* checks.
|
||||||
|
char failure_msg[50] = {};
|
||||||
|
if (!AP::compass().configured(failure_msg, ARRAY_SIZE(failure_msg))) {
|
||||||
|
check_failed(ARMING_CHECK_COMPASS, display_failure, "%s", failure_msg);
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AP_Arming_Blimp::ins_checks(bool display_failure)
|
||||||
|
{
|
||||||
|
bool ret = AP_Arming::ins_checks(display_failure);
|
||||||
|
|
||||||
|
if ((checks_to_perform == ARMING_CHECK_ALL) || (checks_to_perform & ARMING_CHECK_INS)) {
|
||||||
|
|
||||||
|
// get ekf attitude (if bad, it's usually the gyro biases)
|
||||||
|
if (!pre_arm_ekf_attitude_check()) {
|
||||||
|
check_failed(ARMING_CHECK_INS, display_failure, "EKF attitude is bad");
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AP_Arming_Blimp::board_voltage_checks(bool display_failure)
|
||||||
|
{
|
||||||
|
if (!AP_Arming::board_voltage_checks(display_failure)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check battery voltage
|
||||||
|
if ((checks_to_perform == ARMING_CHECK_ALL) || (checks_to_perform & ARMING_CHECK_VOLTAGE)) {
|
||||||
|
if (blimp.battery.has_failsafed()) {
|
||||||
|
check_failed(ARMING_CHECK_VOLTAGE, display_failure, "Battery failsafe");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// call parent battery checks
|
||||||
|
if (!AP_Arming::battery_checks(display_failure)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AP_Arming_Blimp::parameter_checks(bool display_failure)
|
||||||
|
{
|
||||||
|
// check various parameter values
|
||||||
|
if ((checks_to_perform == ARMING_CHECK_ALL) || (checks_to_perform & ARMING_CHECK_PARAMETERS)) {
|
||||||
|
|
||||||
|
// failsafe parameter checks
|
||||||
|
if (blimp.g.failsafe_throttle) {
|
||||||
|
// check throttle min is above throttle failsafe trigger and that the trigger is above ppm encoder's loss-of-signal value of 900
|
||||||
|
if (blimp.channel_down->get_radio_min() <= blimp.g.failsafe_throttle_value+10 || blimp.g.failsafe_throttle_value < 910) {
|
||||||
|
check_failed(ARMING_CHECK_PARAMETERS, display_failure, "Check FS_THR_VALUE");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (blimp.g.failsafe_gcs == FS_GCS_ENABLED_CONTINUE_MISSION) {
|
||||||
|
// FS_GCS_ENABLE == 2 has been removed
|
||||||
|
check_failed(ARMING_CHECK_PARAMETERS, display_failure, "FS_GCS_ENABLE=2 removed, see FS_OPTIONS");
|
||||||
|
}
|
||||||
|
|
||||||
|
// lean angle parameter check
|
||||||
|
if (blimp.aparm.angle_max < 1000 || blimp.aparm.angle_max > 8000) {
|
||||||
|
check_failed(ARMING_CHECK_PARAMETERS, display_failure, "Check ANGLE_MAX");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// pilot-speed-up parameter check
|
||||||
|
if (blimp.g.pilot_speed_up <= 0) {
|
||||||
|
check_failed(ARMING_CHECK_PARAMETERS, display_failure, "Check PILOT_SPEED_UP");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// checks MOT_PWM_MIN/MAX for acceptable values
|
||||||
|
// if (!blimp.motors->check_mot_pwm_params()) {
|
||||||
|
// check_failed(ARMING_CHECK_PARAMETERS, display_failure, "Check MOT_PWM_MIN/MAX");
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// ensure controllers are OK with us arming:
|
||||||
|
// char failure_msg[50];
|
||||||
|
// if (!blimp.pos_control->pre_arm_checks("PSC", failure_msg, ARRAY_SIZE(failure_msg))) {
|
||||||
|
// check_failed(ARMING_CHECK_PARAMETERS, display_failure, "Bad parameter: %s", failure_msg);
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// if (!blimp.attitude_control->pre_arm_checks("ATC", failure_msg, ARRAY_SIZE(failure_msg))) {
|
||||||
|
// check_failed(ARMING_CHECK_PARAMETERS, display_failure, "Bad parameter: %s", failure_msg);
|
||||||
|
// return false;
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check motor setup was successful
|
||||||
|
bool AP_Arming_Blimp::motor_checks(bool display_failure)
|
||||||
|
{
|
||||||
|
// check motors initialised correctly
|
||||||
|
if (!blimp.motors->initialised_ok()) {
|
||||||
|
check_failed(display_failure, "Check firmware or FRAME_CLASS");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// further checks enabled with parameters
|
||||||
|
if (!check_enabled(ARMING_CHECK_PARAMETERS)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AP_Arming_Blimp::pilot_throttle_checks(bool display_failure)
|
||||||
|
{
|
||||||
|
// check throttle is above failsafe throttle
|
||||||
|
// this is near the bottom to allow other failures to be displayed before checking pilot throttle
|
||||||
|
if ((checks_to_perform == ARMING_CHECK_ALL) || (checks_to_perform & ARMING_CHECK_RC)) {
|
||||||
|
if (blimp.g.failsafe_throttle != FS_THR_DISABLED && blimp.channel_down->get_radio_in() < blimp.g.failsafe_throttle_value) {
|
||||||
|
const char *failmsg = "Throttle below Failsafe";
|
||||||
|
check_failed(ARMING_CHECK_RC, display_failure, "%s", failmsg);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AP_Arming_Blimp::rc_calibration_checks(bool display_failure)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// performs pre_arm gps related checks and returns true if passed
|
||||||
|
bool AP_Arming_Blimp::gps_checks(bool display_failure)
|
||||||
|
{
|
||||||
|
// run mandatory gps checks first
|
||||||
|
if (!mandatory_gps_checks(display_failure)) {
|
||||||
|
AP_Notify::flags.pre_arm_gps_check = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if flight mode requires GPS
|
||||||
|
bool mode_requires_gps = blimp.flightmode->requires_GPS();
|
||||||
|
|
||||||
|
|
||||||
|
// return true if GPS is not required
|
||||||
|
if (!mode_requires_gps) {
|
||||||
|
AP_Notify::flags.pre_arm_gps_check = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return true immediately if gps check is disabled
|
||||||
|
if (!(checks_to_perform == ARMING_CHECK_ALL || checks_to_perform & ARMING_CHECK_GPS)) {
|
||||||
|
AP_Notify::flags.pre_arm_gps_check = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// warn about hdop separately - to prevent user confusion with no gps lock
|
||||||
|
if (blimp.gps.get_hdop() > blimp.g.gps_hdop_good) {
|
||||||
|
check_failed(ARMING_CHECK_GPS, display_failure, "High GPS HDOP");
|
||||||
|
AP_Notify::flags.pre_arm_gps_check = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// call parent gps checks
|
||||||
|
if (!AP_Arming::gps_checks(display_failure)) {
|
||||||
|
AP_Notify::flags.pre_arm_gps_check = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we got here all must be ok
|
||||||
|
AP_Notify::flags.pre_arm_gps_check = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check ekf attitude is acceptable
|
||||||
|
bool AP_Arming_Blimp::pre_arm_ekf_attitude_check()
|
||||||
|
{
|
||||||
|
// get ekf filter status
|
||||||
|
nav_filter_status filt_status = blimp.inertial_nav.get_filter_status();
|
||||||
|
|
||||||
|
return filt_status.flags.attitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
// performs mandatory gps checks. returns true if passed
|
||||||
|
bool AP_Arming_Blimp::mandatory_gps_checks(bool display_failure)
|
||||||
|
{
|
||||||
|
// always check if inertial nav has started and is ready
|
||||||
|
const AP_AHRS_NavEKF &ahrs = AP::ahrs_navekf();
|
||||||
|
char failure_msg[50] = {};
|
||||||
|
if (!ahrs.pre_arm_check(false, failure_msg, sizeof(failure_msg))) {
|
||||||
|
check_failed(display_failure, "AHRS: %s", failure_msg);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if flight mode requires GPS
|
||||||
|
bool mode_requires_gps = blimp.flightmode->requires_GPS();
|
||||||
|
|
||||||
|
if (mode_requires_gps) {
|
||||||
|
if (!blimp.position_ok()) {
|
||||||
|
// vehicle level position estimate checks
|
||||||
|
check_failed(display_failure, "Need Position Estimate");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// return true if GPS is not required
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we got here all must be ok
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check GCS failsafe
|
||||||
|
bool AP_Arming_Blimp::gcs_failsafe_check(bool display_failure)
|
||||||
|
{
|
||||||
|
if (blimp.failsafe.gcs) {
|
||||||
|
check_failed(display_failure, "GCS failsafe on");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// performs altitude checks. returns true if passed
|
||||||
|
bool AP_Arming_Blimp::alt_checks(bool display_failure)
|
||||||
|
{
|
||||||
|
// always EKF altitude estimate
|
||||||
|
if (!blimp.flightmode->has_manual_throttle() && !blimp.ekf_alt_ok()) {
|
||||||
|
check_failed(display_failure, "Need Alt Estimate");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// arm_checks - perform final checks before arming
|
||||||
|
// always called just before arming. Return true if ok to arm
|
||||||
|
// has side-effect that logging is started
|
||||||
|
bool AP_Arming_Blimp::arm_checks(AP_Arming::Method method)
|
||||||
|
{
|
||||||
|
return AP_Arming::arm_checks(method);
|
||||||
|
}
|
||||||
|
|
||||||
|
// mandatory checks that will be run if ARMING_CHECK is zero or arming forced
|
||||||
|
bool AP_Arming_Blimp::mandatory_checks(bool display_failure)
|
||||||
|
{
|
||||||
|
// call mandatory gps checks and update notify status because regular gps checks will not run
|
||||||
|
bool result = mandatory_gps_checks(display_failure);
|
||||||
|
AP_Notify::flags.pre_arm_gps_check = result;
|
||||||
|
|
||||||
|
// call mandatory alt check
|
||||||
|
if (!alt_checks(display_failure)) {
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AP_Arming_Blimp::set_pre_arm_check(bool b)
|
||||||
|
{
|
||||||
|
blimp.ap.pre_arm_check = b;
|
||||||
|
AP_Notify::flags.pre_arm_check = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AP_Arming_Blimp::arm(const AP_Arming::Method method, const bool do_arming_checks)
|
||||||
|
{
|
||||||
|
static bool in_arm_motors = false;
|
||||||
|
|
||||||
|
// exit immediately if already in this function
|
||||||
|
if (in_arm_motors) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
in_arm_motors = true;
|
||||||
|
|
||||||
|
// return true if already armed
|
||||||
|
if (blimp.motors->armed()) {
|
||||||
|
in_arm_motors = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!AP_Arming::arm(method, do_arming_checks)) {
|
||||||
|
AP_Notify::events.arming_failed = true;
|
||||||
|
in_arm_motors = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// let logger know that we're armed (it may open logs e.g.)
|
||||||
|
AP::logger().set_vehicle_armed(true);
|
||||||
|
|
||||||
|
// notify that arming will occur (we do this early to give plenty of warning)
|
||||||
|
AP_Notify::flags.armed = true;
|
||||||
|
// call notify update a few times to ensure the message gets out
|
||||||
|
for (uint8_t i=0; i<=10; i++) {
|
||||||
|
AP::notify().update();
|
||||||
|
}
|
||||||
|
|
||||||
|
gcs().send_text(MAV_SEVERITY_INFO, "Arming motors"); //MIR kept in - usually only in SITL
|
||||||
|
|
||||||
|
AP_AHRS_NavEKF &ahrs = AP::ahrs_navekf();
|
||||||
|
|
||||||
|
blimp.initial_armed_bearing = ahrs.yaw_sensor;
|
||||||
|
|
||||||
|
if (!ahrs.home_is_set()) {
|
||||||
|
// Reset EKF altitude if home hasn't been set yet (we use EKF altitude as substitute for alt above home)
|
||||||
|
ahrs.resetHeightDatum();
|
||||||
|
AP::logger().Write_Event(LogEvent::EKF_ALT_RESET);
|
||||||
|
|
||||||
|
// we have reset height, so arming height is zero
|
||||||
|
blimp.arming_altitude_m = 0;
|
||||||
|
} else if (!ahrs.home_is_locked()) {
|
||||||
|
// Reset home position if it has already been set before (but not locked)
|
||||||
|
if (!blimp.set_home_to_current_location(false)) {
|
||||||
|
// ignore failure
|
||||||
|
}
|
||||||
|
|
||||||
|
// remember the height when we armed
|
||||||
|
blimp.arming_altitude_m = blimp.inertial_nav.get_altitude() * 0.01;
|
||||||
|
}
|
||||||
|
|
||||||
|
// enable gps velocity based centrefugal force compensation
|
||||||
|
ahrs.set_correct_centrifugal(true);
|
||||||
|
hal.util->set_soft_armed(true);
|
||||||
|
|
||||||
|
// finally actually arm the motors
|
||||||
|
blimp.motors->armed(true);
|
||||||
|
|
||||||
|
// log flight mode in case it was changed while vehicle was disarmed
|
||||||
|
AP::logger().Write_Mode((uint8_t)blimp.control_mode, blimp.control_mode_reason);
|
||||||
|
|
||||||
|
// perf monitor ignores delay due to arming
|
||||||
|
AP::scheduler().perf_info.ignore_this_loop();
|
||||||
|
|
||||||
|
// flag exiting this function
|
||||||
|
in_arm_motors = false;
|
||||||
|
|
||||||
|
// Log time stamp of arming event
|
||||||
|
blimp.arm_time_ms = millis();
|
||||||
|
|
||||||
|
// Start the arming delay
|
||||||
|
blimp.ap.in_arming_delay = true;
|
||||||
|
|
||||||
|
// assumed armed without a arming, switch. Overridden in switches.cpp
|
||||||
|
blimp.ap.armed_with_switch = false;
|
||||||
|
|
||||||
|
// return success
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// arming.disarm - disarm motors
|
||||||
|
bool AP_Arming_Blimp::disarm(const AP_Arming::Method method, bool do_disarm_checks)
|
||||||
|
{
|
||||||
|
// return immediately if we are already disarmed
|
||||||
|
if (!blimp.motors->armed()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!AP_Arming::disarm(method, do_disarm_checks)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
gcs().send_text(MAV_SEVERITY_INFO, "Disarming motors"); //MIR keeping in - usually only in SITL
|
||||||
|
|
||||||
|
|
||||||
|
AP_AHRS_NavEKF &ahrs = AP::ahrs_navekf();
|
||||||
|
|
||||||
|
// save compass offsets learned by the EKF if enabled
|
||||||
|
Compass &compass = AP::compass();
|
||||||
|
if (ahrs.use_compass() && compass.get_learn_type() == Compass::LEARN_EKF) {
|
||||||
|
for (uint8_t i=0; i<COMPASS_MAX_INSTANCES; i++) {
|
||||||
|
Vector3f magOffsets;
|
||||||
|
if (ahrs.getMagOffsets(i, magOffsets)) {
|
||||||
|
compass.set_and_save_offsets(i, magOffsets);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// send disarm command to motors
|
||||||
|
blimp.motors->armed(false);
|
||||||
|
|
||||||
|
AP::logger().set_vehicle_armed(false);
|
||||||
|
|
||||||
|
// disable gps velocity based centrefugal force compensation
|
||||||
|
ahrs.set_correct_centrifugal(false);
|
||||||
|
hal.util->set_soft_armed(false);
|
||||||
|
|
||||||
|
blimp.ap.in_arming_delay = false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <AP_Arming/AP_Arming.h>
|
||||||
|
|
||||||
|
class AP_Arming_Blimp : public AP_Arming
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
friend class Blimp;
|
||||||
|
friend class ToyMode;
|
||||||
|
|
||||||
|
AP_Arming_Blimp() : AP_Arming()
|
||||||
|
{
|
||||||
|
// default REQUIRE parameter to 1 (Blimp does not have an
|
||||||
|
// actual ARMING_REQUIRE parameter)
|
||||||
|
require.set_default((uint8_t)Required::YES_MIN_PWM);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do not allow copies */
|
||||||
|
AP_Arming_Blimp(const AP_Arming_Blimp &other) = delete;
|
||||||
|
AP_Arming_Blimp &operator=(const AP_Arming_Blimp&) = delete;
|
||||||
|
|
||||||
|
void update(void);
|
||||||
|
|
||||||
|
bool rc_calibration_checks(bool display_failure) override;
|
||||||
|
|
||||||
|
bool disarm(AP_Arming::Method method, bool do_disarm_checks=true) override;
|
||||||
|
bool arm(AP_Arming::Method method, bool do_arming_checks=true) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
bool pre_arm_checks(bool display_failure) override;
|
||||||
|
bool pre_arm_ekf_attitude_check();
|
||||||
|
// bool proximity_checks(bool display_failure) const override;
|
||||||
|
bool arm_checks(AP_Arming::Method method) override;
|
||||||
|
|
||||||
|
// mandatory checks that cannot be bypassed. This function will only be called if ARMING_CHECK is zero or arming forced
|
||||||
|
bool mandatory_checks(bool display_failure) override;
|
||||||
|
|
||||||
|
// NOTE! the following check functions *DO* call into AP_Arming:
|
||||||
|
bool ins_checks(bool display_failure) override;
|
||||||
|
bool compass_checks(bool display_failure) override;
|
||||||
|
bool gps_checks(bool display_failure) override;
|
||||||
|
bool barometer_checks(bool display_failure) override;
|
||||||
|
bool board_voltage_checks(bool display_failure) override;
|
||||||
|
|
||||||
|
// NOTE! the following check functions *DO NOT* call into AP_Arming!
|
||||||
|
bool parameter_checks(bool display_failure);
|
||||||
|
bool motor_checks(bool display_failure);
|
||||||
|
bool pilot_throttle_checks(bool display_failure);
|
||||||
|
bool oa_checks(bool display_failure);
|
||||||
|
bool mandatory_gps_checks(bool display_failure);
|
||||||
|
bool gcs_failsafe_check(bool display_failure);
|
||||||
|
bool alt_checks(bool display_failure);
|
||||||
|
|
||||||
|
void set_pre_arm_check(bool b);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// actually contains the pre-arm checks. This is wrapped so that
|
||||||
|
// we can store away success/failure of the checks.
|
||||||
|
bool run_pre_arm_checks(bool display_failure);
|
||||||
|
|
||||||
|
};
|
|
@ -0,0 +1,51 @@
|
||||||
|
#include "Blimp.h"
|
||||||
|
|
||||||
|
// ---------------------------------------------
|
||||||
|
void Blimp::set_auto_armed(bool b)
|
||||||
|
{
|
||||||
|
// if no change, exit immediately
|
||||||
|
if ( ap.auto_armed == b ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ap.auto_armed = b;
|
||||||
|
if (b) {
|
||||||
|
AP::logger().Write_Event(LogEvent::AUTO_ARMED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------
|
||||||
|
void Blimp::set_failsafe_radio(bool b)
|
||||||
|
{
|
||||||
|
// only act on changes
|
||||||
|
// -------------------
|
||||||
|
if (failsafe.radio != b) {
|
||||||
|
|
||||||
|
// store the value so we don't trip the gate twice
|
||||||
|
// -----------------------------------------------
|
||||||
|
failsafe.radio = b;
|
||||||
|
|
||||||
|
if (failsafe.radio == false) {
|
||||||
|
// We've regained radio contact
|
||||||
|
// ----------------------------
|
||||||
|
failsafe_radio_off_event();
|
||||||
|
} else {
|
||||||
|
// We've lost radio contact
|
||||||
|
// ------------------------
|
||||||
|
failsafe_radio_on_event();
|
||||||
|
}
|
||||||
|
|
||||||
|
// update AP_Notify
|
||||||
|
AP_Notify::flags.failsafe_radio = b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------------------------
|
||||||
|
void Blimp::set_failsafe_gcs(bool b)
|
||||||
|
{
|
||||||
|
failsafe.gcs = b;
|
||||||
|
|
||||||
|
// update AP_Notify
|
||||||
|
AP_Notify::flags.failsafe_gcs = b;
|
||||||
|
}
|
|
@ -0,0 +1,391 @@
|
||||||
|
/*
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Blimp.h"
|
||||||
|
|
||||||
|
#define FORCE_VERSION_H_INCLUDE
|
||||||
|
#include "version.h"
|
||||||
|
#undef FORCE_VERSION_H_INCLUDE
|
||||||
|
|
||||||
|
const AP_HAL::HAL& hal = AP_HAL::get_HAL();
|
||||||
|
|
||||||
|
#define SCHED_TASK(func, rate_hz, max_time_micros) SCHED_TASK_CLASS(Blimp, &blimp, func, rate_hz, max_time_micros)
|
||||||
|
|
||||||
|
/*
|
||||||
|
scheduler table for fast CPUs - all regular tasks apart from the fast_loop()
|
||||||
|
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 Blimp::scheduler_tasks[] = {
|
||||||
|
SCHED_TASK(rc_loop, 100, 130),
|
||||||
|
SCHED_TASK(throttle_loop, 50, 75),
|
||||||
|
SCHED_TASK_CLASS(AP_GPS, &blimp.gps, update, 50, 200),
|
||||||
|
SCHED_TASK(update_batt_compass, 10, 120),
|
||||||
|
SCHED_TASK_CLASS(RC_Channels, (RC_Channels*)&blimp.g2.rc_channels, read_aux_all, 10, 50),
|
||||||
|
SCHED_TASK(arm_motors_check, 10, 50),
|
||||||
|
// SCHED_TASK(auto_disarm_check, 10, 50),
|
||||||
|
// SCHED_TASK(auto_trim, 10, 75),
|
||||||
|
SCHED_TASK(update_altitude, 10, 100),
|
||||||
|
// SCHED_TASK(run_nav_updates, 50, 100),
|
||||||
|
// SCHED_TASK(update_throttle_hover,100, 90),
|
||||||
|
SCHED_TASK(three_hz_loop, 3, 75),
|
||||||
|
SCHED_TASK_CLASS(AP_ServoRelayEvents, &blimp.ServoRelayEvents, update_events, 50, 75),
|
||||||
|
SCHED_TASK_CLASS(AP_Baro, &blimp.barometer, accumulate, 50, 90),
|
||||||
|
#if LOGGING_ENABLED == ENABLED
|
||||||
|
SCHED_TASK(fourhundred_hz_logging,400, 50),
|
||||||
|
#endif
|
||||||
|
SCHED_TASK_CLASS(AP_Notify, &blimp.notify, update, 50, 90),
|
||||||
|
SCHED_TASK(one_hz_loop, 1, 100),
|
||||||
|
SCHED_TASK(ekf_check, 10, 75),
|
||||||
|
SCHED_TASK(check_vibration, 10, 50),
|
||||||
|
// SCHED_TASK(gpsglitch_check, 10, 50),
|
||||||
|
// SCHED_TASK(landinggear_update, 10, 75),
|
||||||
|
// SCHED_TASK(standby_update, 100, 75),
|
||||||
|
// SCHED_TASK(lost_vehicle_check, 10, 50),
|
||||||
|
SCHED_TASK_CLASS(GCS, (GCS*)&blimp._gcs, update_receive, 400, 180),
|
||||||
|
SCHED_TASK_CLASS(GCS, (GCS*)&blimp._gcs, update_send, 400, 550),
|
||||||
|
#if LOGGING_ENABLED == ENABLED
|
||||||
|
SCHED_TASK(ten_hz_logging_loop, 10, 350),
|
||||||
|
SCHED_TASK(twentyfive_hz_logging, 25, 110),
|
||||||
|
SCHED_TASK_CLASS(AP_Logger, &blimp.logger, periodic_tasks, 400, 300),
|
||||||
|
#endif
|
||||||
|
SCHED_TASK_CLASS(AP_InertialSensor, &blimp.ins, periodic, 400, 50),
|
||||||
|
|
||||||
|
SCHED_TASK_CLASS(AP_Scheduler, &blimp.scheduler, update_logging, 0.1, 75),
|
||||||
|
SCHED_TASK(compass_cal_update, 100, 100),
|
||||||
|
SCHED_TASK(accel_cal_update, 10, 100),
|
||||||
|
// SCHED_TASK_CLASS(AP_TempCalibration, &blimp.g2.temp_calibration, update, 10, 100),
|
||||||
|
|
||||||
|
#if STATS_ENABLED == ENABLED
|
||||||
|
SCHED_TASK_CLASS(AP_Stats, &blimp.g2.stats, update, 1, 100),
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
void Blimp::get_scheduler_tasks(const AP_Scheduler::Task *&tasks,
|
||||||
|
uint8_t &task_count,
|
||||||
|
uint32_t &log_bit)
|
||||||
|
{
|
||||||
|
tasks = &scheduler_tasks[0];
|
||||||
|
task_count = ARRAY_SIZE(scheduler_tasks);
|
||||||
|
log_bit = MASK_LOG_PM;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr int8_t Blimp::_failsafe_priorities[4];
|
||||||
|
|
||||||
|
// Main loop - 50hz
|
||||||
|
void Blimp::fast_loop()
|
||||||
|
{
|
||||||
|
// update INS immediately to get current gyro data populated
|
||||||
|
ins.update();
|
||||||
|
|
||||||
|
// run low level rate controllers that only require IMU data
|
||||||
|
// attitude_control->rate_controller_run();
|
||||||
|
|
||||||
|
// send outputs to the motors library immediately
|
||||||
|
motors_output();
|
||||||
|
|
||||||
|
// run EKF state estimator (expensive)
|
||||||
|
// --------------------
|
||||||
|
read_AHRS();
|
||||||
|
|
||||||
|
// Inertial Nav
|
||||||
|
// --------------------
|
||||||
|
read_inertia();
|
||||||
|
|
||||||
|
// check if ekf has reset target heading or position
|
||||||
|
check_ekf_reset();
|
||||||
|
|
||||||
|
// run the attitude controllers
|
||||||
|
update_flight_mode();
|
||||||
|
|
||||||
|
// update home from EKF if necessary
|
||||||
|
update_home_from_EKF();
|
||||||
|
|
||||||
|
// check if we've landed or crashed
|
||||||
|
// Skip for now since Blimp won't land
|
||||||
|
// update_land_and_crash_detectors();
|
||||||
|
|
||||||
|
// log sensor health
|
||||||
|
if (should_log(MASK_LOG_ANY)) {
|
||||||
|
Log_Sensor_Health();
|
||||||
|
}
|
||||||
|
|
||||||
|
AP_Vehicle::fast_loop(); //just does gyro fft
|
||||||
|
}
|
||||||
|
|
||||||
|
// get_non_takeoff_throttle - a throttle somewhere between min and mid throttle which should not lead to a takeoff
|
||||||
|
//copied in from Copter's Attitude.cpp
|
||||||
|
float Blimp::get_non_takeoff_throttle()
|
||||||
|
{
|
||||||
|
// return MAX(0,motors->get_throttle_hover()/2.0f);
|
||||||
|
return 0.0f; //MIR no idle throttle.
|
||||||
|
}
|
||||||
|
|
||||||
|
// start takeoff to given altitude (for use by scripting)
|
||||||
|
// bool Blimp::start_takeoff(float alt)
|
||||||
|
// {
|
||||||
|
// // exit if vehicle is not in Guided mode or Auto-Guided mode
|
||||||
|
// if (!flightmode->in_guided_mode()) {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (mode_guided.do_user_takeoff_start(alt * 100.0f)) {
|
||||||
|
// blimp.set_auto_armed(true);
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// set target location (for use by scripting)
|
||||||
|
// bool Blimp::set_target_location(const Location& target_loc)
|
||||||
|
// {
|
||||||
|
// // exit if vehicle is not in Guided mode or Auto-Guided mode
|
||||||
|
// if (!flightmode->in_guided_mode()) {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return mode_guided.set_destination(target_loc);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// bool Blimp::set_target_velocity_NED(const Vector3f& vel_ned)
|
||||||
|
// {
|
||||||
|
// // exit if vehicle is not in Guided mode or Auto-Guided mode
|
||||||
|
// if (!flightmode->in_guided_mode()) {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // convert vector to neu in cm
|
||||||
|
// const Vector3f vel_neu_cms(vel_ned.x * 100.0f, vel_ned.y * 100.0f, -vel_ned.z * 100.0f);
|
||||||
|
// mode_guided.set_velocity(vel_neu_cms);
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// bool Blimp::set_target_angle_and_climbrate(float roll_deg, float pitch_deg, float yaw_deg, float climb_rate_ms, bool use_yaw_rate, float yaw_rate_degs)
|
||||||
|
// {
|
||||||
|
// // exit if vehicle is not in Guided mode or Auto-Guided mode
|
||||||
|
// if (!flightmode->in_guided_mode()) {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Quaternion q;
|
||||||
|
// q.from_euler(radians(roll_deg),radians(pitch_deg),radians(yaw_deg));
|
||||||
|
|
||||||
|
// mode_guided.set_angle(q, climb_rate_ms*100, use_yaw_rate, radians(yaw_rate_degs), false);
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// rc_loops - reads user input from transmitter/receiver
|
||||||
|
// called at 100hz
|
||||||
|
void Blimp::rc_loop()
|
||||||
|
{
|
||||||
|
// Read radio and 3-position switch on radio
|
||||||
|
// -----------------------------------------
|
||||||
|
read_radio();
|
||||||
|
rc().read_mode_switch();
|
||||||
|
}
|
||||||
|
|
||||||
|
// throttle_loop - should be run at 50 hz
|
||||||
|
// ---------------------------
|
||||||
|
void Blimp::throttle_loop()
|
||||||
|
{
|
||||||
|
// update throttle_low_comp value (controls priority of throttle vs attitude control)
|
||||||
|
// update_throttle_mix();
|
||||||
|
|
||||||
|
// check auto_armed status
|
||||||
|
update_auto_armed();
|
||||||
|
}
|
||||||
|
|
||||||
|
// update_batt_compass - read battery and compass
|
||||||
|
// should be called at 10hz
|
||||||
|
void Blimp::update_batt_compass(void)
|
||||||
|
{
|
||||||
|
// read battery before compass because it may be used for motor interference compensation
|
||||||
|
battery.read();
|
||||||
|
|
||||||
|
if (AP::compass().enabled()) {
|
||||||
|
// update compass with throttle value - used for compassmot
|
||||||
|
// compass.set_throttle(motors->get_throttle());
|
||||||
|
compass.set_voltage(battery.voltage());
|
||||||
|
compass.read();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Full rate logging of attitude, rate and pid loops
|
||||||
|
// should be run at 400hz
|
||||||
|
void Blimp::fourhundred_hz_logging()
|
||||||
|
{
|
||||||
|
if (should_log(MASK_LOG_ATTITUDE_FAST) && !blimp.flightmode->logs_attitude()) {
|
||||||
|
Log_Write_Attitude();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ten_hz_logging_loop
|
||||||
|
// should be run at 10hz
|
||||||
|
void Blimp::ten_hz_logging_loop()
|
||||||
|
{
|
||||||
|
// log attitude data if we're not already logging at the higher rate
|
||||||
|
if (should_log(MASK_LOG_ATTITUDE_MED) && !should_log(MASK_LOG_ATTITUDE_FAST) && !blimp.flightmode->logs_attitude()) {
|
||||||
|
Log_Write_Attitude();
|
||||||
|
}
|
||||||
|
// log EKF attitude data
|
||||||
|
if (should_log(MASK_LOG_ATTITUDE_MED) || should_log(MASK_LOG_ATTITUDE_FAST)) {
|
||||||
|
Log_Write_EKF_POS();
|
||||||
|
}
|
||||||
|
if (should_log(MASK_LOG_MOTBATT)) {
|
||||||
|
Log_Write_MotBatt();
|
||||||
|
}
|
||||||
|
if (should_log(MASK_LOG_RCIN)) {
|
||||||
|
logger.Write_RCIN();
|
||||||
|
if (rssi.enabled()) {
|
||||||
|
logger.Write_RSSI();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (should_log(MASK_LOG_RCOUT)) {
|
||||||
|
logger.Write_RCOUT();
|
||||||
|
}
|
||||||
|
if (should_log(MASK_LOG_IMU) || should_log(MASK_LOG_IMU_FAST) || should_log(MASK_LOG_IMU_RAW)) {
|
||||||
|
logger.Write_Vibration();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// twentyfive_hz_logging - should be run at 25hz
|
||||||
|
void Blimp::twentyfive_hz_logging()
|
||||||
|
{
|
||||||
|
#if HIL_MODE != HIL_MODE_DISABLED
|
||||||
|
// HIL for a blimp needs very fast update of the servo values
|
||||||
|
gcs().send_message(MSG_SERVO_OUTPUT_RAW);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if HIL_MODE == HIL_MODE_DISABLED
|
||||||
|
if (should_log(MASK_LOG_ATTITUDE_FAST)) {
|
||||||
|
Log_Write_EKF_POS();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (should_log(MASK_LOG_IMU)) {
|
||||||
|
logger.Write_IMU();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// three_hz_loop - 3.3hz loop
|
||||||
|
void Blimp::three_hz_loop()
|
||||||
|
{
|
||||||
|
// check if we've lost contact with the ground station
|
||||||
|
failsafe_gcs_check();
|
||||||
|
|
||||||
|
// check if we've lost terrain data
|
||||||
|
// failsafe_terrain_check();
|
||||||
|
}
|
||||||
|
|
||||||
|
// one_hz_loop - runs at 1Hz
|
||||||
|
void Blimp::one_hz_loop()
|
||||||
|
{
|
||||||
|
if (should_log(MASK_LOG_ANY)) {
|
||||||
|
Log_Write_Data(LogDataID::AP_STATE, ap.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
arming.update();
|
||||||
|
|
||||||
|
if (!motors->armed()) {
|
||||||
|
// make it possible to change ahrs orientation at runtime during initial config
|
||||||
|
ahrs.update_orientation();
|
||||||
|
|
||||||
|
// update_using_interlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
// update assigned functions and enable auxiliary servos
|
||||||
|
SRV_Channels::enable_aux_servos();
|
||||||
|
|
||||||
|
AP_Notify::flags.flying = !ap.land_complete;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Blimp::read_AHRS(void)
|
||||||
|
{
|
||||||
|
// Perform IMU calculations and get attitude info
|
||||||
|
//-----------------------------------------------
|
||||||
|
#if HIL_MODE != HIL_MODE_DISABLED
|
||||||
|
// update hil before ahrs update
|
||||||
|
gcs().update();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// we tell AHRS to skip INS update as we have already done it in fast_loop()
|
||||||
|
ahrs.update(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// read baro and log control tuning
|
||||||
|
void Blimp::update_altitude()
|
||||||
|
{
|
||||||
|
// read in baro altitude
|
||||||
|
read_barometer();
|
||||||
|
|
||||||
|
if (should_log(MASK_LOG_CTUN)) {
|
||||||
|
Log_Write_Control_Tuning();
|
||||||
|
#if HAL_GYROFFT_ENABLED
|
||||||
|
gyro_fft.write_log_messages();
|
||||||
|
#else
|
||||||
|
write_notch_log_messages();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vehicle specific waypoint info helpers
|
||||||
|
bool Blimp::get_wp_distance_m(float &distance) const
|
||||||
|
{
|
||||||
|
// see GCS_MAVLINK_Blimp::send_nav_controller_output()
|
||||||
|
distance = flightmode->wp_distance() * 0.01;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// vehicle specific waypoint info helpers
|
||||||
|
bool Blimp::get_wp_bearing_deg(float &bearing) const
|
||||||
|
{
|
||||||
|
// see GCS_MAVLINK_Blimp::send_nav_controller_output()
|
||||||
|
bearing = flightmode->wp_bearing() * 0.01;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// vehicle specific waypoint info helpers
|
||||||
|
bool Blimp::get_wp_crosstrack_error_m(float &xtrack_error) const
|
||||||
|
{
|
||||||
|
// see GCS_MAVLINK_Blimp::send_nav_controller_output()
|
||||||
|
xtrack_error = flightmode->crosstrack_error() * 0.01;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
constructor for main Blimp class
|
||||||
|
*/
|
||||||
|
Blimp::Blimp(void)
|
||||||
|
: logger(g.log_bitmask),
|
||||||
|
flight_modes(&g.flight_mode1),
|
||||||
|
control_mode(Mode::Number::MANUAL),
|
||||||
|
land_accel_ef_filter(LAND_DETECTOR_ACCEL_LPF_CUTOFF),
|
||||||
|
rc_throttle_control_in_filter(1.0f),
|
||||||
|
inertial_nav(ahrs),
|
||||||
|
param_loader(var_info),
|
||||||
|
flightmode(&mode_manual)
|
||||||
|
{
|
||||||
|
// init sensor error logging flags
|
||||||
|
sensor_health.baro = true;
|
||||||
|
sensor_health.compass = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Blimp blimp;
|
||||||
|
AP_Vehicle& vehicle = blimp;
|
||||||
|
|
||||||
|
AP_HAL_MAIN_CALLBACKS(&blimp);
|
|
@ -0,0 +1,544 @@
|
||||||
|
/*
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
/*
|
||||||
|
This is the main Blimp class
|
||||||
|
*/
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Header includes
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include <AP_HAL/AP_HAL.h>
|
||||||
|
|
||||||
|
// Common dependencies
|
||||||
|
#include <AP_Common/AP_Common.h>
|
||||||
|
#include <AP_Common/Location.h>
|
||||||
|
#include <AP_Param/AP_Param.h>
|
||||||
|
#include <StorageManager/StorageManager.h>
|
||||||
|
|
||||||
|
// Application dependencies
|
||||||
|
#include <GCS_MAVLink/GCS.h>
|
||||||
|
#include <AP_Logger/AP_Logger.h> // ArduPilot Mega Flash Memory Library
|
||||||
|
#include <AP_Math/AP_Math.h> // ArduPilot Mega Vector/Matrix math Library
|
||||||
|
// #include <AP_AccelCal/AP_AccelCal.h> // interface and maths for accelerometer calibration
|
||||||
|
// #include <AP_InertialSensor/AP_InertialSensor.h> // ArduPilot Mega Inertial Sensor (accel & gyro) Library
|
||||||
|
#include <AP_AHRS/AP_AHRS.h>
|
||||||
|
// #include <AP_Mission/AP_Mission.h> // Mission command library
|
||||||
|
// #include <AC_AttitudeControl/AC_AttitudeControl_Multi.h> // Attitude control library
|
||||||
|
// #include <AC_AttitudeControl/AC_AttitudeControl_Heli.h> // Attitude control library for traditional helicopter
|
||||||
|
// #include <AC_AttitudeControl/AC_PosControl.h> // Position control library
|
||||||
|
// #include <AP_Motors/AP_Motors.h> // AP Motors library
|
||||||
|
#include <AP_Stats/AP_Stats.h> // statistics library
|
||||||
|
#include <Filter/Filter.h> // Filter library
|
||||||
|
#include <AP_Airspeed/AP_Airspeed.h> // needed for AHRS build
|
||||||
|
#include <AP_Vehicle/AP_Vehicle.h> // needed for AHRS build
|
||||||
|
#include <AP_InertialNav/AP_InertialNav.h> // ArduPilot Mega inertial navigation library
|
||||||
|
// #include <AC_WPNav/AC_WPNav.h> // Blimp waypoint navigation library
|
||||||
|
// #include <AC_WPNav/AC_Loiter.h>
|
||||||
|
// #include <AC_WPNav/AC_Circle.h> // circle navigation library
|
||||||
|
// #include <AP_Declination/AP_Declination.h> // ArduPilot Mega Declination Helper Library
|
||||||
|
#include <AP_RCMapper/AP_RCMapper.h> // RC input mapping library
|
||||||
|
#include <AP_BattMonitor/AP_BattMonitor.h> // Battery monitor library
|
||||||
|
// #include <AP_LandingGear/AP_LandingGear.h> // Landing Gear library
|
||||||
|
// #include <AC_InputManager/AC_InputManager.h> // Pilot input handling library
|
||||||
|
// #include <AC_InputManager/AC_InputManager_Heli.h> // Heli specific pilot input handling library
|
||||||
|
#include <AP_Arming/AP_Arming.h>
|
||||||
|
// #include <AP_SmartRTL/AP_SmartRTL.h>
|
||||||
|
// #include <AP_TempCalibration/AP_TempCalibration.h>
|
||||||
|
// #include <AC_AutoTune/AC_AutoTune.h>
|
||||||
|
// #include <AP_Parachute/AP_Parachute.h>
|
||||||
|
// #include <AC_Sprayer/AC_Sprayer.h>
|
||||||
|
// #include <AP_ADSB/AP_ADSB.h>
|
||||||
|
#include <AP_Scripting/AP_Scripting.h>
|
||||||
|
|
||||||
|
// Configuration
|
||||||
|
#include "defines.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "Fins.h"
|
||||||
|
|
||||||
|
// #define MOTOR_CLASS Fins
|
||||||
|
|
||||||
|
#include "RC_Channel.h" // RC Channel Library
|
||||||
|
|
||||||
|
#include "GCS_Mavlink.h"
|
||||||
|
#include "GCS_Blimp.h"
|
||||||
|
// #include "AP_Rally.h" // Rally point library
|
||||||
|
#include "AP_Arming.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include <AP_Mount/AP_Mount.h>
|
||||||
|
|
||||||
|
// Local modules
|
||||||
|
|
||||||
|
#include "Parameters.h"
|
||||||
|
|
||||||
|
|
||||||
|
#if CONFIG_HAL_BOARD == HAL_BOARD_SITL
|
||||||
|
#include <SITL/SITL.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "mode.h"
|
||||||
|
|
||||||
|
class Blimp : public AP_Vehicle
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
friend class GCS_MAVLINK_Blimp;
|
||||||
|
friend class GCS_Blimp;
|
||||||
|
friend class Parameters;
|
||||||
|
friend class ParametersG2;
|
||||||
|
|
||||||
|
friend class AP_Arming_Blimp;
|
||||||
|
friend class RC_Channel_Blimp;
|
||||||
|
friend class RC_Channels_Blimp;
|
||||||
|
|
||||||
|
friend class Mode;
|
||||||
|
friend class ModeManual;
|
||||||
|
friend class ModeLand;
|
||||||
|
|
||||||
|
friend class Fins;
|
||||||
|
|
||||||
|
Blimp(void);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// key aircraft parameters passed to multiple libraries
|
||||||
|
AP_Vehicle::MultiCopter aparm;
|
||||||
|
|
||||||
|
// Global parameters are all contained within the 'g' class.
|
||||||
|
Parameters g;
|
||||||
|
ParametersG2 g2;
|
||||||
|
|
||||||
|
// used to detect MAVLink acks from GCS to stop compassmot
|
||||||
|
uint8_t command_ack_counter;
|
||||||
|
|
||||||
|
// primary input control channels
|
||||||
|
RC_Channel *channel_right;
|
||||||
|
RC_Channel *channel_front;
|
||||||
|
RC_Channel *channel_down;
|
||||||
|
RC_Channel *channel_yaw;
|
||||||
|
|
||||||
|
AP_Logger logger;
|
||||||
|
|
||||||
|
// flight modes convenience array
|
||||||
|
AP_Int8 *flight_modes;
|
||||||
|
const uint8_t num_flight_modes = 6;
|
||||||
|
|
||||||
|
|
||||||
|
#if CONFIG_HAL_BOARD == HAL_BOARD_SITL
|
||||||
|
SITL::SITL sitl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Arming/Disarming management class
|
||||||
|
AP_Arming_Blimp arming;
|
||||||
|
|
||||||
|
// system time in milliseconds of last recorded yaw reset from ekf
|
||||||
|
uint32_t ekfYawReset_ms;
|
||||||
|
int8_t ekf_primary_core;
|
||||||
|
|
||||||
|
// vibration check
|
||||||
|
struct {
|
||||||
|
bool high_vibes; // true while high vibration are detected
|
||||||
|
uint32_t start_ms; // system time high vibration were last detected
|
||||||
|
uint32_t clear_ms; // system time high vibrations stopped
|
||||||
|
} vibration_check;
|
||||||
|
|
||||||
|
// GCS selection
|
||||||
|
GCS_Blimp _gcs; // avoid using this; use gcs()
|
||||||
|
GCS_Blimp &gcs()
|
||||||
|
{
|
||||||
|
return _gcs;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Documentation of Globals:
|
||||||
|
typedef union {
|
||||||
|
struct {
|
||||||
|
uint8_t unused1 : 1; // 0
|
||||||
|
uint8_t pre_arm_rc_check : 1; // 3 // true if rc input pre-arm checks have been completed successfully
|
||||||
|
uint8_t pre_arm_check : 1; // 4 // true if all pre-arm checks (rc, accel calibration, gps lock) have been performed
|
||||||
|
uint8_t auto_armed : 1; // 5 // stops auto missions from beginning until throttle is raised
|
||||||
|
uint8_t logging_started : 1; // 6 // true if logging has started
|
||||||
|
uint8_t land_complete : 1; // 7 // true if we have detected a landing
|
||||||
|
uint8_t new_radio_frame : 1; // 8 // Set true if we have new PWM data to act on from the Radio
|
||||||
|
uint8_t usb_connected_unused : 1; // 9 // UNUSED
|
||||||
|
uint8_t rc_receiver_present : 1; // 10 // true if we have an rc receiver present (i.e. if we've ever received an update
|
||||||
|
uint8_t compass_mot : 1; // 11 // true if we are currently performing compassmot calibration
|
||||||
|
uint8_t motor_test : 1; // 12 // true if we are currently performing the motors test
|
||||||
|
uint8_t initialised : 1; // 13 // true once the init_ardupilot function has completed. Extended status to GCS is not sent until this completes
|
||||||
|
uint8_t land_complete_maybe : 1; // 14 // true if we may have landed (less strict version of land_complete)
|
||||||
|
uint8_t throttle_zero : 1; // 15 // true if the throttle stick is at zero, debounced, determines if pilot intends shut-down when not using motor interlock
|
||||||
|
uint8_t system_time_set_unused : 1; // 16 // true if the system time has been set from the GPS
|
||||||
|
uint8_t gps_glitching : 1; // 17 // true if GPS glitching is affecting navigation accuracy
|
||||||
|
uint8_t using_interlock : 1; // 20 // aux switch motor interlock function is in use
|
||||||
|
uint8_t land_repo_active : 1; // 21 // true if the pilot is overriding the landing position
|
||||||
|
uint8_t motor_interlock_switch : 1; // 22 // true if pilot is requesting motor interlock enable
|
||||||
|
uint8_t in_arming_delay : 1; // 23 // true while we are armed but waiting to spin motors
|
||||||
|
uint8_t initialised_params : 1; // 24 // true when the all parameters have been initialised. we cannot send parameters to the GCS until this is done
|
||||||
|
uint8_t unused3 : 1; // 25 // was compass_init_location; true when the compass's initial location has been set
|
||||||
|
uint8_t unused2 : 1; // 26 // aux switch rc_override is allowed
|
||||||
|
uint8_t armed_with_switch : 1; // 27 // we armed using a arming switch
|
||||||
|
};
|
||||||
|
uint32_t value;
|
||||||
|
} ap_t;
|
||||||
|
|
||||||
|
ap_t ap; //MIR Set of general variables
|
||||||
|
|
||||||
|
static_assert(sizeof(uint32_t) == sizeof(ap), "ap_t must be uint32_t");
|
||||||
|
|
||||||
|
// This is the state of the flight control system
|
||||||
|
// There are multiple states defined such as STABILIZE, ACRO,
|
||||||
|
Mode::Number control_mode;
|
||||||
|
ModeReason control_mode_reason = ModeReason::UNKNOWN;
|
||||||
|
Mode::Number prev_control_mode;
|
||||||
|
|
||||||
|
RCMapper rcmap;
|
||||||
|
|
||||||
|
// intertial nav alt when we armed
|
||||||
|
float arming_altitude_m;
|
||||||
|
|
||||||
|
// Failsafe
|
||||||
|
struct {
|
||||||
|
uint32_t last_heartbeat_ms; // the time when the last HEARTBEAT message arrived from a GCS - used for triggering gcs failsafe
|
||||||
|
|
||||||
|
int8_t radio_counter; // number of iterations with throttle below throttle_fs_value
|
||||||
|
|
||||||
|
uint8_t radio : 1; // A status flag for the radio failsafe
|
||||||
|
uint8_t gcs : 1; // A status flag for the ground station failsafe
|
||||||
|
uint8_t ekf : 1; // true if ekf failsafe has occurred
|
||||||
|
} failsafe;
|
||||||
|
|
||||||
|
bool any_failsafe_triggered() const
|
||||||
|
{
|
||||||
|
return failsafe.radio || battery.has_failsafed() || failsafe.gcs || failsafe.ekf;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sensor health for logging
|
||||||
|
struct {
|
||||||
|
uint8_t baro : 1; // true if baro is healthy
|
||||||
|
uint8_t compass : 1; // true if compass is healthy
|
||||||
|
uint8_t primary_gps : 2; // primary gps index
|
||||||
|
} sensor_health;
|
||||||
|
|
||||||
|
// Motor Output
|
||||||
|
Fins *motors;
|
||||||
|
|
||||||
|
int32_t _home_bearing;
|
||||||
|
uint32_t _home_distance;
|
||||||
|
|
||||||
|
// Stores initial bearing when armed - initial simple bearing is modified in super simple mode so not suitable
|
||||||
|
int32_t initial_armed_bearing;
|
||||||
|
|
||||||
|
// Battery Sensors
|
||||||
|
AP_BattMonitor battery{MASK_LOG_CURRENT,
|
||||||
|
FUNCTOR_BIND_MEMBER(&Blimp::handle_battery_failsafe, void, const char*, const int8_t),
|
||||||
|
_failsafe_priorities};
|
||||||
|
|
||||||
|
// Altitude
|
||||||
|
int32_t baro_alt; // barometer altitude in cm above home
|
||||||
|
LowPassFilterVector3f land_accel_ef_filter; // accelerations for land and crash detector tests
|
||||||
|
|
||||||
|
// filtered pilot's throttle input used to cancel landing if throttle held high
|
||||||
|
LowPassFilterFloat rc_throttle_control_in_filter;
|
||||||
|
|
||||||
|
// 3D Location vectors
|
||||||
|
// Current location of the vehicle (altitude is relative to home)
|
||||||
|
Location current_loc;
|
||||||
|
|
||||||
|
// Inertial Navigation
|
||||||
|
AP_InertialNav_NavEKF inertial_nav;
|
||||||
|
|
||||||
|
// Attitude, Position and Waypoint navigation objects
|
||||||
|
// To-Do: move inertial nav up or other navigation variables down here
|
||||||
|
// AC_AttitudeControl_t *attitude_control;
|
||||||
|
// AC_PosControl *pos_control;
|
||||||
|
// AC_WPNav *wp_nav;
|
||||||
|
// AC_Loiter *loiter_nav;
|
||||||
|
|
||||||
|
|
||||||
|
// System Timers
|
||||||
|
// --------------
|
||||||
|
// arm_time_ms - Records when vehicle was armed. Will be Zero if we are disarmed.
|
||||||
|
uint32_t arm_time_ms;
|
||||||
|
|
||||||
|
// Used to exit the roll and pitch auto trim function
|
||||||
|
uint8_t auto_trim_counter;
|
||||||
|
bool auto_trim_started = false;
|
||||||
|
|
||||||
|
|
||||||
|
// last valid RC input time
|
||||||
|
uint32_t last_radio_update_ms;
|
||||||
|
|
||||||
|
// Top-level logic
|
||||||
|
// setup the var_info table
|
||||||
|
AP_Param param_loader;
|
||||||
|
|
||||||
|
bool standby_active;
|
||||||
|
|
||||||
|
static const AP_Scheduler::Task scheduler_tasks[];
|
||||||
|
static const AP_Param::Info var_info[];
|
||||||
|
static const struct LogStructure log_structure[];
|
||||||
|
|
||||||
|
enum Failsafe_Action {
|
||||||
|
Failsafe_Action_None = 0,
|
||||||
|
Failsafe_Action_Land = 1,
|
||||||
|
Failsafe_Action_Terminate = 5
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class FailsafeOption {
|
||||||
|
RC_CONTINUE_IF_AUTO = (1<<0), // 1
|
||||||
|
GCS_CONTINUE_IF_AUTO = (1<<1), // 2
|
||||||
|
RC_CONTINUE_IF_GUIDED = (1<<2), // 4
|
||||||
|
CONTINUE_IF_LANDING = (1<<3), // 8
|
||||||
|
GCS_CONTINUE_IF_PILOT_CONTROL = (1<<4), // 16
|
||||||
|
RELEASE_GRIPPER = (1<<5), // 32
|
||||||
|
};
|
||||||
|
|
||||||
|
static constexpr int8_t _failsafe_priorities[] = {
|
||||||
|
Failsafe_Action_Terminate,
|
||||||
|
Failsafe_Action_Land,
|
||||||
|
Failsafe_Action_None,
|
||||||
|
-1 // the priority list must end with a sentinel of -1
|
||||||
|
};
|
||||||
|
|
||||||
|
#define FAILSAFE_LAND_PRIORITY 1
|
||||||
|
static_assert(_failsafe_priorities[FAILSAFE_LAND_PRIORITY] == Failsafe_Action_Land,
|
||||||
|
"FAILSAFE_LAND_PRIORITY must match the entry in _failsafe_priorities");
|
||||||
|
static_assert(_failsafe_priorities[ARRAY_SIZE(_failsafe_priorities) - 1] == -1,
|
||||||
|
"_failsafe_priorities is missing the sentinel");
|
||||||
|
|
||||||
|
// AP_State.cpp
|
||||||
|
void set_auto_armed(bool b);
|
||||||
|
void set_failsafe_radio(bool b);
|
||||||
|
void set_failsafe_gcs(bool b);
|
||||||
|
// void update_using_interlock();
|
||||||
|
|
||||||
|
// Blimp.cpp
|
||||||
|
void get_scheduler_tasks(const AP_Scheduler::Task *&tasks,
|
||||||
|
uint8_t &task_count,
|
||||||
|
uint32_t &log_bit) override;
|
||||||
|
void fast_loop() override;
|
||||||
|
// bool start_takeoff(float alt) override;
|
||||||
|
// bool set_target_location(const Location& target_loc) override;
|
||||||
|
// bool set_target_velocity_NED(const Vector3f& vel_ned) override;
|
||||||
|
// bool set_target_angle_and_climbrate(float roll_deg, float pitch_deg, float yaw_deg, float climb_rate_ms, bool use_yaw_rate, float yaw_rate_degs) override;
|
||||||
|
void rc_loop();
|
||||||
|
void throttle_loop();
|
||||||
|
void update_batt_compass(void);
|
||||||
|
void fourhundred_hz_logging();
|
||||||
|
void ten_hz_logging_loop();
|
||||||
|
void twentyfive_hz_logging();
|
||||||
|
void three_hz_loop();
|
||||||
|
void one_hz_loop();
|
||||||
|
void read_AHRS(void);
|
||||||
|
void update_altitude();
|
||||||
|
|
||||||
|
// Attitude.cpp
|
||||||
|
float get_pilot_desired_yaw_rate(int16_t stick_angle);
|
||||||
|
// void update_throttle_hover();
|
||||||
|
float get_pilot_desired_climb_rate(float throttle_control);
|
||||||
|
float get_non_takeoff_throttle();
|
||||||
|
// void set_accel_throttle_I_from_pilot_throttle();
|
||||||
|
void rotate_body_frame_to_NE(float &x, float &y);
|
||||||
|
uint16_t get_pilot_speed_dn();
|
||||||
|
|
||||||
|
// baro_ground_effect.cpp
|
||||||
|
// void update_ground_effect_detector(void);
|
||||||
|
// void update_ekf_terrain_height_stable();
|
||||||
|
|
||||||
|
// commands.cpp
|
||||||
|
void update_home_from_EKF();
|
||||||
|
void set_home_to_current_location_inflight();
|
||||||
|
bool set_home_to_current_location(bool lock) WARN_IF_UNUSED;
|
||||||
|
bool set_home(const Location& loc, bool lock) WARN_IF_UNUSED;
|
||||||
|
bool far_from_EKF_origin(const Location& loc);
|
||||||
|
|
||||||
|
// compassmot.cpp
|
||||||
|
// MAV_RESULT mavlink_compassmot(const GCS_MAVLINK &gcs_chan);
|
||||||
|
|
||||||
|
// // crash_check.cpp
|
||||||
|
// void crash_check();
|
||||||
|
// void thrust_loss_check();
|
||||||
|
// void parachute_check();
|
||||||
|
// void parachute_release();
|
||||||
|
// void parachute_manual_release();
|
||||||
|
|
||||||
|
// ekf_check.cpp
|
||||||
|
void ekf_check();
|
||||||
|
bool ekf_over_threshold();
|
||||||
|
void failsafe_ekf_event();
|
||||||
|
void failsafe_ekf_off_event(void);
|
||||||
|
void check_ekf_reset();
|
||||||
|
void check_vibration();
|
||||||
|
|
||||||
|
// events.cpp
|
||||||
|
bool failsafe_option(FailsafeOption opt) const;
|
||||||
|
void failsafe_radio_on_event();
|
||||||
|
void failsafe_radio_off_event();
|
||||||
|
void handle_battery_failsafe(const char* type_str, const int8_t action);
|
||||||
|
void failsafe_gcs_check();
|
||||||
|
// void failsafe_gcs_on_event(void); //MIR will probably need these two soon.
|
||||||
|
// void failsafe_gcs_off_event(void);
|
||||||
|
// void gpsglitch_check();
|
||||||
|
// void set_mode_RTL_or_land_with_pause(ModeReason reason);
|
||||||
|
bool should_disarm_on_failsafe();
|
||||||
|
void do_failsafe_action(Failsafe_Action action, ModeReason reason);
|
||||||
|
|
||||||
|
// failsafe.cpp
|
||||||
|
void failsafe_enable();
|
||||||
|
void failsafe_disable();
|
||||||
|
|
||||||
|
// fence.cpp
|
||||||
|
void fence_check();
|
||||||
|
|
||||||
|
// inertia.cpp
|
||||||
|
void read_inertia();
|
||||||
|
|
||||||
|
// landing_detector.cpp
|
||||||
|
void update_land_and_crash_detectors();
|
||||||
|
void update_land_detector();
|
||||||
|
void set_land_complete(bool b);
|
||||||
|
void set_land_complete_maybe(bool b);
|
||||||
|
// void update_throttle_mix();
|
||||||
|
|
||||||
|
// landing_gear.cpp
|
||||||
|
void landinggear_update();
|
||||||
|
|
||||||
|
// // standby.cpp
|
||||||
|
// void standby_update();
|
||||||
|
|
||||||
|
// Log.cpp
|
||||||
|
void Log_Write_Control_Tuning();
|
||||||
|
void Log_Write_Performance();
|
||||||
|
void Log_Write_Attitude();
|
||||||
|
void Log_Write_EKF_POS();
|
||||||
|
void Log_Write_MotBatt();
|
||||||
|
void Log_Write_Data(LogDataID id, int32_t value);
|
||||||
|
void Log_Write_Data(LogDataID id, uint32_t value);
|
||||||
|
void Log_Write_Data(LogDataID id, int16_t value);
|
||||||
|
void Log_Write_Data(LogDataID id, uint16_t value);
|
||||||
|
void Log_Write_Data(LogDataID id, float value);
|
||||||
|
void Log_Write_Parameter_Tuning(uint8_t param, float tuning_val, float tune_min, float tune_max);
|
||||||
|
void Log_Sensor_Health();
|
||||||
|
void Log_Write_Precland();
|
||||||
|
void Log_Write_GuidedTarget(uint8_t target_type, const Vector3f& pos_target, const Vector3f& vel_target);
|
||||||
|
void Log_Write_SysID_Setup(uint8_t systemID_axis, float waveform_magnitude, float frequency_start, float frequency_stop, float time_fade_in, float time_const_freq, float time_record, float time_fade_out);
|
||||||
|
void Log_Write_SysID_Data(float waveform_time, float waveform_sample, float waveform_freq, float angle_x, float angle_y, float angle_z, float accel_x, float accel_y, float accel_z);
|
||||||
|
void Log_Write_Vehicle_Startup_Messages();
|
||||||
|
void log_init(void);
|
||||||
|
|
||||||
|
// mode.cpp
|
||||||
|
bool set_mode(Mode::Number mode, ModeReason reason);
|
||||||
|
bool set_mode(const uint8_t new_mode, const ModeReason reason) override;
|
||||||
|
uint8_t get_mode() const override
|
||||||
|
{
|
||||||
|
return (uint8_t)control_mode;
|
||||||
|
}
|
||||||
|
void update_flight_mode();
|
||||||
|
void notify_flight_mode();
|
||||||
|
|
||||||
|
// mode_land.cpp
|
||||||
|
void set_mode_land_with_pause(ModeReason reason);
|
||||||
|
bool landing_with_GPS();
|
||||||
|
|
||||||
|
// // motors.cpp
|
||||||
|
void arm_motors_check();
|
||||||
|
// void auto_disarm_check();
|
||||||
|
void motors_output();
|
||||||
|
// void lost_vehicle_check();
|
||||||
|
|
||||||
|
// navigation.cpp
|
||||||
|
// void run_nav_updates(void);
|
||||||
|
// int32_t home_bearing();
|
||||||
|
// uint32_t home_distance();
|
||||||
|
|
||||||
|
// Parameters.cpp
|
||||||
|
void load_parameters(void) override;
|
||||||
|
void convert_pid_parameters(void);
|
||||||
|
void convert_lgr_parameters(void);
|
||||||
|
void convert_fs_options_params(void);
|
||||||
|
|
||||||
|
// radio.cpp
|
||||||
|
void default_dead_zones();
|
||||||
|
void init_rc_in();
|
||||||
|
void init_rc_out();
|
||||||
|
void enable_motor_output();
|
||||||
|
void read_radio();
|
||||||
|
void set_throttle_and_failsafe(uint16_t throttle_pwm);
|
||||||
|
void set_throttle_zero_flag(int16_t throttle_control);
|
||||||
|
// void radio_passthrough_to_motors();
|
||||||
|
int16_t get_throttle_mid(void);
|
||||||
|
|
||||||
|
// sensors.cpp
|
||||||
|
void read_barometer(void);
|
||||||
|
void init_rangefinder(void);
|
||||||
|
void read_rangefinder(void);
|
||||||
|
bool rangefinder_alt_ok();
|
||||||
|
bool rangefinder_up_ok();
|
||||||
|
void rpm_update();
|
||||||
|
void init_optflow();
|
||||||
|
void update_optical_flow(void);
|
||||||
|
void compass_cal_update(void);
|
||||||
|
void accel_cal_update(void);
|
||||||
|
void init_proximity();
|
||||||
|
void update_proximity();
|
||||||
|
|
||||||
|
// RC_Channel.cpp
|
||||||
|
void save_trim();
|
||||||
|
void auto_trim();
|
||||||
|
void auto_trim_cancel();
|
||||||
|
|
||||||
|
// system.cpp
|
||||||
|
void init_ardupilot() override;
|
||||||
|
void startup_INS_ground();
|
||||||
|
// void update_dynamic_notch() override;
|
||||||
|
bool position_ok() const;
|
||||||
|
bool ekf_has_absolute_position() const;
|
||||||
|
bool ekf_has_relative_position() const;
|
||||||
|
bool ekf_alt_ok() const;
|
||||||
|
void update_auto_armed();
|
||||||
|
bool should_log(uint32_t mask);
|
||||||
|
MAV_TYPE get_frame_mav_type();
|
||||||
|
const char* get_frame_string();
|
||||||
|
void allocate_motors(void);
|
||||||
|
|
||||||
|
// // tuning.cpp
|
||||||
|
// void tuning();
|
||||||
|
|
||||||
|
// vehicle specific waypoint info helpers
|
||||||
|
bool get_wp_distance_m(float &distance) const override;
|
||||||
|
bool get_wp_bearing_deg(float &bearing) const override;
|
||||||
|
bool get_wp_crosstrack_error_m(float &xtrack_error) const override;
|
||||||
|
|
||||||
|
Mode *flightmode;
|
||||||
|
ModeManual mode_manual;
|
||||||
|
ModeLand mode_land;
|
||||||
|
|
||||||
|
// mode.cpp
|
||||||
|
Mode *mode_from_mode_num(const Mode::Number mode);
|
||||||
|
void exit_mode(Mode *&old_flightmode, Mode *&new_flightmode);
|
||||||
|
|
||||||
|
public:
|
||||||
|
void failsafe_check(); // failsafe.cpp
|
||||||
|
};
|
||||||
|
|
||||||
|
extern Blimp blimp;
|
||||||
|
|
||||||
|
using AP_HAL::millis;
|
||||||
|
using AP_HAL::micros;
|
|
@ -0,0 +1,153 @@
|
||||||
|
#include "Blimp.h"
|
||||||
|
|
||||||
|
//most of these will become parameters...
|
||||||
|
//put here instead of Fins.h so that it can be changed without having to recompile the entire vehicle
|
||||||
|
|
||||||
|
#define FIN_SCALE_MAX 1000
|
||||||
|
|
||||||
|
/*
|
||||||
|
2nd group of parameters
|
||||||
|
*/
|
||||||
|
const AP_Param::GroupInfo Fins::var_info[] = {
|
||||||
|
|
||||||
|
// @Param: FREQ_HZ
|
||||||
|
// @DisplayName: Fins frequency
|
||||||
|
// @Description: This is the oscillation frequency of the fins
|
||||||
|
// @Range: 1 10
|
||||||
|
// @User: Standard
|
||||||
|
AP_GROUPINFO("FREQ_HZ", 1, Fins, freq_hz, 3),
|
||||||
|
|
||||||
|
// @Param: TURBO_MODE
|
||||||
|
// @DisplayName: Enable turbo mode
|
||||||
|
// @Description: Enables double speed on high offset.
|
||||||
|
// @Range: 0 1
|
||||||
|
// @User: Standard
|
||||||
|
AP_GROUPINFO("TURBO_MODE", 2, Fins, turbo_mode, 0),
|
||||||
|
|
||||||
|
AP_GROUPEND
|
||||||
|
};
|
||||||
|
|
||||||
|
//constructor
|
||||||
|
Fins::Fins(uint16_t loop_rate) :
|
||||||
|
_loop_rate(loop_rate)
|
||||||
|
{
|
||||||
|
AP_Param::setup_object_defaults(this, var_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Fins::setup_fins()
|
||||||
|
{
|
||||||
|
//amp r f d y,off r f d y right, front, down, yaw
|
||||||
|
add_fin(0, 0, -1, 0.5, 0, 0, 0, -0.5, 0); //Back(?)
|
||||||
|
add_fin(1, 0, 1, 0.5, 0, 0, 0, -0.5, 0); //Front(?)
|
||||||
|
add_fin(2, -1, 0, 0, 0.5, 0, 0, 0, 0.5); //Right
|
||||||
|
add_fin(3, 1, 0, 0, 0.5, 0, 0, 0, -0.5); //Left
|
||||||
|
|
||||||
|
SRV_Channels::set_angle(SRV_Channel::k_motor1, FIN_SCALE_MAX);
|
||||||
|
SRV_Channels::set_angle(SRV_Channel::k_motor2, FIN_SCALE_MAX);
|
||||||
|
SRV_Channels::set_angle(SRV_Channel::k_motor3, FIN_SCALE_MAX);
|
||||||
|
SRV_Channels::set_angle(SRV_Channel::k_motor4, FIN_SCALE_MAX);
|
||||||
|
|
||||||
|
GCS_SEND_TEXT(MAV_SEVERITY_WARNING, "MIR: All fins have been added.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Fins::add_fin(int8_t fin_num, float right_amp_fac, float front_amp_fac, float down_amp_fac, float yaw_amp_fac,
|
||||||
|
float right_off_fac, float front_off_fac, float down_off_fac, float yaw_off_fac)
|
||||||
|
{
|
||||||
|
|
||||||
|
// ensure valid fin number is provided
|
||||||
|
if (fin_num >= 0 && fin_num < NUM_FINS) {
|
||||||
|
|
||||||
|
// set amplitude factors
|
||||||
|
_right_amp_factor[fin_num] = right_amp_fac;
|
||||||
|
_front_amp_factor[fin_num] = front_amp_fac;
|
||||||
|
_down_amp_factor[fin_num] = down_amp_fac;
|
||||||
|
_yaw_amp_factor[fin_num] = yaw_amp_fac;
|
||||||
|
|
||||||
|
// set offset factors
|
||||||
|
_right_off_factor[fin_num] = right_off_fac;
|
||||||
|
_front_off_factor[fin_num] = front_off_fac;
|
||||||
|
_down_off_factor[fin_num] = down_off_fac;
|
||||||
|
_yaw_off_factor[fin_num] = yaw_off_fac;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//B,F,R,L = 0,1,2,3
|
||||||
|
void Fins::output()
|
||||||
|
{
|
||||||
|
if (!_armed) {
|
||||||
|
// set everything to zero so fins stop moving
|
||||||
|
right_out = 0;
|
||||||
|
front_out = 0;
|
||||||
|
down_out = 0;
|
||||||
|
yaw_out = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
right_out /= RC_SCALE;
|
||||||
|
front_out /= RC_SCALE;
|
||||||
|
down_out /= RC_SCALE;
|
||||||
|
yaw_out /= RC_SCALE;
|
||||||
|
|
||||||
|
_time = AP_HAL::micros() * 1.0e-6;
|
||||||
|
|
||||||
|
for (int8_t i=0; i<NUM_FINS; i++) {
|
||||||
|
_amp[i] = max(0,_right_amp_factor[i]*right_out) + max(0,_front_amp_factor[i]*front_out) +
|
||||||
|
fabsf(_down_amp_factor[i]*down_out) + fabsf(_yaw_amp_factor[i]*yaw_out);
|
||||||
|
_off[i] = _right_off_factor[i]*right_out + _front_off_factor[i]*front_out +
|
||||||
|
_down_off_factor[i]*down_out + _yaw_off_factor[i]*yaw_out;
|
||||||
|
_omm[i] = 1;
|
||||||
|
|
||||||
|
_num_added = 0;
|
||||||
|
if (max(0,_right_amp_factor[i]*right_out) > 0.0f) {
|
||||||
|
_num_added++;
|
||||||
|
}
|
||||||
|
if (max(0,_front_amp_factor[i]*front_out) > 0.0f) {
|
||||||
|
_num_added++;
|
||||||
|
}
|
||||||
|
if (fabsf(_down_amp_factor[i]*down_out) > 0.0f) {
|
||||||
|
_num_added++;
|
||||||
|
}
|
||||||
|
if (fabsf(_yaw_amp_factor[i]*yaw_out) > 0.0f) {
|
||||||
|
_num_added++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_num_added > 0) {
|
||||||
|
_off[i] = _off[i]/_num_added; //average the offsets
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((_amp[i]+fabsf(_off[i])) > 1) {
|
||||||
|
_amp[i] = 1 - fabsf(_off[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (turbo_mode) {
|
||||||
|
//double speed fins if offset at max... MIR
|
||||||
|
if (_amp[i] <= 0.6 && fabsf(_off[i]) >= 0.4) {
|
||||||
|
_omm[i] = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// finding and outputting current position for each servo from sine wave
|
||||||
|
_pos[i]= _amp[i]*cosf(freq_hz * _omm[i] * _time * 2 * M_PI) + _off[i]; //removed +MAX_AMP because output can do -ve numbers
|
||||||
|
SRV_Channels::set_output_scaled(SRV_Channels::get_motor_function(i), _pos[i] * FIN_SCALE_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
::printf("FINS (amp %.1f %.1f %.1f %.1f off %.1f %.1f %.1f %.1f omm %.1f %.1f %.1f %.1f)\n",
|
||||||
|
_amp[0], _amp[1], _amp[2], _amp[3], _off[0], _off[1], _off[2], _off[3], _omm[0], _omm[1], _omm[2], _omm[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Fins::output_min()
|
||||||
|
{
|
||||||
|
right_out = 0;
|
||||||
|
front_out = 0;
|
||||||
|
down_out = 0;
|
||||||
|
yaw_out = 0;
|
||||||
|
Fins::output();
|
||||||
|
}
|
||||||
|
|
||||||
|
// MIR - Probably want to completely get rid of the desired spool state thing.
|
||||||
|
void Fins::set_desired_spool_state(DesiredSpoolState spool)
|
||||||
|
{
|
||||||
|
if (_armed || (spool == DesiredSpoolState::SHUT_DOWN)) {
|
||||||
|
// Set DesiredSpoolState only if it is either armed or it wants to shut down.
|
||||||
|
_spool_desired = spool;
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,175 @@
|
||||||
|
//This class converts horizontal acceleration commands to fin flapping commands.
|
||||||
|
#pragma once
|
||||||
|
// #include <AP_Common/AP_Common.h>
|
||||||
|
// #include <AP_Math/AP_Math.h> // ArduPilot Mega Vector/Matrix math Library
|
||||||
|
#include <AP_Notify/AP_Notify.h> // Notify library
|
||||||
|
#include <SRV_Channel/SRV_Channel.h>
|
||||||
|
// #include <Filter/Filter.h> // filter library
|
||||||
|
// #include <AP_HAL/AP_HAL.h>
|
||||||
|
// #include <GCS_MAVLink/GCS.h>
|
||||||
|
|
||||||
|
extern const AP_HAL::HAL& hal;
|
||||||
|
|
||||||
|
// #define FINS_SPEED_DEFAULT 10 //MIR what is this?
|
||||||
|
#define NUM_FINS 4
|
||||||
|
#define RC_SCALE 1000
|
||||||
|
class Fins
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
friend class Blimp;
|
||||||
|
// Fins(void);
|
||||||
|
|
||||||
|
enum motor_frame_class {
|
||||||
|
MOTOR_FRAME_UNDEFINED = 0,
|
||||||
|
MOTOR_FRAME_AIRFISH = 1,
|
||||||
|
};
|
||||||
|
enum motor_frame_type {
|
||||||
|
MOTOR_FRAME_TYPE_AIRFISH = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
//constructor
|
||||||
|
Fins(uint16_t loop_rate);
|
||||||
|
|
||||||
|
// var_info for holding Parameter information
|
||||||
|
static const struct AP_Param::GroupInfo var_info[];
|
||||||
|
|
||||||
|
// singleton support
|
||||||
|
// static Fins *get_singleton(void) { return _singleton; }
|
||||||
|
|
||||||
|
// desired spool states
|
||||||
|
// from AP_Motors_Class.h
|
||||||
|
enum class DesiredSpoolState : uint8_t {
|
||||||
|
SHUT_DOWN = 0, // all motors should move to stop
|
||||||
|
// GROUND_IDLE = 1, // all motors should move to ground idle
|
||||||
|
THROTTLE_UNLIMITED = 2, // motors should move to being a state where throttle is unconstrained (e.g. by start up procedure)
|
||||||
|
};
|
||||||
|
|
||||||
|
// spool states
|
||||||
|
enum class SpoolState : uint8_t {
|
||||||
|
SHUT_DOWN = 0, // all motors stop
|
||||||
|
// GROUND_IDLE = 1, // all motors at ground idle
|
||||||
|
// SPOOLING_UP = 2, // increasing maximum throttle while stabilizing
|
||||||
|
THROTTLE_UNLIMITED = 3, // throttle is no longer constrained by start up procedure
|
||||||
|
// SPOOLING_DOWN = 4, // decreasing maximum throttle while stabilizing
|
||||||
|
};
|
||||||
|
|
||||||
|
bool initialised_ok() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void armed(bool arm)
|
||||||
|
{
|
||||||
|
if (arm != _armed) {
|
||||||
|
_armed = arm;
|
||||||
|
AP_Notify::flags.armed = arm;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
bool armed() const
|
||||||
|
{
|
||||||
|
return _armed;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// internal variables
|
||||||
|
const uint16_t _loop_rate; // rate in Hz at which output() function is called (normally 400hz)
|
||||||
|
uint16_t _speed_hz; // speed in hz to send updates to motors
|
||||||
|
// float _roll_in; // desired roll control from attitude controllers, -1 ~ +1
|
||||||
|
// float _roll_in_ff; // desired roll feed forward control from attitude controllers, -1 ~ +1
|
||||||
|
// float _pitch_in; // desired pitch control from attitude controller, -1 ~ +1
|
||||||
|
// float _pitch_in_ff; // desired pitch feed forward control from attitude controller, -1 ~ +1
|
||||||
|
// float _yaw_in; // desired yaw control from attitude controller, -1 ~ +1
|
||||||
|
// float _yaw_in_ff; // desired yaw feed forward control from attitude controller, -1 ~ +1
|
||||||
|
float _throttle_in; // last throttle input from set_throttle caller
|
||||||
|
float _down_out; // throttle after mixing is complete
|
||||||
|
// float _forward_in; // last forward input from set_forward caller
|
||||||
|
// float _lateral_in; // last lateral input from set_lateral caller
|
||||||
|
float _throttle_avg_max; // last throttle input from set_throttle_avg_max
|
||||||
|
// LowPassFilterFloat _throttle_filter; // throttle input filter
|
||||||
|
DesiredSpoolState _spool_desired; // desired spool state
|
||||||
|
SpoolState _spool_state; // current spool mode
|
||||||
|
|
||||||
|
float _air_density_ratio; //air density as a proportion of sea level density
|
||||||
|
|
||||||
|
float _time; //current timestep
|
||||||
|
|
||||||
|
bool _armed; // 0 if disarmed, 1 if armed
|
||||||
|
|
||||||
|
float _amp[NUM_FINS]; //amplitudes
|
||||||
|
float _off[NUM_FINS]; //offsets
|
||||||
|
float _omm[NUM_FINS]; //omega multiplier
|
||||||
|
float _pos[NUM_FINS]; //servo positions
|
||||||
|
|
||||||
|
float _right_amp_factor[NUM_FINS];
|
||||||
|
float _front_amp_factor[NUM_FINS];
|
||||||
|
float _down_amp_factor[NUM_FINS];
|
||||||
|
float _yaw_amp_factor[NUM_FINS];
|
||||||
|
|
||||||
|
float _right_off_factor[NUM_FINS];
|
||||||
|
float _front_off_factor[NUM_FINS];
|
||||||
|
float _down_off_factor[NUM_FINS];
|
||||||
|
float _yaw_off_factor[NUM_FINS];
|
||||||
|
|
||||||
|
int8_t _num_added;
|
||||||
|
// private:
|
||||||
|
public:
|
||||||
|
float right_out; //input right movement, negative for left, +1 to -1
|
||||||
|
float front_out; //input front/forwards movement, negative for backwards, +1 to -1
|
||||||
|
float yaw_out; //input yaw, +1 to -1
|
||||||
|
float down_out; //input height control, +1 to -1
|
||||||
|
|
||||||
|
AP_Float freq_hz;
|
||||||
|
AP_Int8 turbo_mode;
|
||||||
|
|
||||||
|
bool _interlock; // 1 if the motor interlock is enabled (i.e. motors run), 0 if disabled (motors don't run)
|
||||||
|
bool _initialised_ok; // 1 if initialisation was successful
|
||||||
|
|
||||||
|
// get_spool_state - get current spool state
|
||||||
|
enum SpoolState get_spool_state(void) const
|
||||||
|
{
|
||||||
|
return _spool_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
// float mapf(float x, float in_min, float in_max, float out_min, float out_max) {
|
||||||
|
// return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; }
|
||||||
|
|
||||||
|
float max(float one, float two)
|
||||||
|
{
|
||||||
|
if (one >= two) {
|
||||||
|
return one;
|
||||||
|
} else {
|
||||||
|
return two;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void output_min();
|
||||||
|
|
||||||
|
void add_fin(int8_t fin_num, float right_amp_fac, float front_amp_fac, float yaw_amp_fac, float down_amp_fac,
|
||||||
|
float right_off_fac, float front_off_fac, float yaw_off_fac, float down_off_fac);
|
||||||
|
|
||||||
|
void setup_fins();
|
||||||
|
|
||||||
|
float get_throttle_hover()
|
||||||
|
{
|
||||||
|
return 0; //MIR temp
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_desired_spool_state(DesiredSpoolState spool);
|
||||||
|
|
||||||
|
void output();
|
||||||
|
|
||||||
|
float get_throttle()
|
||||||
|
{
|
||||||
|
return 0.1f; //MIR temp
|
||||||
|
}
|
||||||
|
|
||||||
|
void rc_write(uint8_t chan, uint16_t pwm);
|
||||||
|
|
||||||
|
// set_density_ratio - sets air density as a proportion of sea level density
|
||||||
|
void set_air_density_ratio(float ratio)
|
||||||
|
{
|
||||||
|
_air_density_ratio = ratio;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
|
@ -0,0 +1,69 @@
|
||||||
|
#include "GCS_Blimp.h"
|
||||||
|
|
||||||
|
#include "Blimp.h"
|
||||||
|
|
||||||
|
uint8_t GCS_Blimp::sysid_this_mav() const
|
||||||
|
{
|
||||||
|
return blimp.g.sysid_this_mav;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* GCS_Blimp::frame_string() const
|
||||||
|
{
|
||||||
|
return blimp.get_frame_string();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GCS_Blimp::update_vehicle_sensor_status_flags(void)
|
||||||
|
{
|
||||||
|
control_sensors_present |=
|
||||||
|
MAV_SYS_STATUS_SENSOR_ANGULAR_RATE_CONTROL |
|
||||||
|
MAV_SYS_STATUS_SENSOR_ATTITUDE_STABILIZATION |
|
||||||
|
MAV_SYS_STATUS_SENSOR_YAW_POSITION;
|
||||||
|
|
||||||
|
control_sensors_enabled |=
|
||||||
|
MAV_SYS_STATUS_SENSOR_ANGULAR_RATE_CONTROL |
|
||||||
|
MAV_SYS_STATUS_SENSOR_ATTITUDE_STABILIZATION |
|
||||||
|
MAV_SYS_STATUS_SENSOR_YAW_POSITION;
|
||||||
|
|
||||||
|
control_sensors_health |=
|
||||||
|
MAV_SYS_STATUS_SENSOR_ANGULAR_RATE_CONTROL |
|
||||||
|
MAV_SYS_STATUS_SENSOR_ATTITUDE_STABILIZATION |
|
||||||
|
MAV_SYS_STATUS_SENSOR_YAW_POSITION;
|
||||||
|
|
||||||
|
const Blimp::ap_t &ap = blimp.ap;
|
||||||
|
|
||||||
|
if (ap.rc_receiver_present) {
|
||||||
|
control_sensors_present |= MAV_SYS_STATUS_SENSOR_RC_RECEIVER;
|
||||||
|
control_sensors_enabled |= MAV_SYS_STATUS_SENSOR_RC_RECEIVER;
|
||||||
|
}
|
||||||
|
|
||||||
|
control_sensors_present |= MAV_SYS_STATUS_SENSOR_Z_ALTITUDE_CONTROL;
|
||||||
|
control_sensors_present |= MAV_SYS_STATUS_SENSOR_XY_POSITION_CONTROL;
|
||||||
|
|
||||||
|
// switch (blimp.control_mode) {
|
||||||
|
// case Mode::Number::AUTO:
|
||||||
|
// case Mode::Number::AVOID_ADSB:
|
||||||
|
// case Mode::Number::GUIDED:
|
||||||
|
// case Mode::Number::LOITER:
|
||||||
|
// control_sensors_enabled |= MAV_SYS_STATUS_SENSOR_Z_ALTITUDE_CONTROL;
|
||||||
|
// control_sensors_health |= MAV_SYS_STATUS_SENSOR_Z_ALTITUDE_CONTROL;
|
||||||
|
// control_sensors_enabled |= MAV_SYS_STATUS_SENSOR_XY_POSITION_CONTROL;
|
||||||
|
// control_sensors_health |= MAV_SYS_STATUS_SENSOR_XY_POSITION_CONTROL;
|
||||||
|
// break;
|
||||||
|
// case Mode::Number::ALT_HOLD:
|
||||||
|
// case Mode::Number::GUIDED_NOGPS:
|
||||||
|
// case Mode::Number::SPORT:
|
||||||
|
// case Mode::Number::AUTOTUNE:
|
||||||
|
// case Mode::Number::FLOWHOLD:
|
||||||
|
// control_sensors_enabled |= MAV_SYS_STATUS_SENSOR_Z_ALTITUDE_CONTROL;
|
||||||
|
// control_sensors_health |= MAV_SYS_STATUS_SENSOR_Z_ALTITUDE_CONTROL;
|
||||||
|
// break;
|
||||||
|
// default:
|
||||||
|
// // stabilize, acro, drift, and flip have no automatic x,y or z control (i.e. all manual)
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (ap.rc_receiver_present && !blimp.failsafe.radio) {
|
||||||
|
control_sensors_health |= MAV_SYS_STATUS_SENSOR_RC_RECEIVER;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <GCS_MAVLink/GCS.h>
|
||||||
|
#include "GCS_Mavlink.h"
|
||||||
|
|
||||||
|
class GCS_Blimp : public GCS
|
||||||
|
{
|
||||||
|
friend class Blimp; // for access to _chan in parameter declarations
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// return GCS link at offset ofs
|
||||||
|
GCS_MAVLINK_Blimp *chan(const uint8_t ofs) override
|
||||||
|
{
|
||||||
|
if (ofs > _num_gcs) {
|
||||||
|
INTERNAL_ERROR(AP_InternalError::error_t::gcs_offset);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return (GCS_MAVLINK_Blimp *)_chan[ofs];
|
||||||
|
}
|
||||||
|
const GCS_MAVLINK_Blimp *chan(const uint8_t ofs) const override
|
||||||
|
{
|
||||||
|
if (ofs > _num_gcs) {
|
||||||
|
INTERNAL_ERROR(AP_InternalError::error_t::gcs_offset);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return (GCS_MAVLINK_Blimp *)_chan[ofs];
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_vehicle_sensor_status_flags(void) override;
|
||||||
|
|
||||||
|
uint32_t custom_mode() const override;
|
||||||
|
MAV_TYPE frame_type() const override;
|
||||||
|
|
||||||
|
const char* frame_string() const override;
|
||||||
|
|
||||||
|
bool vehicle_initialised() const override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
uint8_t sysid_this_mav() const override;
|
||||||
|
|
||||||
|
// minimum amount of time (in microseconds) that must remain in
|
||||||
|
// the main scheduler loop before we are allowed to send any
|
||||||
|
// mavlink messages. We want to prioritise the main flight
|
||||||
|
// control loop over communications
|
||||||
|
uint16_t min_loop_time_remaining_for_message_send_us() const override
|
||||||
|
{
|
||||||
|
return 250;
|
||||||
|
}
|
||||||
|
|
||||||
|
GCS_MAVLINK_Blimp *new_gcs_mavlink_backend(GCS_MAVLINK_Parameters ¶ms,
|
||||||
|
AP_HAL::UARTDriver &uart) override
|
||||||
|
{
|
||||||
|
return new GCS_MAVLINK_Blimp(params, uart);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
|
@ -0,0 +1,977 @@
|
||||||
|
#include "Blimp.h"
|
||||||
|
|
||||||
|
#include "GCS_Mavlink.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* !!NOTE!!
|
||||||
|
*
|
||||||
|
* the use of NOINLINE separate functions for each message type avoids
|
||||||
|
* a compiler bug in gcc that would cause it to use far more stack
|
||||||
|
* space than is needed. Without the NOINLINE we use the sum of the
|
||||||
|
* stack needed for each message type. Please be careful to follow the
|
||||||
|
* pattern below when adding any new messages
|
||||||
|
*/
|
||||||
|
|
||||||
|
MAV_TYPE GCS_Blimp::frame_type() const
|
||||||
|
{
|
||||||
|
return blimp.get_frame_mav_type();
|
||||||
|
}
|
||||||
|
|
||||||
|
MAV_MODE GCS_MAVLINK_Blimp::base_mode() const
|
||||||
|
{
|
||||||
|
uint8_t _base_mode = MAV_MODE_FLAG_STABILIZE_ENABLED;
|
||||||
|
// work out the base_mode. This value is not very useful
|
||||||
|
// for APM, but we calculate it as best we can so a generic
|
||||||
|
// MAVLink enabled ground station can work out something about
|
||||||
|
// what the MAV is up to. The actual bit values are highly
|
||||||
|
// ambiguous for most of the APM flight modes. In practice, you
|
||||||
|
// only get useful information from the custom_mode, which maps to
|
||||||
|
// the APM flight mode and has a well defined meaning in the
|
||||||
|
// ArduPlane documentation
|
||||||
|
|
||||||
|
// switch (blimp.control_mode) {
|
||||||
|
// case Mode::Number::AUTO:
|
||||||
|
// case Mode::Number::RTL:
|
||||||
|
// case Mode::Number::LOITER:
|
||||||
|
// case Mode::Number::AVOID_ADSB:
|
||||||
|
// case Mode::Number::FOLLOW:
|
||||||
|
// case Mode::Number::GUIDED:
|
||||||
|
// case Mode::Number::CIRCLE:
|
||||||
|
// case Mode::Number::POSHOLD:
|
||||||
|
// case Mode::Number::BRAKE:
|
||||||
|
// case Mode::Number::SMART_RTL:
|
||||||
|
// _base_mode |= MAV_MODE_FLAG_GUIDED_ENABLED;
|
||||||
|
// // note that MAV_MODE_FLAG_AUTO_ENABLED does not match what
|
||||||
|
// // APM does in any mode, as that is defined as "system finds its own goal
|
||||||
|
// // positions", which APM does not currently do
|
||||||
|
// break;
|
||||||
|
// default:
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// all modes except INITIALISING have some form of manual
|
||||||
|
// override if stick mixing is enabled
|
||||||
|
_base_mode |= MAV_MODE_FLAG_MANUAL_INPUT_ENABLED;
|
||||||
|
|
||||||
|
#if HIL_MODE != HIL_MODE_DISABLED
|
||||||
|
_base_mode |= MAV_MODE_FLAG_HIL_ENABLED;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// we are armed if we are not initialising
|
||||||
|
if (blimp.motors != nullptr && blimp.motors->armed()) {
|
||||||
|
_base_mode |= MAV_MODE_FLAG_SAFETY_ARMED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// indicate we have set a custom mode
|
||||||
|
_base_mode |= MAV_MODE_FLAG_CUSTOM_MODE_ENABLED;
|
||||||
|
|
||||||
|
return (MAV_MODE)_base_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t GCS_Blimp::custom_mode() const
|
||||||
|
{
|
||||||
|
return (uint32_t)blimp.control_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
MAV_STATE GCS_MAVLINK_Blimp::vehicle_system_status() const
|
||||||
|
{
|
||||||
|
// set system as critical if any failsafe have triggered
|
||||||
|
if (blimp.any_failsafe_triggered()) {
|
||||||
|
return MAV_STATE_CRITICAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (blimp.ap.land_complete) {
|
||||||
|
return MAV_STATE_STANDBY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MAV_STATE_ACTIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GCS_MAVLINK_Blimp::send_position_target_global_int()
|
||||||
|
{
|
||||||
|
Location target;
|
||||||
|
if (!blimp.flightmode->get_wp(target)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mavlink_msg_position_target_global_int_send(
|
||||||
|
chan,
|
||||||
|
AP_HAL::millis(), // time_boot_ms
|
||||||
|
MAV_FRAME_GLOBAL, // targets are always global altitude
|
||||||
|
0xFFF8, // ignore everything except the x/y/z components
|
||||||
|
target.lat, // latitude as 1e7
|
||||||
|
target.lng, // longitude as 1e7
|
||||||
|
target.alt * 0.01f, // altitude is sent as a float
|
||||||
|
0.0f, // vx
|
||||||
|
0.0f, // vy
|
||||||
|
0.0f, // vz
|
||||||
|
0.0f, // afx
|
||||||
|
0.0f, // afy
|
||||||
|
0.0f, // afz
|
||||||
|
0.0f, // yaw
|
||||||
|
0.0f); // yaw_rate
|
||||||
|
}
|
||||||
|
|
||||||
|
// void GCS_MAVLINK_Blimp::send_position_target_local_ned()
|
||||||
|
// {
|
||||||
|
// #if MODE_GUIDED_ENABLED == ENABLED
|
||||||
|
// if (!blimp.flightmode->in_guided_mode()) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const GuidedMode guided_mode = blimp.mode_guided.mode();
|
||||||
|
// Vector3f target_pos;
|
||||||
|
// Vector3f target_vel;
|
||||||
|
// uint16_t type_mask;
|
||||||
|
|
||||||
|
// if (guided_mode == Guided_WP) {
|
||||||
|
// type_mask = 0x0FF8; // ignore everything except position
|
||||||
|
// target_pos = blimp.wp_nav->get_wp_destination() * 0.01f; // convert to metres
|
||||||
|
// } else if (guided_mode == Guided_Velocity) {
|
||||||
|
// type_mask = 0x0FC7; // ignore everything except velocity
|
||||||
|
// target_vel = blimp.flightmode->get_desired_velocity() * 0.01f; // convert to m/s
|
||||||
|
// } else {
|
||||||
|
// type_mask = 0x0FC0; // ignore everything except position & velocity
|
||||||
|
// target_pos = blimp.wp_nav->get_wp_destination() * 0.01f;
|
||||||
|
// target_vel = blimp.flightmode->get_desired_velocity() * 0.01f;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// mavlink_msg_position_target_local_ned_send(
|
||||||
|
// chan,
|
||||||
|
// AP_HAL::millis(), // time boot ms
|
||||||
|
// MAV_FRAME_LOCAL_NED,
|
||||||
|
// type_mask,
|
||||||
|
// target_pos.x, // x in metres
|
||||||
|
// target_pos.y, // y in metres
|
||||||
|
// -target_pos.z, // z in metres NED frame
|
||||||
|
// target_vel.x, // vx in m/s
|
||||||
|
// target_vel.y, // vy in m/s
|
||||||
|
// -target_vel.z, // vz in m/s NED frame
|
||||||
|
// 0.0f, // afx
|
||||||
|
// 0.0f, // afy
|
||||||
|
// 0.0f, // afz
|
||||||
|
// 0.0f, // yaw
|
||||||
|
// 0.0f); // yaw_rate
|
||||||
|
// #endif
|
||||||
|
// }
|
||||||
|
|
||||||
|
void GCS_MAVLINK_Blimp::send_nav_controller_output() const
|
||||||
|
{
|
||||||
|
// if (!blimp.ap.initialised) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// const Vector3f &targets = blimp.attitude_control->get_att_target_euler_cd();
|
||||||
|
// const Mode *flightmode = blimp.flightmode;
|
||||||
|
// mavlink_msg_nav_controller_output_send(
|
||||||
|
// chan,
|
||||||
|
// targets.x * 1.0e-2f,
|
||||||
|
// targets.y * 1.0e-2f,
|
||||||
|
// targets.z * 1.0e-2f,
|
||||||
|
// flightmode->wp_bearing() * 1.0e-2f,
|
||||||
|
// MIN(flightmode->wp_distance() * 1.0e-2f, UINT16_MAX),
|
||||||
|
// blimp.pos_control->get_alt_error() * 1.0e-2f,
|
||||||
|
// 0,
|
||||||
|
// flightmode->crosstrack_error() * 1.0e-2f);
|
||||||
|
}
|
||||||
|
|
||||||
|
float GCS_MAVLINK_Blimp::vfr_hud_airspeed() const
|
||||||
|
{
|
||||||
|
Vector3f airspeed_vec_bf;
|
||||||
|
if (AP::ahrs().airspeed_vector_true(airspeed_vec_bf)) {
|
||||||
|
// we are running the EKF3 wind estimation code which can give
|
||||||
|
// us an airspeed estimate
|
||||||
|
return airspeed_vec_bf.length();
|
||||||
|
}
|
||||||
|
return AP::gps().ground_speed();
|
||||||
|
}
|
||||||
|
|
||||||
|
int16_t GCS_MAVLINK_Blimp::vfr_hud_throttle() const
|
||||||
|
{
|
||||||
|
if (blimp.motors == nullptr) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return (int16_t)(blimp.motors->get_throttle() * 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
send PID tuning message
|
||||||
|
*/
|
||||||
|
void GCS_MAVLINK_Blimp::send_pid_tuning()
|
||||||
|
{
|
||||||
|
static const PID_TUNING_AXIS axes[] = {
|
||||||
|
PID_TUNING_ROLL,
|
||||||
|
PID_TUNING_PITCH,
|
||||||
|
PID_TUNING_YAW,
|
||||||
|
PID_TUNING_ACCZ
|
||||||
|
};
|
||||||
|
for (uint8_t i=0; i<ARRAY_SIZE(axes); i++) {
|
||||||
|
if (!(blimp.g.gcs_pid_mask & (1<<(axes[i]-1)))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!HAVE_PAYLOAD_SPACE(chan, PID_TUNING)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const AP_Logger::PID_Info *pid_info = nullptr;
|
||||||
|
switch (axes[i]) { //MIR Temp
|
||||||
|
// case PID_TUNING_ROLL:
|
||||||
|
// pid_info = &blimp.attitude_control->get_rate_roll_pid().get_pid_info();
|
||||||
|
// break;
|
||||||
|
// case PID_TUNING_PITCH:
|
||||||
|
// pid_info = &blimp.attitude_control->get_rate_pitch_pid().get_pid_info();
|
||||||
|
// break;
|
||||||
|
// case PID_TUNING_YAW:
|
||||||
|
// pid_info = &blimp.attitude_control->get_rate_yaw_pid().get_pid_info();
|
||||||
|
// break;
|
||||||
|
// case PID_TUNING_ACCZ:
|
||||||
|
// pid_info = &blimp.pos_control->get_accel_z_pid().get_pid_info();
|
||||||
|
// break;
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (pid_info != nullptr) {
|
||||||
|
mavlink_msg_pid_tuning_send(chan,
|
||||||
|
axes[i],
|
||||||
|
pid_info->target,
|
||||||
|
pid_info->actual,
|
||||||
|
pid_info->FF,
|
||||||
|
pid_info->P,
|
||||||
|
pid_info->I,
|
||||||
|
pid_info->D);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t GCS_MAVLINK_Blimp::sysid_my_gcs() const
|
||||||
|
{
|
||||||
|
return blimp.g.sysid_my_gcs;
|
||||||
|
}
|
||||||
|
bool GCS_MAVLINK_Blimp::sysid_enforce() const
|
||||||
|
{
|
||||||
|
return blimp.g2.sysid_enforce;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t GCS_MAVLINK_Blimp::telem_delay() const
|
||||||
|
{
|
||||||
|
return (uint32_t)(blimp.g.telem_delay);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GCS_Blimp::vehicle_initialised() const
|
||||||
|
{
|
||||||
|
return blimp.ap.initialised;
|
||||||
|
}
|
||||||
|
|
||||||
|
// try to send a message, return false if it wasn't sent
|
||||||
|
bool GCS_MAVLINK_Blimp::try_send_message(enum ap_message id)
|
||||||
|
{
|
||||||
|
switch (id) {
|
||||||
|
|
||||||
|
case MSG_WIND:
|
||||||
|
CHECK_PAYLOAD_SIZE(WIND);
|
||||||
|
send_wind();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MSG_SERVO_OUT:
|
||||||
|
case MSG_AOA_SSA:
|
||||||
|
case MSG_LANDING:
|
||||||
|
case MSG_ADSB_VEHICLE:
|
||||||
|
// unused
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return GCS_MAVLINK::try_send_message(id);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const AP_Param::GroupInfo GCS_MAVLINK_Parameters::var_info[] = {
|
||||||
|
// @Param: RAW_SENS
|
||||||
|
// @DisplayName: Raw sensor stream rate
|
||||||
|
// @Description: Stream rate of RAW_IMU, SCALED_IMU2, SCALED_IMU3, SCALED_PRESSURE, SCALED_PRESSURE2, SCALED_PRESSURE3 and SENSOR_OFFSETS to ground station
|
||||||
|
// @Units: Hz
|
||||||
|
// @Range: 0 10
|
||||||
|
// @Increment: 1
|
||||||
|
// @User: Advanced
|
||||||
|
AP_GROUPINFO("RAW_SENS", 0, GCS_MAVLINK_Parameters, streamRates[0], 0),
|
||||||
|
|
||||||
|
// @Param: EXT_STAT
|
||||||
|
// @DisplayName: Extended status stream rate to ground station
|
||||||
|
// @Description: Stream rate of SYS_STATUS, POWER_STATUS, MEMINFO, CURRENT_WAYPOINT, GPS_RAW_INT, GPS_RTK (if available), GPS2_RAW (if available), GPS2_RTK (if available), NAV_CONTROLLER_OUTPUT, and FENCE_STATUS to ground station
|
||||||
|
// @Units: Hz
|
||||||
|
// @Range: 0 10
|
||||||
|
// @Increment: 1
|
||||||
|
// @User: Advanced
|
||||||
|
AP_GROUPINFO("EXT_STAT", 1, GCS_MAVLINK_Parameters, streamRates[1], 0),
|
||||||
|
|
||||||
|
// @Param: RC_CHAN
|
||||||
|
// @DisplayName: RC Channel stream rate to ground station
|
||||||
|
// @Description: Stream rate of SERVO_OUTPUT_RAW and RC_CHANNELS to ground station
|
||||||
|
// @Units: Hz
|
||||||
|
// @Range: 0 10
|
||||||
|
// @Increment: 1
|
||||||
|
// @User: Advanced
|
||||||
|
AP_GROUPINFO("RC_CHAN", 2, GCS_MAVLINK_Parameters, streamRates[2], 0),
|
||||||
|
|
||||||
|
// @Param: RAW_CTRL
|
||||||
|
// @DisplayName: Raw Control stream rate to ground station
|
||||||
|
// @Description: Stream rate of RC_CHANNELS_SCALED (HIL only) to ground station
|
||||||
|
// @Units: Hz
|
||||||
|
// @Range: 0 10
|
||||||
|
// @Increment: 1
|
||||||
|
// @User: Advanced
|
||||||
|
AP_GROUPINFO("RAW_CTRL", 3, GCS_MAVLINK_Parameters, streamRates[3], 0),
|
||||||
|
|
||||||
|
// @Param: POSITION
|
||||||
|
// @DisplayName: Position stream rate to ground station
|
||||||
|
// @Description: Stream rate of GLOBAL_POSITION_INT and LOCAL_POSITION_NED to ground station
|
||||||
|
// @Units: Hz
|
||||||
|
// @Range: 0 10
|
||||||
|
// @Increment: 1
|
||||||
|
// @User: Advanced
|
||||||
|
AP_GROUPINFO("POSITION", 4, GCS_MAVLINK_Parameters, streamRates[4], 0),
|
||||||
|
|
||||||
|
// @Param: EXTRA1
|
||||||
|
// @DisplayName: Extra data type 1 stream rate to ground station
|
||||||
|
// @Description: Stream rate of ATTITUDE, SIMSTATE (SITL only), AHRS2 and PID_TUNING to ground station
|
||||||
|
// @Units: Hz
|
||||||
|
// @Range: 0 10
|
||||||
|
// @Increment: 1
|
||||||
|
// @User: Advanced
|
||||||
|
AP_GROUPINFO("EXTRA1", 5, GCS_MAVLINK_Parameters, streamRates[5], 0),
|
||||||
|
|
||||||
|
// @Param: EXTRA2
|
||||||
|
// @DisplayName: Extra data type 2 stream rate to ground station
|
||||||
|
// @Description: Stream rate of VFR_HUD to ground station
|
||||||
|
// @Units: Hz
|
||||||
|
// @Range: 0 10
|
||||||
|
// @Increment: 1
|
||||||
|
// @User: Advanced
|
||||||
|
AP_GROUPINFO("EXTRA2", 6, GCS_MAVLINK_Parameters, streamRates[6], 0),
|
||||||
|
|
||||||
|
// @Param: EXTRA3
|
||||||
|
// @DisplayName: Extra data type 3 stream rate to ground station
|
||||||
|
// @Description: Stream rate of AHRS, HWSTATUS, SYSTEM_TIME, RANGEFINDER, DISTANCE_SENSOR, TERRAIN_REQUEST, BATTERY2, MOUNT_STATUS, OPTICAL_FLOW, GIMBAL_REPORT, MAG_CAL_REPORT, MAG_CAL_PROGRESS, EKF_STATUS_REPORT, VIBRATION and RPM to ground station
|
||||||
|
// @Units: Hz
|
||||||
|
// @Range: 0 10
|
||||||
|
// @Increment: 1
|
||||||
|
// @User: Advanced
|
||||||
|
AP_GROUPINFO("EXTRA3", 7, GCS_MAVLINK_Parameters, streamRates[7], 0),
|
||||||
|
|
||||||
|
// @Param: PARAMS
|
||||||
|
// @DisplayName: Parameter stream rate to ground station
|
||||||
|
// @Description: Stream rate of PARAM_VALUE to ground station
|
||||||
|
// @Units: Hz
|
||||||
|
// @Range: 0 10
|
||||||
|
// @Increment: 1
|
||||||
|
// @User: Advanced
|
||||||
|
AP_GROUPINFO("PARAMS", 8, GCS_MAVLINK_Parameters, streamRates[8], 0),
|
||||||
|
AP_GROUPEND
|
||||||
|
};
|
||||||
|
|
||||||
|
static const ap_message STREAM_RAW_SENSORS_msgs[] = {
|
||||||
|
MSG_RAW_IMU,
|
||||||
|
MSG_SCALED_IMU2,
|
||||||
|
MSG_SCALED_IMU3,
|
||||||
|
MSG_SCALED_PRESSURE,
|
||||||
|
MSG_SCALED_PRESSURE2,
|
||||||
|
MSG_SCALED_PRESSURE3,
|
||||||
|
MSG_SENSOR_OFFSETS
|
||||||
|
};
|
||||||
|
static const ap_message STREAM_EXTENDED_STATUS_msgs[] = {
|
||||||
|
MSG_SYS_STATUS,
|
||||||
|
MSG_POWER_STATUS,
|
||||||
|
MSG_MEMINFO,
|
||||||
|
MSG_CURRENT_WAYPOINT, // MISSION_CURRENT
|
||||||
|
MSG_GPS_RAW,
|
||||||
|
MSG_GPS_RTK,
|
||||||
|
MSG_GPS2_RAW,
|
||||||
|
MSG_GPS2_RTK,
|
||||||
|
MSG_NAV_CONTROLLER_OUTPUT,
|
||||||
|
MSG_FENCE_STATUS,
|
||||||
|
MSG_POSITION_TARGET_GLOBAL_INT,
|
||||||
|
};
|
||||||
|
static const ap_message STREAM_POSITION_msgs[] = {
|
||||||
|
MSG_LOCATION,
|
||||||
|
MSG_LOCAL_POSITION
|
||||||
|
};
|
||||||
|
static const ap_message STREAM_RC_CHANNELS_msgs[] = {
|
||||||
|
MSG_SERVO_OUTPUT_RAW,
|
||||||
|
MSG_RC_CHANNELS,
|
||||||
|
MSG_RC_CHANNELS_RAW, // only sent on a mavlink1 connection
|
||||||
|
};
|
||||||
|
static const ap_message STREAM_EXTRA1_msgs[] = {
|
||||||
|
MSG_ATTITUDE,
|
||||||
|
MSG_SIMSTATE,
|
||||||
|
MSG_AHRS2,
|
||||||
|
MSG_PID_TUNING // Up to four PID_TUNING messages are sent, depending on GCS_PID_MASK parameter
|
||||||
|
};
|
||||||
|
static const ap_message STREAM_EXTRA2_msgs[] = {
|
||||||
|
MSG_VFR_HUD
|
||||||
|
};
|
||||||
|
static const ap_message STREAM_EXTRA3_msgs[] = {
|
||||||
|
MSG_AHRS,
|
||||||
|
MSG_HWSTATUS,
|
||||||
|
MSG_SYSTEM_TIME,
|
||||||
|
MSG_WIND,
|
||||||
|
MSG_RANGEFINDER,
|
||||||
|
MSG_DISTANCE_SENSOR,
|
||||||
|
MSG_BATTERY2,
|
||||||
|
MSG_BATTERY_STATUS,
|
||||||
|
MSG_MOUNT_STATUS,
|
||||||
|
MSG_OPTICAL_FLOW,
|
||||||
|
MSG_GIMBAL_REPORT,
|
||||||
|
MSG_MAG_CAL_REPORT,
|
||||||
|
MSG_MAG_CAL_PROGRESS,
|
||||||
|
MSG_EKF_STATUS_REPORT,
|
||||||
|
MSG_VIBRATION,
|
||||||
|
MSG_RPM,
|
||||||
|
MSG_ESC_TELEMETRY,
|
||||||
|
MSG_GENERATOR_STATUS,
|
||||||
|
};
|
||||||
|
static const ap_message STREAM_PARAMS_msgs[] = {
|
||||||
|
MSG_NEXT_PARAM
|
||||||
|
};
|
||||||
|
static const ap_message STREAM_ADSB_msgs[] = {
|
||||||
|
MSG_ADSB_VEHICLE
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct GCS_MAVLINK::stream_entries GCS_MAVLINK::all_stream_entries[] = {
|
||||||
|
MAV_STREAM_ENTRY(STREAM_RAW_SENSORS),
|
||||||
|
MAV_STREAM_ENTRY(STREAM_EXTENDED_STATUS),
|
||||||
|
MAV_STREAM_ENTRY(STREAM_POSITION),
|
||||||
|
MAV_STREAM_ENTRY(STREAM_RC_CHANNELS),
|
||||||
|
MAV_STREAM_ENTRY(STREAM_EXTRA1),
|
||||||
|
MAV_STREAM_ENTRY(STREAM_EXTRA2),
|
||||||
|
MAV_STREAM_ENTRY(STREAM_EXTRA3),
|
||||||
|
MAV_STREAM_ENTRY(STREAM_ADSB),
|
||||||
|
MAV_STREAM_ENTRY(STREAM_PARAMS),
|
||||||
|
MAV_STREAM_TERMINATOR // must have this at end of stream_entries
|
||||||
|
};
|
||||||
|
|
||||||
|
bool GCS_MAVLINK_Blimp::handle_guided_request(AP_Mission::Mission_Command &cmd)
|
||||||
|
{
|
||||||
|
// #if MODE_AUTO_ENABLED == ENABLED
|
||||||
|
// // return blimp.mode_auto.do_guided(cmd);
|
||||||
|
// #else
|
||||||
|
return false;
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void GCS_MAVLINK_Blimp::handle_change_alt_request(AP_Mission::Mission_Command &cmd)
|
||||||
|
{
|
||||||
|
// add home alt if needed
|
||||||
|
if (cmd.content.location.relative_alt) {
|
||||||
|
cmd.content.location.alt += blimp.ahrs.get_home().alt;
|
||||||
|
}
|
||||||
|
|
||||||
|
// To-Do: update target altitude for loiter or waypoint controller depending upon nav mode
|
||||||
|
}
|
||||||
|
|
||||||
|
void GCS_MAVLINK_Blimp::packetReceived(const mavlink_status_t &status,
|
||||||
|
const mavlink_message_t &msg)
|
||||||
|
{
|
||||||
|
GCS_MAVLINK::packetReceived(status, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GCS_MAVLINK_Blimp::params_ready() const
|
||||||
|
{
|
||||||
|
if (AP_BoardConfig::in_config_error()) {
|
||||||
|
// we may never have parameters "initialised" in this case
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// if we have not yet initialised (including allocating the motors
|
||||||
|
// object) we drop this request. That prevents the GCS from getting
|
||||||
|
// a confusing parameter count during bootup
|
||||||
|
return blimp.ap.initialised_params;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GCS_MAVLINK_Blimp::send_banner()
|
||||||
|
{
|
||||||
|
GCS_MAVLINK::send_banner();
|
||||||
|
send_text(MAV_SEVERITY_INFO, "Frame: %s", blimp.get_frame_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
// a RC override message is considered to be a 'heartbeat' from the ground station for failsafe purposes
|
||||||
|
void GCS_MAVLINK_Blimp::handle_rc_channels_override(const mavlink_message_t &msg)
|
||||||
|
{
|
||||||
|
blimp.failsafe.last_heartbeat_ms = AP_HAL::millis();
|
||||||
|
GCS_MAVLINK::handle_rc_channels_override(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GCS_MAVLINK_Blimp::handle_command_ack(const mavlink_message_t &msg)
|
||||||
|
{
|
||||||
|
blimp.command_ack_counter++;
|
||||||
|
GCS_MAVLINK::handle_command_ack(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
MAV_RESULT GCS_MAVLINK_Blimp::_handle_command_preflight_calibration(const mavlink_command_long_t &packet)
|
||||||
|
{
|
||||||
|
return GCS_MAVLINK::_handle_command_preflight_calibration(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
MAV_RESULT GCS_MAVLINK_Blimp::handle_command_do_set_roi(const Location &roi_loc)
|
||||||
|
{
|
||||||
|
if (!roi_loc.check_latlng()) {
|
||||||
|
return MAV_RESULT_FAILED;
|
||||||
|
}
|
||||||
|
// blimp.flightmode->auto_yaw.set_roi(roi_loc);
|
||||||
|
return MAV_RESULT_ACCEPTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
MAV_RESULT GCS_MAVLINK_Blimp::handle_preflight_reboot(const mavlink_command_long_t &packet)
|
||||||
|
{
|
||||||
|
// call parent
|
||||||
|
return GCS_MAVLINK::handle_preflight_reboot(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GCS_MAVLINK_Blimp::set_home_to_current_location(bool _lock)
|
||||||
|
{
|
||||||
|
return blimp.set_home_to_current_location(_lock);
|
||||||
|
}
|
||||||
|
bool GCS_MAVLINK_Blimp::set_home(const Location& loc, bool _lock)
|
||||||
|
{
|
||||||
|
return blimp.set_home(loc, _lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
MAV_RESULT GCS_MAVLINK_Blimp::handle_command_int_do_reposition(const mavlink_command_int_t &packet)
|
||||||
|
{
|
||||||
|
const bool change_modes = ((int32_t)packet.param2 & MAV_DO_REPOSITION_FLAGS_CHANGE_MODE) == MAV_DO_REPOSITION_FLAGS_CHANGE_MODE;
|
||||||
|
if (!blimp.flightmode->in_guided_mode() && !change_modes) {
|
||||||
|
return MAV_RESULT_DENIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sanity check location
|
||||||
|
if (!check_latlng(packet.x, packet.y)) {
|
||||||
|
return MAV_RESULT_DENIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
Location request_location {};
|
||||||
|
request_location.lat = packet.x;
|
||||||
|
request_location.lng = packet.y;
|
||||||
|
|
||||||
|
if (fabsf(packet.z) > LOCATION_ALT_MAX_M) {
|
||||||
|
return MAV_RESULT_DENIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
Location::AltFrame frame;
|
||||||
|
if (!mavlink_coordinate_frame_to_location_alt_frame((MAV_FRAME)packet.frame, frame)) {
|
||||||
|
return MAV_RESULT_DENIED; // failed as the location is not valid
|
||||||
|
}
|
||||||
|
request_location.set_alt_cm((int32_t)(packet.z * 100.0f), frame);
|
||||||
|
|
||||||
|
if (request_location.sanitize(blimp.current_loc)) {
|
||||||
|
// if the location wasn't already sane don't load it
|
||||||
|
return MAV_RESULT_DENIED; // failed as the location is not valid
|
||||||
|
}
|
||||||
|
|
||||||
|
return MAV_RESULT_ACCEPTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
MAV_RESULT GCS_MAVLINK_Blimp::handle_command_int_packet(const mavlink_command_int_t &packet)
|
||||||
|
{
|
||||||
|
switch (packet.command) {
|
||||||
|
case MAV_CMD_DO_FOLLOW:
|
||||||
|
return MAV_RESULT_UNSUPPORTED;
|
||||||
|
|
||||||
|
case MAV_CMD_DO_REPOSITION:
|
||||||
|
return handle_command_int_do_reposition(packet);
|
||||||
|
default:
|
||||||
|
return GCS_MAVLINK::handle_command_int_packet(packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MAV_RESULT GCS_MAVLINK_Blimp::handle_command_mount(const mavlink_command_long_t &packet)
|
||||||
|
{
|
||||||
|
// if the mount doesn't do pan control then yaw the entire vehicle instead:
|
||||||
|
switch (packet.command) {
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return GCS_MAVLINK::handle_command_mount(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
MAV_RESULT GCS_MAVLINK_Blimp::handle_command_long_packet(const mavlink_command_long_t &packet)
|
||||||
|
{
|
||||||
|
switch (packet.command) {
|
||||||
|
|
||||||
|
case MAV_CMD_NAV_TAKEOFF: {
|
||||||
|
// param3 : horizontal navigation by pilot acceptable
|
||||||
|
// param4 : yaw angle (not supported)
|
||||||
|
// param5 : latitude (not supported)
|
||||||
|
// param6 : longitude (not supported)
|
||||||
|
// param7 : altitude [metres]
|
||||||
|
|
||||||
|
// float takeoff_alt = packet.param7 * 100; // Convert m to cm
|
||||||
|
|
||||||
|
// if (!blimp.flightmode->do_user_takeoff(takeoff_alt, is_zero(packet.param3))) {
|
||||||
|
// return MAV_RESULT_FAILED;
|
||||||
|
//MIR Do I need this?
|
||||||
|
// }
|
||||||
|
return MAV_RESULT_ACCEPTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// #if MODE_AUTO_ENABLED == ENABLED
|
||||||
|
// case MAV_CMD_DO_LAND_START:
|
||||||
|
// if (blimp.mode_auto.mission.jump_to_landing_sequence() && blimp.set_mode(Mode::Number::AUTO, ModeReason::GCS_COMMAND)) {
|
||||||
|
// return MAV_RESULT_ACCEPTED;
|
||||||
|
// }
|
||||||
|
// return MAV_RESULT_FAILED;
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// case MAV_CMD_NAV_LOITER_UNLIM:
|
||||||
|
// if (!blimp.set_mode(Mode::Number::LOITER, ModeReason::GCS_COMMAND)) {
|
||||||
|
// return MAV_RESULT_FAILED;
|
||||||
|
// }
|
||||||
|
// return MAV_RESULT_ACCEPTED;
|
||||||
|
|
||||||
|
// case MAV_CMD_NAV_RETURN_TO_LAUNCH:
|
||||||
|
// if (!blimp.set_mode(Mode::Number::RTL, ModeReason::GCS_COMMAND)) {
|
||||||
|
// return MAV_RESULT_FAILED;
|
||||||
|
// }
|
||||||
|
// return MAV_RESULT_ACCEPTED;
|
||||||
|
|
||||||
|
|
||||||
|
case MAV_CMD_CONDITION_YAW:
|
||||||
|
// param1 : target angle [0-360]
|
||||||
|
// param2 : speed during change [deg per second]
|
||||||
|
// param3 : direction (-1:ccw, +1:cw)
|
||||||
|
// param4 : relative offset (1) or absolute angle (0)
|
||||||
|
if ((packet.param1 >= 0.0f) &&
|
||||||
|
(packet.param1 <= 360.0f) &&
|
||||||
|
(is_zero(packet.param4) || is_equal(packet.param4,1.0f))) {
|
||||||
|
// blimp.flightmode->auto_yaw.set_fixed_yaw(
|
||||||
|
// packet.param1,
|
||||||
|
// packet.param2,
|
||||||
|
// (int8_t)packet.param3,
|
||||||
|
// is_positive(packet.param4));
|
||||||
|
return MAV_RESULT_ACCEPTED;
|
||||||
|
}
|
||||||
|
return MAV_RESULT_FAILED;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return GCS_MAVLINK::handle_command_long_packet(packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GCS_MAVLINK_Blimp::handleMessage(const mavlink_message_t &msg)
|
||||||
|
{
|
||||||
|
switch (msg.msgid) {
|
||||||
|
|
||||||
|
case MAVLINK_MSG_ID_HEARTBEAT: { // MAV ID: 0
|
||||||
|
// We keep track of the last time we received a heartbeat from our GCS for failsafe purposes
|
||||||
|
if (msg.sysid != blimp.g.sysid_my_gcs) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
blimp.failsafe.last_heartbeat_ms = AP_HAL::millis();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// #if MODE_GUIDED_ENABLED == ENABLED
|
||||||
|
// case MAVLINK_MSG_ID_SET_ATTITUDE_TARGET: // MAV ID: 82
|
||||||
|
// {
|
||||||
|
// // decode packet
|
||||||
|
// mavlink_set_attitude_target_t packet;
|
||||||
|
// mavlink_msg_set_attitude_target_decode(&msg, &packet);
|
||||||
|
|
||||||
|
// // exit if vehicle is not in Guided mode or Auto-Guided mode
|
||||||
|
// if (!blimp.flightmode->in_guided_mode()) {
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // ensure type_mask specifies to use attitude and thrust
|
||||||
|
// if ((packet.type_mask & ((1<<7)|(1<<6))) != 0) {
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // check if the message's thrust field should be interpreted as a climb rate or as thrust
|
||||||
|
// const bool use_thrust = blimp.g2.dev_options.get() & DevOptionSetAttitudeTarget_ThrustAsThrust;
|
||||||
|
|
||||||
|
// float climb_rate_or_thrust;
|
||||||
|
// if (use_thrust) {
|
||||||
|
// // interpret thrust as thrust
|
||||||
|
// climb_rate_or_thrust = constrain_float(packet.thrust, -1.0f, 1.0f);
|
||||||
|
// } else {
|
||||||
|
// // convert thrust to climb rate
|
||||||
|
// packet.thrust = constrain_float(packet.thrust, 0.0f, 1.0f);
|
||||||
|
// if (is_equal(packet.thrust, 0.5f)) {
|
||||||
|
// climb_rate_or_thrust = 0.0f;
|
||||||
|
// } else if (packet.thrust > 0.5f) {
|
||||||
|
// // climb at up to WPNAV_SPEED_UP
|
||||||
|
// climb_rate_or_thrust = (packet.thrust - 0.5f) * 2.0f * blimp.wp_nav->get_default_speed_up();
|
||||||
|
// } else {
|
||||||
|
// // descend at up to WPNAV_SPEED_DN
|
||||||
|
// climb_rate_or_thrust = (0.5f - packet.thrust) * 2.0f * -fabsf(blimp.wp_nav->get_default_speed_down());
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // if the body_yaw_rate field is ignored, use the commanded yaw position
|
||||||
|
// // otherwise use the commanded yaw rate
|
||||||
|
// bool use_yaw_rate = false;
|
||||||
|
// if ((packet.type_mask & (1<<2)) == 0) {
|
||||||
|
// use_yaw_rate = true;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// blimp.mode_guided.set_angle(Quaternion(packet.q[0],packet.q[1],packet.q[2],packet.q[3]),
|
||||||
|
// climb_rate_or_thrust, use_yaw_rate, packet.body_yaw_rate, use_thrust);
|
||||||
|
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// case MAVLINK_MSG_ID_SET_POSITION_TARGET_LOCAL_NED: // MAV ID: 84
|
||||||
|
// {
|
||||||
|
// // decode packet
|
||||||
|
// mavlink_set_position_target_local_ned_t packet;
|
||||||
|
// mavlink_msg_set_position_target_local_ned_decode(&msg, &packet);
|
||||||
|
|
||||||
|
// // exit if vehicle is not in Guided mode or Auto-Guided mode
|
||||||
|
// if (!blimp.flightmode->in_guided_mode()) {
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // check for supported coordinate frames
|
||||||
|
// if (packet.coordinate_frame != MAV_FRAME_LOCAL_NED &&
|
||||||
|
// packet.coordinate_frame != MAV_FRAME_LOCAL_OFFSET_NED &&
|
||||||
|
// packet.coordinate_frame != MAV_FRAME_BODY_NED &&
|
||||||
|
// packet.coordinate_frame != MAV_FRAME_BODY_OFFSET_NED) {
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// bool pos_ignore = packet.type_mask & MAVLINK_SET_POS_TYPE_MASK_POS_IGNORE;
|
||||||
|
// bool vel_ignore = packet.type_mask & MAVLINK_SET_POS_TYPE_MASK_VEL_IGNORE;
|
||||||
|
// bool acc_ignore = packet.type_mask & MAVLINK_SET_POS_TYPE_MASK_ACC_IGNORE;
|
||||||
|
// bool yaw_ignore = packet.type_mask & MAVLINK_SET_POS_TYPE_MASK_YAW_IGNORE;
|
||||||
|
// bool yaw_rate_ignore = packet.type_mask & MAVLINK_SET_POS_TYPE_MASK_YAW_RATE_IGNORE;
|
||||||
|
|
||||||
|
// // exit immediately if acceleration provided
|
||||||
|
// if (!acc_ignore) {
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // prepare position
|
||||||
|
// Vector3f pos_vector;
|
||||||
|
// if (!pos_ignore) {
|
||||||
|
// // convert to cm
|
||||||
|
// pos_vector = Vector3f(packet.x * 100.0f, packet.y * 100.0f, -packet.z * 100.0f);
|
||||||
|
// // rotate to body-frame if necessary
|
||||||
|
// if (packet.coordinate_frame == MAV_FRAME_BODY_NED ||
|
||||||
|
// packet.coordinate_frame == MAV_FRAME_BODY_OFFSET_NED) {
|
||||||
|
// blimp.rotate_body_frame_to_NE(pos_vector.x, pos_vector.y);
|
||||||
|
// }
|
||||||
|
// // add body offset if necessary
|
||||||
|
// if (packet.coordinate_frame == MAV_FRAME_LOCAL_OFFSET_NED ||
|
||||||
|
// packet.coordinate_frame == MAV_FRAME_BODY_NED ||
|
||||||
|
// packet.coordinate_frame == MAV_FRAME_BODY_OFFSET_NED) {
|
||||||
|
// pos_vector += blimp.inertial_nav.get_position();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // prepare velocity
|
||||||
|
// Vector3f vel_vector;
|
||||||
|
// if (!vel_ignore) {
|
||||||
|
// // convert to cm
|
||||||
|
// vel_vector = Vector3f(packet.vx * 100.0f, packet.vy * 100.0f, -packet.vz * 100.0f);
|
||||||
|
// // rotate to body-frame if necessary
|
||||||
|
// if (packet.coordinate_frame == MAV_FRAME_BODY_NED || packet.coordinate_frame == MAV_FRAME_BODY_OFFSET_NED) {
|
||||||
|
// blimp.rotate_body_frame_to_NE(vel_vector.x, vel_vector.y);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // prepare yaw
|
||||||
|
// float yaw_cd = 0.0f;
|
||||||
|
// bool yaw_relative = false;
|
||||||
|
// float yaw_rate_cds = 0.0f;
|
||||||
|
// if (!yaw_ignore) {
|
||||||
|
// yaw_cd = ToDeg(packet.yaw) * 100.0f;
|
||||||
|
// yaw_relative = packet.coordinate_frame == MAV_FRAME_BODY_NED || packet.coordinate_frame == MAV_FRAME_BODY_OFFSET_NED;
|
||||||
|
// }
|
||||||
|
// if (!yaw_rate_ignore) {
|
||||||
|
// yaw_rate_cds = ToDeg(packet.yaw_rate) * 100.0f;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // send request
|
||||||
|
// if (!pos_ignore && !vel_ignore) {
|
||||||
|
// blimp.mode_guided.set_destination_posvel(pos_vector, vel_vector, !yaw_ignore, yaw_cd, !yaw_rate_ignore, yaw_rate_cds, yaw_relative);
|
||||||
|
// } else if (pos_ignore && !vel_ignore) {
|
||||||
|
// blimp.mode_guided.set_velocity(vel_vector, !yaw_ignore, yaw_cd, !yaw_rate_ignore, yaw_rate_cds, yaw_relative);
|
||||||
|
// } else if (!pos_ignore && vel_ignore) {
|
||||||
|
// blimp.mode_guided.set_destination(pos_vector, !yaw_ignore, yaw_cd, !yaw_rate_ignore, yaw_rate_cds, yaw_relative);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// case MAVLINK_MSG_ID_SET_POSITION_TARGET_GLOBAL_INT: // MAV ID: 86
|
||||||
|
// {
|
||||||
|
// // decode packet
|
||||||
|
// mavlink_set_position_target_global_int_t packet;
|
||||||
|
// mavlink_msg_set_position_target_global_int_decode(&msg, &packet);
|
||||||
|
|
||||||
|
// // exit if vehicle is not in Guided mode or Auto-Guided mode
|
||||||
|
// if (!blimp.flightmode->in_guided_mode()) {
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// bool pos_ignore = packet.type_mask & MAVLINK_SET_POS_TYPE_MASK_POS_IGNORE;
|
||||||
|
// bool vel_ignore = packet.type_mask & MAVLINK_SET_POS_TYPE_MASK_VEL_IGNORE;
|
||||||
|
// bool acc_ignore = packet.type_mask & MAVLINK_SET_POS_TYPE_MASK_ACC_IGNORE;
|
||||||
|
// bool yaw_ignore = packet.type_mask & MAVLINK_SET_POS_TYPE_MASK_YAW_IGNORE;
|
||||||
|
// bool yaw_rate_ignore = packet.type_mask & MAVLINK_SET_POS_TYPE_MASK_YAW_RATE_IGNORE;
|
||||||
|
|
||||||
|
// // exit immediately if acceleration provided
|
||||||
|
// if (!acc_ignore) {
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // extract location from message
|
||||||
|
// Location loc;
|
||||||
|
// if (!pos_ignore) {
|
||||||
|
// // sanity check location
|
||||||
|
// if (!check_latlng(packet.lat_int, packet.lon_int)) {
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// Location::AltFrame frame;
|
||||||
|
// if (!mavlink_coordinate_frame_to_location_alt_frame((MAV_FRAME)packet.coordinate_frame, frame)) {
|
||||||
|
// // unknown coordinate frame
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// loc = {packet.lat_int, packet.lon_int, int32_t(packet.alt*100), frame};
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // prepare yaw
|
||||||
|
// float yaw_cd = 0.0f;
|
||||||
|
// bool yaw_relative = false;
|
||||||
|
// float yaw_rate_cds = 0.0f;
|
||||||
|
// if (!yaw_ignore) {
|
||||||
|
// yaw_cd = ToDeg(packet.yaw) * 100.0f;
|
||||||
|
// yaw_relative = packet.coordinate_frame == MAV_FRAME_BODY_NED || packet.coordinate_frame == MAV_FRAME_BODY_OFFSET_NED;
|
||||||
|
// }
|
||||||
|
// if (!yaw_rate_ignore) {
|
||||||
|
// yaw_rate_cds = ToDeg(packet.yaw_rate) * 100.0f;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // send targets to the appropriate guided mode controller
|
||||||
|
// if (!pos_ignore && !vel_ignore) {
|
||||||
|
// // convert Location to vector from ekf origin for posvel controller
|
||||||
|
// if (loc.get_alt_frame() == Location::AltFrame::ABOVE_TERRAIN) {
|
||||||
|
// // posvel controller does not support alt-above-terrain
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// Vector3f pos_neu_cm;
|
||||||
|
// if (!loc.get_vector_from_origin_NEU(pos_neu_cm)) {
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// blimp.mode_guided.set_destination_posvel(pos_neu_cm, Vector3f(packet.vx * 100.0f, packet.vy * 100.0f, -packet.vz * 100.0f), !yaw_ignore, yaw_cd, !yaw_rate_ignore, yaw_rate_cds, yaw_relative);
|
||||||
|
// } else if (pos_ignore && !vel_ignore) {
|
||||||
|
// blimp.mode_guided.set_velocity(Vector3f(packet.vx * 100.0f, packet.vy * 100.0f, -packet.vz * 100.0f), !yaw_ignore, yaw_cd, !yaw_rate_ignore, yaw_rate_cds, yaw_relative);
|
||||||
|
// } else if (!pos_ignore && vel_ignore) {
|
||||||
|
// blimp.mode_guided.set_destination(loc, !yaw_ignore, yaw_cd, !yaw_rate_ignore, yaw_rate_cds, yaw_relative);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
case MAVLINK_MSG_ID_RADIO:
|
||||||
|
case MAVLINK_MSG_ID_RADIO_STATUS: { // MAV ID: 109
|
||||||
|
handle_radio_status(msg, blimp.should_log(MASK_LOG_PM));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case MAVLINK_MSG_ID_TERRAIN_DATA:
|
||||||
|
case MAVLINK_MSG_ID_TERRAIN_CHECK:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MAVLINK_MSG_ID_SET_HOME_POSITION: {
|
||||||
|
mavlink_set_home_position_t packet;
|
||||||
|
mavlink_msg_set_home_position_decode(&msg, &packet);
|
||||||
|
if ((packet.latitude == 0) && (packet.longitude == 0) && (packet.altitude == 0)) {
|
||||||
|
if (!blimp.set_home_to_current_location(true)) {
|
||||||
|
// silently ignored
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Location new_home_loc;
|
||||||
|
new_home_loc.lat = packet.latitude;
|
||||||
|
new_home_loc.lng = packet.longitude;
|
||||||
|
new_home_loc.alt = packet.altitude / 10;
|
||||||
|
if (!blimp.set_home(new_home_loc, true)) {
|
||||||
|
// silently ignored
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case MAVLINK_MSG_ID_ADSB_VEHICLE:
|
||||||
|
case MAVLINK_MSG_ID_UAVIONIX_ADSB_OUT_CFG:
|
||||||
|
case MAVLINK_MSG_ID_UAVIONIX_ADSB_OUT_DYNAMIC:
|
||||||
|
case MAVLINK_MSG_ID_UAVIONIX_ADSB_TRANSCEIVER_HEALTH_REPORT:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
handle_common_message(msg);
|
||||||
|
break;
|
||||||
|
} // end switch
|
||||||
|
} // end handle mavlink
|
||||||
|
|
||||||
|
|
||||||
|
MAV_RESULT GCS_MAVLINK_Blimp::handle_flight_termination(const mavlink_command_long_t &packet)
|
||||||
|
{
|
||||||
|
MAV_RESULT result = MAV_RESULT_FAILED;
|
||||||
|
if (packet.param1 > 0.5f) {
|
||||||
|
blimp.arming.disarm(AP_Arming::Method::TERMINATION);
|
||||||
|
result = MAV_RESULT_ACCEPTED;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
float GCS_MAVLINK_Blimp::vfr_hud_alt() const
|
||||||
|
{
|
||||||
|
if (blimp.g2.dev_options.get() & DevOptionVFR_HUDRelativeAlt) {
|
||||||
|
// compatibility option for older mavlink-aware devices that
|
||||||
|
// assume Blimp returns a relative altitude in VFR_HUD.alt
|
||||||
|
return blimp.current_loc.alt * 0.01f;
|
||||||
|
}
|
||||||
|
return GCS_MAVLINK::vfr_hud_alt();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t GCS_MAVLINK_Blimp::capabilities() const
|
||||||
|
{
|
||||||
|
return (MAV_PROTOCOL_CAPABILITY_MISSION_FLOAT |
|
||||||
|
MAV_PROTOCOL_CAPABILITY_MISSION_INT |
|
||||||
|
MAV_PROTOCOL_CAPABILITY_COMMAND_INT |
|
||||||
|
MAV_PROTOCOL_CAPABILITY_SET_POSITION_TARGET_LOCAL_NED |
|
||||||
|
MAV_PROTOCOL_CAPABILITY_SET_POSITION_TARGET_GLOBAL_INT |
|
||||||
|
MAV_PROTOCOL_CAPABILITY_FLIGHT_TERMINATION |
|
||||||
|
MAV_PROTOCOL_CAPABILITY_SET_ATTITUDE_TARGET |
|
||||||
|
GCS_MAVLINK::capabilities());
|
||||||
|
}
|
||||||
|
|
||||||
|
MAV_LANDED_STATE GCS_MAVLINK_Blimp::landed_state() const
|
||||||
|
{
|
||||||
|
if (blimp.ap.land_complete) {
|
||||||
|
return MAV_LANDED_STATE_ON_GROUND;
|
||||||
|
}
|
||||||
|
if (blimp.flightmode->is_landing()) {
|
||||||
|
return MAV_LANDED_STATE_LANDING;
|
||||||
|
}
|
||||||
|
// if (blimp.flightmode->is_taking_off()) {
|
||||||
|
// return MAV_LANDED_STATE_TAKEOFF;
|
||||||
|
// }
|
||||||
|
return MAV_LANDED_STATE_IN_AIR;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GCS_MAVLINK_Blimp::send_wind() const
|
||||||
|
{
|
||||||
|
Vector3f airspeed_vec_bf;
|
||||||
|
if (!AP::ahrs().airspeed_vector_true(airspeed_vec_bf)) {
|
||||||
|
// if we don't have an airspeed estimate then we don't have a
|
||||||
|
// valid wind estimate on blimps
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const Vector3f wind = AP::ahrs().wind_estimate();
|
||||||
|
mavlink_msg_wind_send(
|
||||||
|
chan,
|
||||||
|
degrees(atan2f(-wind.y, -wind.x)),
|
||||||
|
wind.length(),
|
||||||
|
wind.z);
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <GCS_MAVLink/GCS.h>
|
||||||
|
|
||||||
|
class GCS_MAVLINK_Blimp : public GCS_MAVLINK
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
using GCS_MAVLINK::GCS_MAVLINK;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
uint32_t telem_delay() const override;
|
||||||
|
|
||||||
|
MAV_RESULT handle_flight_termination(const mavlink_command_long_t &packet) override;
|
||||||
|
|
||||||
|
uint8_t sysid_my_gcs() const override;
|
||||||
|
bool sysid_enforce() const override;
|
||||||
|
|
||||||
|
bool params_ready() const override;
|
||||||
|
void send_banner() override;
|
||||||
|
|
||||||
|
MAV_RESULT _handle_command_preflight_calibration(const mavlink_command_long_t &packet) override;
|
||||||
|
|
||||||
|
void send_position_target_global_int() override;
|
||||||
|
// void send_position_target_local_ned() override;
|
||||||
|
|
||||||
|
MAV_RESULT handle_command_do_set_roi(const Location &roi_loc) override;
|
||||||
|
MAV_RESULT handle_preflight_reboot(const mavlink_command_long_t &packet) override;
|
||||||
|
MAV_RESULT handle_command_mount(const mavlink_command_long_t &packet) override;
|
||||||
|
MAV_RESULT handle_command_int_packet(const mavlink_command_int_t &packet) override;
|
||||||
|
MAV_RESULT handle_command_long_packet(const mavlink_command_long_t &packet) override;
|
||||||
|
MAV_RESULT handle_command_int_do_reposition(const mavlink_command_int_t &packet);
|
||||||
|
|
||||||
|
// void handle_mount_message(const mavlink_message_t &msg) override;
|
||||||
|
|
||||||
|
bool set_home_to_current_location(bool lock) override WARN_IF_UNUSED;
|
||||||
|
bool set_home(const Location& loc, bool lock) override WARN_IF_UNUSED;
|
||||||
|
void send_nav_controller_output() const override; //MIR can't comment out or build fails??
|
||||||
|
uint64_t capabilities() const override;
|
||||||
|
|
||||||
|
virtual MAV_VTOL_STATE vtol_state() const override
|
||||||
|
{
|
||||||
|
return MAV_VTOL_STATE_MC;
|
||||||
|
};
|
||||||
|
virtual MAV_LANDED_STATE landed_state() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void handleMessage(const mavlink_message_t &msg) override;
|
||||||
|
void handle_command_ack(const mavlink_message_t &msg) override;
|
||||||
|
bool handle_guided_request(AP_Mission::Mission_Command &cmd) override;
|
||||||
|
void handle_change_alt_request(AP_Mission::Mission_Command &cmd) override;
|
||||||
|
void handle_rc_channels_override(const mavlink_message_t &msg) override;
|
||||||
|
bool try_send_message(enum ap_message id) override;
|
||||||
|
|
||||||
|
void packetReceived(const mavlink_status_t &status,
|
||||||
|
const mavlink_message_t &msg) override;
|
||||||
|
|
||||||
|
MAV_MODE base_mode() const override;
|
||||||
|
MAV_STATE vehicle_system_status() const override;
|
||||||
|
|
||||||
|
float vfr_hud_airspeed() const override;
|
||||||
|
int16_t vfr_hud_throttle() const override;
|
||||||
|
float vfr_hud_alt() const override;
|
||||||
|
|
||||||
|
void send_pid_tuning() override;
|
||||||
|
|
||||||
|
void send_wind() const;
|
||||||
|
};
|
|
@ -0,0 +1,555 @@
|
||||||
|
#include "Blimp.h"
|
||||||
|
|
||||||
|
#if LOGGING_ENABLED == ENABLED
|
||||||
|
|
||||||
|
// Code to Write and Read packets from AP_Logger log memory
|
||||||
|
// Code to interact with the user to dump or erase logs
|
||||||
|
|
||||||
|
struct PACKED log_Control_Tuning {
|
||||||
|
LOG_PACKET_HEADER;
|
||||||
|
uint64_t time_us;
|
||||||
|
float throttle_in;
|
||||||
|
float angle_boost;
|
||||||
|
float throttle_out;
|
||||||
|
float throttle_hover;
|
||||||
|
float desired_alt;
|
||||||
|
float inav_alt;
|
||||||
|
int32_t baro_alt;
|
||||||
|
float desired_rangefinder_alt;
|
||||||
|
float rangefinder_alt;
|
||||||
|
float terr_alt;
|
||||||
|
int16_t target_climb_rate;
|
||||||
|
int16_t climb_rate;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Write a control tuning packet
|
||||||
|
void Blimp::Log_Write_Control_Tuning()
|
||||||
|
{
|
||||||
|
// get terrain altitude
|
||||||
|
// float terr_alt = 0.0f;
|
||||||
|
// float des_alt_m = 0.0f;
|
||||||
|
// int16_t target_climb_rate_cms = 0;
|
||||||
|
// if (!flightmode->has_manual_throttle()) {
|
||||||
|
// des_alt_m = pos_control->get_alt_target() / 100.0f;
|
||||||
|
// target_climb_rate_cms = pos_control->get_vel_target_z();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// get surface tracking alts
|
||||||
|
// float desired_rangefinder_alt;
|
||||||
|
// if (!surface_tracking.get_target_dist_for_logging(desired_rangefinder_alt)) {
|
||||||
|
// desired_rangefinder_alt = AP::logger().quiet_nan();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// struct log_Control_Tuning pkt = {
|
||||||
|
// LOG_PACKET_HEADER_INIT(LOG_CONTROL_TUNING_MSG),
|
||||||
|
// time_us : AP_HAL::micros64(),
|
||||||
|
// throttle_in : attitude_control->get_throttle_in(),
|
||||||
|
// angle_boost : attitude_control->angle_boost(),
|
||||||
|
// throttle_out : motors->get_throttle(),
|
||||||
|
// throttle_hover : motors->get_throttle_hover(),
|
||||||
|
// desired_alt : des_alt_m,
|
||||||
|
// inav_alt : inertial_nav.get_altitude() / 100.0f,
|
||||||
|
// baro_alt : baro_alt,
|
||||||
|
// desired_rangefinder_alt : desired_rangefinder_alt,
|
||||||
|
// rangefinder_alt : surface_tracking.get_dist_for_logging(),
|
||||||
|
// terr_alt : terr_alt,
|
||||||
|
// target_climb_rate : target_climb_rate_cms,
|
||||||
|
// climb_rate : int16_t(inertial_nav.get_velocity_z()) // float -> int16_t
|
||||||
|
// };
|
||||||
|
// logger.WriteBlock(&pkt, sizeof(pkt));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write an attitude packet
|
||||||
|
void Blimp::Log_Write_Attitude()
|
||||||
|
{
|
||||||
|
// // Vector3f targets = attitude_control->get_att_target_euler_cd();
|
||||||
|
// targets.z = wrap_360_cd(targets.z);
|
||||||
|
// logger.Write_Attitude(targets);
|
||||||
|
// logger.Write_Rate(ahrs_view, *motors, *attitude_control, *pos_control);
|
||||||
|
// if (should_log(MASK_LOG_PID)) {
|
||||||
|
// logger.Write_PID(LOG_PIDR_MSG, attitude_control->get_rate_roll_pid().get_pid_info());
|
||||||
|
// logger.Write_PID(LOG_PIDP_MSG, attitude_control->get_rate_pitch_pid().get_pid_info());
|
||||||
|
// logger.Write_PID(LOG_PIDY_MSG, attitude_control->get_rate_yaw_pid().get_pid_info());
|
||||||
|
// // logger.Write_PID(LOG_PIDA_MSG, pos_control->get_accel_z_pid().get_pid_info() );
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write an EKF and POS packet
|
||||||
|
void Blimp::Log_Write_EKF_POS()
|
||||||
|
{
|
||||||
|
AP::ahrs_navekf().Log_Write();
|
||||||
|
ahrs.Write_AHRS2();
|
||||||
|
#if CONFIG_HAL_BOARD == HAL_BOARD_SITL
|
||||||
|
sitl.Log_Write_SIMSTATE();
|
||||||
|
#endif
|
||||||
|
ahrs.Write_POS();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PACKED log_MotBatt {
|
||||||
|
LOG_PACKET_HEADER;
|
||||||
|
uint64_t time_us;
|
||||||
|
float lift_max;
|
||||||
|
float bat_volt;
|
||||||
|
float bat_res;
|
||||||
|
float th_limit;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Write an rate packet
|
||||||
|
void Blimp::Log_Write_MotBatt()
|
||||||
|
{
|
||||||
|
// struct log_MotBatt pkt_mot = {
|
||||||
|
// LOG_PACKET_HEADER_INIT(LOG_MOTBATT_MSG),
|
||||||
|
// time_us : AP_HAL::micros64(),
|
||||||
|
// lift_max : (float)(motors->get_lift_max()),
|
||||||
|
// bat_volt : (float)(motors->get_batt_voltage_filt()),
|
||||||
|
// bat_res : (float)(battery.get_resistance()),
|
||||||
|
// th_limit : (float)(motors->get_throttle_limit())
|
||||||
|
// };
|
||||||
|
// logger.WriteBlock(&pkt_mot, sizeof(pkt_mot));
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PACKED log_Data_Int16t {
|
||||||
|
LOG_PACKET_HEADER;
|
||||||
|
uint64_t time_us;
|
||||||
|
uint8_t id;
|
||||||
|
int16_t data_value;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Write an int16_t data packet
|
||||||
|
UNUSED_FUNCTION
|
||||||
|
void Blimp::Log_Write_Data(LogDataID id, int16_t value)
|
||||||
|
{
|
||||||
|
if (should_log(MASK_LOG_ANY)) {
|
||||||
|
struct log_Data_Int16t pkt = {
|
||||||
|
LOG_PACKET_HEADER_INIT(LOG_DATA_INT16_MSG),
|
||||||
|
time_us : AP_HAL::micros64(),
|
||||||
|
id : (uint8_t)id,
|
||||||
|
data_value : value
|
||||||
|
};
|
||||||
|
logger.WriteCriticalBlock(&pkt, sizeof(pkt));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PACKED log_Data_UInt16t {
|
||||||
|
LOG_PACKET_HEADER;
|
||||||
|
uint64_t time_us;
|
||||||
|
uint8_t id;
|
||||||
|
uint16_t data_value;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Write an uint16_t data packet
|
||||||
|
UNUSED_FUNCTION
|
||||||
|
void Blimp::Log_Write_Data(LogDataID id, uint16_t value)
|
||||||
|
{
|
||||||
|
if (should_log(MASK_LOG_ANY)) {
|
||||||
|
struct log_Data_UInt16t pkt = {
|
||||||
|
LOG_PACKET_HEADER_INIT(LOG_DATA_UINT16_MSG),
|
||||||
|
time_us : AP_HAL::micros64(),
|
||||||
|
id : (uint8_t)id,
|
||||||
|
data_value : value
|
||||||
|
};
|
||||||
|
logger.WriteCriticalBlock(&pkt, sizeof(pkt));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PACKED log_Data_Int32t {
|
||||||
|
LOG_PACKET_HEADER;
|
||||||
|
uint64_t time_us;
|
||||||
|
uint8_t id;
|
||||||
|
int32_t data_value;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Write an int32_t data packet
|
||||||
|
void Blimp::Log_Write_Data(LogDataID id, int32_t value)
|
||||||
|
{
|
||||||
|
if (should_log(MASK_LOG_ANY)) {
|
||||||
|
struct log_Data_Int32t pkt = {
|
||||||
|
LOG_PACKET_HEADER_INIT(LOG_DATA_INT32_MSG),
|
||||||
|
time_us : AP_HAL::micros64(),
|
||||||
|
id : (uint8_t)id,
|
||||||
|
data_value : value
|
||||||
|
};
|
||||||
|
logger.WriteCriticalBlock(&pkt, sizeof(pkt));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PACKED log_Data_UInt32t {
|
||||||
|
LOG_PACKET_HEADER;
|
||||||
|
uint64_t time_us;
|
||||||
|
uint8_t id;
|
||||||
|
uint32_t data_value;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Write a uint32_t data packet
|
||||||
|
void Blimp::Log_Write_Data(LogDataID id, uint32_t value)
|
||||||
|
{
|
||||||
|
if (should_log(MASK_LOG_ANY)) {
|
||||||
|
struct log_Data_UInt32t pkt = {
|
||||||
|
LOG_PACKET_HEADER_INIT(LOG_DATA_UINT32_MSG),
|
||||||
|
time_us : AP_HAL::micros64(),
|
||||||
|
id : (uint8_t)id,
|
||||||
|
data_value : value
|
||||||
|
};
|
||||||
|
logger.WriteCriticalBlock(&pkt, sizeof(pkt));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PACKED log_Data_Float {
|
||||||
|
LOG_PACKET_HEADER;
|
||||||
|
uint64_t time_us;
|
||||||
|
uint8_t id;
|
||||||
|
float data_value;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Write a float data packet
|
||||||
|
UNUSED_FUNCTION
|
||||||
|
void Blimp::Log_Write_Data(LogDataID id, float value)
|
||||||
|
{
|
||||||
|
if (should_log(MASK_LOG_ANY)) {
|
||||||
|
struct log_Data_Float pkt = {
|
||||||
|
LOG_PACKET_HEADER_INIT(LOG_DATA_FLOAT_MSG),
|
||||||
|
time_us : AP_HAL::micros64(),
|
||||||
|
id : (uint8_t)id,
|
||||||
|
data_value : value
|
||||||
|
};
|
||||||
|
logger.WriteCriticalBlock(&pkt, sizeof(pkt));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PACKED log_ParameterTuning {
|
||||||
|
LOG_PACKET_HEADER;
|
||||||
|
uint64_t time_us;
|
||||||
|
uint8_t parameter; // parameter we are tuning, e.g. 39 is CH6_CIRCLE_RATE
|
||||||
|
float tuning_value; // normalized value used inside tuning() function
|
||||||
|
float tuning_min; // tuning minimum value
|
||||||
|
float tuning_max; // tuning maximum value
|
||||||
|
};
|
||||||
|
|
||||||
|
void Blimp::Log_Write_Parameter_Tuning(uint8_t param, float tuning_val, float tune_min, float tune_max)
|
||||||
|
{
|
||||||
|
struct log_ParameterTuning pkt_tune = {
|
||||||
|
LOG_PACKET_HEADER_INIT(LOG_PARAMTUNE_MSG),
|
||||||
|
time_us : AP_HAL::micros64(),
|
||||||
|
parameter : param,
|
||||||
|
tuning_value : tuning_val,
|
||||||
|
tuning_min : tune_min,
|
||||||
|
tuning_max : tune_max
|
||||||
|
};
|
||||||
|
|
||||||
|
logger.WriteBlock(&pkt_tune, sizeof(pkt_tune));
|
||||||
|
}
|
||||||
|
|
||||||
|
// logs when baro or compass becomes unhealthy
|
||||||
|
void Blimp::Log_Sensor_Health()
|
||||||
|
{
|
||||||
|
// check baro
|
||||||
|
if (sensor_health.baro != barometer.healthy()) {
|
||||||
|
sensor_health.baro = barometer.healthy();
|
||||||
|
AP::logger().Write_Error(LogErrorSubsystem::BARO,
|
||||||
|
(sensor_health.baro ? LogErrorCode::ERROR_RESOLVED : LogErrorCode::UNHEALTHY));
|
||||||
|
}
|
||||||
|
|
||||||
|
// check compass
|
||||||
|
if (sensor_health.compass != compass.healthy()) {
|
||||||
|
sensor_health.compass = compass.healthy();
|
||||||
|
AP::logger().Write_Error(LogErrorSubsystem::COMPASS, (sensor_health.compass ? LogErrorCode::ERROR_RESOLVED : LogErrorCode::UNHEALTHY));
|
||||||
|
}
|
||||||
|
|
||||||
|
// check primary GPS
|
||||||
|
if (sensor_health.primary_gps != gps.primary_sensor()) {
|
||||||
|
sensor_health.primary_gps = gps.primary_sensor();
|
||||||
|
AP::logger().Write_Event(LogEvent::GPS_PRIMARY_CHANGED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PACKED log_SysIdD {
|
||||||
|
LOG_PACKET_HEADER;
|
||||||
|
uint64_t time_us;
|
||||||
|
float waveform_time;
|
||||||
|
float waveform_sample;
|
||||||
|
float waveform_freq;
|
||||||
|
float angle_x;
|
||||||
|
float angle_y;
|
||||||
|
float angle_z;
|
||||||
|
float accel_x;
|
||||||
|
float accel_y;
|
||||||
|
float accel_z;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Write an rate packet
|
||||||
|
void Blimp::Log_Write_SysID_Data(float waveform_time, float waveform_sample, float waveform_freq, float angle_x, float angle_y, float angle_z, float accel_x, float accel_y, float accel_z)
|
||||||
|
{
|
||||||
|
#if MODE_SYSTEMID_ENABLED == ENABLED
|
||||||
|
struct log_SysIdD pkt_sidd = {
|
||||||
|
LOG_PACKET_HEADER_INIT(LOG_SYSIDD_MSG),
|
||||||
|
time_us : AP_HAL::micros64(),
|
||||||
|
waveform_time : waveform_time,
|
||||||
|
waveform_sample : waveform_sample,
|
||||||
|
waveform_freq : waveform_freq,
|
||||||
|
angle_x : angle_x,
|
||||||
|
angle_y : angle_y,
|
||||||
|
angle_z : angle_z,
|
||||||
|
accel_x : accel_x,
|
||||||
|
accel_y : accel_y,
|
||||||
|
accel_z : accel_z
|
||||||
|
};
|
||||||
|
logger.WriteBlock(&pkt_sidd, sizeof(pkt_sidd));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PACKED log_SysIdS {
|
||||||
|
LOG_PACKET_HEADER;
|
||||||
|
uint64_t time_us;
|
||||||
|
uint8_t systemID_axis;
|
||||||
|
float waveform_magnitude;
|
||||||
|
float frequency_start;
|
||||||
|
float frequency_stop;
|
||||||
|
float time_fade_in;
|
||||||
|
float time_const_freq;
|
||||||
|
float time_record;
|
||||||
|
float time_fade_out;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Write an rate packet
|
||||||
|
void Blimp::Log_Write_SysID_Setup(uint8_t systemID_axis, float waveform_magnitude, float frequency_start, float frequency_stop, float time_fade_in, float time_const_freq, float time_record, float time_fade_out)
|
||||||
|
{
|
||||||
|
#if MODE_SYSTEMID_ENABLED == ENABLED
|
||||||
|
struct log_SysIdS pkt_sids = {
|
||||||
|
LOG_PACKET_HEADER_INIT(LOG_SYSIDS_MSG),
|
||||||
|
time_us : AP_HAL::micros64(),
|
||||||
|
systemID_axis : systemID_axis,
|
||||||
|
waveform_magnitude : waveform_magnitude,
|
||||||
|
frequency_start : frequency_start,
|
||||||
|
frequency_stop : frequency_stop,
|
||||||
|
time_fade_in : time_fade_in,
|
||||||
|
time_const_freq : time_const_freq,
|
||||||
|
time_record : time_record,
|
||||||
|
time_fade_out : time_fade_out
|
||||||
|
};
|
||||||
|
logger.WriteBlock(&pkt_sids, sizeof(pkt_sids));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// // guided target logging
|
||||||
|
// struct PACKED log_GuidedTarget {
|
||||||
|
// LOG_PACKET_HEADER;
|
||||||
|
// uint64_t time_us;
|
||||||
|
// uint8_t type;
|
||||||
|
// float pos_target_x;
|
||||||
|
// float pos_target_y;
|
||||||
|
// float pos_target_z;
|
||||||
|
// float vel_target_x;
|
||||||
|
// float vel_target_y;
|
||||||
|
// float vel_target_z;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// Write a Guided mode target
|
||||||
|
// pos_target is lat, lon, alt OR offset from ekf origin in cm OR roll, pitch, yaw target in centi-degrees
|
||||||
|
// vel_target is cm/s
|
||||||
|
// void Blimp::Log_Write_GuidedTarget(uint8_t target_type, const Vector3f& pos_target, const Vector3f& vel_target)
|
||||||
|
// {
|
||||||
|
// struct log_GuidedTarget pkt = {
|
||||||
|
// LOG_PACKET_HEADER_INIT(LOG_GUIDEDTARGET_MSG),
|
||||||
|
// time_us : AP_HAL::micros64(),
|
||||||
|
// type : target_type,
|
||||||
|
// pos_target_x : pos_target.x,
|
||||||
|
// pos_target_y : pos_target.y,
|
||||||
|
// pos_target_z : pos_target.z,
|
||||||
|
// vel_target_x : vel_target.x,
|
||||||
|
// vel_target_y : vel_target.y,
|
||||||
|
// vel_target_z : vel_target.z
|
||||||
|
// };
|
||||||
|
// logger.WriteBlock(&pkt, sizeof(pkt));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// type and unit information can be found in
|
||||||
|
// libraries/AP_Logger/Logstructure.h; search for "log_Units" for
|
||||||
|
// units and "Format characters" for field type information
|
||||||
|
const struct LogStructure Blimp::log_structure[] = {
|
||||||
|
LOG_COMMON_STRUCTURES,
|
||||||
|
|
||||||
|
// @LoggerMessage: PTUN
|
||||||
|
// @Description: Parameter Tuning information
|
||||||
|
// @URL: https://ardupilot.org/blimp/docs/tuning.html#in-flight-tuning
|
||||||
|
// @Field: TimeUS: Time since system startup
|
||||||
|
// @Field: Param: Parameter being tuned
|
||||||
|
// @Field: TunVal: Normalized value used inside tuning() function
|
||||||
|
// @Field: TunMin: Tuning minimum limit
|
||||||
|
// @Field: TunMax: Tuning maximum limit
|
||||||
|
|
||||||
|
{
|
||||||
|
LOG_PARAMTUNE_MSG, sizeof(log_ParameterTuning),
|
||||||
|
"PTUN", "QBfff", "TimeUS,Param,TunVal,TunMin,TunMax", "s----", "F----"
|
||||||
|
},
|
||||||
|
|
||||||
|
// @LoggerMessage: CTUN
|
||||||
|
// @Description: Control Tuning information
|
||||||
|
// @Field: TimeUS: Time since system startup
|
||||||
|
// @Field: ThI: throttle input
|
||||||
|
// @Field: ABst: angle boost
|
||||||
|
// @Field: ThO: throttle output
|
||||||
|
// @Field: ThH: calculated hover throttle
|
||||||
|
// @Field: DAlt: desired altitude
|
||||||
|
// @Field: Alt: achieved altitude
|
||||||
|
// @Field: BAlt: barometric altitude
|
||||||
|
// @Field: DSAlt: desired rangefinder altitude
|
||||||
|
// @Field: SAlt: achieved rangefinder altitude
|
||||||
|
// @Field: TAlt: terrain altitude
|
||||||
|
// @Field: DCRt: desired climb rate
|
||||||
|
// @Field: CRt: climb rate
|
||||||
|
|
||||||
|
// @LoggerMessage: D16
|
||||||
|
// @Description: Generic 16-bit-signed-integer storage
|
||||||
|
// @Field: TimeUS: Time since system startup
|
||||||
|
// @Field: Id: Data type identifier
|
||||||
|
// @Field: Value: Value
|
||||||
|
|
||||||
|
// @LoggerMessage: DU16
|
||||||
|
// @Description: Generic 16-bit-unsigned-integer storage
|
||||||
|
// @Field: TimeUS: Time since system startup
|
||||||
|
// @Field: Id: Data type identifier
|
||||||
|
// @Field: Value: Value
|
||||||
|
|
||||||
|
// @LoggerMessage: D32
|
||||||
|
// @Description: Generic 32-bit-signed-integer storage
|
||||||
|
// @Field: TimeUS: Time since system startup
|
||||||
|
// @Field: Id: Data type identifier
|
||||||
|
// @Field: Value: Value
|
||||||
|
|
||||||
|
// @LoggerMessage: DFLT
|
||||||
|
// @Description: Generic float storage
|
||||||
|
// @Field: TimeUS: Time since system startup
|
||||||
|
// @Field: Id: Data type identifier
|
||||||
|
// @Field: Value: Value
|
||||||
|
|
||||||
|
// @LoggerMessage: DU32
|
||||||
|
// @Description: Generic 32-bit-unsigned-integer storage
|
||||||
|
// @Field: TimeUS: Time since system startup
|
||||||
|
// @Field: Id: Data type identifier
|
||||||
|
// @Field: Value: Value
|
||||||
|
|
||||||
|
{
|
||||||
|
LOG_CONTROL_TUNING_MSG, sizeof(log_Control_Tuning),
|
||||||
|
"CTUN", "Qffffffefffhh", "TimeUS,ThI,ABst,ThO,ThH,DAlt,Alt,BAlt,DSAlt,SAlt,TAlt,DCRt,CRt", "s----mmmmmmnn", "F----00B000BB"
|
||||||
|
},
|
||||||
|
|
||||||
|
// @LoggerMessage: MOTB
|
||||||
|
// @Description: Battery information
|
||||||
|
// @Field: TimeUS: Time since system startup
|
||||||
|
// @Field: LiftMax: Maximum motor compensation gain
|
||||||
|
// @Field: BatVolt: Ratio betwen detected battery voltage and maximum battery voltage
|
||||||
|
// @Field: BatRes: Estimated battery resistance
|
||||||
|
// @Field: ThLimit: Throttle limit set due to battery current limitations
|
||||||
|
|
||||||
|
{
|
||||||
|
LOG_MOTBATT_MSG, sizeof(log_MotBatt),
|
||||||
|
"MOTB", "Qffff", "TimeUS,LiftMax,BatVolt,BatRes,ThLimit", "s-vw-", "F-00-"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
LOG_DATA_INT16_MSG, sizeof(log_Data_Int16t),
|
||||||
|
"D16", "QBh", "TimeUS,Id,Value", "s--", "F--"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
LOG_DATA_UINT16_MSG, sizeof(log_Data_UInt16t),
|
||||||
|
"DU16", "QBH", "TimeUS,Id,Value", "s--", "F--"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
LOG_DATA_INT32_MSG, sizeof(log_Data_Int32t),
|
||||||
|
"D32", "QBi", "TimeUS,Id,Value", "s--", "F--"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
LOG_DATA_UINT32_MSG, sizeof(log_Data_UInt32t),
|
||||||
|
"DU32", "QBI", "TimeUS,Id,Value", "s--", "F--"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
LOG_DATA_FLOAT_MSG, sizeof(log_Data_Float),
|
||||||
|
"DFLT", "QBf", "TimeUS,Id,Value", "s--", "F--"
|
||||||
|
},
|
||||||
|
|
||||||
|
// @LoggerMessage: SIDD
|
||||||
|
// @Description: System ID data
|
||||||
|
// @Field: TimeUS: Time since system startup
|
||||||
|
// @Field: Time: Time reference for waveform
|
||||||
|
// @Field: Targ: Current waveform sample
|
||||||
|
// @Field: F: Instantaneous waveform frequency
|
||||||
|
// @Field: Gx: Delta angle, X-Axis
|
||||||
|
// @Field: Gy: Delta angle, Y-Axis
|
||||||
|
// @Field: Gz: Delta angle, Z-Axis
|
||||||
|
// @Field: Ax: Delta velocity, X-Axis
|
||||||
|
// @Field: Ay: Delta velocity, Y-Axis
|
||||||
|
// @Field: Az: Delta velocity, Z-Axis
|
||||||
|
|
||||||
|
{
|
||||||
|
LOG_SYSIDD_MSG, sizeof(log_SysIdD),
|
||||||
|
"SIDD", "Qfffffffff", "TimeUS,Time,Targ,F,Gx,Gy,Gz,Ax,Ay,Az", "ss-zkkkooo", "F---------"
|
||||||
|
},
|
||||||
|
|
||||||
|
// @LoggerMessage: SIDS
|
||||||
|
// @Description: System ID settings
|
||||||
|
// @Field: TimeUS: Time since system startup
|
||||||
|
// @Field: Ax: The axis which is being excited
|
||||||
|
// @Field: Mag: Magnitude of the chirp waveform
|
||||||
|
// @Field: FSt: Frequency at the start of chirp
|
||||||
|
// @Field: FSp: Frequency at the end of chirp
|
||||||
|
// @Field: TFin: Time to reach maximum amplitude of chirp
|
||||||
|
// @Field: TC: Time at constant frequency before chirp starts
|
||||||
|
// @Field: TR: Time taken to complete chirp waveform
|
||||||
|
// @Field: TFout: Time to reach zero amplitude after chirp finishes
|
||||||
|
|
||||||
|
{
|
||||||
|
LOG_SYSIDS_MSG, sizeof(log_SysIdS),
|
||||||
|
"SIDS", "QBfffffff", "TimeUS,Ax,Mag,FSt,FSp,TFin,TC,TR,TFout", "s--ssssss", "F--------"
|
||||||
|
},
|
||||||
|
|
||||||
|
// // @LoggerMessage: GUID
|
||||||
|
// // @Description: Guided mode target information
|
||||||
|
// // @Field: TimeUS: Time since system startup
|
||||||
|
// // @Field: Type: Type of guided mode
|
||||||
|
// // @Field: pX: Target position, X-Axis
|
||||||
|
// // @Field: pY: Target position, Y-Axis
|
||||||
|
// // @Field: pZ: Target position, Z-Axis
|
||||||
|
// // @Field: vX: Target velocity, X-Axis
|
||||||
|
// // @Field: vY: Target velocity, Y-Axis
|
||||||
|
// // @Field: vZ: Target velocity, Z-Axis
|
||||||
|
|
||||||
|
// { LOG_GUIDEDTARGET_MSG, sizeof(log_GuidedTarget),
|
||||||
|
// "GUID", "QBffffff", "TimeUS,Type,pX,pY,pZ,vX,vY,vZ", "s-mmmnnn", "F-BBBBBB" },
|
||||||
|
};
|
||||||
|
|
||||||
|
void Blimp::Log_Write_Vehicle_Startup_Messages()
|
||||||
|
{
|
||||||
|
// only 200(?) bytes are guaranteed by AP_Logger
|
||||||
|
logger.Write_MessageF("Frame: %s", get_frame_string());
|
||||||
|
logger.Write_Mode((uint8_t)control_mode, control_mode_reason);
|
||||||
|
ahrs.Log_Write_Home_And_Origin();
|
||||||
|
gps.Write_AP_Logger_Log_Startup_messages();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Blimp::log_init(void)
|
||||||
|
{
|
||||||
|
logger.Init(log_structure, ARRAY_SIZE(log_structure));
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // LOGGING_ENABLED
|
||||||
|
|
||||||
|
void Blimp::Log_Write_Control_Tuning() {}
|
||||||
|
void Blimp::Log_Write_Performance() {}
|
||||||
|
void Blimp::Log_Write_Attitude(void) {}
|
||||||
|
void Blimp::Log_Write_EKF_POS() {}
|
||||||
|
void Blimp::Log_Write_MotBatt() {}
|
||||||
|
void Blimp::Log_Write_Data(LogDataID id, int32_t value) {}
|
||||||
|
void Blimp::Log_Write_Data(LogDataID id, uint32_t value) {}
|
||||||
|
void Blimp::Log_Write_Data(LogDataID id, int16_t value) {}
|
||||||
|
void Blimp::Log_Write_Data(LogDataID id, uint16_t value) {}
|
||||||
|
void Blimp::Log_Write_Data(LogDataID id, float value) {}
|
||||||
|
void Blimp::Log_Write_Parameter_Tuning(uint8_t param, float tuning_val, float tune_min, float tune_max) {}
|
||||||
|
void Blimp::Log_Sensor_Health() {}
|
||||||
|
void Blimp::Log_Write_Precland() {}
|
||||||
|
void Blimp::Log_Write_GuidedTarget(uint8_t target_type, const Vector3f& pos_target, const Vector3f& vel_target) {}
|
||||||
|
void Blimp::Log_Write_SysID_Setup(uint8_t systemID_axis, float waveform_magnitude, float frequency_start, float frequency_stop, float time_fade_in, float time_const_freq, float time_record, float time_fade_out) {}
|
||||||
|
void Blimp::Log_Write_SysID_Data(float waveform_time, float waveform_sample, float waveform_freq, float angle_x, float angle_y, float angle_z, float accel_x, float accel_y, float accel_z) {}
|
||||||
|
void Blimp::Log_Write_Vehicle_Startup_Messages() {}
|
||||||
|
|
||||||
|
void Blimp::log_init(void) {}
|
||||||
|
|
||||||
|
#endif // LOGGING_ENABLED
|
|
@ -0,0 +1,727 @@
|
||||||
|
#include "Blimp.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Blimp parameter definitions
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define GSCALAR(v, name, def) { blimp.g.v.vtype, name, Parameters::k_param_ ## v, &blimp.g.v, {def_value : def} }
|
||||||
|
#define ASCALAR(v, name, def) { blimp.aparm.v.vtype, name, Parameters::k_param_ ## v, (const void *)&blimp.aparm.v, {def_value : def} }
|
||||||
|
#define GGROUP(v, name, class) { AP_PARAM_GROUP, name, Parameters::k_param_ ## v, &blimp.g.v, {group_info : class::var_info} }
|
||||||
|
#define GOBJECT(v, name, class) { AP_PARAM_GROUP, name, Parameters::k_param_ ## v, (const void *)&blimp.v, {group_info : class::var_info} }
|
||||||
|
#define GOBJECTPTR(v, name, class) { AP_PARAM_GROUP, name, Parameters::k_param_ ## v, (const void *)&blimp.v, {group_info : class::var_info}, AP_PARAM_FLAG_POINTER }
|
||||||
|
#define GOBJECTVARPTR(v, name, var_info_ptr) { AP_PARAM_GROUP, name, Parameters::k_param_ ## v, (const void *)&blimp.v, {group_info_ptr : var_info_ptr}, AP_PARAM_FLAG_POINTER | AP_PARAM_FLAG_INFO_POINTER }
|
||||||
|
#define GOBJECTN(v, pname, name, class) { AP_PARAM_GROUP, name, Parameters::k_param_ ## pname, (const void *)&blimp.v, {group_info : class::var_info} }
|
||||||
|
|
||||||
|
#define DEFAULT_FRAME_CLASS 0
|
||||||
|
|
||||||
|
const AP_Param::Info Blimp::var_info[] = {
|
||||||
|
// @Param: FORMAT_VERSION
|
||||||
|
// @DisplayName: Eeprom format version number
|
||||||
|
// @Description: This value is incremented when changes are made to the eeprom format
|
||||||
|
// @User: Advanced
|
||||||
|
// @ReadOnly: True
|
||||||
|
GSCALAR(format_version, "FORMAT_VERSION", 0),
|
||||||
|
|
||||||
|
// @Param: SYSID_THISMAV
|
||||||
|
// @DisplayName: MAVLink system ID of this vehicle
|
||||||
|
// @Description: Allows setting an individual MAVLink system id for this vehicle to distinguish it from others on the same network
|
||||||
|
// @Range: 1 255
|
||||||
|
// @User: Advanced
|
||||||
|
GSCALAR(sysid_this_mav, "SYSID_THISMAV", MAV_SYSTEM_ID),
|
||||||
|
|
||||||
|
// @Param: SYSID_MYGCS
|
||||||
|
// @DisplayName: My ground station number
|
||||||
|
// @Description: Allows restricting radio overrides to only come from my ground station
|
||||||
|
// @Range: 1 255
|
||||||
|
// @User: Advanced
|
||||||
|
GSCALAR(sysid_my_gcs, "SYSID_MYGCS", 255),
|
||||||
|
|
||||||
|
// @Param: PILOT_THR_FILT
|
||||||
|
// @DisplayName: Throttle filter cutoff
|
||||||
|
// @Description: Throttle filter cutoff (Hz) - active whenever altitude control is inactive - 0 to disable
|
||||||
|
// @User: Advanced
|
||||||
|
// @Units: Hz
|
||||||
|
// @Range: 0 10
|
||||||
|
// @Increment: .5
|
||||||
|
GSCALAR(throttle_filt, "PILOT_THR_FILT", 0),
|
||||||
|
|
||||||
|
// @Param: PILOT_TKOFF_ALT
|
||||||
|
// @DisplayName: Pilot takeoff altitude
|
||||||
|
// @Description: Altitude that altitude control modes will climb to when a takeoff is triggered with the throttle stick.
|
||||||
|
// @User: Standard
|
||||||
|
// @Units: cm
|
||||||
|
// @Range: 0.0 1000.0
|
||||||
|
// @Increment: 10
|
||||||
|
GSCALAR(pilot_takeoff_alt, "PILOT_TKOFF_ALT", PILOT_TKOFF_ALT_DEFAULT),
|
||||||
|
|
||||||
|
// @Param: PILOT_THR_BHV
|
||||||
|
// @DisplayName: Throttle stick behavior
|
||||||
|
// @Description: Bitmask containing various throttle stick options. TX with sprung throttle can set PILOT_THR_BHV to "1" so motor feedback when landed starts from mid-stick instead of bottom of stick.
|
||||||
|
// @User: Standard
|
||||||
|
// @Values: 0:None,1:Feedback from mid stick,2:High throttle cancels landing,4:Disarm on land detection
|
||||||
|
// @Bitmask: 0:Feedback from mid stick,1:High throttle cancels landing,2:Disarm on land detection
|
||||||
|
GSCALAR(throttle_behavior, "PILOT_THR_BHV", 0),
|
||||||
|
|
||||||
|
// @Group: SERIAL
|
||||||
|
// @Path: ../libraries/AP_SerialManager/AP_SerialManager.cpp
|
||||||
|
GOBJECT(serial_manager, "SERIAL", AP_SerialManager),
|
||||||
|
|
||||||
|
// @Param: TELEM_DELAY
|
||||||
|
// @DisplayName: Telemetry startup delay
|
||||||
|
// @Description: The amount of time (in seconds) to delay radio telemetry to prevent an Xbee bricking on power up
|
||||||
|
// @User: Advanced
|
||||||
|
// @Units: s
|
||||||
|
// @Range: 0 30
|
||||||
|
// @Increment: 1
|
||||||
|
GSCALAR(telem_delay, "TELEM_DELAY", 0),
|
||||||
|
|
||||||
|
// @Param: GCS_PID_MASK
|
||||||
|
// @DisplayName: GCS PID tuning mask
|
||||||
|
// @Description: bitmask of PIDs to send MAVLink PID_TUNING messages for
|
||||||
|
// @User: Advanced
|
||||||
|
// @Values: 0:None,1:Roll,2:Pitch,4:Yaw,8:AccelZ
|
||||||
|
// @Bitmask: 0:Roll,1:Pitch,2:Yaw,3:AccelZ
|
||||||
|
GSCALAR(gcs_pid_mask, "GCS_PID_MASK", 0),
|
||||||
|
|
||||||
|
// #if MODE_RTL_ENABLED == ENABLED
|
||||||
|
// // @Param: RTL_ALT
|
||||||
|
// // @DisplayName: RTL Altitude
|
||||||
|
// // @Description: The minimum alt above home the vehicle will climb to before returning. If the vehicle is flying higher than this value it will return at its current altitude.
|
||||||
|
// // @Units: cm
|
||||||
|
// // @Range: 200 8000
|
||||||
|
// // @Increment: 1
|
||||||
|
// // @User: Standard
|
||||||
|
// GSCALAR(rtl_altitude, "RTL_ALT", RTL_ALT),
|
||||||
|
|
||||||
|
// // @Param: RTL_CONE_SLOPE
|
||||||
|
// // @DisplayName: RTL cone slope
|
||||||
|
// // @Description: Defines a cone above home which determines maximum climb
|
||||||
|
// // @Range: 0.5 10.0
|
||||||
|
// // @Increment: .1
|
||||||
|
// // @Values: 0:Disabled,1:Shallow,3:Steep
|
||||||
|
// // @User: Standard
|
||||||
|
// GSCALAR(rtl_cone_slope, "RTL_CONE_SLOPE", RTL_CONE_SLOPE_DEFAULT),
|
||||||
|
|
||||||
|
// // @Param: RTL_SPEED
|
||||||
|
// // @DisplayName: RTL speed
|
||||||
|
// // @Description: Defines the speed in cm/s which the aircraft will attempt to maintain horizontally while flying home. If this is set to zero, WPNAV_SPEED will be used instead.
|
||||||
|
// // @Units: cm/s
|
||||||
|
// // @Range: 0 2000
|
||||||
|
// // @Increment: 50
|
||||||
|
// // @User: Standard
|
||||||
|
// GSCALAR(rtl_speed_cms, "RTL_SPEED", 0),
|
||||||
|
|
||||||
|
// // @Param: RTL_ALT_FINAL
|
||||||
|
// // @DisplayName: RTL Final Altitude
|
||||||
|
// // @Description: This is the altitude the vehicle will move to as the final stage of Returning to Launch or after completing a mission. Set to zero to land.
|
||||||
|
// // @Units: cm
|
||||||
|
// // @Range: 0 1000
|
||||||
|
// // @Increment: 1
|
||||||
|
// // @User: Standard
|
||||||
|
// GSCALAR(rtl_alt_final, "RTL_ALT_FINAL", RTL_ALT_FINAL),
|
||||||
|
|
||||||
|
// // @Param: RTL_CLIMB_MIN
|
||||||
|
// // @DisplayName: RTL minimum climb
|
||||||
|
// // @Description: The vehicle will climb this many cm during the initial climb portion of the RTL
|
||||||
|
// // @Units: cm
|
||||||
|
// // @Range: 0 3000
|
||||||
|
// // @Increment: 10
|
||||||
|
// // @User: Standard
|
||||||
|
// GSCALAR(rtl_climb_min, "RTL_CLIMB_MIN", RTL_CLIMB_MIN_DEFAULT),
|
||||||
|
|
||||||
|
// // @Param: RTL_LOIT_TIME
|
||||||
|
// // @DisplayName: RTL loiter time
|
||||||
|
// // @Description: Time (in milliseconds) to loiter above home before beginning final descent
|
||||||
|
// // @Units: ms
|
||||||
|
// // @Range: 0 60000
|
||||||
|
// // @Increment: 1000
|
||||||
|
// // @User: Standard
|
||||||
|
// GSCALAR(rtl_loiter_time, "RTL_LOIT_TIME", RTL_LOITER_TIME),
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// @Param: FS_GCS_ENABLE
|
||||||
|
// @DisplayName: Ground Station Failsafe Enable
|
||||||
|
// @Description: Controls whether failsafe will be invoked (and what action to take) when connection with Ground station is lost for at least 5 seconds. See FS_OPTIONS param for additional actions, or for cases allowing Mission continuation, when GCS failsafe is enabled.
|
||||||
|
// @Values: 0:Disabled/NoAction,1:RTL,2:RTL or Continue with Mission in Auto Mode (Removed in 4.0+-see FS_OPTIONS),3:SmartRTL or RTL,4:SmartRTL or Land,5:Land (4.0+ Only)
|
||||||
|
// @User: Standard
|
||||||
|
GSCALAR(failsafe_gcs, "FS_GCS_ENABLE", FS_GCS_DISABLED),
|
||||||
|
|
||||||
|
// @Param: GPS_HDOP_GOOD
|
||||||
|
// @DisplayName: GPS Hdop Good
|
||||||
|
// @Description: GPS Hdop value at or below this value represent a good position. Used for pre-arm checks
|
||||||
|
// @Range: 100 900
|
||||||
|
// @User: Advanced
|
||||||
|
GSCALAR(gps_hdop_good, "GPS_HDOP_GOOD", GPS_HDOP_GOOD_DEFAULT),
|
||||||
|
|
||||||
|
// @Param: WP_YAW_BEHAVIOR
|
||||||
|
// @DisplayName: Yaw behaviour during missions
|
||||||
|
// @Description: Determines how the autopilot controls the yaw during missions and RTL
|
||||||
|
// @Values: 0:Never change yaw, 1:Face next waypoint, 2:Face next waypoint except RTL, 3:Face along GPS course
|
||||||
|
// @User: Standard
|
||||||
|
GSCALAR(wp_yaw_behavior, "WP_YAW_BEHAVIOR", WP_YAW_BEHAVIOR_DEFAULT),
|
||||||
|
|
||||||
|
// @Param: LAND_SPEED
|
||||||
|
// @DisplayName: Land speed
|
||||||
|
// @Description: The descent speed for the final stage of landing in cm/s
|
||||||
|
// @Units: cm/s
|
||||||
|
// @Range: 30 200
|
||||||
|
// @Increment: 10
|
||||||
|
// @User: Standard
|
||||||
|
GSCALAR(land_speed, "LAND_SPEED", LAND_SPEED),
|
||||||
|
|
||||||
|
// @Param: LAND_SPEED_HIGH
|
||||||
|
// @DisplayName: Land speed high
|
||||||
|
// @Description: The descent speed for the first stage of landing in cm/s. If this is zero then WPNAV_SPEED_DN is used
|
||||||
|
// @Units: cm/s
|
||||||
|
// @Range: 0 500
|
||||||
|
// @Increment: 10
|
||||||
|
// @User: Standard
|
||||||
|
GSCALAR(land_speed_high, "LAND_SPEED_HIGH", 0),
|
||||||
|
|
||||||
|
// @Param: PILOT_SPEED_UP
|
||||||
|
// @DisplayName: Pilot maximum vertical speed ascending
|
||||||
|
// @Description: The maximum vertical ascending velocity the pilot may request in cm/s
|
||||||
|
// @Units: cm/s
|
||||||
|
// @Range: 50 500
|
||||||
|
// @Increment: 10
|
||||||
|
// @User: Standard
|
||||||
|
GSCALAR(pilot_speed_up, "PILOT_SPEED_UP", PILOT_VELZ_MAX),
|
||||||
|
|
||||||
|
// @Param: PILOT_ACCEL_Z
|
||||||
|
// @DisplayName: Pilot vertical acceleration
|
||||||
|
// @Description: The vertical acceleration used when pilot is controlling the altitude
|
||||||
|
// @Units: cm/s/s
|
||||||
|
// @Range: 50 500
|
||||||
|
// @Increment: 10
|
||||||
|
// @User: Standard
|
||||||
|
GSCALAR(pilot_accel_z, "PILOT_ACCEL_Z", PILOT_ACCEL_Z_DEFAULT),
|
||||||
|
|
||||||
|
// @Param: FS_THR_ENABLE
|
||||||
|
// @DisplayName: Throttle Failsafe Enable
|
||||||
|
// @Description: The throttle failsafe allows you to configure a software failsafe activated by a setting on the throttle input channel
|
||||||
|
// @Values: 0:Disabled,1:Enabled always RTL,2:Enabled Continue with Mission in Auto Mode (Removed in 4.0+),3:Enabled always Land,4:Enabled always SmartRTL or RTL,5:Enabled always SmartRTL or Land
|
||||||
|
// @User: Standard
|
||||||
|
GSCALAR(failsafe_throttle, "FS_THR_ENABLE", FS_THR_ENABLED_ALWAYS_RTL),
|
||||||
|
|
||||||
|
// @Param: FS_THR_VALUE
|
||||||
|
// @DisplayName: Throttle Failsafe Value
|
||||||
|
// @Description: The PWM level in microseconds on channel 3 below which throttle failsafe triggers
|
||||||
|
// @Range: 910 1100
|
||||||
|
// @Units: PWM
|
||||||
|
// @Increment: 1
|
||||||
|
// @User: Standard
|
||||||
|
GSCALAR(failsafe_throttle_value, "FS_THR_VALUE", FS_THR_VALUE_DEFAULT),
|
||||||
|
|
||||||
|
// @Param: THR_DZ
|
||||||
|
// @DisplayName: Throttle deadzone
|
||||||
|
// @Description: The deadzone above and below mid throttle in PWM microseconds. Used in AltHold, Loiter, PosHold flight modes
|
||||||
|
// @User: Standard
|
||||||
|
// @Range: 0 300
|
||||||
|
// @Units: PWM
|
||||||
|
// @Increment: 1
|
||||||
|
GSCALAR(throttle_deadzone, "THR_DZ", THR_DZ_DEFAULT),
|
||||||
|
|
||||||
|
// @Param: FLTMODE1
|
||||||
|
// @DisplayName: Flight Mode 1
|
||||||
|
// @Description: Flight mode when Channel 5 pwm is <= 1230
|
||||||
|
// @Values: 0:Stabilize,1:Acro,2:AltHold,3:Auto,4:Guided,5:Loiter,6:RTL,7:Circle,9:Land,11:Drift,13:Sport,14:Flip,15:AutoTune,16:PosHold,17:Brake,18:Throw,19:Avoid_ADSB,20:Guided_NoGPS,21:Smart_RTL,22:FlowHold,23:Follow,24:ZigZag,25:SystemID,26:Heli_Autorotate
|
||||||
|
// @User: Standard
|
||||||
|
GSCALAR(flight_mode1, "FLTMODE1", (uint8_t)FLIGHT_MODE_1),
|
||||||
|
|
||||||
|
// @Param: FLTMODE2
|
||||||
|
// @DisplayName: Flight Mode 2
|
||||||
|
// @Description: Flight mode when Channel 5 pwm is >1230, <= 1360
|
||||||
|
// @Values: 0:Stabilize,1:Acro,2:AltHold,3:Auto,4:Guided,5:Loiter,6:RTL,7:Circle,9:Land,11:Drift,13:Sport,14:Flip,15:AutoTune,16:PosHold,17:Brake,18:Throw,19:Avoid_ADSB,20:Guided_NoGPS,21:Smart_RTL,22:FlowHold,23:Follow,24:ZigZag,25:SystemID,26:Heli_Autorotate
|
||||||
|
// @User: Standard
|
||||||
|
GSCALAR(flight_mode2, "FLTMODE2", (uint8_t)FLIGHT_MODE_2),
|
||||||
|
|
||||||
|
// @Param: FLTMODE3
|
||||||
|
// @DisplayName: Flight Mode 3
|
||||||
|
// @Description: Flight mode when Channel 5 pwm is >1360, <= 1490
|
||||||
|
// @Values: 0:Stabilize,1:Acro,2:AltHold,3:Auto,4:Guided,5:Loiter,6:RTL,7:Circle,9:Land,11:Drift,13:Sport,14:Flip,15:AutoTune,16:PosHold,17:Brake,18:Throw,19:Avoid_ADSB,20:Guided_NoGPS,21:Smart_RTL,22:FlowHold,23:Follow,24:ZigZag,25:SystemID,26:Heli_Autorotate
|
||||||
|
// @User: Standard
|
||||||
|
GSCALAR(flight_mode3, "FLTMODE3", (uint8_t)FLIGHT_MODE_3),
|
||||||
|
|
||||||
|
// @Param: FLTMODE4
|
||||||
|
// @DisplayName: Flight Mode 4
|
||||||
|
// @Description: Flight mode when Channel 5 pwm is >1490, <= 1620
|
||||||
|
// @Values: 0:Stabilize,1:Acro,2:AltHold,3:Auto,4:Guided,5:Loiter,6:RTL,7:Circle,9:Land,11:Drift,13:Sport,14:Flip,15:AutoTune,16:PosHold,17:Brake,18:Throw,19:Avoid_ADSB,20:Guided_NoGPS,21:Smart_RTL,22:FlowHold,23:Follow,24:ZigZag,25:SystemID,26:Heli_Autorotate
|
||||||
|
// @User: Standard
|
||||||
|
GSCALAR(flight_mode4, "FLTMODE4", (uint8_t)FLIGHT_MODE_4),
|
||||||
|
|
||||||
|
// @Param: FLTMODE5
|
||||||
|
// @DisplayName: Flight Mode 5
|
||||||
|
// @Description: Flight mode when Channel 5 pwm is >1620, <= 1749
|
||||||
|
// @Values: 0:Stabilize,1:Acro,2:AltHold,3:Auto,4:Guided,5:Loiter,6:RTL,7:Circle,9:Land,11:Drift,13:Sport,14:Flip,15:AutoTune,16:PosHold,17:Brake,18:Throw,19:Avoid_ADSB,20:Guided_NoGPS,21:Smart_RTL,22:FlowHold,23:Follow,24:ZigZag,25:SystemID,26:Heli_Autorotate
|
||||||
|
// @User: Standard
|
||||||
|
GSCALAR(flight_mode5, "FLTMODE5", (uint8_t)FLIGHT_MODE_5),
|
||||||
|
|
||||||
|
// @Param: FLTMODE6
|
||||||
|
// @DisplayName: Flight Mode 6
|
||||||
|
// @Description: Flight mode when Channel 5 pwm is >=1750
|
||||||
|
// @Values: 0:Stabilize,1:Acro,2:AltHold,3:Auto,4:Guided,5:Loiter,6:RTL,7:Circle,9:Land,11:Drift,13:Sport,14:Flip,15:AutoTune,16:PosHold,17:Brake,18:Throw,19:Avoid_ADSB,20:Guided_NoGPS,21:Smart_RTL,22:FlowHold,23:Follow,24:ZigZag,25:SystemID,26:Heli_Autorotate
|
||||||
|
// @User: Standard
|
||||||
|
GSCALAR(flight_mode6, "FLTMODE6", (uint8_t)FLIGHT_MODE_6),
|
||||||
|
|
||||||
|
// @Param: FLTMODE_CH
|
||||||
|
// @DisplayName: Flightmode channel
|
||||||
|
// @Description: RC Channel to use for flight mode control
|
||||||
|
// @Values: 0:Disabled,5:Channel5,6:Channel6,7:Channel7,8:Channel8
|
||||||
|
// @User: Advanced
|
||||||
|
GSCALAR(flight_mode_chan, "FLTMODE_CH", CH_MODE_DEFAULT),
|
||||||
|
|
||||||
|
// @Param: INITIAL_MODE
|
||||||
|
// @DisplayName: Initial flight mode
|
||||||
|
// @Description: This selects the mode to start in on boot. This is useful for when you want to start in AUTO mode on boot without a receiver.
|
||||||
|
// @Values: 0:Stabilize,1:Acro,2:AltHold,3:Auto,4:Guided,5:Loiter,6:RTL,7:Circle,9:Land,11:Drift,13:Sport,14:Flip,15:AutoTune,16:PosHold,17:Brake,18:Throw,19:Avoid_ADSB,20:Guided_NoGPS,21:Smart_RTL,22:FlowHold,23:Follow,24:ZigZag,25:SystemID,26:Heli_Autorotate
|
||||||
|
// @User: Advanced
|
||||||
|
GSCALAR(initial_mode, "INITIAL_MODE", (uint8_t)Mode::Number::MANUAL),
|
||||||
|
|
||||||
|
// @Param: LOG_BITMASK
|
||||||
|
// @DisplayName: Log bitmask
|
||||||
|
// @Description: 4 byte bitmap of log types to enable
|
||||||
|
// @Values: 830:Default,894:Default+RCIN,958:Default+IMU,1854:Default+Motors,-6146:NearlyAll-AC315,45054:NearlyAll,131071:All+FastATT,262142:All+MotBatt,393214:All+FastIMU,397310:All+FastIMU+PID,655358:All+FullIMU,0:Disabled
|
||||||
|
// @Bitmask: 0:ATTITUDE_FAST,1:ATTITUDE_MED,2:GPS,3:PM,4:CTUN,5:NTUN,6:RCIN,7:IMU,8:CMD,9:CURRENT,10:RCOUT,11:OPTFLOW,12:PID,13:COMPASS,14:INAV,15:CAMERA,17:MOTBATT,18:IMU_FAST,19:IMU_RAW
|
||||||
|
// @User: Standard
|
||||||
|
GSCALAR(log_bitmask, "LOG_BITMASK", DEFAULT_LOG_BITMASK),
|
||||||
|
|
||||||
|
// @Param: TUNE
|
||||||
|
// @DisplayName: Channel 6 Tuning
|
||||||
|
// @Description: Controls which parameters (normally PID gains) are being tuned with transmitter's channel 6 knob
|
||||||
|
// @User: Standard
|
||||||
|
// @Values: 0:None,1:Stab Roll/Pitch kP,4:Rate Roll/Pitch kP,5:Rate Roll/Pitch kI,21:Rate Roll/Pitch kD,3:Stab Yaw kP,6:Rate Yaw kP,26:Rate Yaw kD,56:Rate Yaw Filter,55:Motor Yaw Headroom,14:AltHold kP,7:Throttle Rate kP,34:Throttle Accel kP,35:Throttle Accel kI,36:Throttle Accel kD,12:Loiter Pos kP,22:Velocity XY kP,28:Velocity XY kI,10:WP Speed,25:Acro RollPitch kP,40:Acro Yaw kP,45:RC Feel,13:Heli Ext Gyro,38:Declination,39:Circle Rate,41:RangeFinder Gain,46:Rate Pitch kP,47:Rate Pitch kI,48:Rate Pitch kD,49:Rate Roll kP,50:Rate Roll kI,51:Rate Roll kD,52:Rate Pitch FF,53:Rate Roll FF,54:Rate Yaw FF,58:SysID Magnitude
|
||||||
|
GSCALAR(radio_tuning, "TUNE", 0),
|
||||||
|
|
||||||
|
// @Param: FRAME_TYPE
|
||||||
|
// @DisplayName: Frame Type (+, X, V, etc)
|
||||||
|
// @Description: Controls motor mixing for multiblimps. Not used for Tri or Traditional Heliblimps.
|
||||||
|
// @Values: 0:Plus, 1:X, 2:V, 3:H, 4:V-Tail, 5:A-Tail, 10:Y6B, 11:Y6F, 12:BetaFlightX, 13:DJIX, 14:ClockwiseX, 15: I, 18: BetaFlightXReversed
|
||||||
|
// @User: Standard
|
||||||
|
// @RebootRequired: True
|
||||||
|
GSCALAR(frame_type, "FRAME_TYPE", HAL_FRAME_TYPE_DEFAULT),
|
||||||
|
|
||||||
|
// @Group: ARMING_
|
||||||
|
// @Path: ../libraries/AP_Arming/AP_Arming.cpp
|
||||||
|
GOBJECT(arming, "ARMING_", AP_Arming_Blimp),
|
||||||
|
|
||||||
|
// @Param: DISARM_DELAY
|
||||||
|
// @DisplayName: Disarm delay
|
||||||
|
// @Description: Delay before automatic disarm in seconds. A value of zero disables auto disarm.
|
||||||
|
// @Units: s
|
||||||
|
// @Range: 0 127
|
||||||
|
// @User: Advanced
|
||||||
|
GSCALAR(disarm_delay, "DISARM_DELAY", AUTO_DISARMING_DELAY),
|
||||||
|
|
||||||
|
// @Param: ANGLE_MAX
|
||||||
|
// @DisplayName: Angle Max
|
||||||
|
// @Description: Maximum lean angle in all flight modes
|
||||||
|
// @Units: cdeg
|
||||||
|
// @Range: 1000 8000
|
||||||
|
// @User: Advanced
|
||||||
|
ASCALAR(angle_max, "ANGLE_MAX", DEFAULT_ANGLE_MAX),
|
||||||
|
|
||||||
|
// @Param: PHLD_BRAKE_RATE
|
||||||
|
// @DisplayName: PosHold braking rate
|
||||||
|
// @Description: PosHold flight mode's rotation rate during braking in deg/sec
|
||||||
|
// @Units: deg/s
|
||||||
|
// @Range: 4 12
|
||||||
|
// @User: Advanced
|
||||||
|
GSCALAR(poshold_brake_rate, "PHLD_BRAKE_RATE", POSHOLD_BRAKE_RATE_DEFAULT),
|
||||||
|
|
||||||
|
// @Param: PHLD_BRAKE_ANGLE
|
||||||
|
// @DisplayName: PosHold braking angle max
|
||||||
|
// @Description: PosHold flight mode's max lean angle during braking in centi-degrees
|
||||||
|
// @Units: cdeg
|
||||||
|
// @Range: 2000 4500
|
||||||
|
// @User: Advanced
|
||||||
|
GSCALAR(poshold_brake_angle_max, "PHLD_BRAKE_ANGLE", POSHOLD_BRAKE_ANGLE_DEFAULT),
|
||||||
|
|
||||||
|
// @Param: LAND_REPOSITION
|
||||||
|
// @DisplayName: Land repositioning
|
||||||
|
// @Description: Enables user input during LAND mode, the landing phase of RTL, and auto mode landings.
|
||||||
|
// @Values: 0:No repositioning, 1:Repositioning
|
||||||
|
// @User: Advanced
|
||||||
|
GSCALAR(land_repositioning, "LAND_REPOSITION", LAND_REPOSITION_DEFAULT),
|
||||||
|
|
||||||
|
// @Param: FS_EKF_ACTION
|
||||||
|
// @DisplayName: EKF Failsafe Action
|
||||||
|
// @Description: Controls the action that will be taken when an EKF failsafe is invoked
|
||||||
|
// @Values: 1:Land, 2:AltHold, 3:Land even in Stabilize
|
||||||
|
// @User: Advanced
|
||||||
|
GSCALAR(fs_ekf_action, "FS_EKF_ACTION", FS_EKF_ACTION_DEFAULT),
|
||||||
|
|
||||||
|
// @Param: FS_EKF_THRESH
|
||||||
|
// @DisplayName: EKF failsafe variance threshold
|
||||||
|
// @Description: Allows setting the maximum acceptable compass and velocity variance
|
||||||
|
// @Values: 0.6:Strict, 0.8:Default, 1.0:Relaxed
|
||||||
|
// @User: Advanced
|
||||||
|
GSCALAR(fs_ekf_thresh, "FS_EKF_THRESH", FS_EKF_THRESHOLD_DEFAULT),
|
||||||
|
|
||||||
|
// @Param: FS_CRASH_CHECK
|
||||||
|
// @DisplayName: Crash check enable
|
||||||
|
// @Description: This enables automatic crash checking. When enabled the motors will disarm if a crash is detected.
|
||||||
|
// @Values: 0:Disabled, 1:Enabled
|
||||||
|
// @User: Advanced
|
||||||
|
GSCALAR(fs_crash_check, "FS_CRASH_CHECK", 1),
|
||||||
|
|
||||||
|
// @Param: RC_SPEED
|
||||||
|
// @DisplayName: ESC Update Speed
|
||||||
|
// @Description: This is the speed in Hertz that your ESCs will receive updates
|
||||||
|
// @Units: Hz
|
||||||
|
// @Range: 50 490
|
||||||
|
// @Increment: 1
|
||||||
|
// @User: Advanced
|
||||||
|
GSCALAR(rc_speed, "RC_SPEED", RC_FAST_SPEED),
|
||||||
|
|
||||||
|
// @Param: ACRO_RP_P
|
||||||
|
// @DisplayName: Acro Roll and Pitch P gain
|
||||||
|
// @Description: Converts pilot roll and pitch into a desired rate of rotation in ACRO and SPORT mode. Higher values mean faster rate of rotation.
|
||||||
|
// @Range: 1 10
|
||||||
|
// @User: Standard
|
||||||
|
GSCALAR(acro_rp_p, "ACRO_RP_P", ACRO_RP_P),
|
||||||
|
|
||||||
|
// @Param: ACRO_YAW_P
|
||||||
|
// @DisplayName: Acro Yaw P gain
|
||||||
|
// @Description: Converts pilot yaw input into a desired rate of rotation. Higher values mean faster rate of rotation.
|
||||||
|
// @Range: 1 10
|
||||||
|
// @User: Standard
|
||||||
|
GSCALAR(acro_yaw_p, "ACRO_YAW_P", ACRO_YAW_P),
|
||||||
|
|
||||||
|
// variables not in the g class which contain EEPROM saved variables
|
||||||
|
|
||||||
|
// @Group: RELAY_
|
||||||
|
// @Path: ../libraries/AP_Relay/AP_Relay.cpp
|
||||||
|
GOBJECT(relay, "RELAY_", AP_Relay),
|
||||||
|
|
||||||
|
// @Group: COMPASS_
|
||||||
|
// @Path: ../libraries/AP_Compass/AP_Compass.cpp
|
||||||
|
GOBJECT(compass, "COMPASS_", Compass),
|
||||||
|
|
||||||
|
// @Group: INS_
|
||||||
|
// @Path: ../libraries/AP_InertialSensor/AP_InertialSensor.cpp
|
||||||
|
GOBJECT(ins, "INS_", AP_InertialSensor),
|
||||||
|
|
||||||
|
// // @Group: WPNAV_
|
||||||
|
// // @Path: ../libraries/AC_WPNav/AC_WPNav.cpp
|
||||||
|
// GOBJECTPTR(wp_nav, "WPNAV_", AC_WPNav),
|
||||||
|
|
||||||
|
// // @Group: LOIT_
|
||||||
|
// // @Path: ../libraries/AC_WPNav/AC_Loiter.cpp
|
||||||
|
// GOBJECTPTR(loiter_nav, "LOIT_", AC_Loiter),
|
||||||
|
|
||||||
|
// @Group: ATC_
|
||||||
|
// @Path: ../libraries/AC_AttitudeControl/AC_AttitudeControl.cpp,../libraries/AC_AttitudeControl/AC_AttitudeControl_Multi.cpp,../libraries/AC_AttitudeControl/AC_AttitudeControl_Heli.cpp
|
||||||
|
// #if FRAME_CONFIG == HELI_FRAME
|
||||||
|
// GOBJECTPTR(attitude_control, "ATC_", AC_AttitudeControl_Heli),
|
||||||
|
// #else
|
||||||
|
// GOBJECTPTR(attitude_control, "ATC_", AC_AttitudeControl_Multi),
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// @Group: PSC
|
||||||
|
// @Path: ../libraries/AC_AttitudeControl/AC_PosControl.cpp
|
||||||
|
// GOBJECTPTR(pos_control, "PSC", AC_PosControl),
|
||||||
|
|
||||||
|
// @Group: SR0_
|
||||||
|
// @Path: GCS_Mavlink.cpp
|
||||||
|
GOBJECTN(_gcs.chan_parameters[0], gcs0, "SR0_", GCS_MAVLINK_Parameters),
|
||||||
|
|
||||||
|
#if MAVLINK_COMM_NUM_BUFFERS >= 2
|
||||||
|
// @Group: SR1_
|
||||||
|
// @Path: GCS_Mavlink.cpp
|
||||||
|
GOBJECTN(_gcs.chan_parameters[1], gcs1, "SR1_", GCS_MAVLINK_Parameters),
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MAVLINK_COMM_NUM_BUFFERS >= 3
|
||||||
|
// @Group: SR2_
|
||||||
|
// @Path: GCS_Mavlink.cpp
|
||||||
|
GOBJECTN(_gcs.chan_parameters[2], gcs2, "SR2_", GCS_MAVLINK_Parameters),
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MAVLINK_COMM_NUM_BUFFERS >= 4
|
||||||
|
// @Group: SR3_
|
||||||
|
// @Path: GCS_Mavlink.cpp
|
||||||
|
GOBJECTN(_gcs.chan_parameters[3], gcs3, "SR3_", GCS_MAVLINK_Parameters),
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MAVLINK_COMM_NUM_BUFFERS >= 5
|
||||||
|
// @Group: SR4_
|
||||||
|
// @Path: GCS_Mavlink.cpp
|
||||||
|
GOBJECTN(_gcs.chan_parameters[4], gcs4, "SR4_", GCS_MAVLINK_Parameters),
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MAVLINK_COMM_NUM_BUFFERS >= 6
|
||||||
|
// @Group: SR5_
|
||||||
|
// @Path: GCS_Mavlink.cpp
|
||||||
|
GOBJECTN(_gcs.chan_parameters[5], gcs5, "SR5_", GCS_MAVLINK_Parameters),
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MAVLINK_COMM_NUM_BUFFERS >= 7
|
||||||
|
// @Group: SR6_
|
||||||
|
// @Path: GCS_Mavlink.cpp
|
||||||
|
GOBJECTN(_gcs.chan_parameters[6], gcs6, "SR6_", GCS_MAVLINK_Parameters),
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// @Group: AHRS_
|
||||||
|
// @Path: ../libraries/AP_AHRS/AP_AHRS.cpp
|
||||||
|
GOBJECT(ahrs, "AHRS_", AP_AHRS),
|
||||||
|
|
||||||
|
// @Group: LOG
|
||||||
|
// @Path: ../libraries/AP_Logger/AP_Logger.cpp
|
||||||
|
GOBJECT(logger, "LOG", AP_Logger),
|
||||||
|
|
||||||
|
// @Group: BATT
|
||||||
|
// @Path: ../libraries/AP_BattMonitor/AP_BattMonitor.cpp
|
||||||
|
GOBJECT(battery, "BATT", AP_BattMonitor),
|
||||||
|
|
||||||
|
// @Group: BRD_
|
||||||
|
// @Path: ../libraries/AP_BoardConfig/AP_BoardConfig.cpp
|
||||||
|
GOBJECT(BoardConfig, "BRD_", AP_BoardConfig),
|
||||||
|
|
||||||
|
#if HAL_MAX_CAN_PROTOCOL_DRIVERS
|
||||||
|
// @Group: CAN_
|
||||||
|
// @Path: ../libraries/AP_CANManager/AP_CANManager.cpp
|
||||||
|
GOBJECT(can_mgr, "CAN_", AP_CANManager),
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CONFIG_HAL_BOARD == HAL_BOARD_SITL
|
||||||
|
GOBJECT(sitl, "SIM_", SITL::SITL),
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// @Group: BARO
|
||||||
|
// @Path: ../libraries/AP_Baro/AP_Baro.cpp
|
||||||
|
GOBJECT(barometer, "BARO", AP_Baro),
|
||||||
|
|
||||||
|
// GPS driver
|
||||||
|
// @Group: GPS_
|
||||||
|
// @Path: ../libraries/AP_GPS/AP_GPS.cpp
|
||||||
|
GOBJECT(gps, "GPS_", AP_GPS),
|
||||||
|
|
||||||
|
// @Group: SCHED_
|
||||||
|
// @Path: ../libraries/AP_Scheduler/AP_Scheduler.cpp
|
||||||
|
GOBJECT(scheduler, "SCHED_", AP_Scheduler),
|
||||||
|
|
||||||
|
// @Group: RCMAP_
|
||||||
|
// @Path: ../libraries/AP_RCMapper/AP_RCMapper.cpp
|
||||||
|
GOBJECT(rcmap, "RCMAP_", RCMapper),
|
||||||
|
|
||||||
|
#if HAL_NAVEKF2_AVAILABLE
|
||||||
|
// @Group: EK2_
|
||||||
|
// @Path: ../libraries/AP_NavEKF2/AP_NavEKF2.cpp
|
||||||
|
GOBJECTN(ahrs.EKF2, NavEKF2, "EK2_", NavEKF2),
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if HAL_NAVEKF3_AVAILABLE
|
||||||
|
// @Group: EK3_
|
||||||
|
// @Path: ../libraries/AP_NavEKF3/AP_NavEKF3.cpp
|
||||||
|
GOBJECTN(ahrs.EKF3, NavEKF3, "EK3_", NavEKF3),
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// @Group: RSSI_
|
||||||
|
// @Path: ../libraries/AP_RSSI/AP_RSSI.cpp
|
||||||
|
GOBJECT(rssi, "RSSI_", AP_RSSI),
|
||||||
|
|
||||||
|
// @Group: NTF_
|
||||||
|
// @Path: ../libraries/AP_Notify/AP_Notify.cpp
|
||||||
|
GOBJECT(notify, "NTF_", AP_Notify),
|
||||||
|
|
||||||
|
// @Group:
|
||||||
|
// @Path: Parameters.cpp
|
||||||
|
GOBJECT(g2, "", ParametersG2),
|
||||||
|
|
||||||
|
// @Group: FINS_
|
||||||
|
// @Path: Fins.cpp
|
||||||
|
GOBJECTPTR(motors, "FINS_", Fins),
|
||||||
|
|
||||||
|
// @Group:
|
||||||
|
// @Path: ../libraries/AP_Vehicle/AP_Vehicle.cpp
|
||||||
|
{ AP_PARAM_GROUP, "", Parameters::k_param_vehicle, (const void *)&blimp, {group_info : AP_Vehicle::var_info} },
|
||||||
|
|
||||||
|
AP_VAREND
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
2nd group of parameters
|
||||||
|
*/
|
||||||
|
const AP_Param::GroupInfo ParametersG2::var_info[] = {
|
||||||
|
|
||||||
|
// @Param: WP_NAVALT_MIN
|
||||||
|
// @DisplayName: Minimum navigation altitude
|
||||||
|
// @Description: This is the altitude in meters above which for navigation can begin. This applies in auto takeoff and auto landing.
|
||||||
|
// @Range: 0 5
|
||||||
|
// @User: Standard
|
||||||
|
AP_GROUPINFO("WP_NAVALT_MIN", 1, ParametersG2, wp_navalt_min, 0),
|
||||||
|
|
||||||
|
// @Param: DEV_OPTIONS
|
||||||
|
// @DisplayName: Development options
|
||||||
|
// @Description: Bitmask of developer options. The meanings of the bit fields in this parameter may vary at any time. Developers should check the source code for current meaning
|
||||||
|
// @Bitmask: 0:ADSBMavlinkProcessing,1:DevOptionVFR_HUDRelativeAlt,2:SetAttitudeTarget_ThrustAsThrust
|
||||||
|
// @User: Advanced
|
||||||
|
AP_GROUPINFO("DEV_OPTIONS", 7, ParametersG2, dev_options, 0),
|
||||||
|
|
||||||
|
// @Param: ACRO_Y_EXPO
|
||||||
|
// @DisplayName: Acro Yaw Expo
|
||||||
|
// @Description: Acro yaw expo to allow faster rotation when stick at edges
|
||||||
|
// @Values: 0:Disabled,0.1:Very Low,0.2:Low,0.3:Medium,0.4:High,0.5:Very High
|
||||||
|
// @Range: -0.5 1.0
|
||||||
|
// @User: Advanced
|
||||||
|
AP_GROUPINFO("ACRO_Y_EXPO", 9, ParametersG2, acro_y_expo, ACRO_Y_EXPO_DEFAULT),
|
||||||
|
|
||||||
|
|
||||||
|
// @Param: SYSID_ENFORCE
|
||||||
|
// @DisplayName: GCS sysid enforcement
|
||||||
|
// @Description: This controls whether packets from other than the expected GCS system ID will be accepted
|
||||||
|
// @Values: 0:NotEnforced,1:Enforced
|
||||||
|
// @User: Advanced
|
||||||
|
AP_GROUPINFO("SYSID_ENFORCE", 11, ParametersG2, sysid_enforce, 0),
|
||||||
|
|
||||||
|
#if STATS_ENABLED == ENABLED
|
||||||
|
// @Group: STAT
|
||||||
|
// @Path: ../libraries/AP_Stats/AP_Stats.cpp
|
||||||
|
AP_SUBGROUPINFO(stats, "STAT", 12, ParametersG2, AP_Stats),
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// @Param: FRAME_CLASS
|
||||||
|
// @DisplayName: Frame Class
|
||||||
|
// @Description: Controls major frame class for multiblimp component
|
||||||
|
// @Values: 0:Undefined, 1:Quad, 2:Hexa, 3:Octa, 4:OctaQuad, 5:Y6, 6:Heli, 7:Tri, 8:SingleCopter, 9:CoaxCopter, 10:BiCopter, 11:Heli_Dual, 12:DodecaHexa, 13:HeliQuad, 14:Deca
|
||||||
|
// @User: Standard
|
||||||
|
// @RebootRequired: True
|
||||||
|
AP_GROUPINFO("FRAME_CLASS", 15, ParametersG2, frame_class, DEFAULT_FRAME_CLASS),
|
||||||
|
|
||||||
|
// @Group: SERVO
|
||||||
|
// @Path: ../libraries/SRV_Channel/SRV_Channels.cpp
|
||||||
|
AP_SUBGROUPINFO(servo_channels, "SERVO", 16, ParametersG2, SRV_Channels),
|
||||||
|
|
||||||
|
// @Group: RC
|
||||||
|
// @Path: ../libraries/RC_Channel/RC_Channels_VarInfo.h
|
||||||
|
AP_SUBGROUPINFO(rc_channels, "RC", 17, ParametersG2, RC_Channels_Blimp),
|
||||||
|
|
||||||
|
// // 18 was used by AP_VisualOdom
|
||||||
|
|
||||||
|
// // @Group: TCAL
|
||||||
|
// // @Path: ../libraries/AP_TempCalibration/AP_TempCalibration.cpp
|
||||||
|
// AP_SUBGROUPINFO(temp_calibration, "TCAL", 19, ParametersG2, AP_TempCalibration),
|
||||||
|
|
||||||
|
// @Param: PILOT_SPEED_DN
|
||||||
|
// @DisplayName: Pilot maximum vertical speed descending
|
||||||
|
// @Description: The maximum vertical descending velocity the pilot may request in cm/s
|
||||||
|
// @Units: cm/s
|
||||||
|
// @Range: 50 500
|
||||||
|
// @Increment: 10
|
||||||
|
// @User: Standard
|
||||||
|
AP_GROUPINFO("PILOT_SPEED_DN", 24, ParametersG2, pilot_speed_dn, 0),
|
||||||
|
|
||||||
|
// @Param: LAND_ALT_LOW
|
||||||
|
// @DisplayName: Land alt low
|
||||||
|
// @Description: Altitude during Landing at which vehicle slows to LAND_SPEED
|
||||||
|
// @Units: cm
|
||||||
|
// @Range: 100 10000
|
||||||
|
// @Increment: 10
|
||||||
|
// @User: Advanced
|
||||||
|
AP_GROUPINFO("LAND_ALT_LOW", 25, ParametersG2, land_alt_low, 1000),
|
||||||
|
|
||||||
|
#ifdef ENABLE_SCRIPTING
|
||||||
|
// @Group: SCR_
|
||||||
|
// @Path: ../libraries/AP_Scripting/AP_Scripting.cpp
|
||||||
|
AP_SUBGROUPINFO(scripting, "SCR_", 30, ParametersG2, AP_Scripting),
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// @Param: TUNE_MIN
|
||||||
|
// @DisplayName: Tuning minimum
|
||||||
|
// @Description: Minimum value that the parameter currently being tuned with the transmitter's channel 6 knob will be set to
|
||||||
|
// @User: Standard
|
||||||
|
AP_GROUPINFO("TUNE_MIN", 31, ParametersG2, tuning_min, 0),
|
||||||
|
|
||||||
|
// @Param: TUNE_MAX
|
||||||
|
// @DisplayName: Tuning maximum
|
||||||
|
// @Description: Maximum value that the parameter currently being tuned with the transmitter's channel 6 knob will be set to
|
||||||
|
// @User: Standard
|
||||||
|
AP_GROUPINFO("TUNE_MAX", 32, ParametersG2, tuning_max, 0),
|
||||||
|
|
||||||
|
// @Param: FS_VIBE_ENABLE
|
||||||
|
// @DisplayName: Vibration Failsafe enable
|
||||||
|
// @Description: This enables the vibration failsafe which will use modified altitude estimation and control during high vibrations
|
||||||
|
// @Values: 0:Disabled, 1:Enabled
|
||||||
|
// @User: Standard
|
||||||
|
AP_GROUPINFO("FS_VIBE_ENABLE", 35, ParametersG2, fs_vibe_enabled, 1),
|
||||||
|
|
||||||
|
// @Param: FS_OPTIONS
|
||||||
|
// @DisplayName: Failsafe options bitmask
|
||||||
|
// @Description: Bitmask of additional options for battery, radio, & GCS failsafes. 0 (default) disables all options.
|
||||||
|
// @Values: 0:Disabled, 1:Continue if in Auto on RC failsafe only, 2:Continue if in Auto on GCS failsafe only, 3:Continue if in Auto on RC and/or GCS failsafe, 4:Continue if in Guided on RC failsafe only, 8:Continue if landing on any failsafe, 16:Continue if in pilot controlled modes on GCS failsafe, 19:Continue if in Auto on RC and/or GCS failsafe and continue if in pilot controlled modes on GCS failsafe
|
||||||
|
// @Bitmask: 0:Continue if in Auto on RC failsafe, 1:Continue if in Auto on GCS failsafe, 2:Continue if in Guided on RC failsafe, 3:Continue if landing on any failsafe, 4:Continue if in pilot controlled modes on GCS failsafe, 5:Release Gripper
|
||||||
|
// @User: Advanced
|
||||||
|
AP_GROUPINFO("FS_OPTIONS", 36, ParametersG2, fs_options, (float)Blimp::FailsafeOption::GCS_CONTINUE_IF_PILOT_CONTROL),
|
||||||
|
|
||||||
|
// @Param: FS_GCS_TIMEOUT
|
||||||
|
// @DisplayName: GCS failsafe timeout
|
||||||
|
// @Description: Timeout before triggering the GCS failsafe
|
||||||
|
// @Units: s
|
||||||
|
// @Range: 2 120
|
||||||
|
// @Increment: 1
|
||||||
|
// @User: Standard
|
||||||
|
AP_GROUPINFO("FS_GCS_TIMEOUT", 42, ParametersG2, fs_gcs_timeout, 5),
|
||||||
|
|
||||||
|
AP_GROUPEND
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
constructor for g2 object
|
||||||
|
*/
|
||||||
|
ParametersG2::ParametersG2(void)
|
||||||
|
// : temp_calibration() // this doesn't actually need constructing, but removing it here is problematic syntax-wise
|
||||||
|
{
|
||||||
|
AP_Param::setup_object_defaults(this, var_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Blimp::load_parameters(void)
|
||||||
|
{
|
||||||
|
if (!AP_Param::check_var_info()) {
|
||||||
|
hal.console->printf("Bad var table\n");
|
||||||
|
AP_HAL::panic("Bad var table");
|
||||||
|
}
|
||||||
|
|
||||||
|
// disable centrifugal force correction, it will be enabled as part of the arming process
|
||||||
|
ahrs.set_correct_centrifugal(false);
|
||||||
|
hal.util->set_soft_armed(false);
|
||||||
|
|
||||||
|
if (!g.format_version.load() ||
|
||||||
|
g.format_version != Parameters::k_format_version) {
|
||||||
|
|
||||||
|
// erase all parameters
|
||||||
|
hal.console->printf("Firmware change: erasing EEPROM...\n");
|
||||||
|
StorageManager::erase();
|
||||||
|
AP_Param::erase_all();
|
||||||
|
|
||||||
|
// save the current format version
|
||||||
|
g.format_version.set_and_save(Parameters::k_format_version);
|
||||||
|
hal.console->printf("done.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t before = micros();
|
||||||
|
// Load all auto-loaded EEPROM variables
|
||||||
|
AP_Param::load_all();
|
||||||
|
|
||||||
|
hal.console->printf("load_all took %uus\n", (unsigned)(micros() - before));
|
||||||
|
|
||||||
|
// setup AP_Param frame type flags
|
||||||
|
AP_Param::set_frame_type_flags(AP_PARAM_FRAME_COPTER);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,529 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <AP_Common/AP_Common.h>
|
||||||
|
#include "RC_Channel.h"
|
||||||
|
|
||||||
|
// Global parameter class.
|
||||||
|
//
|
||||||
|
class Parameters
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// The version of the layout as described by the parameter enum.
|
||||||
|
//
|
||||||
|
// When changing the parameter enum in an incompatible fashion, this
|
||||||
|
// value should be incremented by one.
|
||||||
|
//
|
||||||
|
// The increment will prevent old parameters from being used incorrectly
|
||||||
|
// by newer code.
|
||||||
|
//
|
||||||
|
static const uint16_t k_format_version = 120;
|
||||||
|
|
||||||
|
// Parameter identities.
|
||||||
|
//
|
||||||
|
// The enumeration defined here is used to ensure that every parameter
|
||||||
|
// or parameter group has a unique ID number. This number is used by
|
||||||
|
// AP_Param to store and locate parameters in EEPROM.
|
||||||
|
//
|
||||||
|
// Note that entries without a number are assigned the next number after
|
||||||
|
// the entry preceding them. When adding new entries, ensure that they
|
||||||
|
// don't overlap.
|
||||||
|
//
|
||||||
|
// Try to group related variables together, and assign them a set
|
||||||
|
// range in the enumeration. Place these groups in numerical order
|
||||||
|
// at the end of the enumeration.
|
||||||
|
//
|
||||||
|
// WARNING: Care should be taken when editing this enumeration as the
|
||||||
|
// AP_Param load/save code depends on the values here to identify
|
||||||
|
// variables saved in EEPROM.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
enum {
|
||||||
|
// Layout version number, always key zero.
|
||||||
|
//
|
||||||
|
k_param_format_version = 0,
|
||||||
|
k_param_software_type, // deprecated
|
||||||
|
k_param_ins_old, // *** Deprecated, remove with next eeprom number change
|
||||||
|
k_param_ins, // libraries/AP_InertialSensor variables
|
||||||
|
k_param_NavEKF2_old, // deprecated - remove
|
||||||
|
k_param_NavEKF2,
|
||||||
|
k_param_g2, // 2nd block of parameters
|
||||||
|
k_param_NavEKF3,
|
||||||
|
k_param_can_mgr,
|
||||||
|
k_param_osd,
|
||||||
|
|
||||||
|
// simulation
|
||||||
|
k_param_sitl = 10,
|
||||||
|
|
||||||
|
// barometer object (needed for SITL)
|
||||||
|
k_param_barometer,
|
||||||
|
|
||||||
|
// scheduler object (for debugging)
|
||||||
|
k_param_scheduler,
|
||||||
|
|
||||||
|
// relay object
|
||||||
|
k_param_relay,
|
||||||
|
|
||||||
|
// (old) EPM object
|
||||||
|
k_param_epm_unused,
|
||||||
|
|
||||||
|
// BoardConfig object
|
||||||
|
k_param_BoardConfig,
|
||||||
|
|
||||||
|
// GPS object
|
||||||
|
k_param_gps,
|
||||||
|
|
||||||
|
// Parachute object
|
||||||
|
k_param_parachute,
|
||||||
|
|
||||||
|
// Landing gear object
|
||||||
|
k_param_landinggear, // 18
|
||||||
|
|
||||||
|
// Input Management object
|
||||||
|
k_param_input_manager, // 19
|
||||||
|
|
||||||
|
// Misc
|
||||||
|
//
|
||||||
|
k_param_log_bitmask_old = 20, // Deprecated
|
||||||
|
k_param_log_last_filenumber, // *** Deprecated - remove
|
||||||
|
// with next eeprom number
|
||||||
|
// change
|
||||||
|
k_param_toy_yaw_rate, // deprecated - remove
|
||||||
|
k_param_crosstrack_min_distance, // deprecated - remove with next eeprom number change
|
||||||
|
k_param_rssi_pin, // unused, replaced by rssi_ library parameters
|
||||||
|
k_param_throttle_accel_enabled, // deprecated - remove
|
||||||
|
k_param_wp_yaw_behavior,
|
||||||
|
k_param_acro_trainer,
|
||||||
|
k_param_pilot_speed_up, // renamed from k_param_pilot_velocity_z_max
|
||||||
|
k_param_circle_rate, // deprecated - remove
|
||||||
|
k_param_rangefinder_gain,
|
||||||
|
k_param_ch8_option_old, // deprecated
|
||||||
|
k_param_arming_check_old, // deprecated - remove
|
||||||
|
k_param_sprayer,
|
||||||
|
k_param_angle_max,
|
||||||
|
k_param_gps_hdop_good,
|
||||||
|
k_param_battery,
|
||||||
|
k_param_fs_batt_mah, // unused - moved to AP_BattMonitor
|
||||||
|
k_param_angle_rate_max, // remove
|
||||||
|
k_param_rssi_range, // unused, replaced by rssi_ library parameters
|
||||||
|
k_param_rc_feel_rp, // deprecated
|
||||||
|
k_param_NavEKF, // deprecated - remove
|
||||||
|
k_param_mission, // mission library
|
||||||
|
k_param_rc_13_old,
|
||||||
|
k_param_rc_14_old,
|
||||||
|
k_param_rally,
|
||||||
|
k_param_poshold_brake_rate,
|
||||||
|
k_param_poshold_brake_angle_max,
|
||||||
|
k_param_pilot_accel_z,
|
||||||
|
k_param_serial0_baud, // deprecated - remove
|
||||||
|
k_param_serial1_baud, // deprecated - remove
|
||||||
|
k_param_serial2_baud, // deprecated - remove
|
||||||
|
k_param_land_repositioning,
|
||||||
|
k_param_rangefinder, // rangefinder object
|
||||||
|
k_param_fs_ekf_thresh,
|
||||||
|
k_param_terrain,
|
||||||
|
k_param_acro_rp_expo,
|
||||||
|
k_param_throttle_deadzone,
|
||||||
|
k_param_optflow,
|
||||||
|
k_param_dcmcheck_thresh, // deprecated - remove
|
||||||
|
k_param_log_bitmask,
|
||||||
|
k_param_cli_enabled_old, // deprecated - remove
|
||||||
|
k_param_throttle_filt,
|
||||||
|
k_param_throttle_behavior,
|
||||||
|
k_param_pilot_takeoff_alt, // 64
|
||||||
|
|
||||||
|
// 65: AP_Limits Library
|
||||||
|
k_param_limits = 65, // deprecated - remove
|
||||||
|
k_param_gpslock_limit, // deprecated - remove
|
||||||
|
k_param_geofence_limit, // deprecated - remove
|
||||||
|
k_param_altitude_limit, // deprecated - remove
|
||||||
|
k_param_fence,
|
||||||
|
k_param_gps_glitch, // deprecated
|
||||||
|
k_param_baro_glitch, // 71 - deprecated
|
||||||
|
|
||||||
|
// AP_ADSB Library
|
||||||
|
k_param_adsb, // 72
|
||||||
|
k_param_notify, // 73
|
||||||
|
|
||||||
|
// 74: precision landing object
|
||||||
|
k_param_precland = 74,
|
||||||
|
|
||||||
|
//
|
||||||
|
// 75: Singlecopter, CoaxBlimp
|
||||||
|
//
|
||||||
|
k_param_single_servo_1 = 75, // remove
|
||||||
|
k_param_single_servo_2, // remove
|
||||||
|
k_param_single_servo_3, // remove
|
||||||
|
k_param_single_servo_4, // 78 - remove
|
||||||
|
|
||||||
|
//
|
||||||
|
// 80: Heli
|
||||||
|
//
|
||||||
|
k_param_heli_servo_1 = 80, // remove
|
||||||
|
k_param_heli_servo_2, // remove
|
||||||
|
k_param_heli_servo_3, // remove
|
||||||
|
k_param_heli_servo_4, // remove
|
||||||
|
k_param_heli_pitch_ff, // remove
|
||||||
|
k_param_heli_roll_ff, // remove
|
||||||
|
k_param_heli_yaw_ff, // remove
|
||||||
|
k_param_heli_stab_col_min, // remove
|
||||||
|
k_param_heli_stab_col_max, // remove
|
||||||
|
k_param_heli_servo_rsc, // 89 = full! - remove
|
||||||
|
|
||||||
|
//
|
||||||
|
// 90: misc2
|
||||||
|
//
|
||||||
|
k_param_motors = 90,
|
||||||
|
k_param_disarm_delay,
|
||||||
|
k_param_fs_crash_check,
|
||||||
|
k_param_throw_motor_start,
|
||||||
|
k_param_rtl_alt_type,
|
||||||
|
k_param_avoid,
|
||||||
|
k_param_avoidance_adsb,
|
||||||
|
|
||||||
|
// 97: RSSI
|
||||||
|
k_param_rssi = 97,
|
||||||
|
|
||||||
|
//
|
||||||
|
// 100: Inertial Nav
|
||||||
|
//
|
||||||
|
k_param_inertial_nav = 100, // deprecated
|
||||||
|
k_param_wp_nav,
|
||||||
|
k_param_attitude_control,
|
||||||
|
k_param_pos_control,
|
||||||
|
k_param_circle_nav,
|
||||||
|
k_param_loiter_nav, // 105
|
||||||
|
|
||||||
|
// 110: Telemetry control
|
||||||
|
//
|
||||||
|
k_param_gcs0 = 110,
|
||||||
|
k_param_gcs1,
|
||||||
|
k_param_sysid_this_mav,
|
||||||
|
k_param_sysid_my_gcs,
|
||||||
|
k_param_serial1_baud_old, // deprecated
|
||||||
|
k_param_telem_delay,
|
||||||
|
k_param_gcs2,
|
||||||
|
k_param_serial2_baud_old, // deprecated
|
||||||
|
k_param_serial2_protocol, // deprecated
|
||||||
|
k_param_serial_manager,
|
||||||
|
k_param_ch9_option_old,
|
||||||
|
k_param_ch10_option_old,
|
||||||
|
k_param_ch11_option_old,
|
||||||
|
k_param_ch12_option_old,
|
||||||
|
k_param_takeoff_trigger_dz_old,
|
||||||
|
k_param_gcs3,
|
||||||
|
k_param_gcs_pid_mask, // 126
|
||||||
|
k_param_gcs4,
|
||||||
|
k_param_gcs5,
|
||||||
|
k_param_gcs6,
|
||||||
|
|
||||||
|
//
|
||||||
|
// 135 : reserved for Solo until features merged with master
|
||||||
|
//
|
||||||
|
k_param_rtl_speed_cms = 135,
|
||||||
|
k_param_fs_batt_curr_rtl,
|
||||||
|
k_param_rtl_cone_slope, // 137
|
||||||
|
|
||||||
|
//
|
||||||
|
// 140: Sensor parameters
|
||||||
|
//
|
||||||
|
k_param_imu = 140, // deprecated - can be deleted
|
||||||
|
k_param_battery_monitoring = 141, // deprecated - can be deleted
|
||||||
|
k_param_volt_div_ratio, // deprecated - can be deleted
|
||||||
|
k_param_curr_amp_per_volt, // deprecated - can be deleted
|
||||||
|
k_param_input_voltage, // deprecated - can be deleted
|
||||||
|
k_param_pack_capacity, // deprecated - can be deleted
|
||||||
|
k_param_compass_enabled_deprecated,
|
||||||
|
k_param_compass,
|
||||||
|
k_param_rangefinder_enabled_old, // deprecated
|
||||||
|
k_param_frame_type,
|
||||||
|
k_param_optflow_enabled, // deprecated
|
||||||
|
k_param_fs_batt_voltage, // unused - moved to AP_BattMonitor
|
||||||
|
k_param_ch7_option_old,
|
||||||
|
k_param_auto_slew_rate, // deprecated - can be deleted
|
||||||
|
k_param_rangefinder_type_old, // deprecated
|
||||||
|
k_param_axis_enabled = 157, // deprecated - remove with next eeprom number change
|
||||||
|
k_param_copter_leds_mode, // deprecated - remove with next eeprom number change
|
||||||
|
k_param_ahrs, // AHRS group // 159
|
||||||
|
|
||||||
|
//
|
||||||
|
// 160: Navigation parameters
|
||||||
|
//
|
||||||
|
k_param_rtl_altitude = 160,
|
||||||
|
k_param_crosstrack_gain, // deprecated - remove with next eeprom number change
|
||||||
|
k_param_rtl_loiter_time,
|
||||||
|
k_param_rtl_alt_final,
|
||||||
|
k_param_tilt_comp, // 164 deprecated - remove with next eeprom number change
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Camera and mount parameters
|
||||||
|
//
|
||||||
|
k_param_camera = 165,
|
||||||
|
k_param_camera_mount,
|
||||||
|
k_param_camera_mount2, // deprecated
|
||||||
|
|
||||||
|
//
|
||||||
|
// Battery monitoring parameters
|
||||||
|
//
|
||||||
|
k_param_battery_volt_pin = 168, // deprecated - can be deleted
|
||||||
|
k_param_battery_curr_pin, // 169 deprecated - can be deleted
|
||||||
|
|
||||||
|
//
|
||||||
|
// 170: Radio settings
|
||||||
|
//
|
||||||
|
k_param_rc_1_old = 170,
|
||||||
|
k_param_rc_2_old,
|
||||||
|
k_param_rc_3_old,
|
||||||
|
k_param_rc_4_old,
|
||||||
|
k_param_rc_5_old,
|
||||||
|
k_param_rc_6_old,
|
||||||
|
k_param_rc_7_old,
|
||||||
|
k_param_rc_8_old,
|
||||||
|
k_param_rc_10_old,
|
||||||
|
k_param_rc_11_old,
|
||||||
|
k_param_throttle_min, // remove
|
||||||
|
k_param_throttle_max, // remove
|
||||||
|
k_param_failsafe_throttle,
|
||||||
|
k_param_throttle_fs_action, // remove
|
||||||
|
k_param_failsafe_throttle_value,
|
||||||
|
k_param_throttle_trim, // remove
|
||||||
|
k_param_radio_tuning,
|
||||||
|
k_param_radio_tuning_high_old, // unused
|
||||||
|
k_param_radio_tuning_low_old, // unused
|
||||||
|
k_param_rc_speed = 192,
|
||||||
|
k_param_failsafe_battery_enabled, // unused - moved to AP_BattMonitor
|
||||||
|
k_param_throttle_mid, // remove
|
||||||
|
k_param_failsafe_gps_enabled, // remove
|
||||||
|
k_param_rc_9_old,
|
||||||
|
k_param_rc_12_old,
|
||||||
|
k_param_failsafe_gcs,
|
||||||
|
k_param_rcmap, // 199
|
||||||
|
|
||||||
|
//
|
||||||
|
// 200: flight modes
|
||||||
|
//
|
||||||
|
k_param_flight_mode1 = 200,
|
||||||
|
k_param_flight_mode2,
|
||||||
|
k_param_flight_mode3,
|
||||||
|
k_param_flight_mode4,
|
||||||
|
k_param_flight_mode5,
|
||||||
|
k_param_flight_mode6,
|
||||||
|
k_param_flight_mode_chan,
|
||||||
|
k_param_initial_mode,
|
||||||
|
|
||||||
|
//
|
||||||
|
// 210: Waypoint data
|
||||||
|
//
|
||||||
|
k_param_waypoint_mode = 210, // remove
|
||||||
|
k_param_command_total, // remove
|
||||||
|
k_param_command_index, // remove
|
||||||
|
k_param_command_nav_index, // remove
|
||||||
|
k_param_waypoint_radius, // remove
|
||||||
|
k_param_circle_radius, // remove
|
||||||
|
k_param_waypoint_speed_max, // remove
|
||||||
|
k_param_land_speed,
|
||||||
|
k_param_auto_velocity_z_min, // remove
|
||||||
|
k_param_auto_velocity_z_max, // remove - 219
|
||||||
|
k_param_land_speed_high,
|
||||||
|
|
||||||
|
//
|
||||||
|
// 220: PI/D Controllers
|
||||||
|
//
|
||||||
|
k_param_acro_rp_p = 221,
|
||||||
|
k_param_axis_lock_p, // remove
|
||||||
|
k_param_pid_rate_roll, // remove
|
||||||
|
k_param_pid_rate_pitch, // remove
|
||||||
|
k_param_pid_rate_yaw, // remove
|
||||||
|
k_param_p_stabilize_roll, // remove
|
||||||
|
k_param_p_stabilize_pitch, // remove
|
||||||
|
k_param_p_stabilize_yaw, // remove
|
||||||
|
k_param_p_pos_xy, // remove
|
||||||
|
k_param_p_loiter_lon, // remove
|
||||||
|
k_param_pid_loiter_rate_lat, // remove
|
||||||
|
k_param_pid_loiter_rate_lon, // remove
|
||||||
|
k_param_pid_nav_lat, // remove
|
||||||
|
k_param_pid_nav_lon, // remove
|
||||||
|
k_param_p_alt_hold, // remove
|
||||||
|
k_param_p_vel_z, // remove
|
||||||
|
k_param_pid_optflow_roll, // remove
|
||||||
|
k_param_pid_optflow_pitch, // remove
|
||||||
|
k_param_acro_balance_roll_old, // remove
|
||||||
|
k_param_acro_balance_pitch_old, // remove
|
||||||
|
k_param_pid_accel_z, // remove
|
||||||
|
k_param_acro_balance_roll,
|
||||||
|
k_param_acro_balance_pitch,
|
||||||
|
k_param_acro_yaw_p,
|
||||||
|
k_param_autotune_axis_bitmask, // remove
|
||||||
|
k_param_autotune_aggressiveness, // remove
|
||||||
|
k_param_pi_vel_xy, // remove
|
||||||
|
k_param_fs_ekf_action,
|
||||||
|
k_param_rtl_climb_min,
|
||||||
|
k_param_rpm_sensor,
|
||||||
|
k_param_autotune_min_d, // remove
|
||||||
|
k_param_arming, // 252 - AP_Arming
|
||||||
|
k_param_logger = 253, // 253 - Logging Group
|
||||||
|
|
||||||
|
// 254,255: reserved
|
||||||
|
|
||||||
|
k_param_vehicle = 257, // vehicle common block of parameters
|
||||||
|
|
||||||
|
// the k_param_* space is 9-bits in size
|
||||||
|
// 511: reserved
|
||||||
|
};
|
||||||
|
|
||||||
|
AP_Int16 format_version;
|
||||||
|
|
||||||
|
// Telemetry control
|
||||||
|
//
|
||||||
|
AP_Int16 sysid_this_mav;
|
||||||
|
AP_Int16 sysid_my_gcs;
|
||||||
|
AP_Int8 telem_delay;
|
||||||
|
|
||||||
|
AP_Float throttle_filt;
|
||||||
|
AP_Int16 throttle_behavior;
|
||||||
|
AP_Float pilot_takeoff_alt;
|
||||||
|
|
||||||
|
AP_Int16 rtl_altitude;
|
||||||
|
AP_Int16 rtl_speed_cms;
|
||||||
|
AP_Float rtl_cone_slope;
|
||||||
|
|
||||||
|
AP_Int8 failsafe_gcs; // ground station failsafe behavior
|
||||||
|
AP_Int16 gps_hdop_good; // GPS Hdop value at or below this value represent a good position
|
||||||
|
|
||||||
|
AP_Int16 rtl_alt_final;
|
||||||
|
AP_Int16 rtl_climb_min; // rtl minimum climb in cm
|
||||||
|
|
||||||
|
AP_Int8 wp_yaw_behavior; // controls how the autopilot controls yaw during missions
|
||||||
|
|
||||||
|
AP_Int16 poshold_brake_rate; // PosHold flight mode's rotation rate during braking in deg/sec
|
||||||
|
AP_Int16 poshold_brake_angle_max; // PosHold flight mode's max lean angle during braking in centi-degrees
|
||||||
|
|
||||||
|
// Waypoints
|
||||||
|
//
|
||||||
|
AP_Int32 rtl_loiter_time;
|
||||||
|
AP_Int16 land_speed;
|
||||||
|
AP_Int16 land_speed_high;
|
||||||
|
AP_Int16 pilot_speed_up; // maximum vertical ascending velocity the pilot may request
|
||||||
|
AP_Int16 pilot_accel_z; // vertical acceleration the pilot may request
|
||||||
|
|
||||||
|
// Throttle
|
||||||
|
//
|
||||||
|
AP_Int8 failsafe_throttle;
|
||||||
|
AP_Int16 failsafe_throttle_value;
|
||||||
|
AP_Int16 throttle_deadzone;
|
||||||
|
|
||||||
|
// Flight modes
|
||||||
|
//
|
||||||
|
AP_Int8 flight_mode1;
|
||||||
|
AP_Int8 flight_mode2;
|
||||||
|
AP_Int8 flight_mode3;
|
||||||
|
AP_Int8 flight_mode4;
|
||||||
|
AP_Int8 flight_mode5;
|
||||||
|
AP_Int8 flight_mode6;
|
||||||
|
AP_Int8 flight_mode_chan;
|
||||||
|
AP_Int8 initial_mode;
|
||||||
|
|
||||||
|
// Misc
|
||||||
|
//
|
||||||
|
AP_Int32 log_bitmask;
|
||||||
|
AP_Int8 radio_tuning;
|
||||||
|
AP_Int8 frame_type;
|
||||||
|
AP_Int8 disarm_delay;
|
||||||
|
|
||||||
|
AP_Int8 land_repositioning;
|
||||||
|
AP_Int8 fs_ekf_action;
|
||||||
|
AP_Int8 fs_crash_check;
|
||||||
|
AP_Float fs_ekf_thresh;
|
||||||
|
AP_Int16 gcs_pid_mask;
|
||||||
|
|
||||||
|
AP_Int8 rtl_alt_type;
|
||||||
|
|
||||||
|
AP_Int16 rc_speed; // speed of fast RC Channels in Hz
|
||||||
|
|
||||||
|
// Acro parameters
|
||||||
|
AP_Float acro_rp_p;
|
||||||
|
AP_Float acro_yaw_p;
|
||||||
|
AP_Float acro_balance_roll;
|
||||||
|
AP_Float acro_balance_pitch;
|
||||||
|
AP_Int8 acro_trainer;
|
||||||
|
AP_Float acro_rp_expo;
|
||||||
|
|
||||||
|
// Note: keep initializers here in the same order as they are declared
|
||||||
|
// above.
|
||||||
|
Parameters()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
2nd block of parameters, to avoid going past 256 top level keys
|
||||||
|
*/
|
||||||
|
class ParametersG2
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ParametersG2(void);
|
||||||
|
|
||||||
|
// var_info for holding Parameter information
|
||||||
|
static const struct AP_Param::GroupInfo var_info[];
|
||||||
|
|
||||||
|
// altitude at which nav control can start in takeoff
|
||||||
|
AP_Float wp_navalt_min;
|
||||||
|
|
||||||
|
// // button checking
|
||||||
|
// AP_Button *button_ptr;
|
||||||
|
|
||||||
|
#if STATS_ENABLED == ENABLED
|
||||||
|
// vehicle statistics
|
||||||
|
AP_Stats stats;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// ground effect compensation enable/disable
|
||||||
|
// AP_Int8 gndeffect_comp_enabled;
|
||||||
|
|
||||||
|
// temperature calibration handling
|
||||||
|
// AP_TempCalibration temp_calibration;
|
||||||
|
|
||||||
|
|
||||||
|
// whether to enforce acceptance of packets only from sysid_my_gcs
|
||||||
|
AP_Int8 sysid_enforce;
|
||||||
|
|
||||||
|
// developer options
|
||||||
|
AP_Int32 dev_options;
|
||||||
|
|
||||||
|
// acro exponent parameters
|
||||||
|
AP_Float acro_y_expo;
|
||||||
|
|
||||||
|
// frame class
|
||||||
|
AP_Int8 frame_class;
|
||||||
|
|
||||||
|
// RC input channels
|
||||||
|
RC_Channels_Blimp rc_channels;
|
||||||
|
|
||||||
|
// control over servo output ranges
|
||||||
|
SRV_Channels servo_channels;
|
||||||
|
|
||||||
|
// Additional pilot velocity items
|
||||||
|
AP_Int16 pilot_speed_dn;
|
||||||
|
|
||||||
|
// Land alt final stage
|
||||||
|
AP_Int16 land_alt_low;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef ENABLE_SCRIPTING
|
||||||
|
AP_Scripting scripting;
|
||||||
|
#endif // ENABLE_SCRIPTING
|
||||||
|
|
||||||
|
AP_Float tuning_min;
|
||||||
|
AP_Float tuning_max;
|
||||||
|
|
||||||
|
// vibration failsafe enable/disable
|
||||||
|
AP_Int8 fs_vibe_enabled;
|
||||||
|
|
||||||
|
// Failsafe options bitmask #36
|
||||||
|
AP_Int32 fs_options;
|
||||||
|
|
||||||
|
AP_Float fs_gcs_timeout;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const AP_Param::Info var_info[];
|
|
@ -0,0 +1,255 @@
|
||||||
|
#include "Blimp.h"
|
||||||
|
|
||||||
|
#include "RC_Channel.h"
|
||||||
|
|
||||||
|
|
||||||
|
// defining these two macros and including the RC_Channels_VarInfo header defines the parameter information common to all vehicle types
|
||||||
|
#define RC_CHANNELS_SUBCLASS RC_Channels_Blimp
|
||||||
|
#define RC_CHANNEL_SUBCLASS RC_Channel_Blimp
|
||||||
|
|
||||||
|
#include <RC_Channel/RC_Channels_VarInfo.h>
|
||||||
|
|
||||||
|
int8_t RC_Channels_Blimp::flight_mode_channel_number() const
|
||||||
|
{
|
||||||
|
return blimp.g.flight_mode_chan.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RC_Channel_Blimp::mode_switch_changed(modeswitch_pos_t new_pos)
|
||||||
|
{
|
||||||
|
if (new_pos < 0 || (uint8_t)new_pos > blimp.num_flight_modes) {
|
||||||
|
// should not have been called
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!blimp.set_mode((Mode::Number)blimp.flight_modes[new_pos].get(), ModeReason::RC_COMMAND)) {
|
||||||
|
// alert user to mode change failure
|
||||||
|
if (blimp.ap.initialised) {
|
||||||
|
AP_Notify::events.user_mode_change_failed = 1;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// play a tone
|
||||||
|
// alert user to mode change (except if autopilot is just starting up)
|
||||||
|
if (blimp.ap.initialised) {
|
||||||
|
AP_Notify::events.user_mode_change = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RC_Channels_Blimp::has_valid_input() const
|
||||||
|
{
|
||||||
|
if (blimp.failsafe.radio) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (blimp.failsafe.radio_counter != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
RC_Channel * RC_Channels_Blimp::get_arming_channel(void) const
|
||||||
|
{
|
||||||
|
return blimp.channel_yaw;
|
||||||
|
}
|
||||||
|
|
||||||
|
// init_aux_switch_function - initialize aux functions
|
||||||
|
void RC_Channel_Blimp::init_aux_function(const aux_func_t ch_option, const AuxSwitchPos ch_flag)
|
||||||
|
{
|
||||||
|
// init channel options
|
||||||
|
switch (ch_option) {
|
||||||
|
// the following functions do not need to be initialised:
|
||||||
|
case AUX_FUNC::MANUAL:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
RC_Channel::init_aux_function(ch_option, ch_flag);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// do_aux_function_change_mode - change mode based on an aux switch
|
||||||
|
// being moved
|
||||||
|
void RC_Channel_Blimp::do_aux_function_change_mode(const Mode::Number mode,
|
||||||
|
const AuxSwitchPos ch_flag)
|
||||||
|
{
|
||||||
|
switch (ch_flag) {
|
||||||
|
case AuxSwitchPos::HIGH: {
|
||||||
|
// engage mode (if not possible we remain in current flight mode)
|
||||||
|
const bool success = blimp.set_mode(mode, ModeReason::RC_COMMAND);
|
||||||
|
if (blimp.ap.initialised) {
|
||||||
|
if (success) {
|
||||||
|
AP_Notify::events.user_mode_change = 1;
|
||||||
|
} else {
|
||||||
|
AP_Notify::events.user_mode_change_failed = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
// return to flight mode switch's flight mode if we are currently
|
||||||
|
// in this mode
|
||||||
|
if (blimp.control_mode == mode) {
|
||||||
|
rc().reset_mode_switch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RC_Channel_Blimp::do_aux_function_armdisarm(const AuxSwitchPos ch_flag)
|
||||||
|
{
|
||||||
|
RC_Channel::do_aux_function_armdisarm(ch_flag);
|
||||||
|
if (blimp.arming.is_armed()) {
|
||||||
|
// remember that we are using an arming switch, for use by
|
||||||
|
// set_throttle_zero_flag
|
||||||
|
blimp.ap.armed_with_switch = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// do_aux_function - implement the function invoked by auxiliary switches
|
||||||
|
void RC_Channel_Blimp::do_aux_function(const aux_func_t ch_option, const AuxSwitchPos ch_flag)
|
||||||
|
{
|
||||||
|
switch (ch_option) {
|
||||||
|
|
||||||
|
case AUX_FUNC::SAVE_TRIM:
|
||||||
|
if ((ch_flag == AuxSwitchPos::HIGH) &&
|
||||||
|
(blimp.control_mode <= Mode::Number::MANUAL) &&
|
||||||
|
(blimp.channel_down->get_control_in() == 0)) {
|
||||||
|
blimp.save_trim();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// case AUX_FUNC::SAVE_WP:
|
||||||
|
// #if MODE_AUTO_ENABLED == ENABLED
|
||||||
|
// // save waypoint when switch is brought high
|
||||||
|
// if (ch_flag == RC_Channel::AuxSwitchPos::HIGH) {
|
||||||
|
|
||||||
|
// // do not allow saving new waypoints while we're in auto or disarmed
|
||||||
|
// if (blimp.control_mode == Mode::Number::AUTO || !blimp.motors->armed()) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // do not allow saving the first waypoint with zero throttle
|
||||||
|
// if ((blimp.mode_auto.mission.num_commands() == 0) && (blimp.channel_down->get_control_in() == 0)) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // create new mission command
|
||||||
|
// AP_Mission::Mission_Command cmd = {};
|
||||||
|
|
||||||
|
// // if the mission is empty save a takeoff command
|
||||||
|
// if (blimp.mode_auto.mission.num_commands() == 0) {
|
||||||
|
// // set our location ID to 16, MAV_CMD_NAV_WAYPOINT
|
||||||
|
// cmd.id = MAV_CMD_NAV_TAKEOFF;
|
||||||
|
// cmd.content.location.alt = MAX(blimp.current_loc.alt,100);
|
||||||
|
|
||||||
|
// // use the current altitude for the target alt for takeoff.
|
||||||
|
// // only altitude will matter to the AP mission script for takeoff.
|
||||||
|
// if (blimp.mode_auto.mission.add_cmd(cmd)) {
|
||||||
|
// // log event
|
||||||
|
// AP::logger().Write_Event(LogEvent::SAVEWP_ADD_WP);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // set new waypoint to current location
|
||||||
|
// cmd.content.location = blimp.current_loc;
|
||||||
|
|
||||||
|
// // if throttle is above zero, create waypoint command
|
||||||
|
// if (blimp.channel_down->get_control_in() > 0) {
|
||||||
|
// cmd.id = MAV_CMD_NAV_WAYPOINT;
|
||||||
|
// } else {
|
||||||
|
// // with zero throttle, create LAND command
|
||||||
|
// cmd.id = MAV_CMD_NAV_LAND;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // save command
|
||||||
|
// if (blimp.mode_auto.mission.add_cmd(cmd)) {
|
||||||
|
// // log event
|
||||||
|
// AP::logger().Write_Event(LogEvent::SAVEWP_ADD_WP);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// #endif
|
||||||
|
// break;
|
||||||
|
|
||||||
|
// case AUX_FUNC::AUTO:
|
||||||
|
// #if MODE_AUTO_ENABLED == ENABLED
|
||||||
|
// do_aux_function_change_mode(Mode::Number::AUTO, ch_flag);
|
||||||
|
// #endif
|
||||||
|
// break;
|
||||||
|
|
||||||
|
// case AUX_FUNC::LOITER:
|
||||||
|
// do_aux_function_change_mode(Mode::Number::LOITER, ch_flag);
|
||||||
|
// break;
|
||||||
|
|
||||||
|
case AUX_FUNC::MANUAL:
|
||||||
|
do_aux_function_change_mode(Mode::Number::MANUAL, ch_flag);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
RC_Channel::do_aux_function(ch_option, ch_flag);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// save_trim - adds roll and pitch trims from the radio to ahrs
|
||||||
|
void Blimp::save_trim()
|
||||||
|
{
|
||||||
|
// save roll and pitch trim
|
||||||
|
float roll_trim = ToRad((float)channel_right->get_control_in()/100.0f);
|
||||||
|
float pitch_trim = ToRad((float)channel_front->get_control_in()/100.0f);
|
||||||
|
ahrs.add_trim(roll_trim, pitch_trim);
|
||||||
|
AP::logger().Write_Event(LogEvent::SAVE_TRIM);
|
||||||
|
gcs().send_text(MAV_SEVERITY_INFO, "Trim saved");
|
||||||
|
}
|
||||||
|
|
||||||
|
// auto_trim - slightly adjusts the ahrs.roll_trim and ahrs.pitch_trim towards the current stick positions
|
||||||
|
// meant to be called continuously while the pilot attempts to keep the blimp level
|
||||||
|
void Blimp::auto_trim_cancel()
|
||||||
|
{
|
||||||
|
auto_trim_counter = 0;
|
||||||
|
AP_Notify::flags.save_trim = false;
|
||||||
|
gcs().send_text(MAV_SEVERITY_INFO, "AutoTrim cancelled");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Blimp::auto_trim()
|
||||||
|
{
|
||||||
|
if (auto_trim_counter > 0) {
|
||||||
|
if (blimp.flightmode != &blimp.mode_manual ||
|
||||||
|
!blimp.motors->armed()) {
|
||||||
|
auto_trim_cancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// flash the leds
|
||||||
|
AP_Notify::flags.save_trim = true;
|
||||||
|
|
||||||
|
if (!auto_trim_started) {
|
||||||
|
if (ap.land_complete) {
|
||||||
|
// haven't taken off yet
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto_trim_started = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ap.land_complete) {
|
||||||
|
// landed again.
|
||||||
|
auto_trim_cancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto_trim_counter--;
|
||||||
|
|
||||||
|
// calculate roll trim adjustment
|
||||||
|
float roll_trim_adjustment = ToRad((float)channel_right->get_control_in() / 4000.0f);
|
||||||
|
|
||||||
|
// calculate pitch trim adjustment
|
||||||
|
float pitch_trim_adjustment = ToRad((float)channel_front->get_control_in() / 4000.0f);
|
||||||
|
|
||||||
|
// add trim to ahrs object
|
||||||
|
// save to eeprom on last iteration
|
||||||
|
ahrs.add_trim(roll_trim_adjustment, pitch_trim_adjustment, (auto_trim_counter == 0));
|
||||||
|
|
||||||
|
// on last iteration restore leds and accel gains to normal
|
||||||
|
if (auto_trim_counter == 0) {
|
||||||
|
AP_Notify::flags.save_trim = false;
|
||||||
|
gcs().send_text(MAV_SEVERITY_INFO, "AutoTrim: Trims saved");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <RC_Channel/RC_Channel.h>
|
||||||
|
#include "Fins.h"
|
||||||
|
#include "mode.h" //this includes Blimp.h which includes Fins.h
|
||||||
|
|
||||||
|
class RC_Channel_Blimp : public RC_Channel
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
void init_aux_function(aux_func_t ch_option, AuxSwitchPos) override;
|
||||||
|
void do_aux_function(aux_func_t ch_option, AuxSwitchPos) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void do_aux_function_armdisarm(const AuxSwitchPos ch_flag) override;
|
||||||
|
void do_aux_function_change_mode(const Mode::Number mode,
|
||||||
|
const AuxSwitchPos ch_flag);
|
||||||
|
void do_aux_function_change_air_mode(const AuxSwitchPos ch_flag);
|
||||||
|
|
||||||
|
// called when the mode switch changes position:
|
||||||
|
void mode_switch_changed(modeswitch_pos_t new_pos) override;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class RC_Channels_Blimp : public RC_Channels
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
bool has_valid_input() const override;
|
||||||
|
|
||||||
|
RC_Channel *get_arming_channel(void) const override;
|
||||||
|
|
||||||
|
RC_Channel_Blimp obj_channels[NUM_RC_CHANNELS];
|
||||||
|
RC_Channel_Blimp *channel(const uint8_t chan) override
|
||||||
|
{
|
||||||
|
if (chan >= NUM_RC_CHANNELS) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return &obj_channels[chan];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
int8_t flight_mode_channel_number() const override;
|
||||||
|
|
||||||
|
};
|
|
@ -0,0 +1,110 @@
|
||||||
|
#include "Blimp.h"
|
||||||
|
|
||||||
|
// checks if we should update ahrs/RTL home position from the EKF
|
||||||
|
void Blimp::update_home_from_EKF()
|
||||||
|
{
|
||||||
|
// exit immediately if home already set
|
||||||
|
if (ahrs.home_is_set()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// special logic if home is set in-flight
|
||||||
|
if (motors->armed()) {
|
||||||
|
set_home_to_current_location_inflight();
|
||||||
|
} else {
|
||||||
|
// move home to current ekf location (this will set home_state to HOME_SET)
|
||||||
|
if (!set_home_to_current_location(false)) {
|
||||||
|
// ignore failure
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// set_home_to_current_location_inflight - set home to current GPS location (horizontally) and EKF origin vertically
|
||||||
|
void Blimp::set_home_to_current_location_inflight()
|
||||||
|
{
|
||||||
|
// get current location from EKF
|
||||||
|
Location temp_loc;
|
||||||
|
Location ekf_origin;
|
||||||
|
if (ahrs.get_location(temp_loc) && ahrs.get_origin(ekf_origin)) {
|
||||||
|
temp_loc.alt = ekf_origin.alt;
|
||||||
|
if (!set_home(temp_loc, false)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// set_home_to_current_location - set home to current GPS location
|
||||||
|
bool Blimp::set_home_to_current_location(bool lock)
|
||||||
|
{
|
||||||
|
// get current location from EKF
|
||||||
|
Location temp_loc;
|
||||||
|
if (ahrs.get_location(temp_loc)) {
|
||||||
|
if (!set_home(temp_loc, lock)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set_home - sets ahrs home (used for RTL) to specified location
|
||||||
|
// initialises inertial nav and compass on first call
|
||||||
|
// returns true if home location set successfully
|
||||||
|
bool Blimp::set_home(const Location& loc, bool lock)
|
||||||
|
{
|
||||||
|
// check EKF origin has been set
|
||||||
|
Location ekf_origin;
|
||||||
|
if (!ahrs.get_origin(ekf_origin)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check home is close to EKF origin
|
||||||
|
if (far_from_EKF_origin(loc)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool home_was_set = ahrs.home_is_set();
|
||||||
|
|
||||||
|
// set ahrs home (used for RTL)
|
||||||
|
if (!ahrs.set_home(loc)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// init inav and compass declination
|
||||||
|
if (!home_was_set) {
|
||||||
|
// record home is set
|
||||||
|
AP::logger().Write_Event(LogEvent::SET_HOME);
|
||||||
|
|
||||||
|
// #if MODE_AUTO_ENABLED == ENABLED
|
||||||
|
// // log new home position which mission library will pull from ahrs
|
||||||
|
// if (should_log(MASK_LOG_CMD)) {
|
||||||
|
// AP_Mission::Mission_Command temp_cmd;
|
||||||
|
// if (mode_auto.mission.read_cmd_from_storage(0, temp_cmd)) {
|
||||||
|
// logger.Write_Mission_Cmd(mode_auto.mission, temp_cmd);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// lock home position
|
||||||
|
if (lock) {
|
||||||
|
ahrs.lock_home();
|
||||||
|
}
|
||||||
|
|
||||||
|
// return success
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// far_from_EKF_origin - checks if a location is too far from the EKF origin
|
||||||
|
// returns true if too far
|
||||||
|
bool Blimp::far_from_EKF_origin(const Location& loc)
|
||||||
|
{
|
||||||
|
// check distance to EKF origin
|
||||||
|
Location ekf_origin;
|
||||||
|
if (ahrs.get_origin(ekf_origin) && ((ekf_origin.get_distance(loc) > EKF_ORIGIN_MAX_DIST_M) || (labs(ekf_origin.alt - loc.alt) > EKF_ORIGIN_MAX_DIST_M))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// close enough to origin
|
||||||
|
return false;
|
||||||
|
}
|
|
@ -0,0 +1,593 @@
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Default and automatic configuration details.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
#include "defines.h"
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// HARDWARE CONFIGURATION AND CONNECTIONS
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef CONFIG_HAL_BOARD
|
||||||
|
#error CONFIG_HAL_BOARD must be defined to build Blimp
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ADVANCED_FAILSAFE
|
||||||
|
# define ADVANCED_FAILSAFE DISABLED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// HIL_MODE OPTIONAL
|
||||||
|
|
||||||
|
#ifndef HIL_MODE
|
||||||
|
#define HIL_MODE HIL_MODE_DISABLED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ARMING_DELAY_SEC
|
||||||
|
# define ARMING_DELAY_SEC 2.0f
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// FRAME_CONFIG
|
||||||
|
//
|
||||||
|
#ifndef FRAME_CONFIG
|
||||||
|
# define FRAME_CONFIG MULTICOPTER_FRAME
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// PWM control
|
||||||
|
// default RC speed in Hz
|
||||||
|
#ifndef RC_FAST_SPEED
|
||||||
|
# define RC_FAST_SPEED 490
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Rangefinder
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef RANGEFINDER_ENABLED
|
||||||
|
# define RANGEFINDER_ENABLED ENABLED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef RANGEFINDER_HEALTH_MAX
|
||||||
|
# define RANGEFINDER_HEALTH_MAX 3 // number of good reads that indicates a healthy rangefinder
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef RANGEFINDER_TIMEOUT_MS
|
||||||
|
# define RANGEFINDER_TIMEOUT_MS 1000 // rangefinder filter reset if no updates from sensor in 1 second
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef RANGEFINDER_GAIN_DEFAULT
|
||||||
|
# define RANGEFINDER_GAIN_DEFAULT 0.8f // gain for controlling how quickly rangefinder range adjusts target altitude (lower means slower reaction)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SURFACE_TRACKING_VELZ_MAX
|
||||||
|
# define SURFACE_TRACKING_VELZ_MAX 150 // max vertical speed change while surface tracking with rangefinder
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SURFACE_TRACKING_TIMEOUT_MS
|
||||||
|
# define SURFACE_TRACKING_TIMEOUT_MS 1000 // surface tracking target alt will reset to current rangefinder alt after this many milliseconds without a good rangefinder alt
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef RANGEFINDER_WPNAV_FILT_HZ
|
||||||
|
# define RANGEFINDER_WPNAV_FILT_HZ 0.25f // filter frequency for rangefinder altitude provided to waypoint navigation class
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef RANGEFINDER_TILT_CORRECTION // by disable tilt correction for use of range finder data by EKF
|
||||||
|
# define RANGEFINDER_TILT_CORRECTION ENABLED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef RANGEFINDER_GLITCH_ALT_CM
|
||||||
|
# define RANGEFINDER_GLITCH_ALT_CM 200 // amount of rangefinder change to be considered a glitch
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef RANGEFINDER_GLITCH_NUM_SAMPLES
|
||||||
|
# define RANGEFINDER_GLITCH_NUM_SAMPLES 3 // number of rangefinder glitches in a row to take new reading
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Proximity sensor
|
||||||
|
//
|
||||||
|
#ifndef PROXIMITY_ENABLED
|
||||||
|
# define PROXIMITY_ENABLED ENABLED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MAV_SYSTEM_ID
|
||||||
|
# define MAV_SYSTEM_ID 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Battery monitoring
|
||||||
|
//
|
||||||
|
#ifndef BOARD_VOLTAGE_MIN
|
||||||
|
# define BOARD_VOLTAGE_MIN 4.3f // min board voltage in volts for pre-arm checks
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef BOARD_VOLTAGE_MAX
|
||||||
|
# define BOARD_VOLTAGE_MAX 5.8f // max board voltage in volts for pre-arm checks
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// prearm GPS hdop check
|
||||||
|
#ifndef GPS_HDOP_GOOD_DEFAULT
|
||||||
|
# define GPS_HDOP_GOOD_DEFAULT 140 // minimum hdop that represents a good position. used during pre-arm checks if fence is enabled
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// GCS failsafe
|
||||||
|
#ifndef FS_GCS
|
||||||
|
# define FS_GCS DISABLED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Radio failsafe while using RC_override
|
||||||
|
#ifndef FS_RADIO_RC_OVERRIDE_TIMEOUT_MS
|
||||||
|
# define FS_RADIO_RC_OVERRIDE_TIMEOUT_MS 1000 // RC Radio failsafe triggers after 1 second while using RC_override from ground station
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Radio failsafe
|
||||||
|
#ifndef FS_RADIO_TIMEOUT_MS
|
||||||
|
#define FS_RADIO_TIMEOUT_MS 500 // RC Radio Failsafe triggers after 500 milliseconds with No RC Input
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// missing terrain data failsafe
|
||||||
|
#ifndef FS_TERRAIN_TIMEOUT_MS
|
||||||
|
#define FS_TERRAIN_TIMEOUT_MS 5000 // 5 seconds of missing terrain data will trigger failsafe (RTL)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PREARM_DISPLAY_PERIOD
|
||||||
|
# define PREARM_DISPLAY_PERIOD 30
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// pre-arm baro vs inertial nav max alt disparity
|
||||||
|
#ifndef PREARM_MAX_ALT_DISPARITY_CM
|
||||||
|
# define PREARM_MAX_ALT_DISPARITY_CM 100 // barometer and inertial nav altitude must be within this many centimeters
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// EKF Failsafe
|
||||||
|
#ifndef FS_EKF_ACTION_DEFAULT
|
||||||
|
# define FS_EKF_ACTION_DEFAULT FS_EKF_ACTION_LAND // EKF failsafe triggers land by default
|
||||||
|
#endif
|
||||||
|
#ifndef FS_EKF_THRESHOLD_DEFAULT
|
||||||
|
# define FS_EKF_THRESHOLD_DEFAULT 0.8f // EKF failsafe's default compass and velocity variance threshold above which the EKF failsafe will be triggered
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef EKF_ORIGIN_MAX_DIST_M
|
||||||
|
# define EKF_ORIGIN_MAX_DIST_M 50000 // EKF origin and waypoints (including home) must be within 50km
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef COMPASS_CAL_STICK_GESTURE_TIME
|
||||||
|
#define COMPASS_CAL_STICK_GESTURE_TIME 2.0f // 2 seconds
|
||||||
|
#endif
|
||||||
|
#ifndef COMPASS_CAL_STICK_DELAY
|
||||||
|
#define COMPASS_CAL_STICK_DELAY 5.0f
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// OPTICAL_FLOW
|
||||||
|
#ifndef OPTFLOW
|
||||||
|
# define OPTFLOW ENABLED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Auto Tuning
|
||||||
|
#ifndef AUTOTUNE_ENABLED
|
||||||
|
# define AUTOTUNE_ENABLED ENABLED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Crop Sprayer - enabled only on larger firmwares
|
||||||
|
#ifndef SPRAYER_ENABLED
|
||||||
|
# define SPRAYER_ENABLED HAL_SPRAYER_ENABLED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Precision Landing with companion computer or IRLock sensor
|
||||||
|
#ifndef PRECISION_LANDING
|
||||||
|
# define PRECISION_LANDING ENABLED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// gripper - enabled only on larger firmwares
|
||||||
|
#ifndef GRIPPER_ENABLED
|
||||||
|
# define GRIPPER_ENABLED !HAL_MINIMIZE_FEATURES
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// rotations per minute sensor support
|
||||||
|
#ifndef RPM_ENABLED
|
||||||
|
# define RPM_ENABLED !HAL_MINIMIZE_FEATURES
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Parachute release
|
||||||
|
#ifndef PARACHUTE
|
||||||
|
# define PARACHUTE HAL_PARACHUTE_ENABLED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Nav-Guided - allows external nav computer to control vehicle
|
||||||
|
#ifndef NAV_GUIDED
|
||||||
|
# define NAV_GUIDED !HAL_MINIMIZE_FEATURES
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Acro - fly vehicle in acrobatic mode
|
||||||
|
#ifndef MODE_ACRO_ENABLED
|
||||||
|
# define MODE_ACRO_ENABLED ENABLED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Auto mode - allows vehicle to trace waypoints and perform automated actions
|
||||||
|
#ifndef MODE_AUTO_ENABLED
|
||||||
|
# define MODE_AUTO_ENABLED ENABLED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Brake mode - bring vehicle to stop
|
||||||
|
#ifndef MODE_BRAKE_ENABLED
|
||||||
|
# define MODE_BRAKE_ENABLED ENABLED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Circle - fly vehicle around a central point
|
||||||
|
#ifndef MODE_CIRCLE_ENABLED
|
||||||
|
# define MODE_CIRCLE_ENABLED ENABLED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Drift - fly vehicle in altitude-held, coordinated-turn mode
|
||||||
|
#ifndef MODE_DRIFT_ENABLED
|
||||||
|
# define MODE_DRIFT_ENABLED ENABLED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// flip - fly vehicle in flip in pitch and roll direction mode
|
||||||
|
#ifndef MODE_FLIP_ENABLED
|
||||||
|
# define MODE_FLIP_ENABLED ENABLED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Follow - follow another vehicle or GCS
|
||||||
|
#ifndef MODE_FOLLOW_ENABLED
|
||||||
|
# define MODE_FOLLOW_ENABLED !HAL_MINIMIZE_FEATURES
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Guided mode - control vehicle's position or angles from GCS
|
||||||
|
#ifndef MODE_GUIDED_ENABLED
|
||||||
|
# define MODE_GUIDED_ENABLED ENABLED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// GuidedNoGPS mode - control vehicle's angles from GCS
|
||||||
|
#ifndef MODE_GUIDED_NOGPS_ENABLED
|
||||||
|
# define MODE_GUIDED_NOGPS_ENABLED !HAL_MINIMIZE_FEATURES
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Loiter mode - allows vehicle to hold global position
|
||||||
|
#ifndef MODE_LOITER_ENABLED
|
||||||
|
# define MODE_LOITER_ENABLED ENABLED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Position Hold - enable holding of global position
|
||||||
|
#ifndef MODE_POSHOLD_ENABLED
|
||||||
|
# define MODE_POSHOLD_ENABLED ENABLED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// RTL - Return To Launch
|
||||||
|
#ifndef MODE_RTL_ENABLED
|
||||||
|
# define MODE_RTL_ENABLED ENABLED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// SmartRTL - allows vehicle to retrace a (loop-eliminated) breadcrumb home
|
||||||
|
#ifndef MODE_SMARTRTL_ENABLED
|
||||||
|
# define MODE_SMARTRTL_ENABLED ENABLED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Sport - fly vehicle in rate-controlled (earth-frame) mode
|
||||||
|
#ifndef MODE_SPORT_ENABLED
|
||||||
|
# define MODE_SPORT_ENABLED !HAL_MINIMIZE_FEATURES
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// System ID - conduct system identification tests on vehicle
|
||||||
|
#ifndef MODE_SYSTEMID_ENABLED
|
||||||
|
# define MODE_SYSTEMID_ENABLED !HAL_MINIMIZE_FEATURES
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Button - Enable the button connected to AUX1-6
|
||||||
|
#ifndef BUTTON_ENABLED
|
||||||
|
# define BUTTON_ENABLED ENABLED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// RADIO CONFIGURATION
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// FLIGHT_MODE
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef FLIGHT_MODE_1
|
||||||
|
# define FLIGHT_MODE_1 Mode::Number::MANUAL
|
||||||
|
#endif
|
||||||
|
#ifndef FLIGHT_MODE_2
|
||||||
|
# define FLIGHT_MODE_2 Mode::Number::MANUAL
|
||||||
|
#endif
|
||||||
|
#ifndef FLIGHT_MODE_3
|
||||||
|
# define FLIGHT_MODE_3 Mode::Number::MANUAL
|
||||||
|
#endif
|
||||||
|
#ifndef FLIGHT_MODE_4
|
||||||
|
# define FLIGHT_MODE_4 Mode::Number::MANUAL
|
||||||
|
#endif
|
||||||
|
#ifndef FLIGHT_MODE_5
|
||||||
|
# define FLIGHT_MODE_5 Mode::Number::MANUAL
|
||||||
|
#endif
|
||||||
|
#ifndef FLIGHT_MODE_6
|
||||||
|
# define FLIGHT_MODE_6 Mode::Number::MANUAL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Throttle Failsafe
|
||||||
|
//
|
||||||
|
#ifndef FS_THR_VALUE_DEFAULT
|
||||||
|
# define FS_THR_VALUE_DEFAULT 975
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Takeoff
|
||||||
|
//
|
||||||
|
#ifndef PILOT_TKOFF_ALT_DEFAULT
|
||||||
|
# define PILOT_TKOFF_ALT_DEFAULT 0 // default final alt above home for pilot initiated takeoff
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Landing
|
||||||
|
//
|
||||||
|
#ifndef LAND_SPEED
|
||||||
|
# define LAND_SPEED 50 // the descent speed for the final stage of landing in cm/s
|
||||||
|
#endif
|
||||||
|
#ifndef LAND_REPOSITION_DEFAULT
|
||||||
|
# define LAND_REPOSITION_DEFAULT 1 // by default the pilot can override roll/pitch during landing
|
||||||
|
#endif
|
||||||
|
#ifndef LAND_WITH_DELAY_MS
|
||||||
|
# define LAND_WITH_DELAY_MS 4000 // default delay (in milliseconds) when a land-with-delay is triggered during a failsafe event
|
||||||
|
#endif
|
||||||
|
#ifndef LAND_CANCEL_TRIGGER_THR
|
||||||
|
# define LAND_CANCEL_TRIGGER_THR 700 // land is cancelled by input throttle above 700
|
||||||
|
#endif
|
||||||
|
#ifndef LAND_RANGEFINDER_MIN_ALT_CM
|
||||||
|
#define LAND_RANGEFINDER_MIN_ALT_CM 200
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Landing Detector
|
||||||
|
//
|
||||||
|
#ifndef LAND_DETECTOR_TRIGGER_SEC
|
||||||
|
# define LAND_DETECTOR_TRIGGER_SEC 1.0f // number of seconds to detect a landing
|
||||||
|
#endif
|
||||||
|
#ifndef LAND_DETECTOR_MAYBE_TRIGGER_SEC
|
||||||
|
# define LAND_DETECTOR_MAYBE_TRIGGER_SEC 0.2f // number of seconds that means we might be landed (used to reset horizontal position targets to prevent tipping over)
|
||||||
|
#endif
|
||||||
|
#ifndef LAND_DETECTOR_ACCEL_LPF_CUTOFF
|
||||||
|
# define LAND_DETECTOR_ACCEL_LPF_CUTOFF 1.0f // frequency cutoff of land detector accelerometer filter
|
||||||
|
#endif
|
||||||
|
#ifndef LAND_DETECTOR_ACCEL_MAX
|
||||||
|
# define LAND_DETECTOR_ACCEL_MAX 1.0f // vehicle acceleration must be under 1m/s/s
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// CAMERA TRIGGER AND CONTROL
|
||||||
|
//
|
||||||
|
#ifndef CAMERA
|
||||||
|
# define CAMERA ENABLED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Flight mode definitions
|
||||||
|
//
|
||||||
|
|
||||||
|
// Acro Mode
|
||||||
|
#ifndef ACRO_RP_P
|
||||||
|
# define ACRO_RP_P 4.5f
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ACRO_YAW_P
|
||||||
|
# define ACRO_YAW_P 4.5f
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ACRO_LEVEL_MAX_ANGLE
|
||||||
|
# define ACRO_LEVEL_MAX_ANGLE 3000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ACRO_BALANCE_ROLL
|
||||||
|
#define ACRO_BALANCE_ROLL 1.0f
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ACRO_BALANCE_PITCH
|
||||||
|
#define ACRO_BALANCE_PITCH 1.0f
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ACRO_RP_EXPO_DEFAULT
|
||||||
|
#define ACRO_RP_EXPO_DEFAULT 0.3f
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ACRO_Y_EXPO_DEFAULT
|
||||||
|
#define ACRO_Y_EXPO_DEFAULT 0.0f
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ACRO_THR_MID_DEFAULT
|
||||||
|
#define ACRO_THR_MID_DEFAULT 0.0f
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// RTL Mode
|
||||||
|
#ifndef RTL_ALT_FINAL
|
||||||
|
# define RTL_ALT_FINAL 0 // the altitude the vehicle will move to as the final stage of Returning to Launch. Set to zero to land.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef RTL_ALT
|
||||||
|
# define RTL_ALT 1500 // default alt to return to home in cm, 0 = Maintain current altitude
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef RTL_ALT_MIN
|
||||||
|
# define RTL_ALT_MIN 200 // min height above ground for RTL (i.e 2m)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef RTL_CLIMB_MIN_DEFAULT
|
||||||
|
# define RTL_CLIMB_MIN_DEFAULT 0 // vehicle will always climb this many cm as first stage of RTL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef RTL_ABS_MIN_CLIMB
|
||||||
|
# define RTL_ABS_MIN_CLIMB 250 // absolute minimum initial climb
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef RTL_CONE_SLOPE_DEFAULT
|
||||||
|
# define RTL_CONE_SLOPE_DEFAULT 3.0f // slope of RTL cone (height / distance). 0 = No cone
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef RTL_MIN_CONE_SLOPE
|
||||||
|
# define RTL_MIN_CONE_SLOPE 0.5f // minimum slope of cone
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef RTL_LOITER_TIME
|
||||||
|
# define RTL_LOITER_TIME 5000 // Time (in milliseconds) to loiter above home before beginning final descent
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// AUTO Mode
|
||||||
|
#ifndef WP_YAW_BEHAVIOR_DEFAULT
|
||||||
|
# define WP_YAW_BEHAVIOR_DEFAULT WP_YAW_BEHAVIOR_LOOK_AT_NEXT_WP_EXCEPT_RTL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef AUTO_YAW_SLEW_RATE
|
||||||
|
# define AUTO_YAW_SLEW_RATE 60 // degrees/sec
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef YAW_LOOK_AHEAD_MIN_SPEED
|
||||||
|
# define YAW_LOOK_AHEAD_MIN_SPEED 100 // minimum ground speed in cm/s required before blimp is aimed at ground course
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Stabilize Rate Control
|
||||||
|
//
|
||||||
|
#ifndef ROLL_PITCH_YAW_INPUT_MAX
|
||||||
|
# define ROLL_PITCH_YAW_INPUT_MAX 4500 // roll, pitch and yaw input range
|
||||||
|
#endif
|
||||||
|
#ifndef DEFAULT_ANGLE_MAX
|
||||||
|
# define DEFAULT_ANGLE_MAX 4500 // ANGLE_MAX parameters default value
|
||||||
|
#endif
|
||||||
|
#ifndef ANGLE_RATE_MAX
|
||||||
|
# define ANGLE_RATE_MAX 18000 // default maximum rotation rate in roll/pitch axis requested by angle controller used in stabilize, loiter, rtl, auto flight modes
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Stop mode defaults
|
||||||
|
//
|
||||||
|
#ifndef BRAKE_MODE_SPEED_Z
|
||||||
|
# define BRAKE_MODE_SPEED_Z 250 // z-axis speed in cm/s in Brake Mode
|
||||||
|
#endif
|
||||||
|
#ifndef BRAKE_MODE_DECEL_RATE
|
||||||
|
# define BRAKE_MODE_DECEL_RATE 750 // acceleration rate in cm/s/s in Brake Mode
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// PosHold parameter defaults
|
||||||
|
//
|
||||||
|
#ifndef POSHOLD_BRAKE_RATE_DEFAULT
|
||||||
|
# define POSHOLD_BRAKE_RATE_DEFAULT 8 // default POSHOLD_BRAKE_RATE param value. Rotation rate during braking in deg/sec
|
||||||
|
#endif
|
||||||
|
#ifndef POSHOLD_BRAKE_ANGLE_DEFAULT
|
||||||
|
# define POSHOLD_BRAKE_ANGLE_DEFAULT 3000 // default POSHOLD_BRAKE_ANGLE param value. Max lean angle during braking in centi-degrees
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Throttle control defaults
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef THR_DZ_DEFAULT
|
||||||
|
# define THR_DZ_DEFAULT 100 // the deadzone above and below mid throttle while in althold or loiter
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// default maximum vertical velocity and acceleration the pilot may request
|
||||||
|
#ifndef PILOT_VELZ_MAX
|
||||||
|
# define PILOT_VELZ_MAX 250 // maximum vertical velocity in cm/s
|
||||||
|
#endif
|
||||||
|
#ifndef PILOT_ACCEL_Z_DEFAULT
|
||||||
|
# define PILOT_ACCEL_Z_DEFAULT 250 // vertical acceleration in cm/s/s while altitude is under pilot control
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// max distance in cm above or below current location that will be used for the alt target when transitioning to alt-hold mode
|
||||||
|
#ifndef ALT_HOLD_INIT_MAX_OVERSHOOT
|
||||||
|
# define ALT_HOLD_INIT_MAX_OVERSHOOT 200
|
||||||
|
#endif
|
||||||
|
// the acceleration used to define the distance-velocity curve
|
||||||
|
#ifndef ALT_HOLD_ACCEL_MAX
|
||||||
|
# define ALT_HOLD_ACCEL_MAX 250 // if you change this you must also update the duplicate declaration in AC_WPNav.h
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef AUTO_DISARMING_DELAY
|
||||||
|
# define AUTO_DISARMING_DELAY 10
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Throw mode configuration
|
||||||
|
//
|
||||||
|
#ifndef THROW_HIGH_SPEED
|
||||||
|
# define THROW_HIGH_SPEED 500.0f // vehicle much reach this total 3D speed in cm/s (or be free falling)
|
||||||
|
#endif
|
||||||
|
#ifndef THROW_VERTICAL_SPEED
|
||||||
|
# define THROW_VERTICAL_SPEED 50.0f // motors start when vehicle reaches this total 3D speed in cm/s
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Logging control
|
||||||
|
//
|
||||||
|
#ifndef LOGGING_ENABLED
|
||||||
|
# define LOGGING_ENABLED ENABLED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Default logging bitmask
|
||||||
|
#ifndef DEFAULT_LOG_BITMASK
|
||||||
|
# define DEFAULT_LOG_BITMASK \
|
||||||
|
MASK_LOG_ATTITUDE_MED | \
|
||||||
|
MASK_LOG_GPS | \
|
||||||
|
MASK_LOG_PM | \
|
||||||
|
MASK_LOG_CTUN | \
|
||||||
|
MASK_LOG_NTUN | \
|
||||||
|
MASK_LOG_RCIN | \
|
||||||
|
MASK_LOG_IMU | \
|
||||||
|
MASK_LOG_CMD | \
|
||||||
|
MASK_LOG_CURRENT | \
|
||||||
|
MASK_LOG_RCOUT | \
|
||||||
|
MASK_LOG_OPTFLOW | \
|
||||||
|
MASK_LOG_COMPASS | \
|
||||||
|
MASK_LOG_CAMERA | \
|
||||||
|
MASK_LOG_MOTBATT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef CH_MODE_DEFAULT
|
||||||
|
# define CH_MODE_DEFAULT 5
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef STATS_ENABLED
|
||||||
|
# define STATS_ENABLED ENABLED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAL_FRAME_TYPE_DEFAULT
|
||||||
|
#define HAL_FRAME_TYPE_DEFAULT Fins::MOTOR_FRAME_TYPE_AIRFISH
|
||||||
|
#endif
|
|
@ -0,0 +1,209 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <AP_HAL/AP_HAL_Boards.h>
|
||||||
|
|
||||||
|
// Just so that it's completely clear...
|
||||||
|
#define ENABLED 1
|
||||||
|
#define DISABLED 0
|
||||||
|
|
||||||
|
// this avoids a very common config error
|
||||||
|
#define ENABLE ENABLED
|
||||||
|
#define DISABLE DISABLED
|
||||||
|
|
||||||
|
// Autopilot Yaw Mode enumeration
|
||||||
|
enum autopilot_yaw_mode {
|
||||||
|
AUTO_YAW_HOLD = 0, // pilot controls the heading
|
||||||
|
AUTO_YAW_LOOK_AT_NEXT_WP = 1, // point towards next waypoint (no pilot input accepted)
|
||||||
|
AUTO_YAW_ROI = 2, // point towards a location held in roi (no pilot input accepted)
|
||||||
|
AUTO_YAW_FIXED = 3, // point towards a particular angle (no pilot input accepted)
|
||||||
|
AUTO_YAW_LOOK_AHEAD = 4, // point in the direction the blimp is moving
|
||||||
|
AUTO_YAW_RESETTOARMEDYAW = 5, // point towards heading at time motors were armed
|
||||||
|
AUTO_YAW_RATE = 6, // turn at a specified rate (held in auto_yaw_rate)
|
||||||
|
AUTO_YAW_CIRCLE = 7, // use AC_Circle's provided yaw (used during Loiter-Turns commands)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Frame types
|
||||||
|
#define UNDEFINED_FRAME 0
|
||||||
|
#define MULTICOPTER_FRAME 1
|
||||||
|
#define HELI_FRAME 2
|
||||||
|
|
||||||
|
// HIL enumerations
|
||||||
|
#define HIL_MODE_DISABLED 0
|
||||||
|
#define HIL_MODE_SENSORS 1
|
||||||
|
|
||||||
|
// Tuning enumeration
|
||||||
|
enum tuning_func {
|
||||||
|
TUNING_NONE = 0, //
|
||||||
|
TUNING_STABILIZE_ROLL_PITCH_KP = 1, // stabilize roll/pitch angle controller's P term
|
||||||
|
TUNING_STABILIZE_YAW_KP = 3, // stabilize yaw heading controller's P term
|
||||||
|
TUNING_RATE_ROLL_PITCH_KP = 4, // body frame roll/pitch rate controller's P term
|
||||||
|
TUNING_RATE_ROLL_PITCH_KI = 5, // body frame roll/pitch rate controller's I term
|
||||||
|
TUNING_YAW_RATE_KP = 6, // body frame yaw rate controller's P term
|
||||||
|
TUNING_THROTTLE_RATE_KP = 7, // throttle rate controller's P term (desired rate to acceleration or motor output)
|
||||||
|
TUNING_WP_SPEED = 10, // maximum speed to next way point (0 to 10m/s)
|
||||||
|
TUNING_LOITER_POSITION_KP = 12, // loiter distance controller's P term (position error to speed)
|
||||||
|
TUNING_HELI_EXTERNAL_GYRO = 13, // TradHeli specific external tail gyro gain
|
||||||
|
TUNING_ALTITUDE_HOLD_KP = 14, // altitude hold controller's P term (alt error to desired rate)
|
||||||
|
TUNING_RATE_ROLL_PITCH_KD = 21, // body frame roll/pitch rate controller's D term
|
||||||
|
TUNING_VEL_XY_KP = 22, // loiter rate controller's P term (speed error to tilt angle)
|
||||||
|
TUNING_ACRO_RP_KP = 25, // acro controller's P term. converts pilot input to a desired roll, pitch or yaw rate
|
||||||
|
TUNING_YAW_RATE_KD = 26, // body frame yaw rate controller's D term
|
||||||
|
TUNING_VEL_XY_KI = 28, // loiter rate controller's I term (speed error to tilt angle)
|
||||||
|
TUNING_AHRS_YAW_KP = 30, // ahrs's compass effect on yaw angle (0 = very low, 1 = very high)
|
||||||
|
TUNING_AHRS_KP = 31, // accelerometer effect on roll/pitch angle (0=low)
|
||||||
|
TUNING_ACCEL_Z_KP = 34, // accel based throttle controller's P term
|
||||||
|
TUNING_ACCEL_Z_KI = 35, // accel based throttle controller's I term
|
||||||
|
TUNING_ACCEL_Z_KD = 36, // accel based throttle controller's D term
|
||||||
|
TUNING_DECLINATION = 38, // compass declination in radians
|
||||||
|
TUNING_CIRCLE_RATE = 39, // circle turn rate in degrees (hard coded to about 45 degrees in either direction)
|
||||||
|
TUNING_ACRO_YAW_KP = 40, // acro controller's P term. converts pilot input to a desired roll, pitch or yaw rate
|
||||||
|
TUNING_RANGEFINDER_GAIN = 41, // rangefinder gain
|
||||||
|
TUNING_EKF_VERTICAL_POS = 42, // unused
|
||||||
|
TUNING_EKF_HORIZONTAL_POS = 43, // unused
|
||||||
|
TUNING_EKF_ACCEL_NOISE = 44, // unused
|
||||||
|
TUNING_RC_FEEL_RP = 45, // roll-pitch input smoothing
|
||||||
|
TUNING_RATE_PITCH_KP = 46, // body frame pitch rate controller's P term
|
||||||
|
TUNING_RATE_PITCH_KI = 47, // body frame pitch rate controller's I term
|
||||||
|
TUNING_RATE_PITCH_KD = 48, // body frame pitch rate controller's D term
|
||||||
|
TUNING_RATE_ROLL_KP = 49, // body frame roll rate controller's P term
|
||||||
|
TUNING_RATE_ROLL_KI = 50, // body frame roll rate controller's I term
|
||||||
|
TUNING_RATE_ROLL_KD = 51, // body frame roll rate controller's D term
|
||||||
|
TUNING_RATE_PITCH_FF = 52, // body frame pitch rate controller FF term
|
||||||
|
TUNING_RATE_ROLL_FF = 53, // body frame roll rate controller FF term
|
||||||
|
TUNING_RATE_YAW_FF = 54, // body frame yaw rate controller FF term
|
||||||
|
TUNING_RATE_MOT_YAW_HEADROOM = 55, // motors yaw headroom minimum
|
||||||
|
TUNING_RATE_YAW_FILT = 56, // yaw rate input filter
|
||||||
|
UNUSED = 57, // was winch control
|
||||||
|
TUNING_SYSTEM_ID_MAGNITUDE = 58 // magnitude of the system ID signal
|
||||||
|
};
|
||||||
|
|
||||||
|
// Yaw behaviours during missions - possible values for WP_YAW_BEHAVIOR parameter
|
||||||
|
#define WP_YAW_BEHAVIOR_NONE 0 // auto pilot will never control yaw during missions or rtl (except for DO_CONDITIONAL_YAW command received)
|
||||||
|
#define WP_YAW_BEHAVIOR_LOOK_AT_NEXT_WP 1 // auto pilot will face next waypoint or home during rtl
|
||||||
|
#define WP_YAW_BEHAVIOR_LOOK_AT_NEXT_WP_EXCEPT_RTL 2 // auto pilot will face next waypoint except when doing RTL at which time it will stay in it's last
|
||||||
|
#define WP_YAW_BEHAVIOR_LOOK_AHEAD 3 // auto pilot will look ahead during missions and rtl (primarily meant for traditional helicopters)
|
||||||
|
|
||||||
|
// Auto modes
|
||||||
|
enum AutoMode {
|
||||||
|
Auto_TakeOff,
|
||||||
|
Auto_WP,
|
||||||
|
Auto_Land,
|
||||||
|
Auto_RTL,
|
||||||
|
Auto_CircleMoveToEdge,
|
||||||
|
Auto_Circle,
|
||||||
|
Auto_Spline,
|
||||||
|
Auto_NavGuided,
|
||||||
|
Auto_Loiter,
|
||||||
|
Auto_LoiterToAlt,
|
||||||
|
Auto_NavPayloadPlace,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Guided modes
|
||||||
|
enum GuidedMode {
|
||||||
|
Guided_TakeOff,
|
||||||
|
Guided_WP,
|
||||||
|
Guided_Velocity,
|
||||||
|
Guided_PosVel,
|
||||||
|
Guided_Angle,
|
||||||
|
};
|
||||||
|
|
||||||
|
// // Airmode
|
||||||
|
// enum class AirMode {
|
||||||
|
// AIRMODE_NONE,
|
||||||
|
// AIRMODE_DISABLED,
|
||||||
|
// AIRMODE_ENABLED,
|
||||||
|
// };
|
||||||
|
|
||||||
|
// // Safe RTL states
|
||||||
|
// enum SmartRTLState {
|
||||||
|
// SmartRTL_WaitForPathCleanup,
|
||||||
|
// SmartRTL_PathFollow,
|
||||||
|
// SmartRTL_PreLandPosition,
|
||||||
|
// SmartRTL_Descend,
|
||||||
|
// SmartRTL_Land
|
||||||
|
// };
|
||||||
|
|
||||||
|
enum PayloadPlaceStateType {
|
||||||
|
PayloadPlaceStateType_FlyToLocation,
|
||||||
|
PayloadPlaceStateType_Calibrating_Hover_Start,
|
||||||
|
PayloadPlaceStateType_Calibrating_Hover,
|
||||||
|
PayloadPlaceStateType_Descending_Start,
|
||||||
|
PayloadPlaceStateType_Descending,
|
||||||
|
PayloadPlaceStateType_Releasing_Start,
|
||||||
|
PayloadPlaceStateType_Releasing,
|
||||||
|
PayloadPlaceStateType_Released,
|
||||||
|
PayloadPlaceStateType_Ascending_Start,
|
||||||
|
PayloadPlaceStateType_Ascending,
|
||||||
|
PayloadPlaceStateType_Done,
|
||||||
|
};
|
||||||
|
|
||||||
|
// bit options for DEV_OPTIONS parameter
|
||||||
|
enum DevOptions {
|
||||||
|
DevOptionADSBMAVLink = 1,
|
||||||
|
DevOptionVFR_HUDRelativeAlt = 2,
|
||||||
|
DevOptionSetAttitudeTarget_ThrustAsThrust = 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Logging parameters
|
||||||
|
enum LoggingParameters {
|
||||||
|
LOG_CONTROL_TUNING_MSG,
|
||||||
|
LOG_DATA_INT16_MSG,
|
||||||
|
LOG_DATA_UINT16_MSG,
|
||||||
|
LOG_DATA_INT32_MSG,
|
||||||
|
LOG_DATA_UINT32_MSG,
|
||||||
|
LOG_DATA_FLOAT_MSG,
|
||||||
|
LOG_MOTBATT_MSG,
|
||||||
|
LOG_PARAMTUNE_MSG,
|
||||||
|
LOG_HELI_MSG,
|
||||||
|
LOG_PRECLAND_MSG,
|
||||||
|
LOG_GUIDEDTARGET_MSG,
|
||||||
|
LOG_SYSIDD_MSG,
|
||||||
|
LOG_SYSIDS_MSG,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MASK_LOG_ATTITUDE_FAST (1<<0)
|
||||||
|
#define MASK_LOG_ATTITUDE_MED (1<<1)
|
||||||
|
#define MASK_LOG_GPS (1<<2)
|
||||||
|
#define MASK_LOG_PM (1<<3)
|
||||||
|
#define MASK_LOG_CTUN (1<<4)
|
||||||
|
#define MASK_LOG_NTUN (1<<5)
|
||||||
|
#define MASK_LOG_RCIN (1<<6)
|
||||||
|
#define MASK_LOG_IMU (1<<7)
|
||||||
|
#define MASK_LOG_CMD (1<<8)
|
||||||
|
#define MASK_LOG_CURRENT (1<<9)
|
||||||
|
#define MASK_LOG_RCOUT (1<<10)
|
||||||
|
#define MASK_LOG_OPTFLOW (1<<11)
|
||||||
|
#define MASK_LOG_PID (1<<12)
|
||||||
|
#define MASK_LOG_COMPASS (1<<13)
|
||||||
|
#define MASK_LOG_INAV (1<<14) // deprecated
|
||||||
|
#define MASK_LOG_CAMERA (1<<15)
|
||||||
|
#define MASK_LOG_MOTBATT (1UL<<17)
|
||||||
|
#define MASK_LOG_IMU_FAST (1UL<<18)
|
||||||
|
#define MASK_LOG_IMU_RAW (1UL<<19)
|
||||||
|
#define MASK_LOG_ANY 0xFFFF
|
||||||
|
|
||||||
|
// Radio failsafe definitions (FS_THR parameter)
|
||||||
|
#define FS_THR_DISABLED 0
|
||||||
|
#define FS_THR_ENABLED_ALWAYS_RTL 1
|
||||||
|
#define FS_THR_ENABLED_CONTINUE_MISSION 2 // Removed in 4.0+, now use fs_options
|
||||||
|
#define FS_THR_ENABLED_ALWAYS_LAND 3
|
||||||
|
#define FS_THR_ENABLED_ALWAYS_SMARTRTL_OR_RTL 4
|
||||||
|
#define FS_THR_ENABLED_ALWAYS_SMARTRTL_OR_LAND 5
|
||||||
|
|
||||||
|
// GCS failsafe definitions (FS_GCS_ENABLE parameter)
|
||||||
|
#define FS_GCS_DISABLED 0
|
||||||
|
#define FS_GCS_ENABLED_ALWAYS_RTL 1
|
||||||
|
#define FS_GCS_ENABLED_CONTINUE_MISSION 2 // Removed in 4.0+, now use fs_options
|
||||||
|
#define FS_GCS_ENABLED_ALWAYS_SMARTRTL_OR_RTL 3
|
||||||
|
#define FS_GCS_ENABLED_ALWAYS_SMARTRTL_OR_LAND 4
|
||||||
|
#define FS_GCS_ENABLED_ALWAYS_LAND 5
|
||||||
|
|
||||||
|
// EKF failsafe definitions (FS_EKF_ACTION parameter)
|
||||||
|
#define FS_EKF_ACTION_LAND 1 // switch to LAND mode on EKF failsafe
|
||||||
|
#define FS_EKF_ACTION_ALTHOLD 2 // switch to ALTHOLD mode on EKF failsafe
|
||||||
|
#define FS_EKF_ACTION_LAND_EVEN_STABILIZE 3 // switch to Land mode on EKF failsafe even if in a manual flight mode like stabilize
|
||||||
|
|
||||||
|
// for PILOT_THR_BHV parameter
|
||||||
|
#define THR_BEHAVE_FEEDBACK_FROM_MID_STICK (1<<0)
|
||||||
|
#define THR_BEHAVE_HIGH_THROTTLE_CANCELS_LAND (1<<1)
|
||||||
|
#define THR_BEHAVE_DISARM_ON_LAND_DETECT (1<<2)
|
|
@ -0,0 +1,272 @@
|
||||||
|
#include "Blimp.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Detects failures of the ekf or inertial nav system triggers an alert
|
||||||
|
* to the pilot and helps take countermeasures
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EKF_CHECK_ITERATIONS_MAX
|
||||||
|
# define EKF_CHECK_ITERATIONS_MAX 10 // 1 second (ie. 10 iterations at 10hz) of bad variances signals a failure
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef EKF_CHECK_WARNING_TIME
|
||||||
|
# define EKF_CHECK_WARNING_TIME (30*1000) // warning text messages are sent to ground no more than every 30 seconds
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// EKF_check structure
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
static struct {
|
||||||
|
uint8_t fail_count; // number of iterations ekf or dcm have been out of tolerances
|
||||||
|
uint8_t bad_variance : 1; // true if ekf should be considered untrusted (fail_count has exceeded EKF_CHECK_ITERATIONS_MAX)
|
||||||
|
uint32_t last_warn_time; // system time of last warning in milliseconds. Used to throttle text warnings sent to GCS
|
||||||
|
} ekf_check_state;
|
||||||
|
|
||||||
|
// ekf_check - detects if ekf variance are out of tolerance and triggers failsafe
|
||||||
|
// should be called at 10hz
|
||||||
|
void Blimp::ekf_check()
|
||||||
|
{
|
||||||
|
// ensure EKF_CHECK_ITERATIONS_MAX is at least 7
|
||||||
|
static_assert(EKF_CHECK_ITERATIONS_MAX >= 7, "EKF_CHECK_ITERATIONS_MAX must be at least 7");
|
||||||
|
|
||||||
|
// exit immediately if ekf has no origin yet - this assumes the origin can never become unset
|
||||||
|
Location temp_loc;
|
||||||
|
if (!ahrs.get_origin(temp_loc)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return immediately if motors are not armed, or ekf check is disabled
|
||||||
|
if (!motors->armed() || (g.fs_ekf_thresh <= 0.0f)) {
|
||||||
|
ekf_check_state.fail_count = 0;
|
||||||
|
ekf_check_state.bad_variance = false;
|
||||||
|
AP_Notify::flags.ekf_bad = ekf_check_state.bad_variance;
|
||||||
|
failsafe_ekf_off_event(); // clear failsafe
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// compare compass and velocity variance vs threshold and also check
|
||||||
|
// if we are still navigating
|
||||||
|
bool is_navigating = ekf_has_relative_position() || ekf_has_absolute_position();
|
||||||
|
if (ekf_over_threshold() || !is_navigating) {
|
||||||
|
// if compass is not yet flagged as bad
|
||||||
|
if (!ekf_check_state.bad_variance) {
|
||||||
|
// increase counter
|
||||||
|
ekf_check_state.fail_count++;
|
||||||
|
if (ekf_check_state.fail_count == (EKF_CHECK_ITERATIONS_MAX-2) && ekf_over_threshold()) {
|
||||||
|
// we are two iterations away from declaring an EKF failsafe, ask the EKF if we can reset
|
||||||
|
// yaw to resolve the issue
|
||||||
|
ahrs.request_yaw_reset();
|
||||||
|
}
|
||||||
|
if (ekf_check_state.fail_count == (EKF_CHECK_ITERATIONS_MAX-1)) {
|
||||||
|
// we are just about to declare a EKF failsafe, ask the EKF if we can
|
||||||
|
// change lanes to resolve the issue
|
||||||
|
ahrs.check_lane_switch();
|
||||||
|
}
|
||||||
|
// if counter above max then trigger failsafe
|
||||||
|
if (ekf_check_state.fail_count >= EKF_CHECK_ITERATIONS_MAX) {
|
||||||
|
// limit count from climbing too high
|
||||||
|
ekf_check_state.fail_count = EKF_CHECK_ITERATIONS_MAX;
|
||||||
|
ekf_check_state.bad_variance = true;
|
||||||
|
AP::logger().Write_Error(LogErrorSubsystem::EKFCHECK, LogErrorCode::EKFCHECK_BAD_VARIANCE);
|
||||||
|
// send message to gcs
|
||||||
|
if ((AP_HAL::millis() - ekf_check_state.last_warn_time) > EKF_CHECK_WARNING_TIME) {
|
||||||
|
gcs().send_text(MAV_SEVERITY_CRITICAL,"EKF variance");
|
||||||
|
ekf_check_state.last_warn_time = AP_HAL::millis();
|
||||||
|
}
|
||||||
|
failsafe_ekf_event();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// reduce counter
|
||||||
|
if (ekf_check_state.fail_count > 0) {
|
||||||
|
ekf_check_state.fail_count--;
|
||||||
|
|
||||||
|
// if compass is flagged as bad and the counter reaches zero then clear flag
|
||||||
|
if (ekf_check_state.bad_variance && ekf_check_state.fail_count == 0) {
|
||||||
|
ekf_check_state.bad_variance = false;
|
||||||
|
AP::logger().Write_Error(LogErrorSubsystem::EKFCHECK, LogErrorCode::EKFCHECK_VARIANCE_CLEARED);
|
||||||
|
// clear failsafe
|
||||||
|
failsafe_ekf_off_event();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// set AP_Notify flags
|
||||||
|
AP_Notify::flags.ekf_bad = ekf_check_state.bad_variance;
|
||||||
|
|
||||||
|
// To-Do: add ekf variances to extended status
|
||||||
|
}
|
||||||
|
|
||||||
|
// ekf_over_threshold - returns true if the ekf's variance are over the tolerance
|
||||||
|
bool Blimp::ekf_over_threshold()
|
||||||
|
{
|
||||||
|
// return false immediately if disabled
|
||||||
|
if (g.fs_ekf_thresh <= 0.0f) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// use EKF to get variance
|
||||||
|
float position_variance, vel_variance, height_variance, tas_variance;
|
||||||
|
Vector3f mag_variance;
|
||||||
|
ahrs.get_variances(vel_variance, position_variance, height_variance, mag_variance, tas_variance);
|
||||||
|
|
||||||
|
const float mag_max = fmaxf(fmaxf(mag_variance.x,mag_variance.y),mag_variance.z);
|
||||||
|
|
||||||
|
// return true if two of compass, velocity and position variances are over the threshold OR velocity variance is twice the threshold
|
||||||
|
uint8_t over_thresh_count = 0;
|
||||||
|
if (mag_max >= g.fs_ekf_thresh) {
|
||||||
|
over_thresh_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool optflow_healthy = false;
|
||||||
|
if (!optflow_healthy && (vel_variance >= (2.0f * g.fs_ekf_thresh))) {
|
||||||
|
over_thresh_count += 2;
|
||||||
|
} else if (vel_variance >= g.fs_ekf_thresh) {
|
||||||
|
over_thresh_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((position_variance >= g.fs_ekf_thresh && over_thresh_count >= 1) || over_thresh_count >= 2) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// failsafe_ekf_event - perform ekf failsafe
|
||||||
|
void Blimp::failsafe_ekf_event()
|
||||||
|
{
|
||||||
|
// return immediately if ekf failsafe already triggered
|
||||||
|
if (failsafe.ekf) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// EKF failsafe event has occurred
|
||||||
|
failsafe.ekf = true;
|
||||||
|
AP::logger().Write_Error(LogErrorSubsystem::FAILSAFE_EKFINAV, LogErrorCode::FAILSAFE_OCCURRED);
|
||||||
|
|
||||||
|
// // sometimes LAND *does* require GPS so ensure we are in non-GPS land
|
||||||
|
// if (control_mode == Mode::Number::LAND && landing_with_GPS()) {
|
||||||
|
// mode_land.do_not_use_GPS();
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// LAND never requires GPS.
|
||||||
|
|
||||||
|
// does this mode require position?
|
||||||
|
if (!blimp.flightmode->requires_GPS() && (g.fs_ekf_action != FS_EKF_ACTION_LAND_EVEN_STABILIZE)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// take action based on fs_ekf_action parameter
|
||||||
|
switch (g.fs_ekf_action) {
|
||||||
|
case FS_EKF_ACTION_LAND:
|
||||||
|
case FS_EKF_ACTION_LAND_EVEN_STABILIZE:
|
||||||
|
default:
|
||||||
|
set_mode_land_with_pause(ModeReason::EKF_FAILSAFE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// failsafe_ekf_off_event - actions to take when EKF failsafe is cleared
|
||||||
|
void Blimp::failsafe_ekf_off_event(void)
|
||||||
|
{
|
||||||
|
// return immediately if not in ekf failsafe
|
||||||
|
if (!failsafe.ekf) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
failsafe.ekf = false;
|
||||||
|
AP::logger().Write_Error(LogErrorSubsystem::FAILSAFE_EKFINAV, LogErrorCode::FAILSAFE_RESOLVED);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for ekf yaw reset and adjust target heading, also log position reset
|
||||||
|
void Blimp::check_ekf_reset()
|
||||||
|
{
|
||||||
|
// check for yaw reset
|
||||||
|
float yaw_angle_change_rad;
|
||||||
|
uint32_t new_ekfYawReset_ms = ahrs.getLastYawResetAngle(yaw_angle_change_rad);
|
||||||
|
if (new_ekfYawReset_ms != ekfYawReset_ms) {
|
||||||
|
// attitude_control->inertial_frame_reset();
|
||||||
|
ekfYawReset_ms = new_ekfYawReset_ms;
|
||||||
|
AP::logger().Write_Event(LogEvent::EKF_YAW_RESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if AP_AHRS_NAVEKF_AVAILABLE && (HAL_NAVEKF2_AVAILABLE || HAL_NAVEKF3_AVAILABLE)
|
||||||
|
// check for change in primary EKF, reset attitude target and log. AC_PosControl handles position target adjustment
|
||||||
|
if ((ahrs.get_primary_core_index() != ekf_primary_core) && (ahrs.get_primary_core_index() != -1)) {
|
||||||
|
// attitude_control->inertial_frame_reset();
|
||||||
|
ekf_primary_core = ahrs.get_primary_core_index();
|
||||||
|
AP::logger().Write_Error(LogErrorSubsystem::EKF_PRIMARY, LogErrorCode(ekf_primary_core));
|
||||||
|
gcs().send_text(MAV_SEVERITY_WARNING, "EKF primary changed:%d", (unsigned)ekf_primary_core);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for high vibrations affecting altitude control
|
||||||
|
void Blimp::check_vibration()
|
||||||
|
{
|
||||||
|
uint32_t now = AP_HAL::millis();
|
||||||
|
|
||||||
|
// assume checks will succeed
|
||||||
|
bool checks_succeeded = true;
|
||||||
|
|
||||||
|
// check if vertical velocity and position innovations are positive (NKF3.IVD & NKF3.IPD are both positive)
|
||||||
|
Vector3f vel_innovation;
|
||||||
|
Vector3f pos_innovation;
|
||||||
|
Vector3f mag_innovation;
|
||||||
|
float tas_innovation;
|
||||||
|
float yaw_innovation;
|
||||||
|
if (!ahrs.get_innovations(vel_innovation, pos_innovation, mag_innovation, tas_innovation, yaw_innovation)) {
|
||||||
|
checks_succeeded = false;
|
||||||
|
}
|
||||||
|
const bool innov_velD_posD_positive = is_positive(vel_innovation.z) && is_positive(pos_innovation.z);
|
||||||
|
|
||||||
|
// check if vertical velocity variance is at least 1 (NK4.SV >= 1.0)
|
||||||
|
float position_variance, vel_variance, height_variance, tas_variance;
|
||||||
|
Vector3f mag_variance;
|
||||||
|
if (!ahrs.get_variances(vel_variance, position_variance, height_variance, mag_variance, tas_variance)) {
|
||||||
|
checks_succeeded = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if no failure
|
||||||
|
if ((g2.fs_vibe_enabled == 0) || !checks_succeeded || !motors->armed() || !innov_velD_posD_positive || (vel_variance < 1.0f)) {
|
||||||
|
if (vibration_check.high_vibes) {
|
||||||
|
// start clear time
|
||||||
|
if (vibration_check.clear_ms == 0) {
|
||||||
|
vibration_check.clear_ms = now;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// turn off vibration compensation after 15 seconds
|
||||||
|
if (now - vibration_check.clear_ms > 15000) {
|
||||||
|
// restore ekf gains, reset timers and update user
|
||||||
|
vibration_check.high_vibes = false;
|
||||||
|
// pos_control->set_vibe_comp(false);
|
||||||
|
vibration_check.clear_ms = 0;
|
||||||
|
AP::logger().Write_Error(LogErrorSubsystem::FAILSAFE_VIBE, LogErrorCode::FAILSAFE_RESOLVED);
|
||||||
|
gcs().send_text(MAV_SEVERITY_CRITICAL, "Vibration compensation OFF");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vibration_check.start_ms = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// start timer
|
||||||
|
if (vibration_check.start_ms == 0) {
|
||||||
|
vibration_check.start_ms = now;
|
||||||
|
vibration_check.clear_ms = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if failure has persisted for at least 1 second
|
||||||
|
if (now - vibration_check.start_ms > 1000) {
|
||||||
|
if (!vibration_check.high_vibes) {
|
||||||
|
// switch ekf to use resistant gains
|
||||||
|
vibration_check.high_vibes = true;
|
||||||
|
// pos_control->set_vibe_comp(true);
|
||||||
|
AP::logger().Write_Error(LogErrorSubsystem::FAILSAFE_VIBE, LogErrorCode::FAILSAFE_OCCURRED);
|
||||||
|
gcs().send_text(MAV_SEVERITY_CRITICAL, "Vibration compensation ON");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,343 @@
|
||||||
|
#include "Blimp.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This event will be called when the failsafe changes
|
||||||
|
* boolean failsafe reflects the current state
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
bool Blimp::failsafe_option(FailsafeOption opt) const
|
||||||
|
{
|
||||||
|
return (g2.fs_options & (uint32_t)opt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Blimp::failsafe_radio_on_event()
|
||||||
|
{
|
||||||
|
AP::logger().Write_Error(LogErrorSubsystem::FAILSAFE_RADIO, LogErrorCode::FAILSAFE_OCCURRED);
|
||||||
|
|
||||||
|
// set desired action based on FS_THR_ENABLE parameter
|
||||||
|
Failsafe_Action desired_action;
|
||||||
|
switch (g.failsafe_throttle) {
|
||||||
|
case FS_THR_DISABLED:
|
||||||
|
desired_action = Failsafe_Action_None;
|
||||||
|
break;
|
||||||
|
case FS_THR_ENABLED_ALWAYS_LAND:
|
||||||
|
desired_action = Failsafe_Action_Land;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
desired_action = Failsafe_Action_Land;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Conditions to deviate from FS_THR_ENABLE selection and send specific GCS warning
|
||||||
|
if (should_disarm_on_failsafe()) {
|
||||||
|
// should immediately disarm when we're on the ground
|
||||||
|
gcs().send_text(MAV_SEVERITY_WARNING, "Radio Failsafe - Disarming");
|
||||||
|
arming.disarm(AP_Arming::Method::RADIOFAILSAFE);
|
||||||
|
desired_action = Failsafe_Action_None;
|
||||||
|
|
||||||
|
} else if (flightmode->is_landing() && ((battery.has_failsafed() && battery.get_highest_failsafe_priority() <= FAILSAFE_LAND_PRIORITY))) {
|
||||||
|
// Allow landing to continue when battery failsafe requires it (not a user option)
|
||||||
|
gcs().send_text(MAV_SEVERITY_WARNING, "Radio + Battery Failsafe - Continuing Landing");
|
||||||
|
desired_action = Failsafe_Action_Land;
|
||||||
|
|
||||||
|
} else if (flightmode->is_landing() && failsafe_option(FailsafeOption::CONTINUE_IF_LANDING)) {
|
||||||
|
// Allow landing to continue when FS_OPTIONS is set to continue landing
|
||||||
|
gcs().send_text(MAV_SEVERITY_WARNING, "Radio Failsafe - Continuing Landing");
|
||||||
|
desired_action = Failsafe_Action_Land;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
gcs().send_text(MAV_SEVERITY_WARNING, "Radio Failsafe");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the failsafe action handler
|
||||||
|
do_failsafe_action(desired_action, ModeReason::RADIO_FAILSAFE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// failsafe_off_event - respond to radio contact being regained
|
||||||
|
void Blimp::failsafe_radio_off_event()
|
||||||
|
{
|
||||||
|
// no need to do anything except log the error as resolved
|
||||||
|
// user can now override roll, pitch, yaw and throttle and even use flight mode switch to restore previous flight mode
|
||||||
|
AP::logger().Write_Error(LogErrorSubsystem::FAILSAFE_RADIO, LogErrorCode::FAILSAFE_RESOLVED);
|
||||||
|
gcs().send_text(MAV_SEVERITY_WARNING, "Radio Failsafe Cleared");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Blimp::handle_battery_failsafe(const char *type_str, const int8_t action)
|
||||||
|
{
|
||||||
|
AP::logger().Write_Error(LogErrorSubsystem::FAILSAFE_BATT, LogErrorCode::FAILSAFE_OCCURRED);
|
||||||
|
|
||||||
|
Failsafe_Action desired_action = (Failsafe_Action)action;
|
||||||
|
|
||||||
|
// Conditions to deviate from BATT_FS_XXX_ACT parameter setting
|
||||||
|
if (should_disarm_on_failsafe()) {
|
||||||
|
// should immediately disarm when we're on the ground
|
||||||
|
arming.disarm(AP_Arming::Method::BATTERYFAILSAFE);
|
||||||
|
desired_action = Failsafe_Action_None;
|
||||||
|
gcs().send_text(MAV_SEVERITY_WARNING, "Battery Failsafe - Disarming");
|
||||||
|
|
||||||
|
} else if (flightmode->is_landing() && failsafe_option(FailsafeOption::CONTINUE_IF_LANDING) && desired_action != Failsafe_Action_None) {
|
||||||
|
// Allow landing to continue when FS_OPTIONS is set to continue when landing
|
||||||
|
desired_action = Failsafe_Action_Land;
|
||||||
|
gcs().send_text(MAV_SEVERITY_WARNING, "Battery Failsafe - Continuing Landing");
|
||||||
|
} else {
|
||||||
|
gcs().send_text(MAV_SEVERITY_WARNING, "Battery Failsafe");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Battery FS options already use the Failsafe_Options enum. So use them directly.
|
||||||
|
do_failsafe_action(desired_action, ModeReason::BATTERY_FAILSAFE);
|
||||||
|
|
||||||
|
}
|
||||||
|
// failsafe_gcs_check - check for ground station failsafe
|
||||||
|
void Blimp::failsafe_gcs_check()
|
||||||
|
{
|
||||||
|
// Bypass GCS failsafe checks if disabled or GCS never connected
|
||||||
|
if (g.failsafe_gcs == FS_GCS_DISABLED || failsafe.last_heartbeat_ms == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// calc time since last gcs update
|
||||||
|
// note: this only looks at the heartbeat from the device id set by g.sysid_my_gcs
|
||||||
|
const uint32_t last_gcs_update_ms = millis() - failsafe.last_heartbeat_ms;
|
||||||
|
const uint32_t gcs_timeout_ms = uint32_t(constrain_float(g2.fs_gcs_timeout * 1000.0f, 0.0f, UINT32_MAX));
|
||||||
|
|
||||||
|
// Determine which event to trigger
|
||||||
|
if (last_gcs_update_ms < gcs_timeout_ms && failsafe.gcs) {
|
||||||
|
// Recovery from a GCS failsafe
|
||||||
|
set_failsafe_gcs(false);
|
||||||
|
// failsafe_gcs_off_event();
|
||||||
|
|
||||||
|
} else if (last_gcs_update_ms < gcs_timeout_ms && !failsafe.gcs) {
|
||||||
|
// No problem, do nothing
|
||||||
|
|
||||||
|
} else if (last_gcs_update_ms > gcs_timeout_ms && failsafe.gcs) {
|
||||||
|
// Already in failsafe, do nothing
|
||||||
|
|
||||||
|
} else if (last_gcs_update_ms > gcs_timeout_ms && !failsafe.gcs) {
|
||||||
|
// New GCS failsafe event, trigger events
|
||||||
|
set_failsafe_gcs(true);
|
||||||
|
// failsafe_gcs_on_event();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
// failsafe_gcs_on_event - actions to take when GCS contact is lost
|
||||||
|
void Blimp::failsafe_gcs_on_event(void)
|
||||||
|
{
|
||||||
|
AP::logger().Write_Error(LogErrorSubsystem::FAILSAFE_GCS, LogErrorCode::FAILSAFE_OCCURRED);
|
||||||
|
RC_Channels::clear_overrides();
|
||||||
|
|
||||||
|
// convert the desired failsafe response to the Failsafe_Action enum
|
||||||
|
Failsafe_Action desired_action;
|
||||||
|
switch (g.failsafe_gcs) {
|
||||||
|
case FS_GCS_DISABLED:
|
||||||
|
desired_action = Failsafe_Action_None;
|
||||||
|
break;
|
||||||
|
case FS_GCS_ENABLED_ALWAYS_RTL:
|
||||||
|
case FS_GCS_ENABLED_CONTINUE_MISSION:
|
||||||
|
desired_action = Failsafe_Action_RTL;
|
||||||
|
break;
|
||||||
|
case FS_GCS_ENABLED_ALWAYS_SMARTRTL_OR_RTL:
|
||||||
|
desired_action = Failsafe_Action_SmartRTL;
|
||||||
|
break;
|
||||||
|
case FS_GCS_ENABLED_ALWAYS_SMARTRTL_OR_LAND:
|
||||||
|
desired_action = Failsafe_Action_SmartRTL_Land;
|
||||||
|
break;
|
||||||
|
case FS_GCS_ENABLED_ALWAYS_LAND:
|
||||||
|
desired_action = Failsafe_Action_Land;
|
||||||
|
break;
|
||||||
|
default: // if an invalid parameter value is set, the fallback is RTL
|
||||||
|
desired_action = Failsafe_Action_RTL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Conditions to deviate from FS_GCS_ENABLE parameter setting
|
||||||
|
if (!motors->armed()) {
|
||||||
|
desired_action = Failsafe_Action_None;
|
||||||
|
gcs().send_text(MAV_SEVERITY_WARNING, "GCS Failsafe");
|
||||||
|
|
||||||
|
} else if (should_disarm_on_failsafe()) {
|
||||||
|
// should immediately disarm when we're on the ground
|
||||||
|
arming.disarm(AP_Arming::Method::GCSFAILSAFE);
|
||||||
|
desired_action = Failsafe_Action_None;
|
||||||
|
gcs().send_text(MAV_SEVERITY_WARNING, "GCS Failsafe - Disarming");
|
||||||
|
|
||||||
|
} else if (flightmode->is_landing() && ((battery.has_failsafed() && battery.get_highest_failsafe_priority() <= FAILSAFE_LAND_PRIORITY))) {
|
||||||
|
// Allow landing to continue when battery failsafe requires it (not a user option)
|
||||||
|
gcs().send_text(MAV_SEVERITY_WARNING, "GCS + Battery Failsafe - Continuing Landing");
|
||||||
|
desired_action = Failsafe_Action_Land;
|
||||||
|
|
||||||
|
} else if (flightmode->is_landing() && failsafe_option(FailsafeOption::CONTINUE_IF_LANDING)) {
|
||||||
|
// Allow landing to continue when FS_OPTIONS is set to continue landing
|
||||||
|
gcs().send_text(MAV_SEVERITY_WARNING, "GCS Failsafe - Continuing Landing");
|
||||||
|
desired_action = Failsafe_Action_Land;
|
||||||
|
|
||||||
|
} else if (control_mode == Mode::Number::AUTO && failsafe_option(FailsafeOption::GCS_CONTINUE_IF_AUTO)) {
|
||||||
|
// Allow mission to continue when FS_OPTIONS is set to continue mission
|
||||||
|
gcs().send_text(MAV_SEVERITY_WARNING, "GCS Failsafe - Continuing Auto Mode");
|
||||||
|
desired_action = Failsafe_Action_None;
|
||||||
|
|
||||||
|
} else if (failsafe_option(FailsafeOption::GCS_CONTINUE_IF_PILOT_CONTROL) && !flightmode->is_autopilot()) {
|
||||||
|
// should continue when in a pilot controlled mode because FS_OPTIONS is set to continue in pilot controlled modes
|
||||||
|
gcs().send_text(MAV_SEVERITY_WARNING, "GCS Failsafe - Continuing Pilot Control");
|
||||||
|
desired_action = Failsafe_Action_None;
|
||||||
|
} else {
|
||||||
|
gcs().send_text(MAV_SEVERITY_WARNING, "GCS Failsafe");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the failsafe action handler
|
||||||
|
do_failsafe_action(desired_action, ModeReason::GCS_FAILSAFE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// failsafe_gcs_off_event - actions to take when GCS contact is restored
|
||||||
|
void Blimp::failsafe_gcs_off_event(void)
|
||||||
|
{
|
||||||
|
gcs().send_text(MAV_SEVERITY_WARNING, "GCS Failsafe Cleared");
|
||||||
|
AP::logger().Write_Error(LogErrorSubsystem::FAILSAFE_GCS, LogErrorCode::FAILSAFE_RESOLVED);
|
||||||
|
}
|
||||||
|
|
||||||
|
// executes terrain failsafe if data is missing for longer than a few seconds
|
||||||
|
void Blimp::failsafe_terrain_check()
|
||||||
|
{
|
||||||
|
// trigger within <n> milliseconds of failures while in various modes
|
||||||
|
bool timeout = (failsafe.terrain_last_failure_ms - failsafe.terrain_first_failure_ms) > FS_TERRAIN_TIMEOUT_MS;
|
||||||
|
bool trigger_event = timeout && flightmode->requires_terrain_failsafe();
|
||||||
|
|
||||||
|
// check for clearing of event
|
||||||
|
if (trigger_event != failsafe.terrain) {
|
||||||
|
if (trigger_event) {
|
||||||
|
failsafe_terrain_on_event();
|
||||||
|
} else {
|
||||||
|
AP::logger().Write_Error(LogErrorSubsystem::FAILSAFE_TERRAIN, LogErrorCode::ERROR_RESOLVED);
|
||||||
|
failsafe.terrain = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// set terrain data status (found or not found)
|
||||||
|
void Blimp::failsafe_terrain_set_status(bool data_ok)
|
||||||
|
{
|
||||||
|
uint32_t now = millis();
|
||||||
|
|
||||||
|
// record time of first and latest failures (i.e. duration of failures)
|
||||||
|
if (!data_ok) {
|
||||||
|
failsafe.terrain_last_failure_ms = now;
|
||||||
|
if (failsafe.terrain_first_failure_ms == 0) {
|
||||||
|
failsafe.terrain_first_failure_ms = now;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// failures cleared after 0.1 seconds of persistent successes
|
||||||
|
if (now - failsafe.terrain_last_failure_ms > 100) {
|
||||||
|
failsafe.terrain_last_failure_ms = 0;
|
||||||
|
failsafe.terrain_first_failure_ms = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// terrain failsafe action
|
||||||
|
void Blimp::failsafe_terrain_on_event()
|
||||||
|
{
|
||||||
|
failsafe.terrain = true;
|
||||||
|
gcs().send_text(MAV_SEVERITY_CRITICAL,"Failsafe: Terrain data missing");
|
||||||
|
AP::logger().Write_Error(LogErrorSubsystem::FAILSAFE_TERRAIN, LogErrorCode::FAILSAFE_OCCURRED);
|
||||||
|
|
||||||
|
if (should_disarm_on_failsafe()) {
|
||||||
|
arming.disarm(AP_Arming::Method::TERRAINFAILSAFE);
|
||||||
|
#if MODE_RTL_ENABLED == ENABLED
|
||||||
|
} else if (control_mode == Mode::Number::RTL) {
|
||||||
|
mode_rtl.restart_without_terrain();
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
set_mode_RTL_or_land_with_pause(ModeReason::TERRAIN_FAILSAFE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for gps glitch failsafe
|
||||||
|
void Blimp::gpsglitch_check()
|
||||||
|
{
|
||||||
|
// get filter status
|
||||||
|
nav_filter_status filt_status = inertial_nav.get_filter_status();
|
||||||
|
bool gps_glitching = filt_status.flags.gps_glitching;
|
||||||
|
|
||||||
|
// log start or stop of gps glitch. AP_Notify update is handled from within AP_AHRS
|
||||||
|
if (ap.gps_glitching != gps_glitching) {
|
||||||
|
ap.gps_glitching = gps_glitching;
|
||||||
|
if (gps_glitching) {
|
||||||
|
AP::logger().Write_Error(LogErrorSubsystem::GPS, LogErrorCode::GPS_GLITCH);
|
||||||
|
gcs().send_text(MAV_SEVERITY_CRITICAL,"GPS Glitch");
|
||||||
|
} else {
|
||||||
|
AP::logger().Write_Error(LogErrorSubsystem::GPS, LogErrorCode::ERROR_RESOLVED);
|
||||||
|
gcs().send_text(MAV_SEVERITY_CRITICAL,"GPS Glitch cleared");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// set_mode_RTL_or_land_with_pause - sets mode to RTL if possible or LAND with 4 second delay before descent starts
|
||||||
|
// this is always called from a failsafe so we trigger notification to pilot
|
||||||
|
void Blimp::set_mode_RTL_or_land_with_pause(ModeReason reason)
|
||||||
|
{
|
||||||
|
// attempt to switch to RTL, if this fails then switch to Land
|
||||||
|
if (!set_mode(Mode::Number::RTL, reason)) {
|
||||||
|
// set mode to land will trigger mode change notification to pilot
|
||||||
|
set_mode_land_with_pause(reason);
|
||||||
|
} else {
|
||||||
|
// alert pilot to mode change
|
||||||
|
AP_Notify::events.failsafe_mode_change = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// set_mode_SmartRTL_or_land_with_pause - sets mode to SMART_RTL if possible or LAND with 4 second delay before descent starts
|
||||||
|
// this is always called from a failsafe so we trigger notification to pilot
|
||||||
|
void Blimp::set_mode_SmartRTL_or_land_with_pause(ModeReason reason)
|
||||||
|
{
|
||||||
|
// attempt to switch to SMART_RTL, if this failed then switch to Land
|
||||||
|
if (!set_mode(Mode::Number::SMART_RTL, reason)) {
|
||||||
|
gcs().send_text(MAV_SEVERITY_WARNING, "SmartRTL Unavailable, Using Land Mode");
|
||||||
|
set_mode_land_with_pause(reason);
|
||||||
|
} else {
|
||||||
|
AP_Notify::events.failsafe_mode_change = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// set_mode_SmartRTL_or_RTL - sets mode to SMART_RTL if possible or RTL if possible or LAND with 4 second delay before descent starts
|
||||||
|
// this is always called from a failsafe so we trigger notification to pilot
|
||||||
|
void Blimp::set_mode_SmartRTL_or_RTL(ModeReason reason)
|
||||||
|
{
|
||||||
|
// attempt to switch to SmartRTL, if this failed then attempt to RTL
|
||||||
|
// if that fails, then land
|
||||||
|
if (!set_mode(Mode::Number::SMART_RTL, reason)) {
|
||||||
|
gcs().send_text(MAV_SEVERITY_WARNING, "SmartRTL Unavailable, Trying RTL Mode");
|
||||||
|
set_mode_RTL_or_land_with_pause(reason);
|
||||||
|
} else {
|
||||||
|
AP_Notify::events.failsafe_mode_change = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
bool Blimp::should_disarm_on_failsafe()
|
||||||
|
{
|
||||||
|
if (ap.in_arming_delay) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (control_mode) {
|
||||||
|
case Mode::Number::MANUAL:
|
||||||
|
default:
|
||||||
|
// if landed disarm
|
||||||
|
return ap.land_complete;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Blimp::do_failsafe_action(Failsafe_Action action, ModeReason reason)
|
||||||
|
{
|
||||||
|
|
||||||
|
// Execute the specified desired_action
|
||||||
|
switch (action) {
|
||||||
|
case Failsafe_Action_None:
|
||||||
|
return;
|
||||||
|
case Failsafe_Action_Land:
|
||||||
|
set_mode_land_with_pause(reason);
|
||||||
|
break;
|
||||||
|
case Failsafe_Action_Terminate: {
|
||||||
|
arming.disarm(AP_Arming::Method::FAILSAFE_ACTION_TERMINATE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
#include "Blimp.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// failsafe support
|
||||||
|
// Andrew Tridgell, December 2011
|
||||||
|
//
|
||||||
|
// our failsafe strategy is to detect main loop lockup and disarm the motors
|
||||||
|
//
|
||||||
|
|
||||||
|
static bool failsafe_enabled = false;
|
||||||
|
static uint16_t failsafe_last_ticks;
|
||||||
|
static uint32_t failsafe_last_timestamp;
|
||||||
|
static bool in_failsafe;
|
||||||
|
|
||||||
|
//
|
||||||
|
// failsafe_enable - enable failsafe
|
||||||
|
//
|
||||||
|
void Blimp::failsafe_enable()
|
||||||
|
{
|
||||||
|
failsafe_enabled = true;
|
||||||
|
failsafe_last_timestamp = micros();
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// failsafe_disable - used when we know we are going to delay the mainloop significantly
|
||||||
|
//
|
||||||
|
void Blimp::failsafe_disable()
|
||||||
|
{
|
||||||
|
failsafe_enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// failsafe_check - this function is called from the core timer interrupt at 1kHz.
|
||||||
|
//
|
||||||
|
void Blimp::failsafe_check()
|
||||||
|
{
|
||||||
|
uint32_t tnow = AP_HAL::micros();
|
||||||
|
|
||||||
|
const uint16_t ticks = scheduler.ticks();
|
||||||
|
if (ticks != failsafe_last_ticks) {
|
||||||
|
// the main loop is running, all is OK
|
||||||
|
failsafe_last_ticks = ticks;
|
||||||
|
failsafe_last_timestamp = tnow;
|
||||||
|
if (in_failsafe) {
|
||||||
|
in_failsafe = false;
|
||||||
|
AP::logger().Write_Error(LogErrorSubsystem::CPU, LogErrorCode::FAILSAFE_RESOLVED);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!in_failsafe && failsafe_enabled && tnow - failsafe_last_timestamp > 2000000) {
|
||||||
|
// motors are running but we have gone 2 second since the
|
||||||
|
// main loop ran. That means we're in trouble and should
|
||||||
|
// disarm the motors->
|
||||||
|
in_failsafe = true;
|
||||||
|
// reduce motors to minimum (we do not immediately disarm because we want to log the failure)
|
||||||
|
if (motors->armed()) {
|
||||||
|
motors->output_min();
|
||||||
|
}
|
||||||
|
|
||||||
|
AP::logger().Write_Error(LogErrorSubsystem::CPU, LogErrorCode::FAILSAFE_OCCURRED);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (failsafe_enabled && in_failsafe && tnow - failsafe_last_timestamp > 1000000) {
|
||||||
|
// disarm motors every second
|
||||||
|
failsafe_last_timestamp = tnow;
|
||||||
|
if (motors->armed()) {
|
||||||
|
motors->armed(false);
|
||||||
|
motors->output();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
#include "Blimp.h"
|
||||||
|
|
||||||
|
// read_inertia - read inertia in from accelerometers
|
||||||
|
void Blimp::read_inertia()
|
||||||
|
{
|
||||||
|
// inertial altitude estimates. Use barometer climb rate during high vibrations
|
||||||
|
inertial_nav.update(vibration_check.high_vibes);
|
||||||
|
|
||||||
|
// pull position from ahrs
|
||||||
|
Location loc;
|
||||||
|
ahrs.get_position(loc);
|
||||||
|
current_loc.lat = loc.lat;
|
||||||
|
current_loc.lng = loc.lng;
|
||||||
|
|
||||||
|
// exit immediately if we do not have an altitude estimate
|
||||||
|
if (!inertial_nav.get_filter_status().flags.vert_pos) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// current_loc.alt is alt-above-home, converted from inertial nav's alt-above-ekf-origin
|
||||||
|
const int32_t alt_above_origin_cm = inertial_nav.get_altitude();
|
||||||
|
current_loc.set_alt_cm(alt_above_origin_cm, Location::AltFrame::ABOVE_ORIGIN);
|
||||||
|
if (!ahrs.home_is_set() || !current_loc.change_alt_frame(Location::AltFrame::ABOVE_HOME)) {
|
||||||
|
// if home has not been set yet we treat alt-above-origin as alt-above-home
|
||||||
|
current_loc.set_alt_cm(alt_above_origin_cm, Location::AltFrame::ABOVE_HOME);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,537 @@
|
||||||
|
#include "Blimp.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* High level calls to set and update flight modes logic for individual
|
||||||
|
* flight modes is in control_acro.cpp, control_stabilize.cpp, etc
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
constructor for Mode object
|
||||||
|
*/
|
||||||
|
Mode::Mode(void) :
|
||||||
|
g(blimp.g),
|
||||||
|
g2(blimp.g2),
|
||||||
|
// wp_nav(blimp.wp_nav),
|
||||||
|
// loiter_nav(blimp.loiter_nav),
|
||||||
|
// pos_control(blimp.pos_control),
|
||||||
|
inertial_nav(blimp.inertial_nav),
|
||||||
|
ahrs(blimp.ahrs),
|
||||||
|
// attitude_control(blimp.attitude_control),
|
||||||
|
motors(blimp.motors),
|
||||||
|
channel_right(blimp.channel_right),
|
||||||
|
channel_front(blimp.channel_front),
|
||||||
|
channel_down(blimp.channel_down),
|
||||||
|
channel_yaw(blimp.channel_yaw),
|
||||||
|
G_Dt(blimp.G_Dt)
|
||||||
|
{ };
|
||||||
|
|
||||||
|
// return the static controller object corresponding to supplied mode
|
||||||
|
Mode *Blimp::mode_from_mode_num(const Mode::Number mode)
|
||||||
|
{
|
||||||
|
Mode *ret = nullptr;
|
||||||
|
|
||||||
|
switch (mode) {
|
||||||
|
case Mode::Number::MANUAL:
|
||||||
|
ret = &mode_manual;
|
||||||
|
break;
|
||||||
|
case Mode::Number::LAND:
|
||||||
|
ret = &mode_land;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// set_mode - change flight mode and perform any necessary initialisation
|
||||||
|
// optional force parameter used to force the flight mode change (used only first time mode is set)
|
||||||
|
// returns true if mode was successfully set
|
||||||
|
// ACRO, STABILIZE, ALTHOLD, LAND, DRIFT and SPORT can always be set successfully but the return state of other flight modes should be checked and the caller should deal with failures appropriately
|
||||||
|
bool Blimp::set_mode(Mode::Number mode, ModeReason reason)
|
||||||
|
{
|
||||||
|
|
||||||
|
// return immediately if we are already in the desired mode
|
||||||
|
if (mode == control_mode) {
|
||||||
|
control_mode_reason = reason;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mode *new_flightmode = mode_from_mode_num((Mode::Number)mode);
|
||||||
|
if (new_flightmode == nullptr) {
|
||||||
|
gcs().send_text(MAV_SEVERITY_WARNING,"No such mode");
|
||||||
|
AP::logger().Write_Error(LogErrorSubsystem::FLIGHT_MODE, LogErrorCode(mode));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ignore_checks = !motors->armed(); // allow switching to any mode if disarmed. We rely on the arming check to perform
|
||||||
|
|
||||||
|
// ensure vehicle doesn't leap off the ground if a user switches
|
||||||
|
// into a manual throttle mode from a non-manual-throttle mode
|
||||||
|
// (e.g. user arms in guided, raises throttle to 1300 (not enough to
|
||||||
|
// trigger auto takeoff), then switches into manual):
|
||||||
|
bool user_throttle = new_flightmode->has_manual_throttle();
|
||||||
|
if (!ignore_checks &&
|
||||||
|
ap.land_complete &&
|
||||||
|
user_throttle &&
|
||||||
|
!blimp.flightmode->has_manual_throttle() &&
|
||||||
|
new_flightmode->get_pilot_desired_throttle() > blimp.get_non_takeoff_throttle()) {
|
||||||
|
gcs().send_text(MAV_SEVERITY_WARNING, "Mode change failed: throttle too high");
|
||||||
|
AP::logger().Write_Error(LogErrorSubsystem::FLIGHT_MODE, LogErrorCode(mode));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ignore_checks &&
|
||||||
|
new_flightmode->requires_GPS() &&
|
||||||
|
!blimp.position_ok()) {
|
||||||
|
gcs().send_text(MAV_SEVERITY_WARNING, "Mode change failed: %s requires position", new_flightmode->name());
|
||||||
|
AP::logger().Write_Error(LogErrorSubsystem::FLIGHT_MODE, LogErrorCode(mode));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for valid altitude if old mode did not require it but new one does
|
||||||
|
// we only want to stop changing modes if it could make things worse
|
||||||
|
if (!ignore_checks &&
|
||||||
|
!blimp.ekf_alt_ok() &&
|
||||||
|
flightmode->has_manual_throttle() &&
|
||||||
|
!new_flightmode->has_manual_throttle()) {
|
||||||
|
gcs().send_text(MAV_SEVERITY_WARNING, "Mode change failed: %s need alt estimate", new_flightmode->name());
|
||||||
|
AP::logger().Write_Error(LogErrorSubsystem::FLIGHT_MODE, LogErrorCode(mode));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!new_flightmode->init(ignore_checks)) {
|
||||||
|
gcs().send_text(MAV_SEVERITY_WARNING,"Flight mode change failed %s", new_flightmode->name());
|
||||||
|
AP::logger().Write_Error(LogErrorSubsystem::FLIGHT_MODE, LogErrorCode(mode));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// perform any cleanup required by previous flight mode
|
||||||
|
exit_mode(flightmode, new_flightmode);
|
||||||
|
|
||||||
|
// store previous flight mode (only used by tradeheli's autorotation)
|
||||||
|
prev_control_mode = control_mode;
|
||||||
|
|
||||||
|
// update flight mode
|
||||||
|
flightmode = new_flightmode;
|
||||||
|
control_mode = mode;
|
||||||
|
control_mode_reason = reason;
|
||||||
|
logger.Write_Mode((uint8_t)control_mode, reason);
|
||||||
|
gcs().send_message(MSG_HEARTBEAT);
|
||||||
|
|
||||||
|
// update notify object
|
||||||
|
notify_flight_mode();
|
||||||
|
|
||||||
|
// return success
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Blimp::set_mode(const uint8_t new_mode, const ModeReason reason)
|
||||||
|
{
|
||||||
|
static_assert(sizeof(Mode::Number) == sizeof(new_mode), "The new mode can't be mapped to the vehicles mode number");
|
||||||
|
#ifdef DISALLOW_GCS_MODE_CHANGE_DURING_RC_FAILSAFE
|
||||||
|
if (reason == ModeReason::GCS_COMMAND && blimp.failsafe.radio) {
|
||||||
|
// don't allow mode changes while in radio failsafe
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return blimp.set_mode(static_cast<Mode::Number>(new_mode), reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
// update_flight_mode - calls the appropriate attitude controllers based on flight mode
|
||||||
|
// called at 100hz or more
|
||||||
|
void Blimp::update_flight_mode()
|
||||||
|
{
|
||||||
|
// surface_tracking.invalidate_for_logging(); // invalidate surface tracking alt, flight mode will set to true if used
|
||||||
|
|
||||||
|
flightmode->run();
|
||||||
|
}
|
||||||
|
|
||||||
|
// exit_mode - high level call to organise cleanup as a flight mode is exited
|
||||||
|
void Blimp::exit_mode(Mode *&old_flightmode,
|
||||||
|
Mode *&new_flightmode)
|
||||||
|
{
|
||||||
|
|
||||||
|
// smooth throttle transition when switching from manual to automatic flight modes
|
||||||
|
if (old_flightmode->has_manual_throttle() && !new_flightmode->has_manual_throttle() && motors->armed() && !ap.land_complete) {
|
||||||
|
// this assumes all manual flight modes use get_pilot_desired_throttle to translate pilot input to output throttle
|
||||||
|
// set_accel_throttle_I_from_pilot_throttle();
|
||||||
|
}
|
||||||
|
|
||||||
|
// cancel any takeoffs in progress
|
||||||
|
// old_flightmode->takeoff_stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// notify_flight_mode - sets notify object based on current flight mode. Only used for OreoLED notify device
|
||||||
|
void Blimp::notify_flight_mode()
|
||||||
|
{
|
||||||
|
AP_Notify::flags.autopilot_mode = flightmode->is_autopilot();
|
||||||
|
AP_Notify::flags.flight_mode = (uint8_t)control_mode;
|
||||||
|
notify.set_flight_mode_str(flightmode->name4());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mode::update_navigation()
|
||||||
|
{
|
||||||
|
// run autopilot to make high level decisions about control modes
|
||||||
|
run_autopilot();
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns desired angle in centi-degrees
|
||||||
|
void Mode::get_pilot_desired_accelerations(float &right_out, float &front_out) const
|
||||||
|
{
|
||||||
|
// throttle failsafe check
|
||||||
|
if (blimp.failsafe.radio || !blimp.ap.rc_receiver_present) {
|
||||||
|
right_out = 0;
|
||||||
|
front_out = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// fetch roll and pitch inputs
|
||||||
|
right_out = channel_right->get_control_in();
|
||||||
|
front_out = channel_front->get_control_in();
|
||||||
|
|
||||||
|
|
||||||
|
// // do circular limit
|
||||||
|
// float total_in = norm(pitch_out, roll_out);
|
||||||
|
// if (total_in > angle_limit) {
|
||||||
|
// float ratio = angle_limit / total_in;
|
||||||
|
// roll_out *= ratio;
|
||||||
|
// pitch_out *= ratio;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// do lateral tilt to euler roll conversion
|
||||||
|
// roll_out = (18000/M_PI) * atanf(cosf(pitch_out*(M_PI/18000))*tanf(roll_out*(M_PI/18000)));
|
||||||
|
|
||||||
|
// roll_out and pitch_out are returned
|
||||||
|
}
|
||||||
|
|
||||||
|
// bool Mode::_TakeOff::triggered(const float target_climb_rate) const
|
||||||
|
// {
|
||||||
|
// if (!blimp.ap.land_complete) {
|
||||||
|
// // can't take off if we're already flying
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// if (target_climb_rate <= 0.0f) {
|
||||||
|
// // can't takeoff unless we want to go up...
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (blimp.motors->get_spool_state() != Fins::SpoolState::THROTTLE_UNLIMITED) {
|
||||||
|
// // hold aircraft on the ground until rotor speed runup has finished
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
|
||||||
|
bool Mode::is_disarmed_or_landed() const
|
||||||
|
{
|
||||||
|
if (!motors->armed() || !blimp.ap.auto_armed || blimp.ap.land_complete) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mode::zero_throttle_and_relax_ac(bool spool_up)
|
||||||
|
{
|
||||||
|
if (spool_up) {
|
||||||
|
motors->set_desired_spool_state(Fins::DesiredSpoolState::THROTTLE_UNLIMITED);
|
||||||
|
} else {
|
||||||
|
motors->set_desired_spool_state(Fins::DesiredSpoolState::SHUT_DOWN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// void Mode::zero_throttle_and_hold_attitude()
|
||||||
|
// {
|
||||||
|
// // run attitude controller
|
||||||
|
// attitude_control->input_rate_bf_roll_pitch_yaw(0.0f, 0.0f, 0.0f);
|
||||||
|
// attitude_control->set_throttle_out(0.0f, false, blimp.g.throttle_filt);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// void Mode::make_safe_spool_down()
|
||||||
|
// {
|
||||||
|
// // command aircraft to initiate the shutdown process
|
||||||
|
// motors->set_desired_spool_state(Fins::DesiredSpoolState::GROUND_IDLE);
|
||||||
|
// switch (motors->get_spool_state()) {
|
||||||
|
|
||||||
|
// case Fins::SpoolState::SHUT_DOWN:
|
||||||
|
// case Fins::SpoolState::GROUND_IDLE:
|
||||||
|
// // relax controllers during idle states
|
||||||
|
// // attitude_control->reset_rate_controller_I_terms_smoothly();
|
||||||
|
// // attitude_control->set_yaw_target_to_current_heading();
|
||||||
|
// break;
|
||||||
|
|
||||||
|
// case Fins::SpoolState::SPOOLING_UP:
|
||||||
|
// case Fins::SpoolState::THROTTLE_UNLIMITED:
|
||||||
|
// case Fins::SpoolState::SPOOLING_DOWN:
|
||||||
|
// // while transitioning though active states continue to operate normally
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // pos_control->relax_alt_hold_controllers(0.0f); // forces throttle output to go to zero
|
||||||
|
// // pos_control->update_z_controller();
|
||||||
|
// // we may need to move this out
|
||||||
|
// // attitude_control->input_euler_angle_roll_pitch_euler_rate_yaw(0.0f, 0.0f, 0.0f);
|
||||||
|
// }
|
||||||
|
|
||||||
|
/*
|
||||||
|
get a height above ground estimate for landing
|
||||||
|
*/
|
||||||
|
int32_t Mode::get_alt_above_ground_cm(void)
|
||||||
|
{
|
||||||
|
int32_t alt_above_ground_cm;
|
||||||
|
// if (blimp.get_rangefinder_height_interpolated_cm(alt_above_ground_cm)) {
|
||||||
|
// return alt_above_ground_cm;
|
||||||
|
// }
|
||||||
|
// if (!pos_control->is_active_xy()) {
|
||||||
|
// return blimp.current_loc.alt;
|
||||||
|
// }
|
||||||
|
if (blimp.current_loc.get_alt_cm(Location::AltFrame::ABOVE_TERRAIN, alt_above_ground_cm)) {
|
||||||
|
return alt_above_ground_cm;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assume the Earth is flat:
|
||||||
|
return blimp.current_loc.alt;
|
||||||
|
}
|
||||||
|
|
||||||
|
// void Mode::land_run_vertical_control(bool pause_descent)
|
||||||
|
// {
|
||||||
|
// float cmb_rate = 0;
|
||||||
|
// if (!pause_descent) {
|
||||||
|
// float max_land_descent_velocity;
|
||||||
|
// if (g.land_speed_high > 0) {
|
||||||
|
// max_land_descent_velocity = -g.land_speed_high;
|
||||||
|
// } else {
|
||||||
|
// max_land_descent_velocity = pos_control->get_max_speed_down();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Don't speed up for landing.
|
||||||
|
// max_land_descent_velocity = MIN(max_land_descent_velocity, -abs(g.land_speed));
|
||||||
|
|
||||||
|
// // Compute a vertical velocity demand such that the vehicle approaches g2.land_alt_low. Without the below constraint, this would cause the vehicle to hover at g2.land_alt_low.
|
||||||
|
// // cmb_rate = AC_AttitudeControl::sqrt_controller(MAX(g2.land_alt_low,100)-get_alt_above_ground_cm(), pos_control->get_pos_z_p().kP(), pos_control->get_max_accel_z(), G_Dt);
|
||||||
|
|
||||||
|
// // Constrain the demanded vertical velocity so that it is between the configured maximum descent speed and the configured minimum descent speed.
|
||||||
|
// // cmb_rate = constrain_float(cmb_rate, max_land_descent_velocity, -abs(g.land_speed));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // update altitude target and call position controller
|
||||||
|
// pos_control->set_alt_target_from_climb_rate_ff(cmb_rate, G_Dt, true);
|
||||||
|
// pos_control->update_z_controller();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// void Mode::land_run_horizontal_control()
|
||||||
|
// {
|
||||||
|
// float target_roll = 0.0f;
|
||||||
|
// float target_pitch = 0.0f;
|
||||||
|
// float target_yaw_rate = 0;
|
||||||
|
|
||||||
|
// // relax loiter target if we might be landed
|
||||||
|
// if (blimp.ap.land_complete_maybe) {
|
||||||
|
// loiter_nav->soften_for_landing();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // process pilot inputs
|
||||||
|
// if (!blimp.failsafe.radio) {
|
||||||
|
// if ((g.throttle_behavior & THR_BEHAVE_HIGH_THROTTLE_CANCELS_LAND) != 0 && blimp.rc_throttle_control_in_filter.get() > LAND_CANCEL_TRIGGER_THR){
|
||||||
|
// AP::logger().Write_Event(LogEvent::LAND_CANCELLED_BY_PILOT);
|
||||||
|
// // exit land if throttle is high
|
||||||
|
// if (!set_mode(Mode::Number::LOITER, ModeReason::THROTTLE_LAND_ESCAPE)) {
|
||||||
|
// set_mode(Mode::Number::ALT_HOLD, ModeReason::THROTTLE_LAND_ESCAPE);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (g.land_repositioning) {
|
||||||
|
|
||||||
|
// // convert pilot input to lean angles
|
||||||
|
// get_pilot_desired_lean_angles(target_roll, target_pitch, loiter_nav->get_angle_max_cd(), attitude_control->get_althold_lean_angle_max());
|
||||||
|
|
||||||
|
// // record if pilot has overridden roll or pitch
|
||||||
|
// if (!is_zero(target_roll) || !is_zero(target_pitch)) {
|
||||||
|
// if (!blimp.ap.land_repo_active) {
|
||||||
|
// AP::logger().Write_Event(LogEvent::LAND_REPO_ACTIVE);
|
||||||
|
// }
|
||||||
|
// blimp.ap.land_repo_active = true;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // get pilot's desired yaw rate
|
||||||
|
// target_yaw_rate = get_pilot_desired_yaw_rate(channel_yaw->get_control_in());
|
||||||
|
// if (!is_zero(target_yaw_rate)) {
|
||||||
|
// auto_yaw.set_mode(AUTO_YAW_HOLD);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // process roll, pitch inputs
|
||||||
|
// loiter_nav->set_pilot_desired_acceleration(target_roll, target_pitch, G_Dt);
|
||||||
|
|
||||||
|
// // run loiter controller
|
||||||
|
// loiter_nav->update();
|
||||||
|
|
||||||
|
// float nav_roll = loiter_nav->get_roll();
|
||||||
|
// float nav_pitch = loiter_nav->get_pitch();
|
||||||
|
|
||||||
|
// if (g2.wp_navalt_min > 0) {
|
||||||
|
// // user has requested an altitude below which navigation
|
||||||
|
// // attitude is limited. This is used to prevent commanded roll
|
||||||
|
// // over on landing, which particularly affects heliblimps if
|
||||||
|
// // there is any position estimate drift after touchdown. We
|
||||||
|
// // limit attitude to 7 degrees below this limit and linearly
|
||||||
|
// // interpolate for 1m above that
|
||||||
|
// float attitude_limit_cd = linear_interpolate(700, blimp.aparm.angle_max, get_alt_above_ground_cm(),
|
||||||
|
// g2.wp_navalt_min*100U, (g2.wp_navalt_min+1)*100U);
|
||||||
|
// float total_angle_cd = norm(nav_roll, nav_pitch);
|
||||||
|
// if (total_angle_cd > attitude_limit_cd) {
|
||||||
|
// float ratio = attitude_limit_cd / total_angle_cd;
|
||||||
|
// nav_roll *= ratio;
|
||||||
|
// nav_pitch *= ratio;
|
||||||
|
|
||||||
|
// // tell position controller we are applying an external limit
|
||||||
|
// pos_control->set_limit_accel_xy();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // call attitude controller
|
||||||
|
// if (auto_yaw.mode() == AUTO_YAW_HOLD) {
|
||||||
|
// // roll & pitch from waypoint controller, yaw rate from pilot
|
||||||
|
// attitude_control->input_euler_angle_roll_pitch_euler_rate_yaw(nav_roll, nav_pitch, target_yaw_rate);
|
||||||
|
// } else {
|
||||||
|
// // roll, pitch from waypoint controller, yaw heading from auto_heading()
|
||||||
|
// attitude_control->input_euler_angle_roll_pitch_yaw(nav_roll, nav_pitch, auto_yaw.yaw(), true);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
float Mode::throttle_hover() const
|
||||||
|
{
|
||||||
|
return motors->get_throttle_hover();
|
||||||
|
}
|
||||||
|
|
||||||
|
// transform pilot's manual throttle input to make hover throttle mid stick
|
||||||
|
// used only for manual throttle modes
|
||||||
|
// thr_mid should be in the range 0 to 1
|
||||||
|
// returns throttle output 0 to 1
|
||||||
|
float Mode::get_pilot_desired_throttle() const
|
||||||
|
{
|
||||||
|
const float thr_mid = throttle_hover();
|
||||||
|
int16_t throttle_control = channel_down->get_control_in();
|
||||||
|
|
||||||
|
int16_t mid_stick = blimp.get_throttle_mid();
|
||||||
|
// protect against unlikely divide by zero
|
||||||
|
if (mid_stick <= 0) {
|
||||||
|
mid_stick = 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensure reasonable throttle values
|
||||||
|
throttle_control = constrain_int16(throttle_control,0,1000);
|
||||||
|
|
||||||
|
// calculate normalised throttle input
|
||||||
|
float throttle_in;
|
||||||
|
if (throttle_control < mid_stick) {
|
||||||
|
throttle_in = ((float)throttle_control)*0.5f/(float)mid_stick;
|
||||||
|
} else {
|
||||||
|
throttle_in = 0.5f + ((float)(throttle_control-mid_stick)) * 0.5f / (float)(1000-mid_stick);
|
||||||
|
}
|
||||||
|
|
||||||
|
const float expo = constrain_float(-(thr_mid-0.5f)/0.375f, -0.5f, 1.0f);
|
||||||
|
// calculate the output throttle using the given expo function
|
||||||
|
float throttle_out = throttle_in*(1.0f-expo) + expo*throttle_in*throttle_in*throttle_in;
|
||||||
|
return throttle_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mode::AltHoldModeState Mode::get_alt_hold_state(float target_climb_rate_cms)
|
||||||
|
// {
|
||||||
|
// // Alt Hold State Machine Determination
|
||||||
|
// if (!motors->armed()) {
|
||||||
|
// // the aircraft should moved to a shut down state
|
||||||
|
// motors->set_desired_spool_state(Fins::DesiredSpoolState::SHUT_DOWN);
|
||||||
|
|
||||||
|
// // transition through states as aircraft spools down
|
||||||
|
// switch (motors->get_spool_state()) {
|
||||||
|
|
||||||
|
// case Fins::SpoolState::SHUT_DOWN:
|
||||||
|
// return AltHold_MotorStopped;
|
||||||
|
|
||||||
|
// case Fins::SpoolState::GROUND_IDLE:
|
||||||
|
// return AltHold_Landed_Ground_Idle;
|
||||||
|
|
||||||
|
// default:
|
||||||
|
// return AltHold_Landed_Pre_Takeoff;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// } else if (takeoff.running() || takeoff.triggered(target_climb_rate_cms)) {
|
||||||
|
// // the aircraft is currently landed or taking off, asking for a positive climb rate and in THROTTLE_UNLIMITED
|
||||||
|
// // the aircraft should progress through the take off procedure
|
||||||
|
// return AltHold_Takeoff;
|
||||||
|
|
||||||
|
// } else if (!blimp.ap.auto_armed || blimp.ap.land_complete) {
|
||||||
|
// // the aircraft is armed and landed
|
||||||
|
// if (target_climb_rate_cms < 0.0f && !blimp.ap.using_interlock) {
|
||||||
|
// // the aircraft should move to a ground idle state
|
||||||
|
// motors->set_desired_spool_state(Fins::DesiredSpoolState::GROUND_IDLE);
|
||||||
|
|
||||||
|
// } else {
|
||||||
|
// // the aircraft should prepare for imminent take off
|
||||||
|
// motors->set_desired_spool_state(Fins::DesiredSpoolState::THROTTLE_UNLIMITED);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (motors->get_spool_state() == Fins::SpoolState::GROUND_IDLE) {
|
||||||
|
// // the aircraft is waiting in ground idle
|
||||||
|
// return AltHold_Landed_Ground_Idle;
|
||||||
|
|
||||||
|
// } else {
|
||||||
|
// // the aircraft can leave the ground at any time
|
||||||
|
// return AltHold_Landed_Pre_Takeoff;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// } else {
|
||||||
|
// // the aircraft is in a flying state
|
||||||
|
// motors->set_desired_spool_state(Fins::DesiredSpoolState::THROTTLE_UNLIMITED);
|
||||||
|
// return AltHold_Flying;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// pass-through functions to reduce code churn on conversion;
|
||||||
|
// these are candidates for moving into the Mode base
|
||||||
|
// class.
|
||||||
|
float Mode::get_pilot_desired_yaw_rate(int16_t stick_angle)
|
||||||
|
{
|
||||||
|
return blimp.get_pilot_desired_yaw_rate(stick_angle);
|
||||||
|
}
|
||||||
|
|
||||||
|
float Mode::get_pilot_desired_climb_rate(float throttle_control)
|
||||||
|
{
|
||||||
|
return blimp.get_pilot_desired_climb_rate(throttle_control);
|
||||||
|
}
|
||||||
|
|
||||||
|
float Mode::get_non_takeoff_throttle()
|
||||||
|
{
|
||||||
|
return blimp.get_non_takeoff_throttle();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Mode::set_mode(Mode::Number mode, ModeReason reason)
|
||||||
|
{
|
||||||
|
return blimp.set_mode(mode, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mode::set_land_complete(bool b)
|
||||||
|
{
|
||||||
|
return blimp.set_land_complete(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
GCS_Blimp &Mode::gcs()
|
||||||
|
{
|
||||||
|
return blimp.gcs();
|
||||||
|
}
|
||||||
|
|
||||||
|
// set_throttle_takeoff - allows modes to tell throttle controller we
|
||||||
|
// are taking off so I terms can be cleared
|
||||||
|
// void Mode::set_throttle_takeoff()
|
||||||
|
// {
|
||||||
|
// // tell position controller to reset alt target and reset I terms
|
||||||
|
// pos_control->init_takeoff();
|
||||||
|
// }
|
||||||
|
|
||||||
|
uint16_t Mode::get_pilot_speed_dn()
|
||||||
|
{
|
||||||
|
return blimp.get_pilot_speed_dn();
|
||||||
|
}
|
|
@ -0,0 +1,374 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Blimp.h"
|
||||||
|
class Parameters;
|
||||||
|
class ParametersG2;
|
||||||
|
|
||||||
|
class GCS_Blimp;
|
||||||
|
|
||||||
|
class Mode
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Auto Pilot Modes enumeration
|
||||||
|
enum class Number : uint8_t {
|
||||||
|
MANUAL = 0, // manual control similar to Copter's stabilize mode
|
||||||
|
LAND = 1, // currently just stops moving
|
||||||
|
// STABILIZE = 0, // manual airframe angle with manual throttle
|
||||||
|
// ACRO = 1, // manual body-frame angular rate with manual throttle
|
||||||
|
// ALT_HOLD = 2, // manual airframe angle with automatic throttle
|
||||||
|
// AUTO = 3, // fully automatic waypoint control using mission commands
|
||||||
|
// GUIDED = 4, // fully automatic fly to coordinate or fly at velocity/direction using GCS immediate commands
|
||||||
|
// LOITER = 5, // automatic horizontal acceleration with automatic throttle
|
||||||
|
// RTL = 6, // automatic return to launching point
|
||||||
|
// CIRCLE = 7, // automatic circular flight with automatic throttle
|
||||||
|
// LAND = 9, // automatic landing with horizontal position control
|
||||||
|
// DRIFT = 11, // semi-automous position, yaw and throttle control
|
||||||
|
// SPORT = 13, // manual earth-frame angular rate control with manual throttle
|
||||||
|
// FLIP = 14, // automatically flip the vehicle on the roll axis
|
||||||
|
// AUTOTUNE = 15, // automatically tune the vehicle's roll and pitch gains
|
||||||
|
// POSHOLD = 16, // automatic position hold with manual override, with automatic throttle
|
||||||
|
// BRAKE = 17, // full-brake using inertial/GPS system, no pilot input
|
||||||
|
// THROW = 18, // throw to launch mode using inertial/GPS system, no pilot input
|
||||||
|
// AVOID_ADSB = 19, // automatic avoidance of obstacles in the macro scale - e.g. full-sized aircraft
|
||||||
|
// GUIDED_NOGPS = 20, // guided mode but only accepts attitude and altitude
|
||||||
|
// SMART_RTL = 21, // SMART_RTL returns to home by retracing its steps
|
||||||
|
// FLOWHOLD = 22, // FLOWHOLD holds position with optical flow without rangefinder
|
||||||
|
// FOLLOW = 23, // follow attempts to follow another vehicle or ground station
|
||||||
|
// ZIGZAG = 24, // ZIGZAG mode is able to fly in a zigzag manner with predefined point A and point B
|
||||||
|
// SYSTEMID = 25, // System ID mode produces automated system identification signals in the controllers
|
||||||
|
// AUTOROTATE = 26, // Autonomous autorotation
|
||||||
|
};
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
Mode(void);
|
||||||
|
|
||||||
|
// do not allow copying
|
||||||
|
Mode(const Mode &other) = delete;
|
||||||
|
Mode &operator=(const Mode&) = delete;
|
||||||
|
|
||||||
|
// child classes should override these methods
|
||||||
|
virtual bool init(bool ignore_checks)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
virtual void run() = 0;
|
||||||
|
virtual bool requires_GPS() const = 0;
|
||||||
|
virtual bool has_manual_throttle() const = 0;
|
||||||
|
virtual bool allows_arming(bool from_gcs) const = 0;
|
||||||
|
virtual bool is_autopilot() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
virtual bool has_user_takeoff(bool must_navigate) const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
virtual bool in_guided_mode() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
virtual bool logs_attitude() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return a string for this flightmode
|
||||||
|
virtual const char *name() const = 0;
|
||||||
|
virtual const char *name4() const = 0;
|
||||||
|
|
||||||
|
bool do_user_takeoff(float takeoff_alt_cm, bool must_navigate);
|
||||||
|
// virtual bool is_taking_off() const;
|
||||||
|
// static void takeoff_stop() { takeoff.stop(); }
|
||||||
|
|
||||||
|
virtual bool is_landing() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// mode requires terrain to be present to be functional
|
||||||
|
virtual bool requires_terrain_failsafe() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// functions for reporting to GCS
|
||||||
|
virtual bool get_wp(Location &loc)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
virtual int32_t wp_bearing() const
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
virtual uint32_t wp_distance() const
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
virtual float crosstrack_error() const
|
||||||
|
{
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_navigation();
|
||||||
|
|
||||||
|
int32_t get_alt_above_ground_cm(void);
|
||||||
|
|
||||||
|
// pilot input processing
|
||||||
|
void get_pilot_desired_accelerations(float &right_out, float &front_out) const;
|
||||||
|
float get_pilot_desired_yaw_rate(int16_t stick_angle);
|
||||||
|
float get_pilot_desired_throttle() const;
|
||||||
|
|
||||||
|
// returns climb target_rate reduced to avoid obstacles and
|
||||||
|
// altitude fence
|
||||||
|
float get_avoidance_adjusted_climbrate(float target_rate);
|
||||||
|
|
||||||
|
// const Vector3f& get_desired_velocity() {
|
||||||
|
// // note that position control isn't used in every mode, so
|
||||||
|
// // this may return bogus data:
|
||||||
|
// return pos_control->get_desired_velocity();
|
||||||
|
// }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
// navigation support functions
|
||||||
|
virtual void run_autopilot() {}
|
||||||
|
|
||||||
|
// helper functions
|
||||||
|
bool is_disarmed_or_landed() const;
|
||||||
|
void zero_throttle_and_relax_ac(bool spool_up = false);
|
||||||
|
void zero_throttle_and_hold_attitude();
|
||||||
|
void make_safe_spool_down();
|
||||||
|
|
||||||
|
// functions to control landing
|
||||||
|
// in modes that support landing
|
||||||
|
void land_run_horizontal_control();
|
||||||
|
void land_run_vertical_control(bool pause_descent = false);
|
||||||
|
|
||||||
|
// return expected input throttle setting to hover:
|
||||||
|
virtual float throttle_hover() const;
|
||||||
|
|
||||||
|
// Alt_Hold based flight mode states used in Alt_Hold, Loiter, and Sport
|
||||||
|
// enum AltHoldModeState {
|
||||||
|
// AltHold_MotorStopped,
|
||||||
|
// AltHold_Takeoff,
|
||||||
|
// AltHold_Landed_Ground_Idle,
|
||||||
|
// AltHold_Landed_Pre_Takeoff,
|
||||||
|
// AltHold_Flying
|
||||||
|
// };
|
||||||
|
// AltHoldModeState get_alt_hold_state(float target_climb_rate_cms);
|
||||||
|
|
||||||
|
// convenience references to avoid code churn in conversion:
|
||||||
|
Parameters &g;
|
||||||
|
ParametersG2 &g2;
|
||||||
|
// AC_WPNav *&wp_nav;
|
||||||
|
// AC_Loiter *&loiter_nav;
|
||||||
|
AP_InertialNav &inertial_nav;
|
||||||
|
AP_AHRS &ahrs;
|
||||||
|
// AC_AttitudeControl_t *&attitude_control;
|
||||||
|
Fins *&motors;
|
||||||
|
// Fins *&motors;
|
||||||
|
RC_Channel *&channel_right;
|
||||||
|
RC_Channel *&channel_front;
|
||||||
|
RC_Channel *&channel_down;
|
||||||
|
RC_Channel *&channel_yaw;
|
||||||
|
float &G_Dt;
|
||||||
|
|
||||||
|
// note that we support two entirely different automatic takeoffs:
|
||||||
|
|
||||||
|
// "user-takeoff", which is available in modes such as ALT_HOLD
|
||||||
|
// (see has_user_takeoff method). "user-takeoff" is a simple
|
||||||
|
// reach-altitude-based-on-pilot-input-or-parameter routine.
|
||||||
|
|
||||||
|
// "auto-takeoff" is used by both Guided and Auto, and is
|
||||||
|
// basically waypoint navigation with pilot yaw permitted.
|
||||||
|
|
||||||
|
// user-takeoff support; takeoff state is shared across all mode instances
|
||||||
|
// class _TakeOff {
|
||||||
|
// public:
|
||||||
|
// void start(float alt_cm);
|
||||||
|
// void stop();
|
||||||
|
// void get_climb_rates(float& pilot_climb_rate,
|
||||||
|
// float& takeoff_climb_rate);
|
||||||
|
// bool triggered(float target_climb_rate) const;
|
||||||
|
|
||||||
|
// bool running() const { return _running; }
|
||||||
|
// private:
|
||||||
|
// bool _running;
|
||||||
|
// float max_speed;
|
||||||
|
// float alt_delta;
|
||||||
|
// uint32_t start_ms;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// static _TakeOff takeoff;
|
||||||
|
|
||||||
|
// virtual bool do_user_takeoff_start(float takeoff_alt_cm);
|
||||||
|
|
||||||
|
// method shared by both Guided and Auto for takeoff. This is
|
||||||
|
// waypoint navigation but the user can control the yaw.
|
||||||
|
// void auto_takeoff_run();
|
||||||
|
// void auto_takeoff_set_start_alt(void);
|
||||||
|
|
||||||
|
// altitude above-ekf-origin below which auto takeoff does not control horizontal position
|
||||||
|
// static bool auto_takeoff_no_nav_active;
|
||||||
|
// static float auto_takeoff_no_nav_alt_cm;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Navigation Yaw control
|
||||||
|
class AutoYaw
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// yaw(): main product of AutoYaw; the heading:
|
||||||
|
float yaw();
|
||||||
|
|
||||||
|
// mode(): current method of determining desired yaw:
|
||||||
|
autopilot_yaw_mode mode() const
|
||||||
|
{
|
||||||
|
return (autopilot_yaw_mode)_mode;
|
||||||
|
}
|
||||||
|
void set_mode_to_default(bool rtl);
|
||||||
|
void set_mode(autopilot_yaw_mode new_mode);
|
||||||
|
autopilot_yaw_mode default_mode(bool rtl) const;
|
||||||
|
|
||||||
|
// rate_cds(): desired yaw rate in centidegrees/second:
|
||||||
|
float rate_cds() const;
|
||||||
|
void set_rate(float new_rate_cds);
|
||||||
|
|
||||||
|
// set_roi(...): set a "look at" location:
|
||||||
|
void set_roi(const Location &roi_location);
|
||||||
|
|
||||||
|
void set_fixed_yaw(float angle_deg,
|
||||||
|
float turn_rate_dps,
|
||||||
|
int8_t direction,
|
||||||
|
bool relative_angle);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
float look_ahead_yaw();
|
||||||
|
float roi_yaw();
|
||||||
|
|
||||||
|
// auto flight mode's yaw mode
|
||||||
|
uint8_t _mode = AUTO_YAW_LOOK_AT_NEXT_WP;
|
||||||
|
|
||||||
|
// Yaw will point at this location if mode is set to AUTO_YAW_ROI
|
||||||
|
Vector3f roi;
|
||||||
|
|
||||||
|
// bearing from current location to the ROI
|
||||||
|
float _roi_yaw;
|
||||||
|
|
||||||
|
// yaw used for YAW_FIXED yaw_mode
|
||||||
|
int32_t _fixed_yaw;
|
||||||
|
|
||||||
|
// Deg/s we should turn
|
||||||
|
int16_t _fixed_yaw_slewrate;
|
||||||
|
|
||||||
|
// heading when in yaw_look_ahead_yaw
|
||||||
|
float _look_ahead_yaw;
|
||||||
|
|
||||||
|
// turn rate (in cds) when auto_yaw_mode is set to AUTO_YAW_RATE
|
||||||
|
float _rate_cds;
|
||||||
|
|
||||||
|
// used to reduce update rate to 100hz:
|
||||||
|
uint8_t roi_yaw_counter;
|
||||||
|
|
||||||
|
};
|
||||||
|
static AutoYaw auto_yaw;
|
||||||
|
|
||||||
|
// pass-through functions to reduce code churn on conversion;
|
||||||
|
// these are candidates for moving into the Mode base
|
||||||
|
// class.
|
||||||
|
float get_pilot_desired_climb_rate(float throttle_control);
|
||||||
|
float get_non_takeoff_throttle(void);
|
||||||
|
bool set_mode(Mode::Number mode, ModeReason reason);
|
||||||
|
void set_land_complete(bool b);
|
||||||
|
GCS_Blimp &gcs();
|
||||||
|
void set_throttle_takeoff(void);
|
||||||
|
uint16_t get_pilot_speed_dn(void);
|
||||||
|
|
||||||
|
// end pass-through functions
|
||||||
|
};
|
||||||
|
|
||||||
|
class ModeManual : public Mode
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
// inherit constructor
|
||||||
|
using Mode::Mode;
|
||||||
|
|
||||||
|
virtual void run() override;
|
||||||
|
|
||||||
|
bool requires_GPS() const override
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool has_manual_throttle() const override
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool allows_arming(bool from_gcs) const override
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
bool is_autopilot() const override
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
const char *name() const override
|
||||||
|
{
|
||||||
|
return "MANUAL";
|
||||||
|
}
|
||||||
|
const char *name4() const override
|
||||||
|
{
|
||||||
|
return "MANU";
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class ModeLand : public Mode
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
// inherit constructor
|
||||||
|
using Mode::Mode;
|
||||||
|
|
||||||
|
virtual void run() override;
|
||||||
|
|
||||||
|
bool requires_GPS() const override
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool has_manual_throttle() const override
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool allows_arming(bool from_gcs) const override
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
bool is_autopilot() const override
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
const char *name() const override
|
||||||
|
{
|
||||||
|
return "LAND";
|
||||||
|
}
|
||||||
|
const char *name4() const override
|
||||||
|
{
|
||||||
|
return "LAND";
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
};
|
|
@ -0,0 +1,24 @@
|
||||||
|
#include "Blimp.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Init and run calls for stabilize flight mode
|
||||||
|
*/
|
||||||
|
|
||||||
|
// manual_run - runs the main manual controller
|
||||||
|
// should be called at 100hz or more
|
||||||
|
void ModeLand::run()
|
||||||
|
{
|
||||||
|
//stop moving
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// set_mode_land_with_pause - sets mode to LAND and triggers 4 second delay before descent starts
|
||||||
|
// this is always called from a failsafe so we trigger notification to pilot
|
||||||
|
void Blimp::set_mode_land_with_pause(ModeReason reason)
|
||||||
|
{
|
||||||
|
set_mode(Mode::Number::LAND, reason);
|
||||||
|
// land_pause = true;
|
||||||
|
|
||||||
|
// alert pilot to mode change
|
||||||
|
AP_Notify::events.failsafe_mode_change = 1;
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
#include "Blimp.h"
|
||||||
|
/*
|
||||||
|
* Init and run calls for stabilize flight mode
|
||||||
|
*/
|
||||||
|
|
||||||
|
// manual_run - runs the main manual controller
|
||||||
|
// should be called at 100hz or more
|
||||||
|
void ModeManual::run()
|
||||||
|
{
|
||||||
|
// convert pilot input to lean angles
|
||||||
|
// float target_right, target_front;
|
||||||
|
// get_pilot_desired_accelerations(target_right, target_front);
|
||||||
|
|
||||||
|
motors->right_out = channel_right->get_control_in();
|
||||||
|
motors->front_out = channel_front->get_control_in();
|
||||||
|
motors->yaw_out = channel_yaw->get_control_in();
|
||||||
|
motors->down_out = channel_down->get_control_in();
|
||||||
|
|
||||||
|
if (!motors->armed()) {
|
||||||
|
// Motors should be Stopped
|
||||||
|
motors->set_desired_spool_state(Fins::DesiredSpoolState::SHUT_DOWN);
|
||||||
|
} else {
|
||||||
|
motors->set_desired_spool_state(Fins::DesiredSpoolState::THROTTLE_UNLIMITED);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// motors->output(); //MIR need to add sending direction & throttle commands.
|
||||||
|
}
|
|
@ -0,0 +1,92 @@
|
||||||
|
#include "Blimp.h"
|
||||||
|
|
||||||
|
#define ARM_DELAY 20 // called at 10hz so 2 seconds
|
||||||
|
#define DISARM_DELAY 20 // called at 10hz so 2 seconds
|
||||||
|
#define AUTO_TRIM_DELAY 100 // called at 10hz so 10 seconds
|
||||||
|
#define LOST_VEHICLE_DELAY 10 // called at 10hz so 1 second
|
||||||
|
|
||||||
|
// arm_motors_check - checks for pilot input to arm or disarm the blimp
|
||||||
|
// called at 10hz
|
||||||
|
void Blimp::arm_motors_check()
|
||||||
|
{
|
||||||
|
static int16_t arming_counter;
|
||||||
|
|
||||||
|
// check if arming/disarm using rudder is allowed
|
||||||
|
AP_Arming::RudderArming arming_rudder = arming.get_rudder_arming_type();
|
||||||
|
if (arming_rudder == AP_Arming::RudderArming::IS_DISABLED) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensure throttle is down
|
||||||
|
if (channel_down->get_control_in() > 0) { //MIR what dow we do with this?
|
||||||
|
arming_counter = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int16_t yaw_in = channel_yaw->get_control_in();
|
||||||
|
|
||||||
|
// full right
|
||||||
|
if (yaw_in > 900) {
|
||||||
|
|
||||||
|
// increase the arming counter to a maximum of 1 beyond the auto trim counter
|
||||||
|
if (arming_counter <= AUTO_TRIM_DELAY) {
|
||||||
|
arming_counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// arm the motors and configure for flight
|
||||||
|
if (arming_counter == ARM_DELAY && !motors->armed()) {
|
||||||
|
// reset arming counter if arming fail
|
||||||
|
if (!arming.arm(AP_Arming::Method::RUDDER)) {
|
||||||
|
arming_counter = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// arm the motors and configure for flight
|
||||||
|
if (arming_counter == AUTO_TRIM_DELAY && motors->armed() && control_mode == Mode::Number::MANUAL) {
|
||||||
|
gcs().send_text(MAV_SEVERITY_INFO, "AutoTrim start");
|
||||||
|
auto_trim_counter = 250;
|
||||||
|
auto_trim_started = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// full left and rudder disarming is enabled
|
||||||
|
} else if ((yaw_in < -900) && (arming_rudder == AP_Arming::RudderArming::ARMDISARM)) {
|
||||||
|
if (!flightmode->has_manual_throttle() && !ap.land_complete) {
|
||||||
|
arming_counter = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// increase the counter to a maximum of 1 beyond the disarm delay
|
||||||
|
if (arming_counter <= DISARM_DELAY) {
|
||||||
|
arming_counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// disarm the motors
|
||||||
|
if (arming_counter == DISARM_DELAY && motors->armed()) {
|
||||||
|
arming.disarm(AP_Arming::Method::RUDDER);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Yaw is centered so reset arming counter
|
||||||
|
} else {
|
||||||
|
arming_counter = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// motors_output - send output to motors library which will adjust and send to ESCs and servos
|
||||||
|
void Blimp::motors_output()
|
||||||
|
{
|
||||||
|
// output any servo channels
|
||||||
|
SRV_Channels::calc_pwm();
|
||||||
|
|
||||||
|
// cork now, so that all channel outputs happen at once
|
||||||
|
SRV_Channels::cork();
|
||||||
|
|
||||||
|
// update output on any aux channels, for manual passthru
|
||||||
|
SRV_Channels::output_ch_all();
|
||||||
|
|
||||||
|
// send output signals to motors
|
||||||
|
motors->output();
|
||||||
|
|
||||||
|
// push all channels
|
||||||
|
SRV_Channels::push();
|
||||||
|
}
|
|
@ -0,0 +1,192 @@
|
||||||
|
#include "Blimp.h"
|
||||||
|
|
||||||
|
|
||||||
|
// Function that will read the radio data, limit servos and trigger a failsafe
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void Blimp::default_dead_zones()
|
||||||
|
{
|
||||||
|
channel_right->set_default_dead_zone(20);
|
||||||
|
channel_front->set_default_dead_zone(20);
|
||||||
|
channel_down->set_default_dead_zone(30);
|
||||||
|
channel_yaw->set_default_dead_zone(20);
|
||||||
|
rc().channel(CH_6)->set_default_dead_zone(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Blimp::init_rc_in()
|
||||||
|
{
|
||||||
|
channel_right = rc().channel(rcmap.roll()-1);
|
||||||
|
channel_front = rc().channel(rcmap.pitch()-1);
|
||||||
|
channel_down = rc().channel(rcmap.throttle()-1);
|
||||||
|
channel_yaw = rc().channel(rcmap.yaw()-1);
|
||||||
|
|
||||||
|
// set rc channel ranges
|
||||||
|
channel_right->set_angle(RC_SCALE);
|
||||||
|
channel_front->set_angle(RC_SCALE);
|
||||||
|
channel_yaw->set_angle(RC_SCALE);
|
||||||
|
channel_down->set_angle(RC_SCALE);
|
||||||
|
|
||||||
|
// set default dead zones
|
||||||
|
default_dead_zones();
|
||||||
|
|
||||||
|
// initialise throttle_zero flag
|
||||||
|
ap.throttle_zero = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// init_rc_out -- initialise motors
|
||||||
|
void Blimp::init_rc_out()
|
||||||
|
{
|
||||||
|
// motors->init((AP_Motors::motor_frame_class)g2.frame_class.get(), (AP_Motors::motor_frame_type)g.frame_type.get());
|
||||||
|
// MIR will need motors->init later when we switch to other fin config.
|
||||||
|
|
||||||
|
// enable aux servos to cope with multiple output channels per motor
|
||||||
|
SRV_Channels::enable_aux_servos();
|
||||||
|
|
||||||
|
// update rate must be set after motors->init() to allow for motor mapping
|
||||||
|
// motors->set_update_rate(g.rc_speed);
|
||||||
|
|
||||||
|
// motors->set_throttle_range(channel_down->get_radio_min(), channel_down->get_radio_max());
|
||||||
|
|
||||||
|
// refresh auxiliary channel to function map
|
||||||
|
SRV_Channels::update_aux_servo_function();
|
||||||
|
|
||||||
|
/*
|
||||||
|
setup a default safety ignore mask, so that servo gimbals can be active while safety is on
|
||||||
|
*/
|
||||||
|
// uint16_t safety_ignore_mask = (~blimp.motors->get_motor_mask()) & 0x3FFF;
|
||||||
|
// BoardConfig.set_default_safety_ignore_mask(safety_ignore_mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// enable_motor_output() - enable and output lowest possible value to motors
|
||||||
|
void Blimp::enable_motor_output()
|
||||||
|
{
|
||||||
|
// enable motors
|
||||||
|
motors->output_min();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Blimp::read_radio()
|
||||||
|
{
|
||||||
|
const uint32_t tnow_ms = millis();
|
||||||
|
|
||||||
|
if (rc().read_input()) {
|
||||||
|
ap.new_radio_frame = true;
|
||||||
|
|
||||||
|
set_throttle_and_failsafe(channel_down->get_radio_in());
|
||||||
|
set_throttle_zero_flag(channel_down->get_control_in());
|
||||||
|
|
||||||
|
// RC receiver must be attached if we've just got input
|
||||||
|
ap.rc_receiver_present = true;
|
||||||
|
|
||||||
|
// pass pilot input through to motors (used to allow wiggling servos while disarmed on heli, single, coax blimps)
|
||||||
|
// radio_passthrough_to_motors();
|
||||||
|
|
||||||
|
const float dt = (tnow_ms - last_radio_update_ms)*1.0e-3f;
|
||||||
|
rc_throttle_control_in_filter.apply(channel_down->get_control_in(), dt);
|
||||||
|
last_radio_update_ms = tnow_ms;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No radio input this time
|
||||||
|
if (failsafe.radio) {
|
||||||
|
// already in failsafe!
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint32_t elapsed = tnow_ms - last_radio_update_ms;
|
||||||
|
// turn on throttle failsafe if no update from the RC Radio for 500ms or 2000ms if we are using RC_OVERRIDE
|
||||||
|
const uint32_t timeout = RC_Channels::has_active_overrides() ? FS_RADIO_RC_OVERRIDE_TIMEOUT_MS : FS_RADIO_TIMEOUT_MS;
|
||||||
|
if (elapsed < timeout) {
|
||||||
|
// not timed out yet
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!g.failsafe_throttle) {
|
||||||
|
// throttle failsafe not enabled
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!ap.rc_receiver_present && !motors->armed()) {
|
||||||
|
// we only failsafe if we are armed OR we have ever seen an RC receiver
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nobody ever talks to us. Log an error and enter failsafe.
|
||||||
|
AP::logger().Write_Error(LogErrorSubsystem::RADIO, LogErrorCode::RADIO_LATE_FRAME);
|
||||||
|
set_failsafe_radio(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FS_COUNTER 3 // radio failsafe kicks in after 3 consecutive throttle values below failsafe_throttle_value
|
||||||
|
void Blimp::set_throttle_and_failsafe(uint16_t throttle_pwm)
|
||||||
|
{
|
||||||
|
// if failsafe not enabled pass through throttle and exit
|
||||||
|
if (g.failsafe_throttle == FS_THR_DISABLED) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//check for low throttle value
|
||||||
|
if (throttle_pwm < (uint16_t)g.failsafe_throttle_value) {
|
||||||
|
|
||||||
|
// if we are already in failsafe or motors not armed pass through throttle and exit
|
||||||
|
if (failsafe.radio || !(ap.rc_receiver_present || motors->armed())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for 3 low throttle values
|
||||||
|
// Note: we do not pass through the low throttle until 3 low throttle values are received
|
||||||
|
failsafe.radio_counter++;
|
||||||
|
if ( failsafe.radio_counter >= FS_COUNTER ) {
|
||||||
|
failsafe.radio_counter = FS_COUNTER; // check to ensure we don't overflow the counter
|
||||||
|
set_failsafe_radio(true);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// we have a good throttle so reduce failsafe counter
|
||||||
|
failsafe.radio_counter--;
|
||||||
|
if ( failsafe.radio_counter <= 0 ) {
|
||||||
|
failsafe.radio_counter = 0; // check to ensure we don't underflow the counter
|
||||||
|
|
||||||
|
// disengage failsafe after three (nearly) consecutive valid throttle values
|
||||||
|
if (failsafe.radio) {
|
||||||
|
set_failsafe_radio(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// pass through throttle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define THROTTLE_ZERO_DEBOUNCE_TIME_MS 400
|
||||||
|
// set_throttle_zero_flag - set throttle_zero flag from debounced throttle control
|
||||||
|
// throttle_zero is used to determine if the pilot intends to shut down the motors
|
||||||
|
// Basically, this signals when we are not flying. We are either on the ground
|
||||||
|
// or the pilot has shut down the blimp in the air and it is free-falling
|
||||||
|
void Blimp::set_throttle_zero_flag(int16_t throttle_control)
|
||||||
|
{
|
||||||
|
static uint32_t last_nonzero_throttle_ms = 0;
|
||||||
|
uint32_t tnow_ms = millis();
|
||||||
|
|
||||||
|
// if not using throttle interlock and non-zero throttle and not E-stopped,
|
||||||
|
// or using motor interlock and it's enabled, then motors are running,
|
||||||
|
// and we are flying. Immediately set as non-zero
|
||||||
|
if (throttle_control > 0) {
|
||||||
|
last_nonzero_throttle_ms = tnow_ms;
|
||||||
|
ap.throttle_zero = false;
|
||||||
|
} else if (tnow_ms - last_nonzero_throttle_ms > THROTTLE_ZERO_DEBOUNCE_TIME_MS) {
|
||||||
|
ap.throttle_zero = true;
|
||||||
|
}
|
||||||
|
//MIR What does this mean??
|
||||||
|
}
|
||||||
|
|
||||||
|
// pass pilot's inputs to motors library (used to allow wiggling servos while disarmed on heli, single, coax blimps)
|
||||||
|
// void Blimp::radio_passthrough_to_motors()
|
||||||
|
// {
|
||||||
|
// motors->set_radio_passthrough(channel_right->norm_input(),
|
||||||
|
// channel_front->norm_input(),
|
||||||
|
// channel_down->get_control_in_zero_dz()*0.001f,
|
||||||
|
// channel_yaw->norm_input());
|
||||||
|
// }
|
||||||
|
|
||||||
|
/*
|
||||||
|
return the throttle input for mid-stick as a control-in value
|
||||||
|
*/
|
||||||
|
int16_t Blimp::get_throttle_mid(void)
|
||||||
|
{
|
||||||
|
return channel_down->get_control_mid();
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
#include "Blimp.h"
|
||||||
|
|
||||||
|
// return barometric altitude in centimeters
|
||||||
|
void Blimp::read_barometer(void)
|
||||||
|
{
|
||||||
|
barometer.update();
|
||||||
|
|
||||||
|
baro_alt = barometer.get_altitude() * 100.0f;
|
||||||
|
|
||||||
|
motors->set_air_density_ratio(barometer.get_air_density_ratio());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Blimp::compass_cal_update()
|
||||||
|
{
|
||||||
|
compass.cal_update();
|
||||||
|
|
||||||
|
if (hal.util->get_soft_armed()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t compass_cal_stick_gesture_begin = 0;
|
||||||
|
|
||||||
|
if (compass.is_calibrating()) {
|
||||||
|
if (channel_yaw->get_control_in() < -4000 && channel_down->get_control_in() > 900) {
|
||||||
|
compass.cancel_calibration_all();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
bool stick_gesture_detected = compass_cal_stick_gesture_begin != 0 && !motors->armed() && channel_yaw->get_control_in() > 4000 && channel_down->get_control_in() > 900;
|
||||||
|
uint32_t tnow = millis();
|
||||||
|
|
||||||
|
if (!stick_gesture_detected) {
|
||||||
|
compass_cal_stick_gesture_begin = tnow;
|
||||||
|
} else if (tnow-compass_cal_stick_gesture_begin > 1000*COMPASS_CAL_STICK_GESTURE_TIME) {
|
||||||
|
#ifdef CAL_ALWAYS_REBOOT
|
||||||
|
compass.start_calibration_all(true,true,COMPASS_CAL_STICK_DELAY,true);
|
||||||
|
#else
|
||||||
|
compass.start_calibration_all(true,true,COMPASS_CAL_STICK_DELAY,false);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Blimp::accel_cal_update()
|
||||||
|
{
|
||||||
|
if (hal.util->get_soft_armed()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ins.acal_update();
|
||||||
|
// check if new trim values, and set them
|
||||||
|
float trim_roll, trim_pitch;
|
||||||
|
if (ins.get_new_trim(trim_roll, trim_pitch)) {
|
||||||
|
ahrs.set_trim(Vector3f(trim_roll, trim_pitch, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CAL_ALWAYS_REBOOT
|
||||||
|
if (ins.accel_cal_requires_reboot()) {
|
||||||
|
hal.scheduler->delay(1000);
|
||||||
|
hal.scheduler->reboot(false);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
|
@ -0,0 +1,358 @@
|
||||||
|
#include "Blimp.h"
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* The init_ardupilot function processes everything we need for an in - air restart
|
||||||
|
* We will determine later if we are actually on the ground and process a
|
||||||
|
* ground start in that case.
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
static void failsafe_check_static()
|
||||||
|
{
|
||||||
|
blimp.failsafe_check();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Blimp::init_ardupilot()
|
||||||
|
{
|
||||||
|
|
||||||
|
#if STATS_ENABLED == ENABLED
|
||||||
|
// initialise stats module
|
||||||
|
g2.stats.init();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
BoardConfig.init();
|
||||||
|
|
||||||
|
|
||||||
|
// initialise notify system
|
||||||
|
notify.init();
|
||||||
|
notify_flight_mode();
|
||||||
|
|
||||||
|
// initialise battery monitor
|
||||||
|
battery.init();
|
||||||
|
|
||||||
|
// Init RSSI
|
||||||
|
rssi.init();
|
||||||
|
|
||||||
|
barometer.init();
|
||||||
|
|
||||||
|
// setup telem slots with serial ports
|
||||||
|
gcs().setup_uarts();
|
||||||
|
|
||||||
|
#if LOGGING_ENABLED == ENABLED
|
||||||
|
log_init();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// update motor interlock state
|
||||||
|
// update_using_interlock();
|
||||||
|
|
||||||
|
|
||||||
|
init_rc_in(); // sets up rc channels from radio
|
||||||
|
|
||||||
|
// allocate the motors class
|
||||||
|
allocate_motors();
|
||||||
|
|
||||||
|
// initialise rc channels including setting mode
|
||||||
|
rc().init();
|
||||||
|
|
||||||
|
// sets up motors and output to escs
|
||||||
|
init_rc_out();
|
||||||
|
|
||||||
|
|
||||||
|
// motors initialised so parameters can be sent
|
||||||
|
ap.initialised_params = true;
|
||||||
|
|
||||||
|
relay.init();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* setup the 'main loop is dead' check. Note that this relies on
|
||||||
|
* the RC library being initialised.
|
||||||
|
*/
|
||||||
|
hal.scheduler->register_timer_failsafe(failsafe_check_static, 1000);
|
||||||
|
|
||||||
|
// Do GPS init
|
||||||
|
gps.set_log_gps_bit(MASK_LOG_GPS);
|
||||||
|
gps.init(serial_manager);
|
||||||
|
|
||||||
|
AP::compass().set_log_bit(MASK_LOG_COMPASS);
|
||||||
|
AP::compass().init();
|
||||||
|
|
||||||
|
// attitude_control->parameter_sanity_check();
|
||||||
|
// pos_control->set_dt(scheduler.get_loop_period_s());
|
||||||
|
|
||||||
|
#if HIL_MODE != HIL_MODE_DISABLED
|
||||||
|
while (barometer.get_last_update() == 0) {
|
||||||
|
// the barometer begins updating when we get the first
|
||||||
|
// HIL_STATE message
|
||||||
|
gcs().send_text(MAV_SEVERITY_WARNING, "Waiting for first HIL_STATE message");
|
||||||
|
delay(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// set INS to HIL mode
|
||||||
|
ins.set_hil_mode();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// read Baro pressure at ground
|
||||||
|
//-----------------------------
|
||||||
|
barometer.set_log_baro_bit(MASK_LOG_IMU);
|
||||||
|
barometer.calibrate();
|
||||||
|
|
||||||
|
// #if MODE_AUTO_ENABLED == ENABLED
|
||||||
|
// // initialise mission library
|
||||||
|
// mode_auto.mission.init();
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// initialise AP_Logger library
|
||||||
|
logger.setVehicle_Startup_Writer(FUNCTOR_BIND(&blimp, &Blimp::Log_Write_Vehicle_Startup_Messages, void));
|
||||||
|
|
||||||
|
startup_INS_ground();
|
||||||
|
|
||||||
|
#ifdef ENABLE_SCRIPTING
|
||||||
|
g2.scripting.init();
|
||||||
|
#endif // ENABLE_SCRIPTING
|
||||||
|
|
||||||
|
// set landed flags
|
||||||
|
// set_land_complete(true);
|
||||||
|
// set_land_complete_maybe(true);
|
||||||
|
|
||||||
|
// we don't want writes to the serial port to cause us to pause
|
||||||
|
// mid-flight, so set the serial ports non-blocking once we are
|
||||||
|
// ready to fly
|
||||||
|
serial_manager.set_blocking_writes_all(false);
|
||||||
|
|
||||||
|
// enable CPU failsafe
|
||||||
|
// failsafe_enable();
|
||||||
|
|
||||||
|
ins.set_log_raw_bit(MASK_LOG_IMU_RAW);
|
||||||
|
|
||||||
|
// setup fin output
|
||||||
|
motors->setup_fins();
|
||||||
|
|
||||||
|
// enable output to motors
|
||||||
|
if (arming.rc_calibration_checks(true)) {
|
||||||
|
enable_motor_output();
|
||||||
|
}
|
||||||
|
|
||||||
|
// attempt to switch to MANUAL, if this fails then switch to Land
|
||||||
|
if (!set_mode((enum Mode::Number)g.initial_mode.get(), ModeReason::INITIALISED)) {
|
||||||
|
// set mode to MANUAL will trigger mode change notification to pilot
|
||||||
|
set_mode(Mode::Number::MANUAL, ModeReason::UNAVAILABLE);
|
||||||
|
} else {
|
||||||
|
// alert pilot to mode change
|
||||||
|
AP_Notify::events.failsafe_mode_change = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// flag that initialisation has completed
|
||||||
|
ap.initialised = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//******************************************************************************
|
||||||
|
//This function does all the calibrations, etc. that we need during a ground start
|
||||||
|
//******************************************************************************
|
||||||
|
void Blimp::startup_INS_ground()
|
||||||
|
{
|
||||||
|
// initialise ahrs (may push imu calibration into the mpu6000 if using that device).
|
||||||
|
ahrs.init();
|
||||||
|
ahrs.set_vehicle_class(AHRS_VEHICLE_COPTER);
|
||||||
|
|
||||||
|
// Warm up and calibrate gyro offsets
|
||||||
|
ins.init(scheduler.get_loop_rate_hz());
|
||||||
|
|
||||||
|
// reset ahrs including gyro bias
|
||||||
|
ahrs.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// position_ok - returns true if the horizontal absolute position is ok and home position is set
|
||||||
|
bool Blimp::position_ok() const
|
||||||
|
{
|
||||||
|
// return false if ekf failsafe has triggered
|
||||||
|
if (failsafe.ekf) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check ekf position estimate
|
||||||
|
return (ekf_has_absolute_position() || ekf_has_relative_position());
|
||||||
|
}
|
||||||
|
|
||||||
|
// ekf_has_absolute_position - returns true if the EKF can provide an absolute WGS-84 position estimate
|
||||||
|
bool Blimp::ekf_has_absolute_position() const
|
||||||
|
{
|
||||||
|
if (!ahrs.have_inertial_nav()) {
|
||||||
|
// do not allow navigation with dcm position
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// with EKF use filter status and ekf check
|
||||||
|
nav_filter_status filt_status = inertial_nav.get_filter_status();
|
||||||
|
|
||||||
|
// if disarmed we accept a predicted horizontal position
|
||||||
|
if (!motors->armed()) {
|
||||||
|
return ((filt_status.flags.horiz_pos_abs || filt_status.flags.pred_horiz_pos_abs));
|
||||||
|
} else {
|
||||||
|
// once armed we require a good absolute position and EKF must not be in const_pos_mode
|
||||||
|
return (filt_status.flags.horiz_pos_abs && !filt_status.flags.const_pos_mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ekf_has_relative_position - returns true if the EKF can provide a position estimate relative to it's starting position
|
||||||
|
bool Blimp::ekf_has_relative_position() const
|
||||||
|
{
|
||||||
|
// return immediately if EKF not used
|
||||||
|
if (!ahrs.have_inertial_nav()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return immediately if neither optflow nor visual odometry is enabled
|
||||||
|
bool enabled = false;
|
||||||
|
// #if OPTFLOW == ENABLED
|
||||||
|
// if (optflow.enabled()) {
|
||||||
|
// enabled = true;
|
||||||
|
// }
|
||||||
|
// #endif
|
||||||
|
// #if HAL_VISUALODOM_ENABLED
|
||||||
|
// if (visual_odom.enabled()) {
|
||||||
|
// enabled = true;
|
||||||
|
// }
|
||||||
|
// #endif
|
||||||
|
if (!enabled) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get filter status from EKF
|
||||||
|
nav_filter_status filt_status = inertial_nav.get_filter_status();
|
||||||
|
|
||||||
|
// if disarmed we accept a predicted horizontal relative position
|
||||||
|
if (!motors->armed()) {
|
||||||
|
return (filt_status.flags.pred_horiz_pos_rel);
|
||||||
|
} else {
|
||||||
|
return (filt_status.flags.horiz_pos_rel && !filt_status.flags.const_pos_mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns true if the ekf has a good altitude estimate (required for modes which do AltHold)
|
||||||
|
bool Blimp::ekf_alt_ok() const
|
||||||
|
{
|
||||||
|
if (!ahrs.have_inertial_nav()) {
|
||||||
|
// do not allow alt control with only dcm
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// with EKF use filter status and ekf check
|
||||||
|
nav_filter_status filt_status = inertial_nav.get_filter_status();
|
||||||
|
|
||||||
|
// require both vertical velocity and position
|
||||||
|
return (filt_status.flags.vert_vel && filt_status.flags.vert_pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
// update_auto_armed - update status of auto_armed flag
|
||||||
|
void Blimp::update_auto_armed()
|
||||||
|
{
|
||||||
|
// disarm checks
|
||||||
|
if (ap.auto_armed) {
|
||||||
|
// if motors are disarmed, auto_armed should also be false
|
||||||
|
if (!motors->armed()) {
|
||||||
|
set_auto_armed(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// if in stabilize or acro flight mode and throttle is zero, auto-armed should become false
|
||||||
|
if (flightmode->has_manual_throttle() && ap.throttle_zero && !failsafe.radio) {
|
||||||
|
set_auto_armed(false);
|
||||||
|
}
|
||||||
|
// if heliblimps are on the ground, and the motor is switched off, auto-armed should be false
|
||||||
|
// so that rotor runup is checked again before attempting to take-off
|
||||||
|
if (ap.land_complete && motors->get_spool_state() != Fins::SpoolState::THROTTLE_UNLIMITED && ap.using_interlock) {
|
||||||
|
set_auto_armed(false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// arm checks
|
||||||
|
|
||||||
|
// // for tradheli if motors are armed and throttle is above zero and the motor is started, auto_armed should be true
|
||||||
|
// if(motors->armed() && ap.using_interlock) {
|
||||||
|
// if(!ap.throttle_zero && motors->get_spool_state() == Fins::SpoolState::THROTTLE_UNLIMITED) {
|
||||||
|
// set_auto_armed(true);
|
||||||
|
// }
|
||||||
|
// // if motors are armed and throttle is above zero auto_armed should be true
|
||||||
|
// // if motors are armed and we are in throw mode, then auto_armed should be true
|
||||||
|
// } else if (motors->armed() && !ap.using_interlock) {
|
||||||
|
// if(!ap.throttle_zero) {
|
||||||
|
// set_auto_armed(true);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
should we log a message type now?
|
||||||
|
*/
|
||||||
|
bool Blimp::should_log(uint32_t mask)
|
||||||
|
{
|
||||||
|
#if LOGGING_ENABLED == ENABLED
|
||||||
|
ap.logging_started = logger.logging_started();
|
||||||
|
return logger.should_log(mask);
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// return MAV_TYPE corresponding to frame class
|
||||||
|
MAV_TYPE Blimp::get_frame_mav_type()
|
||||||
|
{
|
||||||
|
return MAV_TYPE_QUADROTOR; //MIR changed to this for now - will need to deal with mavlink changes later
|
||||||
|
}
|
||||||
|
|
||||||
|
// return string corresponding to frame_class
|
||||||
|
const char* Blimp::get_frame_string()
|
||||||
|
{
|
||||||
|
return "AIRFISH";
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
allocate the motors class
|
||||||
|
*/
|
||||||
|
void Blimp::allocate_motors(void)
|
||||||
|
{
|
||||||
|
switch ((Fins::motor_frame_class)g2.frame_class.get()) {
|
||||||
|
case Fins::MOTOR_FRAME_AIRFISH:
|
||||||
|
default:
|
||||||
|
motors = new Fins(blimp.scheduler.get_loop_rate_hz());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (motors == nullptr) {
|
||||||
|
AP_HAL::panic("Unable to allocate FRAME_CLASS=%u", (unsigned)g2.frame_class.get());
|
||||||
|
}
|
||||||
|
AP_Param::load_object_from_eeprom(motors, Fins::var_info);
|
||||||
|
|
||||||
|
// const struct AP_Param::GroupInfo *ac_var_info;
|
||||||
|
|
||||||
|
// attitude_control = new AC_AttitudeControl_Multi(*ahrs_view, aparm, *motors, scheduler.get_loop_period_s());
|
||||||
|
// ac_var_info = AC_AttitudeControl_Multi::var_info;
|
||||||
|
// if (attitude_control == nullptr) {
|
||||||
|
// AP_HAL::panic("Unable to allocate AttitudeControl");
|
||||||
|
// }
|
||||||
|
// AP_Param::load_object_from_eeprom(attitude_control, ac_var_info);
|
||||||
|
|
||||||
|
// pos_control = new AC_PosControl(*ahrs_view, inertial_nav, *motors, *attitude_control);
|
||||||
|
// if (pos_control == nullptr) {
|
||||||
|
// AP_HAL::panic("Unable to allocate PosControl");
|
||||||
|
// }
|
||||||
|
// AP_Param::load_object_from_eeprom(pos_control, pos_control->var_info);
|
||||||
|
|
||||||
|
// wp_nav = new AC_WPNav(inertial_nav, *ahrs_view, *pos_control, *attitude_control);
|
||||||
|
|
||||||
|
// if (wp_nav == nullptr) {
|
||||||
|
// AP_HAL::panic("Unable to allocate WPNav");
|
||||||
|
// }
|
||||||
|
// AP_Param::load_object_from_eeprom(wp_nav, wp_nav->var_info);
|
||||||
|
|
||||||
|
// loiter_nav = new AC_Loiter(inertial_nav, *ahrs_view, *pos_control, *attitude_control);
|
||||||
|
// if (loiter_nav == nullptr) {
|
||||||
|
// AP_HAL::panic("Unable to allocate LoiterNav");
|
||||||
|
// }
|
||||||
|
// AP_Param::load_object_from_eeprom(loiter_nav, loiter_nav->var_info);
|
||||||
|
|
||||||
|
// reload lines from the defaults file that may now be accessible
|
||||||
|
AP_Param::reload_defaults_file(true);
|
||||||
|
|
||||||
|
// param count could have changed
|
||||||
|
AP_Param::invalidate_count();
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef FORCE_VERSION_H_INCLUDE
|
||||||
|
#error version.h should never be included directly. You probably want to include AP_Common/AP_FWVersion.h
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "ap_version.h"
|
||||||
|
|
||||||
|
#define THISFIRMWARE "Blimp V4.1.0-dev"
|
||||||
|
|
||||||
|
// the following line is parsed by the autotest scripts
|
||||||
|
#define FIRMWARE_VERSION 4,1,0,FIRMWARE_VERSION_TYPE_DEV
|
||||||
|
|
||||||
|
#define FW_MAJOR 4
|
||||||
|
#define FW_MINOR 1
|
||||||
|
#define FW_PATCH 0
|
||||||
|
#define FW_TYPE FIRMWARE_VERSION_TYPE_DEV
|
||||||
|
|
||||||
|
#include <AP_Common/AP_FWVersionDefine.h>
|
|
@ -0,0 +1,31 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
|
def build(bld):
|
||||||
|
vehicle = bld.path.name
|
||||||
|
bld.ap_stlib(
|
||||||
|
name=vehicle + '_libs',
|
||||||
|
ap_vehicle=vehicle,
|
||||||
|
ap_libraries=bld.ap_common_vehicle_libraries() + [
|
||||||
|
'AC_AttitudeControl',
|
||||||
|
'AC_InputManager',
|
||||||
|
'AC_WPNav',
|
||||||
|
'AP_InertialNav',
|
||||||
|
'AP_RCMapper',
|
||||||
|
'AP_Avoidance',
|
||||||
|
'AP_Arming',
|
||||||
|
'AP_LTM_Telem',
|
||||||
|
'AP_Devo_Telem',
|
||||||
|
'AP_OSD',
|
||||||
|
'AP_KDECAN',
|
||||||
|
'AP_Beacon',
|
||||||
|
'AP_AdvancedFailsafe', #for some reason compiling GCS_Common.cpp (in libraries) fails if this isn't included...
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
bld.ap_program(
|
||||||
|
program_name='blimp',
|
||||||
|
program_groups=['bin', 'blimp'],
|
||||||
|
use=vehicle + '_libs',
|
||||||
|
defines=['FRAME_CONFIG=MULTICOPTER_FRAME'],
|
||||||
|
)
|
Loading…
Reference in New Issue