PX4 編譯分析之Airframe文檔生成

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-buildbuild/px4_sitl_default生成一些配置文件, 第二個和airframe_metadatametadata_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 文件夾):

  1. build/px4_sitl_default 中建立輸出文件夾 docs
  2. 執行 python Tools/px_process_airframes.py -v -a ROMFS/px4fmu_common/init.d --markdown build/px4_sitl_default/docs/airframes.md
  3. 執行 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()

可以看到這裏只是一個入口函數, 解析了一些用戶選項, 然後通過srcscannersrcparser 解析了 -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 <[email protected]>
#

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 方法的執行步驟, 由於其文件比較長,這裏只給出簡要描述, 並不附上代碼.

  1. 首先通過.hil 文件名解析得到序號, 這裏是1001
  2. 進行如下圖流程圖中的操作的描述(尚未全部完成)
Created with Raphaël 2.2.0開始state=None獲取一行輸入放入line去掉行的開始和結束空字符state=None匹配到'^\#\s'設置state爲wait-shortshort_desc=None; long_desc=Nonestate!=comment-processed匹配到'(.*?)\s*\#\n/'line=匹配到的第一組last_comment_line=True匹配到'^\#\s*(.*)'獲取到開頭字符串state="wait-short-end"設置 state="wait_long"last_comment_line=Falseyesnoyesyesyesnoyesyes

主要過程就是把"url", "maintainer", "output", "arch", "name", "type" 這幾個域對應的信息解析出來. 然後調用xmlout 導出到xml,md 或者rc 文件中.
所以 make metadata_airframe 的操作就是把這些信息導出到mdxml 中.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章