智能车打工日记(二):关于起跑线与出入车库

96
0
2021年2月3日 09时30分

目录

 

  • 车库元素一览
  • 入车库
    • 20cm摄像头拍下的车库图
    • 起跑线的识别
    • 入车库的拉线
  • 出车库

 

车库元素一览

 

车库元素是今年赛道元素新增的元素。车库赛道元素是在起跑线旁设置的方形区域,它的尺寸如下图所示:

 

在这里插入图片描述

 

车模出发是从车库驶出,在运行一周之后在驶入车库内。比赛时间是从车模驶出车库和返回车库之间的时间差计算。因此计时线圈是放置在车库门口处。赛道上的斑马线和斑马线下的磁铁放置与往届规则相同。

 

车库应用于“基础四轮组”,“直立节能组”,“双车接力组”

 

 

入车库

 

20cm摄像头拍下的车库图

 

在这里插入图片描述

 

起跑线的识别

 

因为时间紧迫,这里采用最简单的入车库(左入)斑马线识别方法:

 

  1. 找到左前边线的拐点
  2. 从下(拐点的y坐标)向上(拐点的y坐标+m),从左(拐点的x坐标)到右(中线位置),进行寻找由黑到白的转变边界像素点。
  3. 找到了第一个边界,以固定的y坐标(转变边界像素点的y坐标+n),从左到右,重新扫线。
  4. 找到第一个由白转黑的像素点和第一个由黑转白的像素点,记录距离(length),作为判断之后斑马线长度的依据
  5. 持续向右扫线,每找到一个疑似斑马线的像素块,就把边界像素的距离与length进行比较,在设定误差之内,判定斑马线。
  6. 记录斑马线数量,与判定起跑线的斑马线数量阈值比较。

 

代码:

 

byte Garage_Judge(byte i)
        {
            byte y = 0, x = 0, count = 0, pixel_cnt = 0, zebraWidth = 0;
            //左边车库
            if (i == 0)
            {
                for (OlRow = LeftLine_1.Agl_Row; OlRow <= LeftLine_1.Agl_Row + 20; OlRow++)
                {
                    for (OlLine = (byte)(LeftLine_1.Agl_Line - 5); OlLine >= 93; OlLine--)
                    {
                        //SetText_1("Zerba Scan :"+ OlRow+" "+ OlLine);
                        if (J_Pixels[OlRow][OlLine] == white && J_Pixels[OlRow][OlLine - 1] == black)
                        {
                            y = (byte)(OlRow + 3);
                            //x = (byte)(OlLine-1);
                            SetText_1("Find Zebra Point: " + y + " " + OlLine);
                            break;
                        }
                    }
                    if (y != 0)
                        break;
                }
                if (y == 0)
                {
                    SetText_1("Lost Zebra Point");
                    return 0;
                }
                for (x = LeftLine_1.Agl_Line; x >= 185 - LeftLine_1.Agl_Line; x--)
                {
                    if (J_Pixels[y][x + 1] == white && J_Pixels[y][x] == black)
                    {
                        //SetText_1("Zebra Scan Start: " + y + " " + x);
                        pixel_cnt = 1;
                    }
                    else if (J_Pixels[y][x + 1] == black && J_Pixels[y][x] == black)
                    {
                        //SetText_1("Zebra Add: " + y + " " + x);
                        pixel_cnt++;
                    }
                    else if (J_Pixels[y][x + 1] == black && J_Pixels[y][x] == white)
                    {
                        if (count == 0 && pixel_cnt >= 3 && pixel_cnt <= 10)
                        {
                            zebraWidth = pixel_cnt;
                            SetText_1("zebraWidth = " + zebraWidth);
                            SetText_1("zebraStart Point: " + x + " " + y);
                            count = 1;
                        }
                        else if (count > 0 && my_fabs(pixel_cnt - zebraWidth) <= 4)
                        {
                            //SetText_1("Zebra End: " + y + " " + (x - 1));
                            count++;
                        }
                        else
                        {
                            // SetText_1("Zebra Error: " + y + " " + (x - 1));
                        }
                    }
                }
                SetText_1("Zebra Count = " + count);
                if (count >= 6)
                {
                    SetText_1("Proved to be Garage");
                    return 1;
                }
                else
                {
                    SetText_1("Not Proved to be Garage");
                    return 0;
                }
            }
            else  //右边车库
            {
                for (OlRow = RightLine_1.Agl_Row; OlRow <= RightLine_1.Agl_Row + 20; OlRow++)
                {
                    for (OlLine = (byte)(RightLine_1.Agl_Line + 5); OlLine <= 93; OlLine++)
                    {
                        //SetText_1("Zerba Scan :"+ OlRow+" "+ OlLine);
                        if (J_Pixels[OlRow][OlLine] == black && J_Pixels[OlRow][OlLine - 1] == white)
                        {
                            y = (byte)(OlRow + 3);
                            //x = (byte)(OlLine-1);
                            SetText_1("Find Zebra Point: " + y + " " + OlLine);
                            break;
                        }
                    }
                    if (y != 0)
                        break;
                }
                if (y == 0)
                {
                    SetText_1("Lost Zebra Point");
                    return 0;
                }
                for (x = RightLine_1.Agl_Line; x <= 185 - RightLine_1.Agl_Line; x++)
                {
                    if (J_Pixels[y][x - 1] == white && J_Pixels[y][x] == black)
                    {
                        //SetText_1("Zebra Scan Start: " + y + " " + x);
                        pixel_cnt = 1;
                    }
                    else if (J_Pixels[y][x - 1] == black && J_Pixels[y][x] == black)
                    {
                        //SetText_1("Zebra Add: " + y + " " + x);
                        pixel_cnt++;
                    }
                    else if (J_Pixels[y][x - 1] == black && J_Pixels[y][x] == white)
                    {
                        if (count == 0 && pixel_cnt >= 3 && pixel_cnt <= 10)
                        {
                            zebraWidth = pixel_cnt;
                            SetText_1("zebraWidth = " + zebraWidth);
                            SetText_1("zebraStart Point: " + x + " " + y);
                            count = 1;
                        }
                        else if (count > 0 && my_fabs(pixel_cnt - zebraWidth) <= 4)
                        {
                            //SetText_1("Zebra End: " + y + " " + (x - 1));
                            count++;
                        }
                        else
                        {
                            // SetText_1("Zebra Error: " + y + " " + (x - 1));
                        }
                    }
                }
                SetText_1("Zebra Count = " + count);
                if (count >= 6)
                {
                    SetText_1("Proved to be Garage");
                    return 1;
                }
                else
                {
                    SetText_1("Not Proved to be Garage");
                    return 0;
                }
            }
        }

 

由于入库图像与环岛入环图像较为相似,入车库判断函数的优先级需要高于入环判断函数。
实践证明,识别成功率很高。

 

入车库的拉线

 

拉线分为4个阶段:

 

1.阶段0:判断为车库

 

在这里插入图片描述

 

2.阶段1:左前拐点消失

 

在这里插入图片描述

 

3.阶段2:低行右边边线消失

 

在这里插入图片描述

 

4.阶段3:右边边线重新出现

 

在这里插入图片描述

 

5.阶段4:左边边线出现

 

在这里插入图片描述

 

出车库

 

目前最稳定的方法为直接控制出库。

发表评论

后才能评论