PX4二次开发——PX4程序架构

本文深入探讨了PX4飞控在固定翼模式下的程序架构,从RCS启动脚本分析了模块启动过程,重点讲解了commander、navigator、fw_pos_control_l1和fw_att_control四个关键模块的功能和控制逻辑,包括总能量控制系统(TECS)的实现,揭示了固定翼飞行控制的复杂性和精确性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

PX4程序架构

一、从RCS启动脚本可以看出哪些东西

​ 启动脚本是一个神奇的东西,它能够识别出你对应的飞机类型,加载对应的混控器,选择对应的姿态、位置估计程序以及控制程序,初始化你需要的驱动程序。下面来分析下。

1.1RCS位置

  • Firmware->ROMFS->px4fmu_common->init.d->rcs,最新版本的启动脚本如下:
#!/bin/sh
# Un comment and use set +e to ignore and set -e to enable 'exit on error control'
set +e
# Un comment the line below to help debug scripts by printing a trace of the script commands
#set -x
# PX4FMU startup script.
#
# NOTE: environment variable references:
#    If the dollar sign ('$') is followed by a left bracket ('{') then the
#    variable name is terminated with the right bracket character ('}').
#    Otherwise, the variable name goes to the end of the argument.
#
#
# NOTE: COMMENT LINES ARE REMOVED BEFORE STORED IN ROMFS.
#
#------------------------------------------------------------------------------

#
# Set default paramter values.
# Do not add intra word spaces
# it wastes flash
#
set R /
set AUTOCNF no
set AUX_MODE pwm
set DATAMAN_OPT ""
set FAILSAFE none
set FAILSAFE_AUX none
set FCONFIG /fs/microsd/etc/config.txt
set FEXTRAS /fs/microsd/etc/extras.txt
set FMU_MODE pwm
set FRC /fs/microsd/etc/rc.txt
set IOFW "/etc/extras/px4_io-v2_default.bin"
set IO_PRESENT no
set LOG_FILE /fs/microsd/bootlog.txt
set LOGGER_ARGS ""
set LOGGER_BUF  14
set MAV_TYPE none
set MIXER none
set MIXER_AUX none
set MIXER_FILE none
set MK_MODE none
set MKBLCTRL_ARG ""
set OUTPUT_MODE none
set PARAM_FILE /fs/microsd/params
set PWM_AUX_DISARMED p:PWM_AUX_DISARMED
set PWM_AUX_MAX p:PWM_AUX_MAX
set PWM_AUX_MIN p:PWM_AUX_MIN
set PWM_AUX_OUT none
set PWM_AUX_RATE p:PWM_AUX_RATE
set PWM_DISARMED p:PWM_DISARMED
set PWM_MAX p:PWM_MAX
set PWM_MIN p:PWM_MIN
set PWM_OUT none
set PWM_RATE p:PWM_RATE
set RC_INPUT_ARGS ""
set SDCARD_MIXERS_PATH /fs/microsd/etc/mixers
set STARTUP_TUNE 1
set USE_IO no
set VEHICLE_TYPE none

# Airframe parameter versioning: airframe maintainers can set this in the
# airframe startup script, and then increase it by one whenever an airframe
# parameter is updated - it will ensure that these parameters will be updated
# when the firmware is flashed.
set PARAM_DEFAULTS_VER 1

#
# Mount the procfs.
#
mount -t procfs /proc

#
# Start CDC/ACM serial driver.
#
sercon

#
# Print full system version.
#
ver all

#
# Start the ORB (first app to start)
# tone_alarm and tune_control
# is dependent.
#
uorb start

#
# Try to mount the microSD card.
#
# REBOOTWORK this needs to start after the flight control loop.
if mount -t vfat /dev/mmcsd0 /fs/microsd
then
	if hardfault_log check
	then
		# Error tune.
		set STARTUP_TUNE 2
		if hardfault_log commit
		then
			hardfault_log reset
		fi
	fi

	# Prevent MacOS and Ubuntu from creating unnecessary temporary files on the microSD card

	# block MacOS Spotlight indexing (.Spotlight-V100 folder)
	if [ ! -f "/fs/microsd/.metadata_never_index" ]; then
		cat > /fs/microsd/.metadata_never_index
	fi

	# block MacOS trashes
	if [ ! -f "/fs/microsd/.Trashes" ]; then
		cat > /fs/microsd/.Trashes
	fi

	# block MacOS logging of filesystem events
	if [ ! -d "/fs/microsd/.fseventsd" ]; then
		mkdir /fs/microsd/.fseventsd
	fi

	if [ ! -f "/fs/microsd/.fseventsd/no_log" ]; then
		cat > /fs/microsd/.fseventsd/no_log
	fi

	# block Ubuntu trash
	if [ ! -f "/fs/microsd/.Trash-1000" ]; then
		cat > /fs/microsd/.Trash-1000
	fi

else
	# tune SD_INIT
	set STARTUP_TUNE 14 # tune 14 = SD_INIT
	if mkfatfs /dev/mmcsd0
	then
		if mount -t vfat /dev/mmcsd0 /fs/microsd
		then
			echo "INFO [init] card formatted"
		else
			set STARTUP_TUNE 15 # tune 15 = SD_ERROR
			echo "ERROR [init] format failed"
			set LOG_FILE /dev/null
		fi
	else
		set LOG_FILE /dev/null
	fi
fi

#
# Look for an init script on the microSD card.
# Disable autostart if the script found.
#
if [ -f $FRC ]
then
	. $FRC
else

	#
	# Set the parameter file if mtd starts successfully.
	#
	if mtd start
	then
		set PARAM_FILE /fs/mtd_params
	fi

	#
	# Load parameters.
	#
	# if MTD has a secondary storage it is used for (factory) calibration data
	if mtd has-secondary
	then
		if mtd start -i 1 /fs/mtd_caldata
		then
			param load /fs/mtd_caldata
		fi
	fi

	param select $PARAM_FILE
	if ! param import
	then
		param reset_all
	fi

	#
	# Set AUTOCNF flag to use it in AUTOSTART scripts.
	#
	if param greater SYS_AUTOCONFIG 0
	then
		if param compare SYS_AUTOCONFIG 1
		then
			# Wipe out params except RC*, flight modes, total flight time, accel cal, gyro cal, next flight UUID
			param reset_all SYS_AUTOSTART SYS_AUTOCONFIG RC* COM_FLTMODE* LND_FLIGHT_T_* TC_* CAL_ACC* CAL_GYRO* COM_FLIGHT_UUID
		fi

		set AUTOCNF yes
	fi

	#
	# Optional board defaults: rc.board_defaults
	#
	set BOARD_RC_DEFAULTS ${R}etc/init.d/rc.board_defaults
	if [ -f $BOARD_RC_DEFAULTS ]
	then
		echo "Board defaults: ${BOARD_RC_DEFAULTS}"
		. $BOARD_RC_DEFAULTS
	fi
	unset BOARD_RC_DEFAULTS

	#
	# Start the tone_alarm driver.
	# Needs to be started after the parameters are loaded (for CBRK_BUZZER).
	#
	tone_alarm start

	#
	# Play the startup tune (if not disabled or there is an error)
	#
	param compare CBRK_BUZZER 782090
	if [ $? != 0 -o $STARTUP_TUNE != 1 ]
	then
		tune_control play -t $STARTUP_TUNE
	fi

	#
	# Waypoint storage.
	# REBOOTWORK this needs to start in parallel.
	#
	dataman start $DATAMAN_OPT

	#
	# Start the socket communication send_event handler.
	#
	send_event start

	#
	# Start the resource load monitor.
	#
	load_mon start

	#
	# Start system state indicator.
	#
	rgbled start -X -q
	rgbled_ncp5623c start -X -q

	if param greater LIGHT_EN_BLINKM 0
	then
		if blinkm start -X
		then
			blinkm systemstate
		fi
	fi

	#
	# Set parameters and env variables for selected AUTOSTART.
	#
	if ! param compare SYS_AUTOSTART 0
	then
		. ${R}etc/init.d/rc.autostart
	fi

	#
	# Override parameters from user configuration file.
	#
	if [ -f $FCONFIG ]
	then
		echo "Custom: ${FCONFIG}"
		. $FCONFIG
	fi

	#
	# If autoconfig parameter was set, reset it and save parameters.
	#
	if [ $AUTOCNF = yes ]
	then
		param set SYS_AUTOCONFIG 0
	fi

	#
	# Check if PX4IO present and update firmware if needed.
	# Assumption IOFW set to firmware file and IO_PRESENT = no
	#

	if [ -f $IOFW ]
	then
		# Check for the mini using build with px4io fw file
		# but not a px4IO
		if ver hwtypecmp V540 V560
		then
			param set SYS_USE_IO 0
		else
			if px4io checkcrc ${IOFW}
			then
				set IO_PRESENT yes
			else
				# tune Program PX4IO
				tune_control play -t 16 # tune 16 = PROG_PX4IO

				if px4io start
				then
					# Try to safety px4 io so motor outputs don't go crazy.
					if ! px4io safety_on
					then
						# px4io did not respond to the safety command.
						px4io stop
					fi
				fi

				if px4io forceupdate 14662 ${IOFW}
				then
					usleep 10000
					tune_control stop
					if px4io checkcrc ${IOFW}
					then
						echo "PX4IO CRC OK after updating" >> $LOG_FILE
						tune_control play -t 17 # tune 17 = PROG_PX4IO_OK
						set IO_PRESENT yes
					fi
				fi

				if [ $IO_PRESENT = no ]
				then
					echo "PX4IO update failed" >> $LOG_FILE
					tune_control play -t 18 # tune 18 = PROG_PX4IO_ERR
				fi
			fi
		fi
	fi

	#
	# Set USE_IO flag.
	#
	if param compare -s SYS_USE_IO 1
	then
		set USE_IO yes
	fi

	if [ $USE_IO = yes -a $IO_PRESENT = no ]
	then
		echo "PX4IO not found" >> $LOG_FILE
		tune_control play error
	fi

	#
	# RC update (map raw RC input to calibrate manual control)
	#  start before commander
	#
	rc_update start

	#
	# Sensors System (start before Commander so Preflight checks are properly run).
	# Commander needs to be this early for in-air-restarts.
	#
	if param greater SYS_HITL 0
	then
		set OUTPUT_MODE hil
		sensors start -h
		commander start -h
		# disable GPS
		param set GPS_1_CONFIG 0

		# start the simulator in hardware if needed
		if param compare SYS_HITL 2
		then
			sih start
		fi

	else
		#
		# board sensors: rc.sensors
		#
		set BOARD_RC_SENSORS ${R}etc/init.d/rc.board_sensors
		if [ -f $BOARD_RC_SENSORS ]
		then
			echo "Board sensors: ${BOARD_RC_SENSORS}"
			. $BOARD_RC_SENSORS
		fi
		unset BOARD_RC_SENSORS

		. ${R}etc/init.d/rc.sensors

		if param compare -s BAT1_SOURCE 2
		then
			esc_battery start
		fi

		if ! param compare BAT1_SOURCE 1
		then
			battery_status start
		fi

		commander start
	fi

	# Sensors on the PWM interface bank.
	if param compare -s SENS_EN_LL40LS 1
	then
		# Clear pins 5 and 6.
		set FMU_MODE pwm4
		set AUX_MODE pwm4
	fi


	# Check if ATS is enabled
	if param compare FD_EXT_ATS_EN 1
	then
		# Clear pins 5 and 6.
		set FMU_MODE pwm4
		set AUX_MODE pwm4
	fi

	if param greater TRIG_MODE 0
	then
		# We ONLY support trigger on pins 5+6 or 7+8 when simultanously using AUX for actuator output.
		if param compare TRIG_PINS 56
		then
			# clear pins 5 and 6
			set FMU_MODE pwm4
			set AUX_MODE pwm4
		else
			if param compare TRIG_PINS 78
			then
				# clear pins 7 and 8
				set FMU_MODE pwm6
				set AUX_MODE pwm6
			else
				set FMU_MODE none
				set AUX_MODE none
			fi
		fi

		camera_trigger start
		camera_feedback start
	fi

	#
	# Check if UAVCAN is enabled, default to it for ESCs.
	#
	if param greater -s UAVCAN_ENABLE 0
	then
		# Start core UAVCAN module.
		if uavcan start
		then
			if param greater UAVCAN_ENABLE 1
			then
				# Start UAVCAN firmware update server and dynamic node ID allocation server.
				uavcan start fw

				if param greater UAVCAN_ENABLE 2
				then
					set OUTPUT_MODE uavcan_esc
				fi
			fi
		else
			tune_control play error
		fi
	fi

	#
	# Optional board mavlink streams: rc.board_mavlink
	#
	set BOARD_RC_MAVLINK ${R}etc/init.d/rc.board_mavlink
	if [ -f $BOARD_RC_MAVLINK ]
	then
		echo "Board extras: ${BOARD_RC_MAVLINK}"
		. $BOARD_RC_MAVLINK
	fi
	unset BOARD_RC_MAVLINK

	#
	# Start UART/Serial device drivers.
	# Note: rc.serial is auto-generated from Tools/serial/generate_config.py
	#
	. ${R}etc/init.d/rc.serial

	if [ $IO_PRESENT = no ]
	then
		# Must be started after the serial config is read
		rc_input start $RC_INPUT_ARGS
	fi

	#
	# Configure vehicle type specific parameters.
	# Note: rc.vehicle_setup is the entry point for rc.interface,
	#       rc.fw_apps, rc.mc_apps, rc.rover_apps, and rc.vtol_apps.
	#
	. ${R}etc/init.d/rc.vehicle_setup

	# Camera capture driver
	if param greater -s CAM_CAP_FBACK 0
	then
		if camera_capture start
		then
			camera_capture on
		fi
	fi

	#
	# Start the navigator.
	#
	navigator start

	#
	# Start a thermal calibration if required.
	#
	. ${R}etc/init.d/rc.thermal_cal

	#
	# Start vmount to control mounts such as gimbals, disabled by default.
	#
	if ! param compare MNT_MODE_IN -1
	then
		vmount start
	fi

	# Check for flow sensor
	if param compare SENS_EN_PX4FLOW 1
	then
		px4flow start -X
	fi

	# Blacksheep telemetry
	if param greater TEL_BST_EN 0
	then
		bst start -X
	fi

	#
	# Optional board supplied extras: rc.board_extras
	#
	set BOARD_RC_EXTRAS ${R}etc/init.d/rc.board_extras
	if [ -f $BOARD_RC_EXTRAS ]
	then
		echo "Board extras: ${BOARD_RC_EXTRAS}"
		. $BOARD_RC_EXTRAS
	fi
	unset BOARD_RC_EXTRAS

	#
	# Start any custom addons from the sdcard.
	#
	if [ -f $FEXTRAS ]
	then
		echo "Addons script: ${FEXTRAS}"
		. $FEXTRAS
	fi

	#
	# Start the logger.
	#
	. ${R}etc/init.d/rc.logging

	#
	# Set additional parameters and env variables for selected AUTOSTART.
	#
	if ! param compare SYS_AUTOSTART 0
	then
		. ${R}etc/init.d/rc.autostart.post
	fi

	if ! param compare SYS_PARAM_VER ${PARAM_DEFAULTS_VER}
	then
		echo "Switched to different parameter version. Resetting parameters."
		param set SYS_PARAM_VER ${PARAM_DEFAULTS_VER}
		param set SYS_AUTOCONFIG 2
		param save
		reboot
	fi

#
# End of autostart.
#
fi

#
# Unset all script parameters to free RAM.
#
unset R
unset AUTOCNF
unset AUX_MODE
unset DATAMAN_OPT
unset FAILSAFE
unset FAILSAFE_AUX
unset FCONFIG
unset FEXTRAS
unset FMU_MODE
unset FRC
unset IO_PRESENT
unset IOFW
unset LOG_FILE
unset LOGGER_ARGS
unset LOGGER_BUF
unset MAV_TYPE
unset MIXER
unset MIXER_AUX
unset MIXER_FILE
unset MK_MODE
unset MKBLCTRL_ARG
unset OUTPUT_MODE
unset PARAM_DEFAULTS_VER
unset PARAM_FILE
unset PWM_AUX_DISARMED
unset PWM_AUX_MAX
unset PWM_AUX_MIN
unset PWM_AUX_OUT
unset PWM_AUX_RATE
unset PWM_DISARMED
unset PWM_MAX
unset PWM_MIN
unset PWM_OUT
unset PWM_RATE
unset RC_INPUT_ARGS
unset SDCARD_MIXERS_PATH
unset STARTUP_TUNE
unset USE_IO
unset VEHICLE_TYPE

#
# Boot is complete, inform MAVLink app(s) that the system is now fully up and running.
#
mavlink boot_complete

  • 下图从网络上找的的对应启动的顺序一个图示,版本不太一样,但是大致差不多

在这里插入图片描述

  • 总结:
    从上述的图片分析,可以知道,一个启动脚本实现了挂载SD卡,设置存储好的一些飞行控制的初始参数(可以通过地面站修改),启动所有的外设传感器,启动与地面站通行的Mavlink服务,以及机型的选择后对应启动的控制服务(以固定翼为例,启动了ekf2,fw_att_control,fw_pos_control_l1,airspeed_selector,land_detector等服务),打开navigator服务。

1.2 src下在固定翼模式下modules中启动的app有哪些

​ 我们可以通过地面站连接飞控,然后通过mavlink控制台,读取各个应用的工作状态,输入help可以看见一些可以使用的app, 然后在控制台输入app status可以查询其状态,通过查询得知以下src中的app被启动了:

  • airspeed_selector

  • battery_status

  • commander

  • dataman

  • 计算单元ekf2

  • fw_att_control

  • fw_pos_control_l1

  • land_detector工作在固定翼模式下

  • load_mon

  • logger

  • mavlink

  • navigator

  • rc_update

  • sensors

  • uorb

二、PX4程序架构详解——固定翼

​ 从上述分析我们知道了哪些app被启动了,接下来看一下,控制逻辑顺序,下图从网上找到的一个简化的模块使用的控制流程:

在这里插入图片描述

​ 我们可以将上图从中间分成两个看,其中右边为传感器采集(GPS、optical_flow、inertial_sensors)回来的数据,并经过一些处理(position_estimator、attitude_estimator)发布到msg消息中,供左侧控制程序订阅使用。

​ px4的控制部分程序,采用的是分层设计。

  • 用户设定commander和stickmapper生成的控制命令

  • 控制命令使navigator去生成期望的位置信息

  • pos_ctrl通过期望位置与实际位置的偏差使用PID的算法输出期望姿态信息

  • att_ctrl通过期望姿态信息与实际姿态信息使用PID输出控制信息

  • 经过混控器mixer根据机型进行力矩分配然后经过motor_driver输出实际舵面控制的pwm占空比

    下图为各个模块之间的数据流:

    在这里插入图片描述

2.1 commander

2.2 navigator

​ 摘自PX4飞控之导航及任务架构

​ Navigator模块主要功能在于确定任务类型、地理围栏、失效保护,把任务航点更新后送给位置控制器。其中task_main函数是主函数。

在这里插入图片描述

​ 在task_main 函数中,主要分为如下几个部分:

在这里插入图片描述

​ 当commander中的传输来的导航模式为mission时,依次运行mission.cpp中的三个函数:初始化on_activation()、主函数on_active()、退出函数on_inactive()。
对于mission模式的主函数on_active(),代码逻辑如下:

在这里插入图片描述

​ mission的主要功能在于对航点数组pos_sp_triplet更新和赋值,航点数组包括previous、current、next三个航点,这一功能由函数set_mission_item()来实现,主要的逻辑为先从SD卡中读取航点信息read_mission_item()赋值给结构体mission_item,然后再将当前航点复制给pos_sp_triplet.current

在这里插入图片描述

​ 每当一个航点任务完成is_mission_item_reached()返回值为true,则指针++,读取SD卡中的下一个航点。而判断航点的是否完成由三个判断条件:

在这里插入图片描述

​ 航向控制由函数heading_sp_update()实现,将航向setpoint计算赋值给pos_sp_triplet.current.yaw,给到pos控制环,进行航向控制。

在这里插入图片描述

​ 至此,导航完成了航点经纬高、航点类型、航向等信息的更新。而位置控制环以pos_sp_triplet为目标进行控制。
注:航点数组中的高度为绝对高度。

2.3 fw_pos_control_l1

2.3.1 程序框架

fw_pos_control_l1思维导图

2.3.2 总能量控制系统

摘自px4.io官网

​ 1、Total Energy Control System (TECS):总能量控制系统

​ 该模块可以同时控制固定翼飞机的真实空速和高度

在这里插入图片描述

​ 如上图所示,TECS接收空速和高度设定点作为输入,并输出油门和俯仰角设定点。 这两个输出被发送到固定翼姿态控制器,后者执行姿态控制解决方案。 因此,重要的是要了解,TECS的性能直接受变桨控制回路的性能影响。 对空速和高度的不良跟踪通常是由对飞机俯仰角的不良跟踪引起的。

​ 同时控制真实空速和高度并不是一件容易的事。 飞机俯仰角的增加将导致高度的增加,但也会导致空速的降低。 增加节气门将增加空速,但由于升力的增加,高度也会增加。 因此,我们有两个输入(俯仰角和节气门),它们都影响两个输出(空速和高度),这使控制问题变得很困难。

​ TECS通过用能量而不是原始设定值来表示问题来提供解决方案。飞机的总能量是动能和势能之和。推力(通过节气门控制)增加了飞机的总能量状态。给定的总能量状态可以通过势能和动能的任意组合来实现。换句话说,在总的能量意义上,在高海拔但以低速飞行可以等同于在低海拔但以更快的空速飞行。我们将此称为特定能量平衡,它是根据当前高度和真实空速设定点计算得出的。通过飞机俯仰角控制比能量平衡。桨距角的增加将动能转移到势能,而桨距角为负的情况则相反。因此,通过将初始设定值转换为可以独立控制的能量来消除控制问题。我们使用推力来调节车辆的总能量,而俯仰角则在势能(高度)和动能(速度)之间保持特定的平衡。

​ 2、总能量控制回路

​	[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9GQRHRyb-1603627599930)(https://dev.px4.io/master/assets/diagrams/TECS_throttle.jpg)]

​ 3、总能量平衡控制回路

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FTbk0jMB-1603627599931)(https://dev.px4.io/master/assets/diagrams/TECS_pitch.jpg)]

在这里插入图片描述

2.3.2 总能量控制系统实现(tecs_update_pitch_throttl();)
void
FixedwingPositionControl::tecs_update_pitch_throttle(const hrt_abstime &now, float alt_sp, float airspeed_sp,
		float pitch_min_rad, float pitch_max_rad,
		float throttle_min, float throttle_max, float throttle_cruise,
		bool climbout_mode, float climbout_pitch_min_rad,
		uint8_t mode)
{
   
	const float dt = math::constrain((now - _last_tecs_update) * 1e-6f, 0.01f, 0.05f);
	_last_tecs_update = now;

	// do not run TECS if we are not in air
	bool run_tecs = !_vehicle_land_detected.landed;

	// do not run TECS if vehicle is a VTOL and we are in rotary wing mode or in transition
	// (it should also not run during VTOL blending because airspeed is too low still)
	if (_vehicle_status.is_vtol) {
   
		if (_vehicle_status.vehicle_type == vehicle_status_s::VEHICLE_TYPE_ROTARY_WING || _vehicle_status.in_transition_mode) {
   
			run_tecs = false;
		}

		if (_vehicle_status.in_transition_mode) {
   
			// we're in transition
			_was_in_transition = true;

			// set this to transition airspeed to init tecs correctly
			if (_param_fw_arsp_mode.get() == 1 && PX4_ISFINITE(_param_airspeed_trans)) {
   
				// some vtols fly without airspeed sensor
				_asp_after_transition = _param_airspeed_trans;

			} else {
   
				_asp_after_transition = _airspeed;
			}

			_asp_after_transition = constrain(_asp_after_transition, _param_fw_airspd_min.get(), _param_fw_airspd_max.get());

		} else if (_was_in_transition) {
   
			// after transition we ramp up desired airspeed from the speed we had coming out of the transition
			_asp_after_transition += dt * 2; // increase 2m/s

			if (_asp_after_transition < airspeed_sp && _airspeed < airspeed_sp) {
   
				airspeed_sp = max(_asp_after_transition, _airspeed);

			} else {
   
				_was_in_transition = false;
				_asp_after_transition = 0;
			}
		}
	}

	_is_tecs_running = run_tecs;

	if (!run_tecs) {
   
		// next time we run TECS we should reinitialize states
		_reinitialize_tecs = true;
		return;
	}

	if (_reinitialize_tecs) {
   
		_tecs.reset_state();
		_reinitialize_tecs = false;
	}

	if (_vehicle_status.engine_failure) {
   
		/* Force the slow downwards spiral */
		pitch_min_rad = M_DEG_TO_RAD_F * -1.0f;
		pitch_max_rad = M_DEG_TO_RAD_F * 5.0f;
	}

	/* No underspeed protection in landing mode */
	_tecs.set_detect_underspeed_enabled(!(mode == tecs_status_s::TECS_MODE_LAND
					      || mode == tecs_status_s::TECS_MODE_LAND_THROTTLELIM));

	/* Using tecs library */
	float pitch_for_tecs = _pitch - radians(_param_fw_psp_off.get());

	/* filter speed and altitude for controller */
	Vector3f accel_body(_vehicle_acceleration_sub.get().xyz);

	// tailsitters use the multicopter frame as reference, in fixed wing
	// we need to use the fixed wing frame
	if (_vt
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值