首次应用教程(你好,天空)
本主题介绍如何创建和运行第一个板载应用程序。它涵盖了在 PX4 上开发应用程序所需的所有基本概念和 API。
信息
为简化起见,本节省略了启动/停止功能和命令行参数等更高级的功能。这些在 应用程序/模块模板.
先决条件
您需要具备以下条件
- PX4 SITL 模拟器 或 a 兼容 PX4 的飞行控制器.
- PX4 开发工具链 的目标。
- 下载 PX4 源代码 来自 Github
源代码 PX4-Autopilot/src/examples/px4_simple_app 目录中包含本教程的完整版本,如果遇到问题,可以查看该版本。
- 重命名(或删除 px4_simple_app 目录。
最小化应用
在本节中,我们将创建一个 最小应用 只打印出 你好,天空
.这包括一个 C 文件和一个 cmake 定义(告诉工具链如何构建应用程序)。
创建新目录 PX4-Autopilot/src/examples/px4_simple_app.
在该目录下创建一个新的 C 文件,文件名为 px4_simple_app.c:
将默认页眉复制到页面顶部。这应该出现在所有贡献文件中!
c/**************************************************************************** * * 版权 (c) 2012-2022 PX4 开发团队。保留所有权利。 * * 以源代码和二进制形式再分发和使用,无论有无 * 允许修改,但必须符合以下条件 * 符合要求: * * 1.重新分发源代码必须保留上述版权。 * 通知、本条件清单和以下免责声明。 * 2.以二进制形式再分发时,必须复制上述版权声明。 * 本通知、本条件清单和以下免责声明均适用于本网站。 * 随附的文件和/或其他材料 * 分配。 * 3. PX4 这一名称及其撰稿人的姓名均不得被使用。 * 用于为本软件衍生产品背书或促销 * 未经特定的事先书面许可。 * * 本软件由版权所有者和贡献者提供 * 任何明示或暗示的保证,包括但不限于 * 仅限于对适销性和适用性的默示保证 * 不承担任何特定用途的责任。在任何情况下 * 版权所有者或撰稿人不对任何直接、间接、偶然或意外事件负责、 * 附带的、特殊的、惩戒性的或间接的损害赔偿(包括: * 但不限于采购替代货物或服务;损失 * 使用、数据或利润;或业务中断),无论其原因如何 * 以及任何责任理论,无论是合同、严格的 * 责任,或侵权行为(包括过失或其他)中产生的 * 使用本软件的任何后果,即使已被告知 * 这种损害的可能性。 * ****************************************************************************/
在默认头下面复制以下代码。所有贡献文件都应包含此代码!
c/** * @ 文件 px4_simple_app.c * PX4 自动驾驶仪的最小应用示例 * * @ 作者 用户示例 <[email protected]>; */ #include <px4_platform_common/log.h>; __EXPORT int px4_simple_app_main(int 参数, 烧焦 *参数[]); int px4_simple_app_main(int 参数, 烧焦 *参数[]) { PX4_INFO(你好,天空!";); 返回 好的; }
TIP
主函数必须命名为
<module_name>_main
并从模块中导出,如图所示。
创建并打开一个新的 cmake 定义文件命名为 CMakeLists.txt.复制以下文本:
cmake############################################################################ # # 版权 (c) 2015 PX4 开发团队。保留所有权利。 # # 以源代码和二进制形式再分发和使用,无论有无 #修改,但必须符合以下条件 # 符合要求: # # 1.重新分发源代码必须保留上述版权 # 通知、本条件清单和以下免责声明。 # 2.二进制形式的再分发必须复制上述版权信息。 # 通知、本条件清单和以下免责声明 #随附的文件和/或其他材料 # 分发。 # 3.PX4 名称及其贡献者的姓名均不得 # 用于支持或推广由本软件衍生的产品 # 未经事先书面许可。 # # 本软件由版权所有者和贡献者提供 # "AS" 以及任何明示或暗示的保证,包括但不限于 # 仅限于对适销性和适用性的默示保证 # 对特定用途的免责声明。在任何情况下 # 版权所有者或贡献者对任何直接、间接、间接、间接、间接、间接、间接、间接、间接 #附带的、特殊的、惩戒性的或后果性的损害赔偿(包括 # 包括但不限于采购替代货物或服务;损失 # 使用、数据或利润;或业务中断),无论其原因如何 # 在任何责任理论上,无论是合同、严格的 # 或侵权行为(包括过失或其他)中产生的赔偿责任。 # 使用本软件的任何后果,即使已被告知 # 这种损害的可能性。 # ############################################################################ px4_add_module( 模块 examples__px4_simple_app MAIN px4_simple_app stack_main 2000 SRCS px4_simple_app.c 取决于 )
px4_add_module()
方法根据模块描述构建静态库。-
单元
块是模块的固件唯一名称(按照惯例,模块名称的前缀是父目录,直到来源
). -
MAIN
块列出了模块的入口点,它将命令注册到 NuttX 中,以便从 PX4 shell 或 SITL 控制台调用。
TIP
px4_add_module()
格式在 PX4-Autopilot/cmake/px4_add_module.cmake.信息
如果您指定
动态
作为px4_add_module
, a 共享库 而不是 POSIX 平台上的静态库(无需重新编译 PX4 即可加载这些库,并以二进制文件而非源代码的形式与他人共享)。您的应用程序不会成为内建命令,而是会在一个名为examples__px4_simple_app.px4mod
.然后,您可以在运行时使用动态
指挥:dyn ./examples__px4_simple_app.px4mod
-
创建并打开一个新的 Kconfig 定义文件命名为 Kconfig 并定义命名符号(见 Kconfig 命名约定).复制下面的文字:
menuconfig EXAMPLES_PX4_SIMPLE_APP bool "px4_simple_app"; 默认值 n ---帮助 启用对 px4_simple_app 的支持
构建应用程序/固件
应用程序现已完成。要运行它,首先需要确保它是作为 PX4 的一部分构建的。应用程序会被添加到相应板级的构建/固件中。 px4board 文件:
- PX4 SITL(模拟器): PX4-Autopilot/boards/px4/sitl/default.px4board
- Pixhawk v1/2: PX4-Autopilot/boards/px4/fmu-v2/default.px4board
- Pixracer (px4/fmu-v4): PX4-Autopilot/boards/px4/fmu-v4/default.px4board
- px4board 其他板的文件可在 PX4-Autopilot/boards/
要将应用程序编译到固件中,请添加相应的 Kconfig 密钥 CONFIG_EXAMPLES_PX4_SIMPLE_APP=y
在 px4board 文件或运行 boardconfig make px4_fmu-v4_default boardconfig
:
例子
[x] PX4 简单应用程序 ----
信息
由于默认情况下固件中包含示例,因此大多数文件中都会有这一行。
使用电路板专用命令构建示例:
- jMAVSim 模拟器:
make px4_sitl_default jmavsim
- Pixhawk v1/2:
make px4_fmu-v2_default
或仅使 px4_fmu-v2
) - Pixhawk v3:
make px4_fmu-v4_default
- 其他棋盘 构建代码
测试应用程序(硬件)
将固件上传到电路板
启用上传程序,然后重置电路板:
- Pixhawk v1/2:
使 px4_fmu-v2_default 上传
- Pixhawk v3:
使 px4_fmu-v4_default 上传
在重置电路板之前和最后,它应该会打印一些编译信息:
已装载 固件 对于 X,X、 等待 对于 的 引导程序...
重置电路板并上传后,就可以打印了:
擦除 : [====================] 100.0%
计划 [====================] 100.0%
验证 : [====================] 100.0%
重新启动。
[100%] 建立目标上传
连接控制台
现在连接到 系统控制台 通过串口或 USB。点击 输入 会弹出 shell 提示符:
nsh>;
输入 ''help'',然后按 ENTER 键
nsh>; 帮助
帮助 使用: 帮助 [-v] [<;cmd>;]
[ df kill mkfifo ps sleep
? echo losetup mkrd pwd test
cat exec ls mh rm umount
cd exit mb mount rmdir unset
cp free mkdir mv set usleep
dd help mkfatfs mw sh xd
内置应用程序
重新启动
敷衍
顶级
..
px4_simple_app
..
血清
冰蚕
请注意 px4_simple_app
现在是可用命令的一部分。键入 px4_simple_app
和 ENTER 键:
nsh>; px4_simple_app
您好 天空
现在,应用程序已在系统中正确注册,并可进行扩展,以实际执行有用的任务。
测试应用程序(SITL)
如果您使用的是 SITL PX4 控制台 会自动启动(见 构建代码> 首次构建(使用 jMAVSim 模拟器)).与 nsh 控制台 (见上一节),您可以键入 帮助
查看内置应用程序列表。
进入 px4_simple_app
来运行最小应用程序。
pxh>; px4_simple_app
信息 [px4_simple_app]你好,天空!
现在,该应用程序可以扩展到实际执行有用的任务。
订阅传感器数据
要做一些有用的事情,应用程序需要订阅输入并发布输出(如电机或伺服命令)。
TIP
PX4 硬件抽象的优势在这里得到了体现!无需以任何方式与传感器驱动程序交互,也无需在电路板或传感器更新时更新应用程序。
应用程序之间的单独信息通道称为 主题.对于本教程,我们感兴趣的是 传感器组合 主题,其中包含整个系统的同步传感器数据。
订阅主题非常简单:
#include <uORB/topics/sensor_combined.h>;
..
int 传感器子控制器 = 订阅(ORB_ID(sensor_combined));
传感器子控制器
是一个主题句柄,可用于非常高效地执行新数据阻塞等待。当前线程进入休眠状态,一旦有新数据,调度程序就会自动唤醒,在等待过程中不会消耗任何 CPU 周期。为此,我们使用 轮询() POSIX 系统调用。
添加 轮询()
的订阅看起来像 (伪代码,下面是完整的实现过程):
#include <poll.h>;
#include <uORB/topics/sensor_combined.h>;
..
int 传感器子控制器 = 订阅(ORB_ID(sensor_combined));
/* 使用这种技术可以等待多个主题,这里只使用一个 */
px4_pollfd_struct_t fds[] = {
{ .fd = sensor_sub_fd、.events = 波林 }、
};
虽然 (真) {
/* 等待传感器更新 1 个文件描述符 1000 毫秒(1 秒) */
int poll_ret = px4_poll(fds、 1, 1000);
..
如果 (fds[0].revents 及样品; 波林){
/* 获取第一个文件描述符的数据 */
结构 综合传感器 生的;
/* 将传感器原始数据复制到本地缓冲区 */
或复制(ORB_ID(sensor_combined), sensor_sub_fd、 及样品;raw);
PX4_INFO(加速计:\t%8.4f\t%8.4f\t%8.4f";,
(双人) raw.accelerometer_m_s2[0],
(双人) raw.accelerometer_m_s2[1],
(双人) raw.accelerometer_m_s2[2]);
}
}
再次编译应用程序,输入
生产
测试 uORB 订阅
最后一步是在 nsh shell 中键入以下内容,将应用程序作为后台进程/任务启动:
px4_simple_app 及样品;
应用程序将在控制台中显示 5 个传感器值,然后退出:
[px4_simple_app] 加速计: 0.0483 0.0821 0.0332
[px4_simple_app] 加速计: 0.0486 0.0820 0.0336
[px4_simple_app] 加速计: 0.0487 0.0819 0.0327
[px4_simple_app] 加速计: 0.0482 0.0818 0.0323
[px4_simple_app] 加速计: 0.0482 0.0827 0.0331
[px4_simple_app] 加速计: 0.0489 0.0804 0.0328
TIP
全面应用模块模板 可用于编写可由命令行控制的后台进程。
出版数据
要使用计算出的输出结果,下一步是 发布 结果。下面我们将展示如何发布态度主题。
信息
我们选择了 态度
因为我们知道 多点连接 应用程序会将其转发到地面控制站--提供了一种查看结果的简便方法。
界面非常简单:初始化 结构
要发布的主题,并对该主题进行宣传:
#include <uORB/topics/vehicle_attitude.h>;
..
/* 宣传态度主题 */
结构 载具姿态
memset(及样品;att, 0, 尺寸(att));
orb_advert_t att_pub_fd = 广告(ORB_ID(载具姿态)、 及样品;att);
在主循环中,只要信息准备就绪,就发布信息:
出版(ORB_ID(vehicle_attitude), att_pub_fd、 及样品;att);
完整示例代码
完整示例代码 现在是
/****************************************************************************
*
* 版权 (c) 2012-2019 PX4 开发团队。保留所有权利。
*
* 以源代码和二进制形式再分发和使用,无论有无
* 允许修改,但必须符合以下条件
* 符合要求:
*
* 1.重新分发源代码必须保留上述版权。
* 通知、本条件清单和以下免责声明。
* 2.以二进制形式再分发时,必须复制上述版权声明。
* 本通知、本条件清单和以下免责声明均适用于本网站。
* 随附的文件和/或其他材料
* 分配。
* 3. PX4 这一名称及其撰稿人的姓名均不得被使用。
* 用于为本软件衍生产品背书或促销
* 未经特定的事先书面许可。
*
* 本软件由版权所有者和贡献者提供
* 任何明示或暗示的保证,包括但不限于
* 仅限于对适销性和适用性的默示保证
* 不承担任何特定用途的责任。在任何情况下
* 版权所有者或撰稿人不对任何直接、间接、偶然或意外事件负责、
* 附带的、特殊的、惩戒性的或间接的损害赔偿(包括:
* 但不限于采购替代货物或服务;损失
* 使用、数据或利润;或业务中断),无论其原因如何
* 以及任何责任理论,无论是合同、严格的
* 责任,或侵权行为(包括过失或其他)中产生的
* 使用本软件的任何后果,即使已被告知
* 这种损害的可能性。
*
****************************************************************************/
/**
* @ 文件 px4_simple_app.c
* PX4 自动驾驶仪的最小应用示例
*
* @ 作者 用户示例 <[email protected]>;
*/
#include <px4_platform_common/px4_config.h>;
#include <px4_platform_common/tasks.h>;
#include <px4_platform_common/posix.h>;
#include <unistd.h>;
#include <stdio.h>;
#include <poll.h>;
#include <string.h>;
#include <math.h>;
#include <uORB/uORB.h>;
#include <uORB/topics/sensor_combined.h>;
#include <uORB/topics/vehicle_attitude.h>;
__EXPORT int px4_simple_app_main(int 参数, 烧焦 *参数[]);
int px4_simple_app_main(int 参数, 烧焦 *参数[])
{
PX4_INFO(你好,天空!";);
/* 订阅传感器组合主题 */
int 传感器子控制器 = 订阅(ORB_ID(sensor_combined));
/* 将更新速率限制在 5 Hz */
orb_set_interval(sensor_sub_fd、 200);
/* 宣传态度主题 */
结构 载具姿态
memset(及样品;att、 0, 尺寸(att));
orb_advert_t att_pub = 广告(ORB_ID(载具姿态)、 及样品;att);
/* 使用这种技术可以等待多个主题,这里只使用一个 */
px4_pollfd_struct_t fds[] = {
{ .fd = sensor_sub_fd、.events = 波林 }、
/* 这里可能有更多的文件描述符,其形式类似于
* { .fd = other_sub_fd,.events = POLLIN }、
*/
};
int 错误计数器 = 0;
对于 (int i = 0; i <; 5; i++) {
/* 等待传感器更新 1 个文件描述符 1000 毫秒(1 秒) */
int poll_ret = px4_poll(fds、 1, 1000);
/* 处理投票结果 */
如果 (poll_ret == 0) {
/* 这意味着没有一个提供商向我们提供数据 */
PX4_ERR("秒内无数据";);
} 不然 如果 (poll_ret <; 0) {
/* 这太糟糕了--应该是紧急情况 */
如果 (错误计数器 <; 10 || 错误计数器 % 50 == 0) {
/* 使用计数器防止泛洪(并减慢我们的速度) */
PX4_ERR("来自 poll() 的错误返回值: %d";,poll_ret);
}
错误计数器++;
} 不然 {
如果 (fds[0].revents 及样品; 波林){
/* 获取第一个文件描述符的数据 */
结构 传感器综合原始数据;
/* 将传感器原始数据复制到本地缓冲区 */
或复制(ORB_ID(sensor_combined), sensor_sub_fd、 及样品;raw);
PX4_INFO(加速计:\t%8.4f\t%8.4f\t%8.4f";,
(双人) raw.accelerometer_m_s2[0],
(双人) raw.accelerometer_m_s2[1],
(双人) raw.accelerometer_m_s2[2]);
/* 设置 att 并为其他应用程序发布此信息
以下内容没有任何意义,只是一个例子
*/
att.q[0] = raw.accelerometer_m_s2[0];
att.q[1] = raw.accelerometer_m_s2[1];
att.q[2] = raw.accelerometer_m_s2[2];
出版(ORB_ID(vehicle_attitude), att_pub、 及样品;att);
}
/* 这里可能有更多的文件描述符,其形式类似于
* if (fds[1..n].revents & POLLIN) {}
*/
}
}
PX4_INFO(退出;);
返回 0;
}
运行完整示例
最后运行应用程序:
px4_simple_app
如果您开始 QGroundControl您可以在实时图 (分析 > MAVLink 检查器).
总结
本教程涵盖了开发基本 PX4 自动驾驶应用程序所需的全部内容。请记住,uORB 信息/主题的完整列表是 可在此查阅 并对标头进行详细记录和参考。
更多信息和故障排除/常见陷阱,请点击此处: uORB.
下一页将提供一个模板,用于编写具有启动和停止功能的完整应用程序。