原理讲解

因为我们选择的是电磁车,没有摄像头,所以我选择了线性CCD作为感知斑马线的元件,我把他挂在了电磁车的前瞻上,如图:

为什么要把它挂在前瞻上呢?让我们先来看看的过程。

小车上的CCD可以在距离斑马线一定距离的地方就可以判定前方就是斑马线,那么之后,我通过后轮差速和前轮打角就可以实现稳定入库,那么在这个过程中我们需要保证些什么东西呢?

那就是小车知道自己应该拐到什么位置停下来。因为我们这个是一个开环入库方案,所以需要一个反馈量来确定小车稳定入库,这个反馈量是什么呢?请看我画的那个黄色的拐弯路线,没错,我们可以用陀螺仪来记录下小车在入库过程中转过的角度,当角度大于一定数值的时候,也就是说小车的车身已经在车库里面的时候,我们就可以让小车进入停车状态了。

好了,让我们回来原来的那个问题,为什么我要把CCD挂在前瞻上呢?答案很明显了,因为当我的CCD看到斑马线的时候其实小车距离斑马线其实还是有一定位置的,那么如果把CCD放在车头上的话,车子打角的时机就太早了,所以就需要把CCD前移一些放在前瞻上。

我们先来看一下斑马线的CCD图像:

所以,入库实际上就是需要我们能准确识别上面的那个图像,接下来我就来介绍我的出入库方案。

出库方案

我采用了编码器积分+丢线设置的方案。

首先设置一个较低的车速,保持小车的稳定性。然后当我发车的时候首先进行编码器的积分,当编码器的积分累加值大于特定数值的时候设置左右丢线然后进入正常巡迹(因为发车方向是没有规定的,因此我通过按键设置左转或者右转的方向)

因为编码器积分大于特定数值说明小车已经前进了特定距离,小车前轮已经出库,然后可以直接往某个方向设置丢线(左出车库左丢线,右出车库右丢线)。接着小车就会按照正常的流程完成巡迹了。

在5ms中断里面判断编码器积分的数据,大于特定数值之后才能算是前轮出库,这个特定数值在自家实验室测试得出,写入片内flash以供比赛直接调用或者比赛时做微调即可。

车子出库的状态直接决定了他接下来的稳定性,因此我牺牲了一些出库的速度保证了车子的稳定性,而且经过实测,该编码器积分+丢线设置能很好的保证小车的出库姿态,记得放车的时候把车往旁边放一点,假如左边出库就把车子放在车库右边一点的地方。

入库方案

线性CCD采集的数据放到ccd_buf[128]中,是128个0,1信号,黑色(斑马线)对应1,白色(赛道)对应0,所以我们的思路就是识别黑白色块的跳变沿,连续判断4个数据来判断跳变沿从而最大程度上减小误差。

ccd识别部分参考了这位大佬的开源程序:
十四届智能车小白四轮组


CCD_Collect(ccd_buf);//ccd_buf里面是ccd数据,是128个0,1信号,0代表白色,1代表黑色
for (uint8_t i = 0; i <= 123; i++)
{
  if ((ccd_buf[i] > start_line_thres) && (ccd_buf[i + 1 < 128 ? (i + 1) : 127] > start_line_thres) && (ccd_buf[i + 2 < 128 ? (i + 2) : 127] < start_line_thres) && (ccd_buf[i + 3 < 128 ? (i + 3) : 127] < start_line_thres) && (ccd_buf[i + 4 < 128 ? (i + 4) : 127] < start_line_thres))
  {
    jLeft = i + 2;    //黑块左侧位置
    iTmp = jLeft;
    for (; iTmp <= 123; iTmp++)
    {
      if ((ccd_buf[iTmp] < start_line_thres) && (ccd_buf[iTmp + 1] < start_line_thres) && (ccd_buf[iTmp + 2] > start_line_thres) && (ccd_buf[iTmp + 3] > start_line_thres) && (ccd_buf[iTmp + 4] > start_line_thres))
      {
        jRight = iTmp + 1;   //黑块右侧问题
        break;
      }
    }
    if (jRight - jLeft > 2)  //黑块宽度大于2才判定为有效的起跑线
    {
      cntColorChange++;
    }
    if(cntColorChange >= 5)//有5个黑块才判定为起跑线
    {
      cntColorChange = 0;
      getinto_garage_flag = 1;
      break;
    }
  }
}

当识别到车库之后就进行入库动作,方案就是左出库,左入库,右出库,右入库,以左入库为例,那么左轮速度设为0,右轮给一个特定的速度漂移入库。这个过程中用陀螺仪记录车身漂移的角度,角度大于特定数值的时候说明车身完全在车库里面了,然后就进行停车,既两轮速度均设置为0,最后小车就会稳稳的停在车库中。

入库主要需调整的参数有getinto_speed(漂移时的单轮速度),gyro_garage(入库漂移角度,决定小车是否能停进车库或者漂移过头冲出车库)。还有光照对于CCD二值化赛道的影响比较大,所以CCD的阈值需要在比赛场地进行调整,我这里的参数是start_line_thres。CCD的阈值(start_line_thres)要在使用时进行调整。