⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 decisionmakingx.cpp

📁 该程序实现FIRE足球机器人竞赛中的3:3比赛源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	//计算机器人到目标点的角度
	Dx = directionpt.x - robot->x;Dy = directionpt.y - robot->y;
	dist = sqrt(Dx*Dx+Dy*Dy);

	if(distRobot2Pt(*robot,directionpt)<20)
		samespeed = 40*distRobot2Pt(*robot,directionpt)/20;

	double kp4new;

	
	kp4new = 15.0;
	if(samespeed<=40)
	kp4new = 15;// kp4new*samespeed/vemax;


	//计算targetpt到directionpt的角度
	Anglerb2target = atan2(Dy ,Dx);
	Anglerb2target = cn_AngleTrim2PI(Anglerb2target);

	//计算下个周期的目标角度
	double disiredAngle;
	disiredAngle = Anglerb2target;
	disiredAngle = cn_AngleTrim2PI(disiredAngle);
	//计算角度偏差
	double Angle_e;
	Angle_e = disiredAngle - robot->theta;
	Angle_e = cn_AngleTrim2PI(Angle_e);
	//计算左右轮速度差并计算出左右轮速度
	
	double ka,limitation,a;
	a = pi*0.3;
	limitation = 100;
	ka=samespeed;
	double speed_e;
	if(Angle_e <= pi/2)//角度偏差在第一象限
	{
		speed_e = kp4new*Angle_e;
		speed_e = Limit(speed_e,limitation);
		if(a-fabs(Angle_e)>0)
			samespeed = ka*(a-fabs(Angle_e))/a;
		else samespeed = 0;
		
		pSpeed->LeftValue = samespeed + speed_e/2;
		pSpeed->RightValue = samespeed - speed_e/2;
	}
	else if(Angle_e <= pi)
	{
		speed_e = kp4new*(pi - Angle_e);
		speed_e = Limit(speed_e,limitation);
		if(a-fabs(pi-Angle_e)>0)
			samespeed = ka*(a-fabs(pi-Angle_e))/a;
		else samespeed = 0;

		pSpeed->LeftValue = samespeed + speed_e/2;
		pSpeed->RightValue = samespeed - speed_e/2;
		pSpeed->LeftValue =- pSpeed->LeftValue;
		pSpeed->RightValue =- pSpeed->RightValue;
	}
	else if(Angle_e<3*pi/2)
	{
		speed_e = kp4new*(Angle_e - pi);
		speed_e = Limit(speed_e,limitation);
		if(a-fabs(Angle_e - pi)>0)
			samespeed = ka*(a-fabs(Angle_e - pi))/a;
		else samespeed = 0;

		pSpeed->LeftValue = samespeed - speed_e/2;
		pSpeed->RightValue = samespeed + speed_e/2;
		pSpeed->LeftValue =- pSpeed->LeftValue;
		pSpeed->RightValue =- pSpeed->RightValue;
	}
	else
	{
		speed_e = kp4new*(2*pi - Angle_e);
		speed_e = Limit(speed_e,limitation);
		if(a-fabs(2*pi - Angle_e)>0)
			samespeed = ka*(a-fabs(2*pi - Angle_e))/a;
		else samespeed = 0;

		pSpeed->LeftValue = samespeed - speed_e/2;
		pSpeed->RightValue = samespeed + speed_e/2;
	}
	
	if(pSpeed->LeftValue>vemax)
	{
		pSpeed->LeftValue = vemax;
		pSpeed->RightValue = pSpeed->LeftValue - fabs(speed_e);
	}
	if(pSpeed->LeftValue<-vemax)
	{
		pSpeed->LeftValue = -vemax;
		pSpeed->RightValue = pSpeed->LeftValue + fabs(speed_e);
	}
	if(pSpeed->RightValue<-vemax)
	{
		pSpeed->RightValue = -vemax;
		pSpeed->LeftValue = pSpeed->RightValue + fabs(speed_e);
	}
	if(pSpeed->RightValue>vemax)
	{
		pSpeed->RightValue = vemax;
		pSpeed->LeftValue = pSpeed->RightValue - fabs(speed_e);
	}
	
	return 1;
}
//守门员用
int CDecisionMakingx::ToPositionPDGoal(dbROBOTPOSTURE* pROBOTPOSTURE,dbPOINT Target,double startspeed,double endspeed,dbLRWheelVelocity* pLRWheelVelocity)
{
	if(startspeed > 45)startspeed = 45;
	int clock_sign,move_sign;
	double theta,theta_e1;//e1为当前角度误差
	static double theta_e2 = 0;//e2为上一周期角度误差
	double dx,dy,dx1,dy1,distance;
	double same_speed;


	//坐标变换,以小车中心为原点,小车朝向为y轴
	dx1 = Target.x - pROBOTPOSTURE->x;
	dy1 = Target.y - pROBOTPOSTURE->y;
	dx = dx1*cos(pROBOTPOSTURE->theta - pi/2) + dy1*sin(pROBOTPOSTURE->theta - pi/2);
	dy = -dx1*sin(pROBOTPOSTURE->theta - pi/2) + dy1*cos(pROBOTPOSTURE->theta - pi/2);
	distance = sqrt(dx*dx + dy*dy);
	if(distance > m_MoveParameter.max_distanceG)
		same_speed = startspeed;
	else
	{
		same_speed =  distance/m_MoveParameter.max_distanceG*startspeed;
	    if (same_speed>startspeed)
			same_speed=startspeed;
	}
	if(same_speed < endspeed) same_speed = endspeed;
	theta = atan2(dy,dx);	
	if(fabs(fabs(theta) - pi/2) > m_AngleParameter.MaxAngle)
	{
		TurnToPointPD(pROBOTPOSTURE,Target,NOCLOCK,pLRWheelVelocity);
		pLRWheelVelocity->LeftValue /= 3;
		pLRWheelVelocity->RightValue /= 3;
		return 0;
	}
	theta = cn_AngleTrim2PI(theta);
	if(theta <= pi/2)//第一象限
	{
		move_sign = 1;
		clock_sign = 1;
		theta_e1 = pi/2 - theta;
	}
	else if(theta <= pi)//第二象限
	{
		move_sign = 1;
		clock_sign = -1;
		theta_e1 = theta - pi/2;
	}
	else if(theta <= 3*pi/2)//第三象限
	{
		move_sign = -1;
		clock_sign = 1;
		theta_e1 = 3*pi/2 - theta;
	}
	else//第四象限
	{
		move_sign = -1;
		clock_sign = -1;
		theta_e1 = theta - 3*pi/2;
	}
	if(theta_e1 > 30.0/180.0*pi)
		same_speed = same_speed*(1-theta_e1/(pi/2));
	double kp,kd;
	kp = m_MoveParameter.kp4pospdG;
	kd = m_MoveParameter.kd4pospdG;
	if(distance < 20 && fabs(theta_e1) < pi/6)
	{
		kp *= 0.4;
		kd *= 0.4;
	}
	pLRWheelVelocity->LeftValue = same_speed*move_sign + clock_sign*(kp*theta_e1 + kd*(theta_e1- theta_e2));
	pLRWheelVelocity->RightValue = same_speed*move_sign - clock_sign*(kp*theta_e1 + kd*(theta_e1- theta_e2));
	
	//保存本周期角度误差,下一周期作微分用	
	theta_e2 = theta_e1;
	return 0;
}
//基本动作函数结束
//////////////////////////////////////////////////////////////
//                 技术动作函数                             //
//////////////////////////////////////////////////////////////
/************************************************************************************
函数名	:BoundProcess(int which, ballInformation &ball)
创建日期:19/4/2001
作者	:
功能	:边界处理
参数	:	which		机器人号码
			ball		球
**************************************************************************/
int CDecisionMakingx::BoundProcess(dbROBOTPOSTURE *pRobot, BallInformation Ball,int field,dbLRWheelVelocity *pSpeed)
//本函数用于处理边界球,成功返回1
//pRobot为小车的位置信息,pBall为球的位置信息,field为球所在的边界区号,pSpeed为返回的左右轮速
//     |--------------|-------------------------------------------|-------------|
//     |LUpCorner=5   |                  UpBound=1                |RUpCorner=3  |
// |---|--------------|--------------|---------------|------------|-------------|---|
// |   |LZone=10      |BackField=7   |MidField=8     |FrontField=9| RZone=11    |   |
// |   |              |              |               |            |             |   |
// |---|--------------|--------------|---------------|------------|-------------|---|
//     |LDownCorner=6 |                  DownBound=2              |RDownCorner=4|
//     |--------------|-------------------------------------------|-------------|
{
    dbPOINT point,point1,target;
	double RtTheta;
	point.x = Ball.x;
	point.y = Ball.y;
	point1.x = pRobot->x;
	point1.y = pRobot->y;
	RtTheta = pRobot->theta;
	RtTheta = cn_AngleTrim2PI(pRobot->theta);
	switch (field)
	{
	case 1:
		{
			if(RtTheta<pi/2)
			{
				target.x = point1.x + 5;
			    target.y = point1.y + 2;
			}
			else if(RtTheta<pi)
			{
				target.x = point1.x + 5;
			    target.y = point1.y - 2;
			}
			else  if(RtTheta<3*pi/2)
			{
				target.x = point1.x + 5;
			    target.y = point1.y + 2;
			}
			else
			{
				target.x = point1.x + 5;
			    target.y = point1.y - 2;
			}
			break;
		}
	case 2:
		{
			if(RtTheta<pi/2)
			{
				target.x = point1.x - 2;
			    target.y = point1.y - 5;
			}
			else if(RtTheta<pi)
			{
				target.x = point1.x + 2;
			    target.y = point1.y - 5;
			}
			else  if(RtTheta<3*pi/2)
			{
				target.x = point1.x - 2;
			    target.y = point1.y - 5;
			}
			else
			{
				target.x = point1.x + 2;
			    target.y = point1.y - 5;
			}
			break;
		}
	case 3:
		{
			if(RtTheta<pi/2)
			{
				target.x = point1.x - 5;
			    target.y = point1.y - 5;
			}
			else if(RtTheta<pi)
			{
				target.x = point1.x - 5;
			    target.y = point1.y + 2;
			}
			else  if(RtTheta<3*pi/2)
			{
				target.x = point1.x - 5;
			    target.y = point1.y - 5;
			}
			else
			{
				target.x = point1.x - 5;
			    target.y = point1.y + 2;
			}
			break;
		}
	case 4:
		{
			if(RtTheta<pi/2)
			{
				target.x = point1.x + 5;
			    target.y = point1.y + 2;
			}
			else if(RtTheta<pi)
			{
				target.x = point1.x + 5;
			    target.y = point1.y - 2;
			}
			else  if(RtTheta<3*pi/2)
			{
				target.x = point1.x + 5;
			    target.y = point1.y + 2;
			}
			else
			{
				target.x = point1.x + 5;
			    target.y = point1.y - 2;
			}
			break;
		}
	case 5:
		{
			if(RtTheta<pi/2)
			{
				target.x = point1.x + 2;
			    target.y = point1.y + 5;
			}
			else if(RtTheta<pi)
			{
				target.x = point1.x - 2;
			    target.y = point1.y + 5;
			}
			else  if(RtTheta<3*pi/2)
			{
				target.x = point1.x + 2;
			    target.y = point1.y + 5;
			}
			else
			{
				target.x = point1.x - 2;
			    target.y = point1.y + 5;
			}
			break;
		}
	case 6:
		{
			if(RtTheta<pi/2)
			{
				target.x = point1.x - 5;
			    target.y = point1.y - 2;
			}
			else if(RtTheta<pi)
			{
				target.x = point1.x - 5;
			    target.y = point1.y + 5;
			}
			else  if(RtTheta<3*pi/2)
			{
				target.x = point1.x - 5;
			    target.y = point1.y - 2;
			}
			else
			{
				target.x = point1.x - 5;
			    target.y = point1.y + 2;
			}
			break;
		}
	}

	ToPositionN(pRobot,target,60,pSpeed);




	return 1;
}
/************************************************************************************
函数名	:GoalieAction(robotInformation &robot, ballInformation &ball, dbPOINT &proball)
创建日期:19/4/2001
作者	:
功能	:守门
参数	:	robot		机器人位姿
			ball		球
**************************************************************************/
int CDecisionMakingx::GoalieAction1(dbROBOTPOSTURE* pRobotInford, BallInformation ball,dbLRWheelVelocity *pSpeed)
{	
	//int homeline =8;	G_OFFSET
	int		Error_y = 2;						//block goal area up and down corner
	int		xError = 3;						// homePt.x+xError and homePt.x-xError;
	int		gtError = 2, glError = 2;			// gate corner and goal corner +-
	dbPOINT	target;
	dbPOINT	homePt;
	double	dx,dy;
	static double  turn_E2 = 0;
	int		goToken=0;			// go first then turn;

	homePt.x = G_OFFSET;
	homePt.y = CENTER_Y;

	target = homePt;
	///////////////////////////////////

	pRobotInford->theta = cn_AngleTrim2PI(pRobotInford->theta);
	if(ball.x > CENTER_X + 40)
	{
		dx = pRobotInford->x - homePt.x;
		dy = pRobotInford->y - homePt.y;
		if(dx*dx + dy*dy < 2*2)
			if(pRobotInford->theta < pi)
				TurnToAnglePD(pRobotInford,pi/2,NOCLOCK,pSpeed);
			else
				TurnToAnglePD(pRobotInford,3*pi/2,NOCLOCK,pSpeed);
		else
			ToPositionPD(pRobotInford,homePt,m_MoveParameter.V_max,0.0,pSpeed);	
	}
	else	// ball in process area;
	{	// Forcast ball next postition
		if(m_decisionparamter.oldBallPt[0].x > m_decisionparamter.oldBallPt[3].x && m_decisionparamter.oldBallPt[3].x > m_decisionparamter.oldBallPt[6].x)				 // GG new add
		{
			target.y = GetCrossPtWithGLLine(G_OFFSET);			 //update oldball previous
		}
		else
			target.y = 0;		
		if(target.y > GATE_UP_LINE || target.y < GATE_DN_LINE)//交点出了门区
		{
			target.y = ball.y;
			if(ball.x < homePt.x + 5)//x方向离门很近,目标点在禁区里2厘米处
			{
				if(target.y < GOAL_DN_LINE) 
				{
					target.y = GOAL_DN_LINE + glError;
					if(pRobotInford->y < GATE_DN_LINE - glError ) //跑出门区
						goToken = 2;//回目标点
				}
				else if(target.y > GOAL_UP_LINE) 
				{
					target.y = GOAL_UP_LINE - glError;
					if(pRobotInford->y > GATE_UP_LINE + glError ) 
						goToken = 2;						
				}
			}
			else if(ball.x > homePt.x + 20)//离门>25厘米
			{
				if(target.y < GATE_DN_LINE) 
					target.y = GATE_DN_LINE + 5;		  // GGG
				else if(target.y > GATE_UP_LINE) 
					target.y = GATE_UP_LINE - 5; // GGG

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -