PX4 编译分析之Airframe文档生成
本文假设已经阅读了 PX4 的
1 Makefile分析
2 CMakeLists.txt分析
这里要分析的是 make airframe_metadata
的指令, 在 Makefile
文件中找到 airframe_metadata 的编译配置
# Documentation
# --------------------------------------------------------------------
.PHONY: parameters_metadata airframe_metadata module_documentation px4_metadata doxygen
parameters_metadata:
@$(MAKE) --no-print-directory px4_sitl_default metadata_parameters
airframe_metadata:
@$(MAKE) --no-print-directory px4_sitl_default metadata_airframes
可以发现它实际执行的是make px4_sitl_default metadata_airframes
, 第一选项是px4 的仿真配置选项这个会传给CMakeLists.txt
中的cmake-build
在build/px4_sitl_default
生成一些配置文件, 第二个和airframe_metadata
和metadata_airframe
相比只是前后两个单词互换了一下, 接下来依照我们在 Makefile分析 中的分析, 在Firmware 文件夹下的 CMakeLists.txt 中找到以下语句
add_custom_target(metadata_airframes
COMMAND ${CMAKE_COMMAND} -E make_directory ${PX4_BINARY_DIR}/docs
COMMAND ${PYTHON_EXECUTABLE} ${PX4_SOURCE_DIR}/Tools/px_process_airframes.py
-v -a ${PX4_SOURCE_DIR}/ROMFS/px4fmu_common/init.d
--markdown ${PX4_BINARY_DIR}/docs/airframes.md
COMMAND ${PYTHON_EXECUTABLE} ${PX4_SOURCE_DIR}/Tools/px_process_airframes.py
-v -a ${PX4_SOURCE_DIR}/ROMFS/px4fmu_common/init.d
--xml ${PX4_BINARY_DIR}/docs/airframes.xml
COMMENT "Generating full airframe metadata (markdown and xml)"
USES_TERMINAL
)
由以上定义语句我们发现, 编译metadata_airframes
的主要操作是(假设当前目录为源码 Firmware
文件夹):
- 在
build/px4_sitl_default
中建立输出文件夹docs
- 执行
python Tools/px_process_airframes.py -v -a ROMFS/px4fmu_common/init.d --markdown build/px4_sitl_default/docs/airframes.md
- 执行
python Tools/px_process_airframes.py -v -a ROMFS/px4fmu_common/init.d --xml build/px4_sitl_default/docs/airframes.xml
接下来, 继续分析一下 px_process_airframes.py
程序, 摘抄如下
# PX4 airframe config processor (main executable file)
#
# This tool scans the PX4 ROMFS code for declarations of airframes
#
# Currently supported formats are:
# * XML for the parametric UI generator
# * Markdown for the PX4 dev guide (https://github.com/PX4/Devguide)
#
#
from __future__ import print_function
import sys
import os
import argparse
from px4airframes import srcscanner, srcparser, xmlout, rcout, markdownout
def main():
# Parse command line arguments
parser = argparse.ArgumentParser(description="Process airframe documentation.")
parser.add_argument("-a", "--airframes-path",
default="../ROMFS/px4fmu_common",
metavar="PATH",
help="path to source files to scan for parameters")
parser.add_argument("-x", "--xml",
nargs='?',
const="airframes.xml",
metavar="FILENAME",
help="Create XML file"
" (default FILENAME: airframes.xml)")
parser.add_argument("-m", "--markdown",
nargs='?',
const="airframes.md",
metavar="FILENAME",
help="Create Markdown file"
" (default FILENAME: airframes.md)")
default_image_path = '../../assets/airframes/types'
parser.add_argument("-i", "--image-path",
default=default_image_path,
metavar="IMAGEPATH",
help="HTML image path for Markdown (containing the airframe svg files)"
" (default IMAGEPATH: "+default_image_path+")")
parser.add_argument("-s", "--start-script",
nargs='?',
const="rc.autostart",
metavar="FILENAME",
help="Create start script file")
parser.add_argument("-b", "--board",
nargs='?',
const="",
metavar="BOARD",
help="Board to create airframes xml for")
parser.add_argument('-v', '--verbose', action='store_true', help="verbose output")
args = parser.parse_args()
# Check for valid command
if not (args.xml) and not (args.start_script) and not args.markdown:
print("Error: You need to specify at least one output method!\n")
parser.print_usage()
sys.exit(1)
# Initialize source scanner and parser
scanner = srcscanner.SourceScanner()
parser = srcparser.SourceParser()
# Scan directories, and parse the files
if args.verbose: print("Scanning source path " + args.airframes_path)
if not scanner.ScanDir(args.airframes_path, parser):
sys.exit(1)
# We can't validate yet
# if not parser.Validate():
# sys.exit(1)
param_groups = parser.GetParamGroups()
# Output to XML file
if args.xml:
if args.verbose: print("Creating XML file " + args.xml)
out = xmlout.XMLOutput(param_groups, args.board)
out.Save(args.xml)
# Output to markdown file
if args.markdown:
if args.verbose: print("Creating markdown file " + args.markdown)
out = markdownout.MarkdownTablesOutput(param_groups, args.board, args.image_path)
out.Save(args.markdown)
if args.start_script:
if args.verbose: print("Creating start script " + args.start_script)
out = rcout.RCOutput(param_groups, args.board)
out.Save(args.start_script)
if (args.verbose): print("All done!")
if __name__ == "__main__":
main()
可以看到这里只是一个入口函数, 解析了一些用户选项, 然后通过srcscanner
和 srcparser
解析了 -a
选项给定的路径里的.hil
文件或者无扩展名的文件进行解析,这里摘录一个ROMFS/px4fmu_common/init.d/airframes/1001_rc_quad_x.hil
文件如下
#!/bin/sh
#
# @name HIL Quadcopter X
#
# @type Simulation
# @class Copter
#
# @maintainer Lorenz Meier <lorenz@px4.io>
#
sh /etc/init.d/rc.mc_defaults
set MIXER quad_x
set PWM_OUT 1234
if [ $AUTOCNF = yes ]
then
param set COM_DISARM_LAND 5
fi
param set SYS_HITL 1
这里基于上面 .hil
文件我们分析一下Tools/px4airframes/srcparser.py
中的 SourceParser类
的 parse
方法的执行步骤, 由于其文件比较长,这里只给出简要描述, 并不附上代码.
- 首先通过
.hil
文件名解析得到序号, 这里是1001
- 进行如下图流程图中的操作的描述(尚未全部完成)
主要过程就是把"url", "maintainer", "output", "arch", "name", "type"
这几个域对应的信息解析出来. 然后调用xmlout
导出到xml
,md
或者rc
文件中.
所以 make metadata_airframe
的操作就是把这些信息导出到md
和xml
中.