一、软件安装
需要安装的软件包括 USB 摄像头驱动,全局视觉竞赛平台(大平台),全局视觉
竞赛平台策略工程(策略编写),STM32 串口驱动,全局视觉微型控制平台(小
平台),2D 仿真平台和 RAR 解压工具。打开实验箱配套 U 盘或者是从官方获取的
文件进行安装。
实验室的电脑由于时间比较长了,上面的软件不一定可以正常使用,比赛时很大
可能要用自己的电脑,所以一定要找到容易操作的笔记本,一般在自己电脑上安
装,按照平台说明书安装即可。安装过程中可能会出现一些问题,要有耐心,不
断寻求解决问题的方案,安装好软件也可能出现鱼不游动的情况,可能是驱动出
现问题或者其他。可以换用不同的通信模块,或者换电脑使用。操作也特别重要,
组内人员一定要熟练操作,要清楚针对不同的情况如何圈鱼能够节省时间,这些
都要通过具体操作来自己摸索。
注意在生成策略的时候生成 win32 还是 X64,实验室电脑是 32 位的操作系统,
只有 win32 的策略可以用,但是笔记本一般为 64 位的操作系统,要生成 64 位的
才可以用。
二、策略
策略:对所有的柱子都采取同一种策略、对不同柱子采取不同策略、鱼尾撞击
法
我们采用的方法是通过与对柱子进行识别,对柱子鱼头以及鱼头和鱼的中心坐标
进行比较,如果柱子,鱼头,鱼的中心坐标在一条线上,则鱼进行以最大的速度
游向柱子,以鱼头对柱子进行直接撞击,否则用甩头的方式对柱子进行撞击,通
过一些文档的查询,以及重复实验,发现当鱼处于模式 1 时,对柱子撞击是的力
道可以适当的提高,可以增加撞到柱子的机率。根据实际情况调整速度、周期和
方向等。
1、降速判断:当鱼的距离离目标点很远的时候,鱼的速度保持最大(最大是
15),在不断靠近目标点的时候开始降速,防止因为自身的惯性,第一次没有撞
到鱼而游出很远,所以在目标点附近的速度要降低下来。
当鱼靠近目标点的时候,我们修改距离值在 20-30 之间(不同的速度分配不同的
距离判断值,以保证鱼甩头的着力点在柱子上,而不是鱼嘴的着力点在柱子上,
这样就会被缷力),最后停留在 25-29 之间(这个数值不唯一,仅做参考)。
2、鱼的速度:我们采用的是在时间和速度上不统一,可以在水中获得不为均衡
的力,可以引起水池的水晃动,通过水的浮力和鱼的撞击来击倒柱子。
3、鱼的方向:为了获得最佳效果,我们采取最大转向:0-7 左甩头到摆正、14-7
右甩头到摆正。
4、水的深度:在实验室实验时,我们采取的水深是 19cm,需要鱼的撞击力比
较大;但在比赛场地的水深却有 22cm 左右,浮力大,更容易撞倒。
三、主程序
(1)对所有的柱子都采取同一种策略
#include "../Header/StdAfx.h"
#include "../Header/Strategy.h"
CStrategy::CStrategy(void)
{
m_StatePeriod=15;
m_TurnYuan=0;
isRan=false;
time=1;
}
CStrategy::~CStrategy(void)
{
}
BOOL CStrategy::Strategy(IplImage* imgOrig,IplImage* imgRecog ,CFishAction action[],
n_action, CFishInfo fishinfo[], int n_fishinfo,
int
CBallInfo ballinfo[], int n_ballinfo, OBSTAINFO obst[],int n_obst, CHANNEL channel[], int
n_channel)
{
return true;//TRUE
}
//以下 id 及鱼信息、鱼动作信息数组相关,取值说明:
//0-7 是 A 队的,8-15 是 B 队的;
//例如,A 队的第一条鱼的动作是 actions[0],B 队的第一条鱼的动作是 actions[8]
void CStrategy::BasicActionStop(CFishInfo fish[],CFishAction action[],int id)
{
action[id].speed=0;
action[id].direction=7;
action[id].mode=0;
action[id].state++;
if(action[id].state==m_StatePeriod)
{
action[id].state=0;
m_TurnYuan=0;
}
fish[id].SetAction(action[id]);
CStrategy::BasicActionGo(CFishInfo
}
void
direction,int mode)
{
fish[],CFishAction
action[],int
id,int
speed,int
action[id].speed=speed;
action[id].direction=direction;
action[id].mode=mode;
if(m_TurnYuan)//正在执行原始转弯模式
{
action[id].state++;
if(action[id].state>=m_StatePeriod)
{
action[id].state=0;
m_TurnYuan=0;
}
}
else
{
if(mode)
{
action[id].state=0;
m_TurnYuan=mode;
}
else
{
action[id].state++;
if(action[id].state>=m_StatePeriod)
action[id].state=0;
}
}
fish[id].SetAction(action[id]);
}
//static long con_time=0;
//m_action[0] 策 略 控 制 参 数 , direction 控 制 方 向 , speed 控 制 速 度 . 获 取 方 式 :
m_actopm[0].speed
//m_FishInfo[0] 1 号鱼信息,包含坐标点、速度值、弧度值
//m_goalinfo 目标点信息,每次圈到的目标点,可获得坐标值 m_goalinfo.GetBallPoint()
m_FishInfo[],CBallInfo
CStrategy::Strategy0(CFishAction
BOOL
&m_goalinfo, OBSTAINFO m_obst[],CHANNEL m_Channel[])
{
m_action[],CFishInfo
CPoint ballinfo=m_goalinfo.GetBallPoint();//球的坐标
CFishInfo fishinfo=m_FishInfo[0];//获取鱼中心的的信息
CPoint fishpoint=fishinfo.GetHeaderPoint();//鱼头的坐标
CPoint ballpoint=m_goalinfo.GetBallPoint();//获取球的坐标
CFishAction maction=m_action[0];//获取鱼的决策
m_action[0].direction=7;
CFishAction lastaction;
double b=Angle(ballpoint,fishinfo.GetCenterPoint());//球与鱼的中心所成的角度
double c=Angle(ballpoint,fishpoint);//球与鱼头所成的角度
//c>b 时右摆,c=25)//距离值较大时,进行移动到目标点操作
{
Point2point(ballpoint,m_action[0],fishinfo.GetFishID(),fishinfo);
//根据距离调整速度
if(distance<=30)
{m_action[0].speed=7;}
if(distance<=40)
{m_action[0].speed=9;}
if(distance<=55)
{m_action[0].speed=11;}
if(distance<=75)
{m_action[0].speed=13;}
else
{m_action[0].speed=15;}
}
else
{
if((relx1*rely2)==(relx2*rely1))
{
m_action[0].direction=7;
m_action[0].speed=15;//速度待定
}
else
{
m_action[0].mode=1;
if(c>b)
{
m_action[0].direction=14;
time+=1;
if(time%25==0)
{
m_action[0].direction=7;
m_action[0].speed=8;//速度依据实验情况再修改——靠近目标点的
时候
}
}
else
{
m_action[0].direction=0;
time+=1;
if(time%20==0)
m_action[0].direction=7;
m_action[0].speed=9;//
{
}
}
}
}
return true;
}
double CStrategy::Distance(CPoint point,CPoint aimer)
{
double a;
a=sqrt((double)(point.x-aimer.x)*(point.x-aimer.x)+(double)(point.y-aimer.y)*(point.y-aimer.
y));
return a;
}
double CStrategy::Checkangle(double dir)//////////////////////////把 dir 换算成[-pi~pi]之间
的数
{
if(dir>PI)
dir-=2*PI;
else if(dir<-PI)
dir+=2*PI;
return dir;
}
double CStrategy::Angle(CPoint point,CPoint aimer)//计算角度
{
double a;
a=atan2((double)(aimer.y-point.y),(double)(aimer.x-point.x));
return a;
}
void CStrategy::Point2point(CPoint aimpt,CFishAction &action,
m_FishInfo)//点到点 目标点,执行动作的 action,id,鱼的信息,
{
int
fishID, CFishInfo
CPoint FishPt;// 鱼中心的位置
double FishDir;// 鱼头的方向
CPoint FishHeadPt;//鱼头的位置
CPoint LastFishPt;
double dir1=0;
FishPt=m_FishInfo.GetCenterPoint();
FishDir=m_FishInfo.GetDirection();
dir1=Angle(FishPt,aimpt);
dir1-=FishDir;//不懂
dir1=Checkangle(dir1)*180/PI;
action.speed=15;
if(dir1>-5&&dir1<5)
action.direction=7;
else if(dir1<-5&&dir1>-10)
action.direction=5;
else if(dir1<-10&&dir1>-30)
action.direction=4;
else if(dir1<-30&&dir1>-50)
action.direction=2;
else if(dir1<-50&&dir1>-70)
action.direction=1;
else if(dir1<-70&&dir1>-90)
action.direction=0;
else if(dir1<-90)
action.direction=0;
else if(dir1>5&&dir1<10)
action.direction=9;
else if(dir1>10&&dir1<20)
action.direction=10;
else if(dir1>20&&dir1<40)
action.direction=12;
else if(dir1>40&&dir1<50)
action.direction=12;
else if(dir1>50&&dir1<80)
action.direction=14;
else if(dir1>80&&dir1<90)
action.direction=14;
else
}
action.direction=14;
(2)对不同柱子采取不同策略
#include "../Header/StdAfx.h"
#include "../Header/Strategy.h"
CStrategy::CStrategy(void)
{
m_StatePeriod=15;
m_TurnYuan=0;
isRan=false;
time=1;
}
CStrategy::~CStrategy(void)
{
}
BOOL CStrategy::Strategy(IplImage* imgOrig,IplImage* imgRecog ,CFishAction action[],
n_action, CFishInfo fishinfo[], int n_fishinfo,
int
CBallInfo ballinfo[], int n_ballinfo, OBSTAINFO obst[],int n_obst, CHANNEL channel[], int
n_channel)
{
return true;//TRUE
}
//以下 id 及鱼信息、鱼动作信息数组相关,取值说明:
//0-7 是 A 队的,8-15 是 B 队的;
//例如,A 队的第一条鱼的动作是 actions[0],B 队的第一条鱼的动作是 actions[8]
void CStrategy::BasicActionStop(CFishInfo fish[],CFishAction action[],int id)//鱼静止时的动作
{
action[id].speed=0;
action[id].direction=7;
action[id].mode=0; /**模态,0 为通用转弯方式;1 为原始转弯方式(转一下立刻回来)
*/
action[id].state++;/**状态,是否发送命令,0 发送其他数不发送*/
if(action[id].state==m_StatePeriod)
{
action[id].state=0;
m_TurnYuan=0;
}
fish[id].SetAction(action[id]);/**记录机器鱼的动作*/
CStrategy::BasicActionGo(CFishInfo
}
void
direction,int mode)//鱼游的动作
{
fish[],CFishAction
action[],int
id,int
speed,int
action[id].speed=speed;
action[id].direction=direction;
action[id].mode=mode;
if(m_TurnYuan)//正在执行原始转弯模式
{
action[id].state++;
if(action[id].state>=m_StatePeriod)
{
action[id].state=0;
m_TurnYuan=0;
}
}
else
{
if(mode)
{
action[id].state=0;
m_TurnYuan=mode;
}
else
{
action[id].state++;
if(action[id].state>=m_StatePeriod)