微软千人机器人足球赛:规则、策略、接口
[ 2006-04-10 11:16:17 | 作者: 坤坤 ]
我所搜集的资料,没带优盘,先放这里,回宿舍和在看
大部分为吕雄,李延 先生提供,在此表示感谢
微软千人机器人足球赛官方网站:http://www.s1000.org/
千人工程:http://www.soft1000.org/
一、足球赛比赛规则
1、赛前准备
各参赛队应根据比赛时间安排,提前半小时进入比赛区域,做赛前检查及准备调试。
为了验证机器人的编程是否参赛选手自己制作完成,在比赛前将要求参赛选手陈述其机器人的编程思路。
2、猜边:
参赛双方用投币方式选定开球或场地。选定后,参赛双方有2分钟的准备时间。
3、开球:
开球时,所有的机器人都必须位于自己的半场,且必须处于静止状态。所有不开球的机器人必须离球大于25cm。开球方将开球机器人放置在距足球2cm至5cm位置。裁判可以调整机器人的位置,并宣布完成调整。由裁判将比赛双方代码调入。开球机器人触球后,其他机器人方可触球。
某方进球后,应由对方以同样方式,重新开球继续比赛。
下半场,参赛双方互换场地及开球权。
4、比赛时间:
常规赛:比赛分上下两个半场,各5分钟,中场休息时间2分钟,比赛开始前,每队有2分钟的准备调试时间。比赛时钟将持续计时(两个5分钟半场),不会停止。计时器由裁判来控制。由于坠球、罚点球、延误时间及其它原因损失的时间均应扣除。
加时赛:比赛需有胜负时,且双方在10分钟比赛中打成平局,另加加时赛。加时赛分上下两个半场,各2分钟,中间不休息。加时赛规则同上(包括猜边、开球等)。加时赛采取突然死亡法,即一方进球后比赛结束。
5、点球:
胜负点球:比赛需有胜负时,且双方在加时赛中无进球,则以互罚点球决胜负。
首轮罚点球采用3球制,双方猜边、猜球后,轮流罚点球;完成3个点球后,双方仍平局,则采用轮流各罚1个点球,直至分出胜负。罚点球所用机器人为加时赛结束时所用的机器人。罚点球时,除罚球机器人和对方守门机器人外,其他机器人均应在另外半场。对方守门机器人在球被踢出前,必须站在球门线前的中间点。由裁判将球放置在点球位,罚球方将机器人放置在距足球2cm至5cm位置。裁判吹哨后,方可踢球。
如果踢出的球直接或触及守门机器人而进入球门,或主罚机器人将球带入球门,只要没有犯规现象发生,均应判为进球。
如果守门机器人在球被踢出前发生移动,且足球未进,则判守门机器人违例,重新罚点球。
犯规点球:指常规或加时赛中,机器人严重犯规被判罚的点球。罚球方式同上。如果点球未中,换由对方在原点球位开任意球。
6、防守违例:
防守方的两个机器人不能同时并排在己方球门线前(主动或被动)停留超过5秒钟;防守方任一机器人身体的任何部分均不能(主动或被动)越过己方球门线进入球门里面超过5秒钟。
7、坠球:
由裁判员将足球放在距原在位置最近的坠球点上,双方机器人可摆放在距足球15CM以外的任意地方;裁判吹哨后,开始继续比赛。在摆放机器人位置时,各队在自己半场具有优先摆放权。
8、任意球:
获得任意球的一方可以在球附近放置一个机器人,其它参赛机器人应放置在离球25cm以外。
由裁判员将足球放在发生犯规的地方,如果犯规地点距墙壁小于15cm,则将球放在距墙壁15cm处。
防守违例、点球未中时,判对方在最近的坠球点罚任意球。
裁判鸣哨后,继续开始比赛。开任意球的机器人触球后,其他机器人方可触球。任意球为“两脚球”(即开球直接入门无效),否则换由对方在原坠球点罚任意球。
9、参赛队员:
比赛过程中,未经裁判允许,参赛选手不能操作演示机器。如有特殊情况需要参赛选手调试,可以有队中选出一位队员在裁判监督下进行调试,调试完成后应立即离开演示机器。
10、球的运动:
比赛机器人不能“占据”球,即:机器人不能通过堵死球的移动方向来完全控制球。例如:将球固定在机器人身上,或使用机器人身体将球包围,阻止其它机器人触球。不允许使用包围夹子或圆圈,其它机器人必须能触到球。
11、越位:
比赛没有越位规则。
12、时间暂停:
比赛中没有时间暂停。
13、计胜方法:
在比赛中,进球较多的一方为得胜队,如双方均未进球或进球数目相等,则这场比赛应为“平局”。
犯规与处罚
1、防守违例
防守方的两个机器人同时在己方球门线前主动停留超过5秒钟以上;或防守方任一机器人身体的任何部分主动越过己方球门线进入球门里面。判对方罚任意球。
2、延误开球
开(罚)球时,开(罚)球机器人在5秒钟内未能触及球,判延误开(罚)球。换由对方罚任意球。
3、直接判负
出现下述情况时,直接判定该队为比赛负方:
参赛队员不服从裁判裁决并顶撞裁判。
裁判
每场比赛委派两名裁判员执行裁判任务。裁判员在比赛过程中所作的判决,为最后判决。
裁判员的责任:
1.公平公正地执行规则。
2.避免做出对犯规队有利的判罚。
3.记录比赛成绩和比赛时间,使比赛用足规定的时间或双方同意的时间,并补足由于偶然事故或其它原因所损耗的时间。
4.遇到有疑义的问题时,在裁判员之间进行讨论并作出公正的判决;如果无法讨论出可行的方法,可以向技术老师咨询解决方法。
5.比赛完毕后判定比赛的胜负。
环境
比赛现场不允许有不礼貌的行为,否则,根据裁判和管理委员会的决定,将会被驱逐出比赛现场并有可能取消其比赛资格。
其他
1、现场比赛成绩由裁判员确定并由参赛选手当场确认。逾期不得追诉和更改。
2、参赛选手对于裁判的决定必须服从。如有不同意见可以向机器人足球大赛组委会相关成员申述意见,但在竞赛现场不得干扰竞赛的正常秩序。
二、守门员防守策略
在FIRA比赛中,一个好的进攻策略固然重要,但防守策略的设计在某种程序上显得更为重要,尤其是守门员的防守策略。
本文的策略核心是以小球的位置为中心,守门员为主要执行对象,一切以小球为出发点,不考虑对方的进攻方式,只考虑进攻结果,以及守门员采取的策略。
1. 球与球场信息的综合分析
策略的核心是“以小球为中心,守门员为主要执行对象”,所以在考虑守门员如何决策之前,先获取小球的有关信息。
为配合策略设计,对比赛场地进行划分,场地划分基于一个原则:小球离守门员方向门区越近,进球概率越高,危险级别越高;反之,球离球门越远,危险级别越低。
根据以上两方面的分析,对球与场地进行综合分析:
(1) 对于小球,除了需要获取其位置,速度大小外,还需要预测出球在场地中的运动方向,用矢量V来表示,当V指向自己半场时,称其为“向已方运动”,当V指向对方半场时,称其为“向对方运动”,在做“向已方运动”的情况下,当V指向门区,称其为“向球门方向运动”,当V指向门区以外的位置,称其为“不向球门运动”。
(2) 当小球做“向对方运动”时危险级别比较低,为了简化策略的设计,将其和“不向球门运动”统一考虑
(3) 当小球处于某分区内时,根据分区的危险级别,对守门员进行相应的设置,对于球在不同危险级别的区域内时,守门员的策略也应该相应变化。
守门员应该具备以下3个属性:
(1) 预测守门员应该达到的位置:当小球作“向已方运动”时,根据小球运动方向预测出小球的运动轨迹,该轨迹必定与球门所在直线有一个交点,将这个点定义为球到达的位置,这个交点应作为守门员重点参考的位置,守门员根据此交点的位置作相应的调整,在球场中得出一个较优的防守位置,将这个位置定义为守门员应该到达的位置。
(2) 守门员运动轨迹:当预测守门员应该到达的位置后,假如守门员并不在这个位置,并且与该位置有一定距离,守门员必须运动一段距离才能到达这个位置,守门员可以直线运动到这个位置,也可以曲线运动到达上述预测位置,将这种运动路线称为守门员运动轨迹。
(3) 守门员运动速度:当守门员应该到达的位置和守门员运动轨迹确定后,根据策略需要,给守门员的运动速度赋值,这个速度必须满足上述两个要求。
2. 守门员具体策略
以小球为中心对守门员进行具体策略的设计时,根据球的不同运动情况将策略整体分为“不向球门方向运动”和“向球门方向运动”两个模块。
2.1 不向球门方向运动
为方便阐述,将球在球场中的位置抽象为ball(x, y),以下将用ball.x和ball.y代表球在球场坐标系下X轴坐标和Y轴坐标。场地抽象如图1所示:
2.1.1 边线防守
当球在1,7,10,13时,这些区域均靠近连线,可整体考虑。守门员应在向禁区上方某一位置附近进行拦截。但由于球和门区的距离不同,其危险等级也不同,所以守门员应该到达的位置也不同。
1区域危险性较高,守门员应到A位置去等,此位置离禁区边沿较近,可在对方队员进攻时,将球卡在禁区以外,这样做是为了不违反比赛规则。
若球在7区域,守门员应到B位置去等,该位置的确定是通过门区中心与该区域中心的连线与球场坐标系下的一条直线的交点所确定的。因为小球的方向往场地下方跑时,必须过中线附近区域(5,6,8),所以可在相应区域进行位置调整,小球往上方跑的几率比较大,所以应去该位置防守。
三、关于机器人程序的讲解
请注意
平台提供了基本的策略开发框架,见安装目录下的Strategy Source目录 如:C:\Program Files\Robot Soccer v1.5a\Strategy Source)。其模板程序为DLL动态联接库。
一 如何要小车运动
第一点: 在源程序中找到 Strategy 函数
extern "C" STRATEGY_API void Strategy ( Environment *env )
{
switch(env->gamestate)
{
case 0:
//我们只需要对小车的轮子进行赋值 小车就可以动了
int nName = 1; // 1小车的名字
env->home[nName].velocityLeft = 100; // 左轮
env->home[nName].velocityRight = 100; // 右轮
nName = 2; // 2小车的名字
env->home[nName].velocityLeft = 60; // 左轮
env->home[nName].velocityRight = 100; // 右轮
// 小车的转角控制
// 让0号小车 旋转30度
Angle( env->home[0], 30 );
// 让0号小车 旋转60度
Angle( env->home[1], -60 );
// 让0号小车 旋转130度
Angle( env->home[3], 130 );
// 让0号小车 旋转100度
Angle( env->home[4], -100 );
// 小车变换运动
// Position 函数包含 Angle 和 Velocity 函数功能
// 让0号机器人在球门附近跟着球的y坐标跑
Position( &env->home[0], env->goalBounds.left + 10, env->lastBall.pos.y );
// 让1号机器人追着球跑
Position( &env->home[1], env->lastBall.pos.x, env->lastBall.pos.y );
// 让2号机器人追着1号机器人跑
Position( &env->home[2], env->home[1].pos.x, env->home[1].pos.y );
}
}请注意
平台提供了基本的策略开发框架,见安装目录下的Strategy Source目录 如:C:\Program Files\Robot Soccer v1.5a\Strategy Source)。其模板程序为DLL动态联接库。
一 如何要小车运动
第一点: 在源程序中找到 Strategy 函数
extern "C" STRATEGY_API void Strategy ( Environment *env )
{
switch(env->gamestate)
{
case 0:
//我们只需要对小车的轮子进行赋值 小车就可以动了
int nName = 1; // 1小车的名字
env->home[nName].velocityLeft = 100; // 左轮
env->home[nName].velocityRight = 100; // 右轮
nName = 2; // 2小车的名字
env->home[nName].velocityLeft = 60; // 左轮
env->home[nName].velocityRight = 100; // 右轮
// 小车的转角控制
// 让0号小车 旋转30度
Angle( env->home[0], 30 );
// 让0号小车 旋转60度
Angle( env->home[1], -60 );
// 让0号小车 旋转130度
Angle( env->home[3], 130 );
// 让0号小车 旋转100度
Angle( env->home[4], -100 );
// 小车变换运动
// Position 函数包含 Angle 和 Velocity 函数功能
// 让0号机器人在球门附近跟着球的y坐标跑
Position( &env->home[0], env->goalBounds.left + 10, env->lastBall.pos.y );
// 让1号机器人追着球跑
Position( &env->home[1], env->lastBall.pos.x, env->lastBall.pos.y );
// 让2号机器人追着1号机器人跑
Position( &env->home[2], env->home[1].pos.x, env->home[1].pos.y );
}
}
四、机器人足球仿真程序接口程序解释
接口代码解析
程序的接口API函数:
函数接口 Create 主要是程序的初始化,在程序开始时由系统调用,主要作用是定义自有的数据,如创建对应于:Environment->userData 的数据,其中可以用来存储我们的策略执行状态等
extern "C" STRATEGY_API void Create ( Environment *env );
函数接口 Destroy主要是程序的销毁,在程序结束时由系统调用,主要作用是释放自定义的数据,如删除对应于:Environment->userData 的数据
extern "C" STRATEGY_API void Destroy ( Environment *env );
函数接口 Strategy是程序的主要执行逻辑,由系统反复调用,每次调用相当于真实系统下计算出新的机器人左右轮的速率,并发送给小车,在这里,我们必须处理针对赛场上每一时刻的对策,每秒调用60次,即仿真周期为1/60秒。
extern "C" STRATEGY_API void Strategy ( Environment *env );
实际上程序只需要这三个接口,而我们的工作就是完成这几个接口的处理。
程序的基本数据定义:
Vector3D 位置向量定义
typedef struct
{
double x, y, z;
} Vector3D;
Bounds 区域范围定义
typedef struct
{
long left, right, top, bottom;
} Bounds;
Robot 我方机器人的信息定义
typedef struct
{
Vector3D pos; //机器人的坐标位置
double rotation; //机器人当前的转角
double velocityLeft, velocityRight; //机器人的左右轮的速度
} Robot;
OpponentRobot 对方机器人的信息的定义
typedef struct
{
Vector3D pos; //机器人的坐标位置
double rotation; //机器人当前的转角
} OpponentRobot;
Ball 小球的位置定义
typedef struct
{
Vector3D pos; //小球的坐标位置
} Ball;
Environment 最重要的数据定义,包含所有运行时的信息,由系统刷新
typedef struct
{
Robot home[PLAYERS_PER_SIDE]; //我方机器人数组
OpponentRobot opponent[PLAYERS_PER_SIDE]; //敌方机器人数组
Ball currentBall, //当前小球的位置
lastBall, //上一次小球的位置
predictedBall; //预计的小球的位置
Bounds fieldBounds, //场地范围
goalBounds; //球门的位置与范围
long gameState; //当前游戏的状态
long whosBall; //由谁控制球
void *userData; //用户自定义信息
} Environment;
仿真系统每秒会调用Strategy接口60次,但实际上每秒的执行次数是和当前的硬件配置有关,比如每秒20次。也就是我们的每个处理周期为1/60秒,在每次调用时,系统通过Environment * env这个指针向我们传递当前的系统的运行信息,然后我们通过运算,然后设置我方所有机器人的左右轮转速,依此来控制机器人进行足球比赛。
需要注意的是:程序对于左右半场,应该分别处理。
五、接口代码解析
// 程序和平台之间交互的接口文件// -------------------------------------------
#ifndef _INTERFACE_H_
#define _INTERFACE_H_
// 动态连接库中接口函数声明的宏定义
#ifdef STRATEGY_EXPORTS
#define STRATEGY_API __declspec(dllexport)
#else
#define STRATEGY_API __declspec(dllimport)
#endif
#include <string.h>
#include <stdio.h>
// -------------------------------全局参数----------------------------------------
const double PI = 3.1415923; //
const long PLAYERS_PER_SIDE = 5; // 每队球员个数
// 比赛状态
const long FREE_BALL = 1; // 当是自由球
const long PLACE_KICK = 2; // 点球
const long PENALTY_KICK = 3; // 罚球
const long FREE_KICK = 4; // 任意球
const long GOAL_KICK = 5; // 门球
// 发球方
const long ANYONES_BALL = 0; // 没有发球方
const long BLUE_BALL = 1; // 蓝队发球
const long YELLOW_BALL = 2; // 黄队发球
// 场地信息
const double FTOP = 77.2392; // 场地上边界
const double FBOT = 6.3730; // 场地下边界
const double FRIGHTX = 93.4259; // 场地右边界
const double FLEFTX = 6.8118; // 场地左边界
const double GTOPY = 49.6801; // 球门上边界
const double GBOTY = 33.9320; // 球门下边界
const double GRIGHT = 97.3632; // 球门右边界
const double GLEFT = 2.8748; // 球门左边界
//位置向量定义
typedef struct
{
double x, y, z;
} Vector3D;
//区域范围定义
typedef struct
{
long left, right, top, bottom;
} Bounds;
//机器人的信息定义
typedef struct
{
Vector3D pos; //机器人坐标
double rotation; //机器人方向角
double velocityLeft, velocityRight; //机器人左右轮速度
} Robot;
//对方机器人的信息的定义
typedef struct
{
Vector3D pos; //机器人的坐标位置
double rotation; //机器人当前的转角
} OpponentRobot;
//小球的位置定义
typedef struct
{
Vector3D pos; //小球的坐标位置
} Ball;
//主要的定义,包含所有运行时的的信息,由系统刷新
typedef struct
{
Robot home[PLAYERS_PER_SIDE]; //我方机器人数组
OpponentRobot opponent[PLAYERS_PER_SIDE]; //敌方机器人数组
Ball currentBall, //当前小球的位置
lastBall, //上一次小球的位置
predictedBall; //预计的小球的位置
Bounds fieldBounds, //场地范围
goalBounds; //球门的位置与范围
long gameState; //当前游戏的状态
long whosBall; //由谁控制球
void *userData; //用户自定义信息
} Environment;
//##ModelId=440D001A0271
typedef void (*MyStrategyProc)(Environment*);
extern "C" STRATEGY_API void Create ( Environment *env ); // Create 程序的初始化
extern "C" STRATEGY_API void Strategy ( Environment *env ); // Strategy 程序的主要执行逻辑
extern "C" STRATEGY_API void Destroy ( Environment *env ); // Destroy 程序的销毁
#endif // _INTERFACE_H_
// -------------------------------------------// 程序和平台之间交互的接口文件实现
#include <windows.h>
#include "InterFace.h"
#include "Strategy.h"
BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved )
{
return TRUE;
}
extern "C" STRATEGY_API void Create ( Environment *env )
{
}
extern "C" STRATEGY_API void Destroy ( Environment *env )
{
}
extern "C" STRATEGY_API void Strategy ( Environment *env )
{
int testInt = 100;
int nIndex = 0;
switch (env->gameState)
{
case 0:
{
// 缺省情况下的策略
// 三个机器人进行追逐对方的策略
MoonFollowOpponent ( &env->home [1], &env->opponent [2] );
MoonFollowOpponent ( &env->home [2], &env->opponent [3] );
MoonFollowOpponent ( &env->home [3], &env->opponent [4] );
// 第四个抢球
MoonAttack ( &env->home [4], env );
// 守门员守门
Goalie1 ( &env->home [0], env );
}
break;
case FREE_BALL:
{
// 跟随对方机器人
MoonFollowOpponent ( &env->home [1], &env->opponent [2] );
MoonFollowOpponent ( &env->home [2], &env->opponent [3] );
MoonFollowOpponent ( &env->home [3], &env->opponent [4] );
// 抢球
MoonAttack ( &env->home [4], env );
// 守门员守门
Goalie1 ( &env->home [0], env );
}
break;
case PLACE_KICK:
{
// 发生坠球时的策略
// 由二号小车发球
MoonAttack ( &env->home [2], env );
}
break;
case PENALTY_KICK:
// 发生罚球时的策略
switch (env->whosBall)
{
case ANYONES_BALL:
MoonAttack ( &env->home [1], env );
break;
case BLUE_BALL:
MoonAttack ( &env->home [4], env );
break;
case YELLOW_BALL:
MoonAttack ( &env->home [0], env );
break;
}
break;
case FREE_KICK:
{
// 保存对方机器人的相关坐标
FILE * pDebugFile = NULL;
pDebugFile = fopen("debugfile.txt", "a");
for( nIndex = 0; nIndex < PLAYERS_PER_SIDE; nIndex++ )
{
fprintf( pDebugFile, "robot: %d x: %f y: %f z: %f \n",
nIndex, env->opponent[nIndex].pos.x,
env->opponent[nIndex].pos.y,
env->opponent[nIndex].pos.z );
}
fclose(pDebugFile);
// 发生任意球时的策略
MoonAttack ( &env->home [0], env );
}
break;
case GOAL_KICK:
{
// 发生点球时的策略
MoonAttack ( &env->home [0], env );
}
break;
}
}
六、恶心战术
众所周知 这个机器人很难对球进行完美的控制 所以想进行传球等动作都是比较困难的 在这样的情况下我们应该怎么办比较好呢??
这个问题的答案很简单 边路进攻 因为这个比赛的规则中没有出界 所以我们可以尽量把球打向边路 然后使用三个 四个 甚至是五个小车全力的推动 在这种情况下 球不是推进对方球门就是被推入自己球门或者是进入死球状态 为了不被推入自己的球门,我们可以故意用守门员去冲撞对方的进攻球员 或者是因对方两个球员进入禁区导致对方犯规 这是一种简单可行的战术 由哈尔滨师范大学在世界上首先使用 现在国内的强队基本上都对这方面有所加强
我把这个战术列在这里只是为了抛砖引玉 顺便 这个方法比较好实现 在刚接触的情况下很容易入手且打出好的成绩 希望大家能提出更多的意见
七、关于小车转弯半径的讨论研究
为了使得我们的小车运动精确
我们很有必要知道小车左右轮速度跟转弯半径间的关系
我们首先定义一些参数
小车左右轮速度 Vl, Vr
转半园弯所用时间 △T
小车轮距 D
运动内圈半径 R
派P
设 小车初始状态朝上 右轮向内, 顺时钟方向运动半圆周 到小车方向朝下 右轮向内
由于左右轮运动时间相同,且完成的都是半园周运动 所以我们得到一下公式:
运动距离:
Vr * △T = P * R ;
Vl * △T = P * (R + D);
上下两式相除得到
Vr / Vl = R / (R + D);
演算得: R = (Vr * D) / (Vl - Vr);
永久地址: http://www.kyhut.com/feed.asp?q=comment&id=185
引用地址: http://www.kyhut.com/trackback.asp?id=185
大部分为吕雄,李延 先生提供,在此表示感谢
微软千人机器人足球赛官方网站:http://www.s1000.org/
千人工程:http://www.soft1000.org/
一、足球赛比赛规则
1、赛前准备
各参赛队应根据比赛时间安排,提前半小时进入比赛区域,做赛前检查及准备调试。
为了验证机器人的编程是否参赛选手自己制作完成,在比赛前将要求参赛选手陈述其机器人的编程思路。
2、猜边:
参赛双方用投币方式选定开球或场地。选定后,参赛双方有2分钟的准备时间。
3、开球:
开球时,所有的机器人都必须位于自己的半场,且必须处于静止状态。所有不开球的机器人必须离球大于25cm。开球方将开球机器人放置在距足球2cm至5cm位置。裁判可以调整机器人的位置,并宣布完成调整。由裁判将比赛双方代码调入。开球机器人触球后,其他机器人方可触球。
某方进球后,应由对方以同样方式,重新开球继续比赛。
下半场,参赛双方互换场地及开球权。
4、比赛时间:
常规赛:比赛分上下两个半场,各5分钟,中场休息时间2分钟,比赛开始前,每队有2分钟的准备调试时间。比赛时钟将持续计时(两个5分钟半场),不会停止。计时器由裁判来控制。由于坠球、罚点球、延误时间及其它原因损失的时间均应扣除。
加时赛:比赛需有胜负时,且双方在10分钟比赛中打成平局,另加加时赛。加时赛分上下两个半场,各2分钟,中间不休息。加时赛规则同上(包括猜边、开球等)。加时赛采取突然死亡法,即一方进球后比赛结束。
5、点球:
胜负点球:比赛需有胜负时,且双方在加时赛中无进球,则以互罚点球决胜负。
首轮罚点球采用3球制,双方猜边、猜球后,轮流罚点球;完成3个点球后,双方仍平局,则采用轮流各罚1个点球,直至分出胜负。罚点球所用机器人为加时赛结束时所用的机器人。罚点球时,除罚球机器人和对方守门机器人外,其他机器人均应在另外半场。对方守门机器人在球被踢出前,必须站在球门线前的中间点。由裁判将球放置在点球位,罚球方将机器人放置在距足球2cm至5cm位置。裁判吹哨后,方可踢球。
如果踢出的球直接或触及守门机器人而进入球门,或主罚机器人将球带入球门,只要没有犯规现象发生,均应判为进球。
如果守门机器人在球被踢出前发生移动,且足球未进,则判守门机器人违例,重新罚点球。
犯规点球:指常规或加时赛中,机器人严重犯规被判罚的点球。罚球方式同上。如果点球未中,换由对方在原点球位开任意球。
6、防守违例:
防守方的两个机器人不能同时并排在己方球门线前(主动或被动)停留超过5秒钟;防守方任一机器人身体的任何部分均不能(主动或被动)越过己方球门线进入球门里面超过5秒钟。
7、坠球:
由裁判员将足球放在距原在位置最近的坠球点上,双方机器人可摆放在距足球15CM以外的任意地方;裁判吹哨后,开始继续比赛。在摆放机器人位置时,各队在自己半场具有优先摆放权。
8、任意球:
获得任意球的一方可以在球附近放置一个机器人,其它参赛机器人应放置在离球25cm以外。
由裁判员将足球放在发生犯规的地方,如果犯规地点距墙壁小于15cm,则将球放在距墙壁15cm处。
防守违例、点球未中时,判对方在最近的坠球点罚任意球。
裁判鸣哨后,继续开始比赛。开任意球的机器人触球后,其他机器人方可触球。任意球为“两脚球”(即开球直接入门无效),否则换由对方在原坠球点罚任意球。
9、参赛队员:
比赛过程中,未经裁判允许,参赛选手不能操作演示机器。如有特殊情况需要参赛选手调试,可以有队中选出一位队员在裁判监督下进行调试,调试完成后应立即离开演示机器。
10、球的运动:
比赛机器人不能“占据”球,即:机器人不能通过堵死球的移动方向来完全控制球。例如:将球固定在机器人身上,或使用机器人身体将球包围,阻止其它机器人触球。不允许使用包围夹子或圆圈,其它机器人必须能触到球。
11、越位:
比赛没有越位规则。
12、时间暂停:
比赛中没有时间暂停。
13、计胜方法:
在比赛中,进球较多的一方为得胜队,如双方均未进球或进球数目相等,则这场比赛应为“平局”。
犯规与处罚
1、防守违例
防守方的两个机器人同时在己方球门线前主动停留超过5秒钟以上;或防守方任一机器人身体的任何部分主动越过己方球门线进入球门里面。判对方罚任意球。
2、延误开球
开(罚)球时,开(罚)球机器人在5秒钟内未能触及球,判延误开(罚)球。换由对方罚任意球。
3、直接判负
出现下述情况时,直接判定该队为比赛负方:
参赛队员不服从裁判裁决并顶撞裁判。
裁判
每场比赛委派两名裁判员执行裁判任务。裁判员在比赛过程中所作的判决,为最后判决。
裁判员的责任:
1.公平公正地执行规则。
2.避免做出对犯规队有利的判罚。
3.记录比赛成绩和比赛时间,使比赛用足规定的时间或双方同意的时间,并补足由于偶然事故或其它原因所损耗的时间。
4.遇到有疑义的问题时,在裁判员之间进行讨论并作出公正的判决;如果无法讨论出可行的方法,可以向技术老师咨询解决方法。
5.比赛完毕后判定比赛的胜负。
环境
比赛现场不允许有不礼貌的行为,否则,根据裁判和管理委员会的决定,将会被驱逐出比赛现场并有可能取消其比赛资格。
其他
1、现场比赛成绩由裁判员确定并由参赛选手当场确认。逾期不得追诉和更改。
2、参赛选手对于裁判的决定必须服从。如有不同意见可以向机器人足球大赛组委会相关成员申述意见,但在竞赛现场不得干扰竞赛的正常秩序。
二、守门员防守策略
在FIRA比赛中,一个好的进攻策略固然重要,但防守策略的设计在某种程序上显得更为重要,尤其是守门员的防守策略。
本文的策略核心是以小球的位置为中心,守门员为主要执行对象,一切以小球为出发点,不考虑对方的进攻方式,只考虑进攻结果,以及守门员采取的策略。
1. 球与球场信息的综合分析
策略的核心是“以小球为中心,守门员为主要执行对象”,所以在考虑守门员如何决策之前,先获取小球的有关信息。
为配合策略设计,对比赛场地进行划分,场地划分基于一个原则:小球离守门员方向门区越近,进球概率越高,危险级别越高;反之,球离球门越远,危险级别越低。
根据以上两方面的分析,对球与场地进行综合分析:
(1) 对于小球,除了需要获取其位置,速度大小外,还需要预测出球在场地中的运动方向,用矢量V来表示,当V指向自己半场时,称其为“向已方运动”,当V指向对方半场时,称其为“向对方运动”,在做“向已方运动”的情况下,当V指向门区,称其为“向球门方向运动”,当V指向门区以外的位置,称其为“不向球门运动”。
(2) 当小球做“向对方运动”时危险级别比较低,为了简化策略的设计,将其和“不向球门运动”统一考虑
(3) 当小球处于某分区内时,根据分区的危险级别,对守门员进行相应的设置,对于球在不同危险级别的区域内时,守门员的策略也应该相应变化。
守门员应该具备以下3个属性:
(1) 预测守门员应该达到的位置:当小球作“向已方运动”时,根据小球运动方向预测出小球的运动轨迹,该轨迹必定与球门所在直线有一个交点,将这个点定义为球到达的位置,这个交点应作为守门员重点参考的位置,守门员根据此交点的位置作相应的调整,在球场中得出一个较优的防守位置,将这个位置定义为守门员应该到达的位置。
(2) 守门员运动轨迹:当预测守门员应该到达的位置后,假如守门员并不在这个位置,并且与该位置有一定距离,守门员必须运动一段距离才能到达这个位置,守门员可以直线运动到这个位置,也可以曲线运动到达上述预测位置,将这种运动路线称为守门员运动轨迹。
(3) 守门员运动速度:当守门员应该到达的位置和守门员运动轨迹确定后,根据策略需要,给守门员的运动速度赋值,这个速度必须满足上述两个要求。
2. 守门员具体策略
以小球为中心对守门员进行具体策略的设计时,根据球的不同运动情况将策略整体分为“不向球门方向运动”和“向球门方向运动”两个模块。
2.1 不向球门方向运动
为方便阐述,将球在球场中的位置抽象为ball(x, y),以下将用ball.x和ball.y代表球在球场坐标系下X轴坐标和Y轴坐标。场地抽象如图1所示:
2.1.1 边线防守
当球在1,7,10,13时,这些区域均靠近连线,可整体考虑。守门员应在向禁区上方某一位置附近进行拦截。但由于球和门区的距离不同,其危险等级也不同,所以守门员应该到达的位置也不同。
1区域危险性较高,守门员应到A位置去等,此位置离禁区边沿较近,可在对方队员进攻时,将球卡在禁区以外,这样做是为了不违反比赛规则。
若球在7区域,守门员应到B位置去等,该位置的确定是通过门区中心与该区域中心的连线与球场坐标系下的一条直线的交点所确定的。因为小球的方向往场地下方跑时,必须过中线附近区域(5,6,8),所以可在相应区域进行位置调整,小球往上方跑的几率比较大,所以应去该位置防守。
三、关于机器人程序的讲解
请注意
平台提供了基本的策略开发框架,见安装目录下的Strategy Source目录 如:C:\Program Files\Robot Soccer v1.5a\Strategy Source)。其模板程序为DLL动态联接库。
一 如何要小车运动
第一点: 在源程序中找到 Strategy 函数
extern "C" STRATEGY_API void Strategy ( Environment *env )
{
switch(env->gamestate)
{
case 0:
//我们只需要对小车的轮子进行赋值 小车就可以动了
int nName = 1; // 1小车的名字
env->home[nName].velocityLeft = 100; // 左轮
env->home[nName].velocityRight = 100; // 右轮
nName = 2; // 2小车的名字
env->home[nName].velocityLeft = 60; // 左轮
env->home[nName].velocityRight = 100; // 右轮
// 小车的转角控制
// 让0号小车 旋转30度
Angle( env->home[0], 30 );
// 让0号小车 旋转60度
Angle( env->home[1], -60 );
// 让0号小车 旋转130度
Angle( env->home[3], 130 );
// 让0号小车 旋转100度
Angle( env->home[4], -100 );
// 小车变换运动
// Position 函数包含 Angle 和 Velocity 函数功能
// 让0号机器人在球门附近跟着球的y坐标跑
Position( &env->home[0], env->goalBounds.left + 10, env->lastBall.pos.y );
// 让1号机器人追着球跑
Position( &env->home[1], env->lastBall.pos.x, env->lastBall.pos.y );
// 让2号机器人追着1号机器人跑
Position( &env->home[2], env->home[1].pos.x, env->home[1].pos.y );
}
}请注意
平台提供了基本的策略开发框架,见安装目录下的Strategy Source目录 如:C:\Program Files\Robot Soccer v1.5a\Strategy Source)。其模板程序为DLL动态联接库。
一 如何要小车运动
第一点: 在源程序中找到 Strategy 函数
extern "C" STRATEGY_API void Strategy ( Environment *env )
{
switch(env->gamestate)
{
case 0:
//我们只需要对小车的轮子进行赋值 小车就可以动了
int nName = 1; // 1小车的名字
env->home[nName].velocityLeft = 100; // 左轮
env->home[nName].velocityRight = 100; // 右轮
nName = 2; // 2小车的名字
env->home[nName].velocityLeft = 60; // 左轮
env->home[nName].velocityRight = 100; // 右轮
// 小车的转角控制
// 让0号小车 旋转30度
Angle( env->home[0], 30 );
// 让0号小车 旋转60度
Angle( env->home[1], -60 );
// 让0号小车 旋转130度
Angle( env->home[3], 130 );
// 让0号小车 旋转100度
Angle( env->home[4], -100 );
// 小车变换运动
// Position 函数包含 Angle 和 Velocity 函数功能
// 让0号机器人在球门附近跟着球的y坐标跑
Position( &env->home[0], env->goalBounds.left + 10, env->lastBall.pos.y );
// 让1号机器人追着球跑
Position( &env->home[1], env->lastBall.pos.x, env->lastBall.pos.y );
// 让2号机器人追着1号机器人跑
Position( &env->home[2], env->home[1].pos.x, env->home[1].pos.y );
}
}
四、机器人足球仿真程序接口程序解释
接口代码解析
程序的接口API函数:
函数接口 Create 主要是程序的初始化,在程序开始时由系统调用,主要作用是定义自有的数据,如创建对应于:Environment->userData 的数据,其中可以用来存储我们的策略执行状态等
extern "C" STRATEGY_API void Create ( Environment *env );
函数接口 Destroy主要是程序的销毁,在程序结束时由系统调用,主要作用是释放自定义的数据,如删除对应于:Environment->userData 的数据
extern "C" STRATEGY_API void Destroy ( Environment *env );
函数接口 Strategy是程序的主要执行逻辑,由系统反复调用,每次调用相当于真实系统下计算出新的机器人左右轮的速率,并发送给小车,在这里,我们必须处理针对赛场上每一时刻的对策,每秒调用60次,即仿真周期为1/60秒。
extern "C" STRATEGY_API void Strategy ( Environment *env );
实际上程序只需要这三个接口,而我们的工作就是完成这几个接口的处理。
程序的基本数据定义:
Vector3D 位置向量定义
typedef struct
{
double x, y, z;
} Vector3D;
Bounds 区域范围定义
typedef struct
{
long left, right, top, bottom;
} Bounds;
Robot 我方机器人的信息定义
typedef struct
{
Vector3D pos; //机器人的坐标位置
double rotation; //机器人当前的转角
double velocityLeft, velocityRight; //机器人的左右轮的速度
} Robot;
OpponentRobot 对方机器人的信息的定义
typedef struct
{
Vector3D pos; //机器人的坐标位置
double rotation; //机器人当前的转角
} OpponentRobot;
Ball 小球的位置定义
typedef struct
{
Vector3D pos; //小球的坐标位置
} Ball;
Environment 最重要的数据定义,包含所有运行时的信息,由系统刷新
typedef struct
{
Robot home[PLAYERS_PER_SIDE]; //我方机器人数组
OpponentRobot opponent[PLAYERS_PER_SIDE]; //敌方机器人数组
Ball currentBall, //当前小球的位置
lastBall, //上一次小球的位置
predictedBall; //预计的小球的位置
Bounds fieldBounds, //场地范围
goalBounds; //球门的位置与范围
long gameState; //当前游戏的状态
long whosBall; //由谁控制球
void *userData; //用户自定义信息
} Environment;
仿真系统每秒会调用Strategy接口60次,但实际上每秒的执行次数是和当前的硬件配置有关,比如每秒20次。也就是我们的每个处理周期为1/60秒,在每次调用时,系统通过Environment * env这个指针向我们传递当前的系统的运行信息,然后我们通过运算,然后设置我方所有机器人的左右轮转速,依此来控制机器人进行足球比赛。
需要注意的是:程序对于左右半场,应该分别处理。
五、接口代码解析
// 程序和平台之间交互的接口文件// -------------------------------------------
#ifndef _INTERFACE_H_
#define _INTERFACE_H_
// 动态连接库中接口函数声明的宏定义
#ifdef STRATEGY_EXPORTS
#define STRATEGY_API __declspec(dllexport)
#else
#define STRATEGY_API __declspec(dllimport)
#endif
#include <string.h>
#include <stdio.h>
// -------------------------------全局参数----------------------------------------
const double PI = 3.1415923; //
const long PLAYERS_PER_SIDE = 5; // 每队球员个数
// 比赛状态
const long FREE_BALL = 1; // 当是自由球
const long PLACE_KICK = 2; // 点球
const long PENALTY_KICK = 3; // 罚球
const long FREE_KICK = 4; // 任意球
const long GOAL_KICK = 5; // 门球
// 发球方
const long ANYONES_BALL = 0; // 没有发球方
const long BLUE_BALL = 1; // 蓝队发球
const long YELLOW_BALL = 2; // 黄队发球
// 场地信息
const double FTOP = 77.2392; // 场地上边界
const double FBOT = 6.3730; // 场地下边界
const double FRIGHTX = 93.4259; // 场地右边界
const double FLEFTX = 6.8118; // 场地左边界
const double GTOPY = 49.6801; // 球门上边界
const double GBOTY = 33.9320; // 球门下边界
const double GRIGHT = 97.3632; // 球门右边界
const double GLEFT = 2.8748; // 球门左边界
//位置向量定义
typedef struct
{
double x, y, z;
} Vector3D;
//区域范围定义
typedef struct
{
long left, right, top, bottom;
} Bounds;
//机器人的信息定义
typedef struct
{
Vector3D pos; //机器人坐标
double rotation; //机器人方向角
double velocityLeft, velocityRight; //机器人左右轮速度
} Robot;
//对方机器人的信息的定义
typedef struct
{
Vector3D pos; //机器人的坐标位置
double rotation; //机器人当前的转角
} OpponentRobot;
//小球的位置定义
typedef struct
{
Vector3D pos; //小球的坐标位置
} Ball;
//主要的定义,包含所有运行时的的信息,由系统刷新
typedef struct
{
Robot home[PLAYERS_PER_SIDE]; //我方机器人数组
OpponentRobot opponent[PLAYERS_PER_SIDE]; //敌方机器人数组
Ball currentBall, //当前小球的位置
lastBall, //上一次小球的位置
predictedBall; //预计的小球的位置
Bounds fieldBounds, //场地范围
goalBounds; //球门的位置与范围
long gameState; //当前游戏的状态
long whosBall; //由谁控制球
void *userData; //用户自定义信息
} Environment;
//##ModelId=440D001A0271
typedef void (*MyStrategyProc)(Environment*);
extern "C" STRATEGY_API void Create ( Environment *env ); // Create 程序的初始化
extern "C" STRATEGY_API void Strategy ( Environment *env ); // Strategy 程序的主要执行逻辑
extern "C" STRATEGY_API void Destroy ( Environment *env ); // Destroy 程序的销毁
#endif // _INTERFACE_H_
// -------------------------------------------// 程序和平台之间交互的接口文件实现
#include <windows.h>
#include "InterFace.h"
#include "Strategy.h"
BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved )
{
return TRUE;
}
extern "C" STRATEGY_API void Create ( Environment *env )
{
}
extern "C" STRATEGY_API void Destroy ( Environment *env )
{
}
extern "C" STRATEGY_API void Strategy ( Environment *env )
{
int testInt = 100;
int nIndex = 0;
switch (env->gameState)
{
case 0:
{
// 缺省情况下的策略
// 三个机器人进行追逐对方的策略
MoonFollowOpponent ( &env->home [1], &env->opponent [2] );
MoonFollowOpponent ( &env->home [2], &env->opponent [3] );
MoonFollowOpponent ( &env->home [3], &env->opponent [4] );
// 第四个抢球
MoonAttack ( &env->home [4], env );
// 守门员守门
Goalie1 ( &env->home [0], env );
}
break;
case FREE_BALL:
{
// 跟随对方机器人
MoonFollowOpponent ( &env->home [1], &env->opponent [2] );
MoonFollowOpponent ( &env->home [2], &env->opponent [3] );
MoonFollowOpponent ( &env->home [3], &env->opponent [4] );
// 抢球
MoonAttack ( &env->home [4], env );
// 守门员守门
Goalie1 ( &env->home [0], env );
}
break;
case PLACE_KICK:
{
// 发生坠球时的策略
// 由二号小车发球
MoonAttack ( &env->home [2], env );
}
break;
case PENALTY_KICK:
// 发生罚球时的策略
switch (env->whosBall)
{
case ANYONES_BALL:
MoonAttack ( &env->home [1], env );
break;
case BLUE_BALL:
MoonAttack ( &env->home [4], env );
break;
case YELLOW_BALL:
MoonAttack ( &env->home [0], env );
break;
}
break;
case FREE_KICK:
{
// 保存对方机器人的相关坐标
FILE * pDebugFile = NULL;
pDebugFile = fopen("debugfile.txt", "a");
for( nIndex = 0; nIndex < PLAYERS_PER_SIDE; nIndex++ )
{
fprintf( pDebugFile, "robot: %d x: %f y: %f z: %f \n",
nIndex, env->opponent[nIndex].pos.x,
env->opponent[nIndex].pos.y,
env->opponent[nIndex].pos.z );
}
fclose(pDebugFile);
// 发生任意球时的策略
MoonAttack ( &env->home [0], env );
}
break;
case GOAL_KICK:
{
// 发生点球时的策略
MoonAttack ( &env->home [0], env );
}
break;
}
}
六、恶心战术
众所周知 这个机器人很难对球进行完美的控制 所以想进行传球等动作都是比较困难的 在这样的情况下我们应该怎么办比较好呢??
这个问题的答案很简单 边路进攻 因为这个比赛的规则中没有出界 所以我们可以尽量把球打向边路 然后使用三个 四个 甚至是五个小车全力的推动 在这种情况下 球不是推进对方球门就是被推入自己球门或者是进入死球状态 为了不被推入自己的球门,我们可以故意用守门员去冲撞对方的进攻球员 或者是因对方两个球员进入禁区导致对方犯规 这是一种简单可行的战术 由哈尔滨师范大学在世界上首先使用 现在国内的强队基本上都对这方面有所加强
我把这个战术列在这里只是为了抛砖引玉 顺便 这个方法比较好实现 在刚接触的情况下很容易入手且打出好的成绩 希望大家能提出更多的意见
七、关于小车转弯半径的讨论研究
为了使得我们的小车运动精确
我们很有必要知道小车左右轮速度跟转弯半径间的关系
我们首先定义一些参数
小车左右轮速度 Vl, Vr
转半园弯所用时间 △T
小车轮距 D
运动内圈半径 R
派P
设 小车初始状态朝上 右轮向内, 顺时钟方向运动半圆周 到小车方向朝下 右轮向内
由于左右轮运动时间相同,且完成的都是半园周运动 所以我们得到一下公式:
运动距离:
Vr * △T = P * R ;
Vl * △T = P * (R + D);
上下两式相除得到
Vr / Vl = R / (R + D);
演算得: R = (Vr * D) / (Vl - Vr);
[最后编辑于 坤坤, at 2006-04-11 09:43:25]

引用地址: http://www.kyhut.com/trackback.asp?id=185
此文还没有评论.