PPC.c 8.45 KB
#include "PPC.h"

#if 0//P_SETUP_NAV_TYPE==4
//获取激光数据slam,此补偿不是将雷达位置补偿到车体中心而是工位坐标特殊补偿,每个工位的补偿值不一样,龙旗项目使用中
void laserDataUpdate() //
{
    CurrentCenterPoint.TarX = agv.Public.Coordinate_X + agv.Command.X_compensation; //X补偿

    CurrentCenterPoint.TarY = agv.Public.Coordinate_Y + agv.Command.Y_compensation; //Y补偿

    CurrentCenterPoint.CurAngle = agv.Public.Coordinate_W + agv.Command.W_compensation; //W补偿
}

int LightArriveFlagL = 0,LightArriveFlagR = 0;
//到达判断
unsigned char ArriveJugement2()
{
	static u8 lastStopFlagL = 0,lastStopFlagR = 0;
	if(navi.Public.VerticalDistanceAgvToTARGET < LIGHT_STOP_SIGNAL_DIS)
	{
			if ((navi.Public.VerticalDistanceAgvToSTART >= (navi.Public.DistanceSTARTtoTARGET - 25)) && (navi.Public.VerticalDistanceAgvToTARGET < navi.Public.VerticalDistanceAgvToSTART))
			{
				Uart_Printf(COM1,"正常到达  %d\r\n",agv.Command.LightStopSig);
				return 1;
			}
		
	}
	return 0;
}
//更新执行站点
//void pathUpdate(u8 *CurrentID)
//{
//    static int lastTime = 0;
//		static float lastAnglediff = 0;
//    /*****************到达站点判断以及切换站点**********************/
//    if (agv.Command.CurDirection == 1 || agv.Command.CurDirection == 2) //直行判断
//    {
//        //到达站点判断
//        if (ArriveJugement()==1)
//        {
//					navi.Private.FirstZeroPoint = 0;
//            *CurrentID += 1;
///****单机测试***/
//#if P_SETUP_SINGLE_PLAYER == 1
//            if (*CurrentID >= traffic_land_marks.size)
//            {
//                *CurrentID = 1;

//                traffic_land_marks.land_marks[0].Direction = 4;

//                traffic_land_marks.land_marks[3].Direction = 3;
//            }
//#elif P_SETUP_SINGLE_PLAYER == 0
//            if (*CurrentID >= traffic_land_marks.size)
//            {
//               if((agv.Command.LightStopSig == 1 && LightArriveFlagL == 1)||(agv.Command.LightStopSig == 2 && LightArriveFlagR == 1))
//							 {
//								 SetAlarm(0x200); 
//							 }
//							 else
//							 {
//								 SetAlarm(0x40);
//							 }
//							 LightArriveFlagL = 0;
//						
//							 LightArriveFlagR = 0;
//						
//							 agv.Public.i_UpdatePathSig = 1;
//            }
//#endif
//            Uart_Printf(COM1, "站点更新,当前站点 = %d 当前方向 = %d Error_Flag = %x\r\n", agv.Command.standSiteID, agv.Command.CurDirection, agv.Public.Error_Flag);
//        }
//				lastAnglediff = 0;
//    }
//    else if (agv.Command.CurDirection == 7 || agv.Command.CurDirection == 8 || agv.Command.CurDirection == 9 || agv.Command.CurDirection == 10) //弧线转弯
//    {
//        //站点更新
//        if ((fabs(navi.Public.AngleDifference) <= TURNINGOFF_ANGLE)||(navi.Public.AngleDifference*lastAnglediff<0))
//        {
//            *CurrentID += 1;
//        }
//				lastAnglediff = navi.Public.AngleDifference;
//    }
//    agv.Command.DispatchSpeed = traffic_land_marks.land_marks[*CurrentID - 1].DispatchSpeed; //系统下发速度

//    agv.Command.CurDirection = traffic_land_marks.land_marks[*CurrentID - 1].Direction; //当前站点运行方向

//    if (*CurrentID < traffic_land_marks.size) //当前站点不是最后站点,保存下一个站点方向和光电停车信号
//    {
//        agv.Command.LightStopSig = traffic_land_marks.land_marks[*CurrentID].LightStopSig; //目标站点广电信号

//        agv.Command.NextDirection = traffic_land_marks.land_marks[*CurrentID].Direction; //下个站点运行方向

//        agv.Command.NextDispatchSpeed = traffic_land_marks.land_marks[*CurrentID].DispatchSpeed;
//    }
//    else //已经是最后一个站点,没有下一个站点清零
//    {
//        agv.Command.LightStopSig = 0;

//        agv.Command.NextDirection = 0;

//        agv.Command.NextDispatchSpeed = 0;
//    }

//    StartPoint.TarX = traffic_land_marks.land_marks[*CurrentID - 1].pose[0]; //当前点(起点)

//    StartPoint.TarY = traffic_land_marks.land_marks[*CurrentID - 1].pose[1];

//    TargetPoint.TarX = traffic_land_marks.land_marks[*CurrentID].pose[0]; //目标点(终点)

//    TargetPoint.TarY = traffic_land_marks.land_marks[*CurrentID].pose[1];

//    if (*CurrentID >= 2 && *CurrentID < traffic_land_marks.size - 1) //实现弧线转弯需要有四个点位计算
//    {
//        PointOne.TarX = traffic_land_marks.land_marks[*CurrentID - 2].pose[0];

//        PointOne.TarY = traffic_land_marks.land_marks[*CurrentID - 2].pose[1];

//        PointTwo.TarX = traffic_land_marks.land_marks[*CurrentID - 1].pose[0];

//        PointTwo.TarY = traffic_land_marks.land_marks[*CurrentID - 1].pose[1];

//        PointThree.TarX = traffic_land_marks.land_marks[*CurrentID].pose[0];

//        PointThree.TarY = traffic_land_marks.land_marks[*CurrentID].pose[1];

//        PointFour.TarX = traffic_land_marks.land_marks[*CurrentID + 1].pose[0];

//        PointFour.TarY = traffic_land_marks.land_marks[*CurrentID + 1].pose[1];
//    }
//}


//1,获取前视距离,根据剩余距离调整前视距离
float getControlFrontDistance(float *distance)
{
	float valueDis = 0;
	
	if(*distance > 1000)
	{
		valueDis = 1000;
	}
	else
		valueDis = 1000;
	
	return valueDis;
}

//2,根据当前点位在路径上的映射,求出前视点位坐标



//计算偏移量 设置不同运动方式的pid值
void calculateOffsetValue2(unsigned char Direction)
{
    if (Direction == 7 || Direction == 8 || Direction == 9 || Direction == 10) //转弯需要计算圆心坐标
    {
        CircleCenterPoint = GetCircleCenterPoint(CurrentCenterPoint,PointThree,PointFour);                       //计算圆心坐标
        navi.Private.SetCalculationRadius = TwoPointDistance(PointTwo, CircleCenterPoint); //入弯点到圆心的距离
    }

}

//根据P值,I值,D值,位置偏差权重,角度偏差权重,输出偏移值
void offsetCompensationOutput2(navigationPID *Pid)
{
	static int i = 0;
	static float LastCenterOffset = 0, LastAngleOffset = 0;
	static float Error = 0, DcalError = 0, LastError = 0, SumError = 0;
	//当位置和角度偏差变化重新计算
	if (LastCenterOffset != navi.Public.CenterOffset || LastAngleOffset != navi.Public.AngleDifference)
	{
			LastCenterOffset = navi.Public.CenterOffset;

			LastAngleOffset = navi.Public.AngleDifference;
			//取角度和位置偏差做为偏差补偿量
			Error = navi.Public.CenterOffset * Pid->PosCofficient + navi.Public.AngleDifference * 180 / PI * Pid->AngleCofficient;

			DcalError = Error - LastError; //误差变化量

			LastError = Error; //记录上次偏差
	}
	
	navi.Private.OutputOffset = Error * Pid->Kp + SumError * Pid->Ki + DcalError * Pid->Kd;

	if (navi.Private.OutputOffset >= Pid->MaxLimit)
			navi.Private.OutputOffset = Pid->MaxLimit;
	else if (navi.Private.OutputOffset <= -Pid->MaxLimit)
			navi.Private.OutputOffset = -Pid->MaxLimit;
	
	#if PRINT_TYPE_SELECT == 1
	if (i++ > PRINT_FREQUENCY)
	{
			i = 0;
			//		Uart_Printf(COM1,"当前方向 = %d,角度偏差 = %.2f,位置偏差 = %.2f,输出补偿值 = %.2f\r\n",
			//		agv.Command.CurDirection,navi.Public.AngleDifference*57.3,navi.Public.CenterOffset,navi.Private.OutputOffset);
			Uart_Printf(COM1, "X = %.2f Y = %.2f 当前方向 = %d,发送速度 = %.2f %.2f 反馈速度 = %.2f %.2f 角度偏差 = %.2f,位置偏差 = %.2f,输出补偿值 = %.2f\r\n", agv.Public.Coordinate_X, agv.Public.Coordinate_Y,
									agv.Command.CurDirection, DriverMotor1.Command.speed, DriverMotor2.Command.speed, DriverMotor1.Public.encoderSpeed, DriverMotor2.Public.encoderSpeed, navi.Public.AngleDifference * 57.3, navi.Public.CenterOffset, navi.Private.OutputOffset);
	}
	#endif
}

void slamNavigation()
{
	laserDataUpdate(); 										//获取激光数据,以及特殊工位定点补偿**************

//	pathUpdate(&agv.Command.standSiteID); //执行路径更新 和站点++判断。

	CalculateDistance(); 									//计算起始点、目标点、agv之前的距离
	
	if(agv.Command.CurDirection == 1 || agv.Command.CurDirection == 2)
	{
		Line Lpath;
		
		static float angleDiff = 0,valueDis = 0;
		
		Lpath = getLine2(StartPoint,TargetPoint);
		
		navi.Private.FrontViewDistance = getControlFrontDistance(&navi.Public.DistanceAgvToTARGET);//获取并调节前视距离
		
		FrontViewPoint = getControlTargetPoint(CurrentCenterPoint,Lpath,navi.Private.FrontViewDistance);//求预瞄点
		
		navi.Private.FrontViewAngle = CalculatingDirectionAngle(CurrentCenterPoint,FrontViewPoint);//求当前点与预瞄点角度
		
		angleDiff = CalculatingCurrentAndTargetAngle(CurrentCenterPoint.CurAngle,navi.Private.FrontViewAngle);//求车体与预瞄方向夹角
		
		valueDis = TwoPointDistance(CurrentCenterPoint,FrontViewPoint);
		
		if(angleDiff != 0)
		{
			navi.Private.SetCalculationRadius = valueDis/sin(angleDiff)/2;
		}
		else
			navi.Private.SetCalculationRadius = 0;
		
	}
	else
	{
		calculateOffsetValue2(agv.Command.CurDirection); //计算偏移量和设置不同运动方式的pid值

		offsetCompensationOutput2(&pid); 			//计算处理得到补偿值***********
	}
	
	



    
}
#endif