px4原生固件:
git clone https://github.com/PX4/Firmware.git
APM:
git clone https://github.com/ArduPilot/ardupilot.git
所以他们时不同的固件,bootload一样
https://dev.px4.io/zh/setup/building_px4.html
下面时ardupilot/APM的编译和启动
Makefile,以ArduCopter为例:
include ../mk/apm.mk
环境变量定义: *****提前定义ardupilot为根目录
MK_DIR := $(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST))))
MK_DIR=/ardupilot/mk目录
SRCROOT := $(realpath $(dir $(firstword $(MAKEFILE_LIST))))
SRCROOT=ArduCopter目录的绝对地址. = /ardupilot/ArduCopter
SKETCHBOOK := $(shell cd $(SRCROOT)/.. && pwd)
SKETCHBOOK=ardupilot目录绝对地址,就是根目录. = /ardupilot
SKETCH := $(lastword $(subst /, ,$(SRCROOT)))
SKETCH=ArduCopter字符串
BUILDROOT := $(SKETCHBOOK)/Build.$(SKETCH)
BUILDROOT= /ardupilot/Build.ArduCopter
MESSAGE_DEFINITIONS := $(SKETCHBOOK)/modules/mavlink/message_definitions/v1.0
MESSAGE_DEFINITIONS=/ardupilot/modules/mavlink/message_definitions/v1.0
UAVCAN_HEADERS := $(UAVCAN_GEN_INC)/uavcan/Timestamp.hpp $(wildcard $(UAVCAN_GEN_INC),*.hpp)
UAVCAN_HEADERS= /ardupilot/modules/uavcan/libuavcan/include/dsdlc_generated/*.hpp /ardupilot/modules/uavcan/libuavcan/include/dsdlc_generated/uavcan/Timestamp.hpp
PX4FIRMWARE_DIRECTORY ?= $(SKETCHBOOK)/modules/PX4Firmware
PX4FIRMWARE_DIRECTORY = /ardupilot/modules/PX4Firmware
PX4NUTTX_DIRECTORY ?= $(SKETCHBOOK)/modules/PX4NuttX
PX4NUTTX_DIRECTORY = /ardupilot/modules/PX4NuttX
NUTTX_ROOT := $(shell cd $(PX4NUTTX_DIRECTORY) && pwd)
NUTTX_ROOT = /ardupilot/modules/PX4NuttX
NUTTX_SRC := $(NUTTX_ROOT)/nuttx/
NUTTX_SRC := /ardupilot/modules/PX4NuttX/nuttx/
PX4_ROOT := $(shell cd $(PX4FIRMWARE_DIRECTORY) && pwd)
PX4_ROOT = /ardupilot/modules/PX4Firmware
PX4_MAKE_ARCHIVES = $(MAKE) -C $(PX4_ROOT) -f $(PX4_ROOT)/Makefile.make NUTTX_SRC=$(NUTTX_SRC) CCACHE=$(CCACHE) archives MAXOPTIMIZATION="-Os"
PX4_MAKE_ARCHIVES = make -C /ardupilot/modules/PX4Firmware -f /ardupilot/modules/PX4Firmware/Makefile.make NUTTX_SRC=/ardupilot/modules/PX4NuttX/nuttx/ CCACHE=(空) archives MAXOPTIMIZATION="-Os"
PX4_MAKE = $(v)+ GIT_SUBMODULES_ARE_EVIL=1 ARDUPILOT_BUILD=1 $(MAKE) -C $(SKETCHBOOK) -f $(PX4_ROOT)/Makefile.make EXTRADEFINES="$(SKETCHFLAGS) $(WARNFLAGS) $(OPTFLAGS) "'$(EXTRAFLAGS)' APM_MODULE_DIR=$(SKETCHBOOK) SKETCHBOOK=$(SKETCHBOOK) CCACHE=$(CCACHE) PX4_ROOT=$(PX4_ROOT) NUTTX_SRC=$(NUTTX_SRC) MAXOPTIMIZATION="-Os" UAVCAN_DIR=$(UAVCAN_DIR)
PX4_MAKE = $(v)+ GIT_SUBMODULES_ARE_EVIL=1 ARDUPILOT_BUILD=1 make -C /ardupilot -f /ardupilot/modules/PX4Firmware/Makefile.make EXTRADEFINES="$(SKETCHFLAGS) $(WARNFLAGS) $(OPTFLAGS) "'$(EXTRAFLAGS)' APM_MODULE_DIR=/ardupilot SKETCHBOOK=/ardupilot CCACHE=(空) PX4_ROOT=/ardupilot/modules/PX4Firmware/ NUTTX_SRC=/ardupilot/modules/PX4NuttX/nuttx/ MAXOPTIMIZATION="-Os" UAVCAN_DIR=$(UAVCAN_DIR)
SKETCHCPP := $(SRCROOT)/$(SKETCH).cpp
SKETCHCPP = /ardupilot/ArduCopter/ArduCopter.cpp
MAKE_INC=$(wildcard $(SRCROOT)/make.inc)
MAKE_INC = /ardupilot/ArduCopter/make.inc
SRCSUFFIXES = *.cpp
LIBRARIES在mk/make.inc与/ardupilot/ArduCopter/make.inc中定义了.其实就是需要编译的libraries中的库目录
LIBTOKENS := $(LIBRARIES)
LIBTOKENS += AP_HAL_PX4
SKETCHLIBS := $(wildcard $(addprefix $(SKETCHBOOK)/libraries/,$(LIBTOKENS)))
SKETCHLIBS = /ardupilot/libraries/$(LIBTOKENS)包含的目录
SKETCHLIBSRCDIRS := $(SKETCHLIBS) $(addsuffix /utility,$(SKETCHLIBS))
SKETCHLIBSRCDIRS = /ardupilot/libraries/$(LIBTOKENS)包含的目录 /ardupilot/libraries/$(LIBTOKENS)包含的目录/utility
SKETCHLIBSRCS := $(wildcard $(foreach suffix,$(SRCSUFFIXES),$(addsuffix /$(suffix),$(SKETCHLIBSRCDIRS))))
SKETCHLIBSRCS = /ardupilot/libraries/$(LIBTOKENS)包含的目录 和 /ardupilot/libraries/$(LIBTOKENS)包含的目录/utility目录中*.cpp文件扩展出来
SKETCHLIBSRCSRELATIVE := $(subst $(SKETCHBOOK)/,,$(SKETCHLIBSRCS))
SKETCHLIBSRCSRELATIVE = $(SKETCHLIBSRCS) 去掉/ardupilot/部分,得到相对路径.
PX4_V4_CONFIG_FILE=$(MK_DIR)/PX4/config_px4fmu-v4_APM.mk
PX4_V4_CONFIG_FILE=/ardupilot/mk/PX4/config_px4fmu-v4_APM.mk
export PX4_BASE := $(realpath $(dir $(lastword $(MAKEFILE_LIST))))
PX4_BASE = /ardupilot/modules/PX4Firmware
export NUTTX_SRC = $(abspath $(PX4_BASE)/NuttX/nuttx)/
NUTTX_SRC=/ardupilot/modules/PX4Firmware/NuttX/nuttx/
export ARCHIVE_DIR = $(abspath $(PX4_BASE)/Archives)/
ARCHIVE_DIR = /ardupilot/modules/PX4Firmware/Archives/
export PX4_MK_DIR = $(abspath $(PX4_BASE)/makefiles)/
PX4_MK_DIR = /ardupilot/modules/PX4Firmware/makefiles
export PX4_TARGET_OS ?= nuttx
BOARDS="px4fmu-v4" make时带入
NUTTX_ARCHIVES = $(foreach board,$(BOARDS),$(ARCHIVE_DIR)$(board).export)
NUTTX_ARCHIVES = /ardupilot/modules/PX4Firmware/Archives/px4fmu-v4.export
KNOWN_CONFIGS := $(subst config_,,$(basename $(notdir $(wildcard $(PX4_MK_DIR)/$(PX4_TARGET_OS)/config_*.mk))))
KNOWN_CONFIGS = /ardupilot/modules/PX4Firmware/makefiles/nuttx目录下所有:去掉config_和.mk部分内容.如:px4fmu-v2_test, px4fmu-v4_APM等.
CONFIGS ?= $(KNOWN_CONFIGS)
EXPLICIT_CONFIGS := $(filter $(CONFIGS),$(MAKECMDGOALS))
EXPLICIT_CONFIGS = px4fmu-v4_APM
CONFIGS := $(EXPLICIT_CONFIGS)
export IMAGE_DIR = $(abspath $(PX4_BASE)/Images)/
IMAGE_DIR = /ardupilot/modules/PX4Firmware/Images/
DESIRED_FIRMWARES = $(foreach config,$(CONFIGS),$(IMAGE_DIR)$(config).px4)
DESIRED_FIRMWARES = /ardupilot/modules/PX4Firmware/Images/px4fmu-v4_APM.px4
STAGED_FIRMWARES = $(foreach config,$(KNOWN_CONFIGS),$(IMAGE_DIR)$(config).px4)
STAGED_FIRMWARES = /ardupilot/modules/PX4Firmware/Images/px4fmu-v4_APM.px4一系列集合,跟随KNOWN_CONFIGS变化
export BUILD_DIR = $(abspath $(PX4_BASE)/Build)/
BUILD_DIR = /ardupilot/modules/PX4Firmware/Build/
FIRMWARES = $(foreach config,$(KNOWN_CONFIGS),$(BUILD_DIR)$(config).build/firmware.px4)
FIRMWARES = /ardupilot/modules/PX4Firmware/Build/px4fmu-v4_APM.build/firmware.px4等一些列集合对应STAGED_FIRMWARES
=======================================================================================================
makefile第一个目标:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
px4-v4: $(BUILDROOT)/make.flags CHECK_MODULES $(MAVLINK_HEADERS) $(UAVCAN_HEADERS) $(PX4_ROOT)/Archives/px4fmu-v4.export $(SKETCHCPP) module_mk
$(v) echo Building px4-v4
$(RULEHDR)
$(v) cp $(PX4_V4_CONFIG_FILE) $(PX4_ROOT)/makefiles/nuttx/
下面是
编译ArduCopter以及其他模块,下面有介绍
$(PX4_MAKE) px4fmu-v4_APM
$(v) arm-none-eabi-size $(PX4_ROOT)/Build/px4fmu-v4_APM.build/firmware.elf
$(v) cp $(PX4_ROOT)/Images/px4fmu-v4_APM.px4 $(SKETCH)-v4.px4
$(v) mkdir -p $(MK_DIR)/PX4/ROMFS/bootloader/
$(v) cp $(SKETCHBOOK)/mk/PX4/bootloader/px4fmuv4_bl.bin $(MK_DIR)/PX4/ROMFS/bootloader/fmu_bl.bin
$(v) $(SKETCHBOOK)/Tools/scripts/add_git_hashes.py $(HASHADDER_FLAGS) "$(SKETCH)-v4.px4" "$(SKETCH)-v4.px4"
$(v) echo "PX4 $(SKETCH) Firmware is in $(SKETCH)-v4.px4"
=======================================================================================================
$(BUILDROOT)/make.flags: FORCE ###FORCE为空目标
@mkdir -p $(BUILDROOT) ###创建目录/ardupilot/Build.ArduCopter
把环境变量的内容输出到make.flags.new
@echo "// BUILDROOT=$(BUILDROOT) HAL_BOARD=$(HAL_BOARD) HAL_BOARD_SUBTYPE=$(HAL_BOARD_SUBTYPE) TOOLCHAIN=$(TOOLCHAIN) EXTRAFLAGS=$(EXTRAFLAGS)" > $(BUILDROOT)/make.flags.new
####判断环境变量变化没,变化了ArduCopter目录需要重新编译.删除了ArduCopter/*.o的话,需要重新编译.
@cmp $(BUILDROOT)/make.flags $(BUILDROOT)/make.flags.new > /dev/null 2>&1 || rm -f $(SRCROOT)/*.o
@cmp $(BUILDROOT)/make.flags $(BUILDROOT)/make.flags.new > /dev/null 2>&1 || mv $(BUILDROOT)/make.flags.new $(BUILDROOT)/make.flags
@rm -f $(BUILDROOT)/make.flags.new
@cat $(BUILDROOT)/make.flags
=======================================================================================================
调度shell脚本,git方面的脚本,把各个模块下载完,如果我们已经下完,这里就没啥用了.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CHECK_MODULES:
$(if $(BUILDSYS_DEPRECATED),$(call echoallwarnings))
$(v)$(MK_DIR)/check_modules.sh
=======================================================================================================
这个目标就是生成mavlink协议的,使用python生成.如果我们想添加一条mavlink的命令,修改/ardupilot/modules/mavlink/message_definitions/v1.0/ardupilotmega.xml或common.xml,然后编译即可,编译后会生成对应的头文件,调用头文件的xxx_send就好了.mavlink协议解析在gcs_mavlink.cpp;GCS_MAVLINK_Copter::try_send_message发送命令,data_stream_send定时发送,由streamRates控制时间对应命令66设置;GCS_MAVLINK_Copter::handleMessage处理各种下发命令.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$(MAVLINK_HEADERS): $(MESSAGE_DEFINITIONS)/ardupilotmega.xml $(MESSAGE_DEFINITIONS)/common.xml
echo "Generating MAVLink headers..."
#goto mavlink module directory and run the most recent generator script
echo "Generating C code using mavgen.py located at" $(SKETCHBOOK)/modules/mavlink/
PYTHONPATH=$(MAVLINK_DIR) python $(MAVLINK_DIR)/pymavlink/tools/mavgen.py --lang=C --wire-protocol=$(MAVLINK_WIRE_PROTOCOL) --output=$(MAVLINK_OUTPUT_DIR) $(MESSAGE_DEFINITIONS)/ardupilotmega.xml; if [ $$? -le 0 -o $$? -gt 128 ]; then echo "mavgen: success"; exit 0; else echo "mavgen: failed"; exit 1; fi
=======================================================================================================
不明
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$(UAVCAN_HEADERS): $(UAVCAN_DSDL_MESSAGE_DEFINITIONS)
@echo "Generating UAVCAN headers..."
# PYTHONPATH=$(UAVCAN_DIR)libuavcan/dsdl_compiler/python $(UAVCAN_DIR)libuavcan/dsdl_compiler/setup.py build
# PYTHONPATH=$(UAVCAN_DIR)libuavcan/dsdl_compiler/ python $(UAVCAN_DIR)libuavcan/dsdl_compiler/setup.py install
PYTHONPATH=$(UAVCAN_DIRECTORY)/libuavcan/ python $(UAVCAN_DIRECTORY)/libuavcan/dsdl_compiler/libuavcan_dsdlc "$(UAVCAN_DIRECTORY)/dsdl/uavcan" -O"$(UAVCAN_GEN_INC)"
=======================================================================================================
这是
编译nuttx系统
其实就是:make -C /ardupilot/modules/PX4Firmware -f /ardupilot/modules/PX4Firmware/Makefile.make NUTTX_SRC=/ardupilot/modules/PX4NuttX/nuttx/ CCACHE=(空) archives MAXOPTIMIZATION="-Os" BOARDS="px4fmu-v4"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$(PX4_ROOT)/Archives/px4fmu-v4.export:
$(v) $(PX4_MAKE_ARCHIVES) BOARDS="px4fmu-v4"
=======================================================================================================
用于生成/ardupilot/module.mk文件,包含了/ardupilot/ArduCopter所有cpp文件,libraries包含路径的所有cpp文件.用于生成一个模块,nuttx脚本启动.
LIBUAVCAN_SRC := $(shell find $(LIBUAVCAN_DIR)src -type f -name '*.cpp') 先不看了.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
module_mk:
$(v) echo "Building $(SKETCHBOOK)/module.mk"
$(RULEHDR)
$(v) echo "# Auto-generated file - do not edit" > $(SKETCHBOOK)/module.mk.new
$(v) echo "MODULE_COMMAND = ArduPilot" >> $(SKETCHBOOK)/module.mk.new
$(v) echo "SRCS = $(wildcard $(SRCROOT)/*.cpp) $(SKETCHLIBSRCSRELATIVE) $(LIBUAVCAN_SRC)" >> $(SKETCHBOOK)/module.mk.new
$(v) echo "MODULE_STACKSIZE = 4096" >> $(SKETCHBOOK)/module.mk.new
$(v) echo "EXTRACXXFLAGS = -Wframe-larger-than=1300" >> $(SKETCHBOOK)/module.mk.new
$(v) cmp $(SKETCHBOOK)/module.mk $(SKETCHBOOK)/module.mk.new 2>/dev/null || mv $(SKETCHBOOK)/module.mk.new $(SKETCHBOOK)/module.mk
$(v) rm -f $(SKETCHBOOK)/module.mk.new
=======================================================================================================
=======================================================================================================
=======================================================================================================
在Makefile.make文件中:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
archives: checksubmodules $(NUTTX_ARCHIVES)
=======================================================================================================
也是检查git
*****
checksubmodules:
$(Q) ($(PX4_BASE)/Tools/check_submodules.sh)
=======================================================================================================
********$(NUTTX_ARCHIVES):需要依赖$(ARCHIVE_DIR)%.export; 而$(ARCHIVE_DIR)%.export:需要依赖$(NUTTX_SRC)
/ardupilot/modules/PX4Firmware/Archives/%.export什么都没有.
编译nuttx系统,拷贝为/ardupilot/modules/PX4Firmware/Archives/px4fmu-v4.export.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$(NUTTX_ARCHIVES): $(ARCHIVE_DIR)%.export: $(NUTTX_SRC)
@$(ECHO) %% Configuring NuttX for $(board)
$(Q) (cd $(NUTTX_SRC) && $(RMDIR) nuttx-export)
$(Q)+ $(MAKE) -C $(NUTTX_SRC) -r $(MQUIET) distclean
$(Q) (cd $(NUTTX_SRC)/configs && $(COPYDIR) $(PX4_BASE)nuttx-configs/$(board) .)
$(Q) (cd $(NUTTX_SRC)tools && ./configure.sh $(board)/$(configuration))
@$(ECHO) %% Exporting NuttX for $(board)
$(Q)+ $(MAKE) -C $(NUTTX_SRC) -r $(MQUIET) CONFIG_ARCH_BOARD=$(board) export
$(Q) $(MKDIR) -p $(dir $@)
$(Q) $(COPY) $(NUTTX_SRC)nuttx-export.zip $@
$(Q) (cd $(NUTTX_SRC)/configs && $(RMDIR) $(board))
=======================================================================================================
=======================================================================================================
=======================================================================================================
$(PX4_MAKE) px4fmu-v4_APM
其实就是调用Makefile.make中的:
$(EXPLICIT_CONFIGS): all
all: $(DESIRED_FIRMWARES)
$(DESIRED_FIRMWARES)是系列$(STAGED_FIRMWARES)的一个成员.
$(STAGED_FIRMWARES): $(IMAGE_DIR)%.px4: $(BUILD_DIR)%.build/firmware.px4
@$(ECHO) %% Copying $@
$(Q) $(COPY) $< $@
$(Q) $(COPY) $(patsubst %.px4,%.bin,$<) $(patsubst %.px4,%.bin,$@)
就相当于只调用了:
/ardupilot/modules/PX4Firmware/Images/px4fmu-v4_APM.px4: /ardupilot/modules/PX4Firmware/Images/px4fmu-v4_APM.px4: /ardupilot/modules/PX4Firmware/Build/px4fmu-v4_APM.build/firmware.px4
....
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$(BUILD_DIR)%.build/firmware.px4: config = $(patsubst $(BUILD_DIR)%.build/firmware.px4,%,$@)
其中config = px4fmu-v4_APM等系列
$(BUILD_DIR)%.build/firmware.px4: work_dir = $(BUILD_DIR)$(config).build/
其中work_dir= /ardupilot/modules/PX4Firmware/Build/px4fmu-v4_APM.build系列.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
generateuorbtopicheaders生成uorb头文件.
$(FIRMWARES): $(BUILD_DIR)%.build/firmware.px4: generateuorbtopicheaders checksubmodules
@$(ECHO) %%%%
@$(ECHO) %%%% Building $(config) in $(work_dir)
@$(ECHO) %%%%
创建目录/ardupilot/modules/PX4Firmware/Build/px4fmu-v4_APM.build
$(Q) $(MKDIR) -p $(work_dir)
使用文件/ardupilot/modules/PX4Firmware/makefiles/firmware.mk再次mak.其中FIRMWARE_GOAL = firmware
$(Q)+ $(MAKE) -r -C $(work_dir) \
-f $(PX4_MK_DIR)firmware.mk \
CONFIG=$(config) \
WORK_DIR=$(work_dir) \
$(FIRMWARE_GOAL)
这个makefile就不说了,他就是编译各个驱动模块的.下面目录定义了MODULES模块定义.
/ardupilot/modules/PX4Firmware/makefiles/nuttx.mk
/ardupilot/modules/PX4Firmware/makefiles/nuttx/config_px4fmu-v4_APM.mk
/ardupilot/mk/PX4/px4_common.mk
在文件Build/px4fmu-v4_APM.build/builtin_commands.c可以看到有哪些模块.
#######################################################################################################
启动过程:
__start(stm32_start.c)
1-->初始化时钟,早期io口等
1-->os_start(os_start.c)
2-->初始化sem,中断向量表,线程,文件系统等
2-->up_initialize()初始化了串口驱动,usb驱动.
2-->os_bringup(os_bringup.c)
3-->开了2个线程用于定时任务采样. 不过3.6版本后,除了uorb,fmu,adc,其他提到应用层做了.
3-->启动进程CONFIG_USER_ENTRYPOINT-->nsh_main()
4-->nsh_initialize()
5-->nsh_archinitialize()启动各种驱动,IO口,pwm,spi,sd卡
4-->nsh_consolemain()
5-->nsh_initscript()启动脚本/etc/init.d/rcS
5-->nsh_session()用于支持终端交互,相应用户的shell命令,跟linux差不多(如busybox)
脚本: ./mk/PX4/ROMFS/init.d/rcS
挂载sd卡到文件系统.
sh /etc/init.d/rc.APM启动另外一个脚本.
脚本1: ./mk/PX4/ROMFS/init.d/rc.APM
uorb start启动uorb,uorb其实就是利用文件通讯的通讯工具
ArduPilot start启动应用程序.
应用程序入口ArduPilot_main()定义在文件AP_HAL_Main.h
#define AP_HAL_MAIN_CALLBACKS(CALLBACKS) extern "C" { \
int AP_MAIN(int argc, char* const argv[]); \
int AP_MAIN(int argc, char* const argv[]) { \
hal.run(argc, argv, CALLBACKS); \
return 0; \
} \
}
在ArduCopter.cpp中:
AP_HAL_MAIN_CALLBACKS(&copter);
展开:这种方式便于扩展到直升机等目录
int ArduPilot_main(int argc, char* const argv[]);
int ArduPilot_main(int argc, char* const argv[]) {
hal.run(argc, argv, &copter);
return 0;
}
const AP_HAL::HAL& hal = AP_HAL::get_HAL();在copter.c定义.
对应原型在:HAL_PX4_Class.cpp
const AP_HAL::HAL& AP_HAL::get_HAL() {
static const HAL_PX4 hal_px4;
return hal_px4;
}
主程序跳转到HAL_PX4::run()
启动主函数main_loop():配置串口;scheduler任务管理器初始化;调用copter.setup(),ArduCopter.cpp这个函数就是初始化px4所有内容;每隔250us循环调度copter.loop()
=======================================================================================================
Copter::setup()-->init_ardupilot
加载参数;串口管理器初始化;gcs初始化;BoardConfig板级初始化;notify灯和其他通知;battery电池;barometer气压计;init_rc_in遥控器输入初始化;allocate_motors电机对象分配空间,以及初始化参数;init_rc_out电机输出初始化,其中校准电调esc也在这里;gps初始化,gps是自动查询;init_optflow光流传感器;init_precland精准降落,irlock用的比较多;mission是任务,地面站配置航线,保存在飞控的任务;startup_INS_ground初始化ins(惯行传感器,就是角速度计与陀螺仪);init_compass初始化磁罗盘;其他按照其字面意思也能看懂,就不提了.
******注意:参数保存格式是4+n个字节,而内存格式是类,参考AP_PARAMDEF(float, Float, AP_PARAM_FLOAT)进一步了解吧.参数结构做的很好,但是遍历是链表形式,比较慢.还有就是在3.4以前,gcs刷参数是一直刷,3.6现在是1m退出.
初始化中:BoardConfig.init()-->px4_setup()
******注意一个问题:task_spawn调用进程后,如果该进程完成,再调用waitpid,此时得到的pid为-1,而不是task_spawn创建的pid.这个跟vfork区别开.
-->px4_setup_peripherals()开个进程给ADC驱动,启动fmu,初始化gpio管理起,rcin遥控器输入初始化,rcout电机输出初始化.
=====fmu是用来处理gpio驱动,rcin-->sbus,rcout-->pwm输出的.通过/dev/px4fmu系列设备文件通讯
-->px4_setup_pwm(),配置几轴飞机,也就是几路pwm输出
-->px4_setup_safety_mask(),初始化pwm输出,并且除了配置的pwm输出,其他pwm不能通过这个文件配置.就是设置保护.
-->px4_setup_uart不用
-->px4_setup_sbus暂不用,可以配置sbus输出到rcout,我们用pwm输出
-->px4_setup_drivers()对fmu进行sensor_reset 20
初始化IMU就说一个,磁罗盘是一样的:startup_INS_ground()-->ins.init(scheduler.get_loop_rate_hz());-->AP_InertialSensor::init()-->_start_backends()-->detect_backends()
板级配置默认:AP_BoardConfig::PX4_BOARD_PIXRACER
对应添加mpu6000传感器,_add_backend(AP_InertialSensor_Invensense::probe(*this, hal.spi->get_device(HAL_INS_MPU60x0_NAME), ROTATION_ROLL_180))
AP_InertialSensor_Invensense::_init-->_hardware_init去配置寄存器,看这个设备在不在.如果不能获取,说明imu有问题.
3.4之前mpu6000做在驱动里面的,应用层是通过读取uorb或文件来获得数据,现在使用线程直接读取:
AP_InertialSensor_Invensense::start--> _dev->register_periodic_callback(1000, FUNCTOR_BIND_MEMBER(&AP_InertialSensor_Invensense::_poll_data, void));
=======================================================================================================
Copter::loop()
{
-->Copter::fast_loop()
{
-->ins.update();读取加速度和陀螺仪数据.
计算混合油门(这个值用于飞行时(THR_MIX_MAX)姿态控制占油门的比例大小,降落时(THR_MIX_MIN)着陆判断);pid计算roll,pitch,yaw输出.
-->attitude_control->rate_controller_run();-->AC_AttitudeControl_Multi::rate_controller_run
-->motors_output();-->motors->output();-->AP_MotorsMulticopter::output()
{
// update throttle filter滤波
update_throttle_filter();
// calc filtered battery voltage and lift_max,这个_batt_voltage_max=0;所以直接退出了
update_lift_max_from_batt_voltage();
// run spool logic.这是pwm输出的逻辑,解锁时,以_spin_arm带速旋转.
output_logic();
// calculate thrust通过roll,pitch,yaw,油门计算每个电机的推力.AP_MotorsMatrix::output_armed_stabilizing
output_armed_stabilizing();
// apply any thrust compensation for the frame无用
thrust_compensation();
// convert rpy_thrust values to pwm.计算处理的推力转换为pwm到电机上.如果是SHUT_DOWN输出最小值,SPIN_WHEN_ARMED输出带速,其他根据计算出的推力输出.
output_to_motors();
// output any booster throttle无用
output_boost_throttle();
}
-->read_AHRS();
{
copter.h定义:AP_AHRS_NavEKF ahrs;
这里是姿态解算核心代码
ahrs.update(true);-->AP_AHRS_NavEKF::update
{
AP_AHRS_DCM::update()初步计算陀螺仪的数据,以及漂移
update_EKF2();-->EKF2.UpdateFilter();-->NavEKF2::UpdateFilter()-->core[i].UpdateFilter(statePredictEnabled[i]);-->NavEKF2_core::UpdateFilter
这里就是ekf算法核心内容,我也没看懂,不好意思.计算包括roll,pitch,yaw,还有3d位置/速度等
}
}
-->read_inertia();把ekf算出来的数据,转到inertial_nav惯行系统里面,用于后面各个飞行模式使用.
-->check_ekf_reset();ekf几组计算core对应ins对数组,如果某一core计算数据方差太大,切换至另外一组core计算.这个函数只是上报给gcs和写入日志
-->update_flight_mode();这里就是飞行控制模块了.
{
STABILIZE = 0, //手动模式,遥控器输入转换为角度,再通过角度->角速度控制飞机.油门直接控制飞机加速度manual airframe angle with manual throttle
ACRO = 1, //杂技模式,遥控器输入直接到输出 manual body-frame angular rate with manual throttle
ALT_HOLD = 2, //高度保持,油门归中时,高度保持,但水平会有漂移.油门控制飞机速度,roll/pitch控制角度.manual airframe angle with automatic throttle
AUTO = 3, //自动模式,mission在此时就用到了,根据配置的任务执行.除yaw其他不可控 fully automatic waypoint control using mission commands
GUIDED = 4, //指点模式,飞机飞向自定坐标,除yaw其他不可控 fully automatic fly to coordinate or fly at velocity/direction using GCS immediate commands
LOITER = 5, //悬停,不动遥感时保持3d位置.遥控器控制加速度,再算为目标速度,添加到位置中,再算速度,加速度,转换为角度,转为角速度,控制电机. automatic horizontal acceleration with automatic throttle
RTL = 6, //返航,回到home点,然后降落.油门不可控,roll/pitch转为速度控制 automatic return to launching point
CIRCLE = 7, //飞圆圈 automatic circular flight with automatic throttle
LAND = 9, //降落 automatic landing with horizontal position control
DRIFT = 11, // semi-automous position, yaw and throttle control
SPORT = 13, // manual earth-frame angular rate control with manual throttle
FLIP = 14, // automatically flip the vehicle on the roll axis
AUTOTUNE = 15, // automatically tune the vehicle's roll and pitch gains
POSHOLD = 16, //定点模式,3d位置定点loiter,油门转为速度控制,roll/pitch/yaw转为角度控制 automatic position hold with manual override, with automatic throttle
BRAKE = 17, // full-brake using inertial/GPS system, no pilot input
THROW = 18, // throw to launch mode using inertial/GPS system, no pilot input
AVOID_ADSB = 19, // automatic avoidance of obstacles in the macro scale - e.g. full-sized aircraft
GUIDED_NOGPS = 20, // guided mode but only accepts attitude and altitude
油门就是控制飞机垂直方向的动力.手动模式下,油门直接转为加速度,参与pid计算;而在poshold,alt_hold,rtl,land模式下,他们都是通过位置->速度->加速度来控制垂直动力,而油门可用情况下是转换为了请求速度,再通过p->v->a控制.
roll/pitch.手动模式/poshold下,通过角度->角速度进行pid计算.在poshold/guid/auto模式下,通过位置->速度->加速度控制飞机位置,roll/pitch不可控;rtl与land模式下,roll/pitch换算为请求水平加速度,再添加到pos中,再通过p->v->a控制->角度->角速度.
}
-->update_home_from_EKF();计算home的距离
-->update_land_and_crash_detectors();
}
处理其他scheduler_tasks任务.
scheduler.run(time_available > MAIN_LOOP_MICROS ? 0u : time_available);
}