高级会员
- 积分
- 686
- 威望
- 357
- 贡献
- 211
- 兑换币
- 222
- 注册时间
- 2013-8-24
- 在线时间
- 59 小时
|
本帖最后由 枫华幻吟 于 2015-7-21 14:52 编辑
抛砖引玉,下面的算法都是使用单CCD使用120度广角镜下完成的算法。
算法的第一要务是稳定,不会出现误判,下面将列举单线,直道,障碍物,以及斜入直角前的黑线。
1.跳变沿法(自定义的)
在说这些东西的时候,好的方法可以事半功倍。这个方法下面将用到
上图看特点
单线:
这个是单线下的图像,纵轴0表示黑线,255表示白线,首先我们需要记录这条线上的所有的上升沿和下降沿,红色表示下降沿,绿色表示上升沿,红绿数字表示下标,如何统计呢,看程序,(线性CCD有效范围5-122)。
void find_TiaoBian1(uint8 *buf,uint16 len)
{
int fall_num = 0,rase_num = 0,barrier_flag_t = 0;
int fall_index[128] ={0},rase_index[128] ={0};
if(white_flag1 == 0 && black_flag1==0 ) //不是全白且不是全黑的情况下
{
for(int i=5;i<(len-7);i++)
{
if((buf-buf[i+1]) == 255 && (buf-buf[i+2]) == 255) //从白到黑的下降沿(方向从左往右)
{
fall_index[fall_num] = i; //记录所有的下降沿位置下标
fall_num++;
}
}
for(int i=122;i>7;i--)
{
if((buf-buf[i-1]) == 255 && (buf-buf[i-2]) == 255) //从黑到白的上升沿(方向从左往右)
{
rase_index[rase_num] = i; //记录所有的上升沿的位置下标
rase_num++;
}
}
fall = fall_num; //全局变量直道要用
rase = rase_num;
if(Oneflag == 1 && fall_num == 1 && rase_num == 0) //只有右边有下降沿(单线时)
{
if(fall_index[0] <= 120) //判断是不是进入双线状态,黑点太多127-15.下标。
{
Oneflag = 0; //判断进入双线
}
}
else if(Oneflag == 1 && fall_num == 0 && rase_num == 1) //只有右边有上升沿(单线时)
{
if(rase_index[0] >= 18) //判断是不是进入双线状态,黑点太多127-15.下标。
{
Oneflag = 0; //判断进入双线
}
}
for(int i=0;i<fall_num;i++)
{
for(int j=0;j<rase_num;j++)
{
if((rase_index[j]-fall_index)<=13 && (rase_index[j]-fall_index)>=3) //找到了单线
{
lastmid3 = (int)((fall_index + rase_index[j])/2);
Oneflag = 1;
break;
}
else
{
Oneflag = 0;
}
}
Oneflag = 1;的时候就是进入单线的时候,明白了么黑线的宽度范围是3-13,实际检测单线的宽度在6-8之间变化。此方法适用于直入单线,斜入单线,以及单线丢线的情况,100%不会出现问题。
2.障碍:
会使用跳变沿法找到单线,那么障碍物同理也会很容易找到。方法如下
上图
看着这个图发现一个问题,它和单线有点相似,唯一不同的地方是中间的黑线变宽了,宽度大概多少呢,经过测算宽度在18到22之间,程序就不发了,和上面一样,检测到障碍物,但是障碍物到底在左边还是右边呢,这个很简单,找到障碍物黑线两边的下标相加除2得到的值大于63就是在右边,反之在左边。
3,直道(记忆法)
对于直道很多人使用很多方法会误判,单ccd很难去识别。
这里提供一个记忆法,我们没法判断当前状态时,我们可以尝试判断过去,怎样判断呢,直接上程序,你看懂就行、此方法效果明显,避免了十字道丢线法的误判。
void find_Ensure(void)
{
int stack_mid_Left[151] = {0};
int stack_mid_Right[151] = {0};
int Sum_Left_index = 0,Sum_Right_index = 0;
if((fall+rase)>0 && (fall+rase)<=2) //发现呢么这里的fall和rase用到了前面的跳变沿算法他是全局变量
{
mid_num_index++;
if(fall==1)
{
stack_mid_Right[mid_num_index] = 1; //右边下降沿
}
else if(rase==1)
{
stack_mid_Left[mid_num_index] = 1; //左边上升沿
}
if(mid_num_index>=70) //70根据速度快慢自己调大小
{
mid_num_index = 0;
}
}
if(black_flag1==1) //如果出现全黑CCD1
{
for(int i=0;i<=70;i++)
{
Sum_Left_index+=stack_mid_Left; //左边黑线数量统计
Sum_Right_index+=stack_mid_Right; //右边黑线数量统计
}
}
//判断右边直道data_T按键调节大小默认20,我称之为判断灵敏度,防止将黑线判断为直道
if(black_flag1==1 && LR_flag==0 && (Sum_Left_index-Sum_Right_index)>=data_T)
{
Right_TT = 1;
LR_flag = 1;
}
else if(black_flag1==1 && LR_flag==0 && (Sum_Right_index-Sum_Left_index)>=data_T) //判断左边直道
{
Left_TT = 1;
LR_flag = 1;
}
4,斜入直角前的黑线这个也可以用跳变沿法进行判断,这里不再列举,自己养成习惯,画个图,用跳变沿法就能找到特点。我们经常使用上次的中线值作为下次开始的起点,向两边找黑线,这种方法会有误判,是用跳变沿法特点可以用很简短的代码解决这一问题,前面写了很多道路路径识别,识别出来了,怎么去控制小车呢,最笨的方法在直道和障碍物时直接给出中线偏差值,大死角,这个是最笨的方法,很不稳定车体摇晃,易出赛道,可以采用补线的方法。
写了这么久大家如果觉得好,给点鼓励了,拜托了。
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?注册
x
|