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

📄 kick.cpp

📁 RoboCup仿真组世界冠军源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*
    Copyright (C) 2001  Tsinghuaeolus

    Authors : ChenJiang, YaoJinyi, CaiYunpeng, Lishi

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

	If you make any changes or have any comments we would appreciate a 
	message to yjy01@mails.tsinghua.edu.cn.
*/

#include "kick.h"
#include "global.h"

/**************	My OA	****************/
void MyOA::Initvpos(char* filename){
	int i,j,k,l;
	for(i=0; i<KICKDIS; i++){
		for(j=0; j<KICKAGL; j++){
			oapos[i][j].idx_dis = i;
			oapos[i][j].idx_agl = j;
			oapos[i][j].enabled = true;
			oapos[i][j].pos = Polar2Vector(SP_kickable_margin*(i+0.5f)/KICKDIS + SP_ball_size + SP_player_size,360.0f*j/KICKAGL);
		}
	}

	FILE* fp;
	if(filename!=NULL) fp = fopen(filename,"r");
	if(fp == NULL){
		for(i=0; i<KICKDIS; i++){
			for(j=0; j<KICKAGL; j++){
				for(k=0; k<KICKDIS; k++){
					for(l=0; l<KICKAGL; l++){
						oapos[i][j].nextp[k*KICKAGL+l] = &oapos[k][l];
					}
				}
			}
		}	
		return;
	}
	fscanf(fp,"%f",&Tvel.x);
	fscanf(fp,"%f",&Tvel.y);

	Vector vel;
	float maxvel = Sqr(SP_ball_speed_max);
	float minv = -1.0f;
	float tmp;
	for(i=0; i<KICKDIS; i++){
		for(j=0; j<KICKAGL; j++){
			for(k=0; k<KICKDIS; k++){
				for(l=0; l<KICKAGL; l++){
					oapos[i][j].nextp[k*KICKAGL+l] = &oapos[k][l];
					fscanf(fp,"%f",&tmp);
					oapos[i][j].qvalue[k*KICKAGL+l] = tmp;
				}
			}
			//排序
			for(k = 0; k<KICKDIS*KICKAGL-1; k++){
				int max = k;
				float maxv = oapos[i][j].qvalue[max];
				for(l = k+1; l<KICKDIS*KICKAGL; l++){
					if(oapos[i][j].qvalue[l] > maxv){
						max = l;
						maxv = oapos[i][j].qvalue[l];
					}
				}
				if(max != k){
					Swap(oapos[i][j].qvalue[k],oapos[i][j].qvalue[max]);
					Swap(oapos[i][j].nextp[k],oapos[i][j].nextp[max]);
				}
			}
			oapos[i][j].nextp[KICKDIS*KICKAGL] = NULL;
		}
	}

	if(fp!=NULL) fclose(fp);
} 

void MyOA::SetInitState(Vector pos, Vector vel, Vector pvel, float bodyfacing){
	s_pos = pos;
	s_vel = vel;
	p_vel[0] = pvel;
	for(int i=1; i<maxdepth; i++) p_vel[i] = p_vel[i-1] * SP_player_decay;
	bdfacing = bodyfacing;
	//float fvalue = motion.GetStateV(pos,vel);
	float hestimate = 0;
	int idx1= getdisidx(pos.mod());
	int idx2 = getaglidx(pos.Angle());

	kstate s(getkickpos(idx1,idx2));
	s.depth = 0;
	SetInitial(s,hestimate);
	DoLog(LOG_OAKICK, "setinitial");
}

void MyOA::Extend(OAnode<kstate>* pnode){
	if(pnode == NULL) return;
	if(pnode->data.depth >= maxdepth) return;

	kstate* pstate = &pnode->data;
	OApos* npos;	
	float hvalue,cost;
	Vector pos,vel,pmove;
	if(pnode->Getwaypre() == NULL){
		pos = s_pos;
		vel = s_vel;
	}else{
		pos = pnode->data.pos->pos;
		Vector lpos;
		if(pnode->Getwaypre()->Getwaypre() == NULL) lpos = s_pos;
		else lpos = pnode->Getwaypre()->data.pos->pos;
		vel = (pos + p_vel[pnode->data.depth-1] - lpos) * SP_ball_decay;
	}
	int counts = 0;
	while((npos = pstate->Subnode()) != NULL && (counts++)< 100){
		pstate->subnode ++;
		if(!npos->enabled) {
			DoLog(LOG_OAKICK,"skip (%.2f %.2f) %d", npos->pos.x, npos->pos.y, counts);
			continue;
		}
		if(!Canreachpos(pos, vel, bdfacing, npos->pos+p_vel[pnode->data.depth]))	continue;
		kstate nstate(npos);
		if(closelist.FindNode(nstate) != NULL) continue;
		//enqueue cstate's valid nextsubnode
		OAnode<kstate>* ptmp = openlist.FindNode(nstate);
		hvalue = pstate->pos->qvalue[pstate->subnode-1];
		cost = pnode->Getcost() + stepcost;
		if(ptmp == NULL){
			kstate s(npos);
			OAnode<kstate>* node = new OAnode<kstate>(nstate);
			node->Sethvalue(hvalue);
			node->Setcost(cost);
			node->Setwaypre(pnode);
			node->data.depth = pnode->data.depth + 1;
			openlist.enqueue(node);
			break;
		}else if(ptmp->Gethvalue() < hvalue){
			ptmp->Sethvalue(hvalue);
			OAnode<kstate>* ptmp2 = ptmp->Getwaypre(); 
			ptmp->Setwaypre(pnode);
			ptmp->data.depth = ptmp2->data.depth + 1;
			//extend another pstate's sub node
			pnode = ptmp2;
			pstate = &pnode->data ;
		}
	}
	DoLog(LOG_OAKICK,"extend counts %d",counts);
} 

void MyOA::Extendcurnode(){
	if(curnode == NULL) return;
	DoLog(LOG_OAKICK,"oa extend 1");
	Extend(curnode->Getwaypre());
	DoLog(LOG_OAKICK,"oa extend 2");
	Extend(curnode);
}

bool MyOA::IsTargetState(){
	Vector pos,vel;
	if(curnode->Getwaypre() == NULL){
		pos = s_pos;
		vel = s_vel;
	}else{
		Vector lpos;
		pos = curnode->data.pos->pos;
		if(curnode->Getwaypre()->Getwaypre() == NULL){
			lpos = s_pos;
		}else
			lpos = curnode->Getwaypre()->data.pos->pos;
		vel = (pos + p_vel[curnode->data.depth-1] - lpos) * SP_ball_decay;
	}
	return Canreachvel(pos,vel,bdfacing,dvel);
}

void MyOA::Enableall(){
	for(int i=0; i<KICKDIS; i++){
		for(int j=0; j<KICKAGL; j++){
			oapos[i][j].enabled = true;
		}
	}
} 

Vector MyOA::Getnextpos(){
	OAnode<kstate>* tmp1 = curnode;
	OAnode<kstate>* tmp2 = tmp1->Getwaypre(); 
	while(tmp2 != NULL){
		if(tmp2->Getwaypre() == NULL){
			return tmp1->data.pos->pos;
		}
		tmp1 = tmp2;
		tmp2 = tmp1->Getwaypre();
	}
	return Vector(0,0);
}

Vector MyOA::Getfirstkick(){
	OAnode<kstate>* tmp1 = curnode;
	OAnode<kstate>* tmp2 = tmp1->Getwaypre(); 
	while(tmp2 != NULL){
		if(tmp2->Getwaypre() == NULL){
			return tmp1->data.pos->pos + p_vel[0] - s_pos - s_vel;
		}
		tmp1 = tmp2;
		tmp2 = tmp1->Getwaypre();
	}
	return Vector(-s_vel.x, -s_vel.y);
}

bool MyOA::Canreachvel(Vector& bpos, Vector& bvel, float bdfacing, Vector& next_bvel, float* effort){
	float dist_ball = bpos.mod() - SP_player_size - SP_ball_size;
	if(dist_ball > SP_kickable_margin) return false;
	float dir_diff = (float)fabs(Deg2Rad(NormalizeAngle(bpos.Angle() - bdfacing)));
	float eff_power = SP_max_power * SP_kick_power_rate * 
		(1 - 0.25f*dir_diff/PI - 0.25f*dist_ball/SP_kickable_margin);//to be modified

	float gap = (next_bvel- bvel).mod() ;
	if(effort!=NULL) *effort = gap / eff_power ;
	if(gap > eff_power)	return false;
	else return true;
}

bool MyOA::Canreachpos(Vector& bpos, Vector& bvel, float bdfacing, Vector& next_bpos, float* effort){
	Vector tvel = next_bpos - bpos;
	if(tvel.mod2() > Sqr(SP_ball_speed_max)) return false;
	return Canreachvel(bpos,bvel,bdfacing,tvel,effort);
}

/***********	Kick	********************/
Kick::Kick(){
	speedinc[0] = 0.0f;
	maxinc_angle[0] = 0.0f;
	speedinc[1] = 0.0078f;
	maxinc_angle[1] = 5.7296f;
	speedinc[2] = 0.0316f;
	maxinc_angle[2] = 11.4592f;
	speedinc[3] = 0.0718f;
	maxinc_angle[3] = 17.7617f;
	speedinc[4] = 0.1293f;
	maxinc_angle[4] = 24.0642f;
	speedinc[5] = 0.2051f;
	maxinc_angle[5] = 30.9397f;
	speedinc[6] = 0.3000f;
	maxinc_angle[6] = 38.3882f;
	speedinc[7] = 0.4143f;
	maxinc_angle[7] = 46.4096f;
	speedinc[8] =  0.5475f;
	maxinc_angle[8] = 55.0039f;
	speedinc[9] = 0.6974f;
	maxinc_angle[9] = 64.7442f;
	speedinc[10] = 0.8601f;
	maxinc_angle[10] = 75.0575f;
	speedinc[11] = 1.0274f;
	maxinc_angle[11] = 83.0789f;
	speedinc[12] = 1.1455f;
	maxinc_angle[12] = 83.0789f;
	speedinc[13] = 1.1928f;
	maxinc_angle[13] = 83.0789f;
	speedinc[14] = 1.1677f;
	maxinc_angle[14] = 83.0789f;
	speedinc[15] = 1.0711f;
	maxinc_angle[15] = 83.0789f;
	speedinc[16] = 0.9060f;
	maxinc_angle[16] = 83.0789f;
	speedinc[17] = 0.6774f;
	maxinc_angle[17] = 83.0789f;
	speedinc[18] = 0.3951f;
	maxinc_angle[18] = 83.0789f;
}
/* Function smartkick  kick to desire angle with desire speed*/
float Kick::smartkick(float kickspeed, AngleDeg kickangle, Command& command, KK_Mode mode){
	command.Reset();
	if (!ball.kickable()) return 0.0f;

	Vector dvel;
	if (ball.speed_valid())
		dvel = Polar2Vector(kickspeed, kickangle) - ball.global_vel;
	else
		dvel = Polar2Vector(kickspeed, kickangle);

	float angle = NormalizeAngle(dvel.Angle() - Self.bodyfacing);
	float power = dvel.mod() / action.Kickrate();

	if (power > SP_max_power || power < SP_min_power){
		/* try to kick harder than allowed*/
		if (!ball.speed_valid() || ball.speed < FLOAT_EPS){
			pose_limitation(power, SP_min_power, SP_max_power);
		}
		else{
			/* try to kick to the right direction, the kickspeed may not be desire, but
			the angle is correct. And we do our best with the kickspeed.
			It is a ray intersection problem. The idea is from CMU.*/
			Vector solution1, solution2, gap;
			Ray vel(ball.pos, kickangle);
			int num_of_solutions = vel.CircleIntersect(SP_max_power * action.Kickrate(), 
				ball.PredictPos(1), solution1, solution2);
			if (num_of_solutions == 0){
				/* can not kick to the right trajectory. just try to stop it*/
				power = ball.speed / action.Kickrate();
				pose_limitation(power, SP_min_power, SP_max_power);
				angle = NormalizeAngle(ball.vel_angle - Self.bodyfacing + 180);
				command.kick(power, angle);
				my_error("No solution. So stop it!");
			}
			else{
				if (mode == KK_fast)
					gap = solution2 - ball.PredictPos(1);
				else
					gap = solution1 - ball.PredictPos(1);
				power = gap.mod() / action.Kickrate();
				angle = NormalizeAngle(gap.Angle() - Self.bodyfacing);
				pose_limitation(power, SP_min_power, SP_max_power);
			}
		}
	}

	Vector kickvel;
	if (ball.speed_valid()){
		kickvel = ball.global_vel + Polar2Vector(power * action.Kickrate(), angle + Self.bodyfacing);
	}
	else{
		kickvel = Polar2Vector(power * action.Kickrate(), angle + Self.bodyfacing);
	}
	command.kick(power, angle);
	Vector kickeffect = Polar2Vector(power, angle + Self.bodyfacing) * action.Kickrate();
	return kickvel.mod();
}

float Kick::smartkick(float speed, AngleDeg ang, KK_Mode mode){
	Command command;
	float kickspeed;
	kickspeed = smartkick(speed, ang, command, mode);
	mediator.enroll(command, Action_other, PriorityA);
	return kickspeed;
}

KT_Res Kick::turn_ball(TurnDir dir, AngleDeg turn_angle, float turnball_radius, KK_Mode kk_mode){
	Command command;
	KT_Res res = turn_ball(dir, turn_angle, command, turnball_radius, kk_mode);
	mediator.enroll(command, Action_turn_ball, PriorityA);
	return res;
}

KT_Res Kick::turn_ball(TurnDir dir, AngleDeg turn_angle, Command& command, float turnball_radius, KK_Mode kk_mode){
	if(!ball.kickable()){
		return KT_lostball;
	}
	else {
		float kickspeed, kickangle;
		if (ball.distance < CP_turnball_radius_threshold) {
			// the ball is too close
			kickspeed = CP_kickballaway_speed;
			kickangle = ball.global_angle;

			CorrectForMyVel(kickspeed, kickangle);
			smartkick(kickspeed, kickangle, command, kk_mode);
			return KT_kickaway;

⌨️ 快捷键说明

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