[PX4笔记]参数设置

本笔记内容基于v1.8.2固件,基于px4官方文档中章节参数设置

0. 命令行使用

PX4控制台(NSH)提供了param命令,可以用该命令来实现参数设置、读取、保存、导出和导入。

1. 获得和设置参数

使用param show命令可以获得系统的全部参数
并且可以使用通配符搜索
例如:
param shwo RC_MAP_A*

可以使用-c命令来查看已经改变的数值(不同于默认值的)

2. 导出和加载参数

使用 param save 命令可以保存参数到默认文件。
也可以增加一个参数来指定参数文件保存位置。
param save /fs/microsd/vtol_param_backup

可以看出来,存储后在对应目录下生成了vtol_param_backup的参数文件。
有两个命令可以加载参数:param loadparam import

  • param load命令首先重置所有参数到默认值,然后再从文件中加载参数并重写。
  • param import命令从文件中加载参数,重写参数值,并保存结果(调用 param save)。
    load命令和import不同的是load会恢复文件中保存的参数,而把其他参数恢复为默认值;import将文件中保存的参数融合进当前的飞机。例如可以用来导入校准参数,而不重置系统设置。

3. 参数命名

参数名字不超过16个ASCII字符。
通常,同一组中的每个参数使用相同的前缀后跟一个下划线,例如MC_FW_分别表示多旋翼和固定翼相关参数,不过该惯例不是强制的。
代码中的参数命名必须和参数元数据(parameter metadata)中的一致,从而将参数和他的元数据(包括固件中的默认值)关联起来。

4. C/C++ API

有单独的C和C++ API用来在PX4的模块和驱动中访问参数值。
C++版本的API有一个更有效的标准化机制来同步参数值的更改(从地面站)。
参数同步特别重要,因为参数值在什么时候都有可能更改,如果没法立即获得参数的最新值,那就需要在参数改变之后重启然后更新参数值(可以使用@reboot_required元数据来设置该特性)。
C++ API还具有更好的类型安全性,并且占用的内存更小。但是C++ API必须在编译时知道参数名,而C API可以动态使用字符串来创建参数名。

4.1 C++ API

C++ API使用宏来声明参数作为类属性。可以添加模板代码来监听和参数更新相关的uORB主题。框架代码跟踪影响参数特性的uORB消息来维持参数同步。在其他代码中,你可以使用定义好的参数特性,他们会一直保持同步。

首先,包含px4_platform_common/module_params.h在类的头文件中(以便可以使用DEFINE_PARAMETERS宏)。
从类ModuleParams来派生你的自定义类,并使用DEFINE_PARAMETERS宏来指定参数列表和对应的参数属性。参数名必须和他们对应的参数元数据定义一致。
示例代码如下:

class MyModule : ..., public ModuleParams
{
public:
    ...

private:

    /**
     * Check for parameter changes and update them if needed.
     * @param parameter_update_sub uorb subscription to parameter_update
     */
    void parameters_update(int parameter_update_sub, bool force = false);

    DEFINE_PARAMETERS(
        (ParamInt<px4::params::SYS_AUTOSTART>) _sys_autostart,   /**< example parameter */
        (ParamFloat<px4::params::ATT_BIAS_MAX>) _att_bias_max  /**< another parameter */
    )
};

然后使用模板来修改cpp源文件检查和uORB消息相关的参数更新。首先增加如下头文件来访问uORB中的parameter_update消息:

#include <uORB/topics/parameter_update.h>

然后在模块或者驱动启动时订阅参数更新消息,并在模块或驱动结束运行时解除订阅。orb_subscribe()返回的parameter_update_sub是个句柄,我们可以使用该句柄来引用该订阅。

# Subscribe to parameter_update message
int parameter_update_sub = orb_subscribe(ORB_ID(parameter_update));
...
# Unsubscribe to parameter_update messages
orb_unsubscribe(parameter_update_sub);

在代码中周期调用parameters_update(parameter_update_sub);来检查是否有参数更新:

void Module::parameters_update(int parameter_update_sub, bool force)
{
    bool updated;
    struct parameter_update_s param_upd;

    // Check if any parameter updated
    orb_check(parameter_update_sub, &updated);

    // If any parameter updated copy it to: param_upd
    if (updated) {
        orb_copy(ORB_ID(parameter_update), parameter_update_sub, &param_upd);
    }

    if (force || updated) {
        // If any parameter updated, call updateParams() to check if
        // this class attributes need updating (and do so). 
        updateParams();
    }
}

4.2 C API

C API可以在模块或者驱动中使用,首先包含参数API头文件:
#include <parameters/param.h>
然后就可以使用param_get函数来获得参数值,并赋给一个变量。例如如下代码将PARAM_NAME的值赋给my_param变量。

int32_t my_param = 0;
param_get(param_find("PARAM_NAME"), &my_param);

如果需要多次读取参数值,可以缓存参数句柄并且使用param_get来获得参数值:

# Get the handle to the parameter
param_t my_param_handle = PARAM_INVALID;
my_param_handle = param_find("PARAM_NAME");

# Query the value of the parameter when needed
int32_t my_param = 0;
param_get(my_param_handle, &my_param);

5.参数元数据

PX4使用参数元数据来驱动用户界面上的参数表达,并设置固件中每个参数的默认值。正确的参数元数据对于地面站的用户体验特别重要.
参数元数据可以存在代码的任何地方,可以使用.c或者.yaml文件来定义参数(YAML定义比较新,且更灵活).参数元数据文件通常存储在相关模块中。
编译系统通过使用make parameters_metadata来编译参数参考和地面站使用的参数信息。在增加新的参数之后,在重新编译之前必须使用make clean来生成新的参数

5.1 C参数元数据

C语言的参数元数据定义在.c文件中(当前代码中使用的最多的一种方式)。
参数元数据部分如下列代码所示:

/**
 * Pitch P gain
 *
 * Pitch proportional gain, i.e. desired angular speed in rad/s for error 1 rad.
 *
 * @unit 1/s
 * @min 0.0
 * @max 10
 * @decimal 2
 * @increment 0.0005
 * @reboot_required true
 * @group Multicopter Attitude Control
 */
PARAM_DEFINE_FLOAT(MC_PITCH_P, 6.5f);
/**
 * Acceleration compensation based on GPS
 * velocity.
 *
 * @group Attitude Q estimator
 * @boolean
 */
PARAM_DEFINE_INT32(ATT_ACC_COMP, 1);

可以看出,C语言版本的参数元数据采用PARAM_DEFINE_*宏来定义新参数,用注释来表示元数据(分组,说明,类型等信息),每行注释的说明如下所示(更多信息见module_schema.yaml):

/**
 * <title>
 *
 * <longer description, can be multi-line>
 *
 * @unit <the unit, e.g. m for meters>
 * @min <the minimum sane value. Can be overridden by the user>
 * @max <the maximum sane value. Can be overridden by the user>
 * @decimal <the minimum sane value. Can be overridden by the user>
 * @increment <the "ticks" in which this value will increment in the UI>
 * @reboot_required true <add this if changing the param requires a system restart.>
 * @boolean <add this for integer parameters that represent a boolean value>
 * @group <a title for parameters that form a group>
 */

5.2 YAML 元数据

在当前阶段YAML的参数元数据定义不能在Libraries里面使用
YAML用来代替.c定义方式,支持所有同样的元数据,并且支持一些新特性,例如多实例定义。

多实例(模板)参数元数据定义

YAML中支持多实例参数的定义,可以在参数名和参数描述中使用${i}。例如,要生成 MY_PARAM_1_RATEMY_PARAM_2_RATE等,可以使用如下代码:

MY_PARAM_${i}_RATE:
            description:
                short: Maximum rate for instance ${i}

6. 试验

由于代码中使用C方式增加参数的比较多,所以在此使用C API方式添加自定义参数,例如某飞机要使用两套参数进行切换,其中一套标准的,一套机翼比较短,我们以俯仰角速率控制为例,原本俯仰角速率积分系数元数据定义为:

/**
 * Pitch rate integrator gain.
 *
 * This gain defines how much control response will result out of a steady
 * state error. It trims any constant error.
 *
 * @unit %/rad
 * @min 0.005
 * @max 0.5
 * @decimal 3
 * @increment 0.005
 * @group FW Attitude Control
 */
PARAM_DEFINE_FLOAT(FW_PR_I, 0.02f);

我们增加一个后缀SS的,表示Short Span,元数据定义如下:

/**
 * Short Span Pitch rate integrator gain.
 *
 * This gain defines how much control response will result out of a steady
 * state error. It trims any constant error.
 *
 * @unit %/rad
 * @min 0.005
 * @max 0.5
 * @decimal 3
 * @increment 0.005
 * @group FW Attitude Control
 */
PARAM_DEFINE_FLOAT(FW_PR_I_SP, 0.01f);

运行make cleanmake parameters_metadata,然后编译固件并下载到飞控,然后进Mavlink的控制台,用param show指令可以看到该参数:

但是可以看到该参数没有使用,所以在QGC的Parameters标签页的FW Attitude Control中是看不到的,经过查找,发现在Other->Misc组里,好像要在QGC里对应到FW Attitude Control组里的话,需要在QGC源码里添加对应分组信息,并重新编译。
要使用该参数,在FixedwingAttitudeControl.hpp中的_parameter_handels结构体中加入param_t p_i_ss;
并在_parameters中定义该参数float p_i_ss;。然后在FixedwingAttitudeControl::parameters_update()函数中加入
param_get(_parameter_handles.p_i_ss, &(_parameters.p_i_ss));即可将_parameters.p_i_ss的值更新为参数值。

posted @ 2021-07-31 20:58  SpyCoder  阅读(1456)  评论(0编辑  收藏  举报