一、圆环
1.基于传统扫线的补线方法
以右圆环为例
(1)找到近端右拐点,且左边界不丢线
(2)找到右边中间拐点,定位近端右拐点,拉线
(3)右边界底部丢线,结束拉线,找远端右拐点
(4)定位远端右拐点,补线进环
(5)编码器计步大于某阈值,停止补线,进普通循迹状态
(6)赛道宽度突变,补线出环
(7)找远端右拐点,补线不入环
(8)结束,清空状态
void Right_Roll_Judge(void)
{
extern int Distance_L;
extern int Distance_R;
int erro_x,erro_y;
if(XK.roll_flag==0&&XK.roll_situation==0)//初始状态
{
if((Right_NearInflection_Judge(40,30)==1)&&(Left_Road_Lose(10,60)==1))//找到右拐点且左边界不丢失
{
XK.roll_situation=1;
XK.roll_flag=1;
XK.y3=28;
erro_x=0;
erro_y=0;
XK.y2=0;
XK.x2=0;
}
}
if(XK.roll_situation==1)//找拐点,定位
{
Right_NearInflection_Catch(XK.y,60,XK.x,XK.y);//近拐点定位
Right_RoundInflection_Catch(XK.y,1,XK.x2,XK.y2);//中间拐点定位
if(XK.y>0&&XK.y2>0)//找到两个拐点,准备拉线
{
erro_x=0;
erro_y=0;
XK.y1=XK.y2;
XK.x1=XK.x2;
XK.roll_situation=2;
}
}
if(XK.roll_situation==2)//拉线
{
Right_NearInflection_Catch((XK.y-2),60,XK.x2,XK.y2);
erro_y=abs(XK.y2-20);
XK.y3=XK.y;
XK.y4=XK.y1+erro_y;
XK.x3=XK.x;
XK.x4=XK.x1;
XK.line=1;
if(XK.right_line[100]>160)//当右边界底部丢线,结束拉线
{
XK.line=0;
XK.y2=0;
XK.roll_situation=3;
}
}
if(XK.roll_situation==3)//找远拐点
{
Right_FarInflection_Catch(1,40,XK.x2,XK.y2);//远拐点定位
if((XK.y2>0)&&(XK.right_line[20]>150))//找到远拐点且右边界前端丢线,准备拉线
{
XK.y1=XK.y2;
XK.x1=XK.x2;
Distance_L=0;
Distance_R=0;
XK.Encoder_distance=0;
XK.roll_situation=4;
}
}
if(XK.roll_situation==4)//入环补线
{
XK.y3=25;
XK.y4=55;
XK.x3=110;
XK.x4=45;
XK.line=1;
if(XK.Encoder_distance>5)//编码器计步(走一段距离,结束补线)
{
XK.y2=0;
XK.line=0;
Distance_L=0;
Distance_R=0;
XK.Encoder_distance=0;
XK.roll_situation=6;
}
}
if(XK.roll_situation==6)//环内状态
{
if((XK.road_width[29]-XK.road_width[30]>50)||XK.road_width[30]>150)//赛道宽度突变
{
XK.y1=XK.y2;
XK.x1=XK.x2;
XK.y2=0;
Distance_L=0;
Distance_R=0;
XK.Encoder_distance=0;
XK.roll_situation=7;
}
}
if(XK.roll_situation==7)//出环补线
{
XK.y3=25;
XK.y4=60;
XK.x3=115;
XK.x4=30;
XK.line=1;
Right_FarInflection_Catch(1,30,XK.x2,XK.y2);找远端拐点
distence_count();
if((XK.y2>0)&&XK.Encoder_distance>7)//不入环判断:在走一段距离的情况下,找到远端拐点
{
XK.y1=XK.y2;
XK.x1=XK.x2;
XK.roll_situation=8;
}
}
if(XK.roll_situation==8)//不入环补线
{
XK.y3=100;
XK.y4=20;
XK.x3=136;
XK.x4=113;
XK.line=1;
}
if(XK.roll_situation==8)//不入环补线
{
Distance_L=0;
Distance_R=0;
XK.Encoder_distance=0;
XK.y3=100;
XK.y4=20;
XK.x3=136;
XK.x4=113;
XK.line=1;
}
if((Left_Road_Lose(20,60)==1)&&XK.roll_situation==8)//右边界不丢失,圆环标志位清零
{
XK.roll_situation=0;
XK.roll_flag=0;
XK.line=0;
}
}
void draw_line(void)//补线处理函数
{
if(XK.line==1)
{
ips114_add_line(XK.y,XK.x+0,XK.y1,XK.x1+0,0x00);
ips114_add_line(XK.y,XK.x+1,XK.y1,XK.x1+1,0x00);
ips114_add_line(XK.y,XK.x+2,XK.y1,XK.x1+2,0x00);
ips114_add_line(XK.y,XK.x+3,XK.y1,XK.x1+3,0x00);
ips114_add_line(XK.y,XK.x-1,XK.y1,XK.x1-1,0x00);
ips114_add_line(XK.y,XK.x-2,XK.y1,XK.x1-2,0x00);
}
}
关于如何在图像数组中补线,基于逐飞的IPS114画线函数更改即可
void ips114_add_line (uint16 x_start, uint16 y_start, uint16 x_end, uint16 y_end, const uint16 color)
{
int16 x_dir = (x_start<x_end ? 1:-1);
int16 y_dir = (y_start<y_end ? 1:-1);
float temp_rate = 0;
float temp_b = 0;
if(x_start != x_end)
{
temp_rate = (float)(y_start-y_end)/(float)(x_start-x_end);
temp_b = (float)y_start-(float)x_start*temp_rate;
}
else
{
while(y_start != y_end)
{
mt9v03x_image_copy[x_start][ y_start]=0x00;//根据需要更改的图像数组
y_start += y_dir;
}
return;
}
if(abs(y_start-y_end)>abs(x_start-x_end))
{
while(y_start != y_end)
{
mt9v03x_image_copy[x_start][ y_start]=0x00;//根据需要更改的图像数组
y_start += y_dir;
x_start = (int16)(((float)y_start-temp_b)/temp_rate);
}
}
else
{
while(x_start != x_end)
{
mt9v03x_image_copy[x_start][ y_start]=0x00;//根据需要更改的图像数组
x_start += x_dir;
y_start = (int16)((float)x_start*temp_rate+temp_b);
}
}
}
2.电磁圆环,摄像头辅助判断
void elec_roll_judge(void)
{
// ********* 摄像头区分左右环(这一段可单独放在图像处理函数里) ***********
if(XK.roll_flag==1&&XK.roll_situation==1)
{
XK.rolldirr=rroll_dir_judge(10,50,65);
XK.rolldirl=lroll_dir_judge(10,50,65);
}
// *****************************************************************
extern float AD[6];
if(XK.roll_flag==0&&XK.roll_situation==0)
{
if(AD[1]>3000&&AD[0]>3000)//中间电感大于一定阈值
{
XK.roll_flag=1;
XK.roll_situation=1;
Distance_L=0;
Distance_R=0;
XK.Encoder_distance=0;
}
}
if(XK.roll_flag==1&&XK.roll_situation==1)
{
if(XK.rolldirr==1)//右圆环状态
{
XK.roll_flagr=1;
XK.roll_flagl=0;
XK.roll_situation=2;
Distance_L=0;
Distance_R=0;
XK.Encoder_distance=0;
}
else if(XK.rolldirl==1)//左圆环状态
{
XK.roll_flagr=0;
XK.roll_flagl=1;
XK.roll_situation=2;
Distance_L=0;
Distance_R=0;
XK.Encoder_distance=0;
}
if(XK.Encoder_distance>15)//计步大于某值,跳出圆环
{
XK.roll_situation=0;
XK.roll_flag=0;
XK.roll_flagl=0;
XK.roll_flagr=0;
Distance_L=0;
Distance_R=0;
XK.Encoder_distance=0;
}
}
if(XK.roll_flag==1&&XK.roll_situation==2)
{
if(XK.roll_flagl==1&&XK.roll_flagr==0)//右圆环状态
{
if(AD[3]>3300)//右斜电感大于阈值,舵机打角
{
XK.roll_situation=3;
Distance_L=0;
Distance_R=0;
XK.Encoder_distance=0;
}
}
if(XK.roll_flagl==0&&XK.roll_flagr==1)//左圆环状态
{
if(AD[4]>3400)//左斜电感大于阈值,舵机打角
{
XK.roll_situation=3;
Distance_L=0;
Distance_R=0;
XK.Encoder_distance=0;
}
}
}
if(XK.roll_flag==1&&XK.roll_situation==3)//环内状态
{
if(XK.Encoder_distance>9)//计步
{
XK.roll_situation=5;
Distance_L=0;
Distance_R=0;
XK.Encoder_distance=0;
}
}
if(XK.roll_flag==1&&XK.roll_situation==5)
{
if(XK.roll_flagl==1&&XK.roll_flagr==0)//右圆环出环判断
{
if(AD[5]>1700)//右侧电感大于某阈值,右打角
{
XK.roll_situation=6;
Distance_L=0;
Distance_R=0;
XK.Encoder_distance=0;
}
}
if(XK.roll_flagl==0&&XK.roll_flagr==1)//左圆环出环判断
{
if(AD[2]>2800)//左侧电感大于某阈值,左打角
{
XK.roll_situation=6;
Distance_L=0;
Distance_R=0;
XK.Encoder_distance=0;
}
}
}
if(XK.roll_flag==1&&XK.roll_situation==6)//计步大于某阈值,结束圆环,标志位清零
{
if(XK.Encoder_distance>3)
{
XK.roll_situation=0;
XK.roll_flag=0;
XK.roll_flagr=0;
XK.roll_flagl=0;
Distance_L=0;
Distance_R=0;
XK.Encoder_distance=0;
}
}
}
二、避障
这里需要用到编码器计行驶圈数
#define ENCORDER_PRCISION 1024.f //512线、1024线等
#define ENCORDER_D 19.2f //编码器齿轮直径 齿数30
#define WHEEL_D 64.0f //车轮直径
#define WHEEL_GEAR_D 41.0f //车轮直连齿轮直径 齿数 68
#define GET_DISTANCE_M(val) ((((val/ENCORDER_PRCISION)*ENCORDER_D*PI )*WHEEL_D)/WHEEL_GEAR_D/1000)
void distence_count(void)
{
Distance_L = Distance_L + XK.speedl;
Distance_R = Distance_R + XK.speedr;
XK.Encoder_distance=GET_DISTANCE_M((Distance_L + Distance_R) / 2);
}
void barrier (void)
{
extern int Distance_L;//左轮距
extern int Distance_R;//右轮距
if(dl1a_distance_mm<XK.dis1&&XK.barrier_judge==0)//避障预判断
{
Gyro_qin0();//陀螺仪数值清零
XK.barrier_in=1;//避障状态
XK.barrier_judge=1;//避障进入标志位
XK.Encoder_distance=0;//测距距离
}
if(XK.barrier_judge==1)
{
switch (XK.barrier_in)
{
case 1:
{
if(dl1a_distance_mm<=XK.dis2)//行进距离
{
if((mt9v03x_image[2][94]+mt9v03x_image[3][94]+mt9v03x_image[3]
[93]+mt9v03x_image[3][95])/4<55)//tof测距小于某阈值且图像灰度像素小于某阈值
(区分坡道与避障)
{
Distance_L=0;
Distance_R=0;
XK.Encoder_distance=0;
XK.barrier_in=2;
Gyro_qin0();
wireless_uart_send_string("6");//与后车通信
}
else//未达条件跳出状态
{
Distance_L=0;
Distance_R=0;
XK.time=0;
XK.Encoder_distance=0;
XK.barrier_in=0;
XK.barrier_judge=0;
Gyro_qin0();
}
}
}
break;
case 2://打角避障
{
if(XK.dash_dir==1)//右边避障
{
if(eulerAngle.yaw<-3.1)//右航向角
{
Distance_L=0;
Distance_R=0;
XK.time=0;
XK.Encoder_distance=0;
XK.barrier_in=3;
Gyro_qin0();//陀螺仪数值清零
}
}
if(XK.dash_dir==0)//左边避障
{
if(eulerAngle.yaw>1.6)//左航向角
{
Distance_L=0;
Distance_R=0;
XK.time=0;
XK.Encoder_distance=0;
XK.barrier_in=3;
Gyro_qin0();//陀螺仪数值清零
}
}
}
break;
case 3://直行
{
distence_count();//编码器测距
if(XK.Encoder_distance>3)//行进距离
{
Distance_L=0;
Distance_R=0;
XK.time=0;
XK.Encoder_distance=0;
XK.barrier_in=4;
Gyro_qin0();
}
}
break;
case 4://打角
{
if(XK.dash_dir==1)//左边避障
{
if(eulerAngle.yaw>3.6)//左航向角
{
Distance_L=0;
Distance_R=0;
XK.time=0;
XK.Encoder_distance=0;
XK.barrier_in=5;
Gyro_qin0();
}
}
if(XK.dash_dir==0)//右边避障
{
if(eulerAngle.yaw<-6.0)//右航向角
{
Distance_L=0;
Distance_R=0;
XK.time=0;
XK.Encoder_distance=0;
XK.barrier_in=5;
Gyro_qin0();
}
}
}
break;
case 5://直行
{
distence_count();//编码器测距
if(XK.Encoder_distance>1)//行进距离
{
Distance_L=0;
Distance_R=0;
XK.time=0;
XK.Encoder_distance=0;
XK.barrier_in=6;
Gyro_qin0();
}
}
break;
case 6://打角
{
if(XK.dash_dir==1)//左边避障
{
if(eulerAngle.yaw>5.0)//左航向角
{
Distance_L=0;
Distance_R=0;
XK.time=0;
XK.Encoder_distance=0;
XK.barrier_in=7;
Gyro_qin0();
}
}
if(XK.dash_dir==0)//右边避障
{
if(eulerAngle.yaw<-5.9)//右航向角
{
Distance_L=0;
Distance_R=0;
XK.time=0;
XK.Encoder_distance=0;
XK.barrier_in=7;
Gyro_qin0();
}
}
}
break;
case 7://直行,回赛道
{
extern float AD[6];
distence_count();//编码器测距
if(XK.dash_dir==1)
{
if((mt9v03x_image[110][140]+mt9v03x_image[110][141]+mt9v03x_image[110]
[139])/3>100)//图像灰度像素大于某阈值(白色赛道)
{
Distance_L=0;
Distance_R=0;
XK.time=0;
XK.Encoder_distance=0;
XK.barrier_in=0;
XK.barrier_judge=0;
}
}
if(XK.dash_dir==0)
{
if((mt9v03x_image[110][48]+mt9v03x_image[110][49]+mt9v03x_image[110]
[50])/3>100)//图像灰度像素大于某阈值(白色赛道)
{
Distance_L=0;
Distance_R=0;
XK.time=0;
XK.Encoder_distance=0;
XK.barrier_in=0;
XK.barrier_judge=0;
}
}
}
break;
}
}
}
本文旨在本校智能车实验室教学,若有错漏,欢迎指正
版权归原作者 eTao_757 所有, 如有侵权,请联系我们删除。