赞
踩
目录
讲解代码使用的摄像头为总钻风摄像头,图像像素为188*120,图像进行了二值化,这里建议如果需要对光线有要求的同学使用灰度处理。没有使用过上位机,展示的图片都是直接拍摄2寸IPS的显示。
当我们采集到一帧图像并做完二值化后,我们就开始寻边线,我使用了简单方便的左右扫线,因为在某些情况顶部图像会是黑的,所以使用从图像靠近车头的一端扫线。此时我做了些许处理,如果第一次扫线就从中间开始扫,以后会从上一次计算的中线开始扫,这也需要每次扫完一行就得计算一下中线。为了更加符合赛道变化,下一行的扫描起始点是上一行的中线,当然某些特殊情况也会出问题,比如遇到斑马线,所以又必须对斑马线做处理。左右扫线简单方便,但是执行起来需要遍历的数据量比较多。
- //-------------------------------------------------------------------------------------------------------------------
- // @brief 左右巡边线
- // @param BoundaryRight 右丢线行数
- // @param BoundaryLeft 左丢线行数
- // @param
- // @param
- // @return void
- // @note 采用左右扫线的方法,从图像最低端开始,每行扫完会计算一次中线,下一行扫描从上一行中线开始
- //-------------------------------------------------------------------------------------------------------------------
- static uint8 star = 93; //寻线初始点
- //需优化:有时其他赛道会干扰
- //如果当左边线寻到有边界则使以后边线都处于边界
- void Get_Line(void)
- {
- // float k=0; //斜率
- // float b=0; //截距
- //uint8 left=0;
- //int kuan=0;
- // k=((float)xtwo - (float)xone)/((float)ytwo - (float)yone);
- // b=(float)yone - ((float)xone*k);
- BoundaryRight = 0;
- BoundaryLeft = 0;
- if(Middle_Black_Point[119] == 0 || Middle_Black_Point[119] == 187) //判断起始点是否在图像中间
- {
- star = 93;
- }
- else
- {
- star = Middle_Black_Point[119];
- }
- for(uint8 y=119;y>=0;y--)
- {
- for(uint8 x=star;x<188;x++)
- {
- if(Emo_imag[y][x]==EmoBlack) //黑黑黑即判断为边线
- {
- if(Emo_imag[y][x+1]==EmoBlack && Emo_imag[y][x+2]==EmoBlack)
- {
- if(y < Endline )
- Right_Black_Point[y] = 187;
- else
- Right_Black_Point[y]=x;
- //left=star;
- break;
- }
- }
- if(x==186) //有点问题,返校复查
- {
- Right_Black_Point[y]=187;
- //left=star;
- if(y > Endline && y < 108)
- BoundaryRight++;
- break;
- }
- }
- for(uint8 x=star;x>=0;x--)
- {
- if(Emo_imag[y][x]==EmoBlack)
- {
- if(Emo_imag[y][x-1]==EmoBlack && Emo_imag[y][x-2]==EmoBlack)
- {
- if(y < Endline)
- Left_Black_Point[y] = 0;
- else
- Left_Black_Point[y]=x;
- break;
- }
- }
- if(x==0)
- {
- Left_Black_Point[y]=0;
- if(y > Endline && y < 108)
- BoundaryLeft++;
- break;
- }
- }
- if(Right_Black_Point[y]==187&&Left_Black_Point[y]==0) //两边都没找到线
- {
- Middle_Black_Point[y]=Middle_Black_Point[y+1];
- //star=Middle_Black_Point[y];
- star = 93;
- }
- else if(Right_Black_Point[y]==187&&Left_Black_Point[y]!=0) //左边找到线
- {
- Middle_Black_Point[y]=Left_Black_Point[y]+Straight[y];
- star=Middle_Black_Point[y];
- // if(CurvatureRight < -0.0045)
- // {
- // kuan = ((y-120)*(y-120)/(20)+93);
- // kuan = kuan > (187-Right_Black_Point[y]) ? (187-Right_Black_Point[y]) : kuan;
- // Middle_Black_Point[y]=Left_Black_Point[y]+kuan;
- // }
- }
- else if(Left_Black_Point[y]==0&&Right_Black_Point[y]!=187) //右边找到线
- {
- Middle_Black_Point[y]=Right_Black_Point[y]-Straight[y];
- star=Middle_Black_Point[y];
- // if(CurvatureRight < -0.0045)
- // {
- // kuan = ((y-120)*(y-120)/(20)+93);
- // kuan = kuan > Right_Black_Point[y] ? Right_Black_Point[y] : kuan;
- // Middle_Black_Point[y]=Right_Black_Point[y]-kuan;
- // }
- }
- else //两边都找到线
- {
- Middle_Black_Point[y]=(uint8)(((int)Right_Black_Point[y]+(int)Left_Black_Point[y])/2);
- star=Middle_Black_Point[y];
- }
- // Middle_Black_Point[y] = Middle_Black_Point[y] < 1 ? 1 : Middle_Black_Point[y];
- // Middle_Black_Point[y] = Middle_Black_Point[y] > 186 ? 186 : Middle_Black_Point[y];
- Middle_Black_Point[y] = Middle_Black_Point[y] < 1 ? 0 : Middle_Black_Point[y];
- Middle_Black_Point[y] = Middle_Black_Point[y] >186 ? 187 :Middle_Black_Point[y];
- if(y==0)
- break;
- }
- //star = Middle_Black_Point[119];
- }

寻拐点呢我采用了类似于八邻域的原理,首先是下拐点,我们从底端向上寻找,因为拐点对应的一定是丢线的,所以向上一直寻找到丢线行,以丢线行再向下对一个个点进行判断。
以右下拐点为例,我们放大像素块,我们从红点像素块的左下开始以顺时针旋转,当扫描的点周边的八个像素块出现四个白色像素块时即满足拐点。但是需要注意,拐点是不会距离丢线行数太多的,为了防止拐点误判的出现,我们应限制以丢线行数进行扫描的次数。前边说过左右扫线会因为斑马线造成干扰,所以扫寻完下拐点后,上拐点选择从图像上端向下扫,同样是向下扫到丢线后向再向上寻点,当然,对于扫描点附近八个像素块的旋转就应该换个方向。
- //-------------------------------------------------------------------------------------------------------------------
- // @brief 拐点寻找
- // @param findlcount 拐点距离丢线的行数,用于判断大小圆环,和区分P字和圆环
- // @param
- // @param
- // @param
- // @return void
- // @note 采用5邻域的原理寻找拐点,下拐点从图像低端往上扫,上拐点从图像上方向下扫,左右扫线会在斑马线出现问题,
- //-------------------------------------------------------------------------------------------------------------------
- void Identify(void)
- {
- uint8 findr_x = 0; //右点
- uint8 findr_y = 0;
- uint8 examr_x = 0;
- uint8 examr_y = 0;
- uint8 findl_x = 0; //左点
- uint8 findl_y = 0;
- uint8 examl_x = 0;
- uint8 examl_y = 0;
- uint8 star = 0;
- uint8 end = 0;
- uint8 examcount = 0;
- //uint8 count;
- //uint8 examerror;
- // uint8 dircount;
- int directionrd[5][2] = {{-1,1}, {-1,0}, {-1,-1}, {0,1}, {1,1}}; //顺时针下方向数组先x再y
- int directionld[5][2] = {{1,1}, {1,0}, {1,-1}, {0,-1}, {-1,-1}}; //逆时针下方向数组
- int directionru[5][2] = {{1,1}, {0,1}, {-1,1}, {-1,0}, {-1,-1}}; //逆时针上方向数组
- int directionlu[5][2] = {{-1,1}, {0,1}, {1,1}, {1,0}, {1,-1}}; //逆时针上方向数组
-
- //每次采集后都对拐点标志位清零
- if(Right_Up_Point_finish_flag == 1)
- Right_Up_Point_finish_flag = 0;
- if(Left_Up_Point_finish_flag == 1)
- Left_Up_Point_finish_flag = 0;
- if(Right_Down_Point_finish_flag == 1)
- Right_Down_Point_finish_flag = 0;
- if(Left_Down_Point_finish_flag == 1)
- Left_Down_Point_finish_flag = 0;
- for(uint8 y = 105 ; y >= 30 ; y--)
- {
- if(Right_Down_Point_finish_flag == 0)
- {
- if(y > Endline && Right_Black_Point[y-1]==187 && Right_Black_Point[y-2]==187 && Emo_imag[y][Right_Black_Point[y]-6] == EmoWhite
- && y > Endline && Emo_imag[y-2][Right_Black_Point[y]] == EmoWhite && Emo_imag[y-5][Right_Black_Point[y]] == EmoWhite) //右下拐点
- {
- star=y;
- for(uint8 y=star;y<=(star+18);y++)
- {
- if(Right_Black_Point[y]<184 && Emo_abs(Right_Black_Point[y+1]-Right_Black_Point[y])<3
- && Emo_abs(Right_Black_Point[y+2]-Right_Black_Point[y])<4)
- {
- findr_x=Right_Black_Point[y];
- findr_y=y;
- for(uint8 dircount = 0;dircount<5;dircount++)
- {
- examr_x=findr_x+directionrd[dircount][0];
- examr_y=findr_y+directionrd[dircount][1];
- if(Emo_imag[examr_y][examr_x]==255)
- {
- examcount++;
- }
- }
- if(examcount >= 4)
- {
- examcount=0;
- Right_Down_Point[0]=findr_x;
- Right_Down_Point[1]=findr_y;
- // if(Last_Right_Point[0] == 0)
- // {
- // Last_Right_Point[0] = Right_Down_Point[1];
- // }
- // if(Emo_Uint8_dec(Right_Down_Point[1],Last_Right_Point[0]) < -15)
- // {
- // Right_Down_Point_finish_flag = 0;
- // }
- // else
- // {
- Right_Down_Point_finish_flag = 1;
- // Last_Right_Point[0] = Right_Down_Point[1];
- // }
- // findrcount = (int)y-(int)star;
- break;
- }
- else
- {
- Right_Down_Point_finish_flag = 0;
- examcount=0;
- }
- }
- if(y==100)
- {
- Right_Down_Point_finish_flag=0;
- }
- }
- }
- }
- if(Left_Down_Point_finish_flag == 0)
- {
- if(y > Endline && Left_Black_Point[y-1]==0 && Left_Black_Point[y-2]==0 && Emo_imag[y][Left_Black_Point[y]+6] == EmoWhite
- && y > Endline && Emo_imag[y-2][Left_Black_Point[y]] == EmoWhite && Emo_imag[y-5][Left_Black_Point[y]] == EmoWhite) //左下拐点
- {
- star=y;
- for(uint8 y=star;y<=(star+18);y++)
- {
- if(Left_Black_Point[y]>4 && Emo_abs(Left_Black_Point[y+1]-Left_Black_Point[y])<3
- && Emo_abs(Left_Black_Point[y+2]-Left_Black_Point[y])<4)
- {
- findl_x=Left_Black_Point[y];
- findl_y=y;
- for(uint8 dircount = 0;dircount<5;dircount++)
- {
- examl_x=findl_x+directionld[dircount][0];
- examl_y=findl_y+directionld[dircount][1];
- if(Emo_imag[examl_y][examl_x]==255)
- {
- examcount++;
- }
- }
- if(examcount>=4 )
- {
- examcount=0;
- Left_Down_Point[0]=findl_x;
- Left_Down_Point[1]=findl_y;
- // if(Last_Left_Point[0] == 0)
- // {
- // Last_Left_Point[0] = Left_Down_Point[1];
- // }
- // if(Emo_Uint8_dec(Left_Down_Point[1],Last_Left_Point[0]) < -15)
- // {
- // Left_Down_Point_finish_flag = 0;
- // }
- // else
- // {
- Left_Down_Point_finish_flag = 1;
- // Last_Left_Point[0] = Left_Down_Point[1];
- // }
- // findlcount = y-star;
- break;
- }
- else
- {
- Left_Down_Point_finish_flag = 0;
- examcount=0;
- }
- }
- if(y==100)
- {
- Left_Down_Point_finish_flag=0;
- }
- }
- }
- }
- // if(CrossLeft_Down_Point_finish_flag==1 && CrossRight_Down_Point_finish_flag==1)
- // {
- // break;
- // }
- }
- if(Left_Down_Point_finish_flag==1 && Right_Down_Point_finish_flag==1)
- end=Right_Down_Point[1];
- else if(Left_Down_Point_finish_flag==1)
- end=Left_Down_Point[1];
- else if(Right_Down_Point_finish_flag==1)
- end=Right_Down_Point[1];
- else
- end=94;
- for(uint8 y=20;y<=end;y++)
- {
- if(Right_Up_Point_finish_flag == 0)
- {
- if(y > Endline && Right_Black_Point[y+1]==187 && Right_Black_Point[y+2]==187 && Right_Black_Point[y+3]==187) //右上拐点
- {
- star=y;
- for(uint8 y=star;y>=(star-22);y--)
- {
- if(Right_Black_Point[y]<180 && Emo_abs(Right_Black_Point[y-1]-Right_Black_Point[y])<4
- && Emo_abs(Right_Black_Point[y-2]-Right_Black_Point[y])<4 && Emo_imag[y][Right_Black_Point[y]-6] == EmoWhite
- && Emo_imag[y-1][Right_Black_Point[y-1]-5] == EmoWhite && Emo_imag[y-2][Right_Black_Point[y]-5] == EmoWhite
- && Emo_imag[y-3][Right_Black_Point[y]-5] == EmoWhite && Right_Black_Point[y] > Middle_Black_Point[y] && Emo_imag[y+3][Right_Black_Point[y]] == EmoWhite
- && Emo_imag[y+5][Right_Black_Point[y]] == EmoWhite && Emo_imag[y+7][Right_Black_Point[y]] == EmoWhite)
- {
- findr_x=Right_Black_Point[y];
- findr_y=y;
- for(uint8 dircount = 0;dircount<5;dircount++)
- {
- examr_x=findr_x+directionru[dircount][0];
- examr_y=findr_y+directionru[dircount][1];
- if(Emo_imag[examr_y][examr_x]==255)
- {
- examcount++;
- }
- }
- if(examcount>=4 && findr_y >Endline)
- {
- examcount=0;
- Right_Up_Point[0]=findr_x;
- Right_Up_Point[1]=findr_y;
- if(Last_Right_Point[1] == 0)
- {
- Last_Right_Point[1] = Right_Up_Point[1];
- }
- if(Right_Up_Point[1] < 16)
- {
- Right_Up_Point[1] = Last_Right_Point[1];
- Right_Up_Point_finish_flag = 0;
- }
- else
- {
- Right_Up_Point_finish_flag = 1;
- Last_Right_Point[1] = Right_Up_Point[1];
- }
- findrcount=(int)star-(int)findr_y;
- break;
- }
- else
- {
- Right_Up_Point_finish_flag = 0;
- examcount=0;
- }
- }
- if(y==16)
- {
- Right_Up_Point_finish_flag=0;
- break;
- }
- if(y == 1)
- {
- break;
- }
- }
- }
- }
- if(Left_Up_Point_finish_flag == 0)
- {
- if(y > Endline && Left_Black_Point[y+1]==0 && Left_Black_Point[y+2]==0 && Left_Black_Point[y+3]==0) //左上拐点
- {
- star=y;
- for(uint8 y=star;y>=(star-22);y--)
- {
- if(Left_Black_Point[y]>8 && Emo_abs(Left_Black_Point[y-1]-Left_Black_Point[y])<4
- && Emo_abs(Left_Black_Point[y-2]-Left_Black_Point[y])<4 && Emo_imag[y][Left_Black_Point[y]+6] == EmoWhite
- && Emo_imag[y-1][Left_Black_Point[y-1]+5] == EmoWhite && Emo_imag[y-2][Left_Black_Point[y]+5] == EmoWhite
- && Emo_imag[y-3][Left_Black_Point[y]+5] == EmoWhite && Left_Black_Point[y] < Middle_Black_Point[y] && Emo_imag[y+3][Left_Black_Point[y]] == EmoWhite
- && Emo_imag[y+5][Left_Black_Point[y]] == EmoWhite && Emo_imag[y+7][Left_Black_Point[y]] == EmoWhite)
- {
- findl_x=Left_Black_Point[y];
- findl_y=y;
- for(uint8 dircount = 0;dircount<5;dircount++)
- {
- examl_x=findl_x+directionlu[dircount][0];
- examl_y=findl_y+directionlu[dircount][1];
- if(Emo_imag[examl_y][examl_x]==255)
- {
- examcount++;
- }
- }
- if(examcount>=4 && findl_y > Endline)
- {
- examcount=0;
- Left_Up_Point[0]=findl_x;
- Left_Up_Point[1]=findl_y;
- if(Last_Left_Point[1] == 0)
- {
- Last_Left_Point[1] = Left_Up_Point[1];
- }
- if(Left_Up_Point[1] < 16)
- {
- Left_Up_Point[1] = Last_Left_Point[1];
- Left_Up_Point_finish_flag = 0;
- }
- else
- {
- Left_Up_Point_finish_flag = 1;
- Last_Left_Point[1] = Left_Up_Point[1];
- }
- findlcount=(int)star-(int)y;
- break;
- }
- else
- {
- Left_Up_Point_finish_flag = 0;
- examcount=0;
- }
- }
- if(y==16)
- {
- Left_Up_Point_finish_flag=0;
- break;
- }
- if(y == 1)
- {
- break;
- }
- }
- }
- }
- }
-
- }

圆环的类似拐点距离丢线行比较远,于是我选择放开上拐点的距离限制,转而记录下扫描的拐点距离丢线的行数,正好发现可以用来区分17届新加的元素P字 。
当然因为如果距离圆环太远的话,圆环的特征是不太明显的,所以我会在识别到上下拐点时进入元素前摇的函数,在到达百分比区别P字和圆环前,将由此函数接管。
- //元素前摇
- //-------------------------------------------------------------------------------------------------------------------
- // @brief 元素前摇
- // @param
- // @param
- // @param
- // @param
- // @return void
- // @note 在扫描到两个符合的上下两个拐点后,针对先形拐点进行判断是什么元素,判断包括圆环、十字、P字
- //-------------------------------------------------------------------------------------------------------------------
- void Windup(void)
- {
- if(WindupL_flag == 1)
- {
- //Beepindex = Beepon;
- Link_Left_One_Point[0] = Left_Down_Point[0];
- Link_Left_One_Point[1] = Left_Down_Point[1];
- Link_Left_Two_Point[0] = Left_Up_Point[0];
- Link_Left_Two_Point[1] = Left_Up_Point[1];
- PaddingR = 0;
- PaddingL = 1;
- if(Right_Up_Point_finish_flag == 1 && Right_Down_Point_finish_flag == 1 && Left_Down_Point[1] > 42 && findlcount < 6 && Left_Up_Point[0] > 30)
- {
- Cross_flag = 1;
- WindupL_flag = 0;
- Beepindex = 0;
- }
- else if(Left_Up_Point_finish_flag == 1 && Left_Down_Point_finish_flag == 1 &&
- Right_Up_Point_finish_flag == 0 && Right_Down_Point_finish_flag == 0
- && Left_Down_Point[1] >= 75 && Left_Down_Point[1] <= 105 && findlcount < 4 && Left_Up_Point[0] > 30
- && (Left_Up_Point[0] - Left_Down_Point[0]) <= 42 && (Left_Down_Point[1] - Left_Up_Point[1]) >= 45
- && Right_Black_Point[Left_Up_Point[1]] < Right_Black_Point[(Left_Up_Point[1]+Left_Down_Point[1])/2]
- && Right_Black_Point[(Left_Up_Point[1]+Left_Down_Point[1])/2] < Right_Black_Point[Left_Down_Point[1]]
- && Right_Black_Point[Left_Up_Point[1]] < Right_Black_Point[Emo_one_third(Left_Down_Point[1],Left_Up_Point[1])]
- && Right_Black_Point[Emo_one_third(Left_Down_Point[1],Left_Up_Point[1])] < Right_Black_Point[Left_Down_Point[1]]
- && Right_Black_Point[Left_Up_Point[1]] < Right_Black_Point[Emo_two_third(Left_Down_Point[1],Left_Up_Point[1])]
- && Right_Black_Point[Emo_two_third(Left_Down_Point[1],Left_Up_Point[1])] < Right_Black_Point[Left_Down_Point[1]]
- && Right_Black_Point[Left_Up_Point[1]] < Right_Black_Point[Left_Down_Point[1]])
- {
- SlalomLeft_flag = 1;
- Slalomcount = 1;
- WindupL_flag = 0;
- }
- else if(Left_Up_Point_finish_flag == 1 && Left_Down_Point_finish_flag == 1 &&
- Right_Up_Point_finish_flag == 0 && Right_Down_Point_finish_flag == 0
- && Left_Down_Point[1] >= 75 && findlcount >= 8 && Left_Up_Point[0] > 30 && (Left_Down_Point[1] - Left_Up_Point[1]) >= 45
- && (Left_Down_Point[1] - Left_Up_Point[1]) <= 78 && Emo_imag[Left_Up_Point[1]][Left_Up_Point[0] - 5] != EmoWhite
- && Right_Black_Point[Left_Up_Point[1]] < Right_Black_Point[(Left_Up_Point[1]+Left_Down_Point[1])/2]
- && Right_Black_Point[(Left_Up_Point[1]+Left_Down_Point[1])/2] < Right_Black_Point[Left_Down_Point[1]]
- && Right_Black_Point[Left_Up_Point[1]] < Right_Black_Point[Emo_one_third(Left_Down_Point[1],Left_Up_Point[1])]
- && Right_Black_Point[Emo_one_third(Left_Down_Point[1],Left_Up_Point[1])] < Right_Black_Point[Left_Down_Point[1]]
- && Right_Black_Point[Left_Up_Point[1]] < Right_Black_Point[Emo_two_third(Left_Down_Point[1],Left_Up_Point[1])]
- && Right_Black_Point[Emo_two_third(Left_Down_Point[1],Left_Up_Point[1])] < Right_Black_Point[Left_Down_Point[1]]
- && Right_Black_Point[Left_Up_Point[1]] < Right_Black_Point[Left_Down_Point[1]])
- {
- if(findlcount >= 16)
- {
- CircleBig = 1;
- }
- CircleLeft_flag = 1;
- Circlecount = 1;
- WindupL_flag = 0;
- }
- else if(Left_Up_Point_finish_flag == 1 && Left_Down_Point_finish_flag == 1 && Right_Up_Point_finish_flag == 0 && Right_Down_Point_finish_flag == 0 && Left_Down_Point[1] <= 110
- && findlcount <= 17)
- {
- GarageL_Find();
- if(GarageL_Findfinish_flag == 1)
- {
- GarageL_Findfinish_flag = 0;
- GarageL_flag = 1;
- WindupL_flag = 0;
- }
- }
- else if(Left_Down_Point_finish_flag == 0)
- {
- WindupL_flag = 0;
- PaddingR = 0;
- PaddingL = 0;
- Beepindex = 0;
- }
- }
- else if(WindupR_flag == 1)
- {
- //Beepindex = Beepon;
- Link_Right_One_Point[0] = Right_Down_Point[0];
- Link_Right_One_Point[1] = Right_Down_Point[1];
- Link_Right_Two_Point[0] = Right_Up_Point[0];
- Link_Right_Two_Point[1] = Right_Up_Point[1];
- PaddingR = 1;
- PaddingL = 0;
- if(Left_Up_Point_finish_flag == 1 && Left_Down_Point_finish_flag == 1 && Right_Down_Point[1] > 42 && findrcount < 6 && Right_Up_Point[0] < 158)
- {
- Cross_flag = 1;
- WindupR_flag = 0;
- Beepindex = 0;
- }
- else if(Right_Up_Point_finish_flag == 1 && Right_Down_Point_finish_flag == 1 &&
- Left_Up_Point_finish_flag == 0 && Left_Down_Point_finish_flag == 0
- && Right_Down_Point[1] >= 75 && Right_Down_Point[1] <= 105 && findrcount < 4 && Right_Up_Point[0] < 158
- && (Right_Down_Point[0] - Right_Up_Point[0]) <= 42 && Right_Down_Point[1] - Right_Up_Point[1] >= 45
- && Right_Down_Point[1] - Right_Up_Point[1] <= 78 && Emo_imag[Right_Up_Point[1]][Right_Up_Point[0] + 5] != EmoWhite
- && Left_Black_Point[Right_Up_Point[1]] > Left_Black_Point[(Right_Up_Point[1]+Right_Down_Point[1])/2]
- && Left_Black_Point[(Right_Up_Point[1]+Right_Down_Point[1])/2] > Left_Black_Point[Right_Down_Point[1]]
- && Left_Black_Point[Right_Up_Point[1]] > Left_Black_Point[Emo_one_third(Right_Down_Point[1],Right_Up_Point[1])]
- && Left_Black_Point[Emo_one_third(Right_Down_Point[1],Right_Up_Point[1])] > Left_Black_Point[Right_Down_Point[1]]
- && Left_Black_Point[Right_Up_Point[1]] > Left_Black_Point[Emo_two_third(Right_Down_Point[1],Right_Up_Point[1])]
- && Left_Black_Point[Emo_two_third(Right_Down_Point[1],Right_Up_Point[1])] > Left_Black_Point[Right_Down_Point[1]]
- && Left_Black_Point[Right_Up_Point[1]] > Left_Black_Point[Right_Down_Point[1]])
- {
- SlalomRight_flag = 1;
- Slalomcount = 1;
- WindupR_flag = 0;
- }
- else if(Right_Up_Point_finish_flag == 1 && Right_Down_Point_finish_flag == 1 &&
- Left_Up_Point_finish_flag == 0 && Left_Down_Point_finish_flag == 0
- && Right_Down_Point[1] >= 75 && findrcount >= 9 && Right_Up_Point[0] < 158 && Right_Down_Point[1] - Right_Up_Point[1] >= 45
- && Left_Black_Point[Right_Up_Point[1]] > Left_Black_Point[(Right_Up_Point[1]+Right_Down_Point[1])/2]
- && Left_Black_Point[(Right_Up_Point[1]+Right_Down_Point[1])/2] > Left_Black_Point[Right_Down_Point[1]]
- && Left_Black_Point[Right_Up_Point[1]] > Left_Black_Point[Emo_one_third(Right_Down_Point[1],Right_Up_Point[1])]
- && Left_Black_Point[Emo_one_third(Right_Down_Point[1],Right_Up_Point[1])] > Left_Black_Point[Right_Down_Point[1]]
- && Left_Black_Point[Right_Up_Point[1]] > Left_Black_Point[Emo_two_third(Right_Down_Point[1],Right_Up_Point[1])]
- && Left_Black_Point[Emo_two_third(Right_Down_Point[1],Right_Up_Point[1])] > Left_Black_Point[Right_Down_Point[1]]
- && Left_Black_Point[Right_Up_Point[1]] > Left_Black_Point[Right_Down_Point[1]])
- {
- if(findrcount >= 16)
- {
- CircleBig = 1;
- }
- CircleRight_flag = 1;
- Circlecount = 1;
- WindupR_flag = 0;
- }
- else if(Right_Up_Point_finish_flag == 1 && Right_Down_Point_finish_flag == 1 &&
- Left_Up_Point_finish_flag == 0 && Left_Down_Point_finish_flag == 0 && Right_Down_Point[1] <= 110 && findrcount <= 17)
- {
- GarageR_Find();
- if(GarageR_Findfinish_flag == 1)
- {
- GarageR_Findfinish_flag = 0;
- GarageR_flag = 1;
- WindupR_flag = 0;
- }
- }
- else if(Right_Down_Point_finish_flag == 0)
- {
- WindupR_flag = 0;
- PaddingR = 0;
- PaddingL = 0;
- Beepindex = 0;
- }
- }
- }

因为上下拐点之间是有丢线的,所以我们需要做补线处理。
对于十字或者刚开始的P字和圆环,我们只要补直线就好。
- /*******************补线**********************/
- //先找到要补充的两条线,通过两点计算斜率得到两点组成的一次方程,得到剩余x的位置,将线换做左右边线
- //-------------------------------------------------------------------------------------------------------------------
- // @brief 直线补线函数
- // @param xone 第一个补线点x坐标
- // @param yone 第一个补线点y坐标
- // @param xtwo 第二个补线点x坐标
- // @param ytwo 第二个补线点y坐标
- // @return void
- // @note Left_Black_Point[y]为我的左边线数组 Right_Black_Point[y]为我的右边线数组
- //-------------------------------------------------------------------------------------------------------------------
- void Padding_LineR(uint8 xone,uint8 yone,uint8 xtwo,uint8 ytwo)
- {
- float k=0; //斜率
- float b=0; //截距
- //uint8 xstar=0;
- //uint8 xend=0;
- uint8 ystar=0;
- uint8 yend=0;
-
- k=((float)ytwo - (float)yone)/((float)xtwo - (float)xone);
- //k=((float)xtwo - (float)xone)/((float)ytwo - (float)yone);
- b=(float)yone - ((float)xone*k);
-
- if(yone>ytwo)
- {
- ystar=ytwo;
- yend=yone;
- }
- else
- {
- ystar=yone;
- yend=ytwo;
- }
- for(uint8 y=ystar;y<=yend;y++)
- {
- Right_Black_Point[y]=(uint8)(((float)y-b)/k); //两点之间补线
- }
- }

而对于入环和出环这类的控制,我们希望车子运行能够更加顺滑一些,于是我们选择补曲线。当然还需注意开始和结束补线的时机。
- //补曲线,利用弯道进行补
- //Cx曲线上点x,Cy曲线上点y
- //-------------------------------------------------------------------------------------------------------------------
- // @brief 曲线补线函数
- // @param Ux 上补线点x坐标
- // @param Uy 上补线点y坐标
- // @param Dx 下补线点x坐标
- // @param Dx 下补线点y坐标
- // @return void
- // @note 利用拉个朗日插值法,上下两个点由图像决定,中间点为固定点,如果补线效果不好,需要重新校准中间点
- // Left_Black_Point[y]为我的左边线数组 Right_Black_Point[y]为我的右边线数组
- //-------------------------------------------------------------------------------------------------------------------
- void Padding_CurveL(uint8 Ux,uint8 Uy,uint8 Dx,uint8 Dy)
- {
- int x0 = 0,x1 = 0,x2 = 0;
- int y0 = 0,y1 = 0,y2 = 0;
-
-
- //0.0096 -2.1047 138.5182
- //0.0103 -2.2049 141.8985
- //x=x0(y-y1)(y-y2)/(y0-y1)(y0-y2)+x1(y-y0)(y-y2)/(y1-y0)(y1-y2)+x2(y-y0)(y-y1)/(y2-y0)(y2-y1)
- x0 = (int)Dx;
- x1 = (int)(Dx + (float)3*(Ux-Dx)/5);
- x2 = (int)Ux;
- y0 = (int)Dy;
- y1 = (int)(Dy - (float)2*(Dy-Uy)/3);
- y2 = (int)Uy;
- if(Ux == 0 && Ux == 0 && Dx == 0 && Dy == 0)
- {
-
- }
- else
- {
- if(Dy > 110)
- {
- Dy = 110;
- }
- //Re = Left_Black_Point[Dy];
- // Left_Black_Point[Dy] = (uint8)(a*(float)(Dy*Dy)+b*(float)Dy+c);
- //error = (int)Re - (int)Left_Black_Point[Dy];
- for(uint8 y = Uy ;y <= Dy;y++)
- {
- // Re = y - Uy + 25;
- // Left_Black_Point[y]=(uint8)(a*(float)(Re*Re)+b*(float)Re+c);
- Left_Black_Point[y]=(uint8)((x0*(y-y1)*(y-y2))/((y0-y1)*(y0-y2)))+((x1*(y-y0)*(y-y2))/((y1-y0)*(y1-y2)))+((x2*(y-y0)*(y-y1))/((y2-y0)*(y2-y1)));
- }
- }
-
- }
-
- void Padding_CurveR(uint8 Ux,uint8 Uy,uint8 Dx,uint8 Dy)
- {
- int x0 = 0,x1 = 0,x2 = 0;
- int y0 = 0,y1 = 0,y2 = 0;
- //0.0096 -2.1047 138.5182
- //0.0103 -2.2049 141.8985
- //x=x0(y-y1)(y-y2)/(y0-y1)(y0-y2)+x1(y-y0)(y-y2)/(y1-y0)(y1-y2)+x2(y-y0)(y-y1)/(y2-y0)(y2-y1)
- x0 = (int)Dx;
- x1 = (int)(Dx - (float)3*(Dx-Ux)/5);
- x2 = (int)Ux;
- y0 = (int)Dy;
- y1 = (int)(Dy - (float)2*(Dy-Uy)/3);
- y2 = (int)Uy;
- if(Ux == 0 && Ux == 0 && Dx == 0 && Dy == 0)
- {
-
- }
- else
- {
- if(Dy > 110)
- {
- Dy = 110;
- }
- for(uint8 y = Uy ;y <= Dy;y++)
- {
- Right_Black_Point[y]=(uint8)((x0*(y-y1)*(y-y2))/((y0-y1)*(y0-y2)))+((x1*(y-y0)*(y-y2))/((y1-y0)*(y1-y2)))+((x2*(y-y0)*(y-y1))/((y2-y0)*(y2-y1)));
- }
- }
-
- }

补线的点的确定就需要同学自己去定了,也可以参考我的源码上边的点。为了不让元素的代码很乱,所以我选择在需要补线的地方选定补线的点,并打开补线标志,这样当独列出一个函数用来补线,就不会造成元素的代码里边充斥着补线的代码。不然更改补线方式后,需要对每个补线的程序进行更改。
- //-------------------------------------------------------------------------------------------------------------------
- // @brief 补线函数
- // @param PaddingR 右补线标志 0:不补线 1:要补线
- // @param PaddingL 左补线标志
- // @param Padding_CurveR 右曲线补线标志 0:补直线 1:补曲线
- // @param Padding_CurveL 左曲线补线标志
- // @return void
- // @note 补线的方式都通过此函数进行,外部只需要做到决定补线点的位置,和是否左右补线
- // Left_Black_Point[y]为我的左边线数组 Right_Black_Point[y]为我的右边线数组
- //-------------------------------------------------------------------------------------------------------------------
- void Padding_Line(void)
- {
- if(PaddingL == 1 && PaddingR == 1 && Paddingcurve == 0)
- {
- Padding_LineR(Link_Right_One_Point[0],Link_Right_One_Point[1],Link_Right_Two_Point[0],Link_Right_Two_Point[1]);
- Padding_LineL(Link_Left_One_Point[0],Link_Left_One_Point[1],Link_Left_Two_Point[0],Link_Left_Two_Point[1]);
- }
- else if(PaddingL == 1 && PaddingR == 0 && Paddingcurve == 0)
- {
- Padding_LineL(Link_Left_One_Point[0],Link_Left_One_Point[1],Link_Left_Two_Point[0],Link_Left_Two_Point[1]);
- Padding_LineR(0,0,0,0);
- }
- else if(PaddingL == 0 && PaddingR == 1 && Paddingcurve == 0)
- {
- Padding_LineR(Link_Right_One_Point[0],Link_Right_One_Point[1],Link_Right_Two_Point[0],Link_Right_Two_Point[1]);
- Padding_LineL(0,0,0,0);
- }
- else if(PaddingL == 0 && PaddingR == 1 && Paddingcurve == 1)
- {
- Padding_CurveR(Link_Right_One_Point[0],Link_Right_One_Point[1],Link_Right_Two_Point[0],Link_Right_Two_Point[1]);
- Padding_CurveL(0,0,0,0);
- }
- else if(PaddingL == 1 && PaddingR == 0 && Paddingcurve == 1)
- {
- Padding_CurveL(Link_Left_One_Point[0],Link_Left_One_Point[1],Link_Left_Two_Point[0],Link_Left_Two_Point[1]);
- Padding_CurveR(0,0,0,0);
- }
- else
- {
- Padding_LineL(0,0,0,0);
- Padding_LineR(0,0,0,0);
- }
- }

如果有对本文章有建议或者看法的话,可以评论或者私信我,希望可以和各位多多交流。本文章中的代码已经开源,开源地址:GitHub - StingeMoZGD/17th-SmartCar: 17届智能车竞赛,无线充电组
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。