Apm飞控学习笔记之悬停loiter模式-Cxm
Posted CHENxiaomingming
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Apm飞控学习笔记之悬停loiter模式-Cxm相关的知识,希望对你有一定的参考价值。
文章汇集
PX4/APM/飞控的学习笔记前言-Cxm_CHENxiaomingming的博客-CSDN博客_apm和px4哪个好
前言
时隔一段时间又开始琢磨APM飞控了,在上一篇中写了姿态控制,经过实机测试使用的是HC-SR04超声波效果并不是特别理想,并且在外部数据控制无人机姿态的情况下虽然经过了飞控的PID但是效果依然好(可能只是我的超声波算法不太行),所以就展开了对Apm位置控制的了解,我先从官网查询了一下位置控制发现官网介绍的很是简短 如下:
所以打算对定点模式(loiter)和自动模式(AUTO)入手。
70K的代码量真的多而且笔记手法越写感觉越像记流水。
目录
目录
定点模式(loiter)
在ArduCopter\\mode.h文件下我们可以找到
LOITER = 5, // automatic horizontal acceleration with automatic throttle
大概意思就是利用气压计和GPS进行辅助定点的模式,在ArduCopter\\mode_loiter.cpp的内容就是模式所运行的代码,如下:
#include "Copter.h"
#if MODE_LOITER_ENABLED == ENABLED
/*
* Init and run calls for loiter flight mode
*/
// loiter_init - initialise loiter controller
bool ModeLoiter::init(bool ignore_checks)
if (!copter.failsafe.radio)
float target_roll, target_pitch;
// apply SIMPLE mode transform to pilot inputs
update_simple_mode();
// 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());
// process pilot's roll and pitch input
loiter_nav->set_pilot_desired_acceleration(target_roll, target_pitch, G_Dt);
else
// clear out pilot desired acceleration in case radio failsafe event occurs and we do not switch to RTL for some reason
loiter_nav->clear_pilot_desired_acceleration();
loiter_nav->init_target();
// initialise position and desired velocity
//期望位置和期望速度
if (!pos_control->is_active_z())
pos_control->set_alt_target_to_current_alt();
pos_control->set_desired_velocity_z(inertial_nav.get_velocity_z());
return true;
#if PRECISION_LANDING == ENABLED
bool ModeLoiter::do_precision_loiter()
if (!_precision_loiter_enabled)
return false;
if (copter.ap.land_complete_maybe)
return false; // don't move on the ground
// if the pilot *really* wants to move the vehicle, let them....
if (loiter_nav->get_pilot_desired_acceleration().length() > 50.0f)
return false;
if (!copter.precland.target_acquired())
return false; // we don't have a good vector
return true;
void ModeLoiter::precision_loiter_xy()
loiter_nav->clear_pilot_desired_acceleration();
Vector2f target_pos, target_vel_rel;
if (!copter.precland.get_target_position_cm(target_pos))
target_pos.x = inertial_nav.get_position().x;
target_pos.y = inertial_nav.get_position().y;
if (!copter.precland.get_target_velocity_relative_cms(target_vel_rel))
target_vel_rel.x = -inertial_nav.get_velocity().x;
target_vel_rel.y = -inertial_nav.get_velocity().y;
pos_control->set_xy_target(target_pos.x, target_pos.y);
pos_control->override_vehicle_velocity_xy(-target_vel_rel);
#endif
// loiter_run - runs the loiter controller
// should be called at 100hz or more
void ModeLoiter::run()
float target_roll, target_pitch;
float target_yaw_rate = 0.0f;
float target_climb_rate = 0.0f;
float takeoff_climb_rate = 0.0f;
// initialize vertical speed and acceleration
pos_control->set_max_speed_z(-get_pilot_speed_dn(), g.pilot_speed_up);
pos_control->set_max_accel_z(g.pilot_accel_z);
// process pilot inputs unless we are in radio failsafe
if (!copter.failsafe.radio)
// apply SIMPLE mode transform to pilot inputs
update_simple_mode();
// 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());
// process pilot's roll and pitch input
loiter_nav->set_pilot_desired_acceleration(target_roll, target_pitch, G_Dt);
// get pilot's desired yaw rate
target_yaw_rate = get_pilot_desired_yaw_rate(channel_yaw->get_control_in());
// get pilot desired climb rate
target_climb_rate = get_pilot_desired_climb_rate(channel_throttle->get_control_in());
target_climb_rate = constrain_float(target_climb_rate, -get_pilot_speed_dn(), g.pilot_speed_up);
else
// clear out pilot desired acceleration in case radio failsafe event occurs and we do not switch to RTL for some reason
loiter_nav->clear_pilot_desired_acceleration();
// relax loiter target if we might be landed
if (copter.ap.land_complete_maybe)
loiter_nav->soften_for_landing();
// Loiter State Machine Determination
AltHoldModeState loiter_state = get_alt_hold_state(target_climb_rate);
// Loiter State Machine
switch (loiter_state)
case AltHold_MotorStopped:
attitude_control->reset_rate_controller_I_terms();
attitude_control->set_yaw_target_to_current_heading();
pos_control->relax_alt_hold_controllers(0.0f); // forces throttle output to go to zero
loiter_nav->init_target();
attitude_control->input_euler_angle_roll_pitch_euler_rate_yaw(loiter_nav->get_roll(), loiter_nav->get_pitch(), target_yaw_rate);
pos_control->update_z_controller();
break;
case AltHold_Takeoff:
// initiate take-off
if (!takeoff.running())
takeoff.start(constrain_float(g.pilot_takeoff_alt,0.0f,1000.0f));
// get takeoff adjusted pilot and takeoff climb rates
takeoff.get_climb_rates(target_climb_rate, takeoff_climb_rate);
// get avoidance adjusted climb rate
target_climb_rate = get_avoidance_adjusted_climbrate(target_climb_rate);
// run loiter controller
loiter_nav->update();
// call attitude controller
attitude_control->input_euler_angle_roll_pitch_euler_rate_yaw(loiter_nav->get_roll(), loiter_nav->get_pitch(), target_yaw_rate);
// update altitude target and call position controller
pos_control->set_alt_target_from_climb_rate_ff(target_climb_rate, G_Dt, false);
pos_control->add_takeoff_climb_rate(takeoff_climb_rate, G_Dt);
pos_control->update_z_controller();
break;
case AltHold_Landed_Ground_Idle:
attitude_control->set_yaw_target_to_current_heading();
// FALLTHROUGH
case AltHold_Landed_Pre_Takeoff:
attitude_control->reset_rate_controller_I_terms_smoothly();
loiter_nav->init_target();
attitude_control->input_euler_angle_roll_pitch_euler_rate_yaw(0.0f, 0.0f, 0.0f);
pos_control->relax_alt_hold_controllers(0.0f); // forces throttle output to go to zero
pos_control->update_z_controller();
break;
case AltHold_Flying:
// set motors to full range
motors->set_desired_spool_state(AP_Motors::DesiredSpoolState::THROTTLE_UNLIMITED);
#if PRECISION_LANDING == ENABLED
if (do_precision_loiter())
precision_loiter_xy();
#endif
// run loiter controller
loiter_nav->update();
// call attitude controller
attitude_control->input_euler_angle_roll_pitch_euler_rate_yaw(loiter_nav->get_roll(), loiter_nav->get_pitch(), target_yaw_rate);
// adjust climb rate using rangefinder
target_climb_rate = copter.surface_tracking.adjust_climb_rate(target_climb_rate);
// get avoidance adjusted climb rate
target_climb_rate = get_avoidance_adjusted_climbrate(target_climb_rate);
pos_control->set_alt_target_from_climb_rate_ff(target_climb_rate, G_Dt, false);
pos_control->update_z_controller();
break;
uint32_t ModeLoiter::wp_distance() const
return loiter_nav->get_distance_to_target();
int32_t ModeLoiter::wp_bearing() const
return loiter_nav->get_bearing_to_target();
#endif
大致分为两个部分,init都是为初始化的操作函数,run则是控制操作函数
init部分,当模式正常进入到loiter中时
bool ModeLoiter::init(bool ignore_checks)
if (!copter.failsafe.radio)
float target_roll, target_pitch;
// apply SIMPLE mode transform to pilot inputs
update_simple_mode();
// 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());
// process pilot's roll and pitch input
设置导航所需的中心度//dt 加速度应该是自上次调用此函数以来的时间(以秒为单位)
loiter_nav->set_pilot_desired_acceleration(target_roll, target_pitch, G_Dt);
else
// clear out pilot desired acceleration in case radio failsafe event occurs and we do not switch to RTL for some reason
//清除飞行员理想的加速,以防万一无线电故障事件发生,我们不切换到 rtl 的某些原因
loiter_nav->clear_pilot_desired_acceleration();
//初始化的位置和前馈速度从目前的位置和速度
loiter_nav->init_target();
// initialise position and desired velocity
//期望位置和期望速度
if (!pos_control->is_active_z())
pos_control->set_alt_target_to_current_alt();
pos_control->set_desired_velocity_z(inertial_nav.get_velocity_z());
return true;
1.1驾驶员期望角度获取
首先我们来看一下get_pilot_desired_lean_angles(target_roll, target_pitch, loiter_nav->get_angle_max_cd(), attitude_control->get_althold_lean_angle_max());
这个是获取遥控器的数据并转换成角度跳转到ArduCopter\\mode.cpp中
void Mode::get_pilot_desired_lean_angles(float &roll_out, float &pitch_out, float angle_max, float angle_limit) const
// throttle failsafe check
if (copter.failsafe.radio || !copter.ap.rc_receiver_present)
roll_out = 0;
pitch_out = 0;
return;
// fetch roll and pitch inputs
roll_out = channel_roll->get_control_in();
pitch_out = channel_pitch->get_control_in();
// limit max lean angle
angle_limit = constrain_float(angle_limit, 1000.0f, angle_max);
// scale roll and pitch inputs to ANGLE_MAX parameter range
float scaler = angle_max/(float)ROLL_PITCH_YAW_INPUT_MAX;
roll_out *= scaler;
pitch_out *= scaler;
// 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
直接看是这么获取的
roll_out = channel_roll->get_control_in();
pitch_out = channel_pitch->get_control_in();
run部分*
void ModeLoiter::run()
float target_roll, target_pitch;
float target_yaw_rate = 0.0f;
float target_climb_rate = 0.0f;
float takeoff_climb_rate = 0.0f;
// initialize vertical speed and acceleration
//初始化垂直速度和加速度
pos_control->set_max_speed_z(-get_pilot_speed_dn(), g.pilot_speed_up);
pos_control->set_max_accel_z(g.pilot_accel_z);
// process pilot inputs unless we are in radio failsafe
if (!copter.failsafe.radio)
// apply SIMPLE mode transform to pilot inputs
update_simple_mode();
// convert pilot input to lean angles
// RC输入转换成角度
get_pilot_desired_lean_angles(target_roll, target_pitch, loiter_nav->get_angle_max_cd(), attitude_control->get_althold_lean_angle_max());
// process pilot's roll and pitch input
//处理飞行员的横摇和俯仰输入
loiter_nav->set_pilot_desired_acceleration(target_roll, target_pitch, G_Dt);
// get pilot's desired yaw rate
//获取RC偏航
target_yaw_rate = get_pilot_desired_yaw_rate(channel_yaw->get_control_in());
// get pilot desired climb rate
//获取RC爬升速度
target_climb_rate = get_pilot_desired_climb_rate(channel_throttle->get_control_in());
target_climb_rate = constrain_float(target_climb_rate, -get_pilot_speed_dn(), g.pilot_speed_up);
else
// clear out pilot desired acceleration in case radio failsafe event occurs and we do not switch to RTL for some reason
loiter_nav->clear_pilot_desired_acceleration();
// relax loiter target if we might be landed
if (copter.ap.land_complete_maybe)
loiter_nav->soften_for_landing();
// Loiter State Machine Determination
AltHoldModeState loiter_state = get_alt_hold_state(target_climb_rate);
// Loiter State Machine
switch (loiter_state)
case AltHold_MotorStopped:
attitude_control->reset_rate_controller_I_terms();
attitude_control->set_yaw_target_to_current_heading();
pos_control->relax_alt_hold_controllers(0.0f); // forces throttle output to go to zero
loiter_nav->init_target();
attitude_control->input_euler_angle_roll_pitch_euler_rate_yaw(loiter_nav->get_roll(), loiter_nav->get_pitch(), target_yaw_rate);
pos_control->update_z_controller();
break;
case AltHold_Takeoff:
// initiate take-off
if (!takeoff.running())
takeoff.start(constrain_float(g.pilot_takeoff_alt,0.0f,1000.0f));
// get takeoff adjusted pilot and takeoff climb rates
takeoff.get_climb_rates(target_climb_rate, takeoff_climb_rate);
// get avoidance adjusted climb rate
target_climb_rate = get_avoidance_adjusted_climbrate(target_climb_rate);
// run loiter controller
loiter_nav->update();
// call attitude controller
attitude_control->input_euler_angle_roll_pitch_euler_rate_yaw(loiter_nav->get_roll(), loiter_nav->get_pitch(), target_yaw_rate);
// update altitude target and call position controller
pos_control->set_alt_target_from_climb_rate_ff(target_climb_rate, G_Dt, false);
pos_control->add_takeoff_climb_rate(takeoff_climb_rate, G_Dt);
pos_control->update_z_controller();
break;
case AltHold_Landed_Ground_Idle:
attitude_control->set_yaw_target_to_current_heading();
// FALLTHROUGH
case AltHold_Landed_Pre_Takeoff:
attitude_control->reset_rate_controller_I_terms_smoothly();
loiter_nav->init_target();
attitude_control->input_euler_angle_roll_pitch_euler_rate_yaw(0.0f, 0.0f, 0.0f);
pos_control->relax_alt_hold_controllers(0.0f); // forces throttle output to go to zero
pos_control->update_z_controller();
break;
case AltHold_Flying:
// set motors to full range
motors->set_desired_spool_state(AP_Motors::DesiredSpoolState::THROTTLE_UNLIMITED);
#if PRECISION_LANDING == ENABLED
if (do_precision_loiter())
precision_loiter_xy();
#endif
// run loiter controller
loiter_nav->update();
// call attitude controller
attitude_control->input_euler_angle_roll_pitch_euler_rate_yaw(loiter_nav->get_roll(), loiter_nav->get_pitch(), target_yaw_rate);
// adjust climb rate using rangefinder
target_climb_rate = copter.surface_tracking.adjust_climb_rate(target_climb_rate);
// get avoidance adjusted climb rate
target_climb_rate = get_avoidance_adjusted_climbrate(target_climb_rate);
pos_control->set_alt_target_from_climb_rate_ff(target_climb_rate, G_Dt, false);
pos_control->update_z_controller();
break;
其中AltHoldModeState loiter_state = get_alt_hold_state(target_climb_rate);是他的飞行模式判断
在ArduCopter\\mode.h中可以找到对应的模式,这些模式都不是正常使用情况下的模式而是以下的代码。
// 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);
1.1运行位置控制器 loiter_nav->update(); 在libraries\\AC_WPNav\\AC_Loiter.cpp中
/// run the loiter controller
void AC_Loiter::update()
// calculate dt
float dt = _pos_control.time_since_last_xy_update();
if (dt >= 0.2f)
dt = 0.0f;
// initialise pos controller speed and acceleration
_pos_control.set_max_speed_xy(_speed_cms);
_pos_control.set_max_accel_xy(_accel_cmss);
calc_desired_velocity(dt);
//运行水平位置控制器
_pos_control.update_xy_controller();
1.2. 初始化位置控制器的速度和加速度:
// initialise pos controller speed and acceleration
_pos_control.set_max_speed_xy(_speed_cms);
_pos_control.set_max_accel_xy(_accel_cmss);
1.3. 更新最新的期望速度和前馈发送到位置控制器中:
calc_desired_velocity(dt);
1.4.运行水平控制器
_pos_control.update_xy_controller();
这里可以参考
1.5.运行姿态控制器
attitude_control->input_euler_angle_roll_pitch_euler_rate_yaw(loiter_nav->get_roll(), loiter_nav->get_pitch(), target_yaw_rate);
loiter_nav->get_roll(), loiter_nav->get_pitch() 传参是通过水平控制器通过EKF运行计算出来的参数
target_yaw_rate则是飞行员控制的航向,也就是偏航
1.6后面高度的控制了
// 测距仪调整爬升高度
target_climb_rate = copter.surface_tracking.adjust_climb_rate(target_climb_rate);
// get avoidance adjusted climb rate
//调整上升速度
target_climb_rate = get_avoidance_adjusted_climbrate(target_climb_rate);
pos_control->set_alt_target_from_climb_rate_ff(target_climb_rate, G_Dt, false);
//这将运行 z 轴位置控制 PID 循环并将低级油门级别发送到 AP_Motors 库
pos_control->update_z_controller();
break;
要注意的是AltHold_Flying是正在飞行中的标志位
END
以上是关于Apm飞控学习笔记之悬停loiter模式-Cxm的主要内容,如果未能解决你的问题,请参考以下文章