L1 control——ArduPilot——更新圆圈update_Loiter

版权声明:本文为博主原创博文,未经允许不得转载,若要转载,请说明出处并给出博文链接 

本文详细讲解了ArduPilot中AP_L1_control库中的update_loiter函数的具体实现!!!

下面是源代码:

// update L1 control for loitering
void AP_L1_Control::update_loiter(const struct Location &center_WP, float radius, int8_t loiter_direction)
{
    struct Location _current_loc;

    // 计算loiter半径
    radius = loiter_radius(radius);

    // 计算PD控制增益(用于跟踪圆圈)
    float omega = (6.2832f / _L1_period);
    float Kx = omega * omega;
    float Kv = 2.0f * _L1_damping * omega;

    // 计算L1增益(用于捕获航点)
    float K_L1 = 4.0f * _L1_damping * _L1_damping;

    // 获取当前飞机的位置
    if (_ahrs.get_position(_current_loc) == false) {
        // if no GPS loc available, maintain last nav/target_bearing
        _data_is_stale = true;
        return;
    }
    // 通过融合空速计和GPS二者的速度,计算出地速
    Vector2f _groundspeed_vector = _ahrs.groundspeed_vector();

    // 计算地速
    float groundSpeed = MAX(_groundspeed_vector.length() , 1.0f);


    // 更新目标方位角
    _target_bearing_cd = get_bearing_cd(_current_loc, center_WP);


    // 计算L1 length
    // 0.3183099 = 1/pi
    _L1_dist = 0.3183099f * _L1_damping * _L1_period * groundSpeed;

    // 计算飞机相对航点A的水平位置向量
    Vector2f A_air = location_diff(center_WP, _current_loc);

    // 计算A_air的单位长度
    Vector2f A_air_unit;
    if (A_air.length() > 0.1f) {
        A_air_unit = A_air.normalized();
    } else {
        if (_groundspeed_vector.length() < 0.1f) {
            A_air_unit = Vector2f(cosf(_ahrs.yaw), sinf(_ahrs.yaw));
        } else {
            A_air_unit = _groundspeed_vector.normalized();
        }
    }

    // 计算捕获中心航点的Nu
    float xtrackVelCap = A_air_unit % _groundspeed_vector; // 指向航点的垂直方向速度
    float ltrackVelCap = - (_groundspeed_vector * A_air_unit); // 指向航点的速度
    float Nu = atan2f(xtrackVelCap,ltrackVelCap);

    _prevent_indecision(Nu);
    _last_Nu = Nu;

    Nu = constrain_float(Nu, -M_PI_2, M_PI_2); //Limit Nu to +- Pi/2

    // 用L1制导律计算水平倾斜加速度
    float latAccDemCap = K_L1 * groundSpeed * groundSpeed / _L1_dist * sinf(Nu);

    // 计算圆圈半径和速度的误差
    float xtrackVelCirc = -ltrackVelCap; // Radial outbound velocity - reuse previous radial inbound velocity
    float xtrackErrCirc = A_air.length() - radius; // Radial distance from the loiter circle

    // 记录航迹误差
    _crosstrack_error = xtrackErrCirc;

    // 用PD控制器计算水平倾斜加速度
    float latAccDemCircPD = (xtrackErrCirc * Kx + xtrackVelCirc * Kv);

    // 计算切向速度
    float velTangent = xtrackVelCap * float(loiter_direction);

    //Prevent PD demand from turning the wrong way by limiting the command when flying the wrong way
    if (ltrackVelCap < 0.0f && velTangent < 0.0f) {
        latAccDemCircPD =  MAX(latAccDemCircPD, 0.0f);
    }

    // 计算向心加速度
    float latAccDemCircCtr = velTangent * velTangent / MAX((0.5f * radius), (radius + xtrackErrCirc));

    // P+D+ff
    float latAccDemCirc = loiter_direction * (latAccDemCircPD + latAccDemCircCtr);

    // Perform switchover between 'capture' and 'circle' modes at the
    // point where the commands cross over to achieve a seamless transfer
    // Only fly 'capture' mode if outside the circle
    if (xtrackErrCirc > 0.0f && loiter_direction * latAccDemCap < loiter_direction * latAccDemCirc) {
        _latAccDem = latAccDemCap;
        _WPcircle = false;
        _bearing_error = Nu; // angle between demanded and achieved velocity vector, +ve to left of track
        _nav_bearing = atan2f(-A_air_unit.y , -A_air_unit.x); // bearing (radians) from AC to L1 point
    } else {
        _latAccDem = latAccDemCirc;
        _WPcircle = true;
        _bearing_error = 0.0f; // bearing error (radians), +ve to left of track
        _nav_bearing = atan2f(-A_air_unit.y , -A_air_unit.x); // bearing (radians)from AC to L1 point
    }

    _data_is_stale = false; // status are correctly updated with current waypoint data
}

通过对上面的代码进行分析,可以发现该函数包含两个控制器,①capture模式—L1控制器 ②circle模式—PD控制器,两个控制器都会计算出飞机的水平加速度的目标值,即_latAccDem。这两个控制器的工作范围不同,当飞机还没有跟踪上圆圈,也就是还在圆圈外环的时候用L1控制器,当飞机已经跟踪上了圆圈的时候用PD控制器。

在RTL、GUIDED和LOITER模式下都会执行上面这个函数,其中涉及到的相关理论原理以及示意图如下所示。

 

 

             ../_images/L1_loiter.png

<think>好的,用户现在提供了一个关于Waf构建脚本的问题,需要我帮忙分析。让我仔细看看他的问题。 首先,用户之前遇到了编译错误,添加新文件后构建失败。现在他展示了一个`def build(bld):`的Waf脚本片段,可能是他在尝试修改构建配置时遇到问题。我需要解释这段脚本的作用,并帮助他排查可能的错误点。 用户可能是ArduPilot项目的开发者,对Waf构建系统有一定了解,但可能不太清楚如何正确配置模块依赖。他的需求是理解这段脚本的结构,并找出可能导致编译错误的原因。 接下来,我需要分析提供的脚本。脚本中的`bld.ap_stlib`用于创建静态库,包含一系列库模块,`bld.ap_program`则生成可执行文件arduplane,依赖前面创建的库。可能的错误点包括库名称拼写错误、缺少依赖模块或头文件路径问题。 用户之前的问题是关于添加新文件后编译失败,所以可能是在`ap_libraries`列表中没有包含新文件所需的模块,或者新文件没有被正确添加到源文件列表中。此外,检查是否有拼写错误,例如库名是否正确,比如`AP_L1_Control`是否存在,或者是否有遗漏的模块。 另外,用户可能在修改wscript文件时没有正确配置依赖项,导致链接阶段找不到相应的符号。例如,如果新文件使用了某个库的功能,但该库未被添加到`ap_libraries`中,就会导致未定义引用错误。 需要提醒用户检查模块名称的正确性,确认所有需要的库都已包含,并确保新文件的源文件被正确添加到对应的模块中。同时,建议用户使用`-v`参数重新编译,查看详细错误信息,定位具体问题所在。 最后,总结可能的解决步骤:检查库名拼写、确认依赖项完整、清理并重新构建,以及查看详细编译输出。这样用户就能逐步排查问题,解决编译错误。</think>这个Waf构建脚本片段用于配置ArduPilot项目的编译过程,主要涉及静态库创建和可执行程序生成。以下是关键解析与常见问题排查点: --- ### **一、脚本结构解析** #### 1. 静态库构建模块 ```python bld.ap_stlib( name=vehicle + '_libs', # 库名称,如"arduplane_libs" ap_vehicle=vehicle, # 当前载具类型标识 ap_libraries=[ # 核心依赖库列表 bld.ap_common_vehicle_libraries() + # 公共基础库 ['APM_Control', 'AP_Avoidance', ...] # 载具专用库 ] ) ``` - **作用**:将多个模块编译为静态库,供主程序链接 - **常见配置错误**:`AP_L1_Control`等库名拼写错误或实际不存在 #### 2. 可执行程序生成 ```python bld.ap_program( program_name='arduplane', # 输出可执行文件名 program_groups=['bin','plane'], # 文件输出路径分组 use=vehicle + '_libs' # 依赖的静态库 ) ``` - **路径说明**:最终生成`/bin/plane/arduplane`可执行文件 - **关键依赖**:`use`参数必须与静态库的`name`完全匹配 --- ### **二、新文件集成常见问题** #### 1. **模块依赖缺失** 当新文件使用特定模块功能时,需在`ap_libraries`列表中添加对应库: ```python # 示例:若新文件使用光流传感器 ap_libraries=[..., 'AP_OpticalFlow', ...] ``` #### 2. **头文件路径错误** 若出现`No such file`错误,检查: ```python # 在ap_stlib中可能需要添加: includes=['./your_new_module/include'] # 添加自定义头文件路径 ``` #### 3. **库顺序问题** 依赖关系必须按顺序排列,例如: ```python # 控制类库需在导航库之前 ['AC_AttitudeControl', 'AC_WPNav', ...] ``` --- ### **三、调试建议** #### 1. 验证库存在性 检查每个库对应的实际目录是否存在: ```bash ls libraries/AP_L1_Control # 确认目录名称匹配 ``` #### 2. 使用编译日志分析 ```bash ./waf --verbose | grep "undefined reference" # 捕获未定义符号 ``` #### 3. 典型错误对照表 | 错误类型 | 可能原因 | |-----------------------|----------------------------| | `undefined symbol` | 库未加入`ap_libraries`列表 | | `multiple definition` | 同名库被重复包含 | | `invalid conversion` | 库版本与主程序不兼容 | --- ### **四、修改后完整操作流程** 1. 清理旧构建: ```bash ./waf distclean ``` 2. 增量编译测试: ```bash ./waf configure --board sitl && ./waf arduplane -v ``` 3. 若仍失败,可临时注释新库进行隔离测试 建议通过`git diff > build_changes.patch`保存修改,便于问题回溯。实际编译错误需要结合具体输出信息进一步分析。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值