[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 load
和 param 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, ¶m_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参数元数据框架见:module_schema.yaml
- 在MAVLink参数定义中,使用了YAML定义,见:/src/modules/mavlink/module.yaml
多实例(模板)参数元数据定义
YAML中支持多实例参数的定义,可以在参数名和参数描述中使用${i}
。例如,要生成 MY_PARAM_1_RATE
和MY_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 clean
和make 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的值更新为参数值。