资讯详情

PX4从放弃到精通(十八):参数

文章目录

  • 前言
  • 一、 解检查参数
  • 二、安全设置
    • 1.低功率保护
    • 2.遥控信号丢失保护
    • 3.地理围栏保护
    • 4.数据链路丢失保护
    • 5.设置返航模式
    • 6.着陆模式设置
  • 三、任务航点参数
    • 航点半径
    • 无人船在跑航线时走S型
    • 最大水平距离从原点到第一大水平距离
    • 路点之间最大水平距离
    • 最小悬停高度
    • 使用偏航控制
    • 起飞高度
    • 需要起飞点吗?
    • 接受所需的最大偏差误差(度)
    • 偏航模式
    • 置信半径
    • 固定翼着陆前高度置信半径
    • 固定翼高度置信半径
    • 盘旋半径(仅固定翼)
  • 四、无人机室内视觉定位参数
  • 五、其它参数
    • 关闭蜂鸣器
    • 在无人机自稳定或定高模式下设置最大倾斜角
    • 状态估计算法选择参数
    • 空速计开关
    • 发动机故障检测开关
    • 解锁检查固定翼模式
    • 电调检查
    • DShot电调配置
    • DShot 电机最小输出
    • 主GPS的串口配置
    • 主GPS协议
    • MAVLink的串口配置
    • 最大MAVLink发送速率
    • 成功起飞后的动作
    • 修改高数据源
    • 设置日志记录条件
    • 设置自动加锁时间
  • 六、参数的导出和导入
  • 七、自定义参数
  • 八、常用函数分析
    • 1.参数搜索函数param_find
    • 2.参数获取函数param_get

前言

PX4 1.11以上版本 PX所有参数都在firmware-build/src/lib/parameters/px4_parameters.h文件里

一、 解锁检查参数

1电源检查

这个参数是检查解锁时是否有电池供电,默认情况下需要插电流计供电才能解锁。如果你想通过其他方式(如ESC为解锁飞控供电,需设置894281参数。 在这里插入图片描述

2.USB连接检查

该参数检查起飞时是否起飞USB默认情况下有连接USB连接时是无法解锁的,如果需要插USB需要设置为197848

3.检查安全开关

默认情况下,安全开关处于慢闪状态。设置参数蔚2027时,安全开关上电后自动切换为双闪。

4.检查传感器

解锁前,飞行控制器将检查传感器的状态。如果检查失败,则无法解锁。 (1)如果报错加速度偏移过大,high Accelerometer bios 可以把com_arm_ekf_ab这个参数调大了 (2)同样,陀螺仪的起飞检查阈值可以通过改变以下参数来提高,com_arm_ekf_gb (3)如果罗盘没有包含一定程度的错误,COM_ARM_MAG_ANG设为-1 (4)如果GPS搜星少,长时间没进,GPS定位,可以下面EKF2_GPS_CHECK改成0

(5)如果报下面的错

以加速度计为例,如果陀螺仪出现类似的错误,请修改相应的参数 (6)如果偏航角一直漂移 校准陀螺仪的解决方案是校准陀螺仪

二、安全设置

1.低功率保护

在地面站的安全设置中,低功率保护有以下三种动作:警告(只发出警告,不执行任何动作)、着陆(当功率低于故障保护水平时,直接着陆)、临界水平、紧急水平(当功率低于故障保护水平时,当功率低于紧急水平时)

2.遥控信号丢失保护

遥控信号丢失超过时间后,遥控器丢失保护可设置为不使用、返回、降落等模式

3.地理围栏保护

地理围栏是指以无人机设置围栏时的位置为中心,设置的最大半径和最大高度为半径和高度的圆柱体范围。如果无人机飞行过程超出此范围,将启动相应的故障保护动作,如无能、警告、维护、返回、停止等。如果设置了相应的动作,则必须有无人机GPS解锁信号

4.数据链路丢失保护

地面站或板卡mavlink如果数据丢失时间超过设定的超时间,则会触发保护。保护动作包括:维护、返回、降落等

5.设置返航模式

下图可以设置返回后的爬升高度。无人机返回时,首先爬到设定的返回高度,然后飞回起飞点。返回起飞点后,根据设置,您可以选择立即着陆、停留但不着陆,停留一定时间后着陆

6.着陆模式设置

着陆时设置下降速率,着陆后几秒钟锁定电机

三、任务航点参数

航点半径

NAV_ACC_RAD 该参数设置判断到达航点的信心半径

无人船在跑航线时走S型

将参数GND_MAX_ANG改小一点

最大水平距离从原点到第一大水平距离

故障保护检查,防止以前存储在新起飞位置的飞行任务。将值设置为零或更小,以禁止使用。如果当前路点与起始位置的距离大于MIS_DIS_1WP,任务不会启动。

MIS_DIST_1WP 

路点之间最大水平距离

故障保护检查,防止运行路径过远的任务。将值设置为零或更小,以禁止。如果两个后续路点之间的任何距离大于MIS_DIST_WPS,任务不会开始

MIS_DIST_WPS 

最小悬停高度

这是系统将始终遵守的最小高度值。其目的是避免地面效应。如果没有最小悬挂高度,则设置为-1

MIS_LTRMIN_ALT 

使用偏航控制

如果启用,偏航命令将发送到机体,车辆将沿其飞行方向前进。如果禁止,车头将转向感兴趣的区域(ROI),(仅影响多翼机和感兴趣区域(ROI)任务项)

MIS_MNT_YAW_CTL 

起飞高度

这是系统在起飞模式下起飞的最小高度。

MIS_TAKEOFF_ALT 

需要起飞点吗?

若设置,任务可行性检查器将检查任务中是否有起飞点。

MIS_TAKEOFF_REQ 

接受所需的最大偏差误差(度)

MIS_YAW_ERR 
偏航模式

指定自动模式下的偏航航向,有指向航点、指向home点、远离home点、沿轨迹、指向航点(偏航优先)五种

MPC_YAW_MODE

置信半径

默认航点的置信半径,如果设置,如果航点中也设置了置信半径,则将被航路中的置信半径覆盖。对于固定翼,L1转弯距离被用于水平置信半径。

NAV_ACC_RAD

固定翼着陆前高度置信半径

固定翼着陆前最后一个航路点的高度置信半径。这通常小于标准垂直置信半径,因为靠近地面需要更高的精度。

NAV_FW_ALTL_RAD

固定翼高度置信半径

固定飞行高度的置信半径。

NAV_FW_ALT_RAD

盘旋半径(仅固定翼)

任务、保持模式、返航模式等的盘旋半径默认值(仅限固定翼)。

NAV_LOITER_RAD

四、无人机室内视觉定位参数

如果想让无人机在室内通过视觉进行定位,需要修改两个参数, 一个是EKF2_AID_MASK,改成24,位置和航向用视觉的数据。如下: 另一个是EKF2_HGT_MODE,改成Vison,如下:

五、其他参数

关闭蜂鸣器

CBRK_BUZZER改为782097

设置无人机自稳或定高模式下最大的倾斜角度

状态估计算法选择参数

SYS_MC_EST_GROUP,该参数可以指定飞控状态估计的算法,有单四元数互补滤波,四元数互补滤波加LPE,EKF2,默认采用EKF2,使用ekf2所需的最低传感器配置为加速度计、陀螺仪、磁力计、气压计。如果缺少任意一个,则EKF2无法运行,如果缺少磁力计和气压计,可以使用四元数互补滤波进行姿态解算,如果有位置传感器(如GPS),可以采用四元数互补滤波加LPE进行位姿估计。 如果报Disarmed by auto preflight disarming 将COM_DISARM_PRFLT禁用或改大一点

空速计开关

将此参数设置为162128将禁用空速传感器检查。

CBRK_AIRSPD_CHK

发动机故障检测开关

将此参数设置为284953将禁用发动机故障检测

CBRK_ENGINEFAIL

固定翼模式解锁检查

将此参数设置为159753将允许VTOL在固定翼模式下解锁

CBRK_VTOLARMING

电调检查

需要检测到所有电调才能解锁,此参数只正对可以返回状态的电调。正常电调配置不受此参数更改的影响。

COM_ARM_CHK_ESCS

DShot电调配置

启用/禁用DShot电调。不同的模式定义不同的速度,例如DShot150=150kb/s。并非所有ESC都支持所有模式。注:这将启用FMU输出上的DShot。对于带有IO的飞控板,需要禁用IO,将DShot电调接到FMU通道

DSHOT_CONFIG

DShot 电机最小输出

DShot的最小输出值(以百分比为单位)。该值取决于电调。确保将其设置得足够高,以便电机在怠速时始终旋转

DSHOT_MIN

主GPS的串口配置

配置要在哪个串行端口上运行主GPS。

GPS_1_CONFIG

主GPS协议

选择GPS协议(基于串口的数据协议)。选择自动检测将探测所有协议,因此速度较慢。

GPS_1_PROTOCOL

MAVLink的串口配置

配置要在哪个串口上运行MAVLink

MAV_0_CONFIG

最大MAVLink发送速率

配置MAVLink流的最大发送速率(字节/秒)。如果配置的数据流超过最大速率,则会自动降低每个数据流的发送速率。如果该值设置为0,则为理论值最大速率的一半。这对应于波特率/20(字节/秒)(波特率/10=8N1配置链路上的最大数据速率)

MAV_0_RATE

成功起飞后的动作

成功起飞后的模式转换。

COM_TAKEOFF_ACT

修改定高数据来源

ekf2_hgt_mode

设置日志记录条件

SDLOG_MODE

如果要上电后就开始记录日志,需要设置成从boot到shutdown

设置自动加锁时间

COM_DISARM_LAND

这个参数设置在地面解锁无人机后不打油门自动加锁的时间 -1表示不自动加锁

六、参数的导出和导入

先找一架正常能飞的无人机连接地面站 在参数页面右上角点击工具->保存到文件 保存的时候文件名注明参数的相关信息

然后将需要加载参数的无人机连接至地面站,注意需要加载参数的无人机必须和保存的参数脚本的固件版本、机架类型,飞控硬件等信息一致,否则可能炸机。 如果固件版本不一致,就先刷一下相应的固件,再加载参数,固件一致后,点击重置参数为固件的默认值 然后点击从文件载入 选择需要导入的参数文件

导入正常的话地面站上面所有的参数都是正常的,没有红色的提示

这个时候可以不用校准传感器,但是需要校准电调,如果用的遥控器和导入参数脚本所用的无人机的不一致,则需要校准遥控器。

七、自定义参数

首先自定义一个模块,在Firmware/src/modules文件夹下创建03param_test文件夹,然后在03param_test文件夹下面创建下面四个文件: (1) 定义参数文件,我这里创建了param_test_params.c文件,在该文件中添加如下两行定义:

PARAM_DEFINE_FLOAT(PARAM_TEST1, 0.2f);
PARAM_DEFINE_INT32(PARAM_TEST2, 0);

(2) 编辑param_test.h

#pragma once

#include <px4_platform_common/module.h>
#include <px4_platform_common/module_params.h>
#include <uORB/Subscription.hpp>
#include <uORB/Publication.hpp>
#include <uORB/topics/parameter_update.h>
extern "C" __EXPORT int param_test_main(int argc, char *argv[]);


class param_test : public ModuleBase<param_test>, public ModuleParams
{
public:
    param_test(int example_param, bool example_flag);

    virtual ~param_test() = default;

    /** @see ModuleBase */
    static int task_spawn(int argc, char *argv[]);

    /** @see ModuleBase */
    static param_test *instantiate(int argc, char *argv[]);

    /** @see ModuleBase */
    static int custom_command(int argc, char *argv[]);

    /** @see ModuleBase */
    static int print_usage(const char *reason = nullptr);

    /** @see ModuleBase::run() */
    void run() override;

    /** @see ModuleBase::print_status() */
    int print_status() override;

private:

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


    DEFINE_PARAMETERS(
        (ParamFloat<px4::params::PARAM_TEST1>) _param_test1,   /**< example parameter */
        (ParamInt<px4::params::PARAM_TEST2>) _param_test2  /**< another parameter */
    )
    // Subscriptions
    uORB::Subscription	_parameter_update_sub{ORB_ID(parameter_update)};

};

主要是在DEFINE_PARAMETERS里添加下面这条语句定义

DEFINE_PARAMETERS(
    (ParamFloat<px4::params::PARAM_TEST1>) _param_test1,   /**< example parameter */
    (ParamInt<px4::params::PARAM_TEST2>) _param_test2  /**< another parameter */
)

编辑param_test.cpp

#include "param_test.h"

#include <px4_platform_common/getopt.h>
#include <px4_platform_common/log.h>
#include <px4_platform_common/posix.h>
#include <uORB/topics/parameter_update.h>


int param_test::print_status()
{
    PX4_INFO("Running");
    // TODO: print additional runtime information about the state of the module

    return 0;
}

int param_test::custom_command(int argc, char *argv[])
{
    /*
    if (!is_running()) {
        print_usage("not running");
        return 1;
    }

    // additional custom commands can be handled like this:
    if (!strcmp(argv[0], "do-something")) {
        get_instance()->do_something();
        return 0;
    }
     */

    return print_usage("unknown command");
}


int param_test::task_spawn(int argc, char *argv[])
{
    _task_id = px4_task_spawn_cmd("module",
                                  SCHED_DEFAULT,
                                  SCHED_PRIORITY_DEFAULT,
                                  1024,
                                  (px4_main_t)&run_trampoline,
                                  (char *const *)argv);

    if (_task_id < 0)
    {
        _task_id = -1;
        return -errno;
    }

    return 0;
}

param_test *param_test::instantiate(int argc, char *argv[])
{
    int example_param = 0;
    bool example_flag = false;
    bool error_flag = false;

    int myoptind = 1;
    int ch;
    const char *myoptarg = nullptr;

    // parse CLI arguments
    while ((ch = px4_getopt(argc, argv, "p:f", &myoptind, &myoptarg)) != EOF)
    {
        switch (ch)
        {
            case 'p':
                example_param = (int)strtol(myoptarg, nullptr, 10);
                break;

            case 'f':
                example_flag = true;
                break;

            case '?':
                error_flag = true;
                break;

            default:
                PX4_WARN("unrecognized flag");
                error_flag = true;
                break;
        }
    }

    if (error_flag)
    {
        return nullptr;
    }

    param_test *instance = new param_test(example_param, example_flag);

    if (instance == nullptr)
    {
        PX4_ERR("alloc failed");
    }

    return instance;
}

param_test::param_test(int example_param, bool example_flag)
    : ModuleParams(nullptr)
{
}

void param_test::run()
{
    while (!should_exit())
    {
        double param_test1=_param_test1.get();
        int param_test2=_param_test2.get();
        PX4_INFO("param_test1=%lf param_test2=%d\n",param_test1,param_test2);
        usleep(100000);
    }

}

void param_test::parameters_update(bool force)
{
    // check for parameter updates
    if (_parameter_update_sub.updated() || force)
    {
        // clear update
        parameter_update_s update;
        _parameter_update_sub.copy(&update);

        // update parameters from storage
        updateParams();
    }
}

int param_test::print_usage(const char *reason)
{
    if (reason)
    {
        PX4_WARN("%s\n", reason);
    }

    PRINT_MODULE_DESCRIPTION(
        R"DESCR_STR(
### Description
Section that describes the provided module functionality.

This is a template for a module running as a task in the background with start/stop/status functionality.

### Implementation
Section describing the high-level implementation of this module.

### Examples
CLI usage example:
$ module start -f -p 42

)DESCR_STR");

	PRINT_MODULE_USAGE_NAME("module", "template");
	PRINT_MODULE_USAGE_COMMAND("start");
	PRINT_MODULE_USAGE_PARAM_FLAG('f', "Optional example flag", true);
	PRINT_MODULE_USAGE_PARAM_INT('p', 0, 0, 1000, "Optional example parameter", true);
	PRINT_MODULE_USAGE_DEFAULT_COMMANDS();

	return 0;
}

int param_test_main(int argc, char *argv[])
{
        return param_test::main(argc, argv);
}

通过上面的代码设置的参数只有在重启后才会生效,如果想使参数立即生效,可以用parameters_update()函数。下面的param_test.cpp会使参数立即生效。

#include "param_test.h"

#include <px4_platform_common/getopt.h>
#include <px4_platform_common/log.h>
#include <px4_platform_common/posix.h>
#include <uORB/topics/parameter_update.h>


int param_test::print_status()
{ 
        
    PX4_INFO("Running");
    // TODO: print additional runtime information about the state of the module

    return 0;
}

int param_test::custom_command(int argc, char *argv[])
{ 
        
    /* if (!is_running()) { print_usage("not running"); return 1; } // additional custom commands can be handled like this: if (!strcmp(argv[0], "do-something")) { get_instance()->do_something(); return 0; } */

    return print_usage("unknown command");
}


int param_test::task_spawn(int argc, char *argv[])
{ 
        
    _task_id = px4_task_spawn_cmd("module",
                                  SCHED_DEFAULT,
                                  SCHED_PRIORITY_DEFAULT,
                                  1024,
                                  (px4_main_t)&run_trampoline,
                                  (char *const *)argv);

    if (_task_id < 0)
    { 
        
        _task_id = -1;
        return -errno;
    }

    return 0;
}

param_test *param_test::instantiate(int argc, char *argv[])
{ 
        
    int example_param = 0;
    bool example_flag = false;
    bool error_flag = false;

    int myoptind = 1;
    int ch;
    const char *myoptarg = nullptr;

    // parse CLI arguments
    while ((ch = px4_getopt(argc, argv, "p:f", &myoptind, &myoptarg)) != EOF)
    { 
        
        switch (ch)
        { 
        
            case 'p':
                example_param = (int)strtol(myoptarg, nullptr, 10);
                break;

            case 'f':
                example_flag = true;
                break;

            case '?':
                error_flag = true;
                break;

            default:
                PX4_WARN("unrecognized flag");
                error_flag = true;
                break;
        }
    }

    if (error_flag)
    { 
        
        return nullptr;
    }

    param_test *instance = new param_test(example_param, example_flag);

    if (instance == nullptr)
    { 
        
        PX4_ERR("alloc failed");
    }

    return instance;
}

param_test::param_test(int example_param, bool example_flag)
    : ModuleParams(nullptr)
{ 
        
    parameters_update(true);
}

void param_test::run()
{ 
        
    while (!should_exit())
    { 
        
        parameters_update();
        double param_test1=_param_test1.get();
        int param_test2=_param_test2.get();
        PX4_INFO("param_test1=%lf param_test2=%d\n",param_test1,param_test2);
        usleep(100000);
    }

}

void param_test::parameters_update(bool force)
{ 
        
    // check for parameter updates
    if (_parameter_update_sub.updated() || force)
    { 
        
        // clear update
        parameter_update_s update;
        _parameter_update_sub.copy(&update);

        // update parameters from storage
        updateParams();
    }
}

int param_test::print_usage(const char *reason)
{ 
        
    if (reason)
    { 
        
        PX4_WARN("%s\n", reason);
    }

    PRINT_MODULE_DESCRIPTION(
        R"DESCR_STR(
### Description
Section that describes the provided module functionality.

This is a template for a module running as a task in the background with start/stop/status functionality.

### Implementation
Section describing the high-level implementation of this module.

### Examples
CLI usage example:
$ module start -f -p 42

)DESCR_STR");

	PRINT_MODULE_USAGE_NAME("module", "template");
	PRINT_MODULE_USAGE_COMMAND("start");
	PRINT_MODULE_USAGE_PARAM_FLAG('f', "Optional example flag", true);
	PRINT_MODULE_USAGE_PARAM_INT('p', 0, 0, 1000, "Optional example parameter", true);
	PRINT_MODULE_USAGE_DEFAULT_COMMANDS();

	return 0;
}

int param_test_main(int argc, char *argv[])
{ 
        
        return param_test::main(argc, argv);
}

编辑CMakeLists.txt

px4_add_module(
	MODULE modules__03param_test
	MAIN param_test
	SRCS
		param_test.cpp
	)

然后将03param_test添加到编译脚本 我这里添加到fmu-v5的脚本

(3) 先在Firmware路径执行make parameters_metadata (4 )然后编译固件下载到飞控

make px4_fmu-v5_default upload

连接地面站,刷新参数 就可以找到添加的参数

如果进程是手动启动的,在手动启动后要刷新参数,地面站才会显示自定义的参数 可以在启动脚本或者程序里使用自定义的参数 可以仿造SYS_MC_EST_GROUP来写 仿写如下:

if param compare PARAM_TEST2 0
then
a start
else
b start
fi

八、常用函数解析

1.参数查找函数param_find

PX4通过param_find()函数对参数进行查找,该函数的使用方法如下:

param_t handle = param_find("GPS_YAW_OFFSET");

参数为函数名,如果能够找到参数,则返回该参数的索引值(PX4中的所有参数存放在一个结构体数组中,数组中每个结构体代表一个参数,里面存放着参数名和参数的值,,返回的索引值即为该参数在结构体数组中的索引),如果找不到该参数,返回最大值0xffff。该函数定义如下:

param_t param_find(const char *name)
{
	return param_find_internal(name, true);
}

调用了函数param_find_internal(),继续看该函数的定义如下,由于参数是按照字母顺序排列的,这里通过二分查找来查找参数:

static param_t param_find_internal(const char *name, bool notification)
{
	perf_count(param_find_perf);

二分查找的中间值

param_t middle;

二分查找的头

param_t front = 0;

二分查找的尾

param_t last = param_info_count;

当头小于等于尾时,继续执行

while (front <= last) {

middle就是头和尾的中间数

middle = front + (last - front) / 2;

通过strcmp进行比较

int ret = strcmp(name, param_name(middle));

name就是需要查找的参数名,param_name(middle)就是根据索引值middle返回参数名称,定义如下:

const char *param_name(param_t param)
{
	return handle_in_range(param) ? px4::parameters[param].name : nullptr;
}

handle_in_range就是判断参数是否在最大索引值param_info_count范围内,定义如下:

static constexpr bool handle_in_range(param_t param) { return (param < param_info_count); }

param_info_count就是将结构体数组parameters总的大小除以单个结构体param_info_s的大小。

static constexpr uint16_t param_info_count = sizeof(px4::parameters) / sizeof(param_info_s);

如果参数的索引在最大索引值param_info_count范围内,则返回参数名px4::parameters[param].name 参数结构体数组parameters的定义如下:

static constexpr param_info_s parameters[] = {
	{
		"ASPD_BETA_GATE",
		.val = { .i = 1},
	},

	{
		"ASPD_BETA_NOISE",
		.val = { .f = 0.3 },
	},
......(一共一千多个参数,每个参数的结构都一样,后面不列举)
}

该数组由结构体param_info_s组成,该结构提定义如下:包含参数名name和参数值val。

struct param_info_s {
	const char *name;
	union param_value_u val;
};

参数值val是一个共用体,包含指针、int32和float三种类型,一般都用int32或者float

union param_value_u {
	void		*p;
	int32_t		i;
	float		f;
};

通过strcmp进行比较时,name=param_name(middle)两个字符串自左向右逐个字符相比(按ASCII值大小相比较),直到出现不同的字符或遇’\0’为止。若name=param_name(middle),则返回零,说明找到了参数,这时二分查找的中间值middle即为函数的索引值,返回参数的索引值middle。

if (ret == 0) {
	if (notification) {
		param_set_used(middle);
	}
				perf_end(param_find_perf);
			return middle;
				} 

如果没有找到参数并且中间值middle和front相等,说明已经到了最和一个位置也没有找到参数,跳出循环返回未找到

else if (middle == front) {
		/* An end point has been hit, but there has been no match */
		break;

	} 

若name<param_name(middle),则返回负数;由于结构体数组parameters是安照参数名的字母顺序从小到大排列的,因此需要差查找的参数名name对应的索引值应该在front和middle之间,因此front不动,将last置为middle,从而在front和middle之间继续二分查找

else if (ret < 0) {
			last = middle;
		} 

若name>param_name(middle),则返回正数,此时需要差查找的参数名name对应的索引值应该在middle和last之间,因此last不动,将front置为middle,从而在middle和last之间继续二分查找

else {
			front = middle;
		}
	}

未找到则返回PARAM_INVALID(0xffff)

	/* not found */
	return PARAM_INVALID;
}

2.参数获取函数param_get

param_get主要用于获取参数的值,函数定义如下: 宏定义

#define param_get(param, val) param_get_cplusplus(param, val)

参数有float和int32_t两种类型,因此进行了函数的重载,根据不同的类型进行类型检查,然后调用param_get(param, (void *)val)获取参数值

static inline int param_get_cplusplus(param_t param, float *val)
{
	CHECK_PARAM_TYPE(param, PARAM_TYPE_FLOAT);
	return param_get(param, (void *)val);
}
static inline int param_get_cplusplus(param_t param, int32_t *val)
{
	CHECK_PARAM_TYPE(param, PARAM_TYPE_INT32);
	return param_get(param, (void *)val);
}

param_get(param_t param, void *val)的定义如下:

int
param_get(param_t param, void *val)
{
	perf_count(param_get_perf);

如果参数的索引超出范围,返回错误

if (!handle_in_range(param)) {
	PX4_ERR("get: param %" PRId16 " invalid", param);
	return PX4_ERROR;
}
if (!params_active[param]) {
	PX4_DEBUG("get: param %" PRId16 " (%s) not active", param, param_name(param));
}

int result = PX4_ERROR;

if (val) {
	param_lock_reader();

调用param_get_value_ptr(param)返回参数值的指针

const void *v = param_get_value_ptr(param);

通过memcpy将参数值赋值到指针val指向的地址。

if (v) {
	memcpy(val, v, param_size(param));
	result = PX4_OK;
}
		param_unlock_reader();
	}

	return result;
}

函数param_get_value_ptr(param)的定义如下:

static const void *
param_get_value_ptr(param_t param)
{
	param_assert_locked();

如果参数索引在最大范围内 if (handle_in_range(param)) { /* work out whether we’re fetching the default or a written value */ struct param_wbuf_s *s = param_find_changed(param);

	if (s != nullptr) {
		return &s->val;

	} else {
		if (params_custom_default[param] && param_custom_default_values) {
			// get default from custom default storage
			param_wbuf_s key{};
			key.param = param;
			param_wbuf_s *pbuf = (param_wbuf_s *)utarray_find(param_custom_default_values, &key, param_compare_values);

			if (pbuf != nullptr) {
				return &pbuf->val;
			}
		}

		// otherwise return static default value
		switch (param_type(param)) {
		case PARAM_TYPE_INT32:
			return &px4::parameters[param].val.i;

		case PARAM_TYPE_FLOAT:
			return &px4::parameters[param].val.f;
		}
	}
}

return nullptr;

}

标签: px3981传感器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台