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

📄 action.cpp

📁 robot fira SimuroSot 5vs5 (仿真)
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************************************
action.h 艾数机器人角色动作头文件

Purpose:
	角色可以使用的动作

author:
	yy_cn
	
Created Time:
	2006-5-10
****************************************************************************************************/

#include "action.h"

////////////////////////////////////////////////////////////////////////////////////////////////////
//
// 动作系统,提供机器人的一系统动作支持
//

//
// actVelocity
//
void actVelocity (Robot &robot, int vl, int vr)
{
	if (vr > 125)
		vr = 125;
	if (vl > 125)
		vl = 125;
	if (vr < -125)
		vr = -125;
	if (vl < -125)
		vl = -125;

	robot.velocityLeft  = vl;
	robot.velocityRight = vr;
}

//
// move
//
//void move (Robot &robot, BallDirection direction)
//{
//
//}

//
// turn
//
void actTurn (Robot &robot, double angle)
{
	int theta_e, vl, vr;
	theta_e = (int) angle - (int) robot.rotation;	
	
	while (theta_e > 180)
		theta_e -= 360;

	while (theta_e < -180)
		theta_e += 360;

	if (theta_e < -90)
		theta_e += 180;
	else if (theta_e > 90)
		theta_e -= 180;

	if (abs(theta_e) > 50) {
		vl = (int) (-9./90.0 * (double)theta_e);
		vr = (int) (9./90.0 * (double)theta_e);
	}
	else if (abs(theta_e) > 20)  {
		vl = (int) (-11.0/90.0 * (double)theta_e);
		vr = (int) (11.0/90.0 * (double)theta_e);
	}

	if (vl < 0)
		vl = 0;
	if (vr < 0)
		vr = 0;

	actVelocity (robot, vl, vr);
}

//
// toPosition
//
void actToPosition (Robot &robot, double x, double y)
{
	double desired_angle = 0,
		   theta_e = 0,
		   d_angle = 0;
	int	vl,
		vr,
		vc = 200;

	double dx, dy, d_e, Ka = 1.0;//10.0/90.0;

	//
	// 计算到目标位置的直线距离
	//
	d_e = getDistance (robot.pos.x, robot.pos.y, x, y);

	//
	// 计算当前位置与目标的相对位移
	//
	dx = x - robot.pos.x;
	dy = y - robot.pos.y;

	//
	// 计算当前位置到目标点的角度
	//
	if (dx == 0 && dy == 0)
		desired_angle = 90;
	else
		desired_angle = 180. / PI * atan2((double)(dy), (double)(dx));

	//
	// 当前机器人与目标的夹角
	//
	theta_e = desired_angle - robot.rotation;
	
	while (theta_e > 180)
		theta_e -= 360;

	while (theta_e < -180)
		theta_e += 360;

	//if (d_e > 100.) 
	//	Ka = 17. / 90.;			// 0.19
	//else if (d_e > 50)
	//	Ka = 19. / 90.;			// 0.21
	//else if (d_e > 30)
	//	Ka = 21. / 90.;			// 0.23
	//else if (d_e > 20)
	//	Ka = 23. / 90.;			// 0.25
	//else 
	//	Ka = 25. / 90.;			// 0.27

	//if (d_e < 10.0 && d_e > 5.0) {
	//	Ka = 0.1;
	//	vc = 70;
	//}
	//else 
	if (d_e < 10.0 && d_e > 5.0) {
		vc = 40;
	}
	else if (d_e < 4.0 && d_e > 2.0) {
		Ka = 0.1;
		vc = 30;
	}
	else if (d_e < 2.0) {
		Ka = 0.1;
		vc = 20;
	}
	else if (d_e < 1.0) {
		Ka = 0.1;
		vc = 0;
	}
	//if (d_e < 3.0 && d_e > 2.0) {
	//	Ka = 0.1;
	//	vc /= 20;
	//}
	//else if (d_e < 2.0 && d_e > 1.0) {
	//	Ka = 0.1;
	//	vc /= 50;
	//}
	//else if (d_e < 1.0) {
	//	Ka = 0.1;
	//	vc /= 100;
	//}

	if (theta_e > 95 || theta_e < -95) {
		theta_e += 180;
		
		if (theta_e > 180) 
			theta_e -= 360;
		if (theta_e > 80)
			theta_e = 80;
		if (theta_e < -80)
			theta_e = -80;

		//if (d_e < 5.0 && abs(theta_e) < 40)
		//	Ka = 0.1;

		vr = (int) (-vc * (1.0 / (1.0 + exp(-3.0 * d_e)) - 0.3) + Ka * theta_e);
		vl = (int) (-vc * (1.0 / (1.0 + exp(-3.0 * d_e)) - 0.3) - Ka * theta_e);
	}	
	else if (theta_e < 85. && theta_e > -85.) {
		//if (d_e < 5.0 && abs(theta_e) < 40)
		//	Ka = 0.1;

		vr = (int) (vc * (1.0 / (1.0 + exp(-3.0 * d_e)) - 0.3) + Ka * theta_e);
		vl = (int) (vc * (1.0 / (1.0 + exp(-3.0 * d_e)) - 0.3) - Ka * theta_e);
	}
	else {
		vr = (int) (+.1 * theta_e);//(int) (+.17 * theta_e);
		vl = (int) (-.1 * theta_e);//(int) (-.17 * theta_e);
	}

	actVelocity (robot, vl, vr);
}

//
// shoot
//

bool canShoot (double robotX, double robotY, double ballX, double ballY)
{
	/*
		+---------------------------+
		|                           |
		|-            1  2  3      -|- GTOPY		
		| |           4  *  5     | | <- 假设敌方球门
		|-            6  7  8      -|- GBOTY
		|                           |
		+---------------------------+
		<-后                     前->

		1,2,3,4,5,6,7,8 机器人位置
		* 球的位置
	 */
	//
	// 如果机器人的 X 坐标比球的 X 坐标更接近对方球门说明机器人在射门的反方向
	// 不能直接射门,需要跑到球的 X 坐标更接近对方球门的坐标位置
	// 机器人在 3 5 8 位置的情况直接返回不能射门
	//
	if (analyseFieldInfo () == BF_IS_LEFT && robotX > ballX) {
		//
		// 我方在左半场,敌方球门在右半场
		// 机器人的 X 坐标要小于球的坐标才可以直接射门
		//
		return false;
	}
	else if (analyseFieldInfo () == BF_IS_RIGHT && robotX < ballX) {
		//
		// 我方在右半场,敌方球门在左半场
		// 机器人的 X 坐标要大于球的坐标才可以直接射门
		//
		return false;
	}

	//
	// 跟据机器人坐标,球的坐标两点形成的直线映射到对方球门 Y 位置的点
	// 是否在球门范围内来确定是否可以直接射门
	//
	double targetX = OPP_GOAL_CENTER_X;
	double targetY = getMappedTargetY (robotX, robotY, ballX, ballY, targetX);

	//
	// targetY 为跟据 机器人 与 球 之间角度求出 targetX 处 Y 值
	//
	if (targetY < GTOPY && targetY > GBOTY)
		return true;

	return false;
}

void actShoot (Robot &robot, const Environment &env)
{
	//
	// 射门 - 踢球的情况相同
	// 1. 机器人离球非常近,球的速度为中低速,则使用以下方法能够准确的射门
	//    直接以 机器人的中心点 与 球的点心点 形成的一条直线向对方球门区域内移动
	//    将移动的目标点设置为一个比较比较远的位置,此时机器人与球相撞产生的速度能让球快速移动
	//    如果机器人当前的坐标不适合射门,则将机器人移动到一个合适的最近的位置
	//
	// 2. 机器人离球有一定的距离,球的速度为快速,则使用以下方法能够准确的射门
	//    球的运动方向与机器人水平移动的方向能够产生一个交点
	//    且产生交点的机器人移动的方向为敌方方向
	//
	
	//
	// 暂时只考虑 1 的情况
	//
	

	//
	// 射门,先实现简单方法,直接以机器人与球,球门中心的角度踢
	//
	// 有时间的话进行精确的计算,检查机器人,球,球门中心角度的直线上的敌人
	// 射门角度以球所在的区域来击向敌方的死角
	//
	/*
		+------------------+
		|               6 7|
		|-            1   -|
		| |           2  | |
		|-            3   -|
		|               4 5|
		+------------------+
	 */
	double ballX = env.currentBall.pos.x;
	double ballY = env.currentBall.pos.y;

	double targetX, targetY;
	if (canShoot (robot.pos.x, robot.pos.y, ballX, ballY) == false) {
		//
		// 角度不正确,移动机器人到合适的位置 - 面向对方球门方向,在球的边上
		//
		if (analyseFieldInfo () == BF_IS_LEFT) {
			//
			// 我方在左半场,移动到球的左边的一个球位置
			//
			targetX = ballX - BALL_DIAMETER;
		}
		else {
			//
			// 我方在右半场,移动到球的右边的一个球位置
			//
			targetX = ballX + BALL_DIAMETER;
		}

		//
		// 移动的目标点为球门的边角
		//
		double shootX = OPP_GOAL_CENTER_X;
		double shootY = 0;//OPP_GOAL_CENTER_Y;
		if (robot.pos.y < ballY) {
			//
			// 机器人在球的下方
			//
			shootY = GTOPY - BALL_DIAMETER - BALL_DIAMETER;
		}
		else {
			//
			// 机器人在球的上方
			//
			shootY = GBOTY + BALL_DIAMETER - BALL_DIAMETER;
		}

		transform (shootX , shootY);

		//
		// 对方球门中心为第一个点,球为第二个点, targetX 为已知的 X 点,求出 targetY
		//
		targetY = getMappedTargetY (shootX, shootY, ballX, ballY, targetX);
		if (targetX < FLEFTX || targetX > FRIGHTX || targetY < FBOT || targetY > FTOP) {
			//
			// 球靠近场地边框,直接撞球
			//
			actToPosition (robot, ballX, ballY);
			//actBezier2Reach (robot, ballX, ballY, 2.5);
			return;
		}

		//
		// 移动到 targetX, targetY 点
		//
		actToPosition (robot, targetX, targetY);
		//actBezier2Reach (robot, targetX, targetY, 2.5);
		return;
	}

	//
	// 角度正确,获得一个非常远的映射点的为目标点移动达到射门的目的
	// 如果目标点很远,机器人离球越近则射门力度越大
	//
	targetX = FRIGHTX + FIELD_WIDTH / 2;
	transform (targetX, targetY);

	targetY = getMappedTargetY (robot.pos.x, robot.pos.y, ballX, ballY, targetX);
	actToPosition (robot, targetX, targetY);
	//actBezier2Reach (robot, targetX, targetY, 2.5);
}

//
// kickBall
//
/*
	  **********************************
****** 以下参数均以我方在左半场为参考值 *******
	  **********************************

	      A     B          C      D
	    |--|---------|----------|---|
		+---------------------------+
	    |            |              |
	   _|+++         |           +++|_
	  | |  +         |           +  | | ____ 中点 centerY
	  |_|  +         |           +  |_|
		|+++         |           +++|
	    |            |              |
		+---------------------------+
		<-我方球场         敌方球场->

		+---------------------------+
	    |            |              |
	   _|+++         | 1  2  3   +++|_ - GTOPY
	  | |  +         | 4  *  5   +  | | ____ 中点 centerY
	  |_|  +         | 6  7  8   +  |_|
		|+++         |           +++|  - GBOTY
	    |            |              |
		+---------------------------+
		<-后                     前->

		1,2,3,4,5,6,7,8 机器人位置
		* 球的位置

		+---------------------------+
	    |            |              |
	   _|+++         |  1  2  3  +++|_ 
   左 | |  +         |  4  *  5  +  | | 右
	  |_|  +         |  6  7  8  +  |_|
		|+++         |           +++|
	    |            |              |

⌨️ 快捷键说明

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