这里记录一下坡道的写法和思路。博主的坡道处理是纯图像处理,没有使用陀螺仪等其他硬件设备进行辅助,仅给大家提供一种方法。欢迎大家提出意见和修改! 一些数组和参数定义在前几篇文章有说明,如果觉得这篇文章有帮助就点个赞支持一下吧!
先来看看直道和坡道的区别。(17届临近国赛时网传都是比赛会用高度10cm和12cm以下的矮坡,所以下面图像里都是高度为12cm及以下的矮坡道。但是国赛现场居然是用高坡,上大当,不过矮坡判断难度还是更大些,国赛坡道部分也没受到什么影响)
·坡道
·直道
思路:
从上图也能看出一些区别,摄像头在拍到坡道时,明显发现赛道变宽了(相对于直道赛道宽度而言),尤其在图像的顶端,直道末端和坡道末端的宽度差距很大,并且边线的斜率也有不同。我们总结几个特点
1.赛道宽度发生变化。
2.边线要是连续的。
3.边线斜率在一定范围内。
坡道分为3状态:状态一:上坡。状态二:在坡顶。 状态三:下坡。
fiv_width : 赛道宽度数组
podao_flag : 坡道状态标志位
podaoup_flag : 上坡标志位
podaoding_flag : 在坡顶标志位
podaodown_flag : 下坡标志位
long_turn_flag_left : 左边线连续的行数
void po_protect_timer()
{
if(podaoding_flag == 1) po_protcectflag = 1;
if (po_protcectflag == 1)
{
timer++;
po_protect = 1;
// SetText("第" + timer + "帧");
if (timer >= fps_po_protect)
{
po_protcectflag = 0;
timer = 0;
po_protect = 0;
}
}
}
void clear_po()
{
po_protect = 0;
podao_flag = 0;
podaoup_flag = 0;
podaoding_flag = 0;
podaodown_flag = 0;
}
void judg_podao() //坡道判断
{
byte judgtime = 0;
line_width();
fangcha(1,0,59);
fangcha_zuo = (int)sumE;
fangcha(2,0,59);
fangcha_you = (int)sumE;
juge_lineContinuity(0, 69, 5, -5, 1);
juge_lineContinuity(0, 69, 5, -5, 2);
advanced_regression(1, 0, 35, 36, b);
xielv_zuo = parameterB;
advanced_regression(2, 0, 35, 36, b);
xielv_you = parameterB;
// SetText("左方差:" + fangcha_zuo + " 右方差:" + fangcha_you + " 左连续:" + long_turn_flag_left + " 右连续:" + long_turn_flag_right);
// SetText("左斜率:" + xielv_zuo + " 右斜率:" + xielv_you);
//正入坡道
if (po_protect == 0 && podaodown_flag == 0 && podao_flag == 0 && long_turn_flag_left >= 55 && long_turn_flag_right >= 55 && fangcha_you >= 0 && fangcha_you < 120 && fangcha_zuo >= 0 && fangcha_zuo < 120)
{
// SetText("第40行: " + fiv_width[40] + " 第45行: " + fiv_width[45] + " 第50行: " + fiv_width[50] + " 第55行: " + fiv_width[55]);
if (fiv_width[40] >= 80 && fiv_width[45] >= 75 && fiv_width[50] >= 70 && fiv_width[55] >= 65 && b > 40 && !(L_black[50] < 185 && R_black[50] > 0))
{
judgtime = 1;
}
else if (fiv_width[40] >= 87 && fiv_width[45] >= 85 && fiv_width[50] >= 85 && fiv_width[55] >= 75 && b > 40 && L_black[50] < 185 && R_black[50] > 0)
{
judgtime = 1;
}
if (judgtime >= 1 && xielv_zuo > -1.2 && xielv_zuo < 0 && xielv_you > 0 && xielv_you < 1.2)
{
podaoup_flag = 1;
podao_flag = 1;
// SetText("———上坡————");
}
}
if (podao_flag == 1 && long_turn_flag_left < 40 && long_turn_flag_right < 40)
{
podaoup_flag = 0;
podaoding_flag = 1;
// old = 93;
// SetText("———在坡道顶部———");
}
if (podaoding_flag == 1 && b >= 55 && (long_turn_flag_left >= 40 || long_turn_flag_right >= 40) && fiv_width[10] >= 99 && fiv_width[20] >= 95 && fiv_width[25] >= 90)
{
podao_flag = 0;
podaoup_flag = 0;
podaoding_flag = 0;
podaodown_flag = 1;
// SetText("———下坡———");
}
po_protect_timer();
}
思路:上坡的判断要比较上边的赛道宽度(这里我选的是50行附近,矮坡可能会看到坡后面的赛道,所以不能选太高),并且对于直道接坡赛道两边必须是连续的,不能出现大的突变点。并且边线的斜率在一定范围内即可进入状态一。
if (po_protect == 0 && podaodown_flag == 0 && podao_flag == 0 && long_turn_flag_left >= 55 && long_turn_flag_right >= 55 && fangcha_you >= 0 && fangcha_you < 120 && fangcha_zuo >= 0 && fangcha_zuo < 120)
{
// SetText("第40行: " + fiv_width[40] + " 第45行: " + fiv_width[45] + " 第50行: " + fiv_width[50] + " 第55行: " + fiv_width[55]);
if (fiv_width[40] >= 80 && fiv_width[45] >= 75 && fiv_width[50] >= 70 && fiv_width[55] >= 65 && b > 40 && !(L_black[50] < 185 && R_black[50] > 0))
{
judgtime = 1;
}
else if (fiv_width[40] >= 87 && fiv_width[45] >= 85 && fiv_width[50] >= 85 && fiv_width[55] >= 75 && b > 40 && L_black[50] < 185 && R_black[50] > 0)
{
judgtime = 1;
}
if (judgtime >= 1 && xielv_zuo > -1.2 && xielv_zuo < 0 && xielv_you > 0 && xielv_you < 1.2)
{
podaoup_flag = 1;
podao_flag = 1;
// SetText("———上坡————");
}
}
思路:当上一个状态为坡道一状态。并且赛道左右边线的连续数下降(图中蓝色部分为边线连续数,再往上明显发生了由宽到窄的突变)。说明是到了坡道顶部。博主这里是矮缓坡,能看到坡后面的情况,边线也看起来还比较连续的,如果是陡的坡道后面的道路情况是看不见的,断层会更明显。
思路:下坡是比较简单的,这图一看,欸嘿,这不是和上坡一样嘛。没错的,下坡的图像是和上坡很相似,所以只要确保上一个状态是坡道二状态,并且和上坡一样对赛道宽度进行检测对比即可。需要注意的是由于上坡和下坡很相似,很容易出现在下坡时又判出上坡的情况,所以这里加了一个po_protect_timer函数保护在下坡过程中不去判断上坡。
思路:弯接坡的二三状态和直道接坡是一样的,并不太需要改动,主要是上坡状态稍微有点区别。我们看图可以发现,弯接坡是一边丢线,一边没丢线,但主要的赛道宽度,没丢线那边的边线斜率等信息依旧是比较明显的。这里提供2种思路,第一种是直接修改坡道函数代码里的参数,用大量图像提高其鲁棒性,让其能用于直道坡道也可以用于弯道坡道。第二种是分开判断,我先进行丢线,斜率,宽度等特征判断,来区分要进去弯接坡的函数还是直道接坡的函数,再相应的进行坡道判断。很显然博主只给了一套代码说明是选了第一种方法,当然也是可能大概是因为太懒了所以只写了一套。
本文提供的一个纯图像处理方案,加了陀螺仪等也能辅助判断出坡道,做车就是要敢于尝试各种方法,然后仔细进行优化,没有一蹴而就的方案。每一辆去国赛的车肯定有经历过无数次的翻车和日日夜夜的改进才能拿到国一的成就。如果你觉得文章有所帮助还希望点赞鼓励一下!欢迎大家在评论区提出改进意见!
最后的最后如果想看看我这一年智能车的经历和建议可以到第一篇文章最下面浏览一下 智能车学习日记【一】