当前位置:   article > 正文

智能车学习日记【四】————环岛_智能车环岛判断程序

智能车环岛判断程序

智能车学习日记【四】————环岛


前言

环岛从第一次写完到国赛结束之间重写了很多遍,都是在上一次的思路上修修补补,只能说图像补出来的效果还行,但代码结构就和屎山一样,所以我环岛篇就着重说一下我的补线思路(我的方法其实还有很多漏洞需要改进,仅供大家参考理解一下,欢迎各位在评论区指点出可改进之处!)


一、环岛分状态(以左环岛为例)

我将环岛分为7个状态,如下图
环岛状态1:远处看见并判出环岛
在这里插入图片描述
环岛状态2:环岛直行部分
在这里插入图片描述
环岛状态3:拉线转入环岛
在这里插入图片描述
环岛状态4:环岛内转弯
在这里插入图片描述
环岛状态5:拉线出环
在这里插入图片描述

环岛状态6:直道拉线摆正
在这里插入图片描述
环岛状态7:拉线直行
在这里插入图片描述
环岛状态8:退出(可以不细分这个状态)
在这里插入图片描述
整体效果(视频转gif后丢了很多帧导致看着很卡顿)
在这里插入图片描述

二、每个状态思路

状态1和状态2:

状态1和状态2我是放在了判断的最前头,因为直道接环岛会先进入状态1,而弯道接环岛可能会跳过状态1而直接进入状态2。
是进入状态1还是状态2是取决于找到拐点的数量和其他小的限制条件。
下图中红色是下拐点,橙色是中拐点,绿色是上拐点
在这里插入图片描述
在这里插入图片描述
首先进行基础扫线将左右边线扫描出来。这时要进行一波分类,首先找下拐点。
1.若是能找到下拐点,则说明可能是直道接环岛,接下来若能找到中上拐点则直接进入环岛状态1。
2.若找不到下拐点,且左下边的丢线行比较多则说明可能是弯接环岛,接下来若能找到中上拐点则直接进入环岛状态2。

找下拐点思路:与普通十字找下拐点思路类似,一般都会有很明显的突变,根据图像突变找即可。

找中拐点思路:中拐点需要找中间的")" 或 "("形状的最突出点。这个只需要用边线的变化,对于左环岛,中间这段边线是先减小再增大,则突变点就为中拐点。

找上拐点思路:找上拐点与找十字上拐点的方法相似,都是通过上边连续下边突变的方法来找到,当然条件需要适当修改,一般可以认为中拐点与上拐点在一个相近的x区域中,防止上拐点找错找偏。对于状态一而言上拐点太远了,有时候可能就是几个像素,所以我在状态1时拉线会多考虑下拐点和中拐点进行拉线,上拐点只是作为一个进入状态的依据。

状态3:

在这里插入图片描述
状态3为拉线入环。这里就是找一个左上拐点进行拉线即可,这一状态的方法比较简单。值得一提的是在入环时由于车身逐渐偏移,可能会导致中线偏移,使得原本属于左线的部分被归类为右线,就找不出左上拐点。为了解决这种情况,我是添加了一种扫线方式,即找到的左上拐点较远时,依旧采用中线扫线的方式来找拐点拉线,而当左上拐点的高度下降到一定值时,切换扫线方式,改为由左向右扫线(即左边全丢线,然后扫出右边线去找右上拐点。若是右环岛应改为从右向左扫线)。当然使用这些方法的目的是准确找出拉线的上拐点,只要能准确找出来方法是什么倒不是很重要。

状态4:

这个状态没什么好说的,正常的弯道转弯,不需要任何的拉线操作。调好pid和差速即可

状态5:

在这里插入图片描述

状态5为拉线出环,之前状态4过程中是无法找到图中拉线的右下拐点的,当找到右下拐点时跳转到状态5,开始拉线出环。这里找拐点的方式比较简单,几乎不存在中线扫错的情况,左右边线基本都能正确找出来,唯一和找正常下拐点不同的是这个拐点的上下部分都比较连续,没有很大突变,博主是放宽了找拐点的条件,只要有凸出来的地方就算是拐点,而且这种地方一般只有这个拐点处凸的很明显,也很难找错(要是路肩贴的不好出现奇奇怪怪的拐角就另说了)。找到拐点就好拉线了,我这里并没有拉到最左边,因为拉到最左边的话会导致图像倾斜特别厉害,小环容易转得太厉害了导致撞内路肩和侧翻,所以我是在左边线上找了一个点进行拉线。

状态6:

当拉线的拐点消失或者太低了就从状态5转到状态6。状态六的拉线我是比较暴力的,状态5结束时,底下基本都是白色的,左右两边也是白色的,于是我从最左底下开始往上找,找到不丢线的点,然后与右下原点直接拉线。这里拉线方式无所谓,目的就是让他能一直往左转弯,甚至要是很懒的话可以把5和6合并为一个状态用一个拉线方式,只是6的下拐点固定为右下原点(0,0)。

状态7:

在这里插入图片描述
状态6的时候一直找左上拐点,由于状态6左边一直丢线,所以是一直找不到左上拐点,当找到时,跳转到7状态,持续找左上拐点,然后拉线直行。等到左上拐点太低了,或者是找不到了,跳转到最后的退出状态。

部分代码:

前言就说了我开始写这个环岛时没想过什么安排一个合理的结构,所以代码特别乱,有些部分判段嵌套在其他地方了,没办法全部移过来,不过代码主体思路就是我上面的说明,然后就对每一个地方进行细化和微调即可。下面的代码看看图一乐知道大概就好

void huandao_zuo()
 {
    // SetText(" —————————————————————————————————————————————  ");
    // SetText(" ************************************* 左环岛状态机 ***************************************  ");
     int k = 1;
     byte unwhite_zuo = 0;
     byte i;
     byte laxian = 0;
     byte k1 = 0;
     find_middleline();
     findpot();
     int j = 0;
     num1 = 0;
     num2 = 0;
     num3 = 0;
     num4 = 0;
     fangcha(2, 0, 50);
     fangcha_you = (int)sumE;
     advanced_regression(2, 20, 25, 25, 30);
     xielv_now = parameterB;
     advanced_regression(1, 0, 2, 2, 5);
   //  SetText("parameterB11 " + parameterB);
     for (i = 0; i < 50; i++)
     {
         if (L_black[i] == 185)
         {
             j++;
         }
         else
         {
            // SetText("左边丢线行 " + j);
             break;
         }
     }
     if (kt >= 21)
     {
         hd_state = 2;
         kt = 0;
     }
     if ((float_abs(parameterB) >= 0.1 || j < 20) && hd_state <= 1)   //第一个状态,底下没丢线
     {
         hd2_findmiddle();
         for (i = 1; i < 20; i++)
         {
             if (L_black[i] != 185)
             {
                 k = i;
                 break;
             }
         }

         for (i = (byte)k; i < 69; i++)
         {
             if (firstto_hd == 0)
             {
                 if (((L_black[i] - L_black[i - 1] > 3 && L_black[i + 1] - L_black[i - 1] > 3 && L_black[i + 1] - L_black[i] >= 0) || (tubian_xia_y > 0 && L_black[i] > tubian_xia_x)) && num2 <= 15 && i < 45)
                 {
                     num2++;
                     if (num2 == 1)
                     {
                         tubian_xia_y = (byte)(i - 1);                            //记录第一次突变点
                         tubian_xia_x = L_black[i - 1];
                        // SetText("tubian_xia_x " + tubian_xia_x + " tubian_xia_y " + tubian_xia_y);
                     }
                 }
                 if (num2 > 5)
                 {
                     if ((L_black[i] - L_black[i - 1] <= -1 && num3 <= 7) || (num3 >= 5 && L_black[i] - L_black[i - 1] <= 0))
                     {
                         num3++;
                     }
                 }
                 if (num3 >= 7)
                 {
                     if (L_black[i] - L_black[i - 1] > 0)
                     {
                         num4++;
                         if (num4 == 1 && i - 1 < 60)
                         {
                             tubian_zhong_y = (byte)(i - 1);
                             tubian_zhong_x = L_black[i - 1];
                           //  SetText("tubian_zhong_x " + tubian_zhong_x + "tubian_zhong_y  " + tubian_zhong_y);
                         }
                     }
                 }
                 if (num4 > 1)
                 {
                     if (abs(L_black[i + 1] - L_black[i]) <= 1 && L_black[i] - L_black[i - 1] < -6 && L_black[i] > tubian_zhong_x)
                     {
                         tubian_shang_x = L_black[i];
                         tubian_shang_y = i;
                        // SetText("tubian_shang_x " + tubian_shang_x + " tubian_shang_y " + tubian_shang_y);
                     }
                 }
             }
             if (tubian_xia_y > 0 && tubian_zhong_y > 0 && tubian_shang_y > 0)          //3个拐点都找到
             {
                 advanced_regression(1, tubian_xia_y - 1, tubian_xia_y, tubian_zhong_y - 1, tubian_zhong_y);
                 run(1, tubian_xia_y - 1, tubian_zhong_y, parameterB, parameterA);
                 advanced_regression(1, tubian_zhong_y - 1, tubian_zhong_y, tubian_shang_y, tubian_shang_y + 1);
                 run(1, tubian_zhong_y, tubian_shang_y, parameterB, parameterA);
                 run(0, 0, tubian_shang_y, parameterB, parameterA);
               //  SetText("parameterB " + parameterB + " parameterA " + parameterA);
              //   SetText(" 状态 :  赛道中间 正常补线  ");
                 break;
             }
             else if (tubian_xia_y > 0 && tubian_zhong_y > 0 && tubian_shang_y == 0 && (i == 68 || firstto_hd == 1))   //上拐点没找到
             {
                 parameterB = (float)((tubian_xia_x - tubian_zhong_x) * 1.0 / (tubian_xia_y - tubian_zhong_y)*1.0);
                 parameterA = tubian_zhong_x - parameterB * tubian_zhong_y;
                 run(1, tubian_xia_y - 1, tubian_zhong_y, parameterB, parameterA);
                 run(0, 0, tubian_zhong_y, parameterB, parameterA);
               //  SetText("parameterB " + parameterB + " parameterA " + parameterA);
                // SetText(" 状态 :  赛道中间  没找到上拐点  正常补线  ");
                 break;
             }
         }
         hd_state = 1;                       //状态一 正常补线
         firstto_hd = 0;
     }
     if ((parameterB > -0.1 && hd_state == 1 && tubian_xia_y == 0 && L_black[0] == 185) || hd_state == 2)                 // 底下丢线
     {
         hd2_findmiddle();
         findpot();
         hdtime2++;
         byte unwhitenum_zuo = 0;
         for (i = 1; i < 20; i++)
         {
             if (L_black[i] != 185)
             {
                 k = i;
                 break;
             }
         }
         for (i = (byte)k; i < 69; i++)     //这里找下拐点是因为弯接环岛后实际应该为状态1,却判定为状态2,而本来下拐点的位置找成中拐点,所以可以根据中下拐点的位置来判断是否需要回退状态,这个下拐点找的条件较松,尽量按照中拐点的方式去找
         {
             if (L_black[i] - L_black[i - 1] >= 1 && L_black[i + 1] - L_black[i - 1] >= 1 && L_black[i + 1] - L_black[i] >= 0 && i > 1)
             {
                 tubian_xia_y = (byte)(i - 1);                            //记录第一次突变点
                 tubian_xia_x = L_black[i - 1];
                // SetText("tubian_xia_x " + tubian_xia_x + " tubian_xia_y " + tubian_xia_y);
                 break;
             }
         }
         for (i = (byte)k; i < b-1; i++)
         {
             if ((L_black[i] - L_black[i - 1] > 0 && i > 1 && L_black[i+1] - L_black[i-1] > 0 && L_black[i - 1] >= 5 && L_black[i - 1] <= 180) || (num4 >= 1 && L_black[i] == 185))
             {
                 num4++;
                 if (num4 >= 1 && i - 1 < 59 && tubian_zhong_y == 0)
                 {
                     tubian_zhong_y = (byte)(i - 1);
                     tubian_zhong_x = L_black[i - 1];
                    // SetText("tubian_zhong_x " + tubian_zhong_x + "tubian_zhong_y  " + tubian_zhong_y);
                 }
             }
             if (num4 > 1)
             {
                 if (abs(L_black[i + 1] - L_black[i]) <= 6 && L_black[i] - L_black[i - 1] >= -3 && L_black[i] < tubian_zhong_x && tubian_zhong_y != 0)
                 {
                     tubian_shang_x = L_black[i];
                     tubian_shang_y = i;
                   //  SetText("tubian_shang_x " + tubian_shang_x + " tubian_shang_y " + tubian_shang_y);
                 }
             }
             if (tubian_zhong_y > 0)
             {
                 j = 0;
                 for (y = 0; y < tubian_zhong_y; y++)
                 {
                     if (L_black[y] == 185)
                     {
                         j++;
                     }
                 }
             }
             if (tubian_zhong_y > 0 && tubian_shang_y > 0)    //上中拐点都找到
             {
                 hd2_ChangeStateTime++;
               //  SetText("hd2_ChangeStateTime = " + hd2_ChangeStateTime);
                 if (hd2_ChangeStateTime <= 4)      //如果二状态中拐点下面不是全白,则回退一状态
                 {
                     for (y = tubian_zhong_y; y >= 0; y--)
                     {
                         if (L_black[y] == 185)
                             break;
                         if (y == 0)
                             break;
                     }
                     if (y <= 3)
                     {
                         if (abs(tubian_zhong_y - tubian_xia_y) < 5 && tubian_zhong_y <= 25 && L_black[tubian_zhong_y + 10] == 185)
                         {
                             hd_state = 1;
                            // SetText("弯接环岛第" + hd2_ChangeStateTime + "帧,底下出现非丢线行,环岛状态2变为1");
                         }
                     }
                     else
                     {
                         for (; y >= 0; y--)
                         {
                             if (L_black[y] != 185)
                                 unwhitenum_zuo++;
                             if (y == 0)
                                 break;
                         }
                         if (unwhitenum_zuo >= 5 && abs(tubian_zhong_y - tubian_xia_y) < 5)
                         {
                             hd_state = 1;
                          //   SetText("弯接环岛第" + hd2_ChangeStateTime + "帧,底下出现非丢线行,环岛状态2变为1");
                         }
                     }
                 }
                 advanced_regression(1, tubian_zhong_y - 1, tubian_zhong_y, tubian_shang_y, tubian_shang_y + 1);
                 float kb = parameterB;
                 float jieju = parameterA;
                 if (parameterB <= -1.15 || parameterB >= 0)
                 {
                     advanced_regression(1, tubian_shang_y, tubian_shang_y + 1, tubian_shang_y + 2, tubian_shang_y + 3);
                     if (parameterB <= -1.15 || parameterB >= 0)
                     {
                         byte y1 = 0;
                         for (y = tubian_zhong_y; y > 1; y--)
                         {
                             if (L_black[y] - L_black[y - 1] < 0 && L_black[y - 1] - L_black[y - 2] < 0)
                             {
                                 y1 = (byte)(y - 2);
                                 break;
                             }
                         }
                         if (y1 > 3)
                         {
                             advanced_regression(1, y1, y1 - 1, y1 - 2, y1 - 3);
                         }
                         if (parameterB <= -1.15 || parameterB >= 0)
                         {
                             parameterB = kb;
                             parameterA = jieju;
                         }
                     }
                 }
                 run(1, 0, 68, parameterB, parameterA);
                 run(0, 0, tubian_shang_y, parameterB, parameterA);
               //  SetText("中上拐点之间拉线斜率为" + parameterB);
                 //  SetText(" 状态 :  即将进入环岛 正常补线  ");
                 break;
             }
             else if (tubian_zhong_y > 0 && tubian_shang_y == 0 && i == 68)
             {
                 advanced_regression(1, tubian_zhong_y - 2, tubian_zhong_y - 1, tubian_zhong_y - 1, tubian_zhong_y);
                 run(1, 0, 68, parameterB, parameterA);
                 run(0, 0, 68, parameterB, parameterA);
                 // SetText(" 状态 :  即将进入环岛  没找到上拐点  正常补线  ");
                 break;
             }
         }
         if ((unwhitenum_zuo >= 5 || ((abs(tubian_zhong_y - tubian_xia_y) < 5) && hd_state == 1 && hd2_ChangeStateTime <= 5)))
         {
             hd2_ChangeStateTime = 10;
         }
         else
         {
            // SetText("j = " + j);
             hd_state = 2;
             if ((tubian_zhong_y == 0 && tubian_shang_y == 0) || (tubian_shang_y >= 58 && tubian_zhong_y >= 50 && Pixels[0][185] != 0 && Pixels[5][185] != 0 && last_tubian_zhong_y < 45 && hdtime2 >= 5))       //都没找到,可能左边丢线
             {
                 k1 = 0;
                 fangcha(1, 0, 50);
                 fangcha_zuo = (int)sumE;
                 fangcha(2, 0, 50);
                 fangcha_you = (int)sumE;
               //  SetText("fangcha_zuo " + fangcha_zuo + " fangcha_you " + fangcha_you);
                 for (y = 0; y < 50; y++)
                 {
                     if (Pixels[y][185] == 0)
                     {
                         k1++;
                     }
                     for (x = LCenter[0]; x < 186; x++)
                     {
                         if (x == 185)
                         {
                             k++;
                             break;
                         }
                         if (Pixels[y][x] != 0 && Pixels[y][x + 1] == 0 && Pixels[y][x - 1] != 0)
                         {
                             break;
                         }
                     }
                 }
                 if (k >= 37 && fangcha_zuo > 300 && lefty[1] != 0 && tubian_zhong_y >= 40)
                 {
                     hd_state = 3;
                 }
                 else if (k >= 31 && fangcha_zuo > 300 && lefty[1] != 0 && tubian_zhong_y < 40)
                 {
                     hd_state = 3;
                 }
                 else if (k >= 25 && fangcha_zuo < 900 && lefty[1] != 0 && tubian_zhong_y == 0)
                 {
                     hd_state = 3;
                 }
             }
         }
     }
     if ((Pixels[0][185] == 0 && Pixels[2][185] == 0 && Pixels[3][185] == 0 && hd_state == 2 && k1 > 20) || (hd_state == 3) || (j >= 40 && hd_state == 2 && (tubian_zhong_y < 44 || (j >= 40 && tubian_zhong_y >= 50 && tubian_shang_y == 0)) && lefty[1] != 0) || (tubian_zhong_y >= 35 && j >= 21 && lefty[1] != 0 && last_tubian_zhong_y < 30 && last_tubian_zhong_y != 0) || (last_tubian_zhong_y < 25 && tubian_zhong_x > 180 && last_tubian_zhong_y != 0 && (j > 15 || (j == 0 && hdtime2 >= 4))))
     {
         k = 0;
         laxian = 0;
         find_middleline();
         findpot();
         if (lefty[1] == 0)
         {
             if (righty[1] == 0)
             {
                 for (i = 1; i < b; i++)
                 {
                     if (R_black[i] - R_black[i - 1] > 15 && i + 5 < b && R_black[i + 5] != 0)
                     {
                         lefty[1] = i;
                         leftx[1] = R_black[i];
                         break;
                     }
                 }
             }
             else
             {
                 for (i = 1; i < 60; i++)
                 {
                     if (R_black[i] - R_black[i - 1] > 15 && R_black[i] >= rightx[1] && i <= last_guaiy)
                     {
                         lefty[1] = i;
                         leftx[1] = R_black[i];
                         break;
                     }
                 }
                 if (lefty[1] == 0)
                 {
                     for (i = 1; i < 60; i++)
                     {
                         if (L_black[i] - L_black[i - 1] <= -10 && i <= last_guaiy)
                         {
                             lefty[1] = i;
                             leftx[1] = L_black[i];
                             break;
                         }
                     }
                 }
             }

         }
         if ((lefty[1] == 0 && b < 50) || abs(lefty[1] - b) < 10)
         {
             for (y = 1; y < b + 5; y++)
             {
                 for (x = (byte)(LCenter[0] - 10); x < 186; x++)
                 {
                     if (x == 185 || (Pixels[y][x] != 0 && Pixels[y][x - 1] != 0 && Pixels[y][x + 1] == 0))
                     {
                         L_black[y] = x;
                         break;
                     }
                 }
                 if (L_black[y] - L_black[y - 1] < -20 && L_black[y + 1] != 185)
                 {
                     lefty[1] = y;
                     leftx[1] = L_black[y];
                     break;
                 }
             }
         }
         if ((lefty[1] > 0 && lefty[1] <= 25 && L_black[0] == 185) || hd3_potlinechange == 1)             //入环时右上拐点太低了就换个扫线方式,防止基本扫线的中线太靠中间导致舵机打角太小
         {
             hd3_potlinechange = 1;
             hd_findline(4);
             laxian = 1;
          //   SetText("改为从左向右扫线");
         }
         if (lefty[1] > 0)
         {
             last_guaix = leftx[1];
             last_guaiy = lefty[1];
             parameterB = (float)((leftx[1] - 0) * 1.2) / (lefty[1]);
             parameterA = (float)(leftx[1] * 1.0 - parameterB * lefty[1] * 1.0);
           //  SetText("parameterB " + parameterB + " parameterA " + parameterA);
             run(2, 0, lefty[1], parameterB, parameterA);
             run(0, 0, lefty[1], parameterB, parameterA);
            // SetText(" 状态 :  进入环岛中  正常拉线   左上拐点 y,x" + lefty[1] + " " + leftx[1]);
             if (lefty[1] > 25)
             {
                 for (i = (byte)(lefty[1]); i < 69; i++)
                 {
                     LCenter[i] = LCenter[lefty[1] - 1];
                 }
             }
             else
             {
                 for (i = b; i < 70; i++)
                 {
                     LCenter[i] = 184;
                 }
             }
         }
         hd_state = 3;
         if (lefty[1] == 0 && last_guaiy != 0)
         {
             if (lefty[1] == 0)
             {
                 if (L_black[0] >= 185)
                 {
                     for (i = 184; i > 0; i--)
                     {
                         if (k == 0 && i > 5 && Pixels[0][i + 1] != 0 && Pixels[0][i] != 0 && Pixels[0][i - 1] == 0)
                         {
                             k = i;
                         }
                         if (i > 1 && k != 0 && Pixels[0][i + 1] == 0 && Pixels[0][i] == 0 && Pixels[0][i - 1] != 0)
                         {
                            // SetText("左下有断层,状态3变4");
                             flag4 = 1;
                             hd_state = 4;
                         }
                     }
                     if (hd_state != 4)
                     {
                         for (i = 184; i > 0; i--)
                         {
                             if (Pixels[0][i + 1] != 0 && Pixels[0][i] != 0 && Pixels[0][i - 1] == 0)
                             {
                                 break;
                             }
                         }
                         if (i > 1)
                         {
                             i--;
                             for (; i >= 0; i--)
                             {
                                 if (i == 0)
                                 {
                                     flag4 = 1;
                                     hd_state = 4;
                                   //  SetText("上拐点找不到,已经进入弯道状态,状态3变4");
                                     break;
                                 }
                                 if (Pixels[0][i] != 0)
                                 {
                                     break;
                                 }
                             }
                         }

                     }
                 }
             }
             if (hd_state == 3)
             {
                 parameterB = (float)((last_guaix - 0) * 1.2) / (last_guaiy);
                 parameterA = (float)(last_guaix * 1.0 - parameterB * last_guaiy * 1.0);
                // SetText("parameterB " + parameterB + " parameterA " + parameterA);
                 run(2, 0, last_guaiy, parameterB, parameterA);
                 if (laxian == 1)
                 {
                     run(0, 0, b, parameterB, parameterA);
                 }
                 else
                 {
                     run(0, 0, last_guaiy, parameterB, parameterA);
                     for (i = (byte)(last_guaiy); i < 69; i++)
                     {
                         LCenter[i] = LCenter[last_guaiy - 1];
                     }
                 }
                // SetText(" 状态 :  进入环岛中  根据上次拐点拉线  ");
             }
         }
     }
     if ((hd_state == 3 && Pixels[5][0] == 0 && Pixels[7][0] == 0 && Pixels[10][0] == 0 && b < 45 && lefty[1] <= 20 && laxian == 0) || ((hd_state == 4) || flag4 == 1) || (lefty[1] == 0 && righty[1] > 0 && hd_state == 3 && last_guaiy != 0))
     {
         j = 0;
         unwhite_zuo = 0;
         find_middleline();
         findpot();
         for (i = 1; i < 50; i++)
         {
             if (LCenter[i] != LCenter[i - 1])
             {
                 break;
             }
             if (i > 45)
             {
                 //SetText("重新扫线  ");
                 hd_findline(1);
                 break;
             }
             // SetText(" 状态 :  出环中  重新找线  ");
         }
         if (flag4 == 1)
         {
             hd_findline(1);
             flag4 = 0;
         }
        // SetText(" 状态 :  环岛内  正常拉线  ");
         hd_state = 4;
         hdtime4++;
         for (i = (byte)(b-1); i > 0; i--)
         {
             if (L_black[i] != 185 && L_black[i - 1] != 185)
             {
                 unwhite_zuo++;
             }
         }
         for (i = 1; i < b; i++)
         {
             if (R_black[i] - R_black[i - 1] <= -1 && R_black[i] != 0 && R_black[i + 1] - R_black[i] <= 0 && R_black[i + 1] != 0 && R_black[i + 2] - R_black[i + 1] <= 0)
             {
                 j = 1;
                 break;
             }
         }
     }
     if ((b >= 38 && hd_state == 4 && R_black[0] != 0 && hdtime4 > 3 && j == 1 && unwhite_zuo >= 3) || (hd_state == 5))
     {
         find_middleline();
         //findpot();
         for (i = 1; i < b; i++)
         {
             if (R_black[i] - R_black[i - 1] >= 0 && R_black[i + 1] - R_black[i] < 0)
             {
                 righty[0] = i;
                 rightx[0] = R_black[i];
              //   SetText("找到右下拐点y x " + i + " " + R_black[i]);
                 break;
             }
         }
         if (righty[0] > 0)
         {
             for (i = 1; i < b; i++)
             {
                 if (Pixels[i - 1][185] != 0 && Pixels[i][185] != 0 && Pixels[i + 1][185] == 0)
                 {
                     x = i;
                     y = 185;
                    // SetText("x " + x + " y " + y);
                     break;

                 }
             }
             if (x == righty[0])
                 x++;
             parameterB = (float)((y - rightx[0]) * 1.0 / (x - righty[0]));
             parameterA = (float)(rightx[0] * 1.0 - parameterB * righty[0] * 1.0);
            // SetText("parameterB " + parameterB + " parameterA " + parameterA);
             run(2, righty[0] - 1, b, parameterB, parameterA);
             for (i = 0; i < 60; i++)
             {
                 L_black[i] = 185;
             }
             run(0,0, 50, parameterB, parameterA);
             for (i = x; i < 70; i++)
             {
                 LCenter[i] = LCenter[x];
             }
             //SetText(" 状态 :  准备出环  正常拉线  ");
         }
         hd_state = 5;
         if (last_guaiy - righty[0] < -5 && last_guaiy != 0 && last_guaiy <= 16)
         {
             hd_state = 6;
         }
         last_guaiy = righty[0];

     }
     if ((righty[0] <= 7 && hd_state == 5 && last_guaiy < 15) || (hd_state == 6))
     {
         x = 0;
         y = 0;
         k = 0;
         byte cnt = 0;
         float k_you = 0;
         byte x_down = 0;
         byte y_down = 73;
         byte whitezuo = 0;
         byte whiteyou = 0;
         for (i = 0; i < 50; i++)
         {
             if (LCenter[i] != 92)
             {
                 break;
             }
             if (i > 48)
             {
                 hd_findline(1);
              //   SetText(" 状态 :  出环中  重新找线  ");
             }
         }
         for (i = 0; i < b; i++)
         {
             if (L_black[i] == 185)
                 whitezuo++;
             else
                 break;
         }
         for (i = 0; i < b; i++)
         {
             if (R_black[i] == 0)
                 whiteyou++;
             else
                 break;
         }
        // SetText("左边丢线行与右边丢线行的差值为:" + (whitezuo - whiteyou));

         for (i = 1; i < 60; i++)
         {
             if (L_black[i] == 185 && R_black[i] - R_black[i - 1] > 2 && R_black[i] != 0 && R_black[0] != 0)
             {
                 k++;
             }
         }
       //  SetText(" k " + k);
         if (k < 17)
         {
             for (i = 1; i < 68; i++)
             {
                 if (Pixels[i][185] == 0 && Pixels[i - 1][185] != 0 && Pixels[i + 1][185] == 0 && Pixels[i + 2][185] == 0)
                 {
                     x = i;
                     y = 185;
                     break;
                 }
             }
         }
         cnt = 0;
         for (i = 0; i < b; i++)
         {
             if (L_black[i] < 185 && L_black[i] >= 92)
             {
                 cnt++;
             }
         }
       //  SetText(" 左上边出现不是丢线数 cnt" + cnt);
         advanced_regression(2, 0, 15, 15, 30);
         k_you = parameterB;
        // SetText("右边下边30行的斜率是" + k_you);       //下边斜率不能太斜,防止大弯转弯过大导致左边提前出现黑色退出六状态
         if (b > 10)
         {
             fangcha(1, 0, b - 10);
             fangcha_zuo = (int)sumE;
             fangcha(2, 0, b - 10);
             fangcha_you = (int)sumE;
            // SetText("左方差 " + fangcha_zuo + " 右方差 " + fangcha_you);
         }
         for (i = 0; i < 185; i++)
         {
             if (Pixels[0][i] == 0 && Pixels[0][i+1] != 0)
             {
                 y_down = i;
                 break;
             }

         }
         if (x != 0 && y > 93)
         {
            // SetText("拉线的左上点 y=" + x + " x=" + y + "拉线下拐点y0=0 x0=" + y_down);
             parameterB = (float)((y - y_down) * 1.0 / x);
             parameterA = (float)(y * 1.0 - parameterB * x * 1.0);
             run(2, 0, x, parameterB, parameterA);
             run(0, 0, x, parameterB, parameterA);
            // SetText("parameterB " + parameterB + " parameterA " + parameterA);
             for (i = x; i < 60; i++)
             {
                 L_black[i] = L_black[x - 1];
                 R_black[i] = R_black[x - 1];
                 LCenter[i] = LCenter[x - 1];
             }
            // SetText(" 状态 :  出环中  正常拉线  ");
             laxian = 1;
         }
         if (y < 93)
         {
             //SetText("拉线的左上点 y=" + y + " x=" + x);
             for (i = 0; i < 70; i++)
             {
                 if (Pixels[i][185] != 0 && Pixels[i + 1][185] == 0)
                 {
                     x = i;
                     y = 185;
                     break;
                 }
             }
            // SetText("拉线的左上点 y=" + x + " x=" + y + "拉线下拐点y0=0 x0=" + y_down);
             parameterB = (float)((y - y_down) * 1.0 / x);
             parameterA = (float)(y * 1.0 - parameterB * x * 1.0);
             run(2, 0, x, parameterB, parameterA);
             run(0, 0, x, parameterB, parameterA);
            // SetText("parameterB " + parameterB + " parameterA " + parameterA);
             if (x > 0)
             {
                 for (i = x; i < 60; i++)
                 {
                     L_black[i] = L_black[x - 1];
                     R_black[i] = R_black[x - 1];
                     LCenter[i] = LCenter[x - 1];
                 }
             }
             laxian = 1;
         }
         if (b > 10)
         {
             if ((fangcha_zuo < 350 && cnt >= 15 && k_you <= 1.6 && k_you >= 0) || (fangcha_you < 40 && cnt >= 25 && k_you <= 2.3 && k_you >= 0) || (k_you <= 2 && (whitezuo - whiteyou) > 35 && k_you > 0.7))      //正常左线斜率不会这么小
             {
                 hd_state = 7;
             }
             else
             {
                 hd_state = 6;
             }
         }
     }
     if ((float_abs(xielv_now) > 2 && hd_state == 6 && float_abs(xielv_last) >= 2 && Pixels[5][185] == 0 && Pixels[10][185] == 0 && laxian == 0) || hd_state == 7)
     {
         find_middleline();
         findpot();
         fangcha(1, 0, 50);
         fangcha_zuo = (int)sumE;
         fangcha(2, 0, 50);
         fangcha_you = (int)sumE;
       //  SetText("左方差 " + fangcha_zuo + " 右方差 " + fangcha_you);
         juge_lineContinuity(20, 60, 3, -3, 0);
       //  SetText("中线连续行 " + long_turn_flag);
         for (i = 0; i < 50; i++)
         {
             if (L_black[i] < 185)
             {
                 i++;
             }
         }
         advanced_regression(1, 0, 20, 20, 40);
       //  SetText("左下边40行的斜率为" + parameterB);
         if ((i > 40 && L_black[15] != 185 && (lefty[1] <= 20 || lefty[1] >= 45) && long_turn_flag > 30) || (i > 40 && L_black[5] != 185 && L_black[3] != 185 && L_black[7] != 185))
         {
             if(parameterB <= 0)
                 hd_state = 8;                  //退出状态机
         }
         if (hd_state != 8)
         {
             if (lefty[1] > 0 && lefty[1] < 45)
             {
                 advanced_regression(1, lefty[1], lefty[1] + 2, lefty[1] + 2, lefty[1] + 4);
                 run(1, 0, lefty[1], parameterB, parameterA);
                 run(0, 0, lefty[1], parameterB, parameterA);
                // SetText(" 状态 :  回到赛道中  正常拉线  ");
                 last_guaiy = lefty[1];
             }

             hd_state = 7;
         }

     }
     if (hd_state == 8)
     {
         find_middleline();
         hd_flag1 = 0;
         hd_num++;
         hd_state = 0;
         flag4 = 0;
         hd_crossback_flag = 1;   //开始出环岛的十字回环保护
         hd3_potlinechange = 0;
        // SetText(" 状态 :  退出左环岛状态机  ");
     }
     if (hd_state != 2 && hd_state != 3 && hd_state != 5)
     {
         last_guaix = 0;
         last_guaiy = 0;
     }
     if (hd_state != 4)
         hdtime4 = 0;
     if (hd_state != 2)
         hdtime2 = 0;
     if (hd_state == 2)
     {
         if (last_tubian_zhong_y == 0)
             last_tubian_zhong_y = tubian_zhong_y;
         else if (last_tubian_zhong_y > tubian_zhong_y)
             last_tubian_zhong_y = tubian_zhong_y;
     }
     else
     {
         last_tubian_zhong_y = 0;
     }
     //SetText("xielv_last " + xielv_last + " xielv_now " + xielv_now + " 环岛状态  " + hd_state + " 左边连续 " + j);
     xielv_last = xielv_now;
   //  SetText(" ************************************* 左环岛状态机 ***************************************  ");
     //SetText(" —————————————————————————————————————————————  ");
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • 339
  • 340
  • 341
  • 342
  • 343
  • 344
  • 345
  • 346
  • 347
  • 348
  • 349
  • 350
  • 351
  • 352
  • 353
  • 354
  • 355
  • 356
  • 357
  • 358
  • 359
  • 360
  • 361
  • 362
  • 363
  • 364
  • 365
  • 366
  • 367
  • 368
  • 369
  • 370
  • 371
  • 372
  • 373
  • 374
  • 375
  • 376
  • 377
  • 378
  • 379
  • 380
  • 381
  • 382
  • 383
  • 384
  • 385
  • 386
  • 387
  • 388
  • 389
  • 390
  • 391
  • 392
  • 393
  • 394
  • 395
  • 396
  • 397
  • 398
  • 399
  • 400
  • 401
  • 402
  • 403
  • 404
  • 405
  • 406
  • 407
  • 408
  • 409
  • 410
  • 411
  • 412
  • 413
  • 414
  • 415
  • 416
  • 417
  • 418
  • 419
  • 420
  • 421
  • 422
  • 423
  • 424
  • 425
  • 426
  • 427
  • 428
  • 429
  • 430
  • 431
  • 432
  • 433
  • 434
  • 435
  • 436
  • 437
  • 438
  • 439
  • 440
  • 441
  • 442
  • 443
  • 444
  • 445
  • 446
  • 447
  • 448
  • 449
  • 450
  • 451
  • 452
  • 453
  • 454
  • 455
  • 456
  • 457
  • 458
  • 459
  • 460
  • 461
  • 462
  • 463
  • 464
  • 465
  • 466
  • 467
  • 468
  • 469
  • 470
  • 471
  • 472
  • 473
  • 474
  • 475
  • 476
  • 477
  • 478
  • 479
  • 480
  • 481
  • 482
  • 483
  • 484
  • 485
  • 486
  • 487
  • 488
  • 489
  • 490
  • 491
  • 492
  • 493
  • 494
  • 495
  • 496
  • 497
  • 498
  • 499
  • 500
  • 501
  • 502
  • 503
  • 504
  • 505
  • 506
  • 507
  • 508
  • 509
  • 510
  • 511
  • 512
  • 513
  • 514
  • 515
  • 516
  • 517
  • 518
  • 519
  • 520
  • 521
  • 522
  • 523
  • 524
  • 525
  • 526
  • 527
  • 528
  • 529
  • 530
  • 531
  • 532
  • 533
  • 534
  • 535
  • 536
  • 537
  • 538
  • 539
  • 540
  • 541
  • 542
  • 543
  • 544
  • 545
  • 546
  • 547
  • 548
  • 549
  • 550
  • 551
  • 552
  • 553
  • 554
  • 555
  • 556
  • 557
  • 558
  • 559
  • 560
  • 561
  • 562
  • 563
  • 564
  • 565
  • 566
  • 567
  • 568
  • 569
  • 570
  • 571
  • 572
  • 573
  • 574
  • 575
  • 576
  • 577
  • 578
  • 579
  • 580
  • 581
  • 582
  • 583
  • 584
  • 585
  • 586
  • 587
  • 588
  • 589
  • 590
  • 591
  • 592
  • 593
  • 594
  • 595
  • 596
  • 597
  • 598
  • 599
  • 600
  • 601
  • 602
  • 603
  • 604
  • 605
  • 606
  • 607
  • 608
  • 609
  • 610
  • 611
  • 612
  • 613
  • 614
  • 615
  • 616
  • 617
  • 618
  • 619
  • 620
  • 621
  • 622
  • 623
  • 624
  • 625
  • 626
  • 627
  • 628
  • 629
  • 630
  • 631
  • 632
  • 633
  • 634
  • 635
  • 636
  • 637
  • 638
  • 639
  • 640
  • 641
  • 642
  • 643
  • 644
  • 645
  • 646
  • 647
  • 648
  • 649
  • 650
  • 651
  • 652
  • 653
  • 654
  • 655
  • 656
  • 657
  • 658
  • 659
  • 660
  • 661
  • 662
  • 663
  • 664
  • 665
  • 666
  • 667
  • 668
  • 669
  • 670
  • 671
  • 672
  • 673
  • 674
  • 675
  • 676
  • 677
  • 678
  • 679
  • 680
  • 681
  • 682
  • 683
  • 684
  • 685
  • 686
  • 687
  • 688
  • 689
  • 690
  • 691
  • 692
  • 693
  • 694
  • 695
  • 696
  • 697
  • 698
  • 699
  • 700
  • 701
  • 702
  • 703
  • 704
  • 705
  • 706
  • 707
  • 708
  • 709
  • 710
  • 711
  • 712
  • 713
  • 714
  • 715
  • 716
  • 717
  • 718
  • 719
  • 720
  • 721
  • 722
  • 723
  • 724
  • 725
  • 726
  • 727
  • 728
  • 729
  • 730
  • 731
  • 732
  • 733
  • 734
  • 735
  • 736
  • 737
  • 738
  • 739
  • 740
  • 741
  • 742
  • 743
  • 744
  • 745
  • 746
  • 747
  • 748
  • 749
  • 750
  • 751
  • 752
  • 753
  • 754
  • 755
  • 756
  • 757
  • 758
  • 759
  • 760
  • 761
  • 762
  • 763
  • 764
  • 765
  • 766
  • 767
  • 768
  • 769
  • 770
  • 771
  • 772
  • 773
  • 774
  • 775
  • 776
  • 777
  • 778
  • 779
  • 780
  • 781
  • 782
  • 783
  • 784
  • 785
  • 786
  • 787
  • 788
  • 789
  • 790
  • 791
  • 792
  • 793
  • 794
  • 795

总结

大二这一年从省赛到国赛现场我也看到很多环岛翻车的情况(暗暗庆幸我的小车正式比赛时没在环岛翻车过)。环岛出来了这么久,各种写法也越来越多,也有加陀螺仪之类的进行辅助,我这里只是提供一个纯图像过环岛的写法,能力有限说的可能不是很详细,讲的不一定完全正确,欢迎大佬在评论区进行指点和改进。有什么问题可以在评论区留言或私信我!

最后的最后如果想看看我这一年智能车的经历和建议可以到第一篇文章最下面浏览一下 智能车学习日记【一】

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/380980
推荐阅读
相关标签
  

闽ICP备14008679号