bool Copter::rtl_init(bool ignore_checks)

{

if (position_ok() || ignore_checks) {

rtl_build_path(!failsafe.terrain); 如果有地形数据,创建返回路线

rtl_climb_start();1,设置飞机上升点,rtl_state = RTL_InitialClimb;  rtl_state_complete = false;给WP控制器的climb target

return true;

}else{

return false;

}

}

Location_Class类 包含点的经纬度和三种高度

rtl_path结构体,描述了返航航迹,包括起始点、上升目标点、返回目标点、下降目标点。

void Copter::rtl_build_path(bool terrain_following_allowed)

{

// origin point is our stopping point

Vector3f stopping_point;

pos_control.get_stopping_point_xy(stopping_point);

pos_control.get_stopping_point_z(stopping_point);

rtl_path.origin_point = Location_Class(stopping_point); 把飞机停止点当做起始点

rtl_path.origin_point.change_alt_frame(Location_Class::ALT_FRAME_ABOVE_HOME);

把起始点高度改成高于HOME点

// compute return target

rtl_compute_return_target(terrain_following_allowed); 计算返回目标点,目标点在HOME点正上方,高度是地形高度。

// climb target is above our origin point at the return altitude

rtl_path.climb_target = Location_Class(rtl_path.origin_point.lat, rtl_path.origin_point.lng, rtl_path.return_target.alt, rtl_path.return_target.get_alt_frame()); 爬升点,在起始点正上方,高度是返回点的高度,(地形高度)

// descent target is below return target at rtl_alt_final

rtl_path.descent_target = Location_Class(rtl_path.return_target.lat, rtl_path.return_target.lng, g.rtl_alt_final, Location_Class::ALT_FRAME_ABOVE_HOME);

下降点,在返回点的正下方,高度是HOME高度

// set land flag

rtl_path.land = g.rtl_alt_final <= 0;

}

// compute the return target - home or rally point

//   return altitude in cm above home at which vehicle should return home

//   return target's altitude is updated to a higher altitude that the vehicle can safely return at (frame may also be set)

返回点在HOME点的正上方,函数主要是计算返回点高度

void Copter::rtl_compute_return_target(bool terrain_following_allowed)

{

// set return target to nearest rally point or home position (Note: alt is absolute)

#if AC_RALLY == ENABLED

rtl_path.return_target = rally.calc_best_rally_or_home_location(current_loc, ahrs.get_home().alt);

#else

rtl_path.return_target = ahrs.get_home();返回HOME点

#endif

// curr_alt is current altitude above home or above terrain depending upon use_terrain

int32_t curr_alt = current_loc.alt;获得当前点高度,可能是地形高度,可能是高于HOME点高度

// decide if we should use terrain altitudes

rtl_path.terrain_used = terrain_use() && terrain_following_allowed;

if (rtl_path.terrain_used) {如果使用地形高度

// attempt to retrieve terrain alt for current location, stopping point and origin检查当前点、返回点、起始点的地形高度。

int32_t origin_terr_alt, return_target_terr_alt;

if (!rtl_path.origin_point.get_alt_cm(Location_Class::ALT_FRAME_ABOVE_TERRAIN, origin_terr_alt) ||获取起始点地形高度

!rtl_path.return_target.get_alt_cm(Location_Class::ALT_FRAME_ABOVE_TERRAIN, return_target_terr_alt) || 获取返回点地形高度

!current_loc.get_alt_cm(Location_Class::ALT_FRAME_ABOVE_TERRAIN, curr_alt)) {获取当前点地形高度

rtl_path.terrain_used = false;万一有一个获取地形高度失败,则false

Log_Write_Error(ERROR_SUBSYSTEM_TERRAIN, ERROR_CODE_MISSING_TERRAIN_DATA);

}

}

// convert return-target alt (which is an absolute alt) to alt-above-home or alt-above-terrain

if (!rtl_path.terrain_used 如果没使用地形高度|| !rtl_path.return_target.change_alt_frame(Location_Class::ALT_FRAME_ABOVE_TERRAIN)) 如果改成地形高度也没有成功{

if (!rtl_path.return_target.change_alt_frame(Location_Class::ALT_FRAME_ABOVE_HOME)) 再一次改成HOME高度,还是没有成功{

// this should never happen but just in case

rtl_path.return_target.set_alt_cm(0, Location_Class::ALT_FRAME_ABOVE_HOME);那就把它改成高于HOME高度且数值为0

}

rtl_path.terrain_used = false;

}

// set new target altitude to return target altitude

// Note: this is alt-above-home or terrain-alt depending upon use_terrain

// Note: ignore negative altitudes which could happen if user enters negative altitude for rally point or terrain is higher at rally point compared to home

int32_t target_alt = MAX(rtl_path.return_target.alt, 0);如果返回点的高度为负值,则让他为0

// increase target to maximum of current altitude + climb_min and rtl altitude

target_alt = MAX(target_alt, curr_alt + MAX(0, g.rtl_climb_min));增加目标点,是当前点加最小上升高度

target_alt = MAX(target_alt, MAX(g.rtl_altitude, RTL_ALT_MIN));2m

// reduce climb if close to return target

float rtl_return_dist_cm = rtl_path.return_target.get_distance(rtl_path.origin_point) * 100.0f;计算起始点到返回点的距离

// don't allow really shallow slopes

if (g.rtl_cone_slope >= RTL_MIN_CONE_SLOPE) {最小的椎体斜坡0.5

target_alt = MAX(curr_alt, MIN(target_alt, MAX(rtl_return_dist_cm*g.rtl_cone_slope, curr_alt+RTL_ABS_MIN_CLIMB)));

}起始点到返回点距离乘以椎体斜坡率,当前高度加2.5m,

// set returned target alt to new target_alt

rtl_path.return_target.set_alt_cm(target_alt, rtl_path.terrain_used ? Location_Class::ALT_FRAME_ABOVE_TERRAIN : Location_Class::ALT_FRAME_ABOVE_HOME);

#if AC_FENCE == ENABLED

// ensure not above fence altitude if alt fence is enabled

// Note: because the rtl_path.climb_target's altitude is simply copied from the return_target's altitude,

//       if terrain altitudes are being used, the code below which reduces the return_target's altitude can lead to

//       the vehicle not climbing at all as RTL begins.  This can be overly conservative and it might be better

//       to apply the fence alt limit independently on the origin_point and return_target

if ((fence.get_enabled_fences() & AC_FENCE_TYPE_ALT_MAX) != 0) {

// get return target as alt-above-home so it can be compared to fence's alt

if (rtl_path.return_target.get_alt_cm(Location_Class::ALT_FRAME_ABOVE_HOME, target_alt)) {

float fence_alt = fence.get_safe_alt()*100.0f;

if (target_alt > fence_alt) {

// reduce target alt to the fence alt

rtl_path.return_target.alt -= (target_alt - fence_alt);

}

}

}

#endif

// ensure we do not descend

rtl_path.return_target.alt = MAX(rtl_path.return_target.alt, curr_alt);

}

// rtl_run - runs the return-to-launch controller

// should be called at 100hz or more

void Copter::rtl_run()

{

// check if we need to move to next state

if (rtl_state_complete) {  当前状态是否完成

switch (rtl_state) {

case RTL_InitialClimb:

rtl_return_start();3,rtl_state = RTL_ReturnHome; rtl_state_complete = false。飞机已经上升,该函数主要让Yaw角指向HOME点 给WP控制器的是return target

break;

case RTL_ReturnHome:

rtl_loiterathome_start();5,rtl_state = RTL_LoiterAtHome; rtl_state_complete = false,yaw角调整到起飞时的初始角

break;

case RTL_LoiterAtHome:

if (rtl_path.land || failsafe.radio) {

rtl_land_start(); 7.着陆

}else{

rtl_descent_start();7.下降rtl_state = RTL_FinalDescent;

rtl_state_complete = false;

}

break;

case RTL_FinalDescent:

// do nothing

break; 9.下降结束

case RTL_Land:

// do nothing - rtl_land_run will take care of disarming motors

break; 9.着陆结束

}

}

// call the correct run function

switch (rtl_state) {

case RTL_InitialClimb:

rtl_climb_return_run(); 2,完成climb_target,让飞机上升,rtl_state = RTL_InitialClimb,rtl_state_complete = true

break;

case RTL_ReturnHome:

rtl_climb_return_run();4完成return target,rtl_state = RTL_ReturnHome,rtl_state_complete = true。此时飞机飞到HOME的正上方

break;

case RTL_LoiterAtHome:

rtl_loiterathome_run();6,一直盘旋,调整yaw角

break;

case RTL_FinalDescent:

rtl_descent_run();8.下降

break;

case RTL_Land:

rtl_land_run(); 8.着陆

break;

}

}

void Copter::rtl_climb_start()

{

rtl_state = RTL_InitialClimb;

rtl_state_complete = false;

// initialise waypoint and spline controller

wp_nav.wp_and_spline_init(); 初始化WP控制器

// RTL_SPEED == 0 means use WPNAV_SPEED

if (g.rtl_speed_cms != 0) {

wp_nav.set_speed_xy(g.rtl_speed_cms);设置WP控制器的最大水平速度,没有则用默认5m/s

}

// set the destination

if (!wp_nav.set_wp_destination(rtl_path.climb_target)) {设置目标点

// this should not happen because rtl_build_path will have checked terrain data was available

Log_Write_Error(ERROR_SUBSYSTEM_NAVIGATION, ERROR_CODE_FAILED_TO_SET_DESTINATION);

set_mode(LAND, MODE_REASON_TERRAIN_FAILSAFE);

return;

}

wp_nav.set_fast_waypoint(true);目标点为fast wp

// hold current yaw during initial climb

set_auto_yaw_mode(AUTO_YAW_HOLD);在爬升期间yaw角模式设为遥控器控制模式

}

// rtl_climb_return_run - implements the initial climb, return home and descent portions of RTL which all rely on the wp controller

//      called by rtl_run at 100hz or more

void Copter::rtl_climb_return_run()

{

// if not auto armed or motor interlock not enabled set throttle to zero and exit immediately

if (!motors.armed() || !ap.auto_armed || !motors.get_interlock()) {

#if FRAME_CONFIG == HELI_FRAME  // Helicopters always stabilize roll/pitch/yaw

// call attitude controller

attitude_control.input_euler_angle_roll_pitch_euler_rate_yaw(0, 0, 0, get_smoothing_gain());

attitude_control.set_throttle_out(0,false,g.throttle_filt);

#else

motors.set_desired_spool_state(AP_Motors::DESIRED_SPIN_WHEN_ARMED);

// multicopters do not stabilize roll/pitch/yaw when disarmed

// reset attitude control targets

attitude_control.set_throttle_out_unstabilized(0,true,g.throttle_filt);

#endif

// To-Do: re-initialise wpnav targets

return;

}不需要

// process pilot's yaw input

float target_yaw_rate = 0;

if (!failsafe.radio) {

// get pilot's desired yaw rate

target_yaw_rate = get_pilot_desired_yaw_rate(channel_yaw->get_control_in());获取遥控器给出的yaw角

if (!is_zero(target_yaw_rate)) {

set_auto_yaw_mode(AUTO_YAW_HOLD); 如果遥控器有输出yaw角,设置为遥控器控制yaw角模式

}

}

// set motors to full range

motors.set_desired_spool_state(AP_Motors::DESIRED_THROTTLE_UNLIMITED);电机可以全速转动

// run waypoint controller

failsafe_terrain_set_status(wp_nav.update_wpnav()); 运行wp控制器

// call z-axis position controller (wpnav should have already updated it's alt target)

pos_control.update_z_controller();

// 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(wp_nav.get_roll(), wp_nav.get_pitch(), target_yaw_rate, get_smoothing_gain()); WP控制器输出的roll,pitch。遥控器输出的yaw

}else{

// roll, pitch from waypoint controller, yaw heading from auto_heading()

attitude_control.input_euler_angle_roll_pitch_yaw(wp_nav.get_roll(), wp_nav.get_pitch(), get_auto_heading(),true, get_smoothing_gain());WP控制器输出的roll,pitch。Yaw不变

}

// check if we've completed this stage of RTL

rtl_state_complete = wp_nav.reached_wp_destination();

}

APM程序分析-Control_rtl.cpp的更多相关文章

  1. APM程序分析-AC_WPNav.cpp

    APM程序分析 主程序在ArduCopter.cpp的loop()函数. /// advance_wp_target_along_track - move target location along ...

  2. APM程序分析-ArduCopter.cpp

    该文件是APM的主文件. #define SCHED_TASK(func, rate_hz, max_time_micros) SCHED_TASK_CLASS(Copter, &copter ...

  3. 二进制程序分析工具Pin在Windows系统中的安装和使用方法

    这篇日志其实很弱智,也是因为换了新电脑,实验环境不全(当然,做这个实验我是在虚拟机里,因为接下来想拿些恶意代码的数据),所以这里记录一下在Windows下怎么安装和使用Pin这个程序分析领域最常用的工 ...

  4. 对Java数组中去除重复项程序分析

    我作为一个Java菜鸟,只会用简单的办法来处理这个问题.如果有大神看到,请略过,感激不尽! 所以首先先分析这道题目:数组中重复的数据进行删除,并且要让数组里的数据按原来的顺序排列,中间不能留空. 既然 ...

  5. (IOS)BaiduFM 程序分析

    本文主要分享下楼主在学习Swift编程过程中,对GitHub上的一个开源app BaiduFM的研究心得. 项目地址:https://github.com/belm/BaiduFM-Swift 一.项 ...

  6. Linux程序分析工具:ldd和nm

    ldd和nm是Linux下两个非常实用的程序分析工具.其中,ldd是用来分析程序运行时需要依赖的动态链接库的工具,nm是用来查看指定程序中的符号表信息的工具. 1 ldd 格式:ldd [option ...

  7. C#程序分析

    一.程序及问题 阅读下面程序,请回答如下问题: 问题1:这个程序要找的是符合什么条件的数? 问题2:这样的数存在么?符合这一条件的最小的数是什么? 问题3:在电脑上运行这一程序,你估计多长时间才能输出 ...

  8. linux程序分析工具

    ldd和nm是Linux下两个非常实用的程序分析工具.ldd是用来分析程序运行时需要依赖的动态链接库的工具,nm是用来查看指定程序中的符号表信息的工具,objdump用来查看源代码与汇编代码,-d只查 ...

  9. caffe源代码分析--softmax_layer.cpp

    caffe源代码分析--softmax_layer.cpp // Copyright 2013 Yangqing Jia // #include <algorithm> #include ...

随机推荐

  1. localForage——轻松实现 Web 离线存储(转)

    localStorage 能够让你实现基本的数据存储,但它的速度慢,而且不能处理二进制数据.IndexedDB 和 WebSQL 是异步的,速度快,支持大数据集,但他们的API 使用起来有点复杂.不仅 ...

  2. Javascript动态执行JS(new Function与eval比较)

    new Function与eval可以动态执行JS,只要把拼接好的JS方法,然后以字符串的形式传入到这两个函数,可以执行,其中new Function用在模板引擎比较多. 用 Function 类直接 ...

  3. CUDA[1] Introductory

    Section 0 :Induction of CUDA CUDA是啥?CUDA®: A General-Purpose Parallel Computing Platform and Program ...

  4. table:设置边距,td内容过长用省略号代替

    table:设置边距,td内容过长用省略号代替 1.table:设置边距 合并表格边框border-collapse: collapse,然后用th,td的padding设置内容和边框之间的空隙pad ...

  5. Bzoj3894 文理分科

    Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 667  Solved: 389 Description  文理分科是一件很纠结的事情!(虽然看到这个题 ...

  6. PHP日志记录规范PSR-3

    .note-content { font-family: "Helvetica Neue", Arial, "Hiragino Sans GB", STHeit ...

  7. ADO.NET--收藏整理别人的教程

    本文所有内容均从前辈的博客中收集整理而来,仅供自己学习参考的时候快速访问用. ADO.NET入门教程(一) 初识ADO.NET ADO.NET入门教程(二)了解.NET数据提供程序 ADO.NET入门 ...

  8. wifi万能钥pc版提示手机未连接

     关于PC版万能钥匙的用法 大部分人都是在“未连接到手机”再不知道怎么搞了 怎么连接到手机呢? 首先要把你的手机变成路由器 让电脑连上 这个都知道怎么搞吧 手机版万能钥匙有个一键让手机变成热点 再用电 ...

  9. YII Install 安装

    Download     Yii is an open source project released under the terms of the BSD License. This means t ...

  10. php文件锁

    前言 1.锁机制之所以存在是因为并发问题导致的资源竞争,为了确保操作的有效性和完整性,可以通过锁机制将并发状态转换成串行状态.作为锁机制中的一种,PHP 的文件锁也是为了应对资源竞争.假设一个应用场景 ...