PX4模块设计之十一:Built-In框架

2023-05-16

PX4模块设计之十一:Built-In框架

  • 1. Nuttx Built-In框架
  • 2. PX4 Built-In框架
    • 2.1 NSH Built-In关联文件
    • 2.2 NSH Built-In关联文件生成
    • 2.3 NSH Built-In注册文件生成
    • 2.4 NSH应用.pdat/.bdat生成途径
    • 2.5 PX4应用.pdat/.bdat生成途径
  • 3. Nuttx Built-In代码实现
    • 3.1 builtin_isavail
    • 3.2 builtin_for_index
    • 3.3 exec_builtin
  • 4. Nuttx Built-In命令触发
    • 4.1 启动脚本触发
    • 4.2 命令行session
  • 5. 总结
  • 6. 参考资料
  • 7. 补充说明:Nuttx Build
    • 7.1 Flat Build
    • 7.2 PROTECTED/KERNEL build

前面介绍了PX4模块设计之十:PX4启动过程,在应用上,最为重要的阶段就是飞控应用初始化,这个过程是通过nsh启动脚本实现的。也许对于linux bash熟悉的同学会马上说“这不就是进程按照顺序启动嘛”。当然这个说法是不错的,那么现在的问题是Nuttx没有进程的概念。

注:当然在px4模拟程序里面确实大家看到了大量的二进制bin文件,那是因为在Linux系统上模拟。那么可以想想也许他是通过函数调用的方式进行任务的启动,如果采用这种方式就必须知道这些应用的函数入口。

网上搜了下资料,关于这块的内容其实并没有太多的介绍,也许太简单,也许应用的角度不需要关注。但是从理解和逻辑的角度我们更应该知道整个应用是如何启动起来的,这属于框架设计的一部分。

接下来我们就来看看这个启动是如何依赖脚本实现的。

1. Nuttx Built-In框架

NuttX是一个实时操作系统,主要强调POSIX和ANSI标准的兼容性,同时占用资源小。适合于8位或者更高的MCU环境。但是该系统与Linux不同步区分内核态和用户态,整个系统在一个地址空间。

这里先给出Nuttx NSH Build-In Framework,这个使我们理解的基础,虽然部分内容和实际代码有所差异,但是可以看出大概的思路。

通过builtin_list.c代码,可以看出有builtin_list被添加到了g_builtins数组。

41 #include "builtin_proto.h"
42
43 const struct builtin_s g_builtins[] =
44 {
45 # include "builtin_list.h"
46   { NULL, 0, 0, 0 }
47 };
48 
49 const int g_builtin_count = sizeof(g_builtins) / sizeof(g_builtins[0]);

到这里,我们可以比较清楚的理解Nuttx下是如何将引用和NSH联系起来的。接下去我们要重点关注当前PX4代码是如何将PX4下的应用和NSH联系起来的。

2. PX4 Built-In框架

PX4 Built-In框架框架涉及两部分:

  • Nuttx Built-In应用
  • PX4 Built-In应用

注:这里使用holybro_kakutef7作为例子。

2.1 NSH Built-In关联文件

两个关联文件(函数定义和符号表数组),其中大部分是PX4的应用:

注:NSH应用是sercon_main、serdis_main、nsh_main、sh_main。

platforms\nuttx\NuttX\apps\builtin\builtin_proto.h

int sercon_main(int argc, char *argv[]);
int atxxxx_main(int argc, char *argv[]);
int bmp280_main(int argc, char *argv[]);
int board_adc_main(int argc, char *argv[]);
int dshot_main(int argc, char *argv[]);
int frsky_telemetry_main(int argc, char *argv[]);
int icm20689_main(int argc, char *argv[]);
int mpu6000_main(int argc, char *argv[]);
int pwm_out_main(int argc, char *argv[]);
int rc_input_main(int argc, char *argv[]);
int manual_control_main(int argc, char *argv[]);
int attitude_estimator_q_main(int argc, char *argv[]);
int battery_status_main(int argc, char *argv[]);
int commander_main(int argc, char *argv[]);
int control_allocator_main(int argc, char *argv[]);
int dataman_main(int argc, char *argv[]);
int flight_mode_manager_main(int argc, char *argv[]);
int land_detector_main(int argc, char *argv[]);
int logger_main(int argc, char *argv[]);
int mavlink_main(int argc, char *argv[]);
int mc_att_control_main(int argc, char *argv[]);
int mc_pos_control_main(int argc, char *argv[]);
int mc_rate_control_main(int argc, char *argv[]);
int navigator_main(int argc, char *argv[]);
int rc_update_main(int argc, char *argv[]);
int sensors_main(int argc, char *argv[]);
int mixer_main(int argc, char *argv[]);
int param_main(int argc, char *argv[]);
int pwm_main(int argc, char *argv[]);

int nsh_main(int argc, char *argv[]);
int sh_main(int argc, char *argv[]);
int serdis_main(int argc, char *argv[]);

platforms\nuttx\NuttX\apps\builtin\builtin_list.h

{ "sh", 100, 2048, sh_main },
{ "sercon", SCHED_PRIORITY_DEFAULT, 2048, sercon_main },
{ "atxxxx", SCHED_PRIORITY_DEFAULT, 2048, atxxxx_main },
{ "bmp280", SCHED_PRIORITY_DEFAULT, 2048, bmp280_main },
{ "board_adc", SCHED_PRIORITY_DEFAULT, 2048, board_adc_main },
{ "dshot", SCHED_PRIORITY_DEFAULT, 2048, dshot_main },
{ "frsky_telemetry", SCHED_PRIORITY_DEFAULT, 2048, frsky_telemetry_main },
{ "icm20689", SCHED_PRIORITY_DEFAULT, 2048, icm20689_main },
{ "mpu6000", SCHED_PRIORITY_DEFAULT, 2048, mpu6000_main },
{ "pwm_out", SCHED_PRIORITY_DEFAULT, 2048, pwm_out_main },
{ "rc_input", SCHED_PRIORITY_DEFAULT, 2048, rc_input_main },
{ "manual_control", SCHED_PRIORITY_DEFAULT, 2048, manual_control_main },
{ "attitude_estimator_q", SCHED_PRIORITY_DEFAULT, 2048, attitude_estimator_q_main },
{ "battery_status", SCHED_PRIORITY_DEFAULT, 2048, battery_status_main },
{ "commander", SCHED_PRIORITY_DEFAULT, 2048, commander_main },
{ "control_allocator", SCHED_PRIORITY_DEFAULT, 3000, control_allocator_main },
{ "dataman", SCHED_PRIORITY_DEFAULT, 2048, dataman_main },
{ "flight_mode_manager", SCHED_PRIORITY_DEFAULT, 2048, flight_mode_manager_main },
{ "land_detector", SCHED_PRIORITY_DEFAULT, 2048, land_detector_main },
{ "logger", SCHED_PRIORITY_MAX-30, 2048, logger_main },
{ "mavlink", SCHED_PRIORITY_DEFAULT, 2048, mavlink_main },
{ "mc_att_control", SCHED_PRIORITY_DEFAULT, 2048, mc_att_control_main },
{ "mc_pos_control", SCHED_PRIORITY_DEFAULT, 2048, mc_pos_control_main },
{ "mc_rate_control", SCHED_PRIORITY_DEFAULT, 2048, mc_rate_control_main },
{ "navigator", SCHED_PRIORITY_DEFAULT, 2048, navigator_main },
{ "rc_update", SCHED_PRIORITY_DEFAULT, 2048, rc_update_main },
{ "sensors", SCHED_PRIORITY_DEFAULT, 2048, sensors_main },
{ "mixer", SCHED_PRIORITY_DEFAULT, 4096, mixer_main },
{ "param", SCHED_PRIORITY_DEFAULT, 2048, param_main },
{ "pwm", SCHED_PRIORITY_DEFAULT, 2048, pwm_main },


{ "nsh", 100, 2048, nsh_main },
{ "serdis", SCHED_PRIORITY_DEFAULT, 2048, serdis_main },

2.2 NSH Built-In关联文件生成

关联文件是通过Makefile脚本通过将.pdat/.bdat文件中的内容合并生成的。

27 # Registry entry lists
28 
29 PDATLIST = $(strip $(call RWILDCARD, registry, *.pdat))
30 BDATLIST = $(strip $(call RWILDCARD, registry, *.bdat))
31 
32 builtin_list.c: builtin_list.h builtin_proto.h
33 
34 registry$(DELIM).updated:
35 	$(Q) touch registry$(DELIM).updated
36 
37 builtin_list.h: registry$(DELIM).updated
38 ifeq ($(BDATLIST),)
39 	$(call DELFILE, builtin_list.h)
40 	$(Q) touch builtin_list.h
41 else
42 	$(call CATFILE, builtin_list.h, $(BDATLIST))
43 endif
44 
45 builtin_proto.h: registry$(DELIM).updated
46 ifeq ($(PDATLIST),)
47 	$(call DELFILE, builtin_proto.h)
48 	$(Q) touch builtin_proto.h
49 else
50 	$(call CATFILE, builtin_proto.h, $(PDATLIST))
51 endif

2.3 NSH Built-In注册文件生成

通过分析,可以看到找到各个文件的主要出处如下:

  • platforms\nuttx\NuttX\CMakeLists.txt ==》 px4 px4_kernel
  • platforms\nuttx\NuttX\apps\system\nsh ==》 nsh sh
  • platforms\nuttx\NuttX\apps\system\cdcacm ==》sercon serdis

注:px4.bdat/.pdat是px4的应用,其他是Nuttx的应用。

./platforms/nuttx/NuttX/apps/builtin/registry/
├── px4.bdat
├── px4.pdat
├── nsh.bdat
├── nsh.pdat
├── sercon.bdat
├── sercon.pdat
├── serdis.bdat
├── serdis.pdat
├── sh.bdat
└── sh.pdat

注:Google/Baidu并没有给出什么信息。PX4论坛上也咨询了下,不过没有什么反馈。估计大家的重点是在应用。How .bdat/.pdat files generated in NuttX/apps/builtin/registry/? 。

2.4 NSH应用.pdat/.bdat生成途径

NSH应用的Makefile文件会提前引用

include $(APPDIR)/Make.defs

该文件platforms\nuttx\NuttX\apps\Make.defs将每个应用的入口函数通过符号重命名脚本define.sh进行了整理,输出到注册文件中。

86 define REGISTER
87 	$(Q) echo Register: $1
88 	$(Q) echo { \"$1\", $2, $3, $4 }, > "$(BUILTIN_REGISTRY)$(DELIM)$1.bdat"
89 	$(Q) if [ ! -z $4 ]; then \
90 	        echo "int $4(int argc, char *argv[]);" > "$(BUILTIN_REGISTRY)$(DELIM)$1.pdat"; \
91 	     fi;
92 	$(Q) touch "$(BUILTIN_REGISTRY)$(DELIM).updated"
93 endef

2.5 PX4应用.pdat/.bdat生成途径

PX4应用的符号通过CMakeList下的px4_add_module添加到全局变量,并在通过.in文件输出到.bdat/.pdat注册文件

111 	configure_file(${CMAKE_CURRENT_SOURCE_DIR}/px4_kernel.bdat.in ${CMAKE_CURRENT_BINARY_DIR}/px4_kernel.bdat)
112 	configure_file(${CMAKE_CURRENT_SOURCE_DIR}/px4_kernel.pdat.in ${CMAKE_CURRENT_BINARY_DIR}/px4_kernel.pdat)
...

117 		COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_BINARY_DIR}/px4_kernel.bdat kernel_builtin_list.h
118 		COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_BINARY_DIR}/px4_kernel.pdat kernel_builtin_proto.h
...

125 configure_file(${CMAKE_CURRENT_SOURCE_DIR}/px4.bdat.in ${CMAKE_CURRENT_BINARY_DIR}/px4.bdat)
126 configure_file(${CMAKE_CURRENT_SOURCE_DIR}/px4.pdat.in ${CMAKE_CURRENT_BINARY_DIR}/px4.pdat)
...

138 	COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_BINARY_DIR}/px4.bdat ${APPS_DIR}/builtin/registry/px4.bdat
139 	COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_BINARY_DIR}/px4.pdat ${APPS_DIR}/builtin/registry/px4.pdat

3. Nuttx Built-In代码实现

执行脚本最关键的Built-In函数是下面两个:

  • builtin_isavail
  • builtin_for_index
  • exec_builtin
nsh_script
 └──> nsh_parse
     └──> nsh_parse_command
         └──> nsh_execute
             └──> nsh_builtin
                 └──> exec_builtin
                     ├──> builtin_isavail
                     ├──> builtin_for_index
                     └──> task_spawn(builtin->name, builtin->main, &file_actions,
                                           &attr, (argv) ? &argv[1] : (FAR char * const *)NULL,
                                           (FAR char * const *)NULL);

3.1 builtin_isavail

lib_builtin_isavail.c 实现了builtin_isavail函数,确认命令是否未有效Built-In命令。

56 int builtin_isavail(FAR const char *appname)
57 {
58   FAR const char *name;
59   int i;
60
61   for (i = 0; (name = builtin_getname(i)) != NULL; i++)
62    {
63       if (strcmp(name, appname) == 0)
64         {
65           return i;
66         }
67     }
68 
69   return -ENOENT;
70 }

3.2 builtin_for_index

lib_builtin_forindex.c实现了builtin_for_index函数,返回该命令相关执行参数(优先级,堆栈大小,函数入口符号等)。

52 FAR const struct builtin_s *builtin_for_index(int index)
53 {
54   if (index < g_builtin_count)
55     {
56       return &g_builtins[index];
57     }
58
59   return NULL;
60 }

3.3 exec_builtin

exec_builtin.c,启动一个任务,如果子任务不退出,那么就会一直运行。

exec_builtin
 ├──> builtin_isavail
 ├──> builtin_for_index
 ├──> posix_spawnattr_init
 ├──> posix_spawn_file_actions_init
 ├──> posix_spawnattr_setschedparam
 ├──> task_spawnattr_setstacksize
 ├──> <CONFIG_RR_INTERVAL > 0>
 │   ├──> posix_spawnattr_setschedpolicy
 │   └──> posix_spawnattr_setflags
 ├──> <!(CONFIG_RR_INTERVAL > 0)>
 │   └──> posix_spawnattr_setflags
 ├──> <redirfile>
 │   └──> posix_spawn_file_actions_addopen
 ├──> posix_spawn
 ├──> <ret != 0 && builtin->main != NULL>
 │   └──> task_spawn
 ├──> posix_spawn_file_actions_destroy
 └──> posix_spawnattr_destroy

4. Nuttx Built-In命令触发

4.1 启动脚本触发

系统初始化会执行init任务,该任务最后将会执行脚本/etc/init.d/rcS(详见PX4模块设计之十:PX4启动过程)。

4.2 命令行session

通过USB或者字符设备的命令行,通过命令解析进行执行。

nsh_consolemain (USB console/Normal character device)
 └──> nsh_session
     └──> nsh_parse
         └──> nsh_parse_command
             └──> nsh_loop
                 └──> nsh_argument
                     └──> nsh_argexpand
                         └──> nsh_cmdparm
                             └──> nsh_parse_cmdparm
                                 └──> nsh_execute
                                     └──> nsh_builtin
                                         └──> exec_builtin

5. 总结

  1. Nuttx官网的Built-In介绍的REGISTER和实际PX4工程的主要差异是PX4采用的.bdat/.pdat中间文件的方式(详见:2.4 NSH应用.pdat/.bdat生成途径)
    Nuttx官网REGISTER

  2. PX4使用了大量的submodule,相关整合方面的介绍比较欠缺,尤其是工程面的。(对于C背景的研发人员可能会有一点的不习惯。通常C背景的会将每行代码都搞得一清二楚。不想现在大量使用组件方式,不太关注框架,更重视应用的快节奏。)

  3. 关于符号重命名脚本define.sh这里没有展开,感兴趣的朋友可以自己研究,其主要功能就是将main符号转换成另一个不重复的符号,比如:sh_main

-Dmain=shmain

6. 参考资料

【1】PX4开源软件框架简明简介
【2】PX4开源工程结构简明介绍
【3】Nuttx NSH Build-In Framework

7. 补充说明:Nuttx Build

从小系统的角度来说,可能ChibiOS比Nuttx会更加精简。ChibiOS没有用户态和内核态的概念,有点类似Nuttx Flat Build的设计。

7.1 Flat Build

通过API接口函数直接调用(无内核态概念)
Flat Build

7.2 PROTECTED/KERNEL build

通过SystemCall系统API接口调用(安全,但用户/内核态数据交互有数据Copy代价,额外的接口处理设计)

Protected Build

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

PX4模块设计之十一:Built-In框架 的相关文章

  • 下载并构建PX4

    根据官方的文档 xff0c PX4下载和构建的方式有两种 xff1a Linux系列的Console模式 xff08 当然也支持Windows下的MINGW32 xff09 和Windows模式 在Windows平台下 xff0c 我们习惯
  • 编译PX4固件

    PX4编译 文章目录 PX4编译疑难杂症bug1bug2catkin build isolated 官方脚本Step1Step2 安装常用依赖Step3 创建并运行脚本Step4 补全代码子模块Step5 验证仿真 官方offboard 例
  • 【2020-8-9】APM,PX4,GAZEBO,MAVLINK,MAVROS,ROS之间的关系以及科研设备选型

    0 概述 无人机自主飞行平台可以分为四个部分 xff1a 动力平台 xff0c 飞行控制器 xff0c 机载电脑和模拟平台 动力平台 xff1a 负责执行飞行任务 xff0c 包括螺旋桨 电机 机架等 xff0c 用于科研的一般都是F380
  • px4: v2的主板刷写v2的固件

    v2的主板刷写v2的固件 fengxuewei 64 fengxuewei Legion Y7000 2019 PG0 src Firmware changwei rc span class token function make span
  • Ubuntu18.04安装PX4踩坑、报错及解决方案整理

    笔者最近需要跑无人机巡检大坝的仿真 xff0c 于是在自己的Ubuntu2018 04中开始安装PX4 xff0c 问过不少之前已经装过PX4的师兄和同学 xff0c 都曾在PX4安装过程中踩过许多坑 xff0c 耗费了不少时间 xff0c
  • 关于PX4中的高度若干问题

    飞行的高度是如何测量的 xff1f 地面的高度和海平面的高度差别很大 xff0c 飞控又是如何有效判别进行降落的 xff1f 这是我脑子里的疑问 搜索的一圈发现很少有人讨论这方面的问题 xff0c 于是本次我就直接看一下源代码 xff0c
  • Ubuntu20.04+MAVROS+PX4+Gazebo保姆级安装教程

    Ubuntu20 04 43 MAVROS 43 PX4 43 Gazebo 安装PX4步骤安装MAVROS安装QGCPX4仿真 安装PX4步骤 从github上clone源码 span class token function git s
  • PX4无人机 - 键盘控制飞行代码

    PX4无人机 键盘控制飞行代码 仿真效果 实机效果 由于图片限制5M以内 xff0c 只能上传一小段了 xff0c 整段视频请点击链接 Pixhawk 6c 无人机 键盘控制无人机 Offboard模式 核心 xff1a 发布 mavros
  • 基于F4/F7/H7飞控硬件和px4飞控固件的廉价自主无人机系统(1)-飞控

    前言 穿越机F4 F7 H7飞控是一系列采用stm32系列F4xx和F7xx处理器的飞控的统称 xff0c 是目前穿越机爱好者非常喜欢使用的飞控硬件 xff0c 其价格也非常便宜180 xff5e 410 而px4则是一款常见的开源飞控固件
  • PX4代码学习系列博客(5)——在px4中添加自己的模块

    怎么在px4中添加自己的模块 在 px4固件目录结构和代码风格 这一节 xff0c 曾经说过NuttX是一个实时的嵌入式系统 xff0c 上面可以像windows那样运行程序 那既然是应用程序 xff0c 那我们应该也能写一些可以在Nutt
  • px4源码编译指南

    px4源码编译指南 强烈推荐大家去看官网的英文文档 xff0c 国内的博客杂七杂八 xff0c 官网的中文也很久没有更新 xff0c 这几天自己踩了很多坑 xff0c 写个教程希望能帮助到大家 xff08 本文选用平台是pixhawk1 1
  • PX4飞控之PWM输出控制

    PX4飞控之PWM输出控制 多旋翼电调如好盈XRotor xff0c DJI通用电调等都支持PWM信号来传输控制信号 常用的400Hz电调信号对应周期2500us xff0c 一般使用高电平时间1000us 2000us为有效信号区间 xf
  • PX4模块设计之一:SITL & HITL模拟框架

    PX4模块设计之一 xff1a SITL amp HITL模拟框架 1 模拟框架1 1 SITL模拟框架1 2 HITL模拟框架 2 模拟器类型3 MAVLink API4 总结 基于PX4开源软件框架简明简介的框架设计 xff0c 逐步分
  • PX4模块设计之六:PX4-Fast RTPS(DDS)简介

    64 TOC PX4模块设计之六 xff1a PX4 Fast RTPS DDS 简介 基于PX4开源软件框架简明简介的框架设计 xff0c 逐步分析内部模块功能设计 PX4 Fast RTPS DDS 具有实时发布 订阅uORB消息接口
  • PX4模块设计之十八:Logger模块

    PX4模块设计之十八 xff1a Logger模块 1 Logger模块简介2 模块入口函数2 1 主入口logger main2 2 自定义子命令Logger custom command2 3 日志主题uORB注册 3 重要实现函数3
  • PX4模块设计之三十四:ControlAllocator模块

    PX4模块设计之三十四 xff1a ControlAllocator模块 1 ControlAllocator模块简介2 模块入口函数2 1 主入口control allocator main2 2 自定义子命令custom command
  • PX4模块设计之四十六:dataman模块

    PX4模块设计之四十六 xff1a dataman模块 1 dataman模块简介2 模块入口函数dataman main3 dataman模块重要函数3 1 start3 2 stop3 3 status3 4 task main 4 A
  • px4_simple_example和uorb机制

    px4 simple app PX4 Autopilot src exampes px4 simple app xff0c 这个程序是用c语言调用orb API和poll机制订阅和发布通讯数据 xff0c 但是这个例子并不是既有接收又有发送
  • 四、无人机知识笔记(初级:基本运动原理)

    笔记来源于 沈阳无距科技 工业级无人机的中国名片 编程外星人 目录 一 多旋翼直升机 二 基本飞行姿态 三 多旋翼飞行原理 四 反扭力与偏航运动 五 螺旋桨 六 有刷电机和无刷电机 七 电调与PWM信号 八 动力电池 九 遥控器 十 机架设
  • 大神浅谈无人机飞控软件设计 系统性总结

    写在前面 深感自己对飞控软件 算法的知识点过于杂乱 很久没有进行系统的总结了 因此决定写几篇文章记录一些飞控开发过程的知识点 主要是针对一些软件 算法部分进行讨论 如内容有错误 欢迎指出 1 飞控软件的基本模块 无人机能够飞行主要是依靠传感

随机推荐

  • 四轴飞控DIY调试起飞简明步骤

    四轴飞控DIY调试起飞简明步骤 调试起飞简明步骤Step1 xff1a 飞控配置Step2 xff1a 试飞目标测试内容坐标系 Step3 xff1a 试飞方法1 升降 xff08 Throttle xff09 2 偏航 xff08 yaw
  • BetaFlight开源工程结构简明介绍

    BetaFlight开源工程结构简明介绍 Step1 获取开源代码开源代码版本克隆开源代码 Step2 了解工程情况支持模型类型 xff1a 多旋翼 amp 固定翼支持特性 amp 功能安装 amp 文档链接配置工具下载其他介绍 xff08
  • 四轴FPV无人机手动操作简明介绍

    四轴FPV无人机手动操作简明介绍 通常航拍机都是有自稳算法 43 GPS导航 43 辅助功能 避障 的支持 xff0c 从而保证飞手能够相对容易且稳定的操作模型飞机 xff0c 通常通过阅读说明书都能很快上手 xff0c 这里就不在赘述 本
  • BetaFlight开源代码框架简介

    BetaFlight开源代码框架简介 1 框架设计分析考量2 框架分析前提条件3 主程序框架4 调度框架5 模块方法6 典型任务 amp 模块6 1 典型任务6 2 典型模块6 3 传感模块 7 回顾 amp 分析8 分析模板 1 框架设计
  • 四轴飞控DIY集成FPV功能

    四轴飞控DIY集成FPV功能 1 功能需求2 概念介绍2 1 制式2 2 显示分辨率2 3 摄像头线数高于700线低于700线 3 需求分析4 组件选择5 接线组装5 1 摄像头接线5 2 图传接线 6 组装位置7 FPV功能调试7 1 摄
  • MFC拷贝文件及进度条显示

    参考 xff1a 封装CopyFileEx函数 xff0c 实现文件复制中的暂停 xff0c 控速 xff0c 获取进度 http blog csdn net career2011 article details 6844513 实例讲解C
  • BetaFlight模块设计之三十二:MSP协议模块分析

    BetaFlight模块设计之三十二 xff1a MSP协议模块分析 1 MSP协议模块1 1 MSP描述1 2 MSP版本优缺点1 3 MSP代码资源 2 MSP报文解析2 1 MSP收包状态机2 2 MSP报文格式 3 MSP报文处理3
  • BetaFlight模块设计之三十三:Pid模块分析

    BetaFlight模块设计之三十三 xff1a Pid模块分析 Pid模块1 Pid audio子模块2 Pid init子模块3 Pid算法子模块3 1 TPA模式3 2 飞行模式3 3 Launch模式3 4 AcroTrainer模
  • BetaFlight模块设计之三十四:OSD模块分析

    BetaFlight模块设计之三十四 xff1a OSD模块分析 1 OSD模块1 1 osd状态机子模块1 2 osd warnings检查子模块1 3 osd elements子模块 2 OSD设备 驱动及适配框架2 1 OSD设备2
  • ssh无法远程登陆问题汇总

    ssh无法远程登陆问题汇总 1 ssh服务是否已经启动1 1 sshd服务是否已经安装1 2 sshd是否已经启动 2 检查sshd配置3 检查路由情况4 检查hosts许可文件5 检查防火墙问题5 1 检查防火墙是否启动5 2 修改防火墙
  • traceroute命令结果分析

    traceroute命令结果分析 1 基本原理2 IP地址种类2 1 A类IP地址2 2 B类IP地址2 3 C类IP地址2 4 D类地址用于多点广播 Multicast 2 5 E类IP地址 3 测试3 1 第一次3 2 第二次 4 总结
  • bash脚本返回值应用

    bash脚本返回值应用 应该说bash脚本对于linux系统来说具有举足轻重的意义 这里不做展开 xff0c 也不做bash脚本介绍 更多的是做一个例子 xff0c 应用了bash脚本的以下特性 xff1a 输入参数函数定义调用可执行命令脚
  • 如何理解printf变参函数的实现

    如何理解printf变参函数的实现 1 printf函数变参的问题2 printf函数定义和解释2 1 printf函数定义2 2 Linux Man page解释 https man7 org linux man pages man3 s
  • BetaFlight模块设计之三十五:RSSI信号强度&链路稳定性分析

    BetaFlight模块设计之三十五 xff1a RSSI信号强度 amp 链路稳定性分析 1 RSSI信号强度1 1 RSSI Value1 2 RSSI dBm Value 2 链路稳定性3 RSSI amp LinkQuality来源
  • Linux的so组件设计框架及逻辑

    Linux的so组件设计框架及逻辑 1 组件关注点1 1 组件定义关注点1 2 组件业务关注点 2 so特性3 so组件设计逻辑4 so组件设计框架4 1 so组件范例4 2 so隐式调用范例4 3 so显式调用范例 5 so组件设计建议
  • PX4模块设计之八:Ubuntu 20.04搭建FlightGear模拟器

    PX4模块设计之八 xff1a Ubuntu 20 04搭建FlightGear模拟器 1 使用FlightGear的源由2 FlightGear模拟器简介3 Ubuntu 20 04搭建FlightGear步骤3 1 设置flightge
  • 封装CopyFileEx函数,实现文件复制中的暂停,控速,获取进度

    封装CopyFileEx函数 xff0c 实现文件复制中的暂停 xff0c 控速 xff0c 获取进度等 前段时间无意间想到如何控制文件复制过程的复制速度 xff0c 并且能实时获得复制进度 对于一个几兆甚至更小的文件 xff0c 调用AP
  • PX4模块设计之九:PX4飞行模式简介

    PX4模块设计之九 xff1a PX4飞行模式简介 关于模式的探讨1 需求角度1 1 多旋翼 MC multi copter 1 1 1 RC控制模式1 1 1 1 Position Mode1 1 1 2 Altitude Mode1 1
  • PX4模块设计之十:PX4启动过程

    PX4模块设计之十 xff1a PX4启动过程 1 硬件 飞控硬件上电2 硬件 飞控硬件初始化3 硬件 43 软件 飞控bootloader初始化4 硬件 43 软件 飞控系统初始化5 软件 飞控应用初始化6 配置 SD卡配置文件6 1 e
  • PX4模块设计之十一:Built-In框架

    PX4模块设计之十一 xff1a Built In框架 1 Nuttx Built In框架2 PX4 Built In框架2 1 NSH Built In关联文件2 2 NSH Built In关联文件生成2 3 NSH Built In