查看: 954|回复: 0

无人机 PX4 飞控 | PX4源码添加自定义模块方法

[复制链接]

57

主题

893

帖子

1788

积分

金牌飞友

Rank: 6Rank: 6

积分
1788
飞币
893
注册时间
2017-8-11
发表于 2025-2-9 19:08:13 | 显示全部楼层 |阅读模式
0 前言

PX4的模块是构成PX4飞控系统的重要组成部分,负责实现特定的功能,如飞控算法、传感器数据处理、通信协议等。

每个模块负责特定的任务,例如:

navigator 模块负责航线规划与任务执行。

commander模块负责处理飞行模式切换和系统状态监控。

sensors模块负责传感器数据的采集与处理。

PX4的设计允许用户添加自定义模块,从而扩展系统的功能。模块之间通过UORB(微ORB)进行数据交换,实现高效的信息传递

本篇文章在PX4-AutoPilot 1.14.0版本中,加入了一个自定义的模块,打印了一条消息,作为PX4源码添加自定义模块方法。

1 PX4模块的代码架构介绍

在PX4的代码里 src/modules 文件夹下,有很多的不同名字的文件夹,每个文件夹就是一个模块

如下:



例如多旋翼位置控制任务文件夹 mc_pos_control ,点进入可以看到有一个cpp和hpp文件



打开MulticopterPositionControl.hpp文件,这个是一个头文件,头文件里面一般是一个类



里面有个重要的函数Run



和这个位置控制模块一样,一般的某块需要包含:

一个cpp文件

一个hpp文件

一个**_params.c文件

一个CMakeLists.txt文件

一个Kconfig 文件

上面是最小的组成部分,如果还需要其它的库,则需要像位置控制模块一样再包含其它的文件夹(PositionControl、Takeoff),包含其它文件夹的个数不限。

2 新建分支避免弄乱源码

查看当前分支

git status



创建新分支

git branch feature_demo

切换到这个分支

git checkout feature_demo



以前的改动被提示

3 创建新模块

3.1 新件文件

在PX4源码里的src/modules文件夹下创建一个新文件夹命名为 jone_demo

并且在里面新建第1节提到的最小组成部分,即那几个文件分别命名为:

CMakeLists.txt

jone_demo_params.c

JoneDemo.cpp

JoneDemo.hpp

Kconfig



3.2 编辑CMakeLists.txt文件

编辑CMakeLists.txt文件,该文件负责编译

还是观察mc_pos_control模块的源文件:

add_subdirectory(PositionControl)add_subdirectory(Takeoff)
px4_add_module(  MODULE modules__mc_pos_control  MAIN mc_pos_control  COMPILE_FLAGS  SRCS    MulticopterPositionControl.cpp    MulticopterPositionControl.hpp  DEPENDS    PositionControl    Takeoff    controllib    geo    SlewRate  )


自定义的模块不需要 子文件夹 PositionControl 和 Takeoff 所以前两行可以删了

MODULE 模块的名字改为 modules__jone_demo

MAIN后面的改为 jone_demo

SRCS对应的文件名称进行修改

DEPENDS中 PostionControl 和Takeoff 没有对应的子文件,所以去掉,其它的可以保留

px4_add_module(  MODULE modules__jone_demo  MAIN jone_demo  COMPILE_FLAGS  SRCS    JoneDemo.cpp    JoneDemo.hpp  DEPENDS    controllib    geo    SlewRate  )


3.3 编辑Kconfig文件

下面来修改Kconfig文件,该文件是生成可执行文件的

照着 mc_pos_control 的 模板改就可以了

源文件:

menuconfig MODULES_MC_POS_CONTROL  bool"mc_pos_control"  default n  ---help---    Enable support for mc_pos_control
menuconfig USER_MC_POS_CONTROL  bool"mc_pos_control running as userspace module"  default y  depends on BOARD_PROTECTED && MODULES_MC_POS_CONTROL  ---help---    Put mc_pos_control in userspace memory

修改后文件:

menuconfig MODULES_JONE_DEMO  bool"jone_demo"  default n  ---help---    Enable support for jone_demo
menuconfig USER_JONE_DEMO  bool"jone_demo running as userspace module"  default y  depends on BOARD_PROTECTED && MODULES_JONE_DEMO  ---help---    Put jone_demo in userspace memory

3.4 编辑**_params.c文件

下面修改参数文件 jone_demo_params.c

这个例程不需要参数,只是打印个消息,所以空的就行。

3.5 编辑**.hpp文件

下面修改头文件:JoneDemo.hpp

复制 MulticopterPositionControl.hpp 文件的内容

删除掉包含的头文件

#include"PositionControl/PositionControl.hpp"#include"Takeoff/Takeoff.hpp"

将原文件所有的 类名称 MulticopterPositionControl 替换为 JoneDemo

内容 只保留 public 里面的函数,和 private里面的Run函数和parameters_update函数,还有一个变量

classJoneDemo :public ModuleBase<JoneDemo>, public control::SuperBlock,  public ModuleParams, public px4::ScheduledWorkItem{public:  JoneDemo();  ~JoneDemo() override;
  /** @see ModuleBase */  staticinttask_spawn(int argc, char *argv[]);
  /** @see ModuleBase */  staticintcustom_command(int argc, char *argv[]);
  /** @see ModuleBase */  staticintprint_usage(constchar *reason = nullptr);
  boolinit();
private:  voidRun()override;  voidparameters_update(bool force);  perf_counter_t _cycle_perf{perf_alloc(PC_ELAPSED, MODULE_NAME": cycle time")};};


构造函数和析构函数是每个类都有的

task_spawn、custom_command、print_usage函数每个模块也都有

3.6 编辑**.cpp文件

下面修改cpp文件:JoneDemo.cpp

同样复制 MulticopterPositionControl.cpp 文件的内容

原包含的头文件改为

#include"JoneDemo.hpp"

删除掉包含的头文件

#include"PositionControl/ControlMath.hpp"

将原文件所有的 类名称 MulticopterPositionControl 替换为 JoneDemo

构造函数将 _vehicle_attitude_setpoint_pub 、_vel_x_deriv、_vel_y_deriv、_vel_z_deriv 删掉,内容都删除

JoneDemo::JoneDemo(bool vtol) :  SuperBlock(nullptr, "MPC"),  ModuleParams(nullptr),  ScheduledWorkItem(MODULE_NAME, px4::wq_configurations::nav_and_controllers){  }

析构函数不用改

JoneDemo::~JoneDemo(){  perf_free(_cycle_perf);}

初始化函数:

boolJoneDemo::init(){  ScheduleNow();
  returntrue;}

参数更新函数parameters_update内容全部删除

设置飞行状态函数 set_vehicle_states 删除

Run函数,仅保留模板内容,并加入一个打印信息

voidJoneDemo::Run(){  if (should_exit()) {      exit_and_cleanup();    return;  }
  // reschedule backup  ScheduleDelayed(100_ms);
  parameters_update(false);
  perf_begin(_cycle_perf);    printf("hello jone\r\n");
  perf_end(_cycle_perf);}

generateFailsafeSetpoint函数删除

task_spawn 函数

intJoneDemo::task_spawn(int argc, char *argv[]){  JoneDemo *instance = new JoneDemo();
  if (instance) {    _object.store(instance);    _task_id = task_id_is_work_queue;
    if (instance->init()) {      return PX4_OK;    }
  } else {    PX4_ERR("alloc failed");  }
  delete instance;  _object.store(nullptr);  _task_id = -1;
  return PX4_ERROR;}

custom_command函数

intJoneDemo::custom_command(int argc, char *argv[]){  return print_usage("unknown command");}

print_usage 函数的描述修改,PRINT_MODULE_USAGE_NAME 里面的参数修改为jone_demo

intJoneDemo::print_usage(constchar *reason){  if (reason) {    PX4_WARN("%s\n", reason);  }
  PRINT_MODULE_DESCRIPTION(    R"DESCR_STR(### Description  jone demo)DESCR_STR");
  PRINT_MODULE_USAGE_NAME("jone_demo", "controller");  PRINT_MODULE_USAGE_COMMAND("start");  PRINT_MODULE_USAGE_DEFAULT_COMMANDS();
  return0;}

main函数修改

extern"C"__EXPORT intjone_demo_main(int argc, char *argv[]){  return JoneDemo::main(argc, argv);}

注意 jone_demo_main 这个在 jone_demo 要和 CMakeLists.txt 文件中的 MAIN jone_demo 保持一致,否则报错

4 编译

编译

make px4_sitl_default

如果报错的话,需要看具体原因进行修改

运行gazebo仿真的

make px4_sitl_default gazebo

第一个的编译要慢一些

运行起来发现:没有要打印的东西



因为模块还没有加到PX4的运行代码里面去

下面把模块加到PX4的运行代码里面去

make px4_sitl_default boardconfig

新建了一个模块,可以通过这个指令,把模块加进去

刚进入,终端变成这样



选择modules按回车

出来了很多的当前有的任务



选到我们新建的任务 jone_demo



可以看到它前面的方框没有星号,然后按下空格建,就加上星了,也就加入了编译



按下S,弹出下面内容,再回车进行保存,





最后按q,即可退出该指令

然后再编译一次,看报不报错

make px4_sitl_default

编译过了



5 测试

5.1 代码启动终端开启运行

运行

make px4_sitl_default gazebo

还是没有,需要在上面启动的终端中,先按回车,再输入指令

jone_demo start



成功输出

为什么一定要在终端中 进行start才能运行呢,因为在

print_usage函数中有这样一行代码

PRINT_MODULE_USAGE_COMMAND("start");

在终端中输入了start才运行打印

5.2 代码启动直接运行

如果希望程序启动就运行,不需要外部输入指令的话,那么则需要涉及到ROMFS文件夹了,它就是负责启动的

打开该文件夹下的rc.mc.apps文件



在最后加一句 jone_demo start,这样程序一启动就会运行

再启动一次就会发现,直接就输出了打印信息,不用在终端输入指令了

6 提交git

最后 git status 看下状态



上面两个箭头上修改的文件,第一个是rc.mc_apps 是为了自启动修改的

而第二个箭头default.px4board 文件则是在运行 make px4_sitl_default boardconfig指令的时候通过gui的界面自动修改的,可以打开看下



多了第25行的内容

通过下面指令将修改的内容加上

git add .

提交上去

git commit -m "Create Task and run"














点击“阅读原文”查看详情
您需要登录后才可以回帖 登录 | 加入联盟

本版积分规则

快速回复 返回顶部 返回列表