ACfly的ctrl_positon.cpp的代码

2023-05-16

ACfly的ctrl_positon.cpp的代码

 

#include "ctrl_Attitude.hpp"
#include "ControlSystem.hpp"
#include "ctrl_Main.hpp"
#include "Parameters.hpp"
#include "MeasurementSystem.hpp"
#include "Sensors.hpp"
#include "TD4.hpp"
#include "ESO_AngularRate.hpp"
#include "ESO_h.hpp"
#include "Filters_LP.hpp"
#include "drv_PWMOut.hpp"
#include "smooth_kp.hpp"
#include "TD3_3D.hpp"
#include "vector2.hpp"
#include "Commulink.hpp"

#include "StorageSystem.hpp"

/*参数*/
	//控制参数
	struct PosCtrlCfg
	{
		//XY航线速度
		float AutoVXY[2];
		//Z航线速度
		float AutoVZ[2];
		//XYZ航线速度
		float AutoVXYZ[2];
		
		//高度前馈滤波器
		float Z_TD4P1[2];
		float Z_TD4P2[2];
		float Z_TD4P3[2];
		float Z_TD4P4[2];
		
		//位置反馈增益
		float P1[2];
		//速度反馈增益
		float P2[2];
		//加速度反馈增益
		float P3[2];
		//水平速度控制速度反馈增益
		float P2_VelXY[2];
		//水平速度控制加速度反馈增益
		float P3_VelXY[2];
		
		//最大水平速度
		float maxVelXY[2];
		//最大水平加速度
		float maxAccXY[2];
		//最大水平加加速度
		float maxJerkXY[2];
		//自动模式最大水平速度
		float maxAutoVelXY[2];
		//自动模式最大水平加速度
		float maxAutoAccXY[2];
		//自动模式最大水平加加速度
		float maxAutoJerkXY[2];
		
		//最大向上速度
		float maxVelUp[2];
		//最大向下速度
		float maxVelDown[2];
		//最大向上加速度
		float maxAccUp[2];
		//最大向下加速度
		float maxAccDown[2];
		//最大向上加加速度
		float maxJerkUp[2];
		//最大向下加加速度
		float maxJerkDown[2];
		//自动模式最大向上速度
		float maxAutoVelUp[2];
		//自动模式最大向下速度
		float maxAutoVelDown[2];
		//自动模式最大向上加速度
		float maxAutoAccUp[2];
		//自动模式最大向下加速度
		float maxAutoAccDown[2];
		//自动模式最大向上加加速度
		float maxAutoJerkUp[2];
		//自动模式最大向下加加速度
		float maxAutoJerkDown[2];
	}__PACKED;
	static PosCtrlCfg cfg;
/*参数*/	

/*参数接口*/
	float get_maxVelUp()
	{
		return cfg.maxVelUp[0];
	}
	float get_maxVelDown()
	{
		return cfg.maxVelDown[0];
	}
	float get_maxVelXY()
	{
		return cfg.maxVelXY[0];
	}
/*参数接口*/
	
/*控制接口*/
	static bool Altitude_Control_Enabled = false;
	static bool Position_Control_Enabled = false;
	
	//位置控制模式
	static Position_ControlMode Altitude_ControlMode = Position_ControlMode_Position;
	static Position_ControlMode HorizontalPosition_ControlMode = Position_ControlMode_Position;
	
	//期望TD4滤波器
	static TD4_SL Target_tracker[3];
	//期望速度低通滤波器
	static Filter_Butter4_LP TargetVelocityFilter[3];
	
	static vector3<double> target_position;
	static vector3<double> target_velocity;
	static double VelCtrlMaxRoll = -1 , VelCtrlMaxPitch = -1;
	
	/*高度*/
		bool is_Altitude_Control_Enabled( bool* ena, double TIMEOUT )
		{
			if( LockCtrl(TIMEOUT) )
			{
				*ena = Altitude_Control_Enabled;
				UnlockCtrl();
				return true;
			}
			return false;
		}
		bool Altitude_Control_Enable( double TIMEOUT )
		{
			if( get_Altitude_MSStatus() != MS_Ready )
				return false;
			
			if( LockCtrl(TIMEOUT) )
			{
				if( Altitude_Control_Enabled == true )
				{	//控制器已打开
					UnlockCtrl();
					return false;
				}
				bool isMSafe = (xTaskGetCurrentTaskHandle()==MSafeTaskHandle);
				if( !isMSafe && ForceMSafeCtrl )
				{	//屏蔽用户控制
					last_ZCtrlTime = TIME::now();
					UnlockCtrl();
					return false;
				}
				Attitude_Control_Enable();
				Altitude_ControlMode = Position_ControlMode_Locking;
				Altitude_Control_Enabled = true;
				
				//更新控制时间
				if(!isMSafe)
					last_ZCtrlTime = TIME::now();
				
				//读参数
				if( ReadParamGroup( "PosCtrl", (uint64_t*)&cfg, 0, TIMEOUT ) != PR_OK )
				{
					UnlockCtrl();
					return false;
				}				
				Position_Control_set_ZAutoSpeed(cfg.AutoVZ[0]);
				Target_tracker[2].P1 = cfg.Z_TD4P1[0];
				Target_tracker[2].P2 = cfg.Z_TD4P2[0];
				Target_tracker[2].P3 = cfg.Z_TD4P3[0];
				Target_tracker[2].P4 = cfg.Z_TD4P4[0];
				
				UnlockCtrl();
				return true;
			}
			return false;
		}
		bool Altitude_Control_Disable( double TIMEOUT )
		{
			if( LockCtrl(TIMEOUT) )
			{
				if( Altitude_Control_Enabled == false )
				{
					UnlockCtrl();
					return false;
				}
				bool isMSafe = (xTaskGetCurrentTaskHandle()==MSafeTaskHandle);
				if( ForceMSafeCtrl && !isMSafe )
				{	//屏蔽用户控制
					UnlockCtrl();
					return false;
				}
				Position_Control_Disable();
				Altitude_ControlMode = Position_ControlMode_Null;
				Altitude_Control_Enabled = false;					
				
				UnlockCtrl();
				return true;
			}
			return false;
		}
		
		bool get_Altitude_ControlMode( Position_ControlMode* mode, double TIMEOUT )
		{
			if( LockCtrl(TIMEOUT) )
			{
				bool isMSafe = (xTaskGetCurrentTaskHandle()==MSafeTaskHandle);
				if( !isMSafe && (Is_2DAutoMode(Altitude_ControlMode) || Is_3DAutoMode(Altitude_ControlMode)) )
				{	//用户控制访问且为自动模式时更新控制时间
					last_ZCtrlTime = TIME::now();
				}
				*mode = Altitude_ControlMode;
				UnlockCtrl();
				return true;
			}
			return false;
		}
		
		//设定Z自动飞行速度
		static double AutoVelZ = 200;
		bool Position_Control_set_ZAutoSpeed( double AtVelZ, double TIMEOUT )
		{
			if( isnan(AtVelZ) || isinf(AtVelZ) )
				return false;
			
			if( LockCtrl(TIMEOUT) )
			{
				AutoVelZ = AtVelZ;
				
				UnlockCtrl();
				return true;
			}
			return false;
		}
		
		//移动Z目标位置
		bool Position_Control_move_TargetPositionZRelative( double posz, double TIMEOUT )
		{
			if( isnan(posz) || isinf(posz) )
				return false;
			//必须为位置或者自动模式
			if( Altitude_ControlMode!=Position_ControlMode_Position &&
					Is_2DAutoMode(Altitude_ControlMode)==false &&
					Is_3DAutoMode(Altitude_ControlMode)==false )
				return false;
			
			bool isMSafe = (xTaskGetCurrentTaskHandle()==MSafeTaskHandle);
			if( !isMSafe )
			{	//用户控制访问更新控制时间
				last_ZCtrlTime = TIME::now();
			}
			target_position.z += posz;
			
			return true;
		}
		
		bool Position_Control_set_TargetPositionZ( double posz, double TIMEOUT )
		{
			if( isnan(posz) || isinf(posz) )
				return false;
			if( LockCtrl(TIMEOUT) )
			{
				if( Altitude_Control_Enabled == false )
				{
					UnlockCtrl();
					return false;
				}
				bool isMSafe = (xTaskGetCurrentTaskHandle()==MSafeTaskHandle);
				if( !isMSafe && ForceMSafeCtrl )
				{	//屏蔽用户控制
					last_ZCtrlTime = TIME::now();
					UnlockCtrl();
					return false;
				}
				target_position.z = posz;
				if( Is_2DAutoMode(Altitude_ControlMode)==false && Altitude_ControlMode!=Position_ControlMode_Position )
				{
					vector3<double> pos;
					get_Position(&pos);
					Target_tracker[2].x1 = pos.z;
				}
				Altitude_ControlMode = Position_ControlMode_RouteLine;
			
				//更新控制时间
				if(!isMSafe)
					last_ZCtrlTime = TIME::now();
				
				UnlockCtrl();
				return true;
			}
			return false;
		}
		bool Position_Control_set_TargetPositionZGlobal( double posz, double TIMEOUT )
		{
			if( isnan(posz) || isinf(posz) )
				return false;
			
			//获取最优全球定位传感器信息
			PosSensorHealthInf1 global_inf;
			if( get_OptimalGlobal_Z( &global_inf ) == false )
				return false;
			posz -= global_inf.HOffset;
			return Position_Control_set_TargetPositionZ( posz, TIMEOUT );
		}
		bool Position_Control_set_TargetPositionZRelative( double posz, double TIMEOUT )
		{
			if( isnan(posz) || isinf(posz) )
				return false;
			vector3<double> pos;
			if( get_Position( &pos, TIMEOUT ) == false )
				return false;
			return Position_Control_set_TargetPositionZ( pos.z + posz, TIMEOUT );
		}
		bool Position_Control_set_TargetVelocityZ( double velz, double TIMEOUT )
		{
			if( isnan(velz) || isinf(velz) )
				return false;
			if( LockCtrl(TIMEOUT) )
			{
				if( Altitude_Control_Enabled == false )
				{	//控制器未打开
					UnlockCtrl();
					return false;
				}
				bool isMSafe = (xTaskGetCurrentTaskHandle()==MSafeTaskHandle);
				if( !isMSafe && ForceMSafeCtrl )
				{	//屏蔽用户控制
					last_ZCtrlTime = TIME::now();
					UnlockCtrl();
					return false;
				}
				target_velocity.z = velz;
				Altitude_ControlMode = Position_ControlMode_Velocity;
			
				//更新控制时间
				if(!isMSafe)
					last_ZCtrlTime = TIME::now();
				
				UnlockCtrl();
				return true;
			}
			return false;
		}
		bool Position_Control_set_TargetPositionZRA( double posz, double TIMEOUT )
		{
			//获取起飞位置Z坐标
			double homeZ;
			getHomeLocalZ(&homeZ);
			return Position_Control_set_TargetPositionZ( homeZ + posz, TIMEOUT );
		}
		bool Position_Control_set_ZLock( double TIMEOUT )
		{
			vector3<double> pos;
			if( get_Position( &pos, TIMEOUT ) == false )
				return false;
			if( LockCtrl(TIMEOUT) )
			{
				if( Altitude_Control_Enabled == false )
				{	//控制器未打开
					UnlockCtrl();
					return false;
				}
				bool isMSafe = (xTaskGetCurrentTaskHandle()==MSafeTaskHandle);
				if( !isMSafe && ForceMSafeCtrl )
				{	//屏蔽用户控制
					last_ZCtrlTime = TIME::now();
					UnlockCtrl();
					return false;
				}
				if( Altitude_ControlMode != Position_ControlMode_Position )
					Altitude_ControlMode = Position_ControlMode_Locking;
				Target_tracker[2].x1 = pos.z;
				
				//更新控制时间
				if(!isMSafe)
					last_ZCtrlTime = TIME::now();
				
				UnlockCtrl();
				return true;
			}
			return false;
		}
		
		//起飞到当前高度上方的height高度
		static double TakeoffHeight;
		bool Position_Control_Takeoff_HeightRelative( double height, double TIMEOUT )
		{
			if( height < 10 )
					return false;
			bool inFlight;	get_is_inFlight(&inFlight);
			if( inFlight == true )
				return false;
			
			if( LockCtrl(TIMEOUT) )
			{
				if( Altitude_Control_Enabled == false )
				{	//控制器未打开
					UnlockCtrl();
					return false;
				}	
				bool isMSafe = (xTaskGetCurrentTaskHandle()==MSafeTaskHandle);
				if( !isMSafe && ForceMSafeCtrl )
				{	//屏蔽用户控制
					last_ZCtrlTime = TIME::now();
					UnlockCtrl();
					return false;
				}
				
				Altitude_ControlMode = Position_ControlMode_Takeoff;
				TakeoffHeight = height;
			
				//更新控制时间
				if(!isMSafe)
					last_ZCtrlTime = TIME::now();
				
				UnlockCtrl();
				return true;
			}
			return false;
		}
		bool Position_Control_Takeoff_HeightGlobal( double height, double TIMEOUT )
		{
			//获取最优全球定位传感器信息
			PosSensorHealthInf1 global_inf;
			if( get_OptimalGlobal_Z( &global_inf ) == false )
				return false;
			height -= global_inf.HOffset;
			height -= global_inf.PositionENU.z;
			return Position_Control_Takeoff_HeightRelative( height, TIMEOUT );
		}
		bool Position_Control_Takeoff_Height( double height, double TIMEOUT )
		{
			vector3<double> pos;
			get_Position(&pos);
			height = height - pos.z;
			return Position_Control_Takeoff_HeightRelative( height, TIMEOUT );
		}
	/*高度*/
		
	/*水平位置*/
		bool is_Position_Control_Enabled( bool* ena, double TIMEOUT )
		{
			if( LockCtrl(TIMEOUT) )
			{
				*ena = Position_Control_Enabled;
				UnlockCtrl();
				return true;
			}
			return false;
		}
		bool Position_Control_Enable( double TIMEOUT )
		{
			if( get_Position_MSStatus() != MS_Ready )
				return false;
			
			if( LockCtrl(TIMEOUT) )
			{
				if( Position_Control_Enabled == true )
				{	//控制器已打开
					UnlockCtrl();
					return false;
				}
				bool isMSafe = (xTaskGetCurrentTaskHandle()==MSafeTaskHandle);
				if( !isMSafe && ForceMSafeCtrl )
				{	//屏蔽用户控制
					last_XYCtrlTime = TIME::now();
					UnlockCtrl();
					return false;
				}
				Altitude_Control_Enable();
				if( Altitude_Control_Enabled == false )
				{
					UnlockCtrl();
					return false;
				}
				HorizontalPosition_ControlMode = Position_ControlMode_Locking;
				Position_Control_Enabled = true;
				
				//更新控制时间
				if(!isMSafe)
					last_XYCtrlTime = TIME::now();
				
				//读参数	
				Position_Control_set_XYAutoSpeed(cfg.AutoVXY[0]);
				Position_Control_set_XYZAutoSpeed(cfg.AutoVXYZ[0]);
				
				UnlockCtrl();
				return true;
			}
			return false;
		}
		bool Position_Control_Disable( double TIMEOUT )
		{
			if( LockCtrl(TIMEOUT) )
			{
				if( Position_Control_Enabled == false )
				{
					UnlockCtrl();
					return false;
				}
				bool isMSafe = (xTaskGetCurrentTaskHandle()==MSafeTaskHandle);
				if( ForceMSafeCtrl && !isMSafe )
				{	//屏蔽用户控制
					UnlockCtrl();
					return false;
				}
				HorizontalPosition_ControlMode = Position_ControlMode_Null;
				Position_Control_Enabled = false;		
				
				UnlockCtrl();
				return true;
			}
			return false;
		}
		
		bool get_Position_ControlMode( Position_ControlMode* mode, double TIMEOUT )
		{
			if( LockCtrl(TIMEOUT) )
			{
				bool isMSafe = (xTaskGetCurrentTaskHandle()==MSafeTaskHandle);
				if( !isMSafe && (Is_2DAutoMode(HorizontalPosition_ControlMode) || Is_3DAutoMode(HorizontalPosition_ControlMode)) )
				{	//用户控制访问且为自动模式时更新控制时间
					last_XYCtrlTime = TIME::now();
				}
				*mode = HorizontalPosition_ControlMode;
				UnlockCtrl();
				return true;
			}
			return false;
		}
		
		//设定自动飞行速度
		static double AutoVelXY = 500;
		static double AutoVelXYZ = 500;
		bool Position_Control_set_XYAutoSpeed( double AtVelXY, double TIMEOUT )
		{
			if( isnan(AtVelXY) || isinf(AtVelXY) )
				return false;
			
			if( LockCtrl(TIMEOUT) )
			{
				AutoVelXY = AtVelXY;
				
				UnlockCtrl();
				return true;
			}
			return false;
		}
		bool Position_Control_set_XYZAutoSpeed( double AtVelXYZ, double TIMEOUT )
		{
			if( isnan(AtVelXYZ) || isinf(AtVelXYZ) )
				return false;
			
			if( LockCtrl(TIMEOUT) )
			{
				AutoVelXYZ = AtVelXYZ;
				
				UnlockCtrl();
				return true;
			}
			return false;
		}
		
		bool Position_Control_set_TargetVelocityXY_AngleLimit( double velx, double vely, double maxAngle, double TIMEOUT )
		{
			if( isnan(velx) || isinf(velx) ||
					isnan(vely) || isinf(vely) ||
					isnan(maxAngle) || isinf(maxAngle)
				)
				return false;
			
			if( LockCtrl(TIMEOUT) )
			{
				if( Position_Control_Enabled == false )
				{	//控制器未打开
					UnlockCtrl();
					return false;
				}	
				
				Quaternion attitude;
				if( get_AirframeY_quat( &attitude, TIMEOUT ) == false )
				{
					UnlockCtrl();
					return false;
				}
				
				bool isMSafe = (xTaskGetCurrentTaskHandle()==MSafeTaskHandle);
				if( !isMSafe && ForceMSafeCtrl )
				{	//屏蔽用户控制
					last_XYCtrlTime = TIME::now();
					UnlockCtrl();
					return false;
				}
				
				constrain_vector( velx, vely, (double)cfg.maxVelXY[0] );
				target_velocity.x = velx;
				target_velocity.y = vely;	
				HorizontalPosition_ControlMode = Position_ControlMode_Velocity;
				VelCtrlMaxRoll = maxAngle;
				if( VelCtrlMaxRoll>=0 && VelCtrlMaxRoll<0.05 )
					VelCtrlMaxRoll = 0.05;
				VelCtrlMaxPitch = -1;

				//更新控制时间
				if(!isMSafe)
					last_XYCtrlTime = TIME::now();
			
				UnlockCtrl();
				return true;
			}
			return false;
		}
		bool Position_Control_set_TargetVelocityBodyHeadingXY_AngleLimit( double velx, double vely, double maxRoll, double maxPitch, double TIMEOUT )
		{
			if( isnan(velx) || isinf(velx) ||
					isnan(vely) || isinf(vely) ||
					isnan(maxPitch) || isinf(maxPitch) ||
					isnan(maxRoll) || isinf(maxRoll)
				)
				return false;
			
			if( LockCtrl(TIMEOUT) )
			{
				if( Position_Control_Enabled == false )
				{	//控制器未打开
					UnlockCtrl();
					return false;
				}	
				
				Quaternion attitude;
				if( get_AirframeY_quat( &attitude, TIMEOUT ) == false )
				{
					UnlockCtrl();
					return false;
				}
				
				bool isMSafe = (xTaskGetCurrentTaskHandle()==MSafeTaskHandle);
				if( !isMSafe && ForceMSafeCtrl )
				{	//屏蔽用户控制
					last_XYCtrlTime = TIME::now();
					UnlockCtrl();
					return false;
				}
				
				constrain_vector( velx, vely, (double)cfg.maxVelXY[0] );
				
				double yaw = attitude.getYaw();		
				double sin_Yaw, cos_Yaw;
				fast_sin_cos( yaw, &sin_Yaw, &cos_Yaw );
				double velx_ENU = BodyHeading2ENU_x( velx , vely , sin_Yaw , cos_Yaw );
				double vely_ENU = BodyHeading2ENU_y( velx , vely , sin_Yaw , cos_Yaw );
				
				target_velocity.x = velx_ENU;
				target_velocity.y = vely_ENU;	
				HorizontalPosition_ControlMode = Position_ControlMode_Velocity;
				VelCtrlMaxRoll = maxRoll;
				if( VelCtrlMaxRoll>=0 && VelCtrlMaxRoll<0.05 )
					VelCtrlMaxRoll = 0.05;
				VelCtrlMaxPitch = maxPitch;
				if( VelCtrlMaxPitch>=0 && VelCtrlMaxPitch < 0.05 )
					VelCtrlMaxPitch = 0.05;		

				//更新控制时间
				if(!isMSafe)
					last_XYCtrlTime = TIME::now();
			
				UnlockCtrl();
				return true;
			}
			return false;
		}
		bool Position_Control_set_XYLock( double TIMEOUT )
		{
			if( LockCtrl(TIMEOUT) )
			{
				if( Position_Control_Enabled == false )
				{
					UnlockCtrl();
					return false;
				}
				bool isMSafe = (xTaskGetCurrentTaskHandle()==MSafeTaskHandle);
				if( !isMSafe && ForceMSafeCtrl )
				{	//屏蔽用户控制
					last_XYCtrlTime = TIME::now();
					UnlockCtrl();
					return false;
				}
				if( HorizontalPosition_ControlMode != Position_ControlMode_Position )
					HorizontalPosition_ControlMode = Position_ControlMode_Locking;
				
				//更新控制时间
				if(!isMSafe)
					last_XYCtrlTime = TIME::now();
				
				UnlockCtrl();
				return true;
			}
			return false;
		}
		
		/*直线飞行*/
			//直线方程系数
			//A=(x1,y1,z1)=target_position目标点
			//B=(x2,y2,z2)=起点
			static vector3<double> route_line_A_B;	//(B-A)
			static double route_line_m;	// 1/(B-A)^2
		
			bool Position_Control_set_TargetPositionXY( double posx, double posy, double TIMEOUT )
			{
				if( isnan(posx) || isinf(posx) ||
						isnan(posy) || isinf(posy)	)
					return false;
				if( LockCtrl(TIMEOUT) )
				{
					if( Position_Control_Enabled == false )
					{
						UnlockCtrl();
						return false;
					}
					bool isMSafe = (xTaskGetCurrentTaskHandle()==MSafeTaskHandle);
					if( !isMSafe && ForceMSafeCtrl )
					{	//屏蔽用户控制
						last_XYCtrlTime = TIME::now();
						UnlockCtrl();
						return false;
					}
					target_position.x = posx;
					target_position.y = posy;
					vector3<double> position;
					get_Position(&position);
					//calculate vector B-A
					route_line_A_B = position - target_position;
					route_line_A_B.z = 0;
					double route_line_A_B_sq = route_line_A_B.get_square();
					if( route_line_A_B_sq > 0.1 )
					{
						//calculate 1/(B-A)^2
						route_line_m = 1.0 / route_line_A_B_sq;
						HorizontalPosition_ControlMode = Position_ControlMode_RouteLine;
					}
					else
						HorizontalPosition_ControlMode = Position_ControlMode_Position;
				
					//更新控制时间
					if(!isMSafe)
						last_XYCtrlTime = TIME::now();
					
					UnlockCtrl();
					return true;
				}
				return false;
			}
			
			bool Position_Control_set_TargetPositionXYZ( double posx, double posy, double posz, double TIMEOUT )
			{
				if( isnan(posx) || isinf(posx) ||
						isnan(posy) || isinf(posy) ||
						isnan(posz) || isinf(posz) )
					return false;
				if( LockCtrl(TIMEOUT) )
				{
					if( Position_Control_Enabled == false )
					{
						UnlockCtrl();
						return false;
					}
					bool isMSafe = (xTaskGetCurrentTaskHandle()==MSafeTaskHandle);
					if( !isMSafe && ForceMSafeCtrl )
					{	//屏蔽用户控制
						last_XYCtrlTime = last_ZCtrlTime = TIME::now();
						UnlockCtrl();
						return false;
					}
					target_position.x = posx;
					target_position.y = posy;
					target_position.z = posz;
					vector3<double> position;
					get_Position(&position);
					//calculate vector B-A
					route_line_A_B = position - target_position;
					double route_line_A_B_sq = route_line_A_B.get_square();
					if( route_line_A_B_sq > 0.1 )
					{
						//calculate 1/(B-A)^2
						route_line_m = 1.0 / route_line_A_B_sq;
						HorizontalPosition_ControlMode = Altitude_ControlMode = Position_ControlMode_RouteLine3D;
					}
					else
						HorizontalPosition_ControlMode = Altitude_ControlMode = Position_ControlMode_Position;
				
					//更新控制时间
					if(!isMSafe)
						last_XYCtrlTime = last_ZCtrlTime = TIME::now();
					
					UnlockCtrl();
					return true;
				}
				return false;
			}
			
			bool Position_Control_set_TargetPositionXYRelative( double posx, double posy, double TIMEOUT )
			{
				if( isnan(posx) || isinf(posx) ||
						isnan(posy) || isinf(posy)	)
					return false;
				vector3<double> position;
				get_Position(&position);
				if( LockCtrl(TIMEOUT) )
				{
					if( Position_Control_Enabled == false )
					{
						UnlockCtrl();
						return false;
					}
					bool isMSafe = (xTaskGetCurrentTaskHandle()==MSafeTaskHandle);
					if( !isMSafe && ForceMSafeCtrl )
					{	//屏蔽用户控制
						last_XYCtrlTime = TIME::now();
						UnlockCtrl();
						return false;
					}					
					target_position.x = position.x + posx;
					target_position.y = position.y + posy;				
					//calculate vector B-A
					route_line_A_B = position - target_position;
					route_line_A_B.z = 0;
					double route_line_A_B_sq = route_line_A_B.get_square();
					if( route_line_A_B_sq > 0.1 )
					{
						//calculate 1/(B-A)^2
						route_line_m = 1.0 / route_line_A_B_sq;
						HorizontalPosition_ControlMode = Position_ControlMode_RouteLine;
					}
					else
						HorizontalPosition_ControlMode = Position_ControlMode_Position;
				
					//更新控制时间
					if(!isMSafe)
						last_XYCtrlTime = TIME::now();
					
					UnlockCtrl();
					return true;
				}
				return false;
			}
			bool Position_Control_set_TargetPositionXYZRelative( double posx, double posy, double posz, double TIMEOUT )
			{
				if( isnan(posx) || isinf(posx) ||
						isnan(posy) || isinf(posy) || 
						isnan(posz) || isinf(posz) )
					return false;
				vector3<double> position;
				get_Position(&position);
				if( LockCtrl(TIMEOUT) )
				{
					if( Position_Control_Enabled == false )
					{
						UnlockCtrl();
						return false;
					}
					bool isMSafe = (xTaskGetCurrentTaskHandle()==MSafeTaskHandle);
					if( !isMSafe && ForceMSafeCtrl )
					{	//屏蔽用户控制
						last_XYCtrlTime = last_ZCtrlTime = TIME::now();
						UnlockCtrl();
						return false;
					}				
					target_position.x = position.x + posx;
					target_position.y = position.y + posy;
					target_position.z = position.z + posz;
					//calculate vector B-A
					route_line_A_B = position - target_position;
					double route_line_A_B_sq = route_line_A_B.get_square();
					if( route_line_A_B_sq > 0.1 )
					{
						//calculate 1/(B-A)^2
						route_line_m = 1.0 / route_line_A_B_sq;
						HorizontalPosition_ControlMode = Altitude_ControlMode = Position_ControlMode_RouteLine3D;
					}
					else
						HorizontalPosition_ControlMode = Altitude_ControlMode = Position_ControlMode_Position;
				
					//更新控制时间
					if(!isMSafe)
						last_XYCtrlTime = last_ZCtrlTime = TIME::now();
					
					UnlockCtrl();
					return true;
				}
				return false;
			}
			
			bool Position_Control_set_TargetPositionXYRelativeBodyheading( double posx, double posy, double TIMEOUT )
			{
				Quaternion att;
				get_Attitude_quat( &att );
				double yaw = att.getYaw();
				double sin_Yaw, cos_Yaw;
				fast_sin_cos( yaw, &sin_Yaw, &cos_Yaw );
				double posx_enu = BodyHeading2ENU_x( posx , posy , sin_Yaw , cos_Yaw );
				double posy_enu = BodyHeading2ENU_y( posx , posy , sin_Yaw , cos_Yaw );
				return Position_Control_set_TargetPositionXYRelative( posx_enu, posy_enu, TIMEOUT );
			}
			bool Position_Control_set_TargetPositionXYZRelativeBodyheading( double posx, double posy, double posz, double TIMEOUT )
			{
				Quaternion att;
				get_Attitude_quat( &att );
				double yaw = att.getYaw();
				double sin_Yaw, cos_Yaw;
				fast_sin_cos( yaw, &sin_Yaw, &cos_Yaw );
				double posx_enu = BodyHeading2ENU_x( posx , posy , sin_Yaw , cos_Yaw );
				double posy_enu = BodyHeading2ENU_y( posx , posy , sin_Yaw , cos_Yaw );
				return Position_Control_set_TargetPositionXYZRelative( posx_enu, posy_enu, posz, TIMEOUT );
			}
			
			bool Position_Control_set_TargetPositionXY_LatLon( double Lat, double Lon, double TIMEOUT )
			{
				if( isnan(Lat) || isinf(Lat) ||
						isnan(Lon) || isinf(Lon)	)
					return false;
				
				//获取最优全球定位传感器信息
				PosSensorHealthInf2 global_inf;
				if( get_OptimalGlobal_XY( &global_inf ) == false )
					return false;
				//获取指定经纬度平面坐标
				double x, y;
				map_projection_project( &global_inf.mp, Lat, Lon, &x, &y );
				x -= global_inf.HOffset.x;
				y -= global_inf.HOffset.y;
				return Position_Control_set_TargetPositionXY( x, y, TIMEOUT );
			}
			bool Position_Control_set_TargetPositionXYZ_LatLon( double Lat, double Lon, double posz, double TIMEOUT )
			{
				if( isnan(Lat) || isinf(Lat) ||
						isnan(Lon) || isinf(Lon) || 
						isnan(posz) || isinf(posz) )
					return false;
				
				//获取最优全球定位传感器信息
				PosSensorHealthInf3 global_inf;
				if( get_OptimalGlobal_XYZ( &global_inf ) == false )
					return false;
				//获取指定经纬度平面坐标
				double x, y;
				map_projection_project( &global_inf.mp, Lat, Lon, &x, &y );
				x -= global_inf.HOffset.x;
				y -= global_inf.HOffset.y;
				posz -= global_inf.HOffset.z;
				return Position_Control_set_TargetPositionXYZ( x, y, posz, TIMEOUT );
			}
			bool Position_Control_set_TargetPositionXYZRA_LatLon( double Lat, double Lon, double posz, double TIMEOUT )
			{
				if( isnan(Lat) || isinf(Lat) ||
						isnan(Lon) || isinf(Lon) || 
						isnan(posz) || isinf(posz) )
					return false;
				
				//获取最优全球定位传感器信息
				PosSensorHealthInf2 global_inf;
				if( get_OptimalGlobal_XY( &global_inf ) == false )
					return false;
				//获取指定经纬度平面坐标
				double x, y;
				map_projection_project( &global_inf.mp, Lat, Lon, &x, &y );
				x -= global_inf.HOffset.x;
				y -= global_inf.HOffset.y;
				//获取起飞位置Z坐标
				double homeZ;
				getHomeLocalZ(&homeZ);
				return Position_Control_set_TargetPositionXYZ( x, y, homeZ + posz, TIMEOUT );
			}
			bool Position_Control_set_TargetPositionXYZRelative_LatLon( double Lat, double Lon, double posz, double TIMEOUT )
			{
				if( isnan(Lat) || isinf(Lat) ||
						isnan(Lon) || isinf(Lon) || 
						isnan(posz) || isinf(posz) )
					return false;
				
				//获取最优全球定位传感器信息
				PosSensorHealthInf2 global_inf;
				if( get_OptimalGlobal_XY( &global_inf ) == false )
					return false;
				//获取指定经纬度平面坐标
				double x, y, z;
				map_projection_project( &global_inf.mp, Lat, Lon, &x, &y );
				x -= global_inf.HOffset.x;
				y -= global_inf.HOffset.y;
				z = global_inf.PositionENU.z + posz;
				return Position_Control_set_TargetPositionXYZ( x, y, z, TIMEOUT );
			}
		/*直线飞行*/
	/*水平位置*/
/*控制接口*/
		
/*滤波器*/
	static Filter_Butter4_LP ThrOut_Filters[3];
/*滤波器*/
			
void ctrl_Position()
{	
	bool Attitude_Control_Enabled;	is_Attitude_Control_Enabled(&Attitude_Control_Enabled);
	if( Attitude_Control_Enabled == false )
	{
		Altitude_Control_Enabled = false;
		Position_Control_Enabled = false;
		return;
	}
	
	double e_1_n;
	double e_1;
	double e_2_n;
	double e_2;
	
	bool inFlight;	get_is_inFlight(&inFlight);
	vector3<double> Position;	get_Position_Ctrl(&Position);
	vector3<double> VelocityENU;	get_VelocityENU_Ctrl(&VelocityENU);
	vector3<double> AccelerationENU;	get_AccelerationENU_Ctrl(&AccelerationENU);
	get_throttle_force(&AccelerationENU.z);	AccelerationENU.z-=GravityAcc;
	
	//位置速度滤波
	double Ps = cfg.P1[0];
	double Pv = cfg.P2[0];
	double Pa = cfg.P3[0];
	
	static vector3<double> TAcc;
	vector3<double> TargetVelocity;
	vector3<double> TargetVelocity_1;
	vector3<double> TargetVelocity_2;
	
	//XY或Z其中一个为非3D模式则退出3D模式
	if( Is_3DAutoMode(HorizontalPosition_ControlMode) && Is_3DAutoMode(Altitude_ControlMode)==false )
		HorizontalPosition_ControlMode = Position_ControlMode_Locking;
	else if( Is_3DAutoMode(HorizontalPosition_ControlMode)==false && Is_3DAutoMode(Altitude_ControlMode) )
		Altitude_ControlMode = Position_ControlMode_Locking;
	
	if( Position_Control_Enabled )
	{	//水平位置控制
		if( get_Position_MSStatus() != MS_Ready )
		{
			Position_Control_Enabled = false;
			goto PosCtrl_Finish;
		}
		
		switch( HorizontalPosition_ControlMode )
		{
			case Position_ControlMode_Position:
			{
				if( inFlight )
				{
					vector2<double> e1;
					e1.x = target_position.x - Position.x;
					e1.y = target_position.y - Position.y;
					vector2<double> e1_1;
					e1_1.x = - VelocityENU.x;
					e1_1.y = - VelocityENU.y;
					vector2<double> e1_2;
					e1_2.x = - TAcc.x;
					e1_2.y = - TAcc.y;
					double e1_length = safe_sqrt(e1.get_square());
					e_1_n = e1.x*e1_1.x + e1.y*e1_1.y;
					if( !is_zero(e1_length) )
						e_1 = e_1_n / e1_length;
					else
						e_1 = 0;
					e_2_n = ( e1.x*e1_2.x + e1.y*e1_2.y + e1_1.x*e1_1.x + e1_1.y*e1_1.y )*e1_length - e_1*e_1_n;
					if( !is_zero(e1_length*e1_length) )
						e_2 = e_2_n / (e1_length*e1_length);
					else
						e_2 = 0;
					smooth_kp_d2 d1 = smooth_kp_2( e1_length, e_1, e_2 , Ps, 200 );
					vector2<double> T2;
					vector2<double> T2_1;
					vector2<double> T2_2;
					if( !is_zero(e1_length*e1_length*e1_length) )
					{
						vector2<double> n = e1 * (1.0/e1_length);
						vector2<double> n_1 = (e1_1*e1_length - e1*e_1) / (e1_length*e1_length);
						vector2<double> n_2 = ( (e1_2*e1_length-e1*e_2)*e1_length - (e1_1*e1_length-e1*e_1)*(2*e_1) ) / (e1_length*e1_length*e1_length);
						T2 = n*d1.d0;
						T2_1 = n*d1.d1 + n_1*d1.d0;
						T2_2 = n*d1.d2 + n_1*(2*d1.d1) + n_2*d1.d0;
					}
					TargetVelocity.x = T2.x;	TargetVelocity.y = T2.y;
					TargetVelocity_1.x = T2_1.x;	TargetVelocity_1.y = T2_1.y;
					TargetVelocity_2.x = T2_2.x;	TargetVelocity_2.y = T2_2.y;
				}
				else
				{
					//没起飞前在位置控制模式
					//重置期望位置
					target_position.x = Position.x;
					target_position.y = Position.y;
					Attitude_Control_set_Target_RollPitch( 0, 0 );
					goto PosCtrl_Finish;
				}
				break;
			}		
			case Position_ControlMode_Velocity:
			{
				if( !inFlight )
				{
					//没起飞时重置期望速度
					Attitude_Control_set_Target_RollPitch( 0, 0 );
					goto PosCtrl_Finish;
				}
				else
				{
					TargetVelocity.x = target_velocity.x;
					TargetVelocity.y = target_velocity.y;
					Pv = cfg.P2_VelXY[0];
				}
				break;
			}
			
			case Position_ControlMode_RouteLine:
			{
				if( inFlight )
				{
					//计算垂足
					vector2<double> A( target_position.x, target_position.y );
					vector2<double> C( Position.x, Position.y );
					vector2<double> A_C = C - A;
					vector2<double> A_B( route_line_A_B.x, route_line_A_B.y );
					double k = (A_C * A_B) * route_line_m;
					vector2<double> foot_point = (A_B * k) + A;
					
					//计算偏差
					vector2<double> e1r = A - foot_point;
					vector2<double> e1d = foot_point - C;
					double e1r_length = safe_sqrt(e1r.get_square());
					double e1d_length = safe_sqrt(e1d.get_square());
					
					//计算route方向单位向量
					vector2<double> route_n;
					if( e1r_length > 0.001 )
						route_n = e1r * (1.0/e1r_length);
					
					//计算d方向单位向量
					vector2<double> d_n;
					if( e1d_length > 0.001 )
						d_n = e1d * (1.0/e1d_length);
					
					//计算e1导数
					vector2<double> e1_1( VelocityENU.x, VelocityENU.y );
					double e1r_1 = -(e1_1 * route_n);
					double e1d_1 = -(e1_1 * d_n);
					//e1二阶导
					vector2<double> e1_2( TAcc.x, TAcc.y );
					double e1r_2 = -(e1_2 * route_n);
					double e1d_2 = -(e1_2 * d_n);
					
					/*route方向*/
						smooth_kp_d2 d1r = smooth_kp_2( e1r_length, e1r_1, e1r_2 , Ps, AutoVelXY );
						vector2<double> T2r = route_n * d1r.d0;
						vector2<double> T2r_1 = route_n * d1r.d1;
						vector2<double> T2r_2 = route_n * d1r.d2;
					/*route方向*/
					
					/*d方向*/
						smooth_kp_d2 d1d = smooth_kp_2( e1d_length, e1d_1, e1d_2 , Ps, AutoVelXY );
						vector2<double> T2d = d_n * d1d.d0;
						vector2<double> T2d_1 = d_n * d1d.d1;
						vector2<double> T2d_2 = d_n * d1d.d2;
					/*d方向*/
						
					TargetVelocity.x = T2r.x+T2d.x;	TargetVelocity.y = T2r.y+T2d.y;
					TargetVelocity_1.x = T2r_1.x+T2d_1.x;	TargetVelocity_1.y = T2r_1.y+T2d_1.y;
					TargetVelocity_2.x = T2r_2.x+T2d_2.x;	TargetVelocity_2.y = T2r_2.y+T2d_2.y;
						
					if( e1r.get_square() + e1d.get_square() < 20*20 )
						HorizontalPosition_ControlMode = Position_ControlMode_Position;
				}
				else
				{
					//没起飞时重置期望速度
					Attitude_Control_set_Target_RollPitch( 0, 0 );
					return;
				}
				break;
			}
			
			case Position_ControlMode_RouteLine3D:
			{
				if( inFlight )
				{
					//计算垂足
					vector3<double> A_C = Position - target_position;
					double k = (A_C * route_line_A_B) * route_line_m;
					vector3<double> foot_point = (route_line_A_B * k) + target_position;
					
					//计算偏差
					vector3<double> e1r = target_position - foot_point;
					vector3<double> e1d = foot_point - Position;
					double e1r_length = safe_sqrt(e1r.get_square());
					double e1d_length = safe_sqrt(e1d.get_square());
					
					//计算route方向单位向量
					vector3<double> route_n;
					if( e1r_length > 0.001 )
						route_n = e1r * (1.0/e1r_length);
					
					//计算e1导数
					double e1r_1_length = -(VelocityENU * route_n);	
					vector3<double> e1r_1 = route_n * e1r_1_length;					
					vector3<double> e1d_1 = -(VelocityENU + e1r_1);
					//e1二阶导
					vector3<double> e1_2( TAcc.x, TAcc.y, AccelerationENU.z );
					double e1r_2_length = -(e1_2 * route_n);
					vector3<double> e1r_2 = route_n * e1r_2_length;					
					vector3<double> e1d_2 = -(e1_2 + e1r_2);
					
					/*route方向*/
						smooth_kp_d2 d1r = smooth_kp_2( e1r_length, e1r_1_length, e1r_2_length , Ps, AutoVelXYZ );
						vector3<double> T2r = route_n * d1r.d0;
						vector3<double> T2r_1 = route_n * d1r.d1;
						vector3<double> T2r_2 = route_n * d1r.d2;
					/*route方向*/
					
					/*d方向*/
						e_1_n = e1d.x*e1d_1.x + e1d.y*e1d_1.y + e1d.z*e1d_1.z;
						if( !is_zero(e1d_length) )
							e_1 = e_1_n / e1d_length;
						else
							e_1 = 0;
						e_2_n = ( e1d.x*e1d_2.x + e1d.y*e1d_2.y + e1d.z*e1d_2.z + e1d_1.x*e1d_1.x + e1d_1.y*e1d_1.y + e1d_1.z*e1d_1.z )*e1d_length - e_1*e_1_n;
						if( !is_zero(e1d_length*e1d_length) )
							e_2 = e_2_n / (e1d_length*e1d_length);
						else
							e_2 = 0;
						smooth_kp_d2 d1d = smooth_kp_2( e1d_length, e_1, e_2 , Ps, AutoVelXYZ );
						vector3<double> T2d;
						vector3<double> T2d_1;
						vector3<double> T2d_2;
						if( !is_zero(e1d_length*e1d_length*e1d_length) )
						{
							vector3<double> n = e1d * (1.0/e1d_length);
							vector3<double> n_1 = (e1d_1*e1d_length - e1d*e_1) / (e1d_length*e1d_length);
							vector3<double> n_2 = ( (e1d_2*e1d_length-e1d*e_2)*e1d_length - (e1d_1*e1d_length-e1d*e_1)*(2*e_1) ) / (e1d_length*e1d_length*e1d_length);
							T2d = n*d1d.d0;
							T2d_1 = n*d1d.d1 + n_1*d1d.d0;
							T2d_2 = n*d1d.d2 + n_1*(2*d1d.d1) + n_2*d1d.d0;
						}
					/*d方向*/
						
					TargetVelocity = T2r + T2d;
					TargetVelocity_1 = T2r_1 + T2d_1;
					TargetVelocity_2 = T2r_2 + T2d_2;
						
					if( e1r.get_square() + e1d.get_square() < 20*20 )
						HorizontalPosition_ControlMode = Altitude_ControlMode = Position_ControlMode_Position;
				}
				else
				{
					//没起飞时重置期望速度
					Attitude_Control_set_Target_RollPitch( 0, 0 );
					return;
				}
				break;
			}
			
			case Position_ControlMode_Locking:
			default:
			{	//刹车锁位置
				static uint16_t lock_counter = 0;
				if( inFlight )
				{					
					TargetVelocity.x = 0;
					TargetVelocity.y = 0;
					if( VelocityENU.x*VelocityENU.x + VelocityENU.y*VelocityENU.y < 10*10 )
					{
						if( ++lock_counter >= CtrlRateHz*0.7 )
						{
							lock_counter = 0;
							target_position.x = Position.x;
							target_position.y = Position.y;
							HorizontalPosition_ControlMode = Position_ControlMode_Position;
						}
					}
					else
						lock_counter = 0;
				}
				else
				{
					lock_counter = 0;
					target_position.x = Position.x;
					target_position.y = Position.y;
					HorizontalPosition_ControlMode = Position_ControlMode_Position;
					Attitude_Control_set_Target_RollPitch( 0, 0 );
					return;
				}
				break;
			}
		}	
		
		//计算期望加速度
		vector2<double> e2;
		e2.x = TargetVelocity.x - VelocityENU.x;
		e2.y = TargetVelocity.y - VelocityENU.y;
		vector2<double> e2_1;
		e2_1.x = TargetVelocity_1.x - TAcc.x;
		e2_1.y = TargetVelocity_1.y - TAcc.y;
		double e2_length = safe_sqrt(e2.get_square());
		e_1_n = e2.x*e2_1.x + e2.y*e2_1.y;
		if( !is_zero(e2_length) )
			e_1 = e_1_n / e2_length;
		else
			e_1 = 0;
		smooth_kp_d1 d2;
		if( Is_AutoMode(HorizontalPosition_ControlMode) )
			d2 = smooth_kp_1( e2_length, e_1 , Pv, cfg.maxAutoAccXY[0] );
		else
			d2 = smooth_kp_1( e2_length, e_1 , Pv, cfg.maxAccXY[0] );
		vector2<double> T3;
		vector2<double> T3_1;
		if( !is_zero(e2_length*e2_length) )
		{
			vector2<double> n = e2 * (1.0/e2_length);
			vector2<double> n_1 = (e2_1*e2_length - e2*e_1) / (e2_length*e2_length);
			T3 = n*d2.d0;
			T3_1 = n*d2.d1 + n_1*d2.d0;
		}
		T3 += vector2<double>( TargetVelocity_1.x, TargetVelocity_1.y );
		T3_1 += vector2<double>( TargetVelocity_2.x, TargetVelocity_2.y );
		
		vector2<double> e3;
		e3.x = T3.x - TAcc.x;
		e3.y = T3.y - TAcc.y;
		double e3_length = safe_sqrt(e3.get_square());
		double d3;
		if( Is_AutoMode(HorizontalPosition_ControlMode) )
			d3 = smooth_kp_0( e3_length , Pa, cfg.maxAutoJerkXY[0] );
		else
			d3 = smooth_kp_0( e3_length , Pa, cfg.maxJerkXY[0] );
		vector2<double> T4;
		if( !is_zero(e3_length) )
		{
			vector2<double> n = e3 * (1.0/e3_length);
			T4 = n*d3;
		}
		if( Is_AutoMode(HorizontalPosition_ControlMode) )
			T4.constrain( cfg.maxAutoJerkXY[0] );
		else
			T4.constrain( cfg.maxJerkXY[0] );
		T4 += T3_1;
		
		TAcc.x += T4.x*(1.0/CtrlRateHz);
		TAcc.y += T4.y*(1.0/CtrlRateHz);	
		
		//去除风力扰动
		vector3<double> WindDisturbance;
		get_WindDisturbance( &WindDisturbance );
		vector2<double> target_acceleration;
//		target_acceleration.x = TAcc.x - WindDisturbance.x;
//		target_acceleration.y = TAcc.y - WindDisturbance.y;
		target_acceleration.x = T3.x - WindDisturbance.x;
		target_acceleration.y = T3.y - WindDisturbance.y;
		
		//旋转至Bodyheading
		Quaternion attitude;
		get_Attitude_quat(&attitude);
		double yaw = attitude.getYaw();		
		double sin_Yaw, cos_Yaw;
		fast_sin_cos( yaw, &sin_Yaw, &cos_Yaw );
		double target_acceleration_x_bodyheading = ENU2BodyHeading_x( target_acceleration.x , target_acceleration.y , sin_Yaw , cos_Yaw );
		double target_acceleration_y_bodyheading = ENU2BodyHeading_y( target_acceleration.x , target_acceleration.y , sin_Yaw , cos_Yaw );
//		target_acceleration_x_bodyheading = ThrOut_Filters[0].run(target_acceleration_x_bodyheading);
//		target_acceleration_y_bodyheading = ThrOut_Filters[1].run(target_acceleration_y_bodyheading);
		
		//计算风力补偿角度
		double WindDisturbance_Bodyheading_x = ENU2BodyHeading_x( WindDisturbance.x , WindDisturbance.y , sin_Yaw , cos_Yaw );
		double WindDisturbance_Bodyheading_y = ENU2BodyHeading_y( WindDisturbance.x , WindDisturbance.y , sin_Yaw , cos_Yaw );
		//计算角度
		double AccUp = GravityAcc + AccelerationENU.z;
		double AntiDisturbancePitch = atan2( -WindDisturbance_Bodyheading_x , AccUp );
		double AntiDisturbanceRoll = atan2( WindDisturbance_Bodyheading_y , AccUp );
		
		//计算目标角度
		double target_Roll = atan2( -target_acceleration_y_bodyheading , AccUp );
		double target_Pitch = atan2( target_acceleration_x_bodyheading , AccUp );
		if( HorizontalPosition_ControlMode==Position_ControlMode_Velocity )
		{	//角度限幅
			if( VelCtrlMaxRoll>0 && VelCtrlMaxPitch>0 )
			{
				target_Roll = constrain( target_Roll , AntiDisturbanceRoll - VelCtrlMaxRoll, AntiDisturbanceRoll + VelCtrlMaxRoll );
				target_Pitch = constrain( target_Pitch , AntiDisturbancePitch - VelCtrlMaxPitch, AntiDisturbancePitch + VelCtrlMaxPitch );
			}
			else if( VelCtrlMaxRoll>0 )
			{
				vector2<double> Tangle( target_Roll - AntiDisturbanceRoll, target_Pitch - AntiDisturbancePitch );
				Tangle.constrain(VelCtrlMaxRoll);
				target_Roll = AntiDisturbanceRoll + Tangle.x;
				target_Pitch = AntiDisturbancePitch + Tangle.y;
			}
		}

		//设定目标角度
		Attitude_Control_set_Target_RollPitch( target_Roll, target_Pitch );
		
		//获取真实目标角度修正TAcc
		Attitude_Control_get_Target_RollPitch( &target_Roll, &target_Pitch );
		target_acceleration_x_bodyheading = tan(target_Pitch)*GravityAcc;
		target_acceleration_y_bodyheading = -tan(target_Roll)*GravityAcc;
		target_acceleration.x = BodyHeading2ENU_x( target_acceleration_x_bodyheading, target_acceleration_y_bodyheading , sin_Yaw, cos_Yaw );
		target_acceleration.y = BodyHeading2ENU_y( target_acceleration_x_bodyheading, target_acceleration_y_bodyheading , sin_Yaw, cos_Yaw );
		TAcc.x = target_acceleration.x + WindDisturbance.x;
		TAcc.y = target_acceleration.y + WindDisturbance.y;
	}//水平位置控制
	else
	{
		ThrOut_Filters[0].reset(0);
		ThrOut_Filters[1].reset(0);
	}
	
PosCtrl_Finish:	
	if( Altitude_Control_Enabled )
	{//高度控制
			
		//设置控制量限幅
		Target_tracker[2].r2p = cfg.maxVelUp[0];
		Target_tracker[2].r2n = cfg.maxVelDown[0];
		Target_tracker[2].r3p = cfg.maxAccUp[0];
		Target_tracker[2].r3n = cfg.maxAccDown[0];
		Target_tracker[2].r4p = cfg.maxJerkUp[0];
		Target_tracker[2].r4n = cfg.maxJerkDown[0];
		
		if( !Is_3DAutoMode(Altitude_ControlMode) )
		{
			switch( Altitude_ControlMode )
			{
				case Position_ControlMode_Position:
				{	//控制位置
					if( inFlight )
					{
						Target_tracker[2].r2p = 0.3*cfg.maxVelUp[0];
						Target_tracker[2].r2n = 0.3*cfg.maxVelDown[0];
						Target_tracker[2].track4( target_position.z , 1.0 / CtrlRateHz );
					}
					else
					{
						//没起飞前在位置控制模式
						//不要起飞
						Target_tracker[2].reset();
						target_position.z = Target_tracker[2].x1 = Position.z;
						Attitude_Control_set_Throttle( get_STThrottle() );
						goto AltCtrl_Finish;
					}
					break;
				}
				case Position_ControlMode_Velocity:
				{	//控制速度
					if( inFlight || target_velocity.z > 0 )
					{
						double TVel;
						if( target_velocity.z > cfg.maxVelUp[0] )
							TVel = cfg.maxVelUp[0];
						else if( target_velocity.z < -cfg.maxVelDown[0] )
							TVel = -cfg.maxVelDown[0];
						else
							TVel = target_velocity.z;
						Target_tracker[2].track3( TVel , 1.0 / CtrlRateHz );
					}
					else
					{
						//没起飞且期望速度为负
						//不要起飞
						Target_tracker[2].reset();
						Target_tracker[2].x1 = Position.z;
						Attitude_Control_set_Throttle( get_STThrottle() );
						goto AltCtrl_Finish;
					}
					break;
				}
				
				case Position_ControlMode_Takeoff:
				{	//起飞
					
					//设置控制量最大值
					Target_tracker[2].r3p = cfg.maxAutoAccUp[0];
					Target_tracker[2].r3n = cfg.maxAutoAccDown[0];
					Target_tracker[2].r4p = cfg.maxAutoJerkUp[0];
					Target_tracker[2].r4n = cfg.maxAutoJerkDown[0];
					
					if( inFlight )
					{
						//已起飞
						//控制达到目标高度
						double homeZ;
						getHomeLocalZ(&homeZ);
						if( Position.z - homeZ < 100 )
							Target_tracker[2].r2n = Target_tracker[2].r2p = 50;
						else
							Target_tracker[2].r2n = Target_tracker[2].r2p = ( AutoVelZ < cfg.maxAutoVelUp[0] ) ? AutoVelZ : cfg.maxAutoVelUp[0];
						Target_tracker[2].track4( target_position.z , 1.0 / CtrlRateHz );
						if( fabs( target_position.z - Position.z ) < 10 && \
								in_symmetry_range( Target_tracker[2].x2 , 0.1 ) && \
								in_symmetry_range( Target_tracker[2].x3 , 0.1 )	)
							Altitude_ControlMode = Position_ControlMode_Position;
					}
					else
					{
						//未起飞
						//等待起飞
						target_position.z =  Position.z + TakeoffHeight;
						Target_tracker[2].x1 = Position.z;
						Target_tracker[2].track3( 50 , 1.0 / CtrlRateHz );
					}
					break;
				}
				case Position_ControlMode_RouteLine:
				{	//飞到指定高度
					
					//设置控制量最大值
					Target_tracker[2].r3p = cfg.maxAutoAccUp[0];
					Target_tracker[2].r3n = cfg.maxAutoAccDown[0];
					Target_tracker[2].r4p = cfg.maxAutoJerkUp[0];
					Target_tracker[2].r4n = cfg.maxAutoJerkDown[0];
					
					if( inFlight )
					{
						//已起飞
						//控制达到目标高度
						Target_tracker[2].r2n = Target_tracker[2].r2p = AutoVelZ;
						Target_tracker[2].track4( target_position.z , 1.0f / CtrlRateHz );
						if( fabs( target_position.z - Position.z ) < 10 && \
								in_symmetry_range( VelocityENU.z , 10.0f ) &&  \
								in_symmetry_range( AccelerationENU.z , 50.0f ) && \
								in_symmetry_range( Target_tracker[2].x2 , 0.1f ) && \
								in_symmetry_range( Target_tracker[2].x3 , 0.1f )	)
							Altitude_ControlMode = Position_ControlMode_Position;
					}
					else
					{
						//未起飞
						//不要起飞
						Target_tracker[2].reset();
						Target_tracker[2].x1 = Position.z;
						Attitude_Control_set_Throttle( 0 );
						goto AltCtrl_Finish;
					}
					break;
				}
				
				case Position_ControlMode_Locking:
				default:
				{	//锁位置(减速到0然后锁住高度)
					if( inFlight )
					{
						Target_tracker[2].track3( 0 , 1.0 / CtrlRateHz );
						if( in_symmetry_range( VelocityENU.z , 10.0 ) && \
								in_symmetry_range( Target_tracker[2].x2 , 0.1 ) && \
								in_symmetry_range( Target_tracker[2].x3 , 0.1 )	)
						{
							target_position.z = Target_tracker[2].x1;
							Altitude_ControlMode = Position_ControlMode_Position;
						}
					}
					else
					{
						Altitude_ControlMode = Position_ControlMode_Position;
						Attitude_Control_set_Throttle( get_STThrottle() );
						goto AltCtrl_Finish;
					}
					break;
				}
			}
		}
		
		if( inFlight )
		{
			//计算期望速度
			double target_velocity_z;
			//期望垂直速度的导数
			double Tvz_1, Tvz_2;
			if( Is_3DAutoMode(Altitude_ControlMode) )
			{
				target_velocity_z = TargetVelocity.z;
				Tvz_1 = TargetVelocity_1.z;
				Tvz_2 = TargetVelocity_2.z;
				Target_tracker[2].reset();
				Target_tracker[2].x1 = target_position.z;
			}
			else
			{
				if( Target_tracker[2].get_tracking_mode() == 4 )
				{
					double max_fb_vel = ( Target_tracker[2].x1 - Position.z ) > 0 ? cfg.maxAutoVelUp[0] : cfg.maxAutoVelDown[0];
					smooth_kp_d2 TvFb = smooth_kp_2(
							Target_tracker[2].x1 - Position.z,
							Target_tracker[2].x2 - VelocityENU.z, 
							Target_tracker[2].x3 - AccelerationENU.z, 
							Ps, max_fb_vel );
					target_velocity_z = TvFb.d0 + Target_tracker[2].x2;
					Tvz_1 = TvFb.d1 + Target_tracker[2].x3;
					Tvz_2 = TvFb.d2 + Target_tracker[2].x4;
				}
				else
				{
					target_velocity_z = Target_tracker[2].x2;
					Tvz_1 = Target_tracker[2].x3;
					Tvz_2 = Target_tracker[2].x4;
				}
			}
			
			//计算期望加速度
			double max_fb_acc = ( target_velocity_z - VelocityENU.z ) > 0 ? cfg.maxAutoAccUp[0] : cfg.maxAutoAccDown[0];
			smooth_kp_d1 TaFb = smooth_kp_1(
					target_velocity_z - VelocityENU.z,
					Tvz_1 - AccelerationENU.z, 
					Pv, max_fb_acc );
			double target_acceleration_z = TaFb.d0 + Tvz_1;
			double target_acceleration_z_1 = TaFb.d1 + Tvz_2;
			//target_acceleration_z = TargetVelocityFilter[2].run( target_acceleration_z );
			//加速度误差
			double acceleration_z_error = target_acceleration_z - AccelerationENU.z;
			
			//获取倾角cosin
			Quaternion quat;
			get_Airframe_quat(&quat);
			double lean_cosin = quat.get_lean_angle_cosin();
			
			//获取电机起转油门
			double MotorStartThrottle = get_STThrottle();
			//获取悬停油门 - 电机起转油门
			double hover_throttle;
			get_hover_throttle(&hover_throttle);
			hover_throttle = hover_throttle - MotorStartThrottle;	
			
			//计算输出油门
			double force, T, b;
			get_throttle_force(&force);
			get_ESO_height_T(&T);
			get_throttle_b(&b);
			if( force < 1 )
				force = 1;
			double throttle = ( force + T * ( acceleration_z_error * Pa + target_acceleration_z_1 ) )/b;
			//倾角补偿
			if( lean_cosin > 0.1 )				
				throttle /= lean_cosin;
			else	//倾角太大
				throttle = (100 - MotorStartThrottle) / 2;
			
			if( inFlight )
			{
				double logbuf[10];
				logbuf[0] = throttle;
				logbuf[1] = hover_throttle;
				logbuf[2] = force;
				logbuf[3] = target_acceleration_z;
				logbuf[4] = AccelerationENU.z;
				SDLog_Msg_DebugVect( "thr", logbuf, 5 );
			}
			
			//油门限幅
			throttle += MotorStartThrottle;
			if( throttle > 90 )
				throttle = 90;
			if( inFlight )
			{
				if( throttle < MotorStartThrottle )
					throttle = MotorStartThrottle;
			}
			
			//侧翻保护
			static uint32_t RollOverProtectCounter = 0;
			if( lean_cosin < 0 )
			{
				if( ++RollOverProtectCounter >= CtrlRateHz*3 )
				{
					RollOverProtectCounter = CtrlRateHz*3;
					throttle = 0;
				}
			}
			else
				RollOverProtectCounter = 0;
			
//			throttle = ThrOut_Filters[2].run(throttle);
			//输出
			Attitude_Control_set_Throttle( throttle );
		}
		else
		{
			//没起飞
			//均匀增加油门起飞
			double throttle;
			get_Target_Throttle(&throttle);
			ThrOut_Filters[2].reset(throttle);
			Attitude_Control_set_Throttle( throttle + 1.0/CtrlRateHz * 15 );
		}
		
	}//高度控制
AltCtrl_Finish:
	return;
}

void init_Ctrl_Position()
{
	//初始化期望TD4滤波器
	Target_tracker[0] = TD4_SL( 15 , 15 , 15 , 15 );
	Target_tracker[1] = TD4_SL( 15 , 15 , 15 , 15 );
	Target_tracker[2] = TD4_SL( 1 , 2 , 50 , 60 );	
	Target_tracker[2].r3p = 900;
	Target_tracker[2].r3n = 600;
	
	//初始化期望速度低通滤波器
	TargetVelocityFilter[0].set_cutoff_frequency( CtrlRateHz , 10 );
	TargetVelocityFilter[1].set_cutoff_frequency( CtrlRateHz , 10 );
	TargetVelocityFilter[2].set_cutoff_frequency( CtrlRateHz , 10 );
	
	/*初始化参数*/
		PosCtrlCfg initial_cfg;
		//XY航线速度
		initial_cfg.AutoVXY[0] = 500;
		//Z航线速度
		initial_cfg.AutoVZ[0] = 200;
		//XYZ航线速度
		initial_cfg.AutoVXYZ[0] = 500;	
		
		//高度前馈滤波器
		initial_cfg.Z_TD4P1[0] = 1;
		initial_cfg.Z_TD4P2[0] = 5;
		initial_cfg.Z_TD4P3[0] = 50;
		initial_cfg.Z_TD4P4[0] = 60;
		
		//位置反馈增益
		initial_cfg.P1[0] = 1;
		//速度反馈增益
		initial_cfg.P2[0] = 2;
		//加速度反馈增益
		initial_cfg.P3[0] = 10;
		//水平速度控制速度反馈增益
		initial_cfg.P2_VelXY[0] = 4;
		//水平速度控制加速度反馈增益
		initial_cfg.P3_VelXY[0] = 25;
		
		//最大水平速度
		initial_cfg.maxVelXY[0] = 1500;
		//最大水平加速度
		initial_cfg.maxAccXY[0] = 600;
		//最大水平加加速度
		initial_cfg.maxJerkXY[0] = 3000;
		//自动模式最大水平速度
		initial_cfg.maxAutoVelXY[0] = 1200;
		//自动模式最大水平加速度
		initial_cfg.maxAutoAccXY[0] = 300;
		//自动模式最大水平加加速度
		initial_cfg.maxAutoJerkXY[0] = 600;
		
		//最大向上速度
		initial_cfg.maxVelUp[0] = 250;
		//最大向下速度
		initial_cfg.maxVelDown[0] = 200;
		//最大向上加速度
		initial_cfg.maxAccUp[0] = 800;
		//最大向下加速度
		initial_cfg.maxAccDown[0] = 600;
		//最大向上加加速度
		initial_cfg.maxJerkUp[0] = 5000;
		//最大向下加加速度
		initial_cfg.maxJerkDown[0] = 3000;		
		//自动模式最大向上速度
		initial_cfg.maxAutoVelUp[0] = 200;
		//自动模式最大向下速度
		initial_cfg.maxAutoVelDown[0] = 200;
		//自动模式最大向上加速度
		initial_cfg.maxAutoAccUp[0] = 250;
		//自动模式最大向下加速度
		initial_cfg.maxAutoAccDown[0] = 200;
		//自动模式最大向上加加速度
		initial_cfg.maxAutoJerkUp[0] = 800;
		//自动模式最大向下加加速度
		initial_cfg.maxAutoJerkDown[0] = 800;
	/*初始化参数*/

	SName param_names[] = {
		//XY航线速度
		"PC_AutoVXY" ,	
		//Z航线速度
		"PC_AutoVZ" ,	
		//XYZ航线速度
		"PC_AutoVXYZ" ,	
		
		//高度前馈滤波器
		"PC_Z_TD4P1" ,
		"PC_Z_TD4P2" ,
		"PC_Z_TD4P3" ,
		"PC_Z_TD4P4" ,
		
		//位置反馈增益
		"PC_P1" ,
		//速度反馈增益
		"PC_P2" ,
		//加速度反馈增益
		"PC_P3" ,
		//水平速度控制速度反馈增益
		"PC_P2VelXY" ,
		//水平速度控制加速度反馈增益
		"PC_P3VelXY" ,
		
		//最大水平速度
		"PC_maxVelXY" ,
		//最大水平加速度
		"PC_maxAccXY" ,
		//最大水平加加速度
		"PC_maxJerkXY" ,
		//自动模式最大水平速度
		"PC_maxAutoVelXY" ,
		//自动模式最大水平加速度
		"PC_maxAutoAccXY" ,
		//自动模式最大水平加加速度
		"PC_maxAutoJerkXY" ,
		
		//最大向上速度
		"PC_maxVelUp" ,
		//最大向下速度
		"PC_maxVelDn" ,
		//最大向上加速度
		"PC_maxAccUp" ,
		//最大向下加速度
		"PC_maxAccDn" ,
		//最大向上加加速度
		"PC_maxJerkUp" ,
		//最大向下加加速度
		"PC_maxJerkDn" ,
		//自动模式最大向上速度
		"PC_maxAutoVelUp" ,
		//自动模式最大向下速度
		"PC_maxAutoVelDn" ,
		//自动模式最大向上加速度
		"PC_maxAutoAccUp" ,
		//自动模式最大向下加速度
		"PC_maxAutoAccDn" ,
		//自动模式最大向上加加速度
		"PC_maxAutoJerkUp" ,
		//自动模式最大向下加加速度
		"PC_maxAutoJerkDn" ,
	};

	MAV_PARAM_TYPE param_types[] = {
		//XY航线速度
		MAV_PARAM_TYPE_REAL32 ,	
		//Z航线速度
		MAV_PARAM_TYPE_REAL32 ,	
		//XYZ航线速度
		MAV_PARAM_TYPE_REAL32 ,	
		//高度前馈滤波器
		MAV_PARAM_TYPE_REAL32 ,
		MAV_PARAM_TYPE_REAL32 ,
		MAV_PARAM_TYPE_REAL32 ,
		MAV_PARAM_TYPE_REAL32 ,
		
		//位置反馈增益
		MAV_PARAM_TYPE_REAL32 ,
		//速度反馈增益
		MAV_PARAM_TYPE_REAL32 ,
		//加速度反馈增益
		MAV_PARAM_TYPE_REAL32 ,
		//水平速度控制速度反馈增益
		MAV_PARAM_TYPE_REAL32 ,
		//水平速度控制加速度反馈增益
		MAV_PARAM_TYPE_REAL32 ,
		
		//最大水平速度
		MAV_PARAM_TYPE_REAL32 ,
		//最大水平加速度
		MAV_PARAM_TYPE_REAL32 ,
		//最大水平加加速度
		MAV_PARAM_TYPE_REAL32 ,
		//自动模式最大水平速度
		MAV_PARAM_TYPE_REAL32 ,
		//自动模式最大水平加速度
		MAV_PARAM_TYPE_REAL32 ,
		//自动模式最大水平加加速度
		MAV_PARAM_TYPE_REAL32 ,
		
		//最大向上速度
		MAV_PARAM_TYPE_REAL32 ,
		//最大向下速度
		MAV_PARAM_TYPE_REAL32 ,
		//最大向上加速度
		MAV_PARAM_TYPE_REAL32 ,
		//最大向下加速度
		MAV_PARAM_TYPE_REAL32 ,
		//最大向上加加速度
		MAV_PARAM_TYPE_REAL32 ,
		//最大向下加加速度
		MAV_PARAM_TYPE_REAL32 ,	
		//自动模式最大向上速度
		MAV_PARAM_TYPE_REAL32 ,
		//自动模式最大向下速度
		MAV_PARAM_TYPE_REAL32 ,
		//自动模式最大向上加速度
		MAV_PARAM_TYPE_REAL32 ,
		//自动模式最大向下加速度
		MAV_PARAM_TYPE_REAL32 ,
		//自动模式最大向上加加速度
		MAV_PARAM_TYPE_REAL32 ,
		//自动模式最大向下加加速度
		MAV_PARAM_TYPE_REAL32 ,
	};

	ThrOut_Filters[0].set_cutoff_frequency( CtrlRateHz, 20 );
	ThrOut_Filters[1].set_cutoff_frequency( CtrlRateHz, 20 );
	ThrOut_Filters[2].set_cutoff_frequency( CtrlRateHz, 20 );
	
	ParamGroupRegister( "PosCtrl", 2, 30, param_types, param_names, (uint64_t*)&initial_cfg );
}

 

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

ACfly的ctrl_positon.cpp的代码 的相关文章

  • eclipse:解决Ctrl+S 无法保存问题

    解决Ctrl 43 S 无法保存问题 工作中有一个同事的eclipse中无法使用Ctrl 43 S保存文件 xff0c 尝试了各种方法 xff0c 禁用了所有其他软件的快捷键 xff0c 依然无法解决 xff0c 最终发现是eclipse自
  • boringssl android编译,boringssl_self_test.cpp

    boringssl self test cpp Copyright C 2018 The Android Open Source Project Licensed under the Apache License Version 2 0 t
  • pixhawk position_estimator_inav.cpp思路整理及数据流

    写在前面 xff1a 这篇blog主要参考pixhawk的高度解算算法解读 xff0c 并且加以扩展 xff0c 扩展到其他传感器 xff0c 其实里面处理好多只是记录了流程 xff0c 至于里面实际物理意义并不是很清楚 xff0c 也希望
  • windows上使用cmake 编译yaml-cpp源码,生成yam-cpp.lib

    1 打开cmake gui 2 添加CmakeList 3 建立build 4 进入工程中生成debug和release版本的lib
  • C++ 在.h文件中包含头文件和在.cpp文件中包含头文件的原则

    1 第一个原则 xff1a 如果可以不包含头文件 xff0c 那就不要包含了 xff0c 这时候前置声明可以解决问题 如果使用的仅仅是一个类的指针 xff0c 没有使用这个类的具体对象 xff08 非指针 xff09 xff0c 也没有访问
  • [C++]-yml库yaml-cpp简介

    文章目录 YAML基本语法数据类型对象数组标量引用 yaml cpp库生成器Emitter节点Node数组对象创建解析 yaml cpp是一个yml操作库 YAML YAML YAML Ain t a Markup Language xff
  • 解决vscode智能代码提示快捷键 Ctrl+Space 无效的问题

    背景 vscode 智能代码提示除了输入时通过字符触发 xff0c 还能使用快捷键ctrl 43 space触发 xff0c 但是在 Windows 下会发现没有效果 因为这个快捷键在Windows下是系统的中文 简体 输入法 输入法 非输
  • 侯捷-C++面向对象高级开发(上)-String类实现

    String类实现 String h ifndef MY STRING H define MY STRING H include
  • leetcode 2. 两数相加

    2023 9 14 这道题还是有点难度 需要维护一个进位值 构造一个虚拟头节点dummy 用于结果的返回 还要构造一个当前节点cur 用于遍历修改新链表 整体思路就是长度短的链表需要补0 然后两链表从头开始遍历相加 要考虑进位 需要注意的点
  • [填坑]QT信号与槽机制注意事项

    1 信号与槽机制与回调函数性能对比 信号与槽机制比回调函数的方式要慢 当槽函数是非虚函数时 信号与槽机制大约比回到函数机制慢10倍 但依旧能够满足大多数应用的需求 因为1秒钟可以出发200万次这样的信号 i586 500机器 1个信号绑定一
  • (Xcode) 編譯器小白筆記 - LLVM前端Clang

    转自 https juejin im post 6844903716709990414 做笔记之用 Xcode 編譯器小白筆記 LLVM前端Clang 本文为笔记型式呈现 并非全部原创 来源见文末 Compiler Clang LLVM A
  • 学习笔记-BNF、EBNF、ABNF语法格式描述规范

    目标是确认一些c cpp的语法细节 需要看cpp语法定义文件 考虑从c的语法定义文件开始确认 考虑实现一个简化的语言定义和编译器 为后续的实际需求做自定义扩展 参考网页 https en wikipedia org wiki Extende
  • Cpp学习——动态内存管理

    目录 一 new 1 malloc realloc calloc的使用不便之处 2 new的好处 3 opreator new 二 delete 1 为什么要有delete 2 为什么要匹配使用 一 new 1 malloc realloc
  • C++ 实现 C# delegate 机制

    C 里的 delegate C 里的 delegate 作为语法特性的一部分 使用起来非常方便 首先按照函数签名 声明一个 delegate 类型 delegate void DelegateType 之后就可以用这个 delegate 类
  • Cpp学习——list的模拟实现

    目录 一 实现list所需要包含的三个类 二 三个类的实现 1 list node 2 list类 3 iterator list类 三 功能实现 1 list类里的push back 2 iterator类里的运算符重载 3 list类里
  • C++多线程:thread_local

    概念 首先thread local是一个关键词 thread local是C 11新引入的一种存储期指定符 它会影响变量的存储周期 Storage duration 与它同是存储期指定符的还有以下几个 关键字 说明 备注 auto 自动存储
  • 《面向对象程序设计》教学资源汇总(2023)

    面向对象程序设计 教学资源汇总 2023 一 教学网站 blog csdn net bigleo 二 课堂派加课码 加课码 M274UN QRCode 三 课件下载 课件下载 长期有效 提取密码 tqucqx 四 本课程课件 二套 及实验
  • leetcode 10. 正则表达式匹配

    2023 9 20 感觉是目前做过dp题里最难的一题了 本题首要的就是需要理解题意 翻了评论区我才发现之前一直理解的题意是错的 我原来理解的 匹配0次 是指 直接消失 不会影响到前面的字符 但是 和前一个字符其实是连体的 所以说 如果匹配0
  • leetcode 1035. 不相交的线

    2023 8 25 本题可以转化为 求两数组的最长公共子序列 进而可以用dp算法解决 方法类似于这题最长公共子序列 代码如下 class Solution public int maxUncrossedLines vector
  • 通过按钮触发 Ctrl S 或 Ctrl P

    Ok now I am aware that you can listen to keypresses keydowns keyups etc but I would like to TRIGGER a keypress Like as i

随机推荐