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

📄 decision.cpp

📁 本程序是2005年参加中国机器人大赛的比赛程序
💻 CPP
📖 第 1 页 / 共 4 页
字号:
// Decision.cpp: implementation of the CDecision class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "Robocup.h"
#include "Decision.h"
#include "Object.h"

#include "math.h"
#include "stdlib.h"



#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

extern Vector m_OpponentGoal;
int TheLest;

//周全——2003年6月27日19:00
//注意,机器人是0--4号;现假设0号为守门员已经确定,决策只是在1、2、3、4里面进行
//所有数字的单位都是厘米,场地大小为:290*240(cm*cm)    角度在-180——+180之间
//考虑用两个函数分别作出进攻和防守的决策,
//另外设置一个整体函数进行集成,1、判断整体态势2、角色选择3、角色动作和目标点的选择
//动作中直接将命令发送出去,每个机器人的动作和目标点判定出来以后直接发出命令动作(通讯部分)
//以上为方案1

CDecision::CDecision()
{
/*	MAttacker=1;
	AAssist1=2;
	AAssist2=3;
	AttackFreeMan=4;

	MainDeffenser1=1;
	MainDeffenser2=2;
	DeffenseAssistant=3;
	DeffenseFreeMan=4;
*/	
}

CDecision::~CDecision()
{

}
//简单决策:

/*
void CDecision::SimpleDecision()
{
	for(int i=0; i<5;i++)
	{
		MainAttacker=i;
	if( g_MyTeam[MainAttacker].Get_vPos().x>=g_Ball.Get_vPos().x)
	{
		if ( g_MyTeam[MainAttacker].Get_vPos().y>120)
	//	{
			if( (g_MyTeam[MainAttacker].Get_m_Angle()<=90)&&((g_MyTeam[MainAttacker].Get_m_Angle()>=0)))
			{
				g_MyTeam[MainAttacker].BasicAct(0,FALSE,TRUE,-MAX_VELOCITY);
			}
			if( (g_MyTeam[MainAttacker].Get_m_Angle()<=180)&&((g_MyTeam[MainAttacker].Get_m_Angle()>=90)))
			{
				g_MyTeam[MainAttacker].BasicAct(0,FALSE,TRUE,MAX_VELOCITY);
			}
			if( (g_MyTeam[MainAttacker].Get_m_Angle()<=0)&&((g_MyTeam[MainAttacker].Get_m_Angle()>=-90)))
			{
				g_MyTeam[MainAttacker].BasicAct(0,FALSE,TRUE,-MAX_VELOCITY);
			}
			if( (g_MyTeam[MainAttacker].Get_m_Angle()<=0)&&((g_MyTeam[MainAttacker].Get_m_Angle()>=90)))
			{
				g_MyTeam[MainAttacker].BasicAct(0,FALSE,TRUE,MAX_VELOCITY);
			}
	}
		}
	else
	{
		if( DistRandB(g_MyTeam[MainAttacker],g_Ball)<SHOOTDIST )
		{
			if( currentBall.Get_vPos().y<=m_OpponentGoal.y )	
			{
				g_MyTeam[MainAttacker].BasicAct(10,TRUE,FALSE,MAX_VELOCITY);///Lshoot执行射门动作:左射门;
			}
			else				
			{
				g_MyTeam[MainAttacker].BasicAct(10,FALSE,FALSE,MAX_VELOCITY);// Rshoot;
			}
		}
		else	
		{	
			if(fabs(k1-k2)<PI/4)
			{
				g_MyTeam[MainAttacker].BasicAct(0,FALSE,TRUE,MAX_VELOCITY);
			}
			else
			{
				g_MyTeam[MainAttacker].TurnTo4Debug(g_Ball.Get_vPos());
			}
		}
	}
	MainAttackA();
	
}
*/
void CDecision::PredictBall()//对从视觉送来的每一帧都做关于球的处理;
{
	currentBall=g_Ball;
	double dx=currentBall.Get_vPos().x-lastBall.Get_vPos().x;
	double dy=currentBall.Get_vPos().y-lastBall.Get_vPos().y;
	predictedBall.m_vPos.x=currentBall.Get_vPos().x+dx;
	predictedBall.m_vPos.y=currentBall.Get_vPos().y+dy;
	lastBall.m_vPos.x=currentBall.Get_vPos().x;
	lastBall.m_vPos.y=currentBall.Get_vPos().y;
}
/*
double CDecision::DistVandV(Vector &vector1, Vector &vector2)
//求两点之间的距离的平方
{
	double dx,dy,dz;
	dx=(vector1.x-vector2.x);
	dy=(vector1.y-vector2.y);
	dz=dx*dx+dy*dy;
	return dz;
}

double CDecision::DistRandB(Player &player, Ball &ball)//求robot与ball之间的距离
{
	return DistVandV( player.Get_vPos(), ball.Get_vPos() );
}

double CDecision::DistRandR(Player &player1, Player &player2)
{
	return DistVandV( player1.Get_vPos(), player2.Get_vPos() );
}
*/
/*int CDecision::IsHaveObstacle(Vector &vector1, Vector &vector2)
//判断两点之间是否有障碍物的函数,真则返回TRUE,否则返回FALSE;
//算法为:建立两点之间的连线,如果其他机器人到该直线的距离小于某个值时,则说明该机器人为障碍;
{
	//vector1=(x1,y1),vector2=(x2,y2)  可以得到直线方程(y2-y1)*x-(x2-x1)*y-(x2-y2)*(x2-x1)=0
	for(int i=0;i<7;i++)
	{
		if(x[i]<x2&&x[i]>x1&&yi<y2&&yi>y1)
		{
			if(abs((y2-y1)*xi-(x2-x1)*yi-(x2-y2)*(x2-x1))/sqrt((y2-y1)*(y2-y1)+(x2-x1)+(x2-x1))<DMin)   //角度和距离的极小值参数
			{
				return i;       //返回该球员的号码
			}
			return -1;
		}
	}

	return -1;
}

int CDecision::ChooseLest(double *array)
{
	double *p,lest;
	int i;
	if( array!=NULL)
	{
		p=array;
	}
	i=0;
	lest=*p;
	for ( ; p!=NULL; p++ )
	{
		if ( *p<lest )
		{
			lest=*p;
			i++;
		}
	}
	return i;//返回数组中值最小的标号;
}

int CDecision::WhoHasBall()//我们控球则返回队员的标号,且其为主要进攻者
{
	static double dist[11];//全局变量,用来存储10个机器人与球的距离
	
	dist[0]=10000.0;//令dist[0]为较大值,有利于返回队员的标号
	for ( int i=1; i<6; i++ )//将我方robot与球的距离赋给数组dist[1,2,3,4,5];
	{
		dist[i]=DistRandB( g_MyTeam[i-1], currentBall );
	}
	for ( ; i<11; i++ )//将对方robot与球的距离赋给数组dist[6,7,8,9,10];
	{
		dist[i]=DistRandB(g_TheirTeam[i], currentBall );
	}
	//从dist[]中找出最小的一个,如果他们的队员离球最近,则返回其队员标号;
	TheLest=ChooseLest(dist);//从dist[]中选出最小的;
	return TheLest;
}

state CDecision::stateDecision()
{
	if (  ( (TheLest>0) && ( TheLest<6) ) &&  (g_MyTeam[TheLest].Get_vPos().x<currentBall.Get_vPos().x) && ( fabs( tn(TheLest)-g_MyTeam[TheLest].Get_m_Angle() ) )<(PI/3) )
//如果我方与球距离最小的其x位置比球
		//小既靠近我方半场,且方向与球和机器人的连线的偏差不超过一个定值PI/3时,则说我方控球
	{	
		return		ATTACK;
	}
		return		DEFFENSE;
}

int CDecision::AAssistant1()//以下为1号辅攻队员的选取,最靠近前方的球员(除了主攻者)动作就是进攻跑位
//确定第一辅助进攻者并返回其标号;
{
	int k=0;
	double l=0;
	for( int i=1; i<5; i++ )
	{
		if(i==MAttacker)
		{
			continue;
		}
		if( g_MyTeam[i].Get_vPos().x>l )
		{
			k=i;
			l=g_MyTeam[i].Get_vPos().x;
		}
	}
	return k;
}

int CDecision::AAssistant2()//以下为2号辅攻队员的选取:除了MainAttacker,Assistant1以外的最靠近前方的球员;目的:位置在带球人的后面,
//动作顺序为:判断是否满足了条件,(位置在带球队员的身后的某个区域)不满足,则运动到所定义的点:
//满足条件则保持队形,根据带球队员的位置来调整相应的位置(确定目标点)
{
	int k=0;
	double l=0;
	for( int i=0; i<5; i++ )
	{
		if( (i==MAttacker)||(i==AAssist1) )
		{
			continue;
		}
		if( g_MyTeam[i].Get_vPos().x>l )
		{
			k=i;
			l=g_MyTeam[i].Get_vPos().x;
		}
	}
	return k;
}

int CDecision::CAFreeMan()//自由人的选取
//判断出前三个之后剩下的即为自由人
{
	int k=0;
	for ( int i=1; i<5; i++ )
	{
		if ( ( i!=MAttacker )&&( i!=AAssist1 )&&( i!=AAssist2 ) )
		{
			k=i;
			break;
		}
	}
	return i;
}

void  CDecision::MainAttackA()//6.27机器人能找到球,并且运动到适当位置(球的后面),进行粗糙的射门
{
//	MAttacker=WhoHasBall();
	double k1,k2,k3;
//	int m;
	k1=g_MyTeam[MAttacker].Get_m_Angle();
	k2=(g_MyTeam[MAttacker].Get_vPos().y-currentBall.m_vPos.y)/( g_MyTeam[MAttacker].Get_vPos().x-currentBall.m_vPos.x );
	k3=(g_MyTeam[MAttacker].Get_vPos().y-m_OpponentGoal.y)/( g_MyTeam[MAttacker].Get_vPos().x-m_OpponentGoal.x );
//	double time=sqrt(currentBall.Get_vPos(),g_MyTeam[MAttacker].Get_vPos())*100;
	double time=500;
	if( ( g_MyTeam[MAttacker].Get_vPos().x<currentBall.m_vPos.x ) )// ( fabs(k3-k2)<(PI/6) )机器人在球的后面
	{
		if( DistRandB( g_MyTeam[MAttacker], currentBall )<SHOOTDIST )	//SHOOTDIST为射门距离,自定义
		{
			if( fabs(k1-k2)<(PI/3) )
			{
				if( currentBall.Get_vPos().y<=m_OpponentGoal.y )	
				{
					g_MyTeam[MAttacker].BasicAct(10,TRUE,FALSE,MAX_VELOCITY,time);///Lshoot执行射门动作:左射门;
				}
				else				
				{
					g_MyTeam[MAttacker].BasicAct(10,FALSE,FALSE,MAX_VELOCITY,time);// Rshoot;
				}
			}
			else
			{
				g_MyTeam[MAttacker].TurnTo4Debug(g_Ball.Get_vPos());//DirectionProcess;	进行正向处理;
			}
		}
		else
		{
			g_MyTeam[MAttacker].BasicAct(0,TRUE,TRUE,MAX_VELOCITY,time);
		}	
	}
	else//机器人在球的前面,先返回,就是做防守跑位:先简单作为跑到边线再回去
	{
		if(  g_MyTeam[MAttacker].Get_vPos().y>120 )//从左边返回去
		{
			if(  ( fabs(g_MyTeam[MAttacker].Get_m_Angle()-90)>10 )||( fabs(g_MyTeam[MAttacker].Get_m_Angle()+90)>10 ) )
			{
				Vector destPos=(g_MyTeam[MAttacker].Get_vPos().x, 160);
				g_MyTeam[MAttacker].TurnTo(destPos);
			}
			else
			{
				g_MyTeam[MAttacker].BasicAct(0,0,1,MAX_VELOCITY,time);
			}
		}
	}
}
*/
/*以下为传球判断:	不要了
	m=Shooter(); 	
	if( m!=-1 )  // 判定前方是否有我方队员,适于传球用
	{
		//对应函数为:return 	sendball;          //传球动作目标点为本方接球队员   动作即为sendball;
	     	//在传球动作结束后  应break  将接球队员的角色转换为主攻队员
		g_MyTeam[MAttacker].SendBall((g_MyTeam[MAttacker].Get_vPos()-g_MyTeam[m].Get_vPos()).mod(), g_MyTeam[m].Get_vPos());
	}
	else
	{
		//对应函数为:return dribble;        //带球动作待定   其中应该包括正向处理动作
			//带球动作中只考虑一个周期内的最优目标点  每个周期后都要重新判断
		g_MyTeam[MAttacker].MoveTo(currentBall.Get_vPos());
	}
*/

/*
int CDecision::Shooter() //计算一个我方前场队员的号码,并返回该值,如果我方前场没人,则返回-1;
{
	int i=1,k;
	for(;i<5;i++)
	{
		if(g_MyTeam[i].Get_vPos().x>=2933)	{k=i;break;}
		else	k=-1;
	}
	return -1;

}
*/
/*
void   CDecision::AssistAttack1A()
{
	AAssist1=AAssistant1();
	Vector dest=(g_MyTeam[AAssist1].Get_vPos().x,ShootP());
	if(  g_MyTeam[AAssist1].Get_vPos().x>g_MyTeam[MAttacker].Get_vPos().x )
	//该辅助进攻者已经在主攻者前方,则选取最佳的进攻点,
	//运动到该点(最好是正向处理的运动) 由ShootP()确定
	{
	//	return moveto;or DirectionProcess;//对应函数为:	//	
		
		g_MyTeam[AAssist1].MoveToWithAngle(dest,45);	//假设45为对着对方球门的方向
	}
	else//在带球队员的后面的话,则运动到其前方,可以做好射门或者接传球的准备
	{
				//	return moveto;	//对应函数为:
		Vector dest=(g_MyTeam[AAssist1].Get_vPos().x,ShootP());
		g_MyTeam[AAssist1].MoveToWithAngleOA(dest,45);//假设45为对着对方球门的方向
	}
}


int CDecision::ShootP()//找出最佳射门位置的纵坐标,并返回此值
{
	double p1,p2,p,y;
	 if(currentBall.Get_vPos().x-g_TheirTeam[0].Get_vPos().x)//g_TheirTeam[0]为对方守门员
	 {
         y=(4000-currentBall.Get_vPos().x)*(currentBall.Get_vPos().y-g_TheirTeam[0].Get_vPos().y)/(currentBall.Get_vPos().x-g_TheirTeam[0].Get_vPos().x)+currentBall.Get_vPos().y;
	  	 p1=fabs(atan2(currentBall.Get_vPos().y-1600,currentBall.Get_vPos().x-4000)-atan2(currentBall.Get_vPos().y-g_TheirTeam[0].Get_vPos().y,currentBall.Get_vPos().x-g_TheirTeam[0].Get_vPos().x));
		 p2=fabs(atan2(currentBall.Get_vPos().y-900,currentBall.Get_vPos().x-4000)-atan2(currentBall.Get_vPos().y-g_TheirTeam[0].Get_vPos().y,currentBall.Get_vPos().x-g_TheirTeam[0].Get_vPos().x));
		 p=p1>p2?(1600-(1600-y)/3):(900+(y-900)/3);
	 }
	 else
         p=1250;
	 return (int)p;
}

void CDecision::AssistAttack2A()//以下为第二辅助进攻队员的动作规划及其目标点的选取
{
	AAssist2=AAssistant2();
	Vector dest=(g_MyTeam[MAttacker].Get_vPos().x-40,g_MyTeam[MAttacker].Get_vPos().y );
	if(  g_MyTeam[AAssist2].Get_vPos().x<g_MyTeam[MAttacker].Get_vPos().x )
	//如果在带球人后方,则只需要做正向处理运动到带球队员后方的某个点,根据带球队员的位置
	//来确定,如:其中400为经验值
	{
		//对应函数为return	 moveto;:
		
		g_MyTeam[AAssist2].MoveTo(dest);
	}	
//防守跑位动作,同样可用于对自己控球队员的接应;	return	  DPosition;
				//对应函数:
		g_MyTeam[AAssist2].MoveToWithAngle(dest,0);
}

void	 CDecision::AFreeManA()//FreeMan动作规划和目标点的选取,
{
	AttackFreeMan=CAFreeMan();
	double k2,k3;
	k2=(g_MyTeam[MAttacker].Get_vPos().y-currentBall.m_vPos.y)/( g_MyTeam[MAttacker].Get_vPos().x-currentBall.m_vPos.x );
	k3=(g_MyTeam[MAttacker].Get_vPos().y-m_OpponentGoal.y)/( g_MyTeam[MAttacker].Get_vPos().x-m_OpponentGoal.x );

	if( g_MyTeam[AttackFreeMan].Get_vPos().x>g_MyTeam[MAttacker].Get_vPos().x )//在带球队员前方则回防
	{
	//	return DPosition;//目标点为:
		Vector dest=(currentBall.Get_vPos().x, 30);//y为我方球门前某点,可以人为设定
		g_MyTeam[AttackFreeMan].MoveToWithAngleOA(dest,180);
	}
	else//选择最有利于进攻的点
	{
		if( ( g_MyTeam[MAttacker].Get_vPos().x<currentBall.Get_vPos().x )&& ( fabs(k3-k2)<(PI/3) ) )      
				//SHOOTDIST为射门距离,自定义
//判断是否满足射门条件,比主攻者的条件宽松一点,但是不能撞我方的主攻者
//或者判断与球之间是否有障碍,没有的时候才进行该动作
		{
			//return moveto;// or shoot; //避障运行到球的坐标,随机的创造机会,目标为球
			g_MyTeam[AttackFreeMan].MoveTo(currentBall.Get_vPos());//对应函数:
		}
		//	对应函数:return DPosition;//目标点为:y为我方球门前某点,可以人为设定
		Vector dest=(currentBall.Get_vPos().x, 40);
		g_MyTeam[AttackFreeMan].MoveToWithAngleOA(dest,180);
	}
}

//2、防守时的角色分配		
//MainDeffenser1, MainDeffenser2, DeffenseAssistant,DFreeMan
//两个主要防守者+一个辅助防守者+一个自由人
//两个主要防守者是球的我方半场中,离球最近的球员

int CDecision::MDeffenser1()
{
	for( int i=1; i<5; i++ )//从场上四个机器人当中选取
	{
		if( (g_MyTeam[i].Get_vPos().x<currentBall.Get_vPos().x) )
		{
			if( fabs(g_MyTeam[i].Get_m_Angle()-tn(i) )<PI/4  )	return i;
												//一般这个角色是一定能取到的
		}
	}	
	 //没有合适条件(即没有机器人在球的后方)
	return AttackFreeMan;//返回上次进攻决策中FreeMan的标号
}

int CDecision::MDeffenser2()
{
	for ( int i=1; i<5; i++ )
	{
		if( i!=MainDeffenser1 )//不能和MainDeffenser1冲突
		{
			if( g_MyTeam[i].Get_vPos().x<g_TheirTeam[MAttacker].Get_vPos().x )
			{//选择我方球员中球左边第一个队员,即横坐标小于球的横坐标但最小的那个人
				if( fabs(tn(i)-g_MyTeam[i].Get_m_Angle())<(PI/4) )		return i;//可调整
			}
		}
	}	
	return AAssist2;//返回上次进攻决策中AttackerAssistant2的标号
}

int CDecision::DAssistant()//辅助进攻者的选取
{
	int k=0;
	for( int i=1; i<5; i++ )
	{
		if( (i!=MainDeffenser1)&&(i!=MainDeffenser2)  )
		{
			k=i;
			break;
		}
	}
	return k;
}


int CDecision::DFreeMan()
{
	int k=0;
	for( int i=1; i<5; i++ )
	{
		if(  (i!=MainDeffenser1)&&(i!=MainDeffenser2)&&(i!=DeffenseAssistant) )
		{
			k=i;
			break;
		}
	}
	return i;
}
//防守时的动作规划及目标点选取

void  CDecision::MDeffenser1A()
{
	MainDeffenser1=MDeffenser1();
	if( g_MyTeam[MainDeffenser1].Get_vPos().x<currentBall.Get_vPos().x )
	{
			//对应函数:return block;//目标点为predictedBall.pos
		g_MyTeam[MainDeffenser1].MoveTo(g_Ball.Get_vPos());
	}
//对应函数:	return DPosition;//目标点为:(PredictedBall.x-100, PredictedBall.y)100为经验常数
	g_MyTeam[MainDeffenser1].MoveToWithAngleOA(g_Ball.Get_vPos(),180);
}

void	CDecision::MDeffenser2A()
{
	MainDeffenser2=MDeffenser2();	
	if( g_MyTeam[MainDeffenser1].Get_vPos().x<currentBall.Get_vPos().x )
	{
			//return block;//目标点为
		Vector dest=(predictedBall.Get_vPos().x-20,predictedBall.Get_vPos().y-20 );
	g_MyTeam[MainDeffenser1].MoveTo(dest);
	}

⌨️ 快捷键说明

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