1 整体设计
根据功能的不同,小车分为六部分:摄像头图像采集模块、电源模块、电机驱动模块、测速模块、舵机转向模块、辅助调试模块。图1是小车系统硬件模块框图。
图1 系统硬件模块图
(1) 摄像头图像采集模块
采用CMOS摄像头作为识别路径的传感器。此模块的主要作用是识别黑色引导线,工作原理为:摄像头的信号通过LM1881视频分离芯片向DG128产生行信号中断和场信号中断,以控制图像A/D值的采集;然后通过边沿提取算法提取出每行黑线的位置,通过提取连续段重新购建一帧图像的算法对整个图像进行处理。
(2) 驱动模块
Freescale公司生产的MC33886芯片是一款性能优良的直流电压驱动芯片。通过输入不同占空比的方波信号,可以在MC33886的输出端得到不同的电压,进而驱动电机,实现调速。
(3) 测速模块
采用光电耦合管和自制的码盘作为测速的传感器。光耦合管的输出信号经过555定时器组成的斯密特触发器整形得到一定频率的矩形波信号,再经过DG128的输入捕捉功能提取出小车的速度值。
(4) 舵机转向模块
为了保证小车在转弯过程中既能快速响应,又防止速度过快冲出跑道,利用汽车转向机构原理,把舵机的位置进行了提升。这样可以增大力矩,使小车快速响应,按照轨迹进行快速转弯。
2 图像采集及处理
2.1 图像采集
常用的摄像头视频输出信号是电视机的PAL制式。它的工作原理与电视机的工作原理相似:在一定分辨率下,每秒扫描25帧图像,每帧图像含有625行信息;分为奇、偶场,隔行扫描;总共每秒50场信号,每场有312.5行信息;从奇数行开始扫描,即依次扫描第1、3、5、7、9……当扫描完奇数场后,再开始扫描偶数场,构成一帧图像。
对图像的采集是根据摄像头的行信号和场信号对图像模拟量的采集。如图2所示,输出信号包括行同步信号、场同步信号、图像信号以及各种消隐信号。行同步信号代表一行的图像数据扫描开始,场同步信号代表一帧的图像数据扫描开始。要完成图像的正确采集,必须严格遵守时序的要求:当捕捉到一行信号时,开始对该行各点的模拟量进行采集,当下一行信号发生时表明该行采集完毕,需要对下一行的模拟量进行采集。
由于MC9S12DG128片内A/D采样频率的影响,每一行采集的点数受到了限制,在系统时钟倍频到24 MHz,A/D每次采集时间为2.3 μs的情况下,每一行图像的采集能达到34个点。这虽然远远小于摄像头本身的分辨频率,但在不使用2.8 mm广角镜头的前提下,仍能分辨出黑线,因此我们将数组列数设为34,同时每间隔6个摄像头行信号采集一次,一共有312个行信号,则一共可采集312/6=52行。去掉首尾干扰加大的行,选择采集46行,因此数组的行数为46。最终,设定的数组大小为:data_save1[46][34],还原效果如图3所示。
图2 输出信号波形组成
图3 34列46行的二维数组还原效果
2.2 图像采集的处理方法
这里的黑色引导线以白色为衬底,因黑线和白色底板存在很多大灰度比,在图像信号上会形成相应高低不同的电压值。当检测到黑线时,图像信号中将形成一个“凹”形槽,图4中 凹槽处即是黑线在一行数据中的相对位置(26)。
图4 数组一行数据还原波形(一帧图像的某一行)
对图像每行数据的处理将得到每行图像中黑线的相对位置,即下面的行数据处理;而对每行图像中黑线的位置的综合分析将再现黑线的形状,即下面的帧数据处理。本设计将采集的模拟量数据存放在一个二维数组中,当完成对一行数据的采集后,就可以对该行的数据进行处理,即提取黑线的算法。在提取黑线上采用边沿提取法。该算法具有对黑线反应灵敏、准确度高、抗干扰能力强等特点。
图5表示的是光线比较好的情况下,A/D采集一帧中一行图像的数值结果,即二维数组中的某一行数据。小圆点的纵坐标表示A/D采集值,横坐标表示采集点在二维数组该行中的相对位置。
图5 黑线位置提取
边沿提取法,即通过程序检测到上述图形的上升沿和下降沿,然后通过上升沿和下降沿的位置求出黑线的位置。边沿提取算法流程:
① 通过i控制循环语句不断检测上升沿或下降沿。当第i个点的A/D值与第i+2个点的A/D值之差大于设定的阈值时,表明出现了下降沿,这时读取i的值。
② 一旦出现了下降沿,就开始不断地判断第i+2个点的A/D值与第i个点的A/D值之差是否大于设定的阈值。如果大于则表明检测到了上升沿,这时也读取i的值。通过2次i的值,便能够求得黑线对应的点是第几个点,进而求出黑线与小车轴线的相对位置。其提取流程如图6所示。
图6 边沿提取算法流程
通过判断下降沿位置和上升沿位置,来计算黑线的相对位置,并通过判断上升沿之后的数据是否满足相差不大于阈值来减小误差,以精确计算黑线的相对位置。
在光线比较好的情况下,简单地运用上述算法即可求得比较准确的相对位置,此时也不需要对阈值进行动态调整。当受到太阳光或其他比较强烈的光线影响时,就需要设置动态阈值。图7为光线不理想时图像的一种情况。
图7 光线不理想时的图像示意图
光线不好的情况下,采集的图像通常会出现图7中凸起的情形,这时,黑线提取算法的出错几率会大大增加。为了避免这种情况,可以根据图像的变化趋势将阈值附加上一个修正值。如图7,在进行下降沿检测时,可以在预先设定的阈值上减去一个数值,以克服凸起处的变形造成实际阈值的变小;上升沿检测时,可以在预先设定的阈值上加上一个数值,克服图像呈上升趋势带来的阈值变大。修正值的计算可以大致采用下式:
2.3 图像帧数据的处理
经过黑线提取算法得到每一行黑线的位置,并存在一个一维数组里,通过这个数组就可以粗糙地控制小车转向。但摄像头可能会将黑线以外的其他物体错误识别成黑线,直接使用数组不能满足稳定性的要求,还需要对数组的数据进行进一步的处理,把干扰图像滤除,即这里所说的帧数据的处理。
在帧数据处理上采用提取连续段的方法,将图像中错误的数据去除掉。图8是把干扰图像误当成黑线的情况,虚线代表实际的黑线位置。
图8 帧处理算法
连续段提取算法的流程大致为:
① 通过程序将图像中连续的段提取出来,提取的方法即通过i控制循环语句不断检验(Yi+1-Yi)的值是否大于设定的阈值。如果小于则表明第i个点和前面各点是连续的,否则和前面各点不连续。如图能够提取出3个连续的段,即连续段1、连续段2、连续段3。
② 判断连续段的可靠性,判断的依据是连续段中的点越多表明该连续段越可靠,如图8,显然连续段1和连续段3比连续段2可靠。将可靠性好的段作为可用段,可靠性差的段作为不可用段。
③ 排除不可用段,将可用段连接起来形成一个大段。最后采用插补法,将不可用段归算到这个大段中。
用该方法得到的归算后的“大段”给下面循迹算法提供了依据。图像处理的稳定性,是小车循迹稳定性的前提条件。实验表明,该算法能够很好地满足稳定性的要求。
3 小车循迹算法
由于选用的摄像头的照射宽度比较小,使得算法上很难对赛道进行大面积的分析,因此循迹上,算法应该以适应性强为主。在舵机转向上采用3个变量来控制舵机的值:part_1、part_2、part_3。part_1对应图像的斜率,它是控制转向的主要变量;part_2对应小车相对于黑线的位置,是控制转向的辅助变量,它的目的是为了防止小车偏离引导线;part_3对应于转向的超前校正,它由图像前端的斜率求得。
part_1、part_2、part_3的计算子函数程序为:
void photo_access(void){
unsigned char i;
long item_1=0;
int item_2=0,item_3=0,item_4=0;
static unsigned int out_degree_temp=0xffff;
/*line_data_refined[i]内存储的数据为一帧图像数据处理后的黑线在每一行中的相对位置,“i”代表采集的第i行,总共有46行。
bottom为一帧图像归算后,整个连续段的最后一行;top为一帧图像归算后,整个连续段的首行*/
/*part_1求解*/
for(i=0,slope_photo=0;i<=bottom-top;i++) {
item_1+=i*line_data_refined[bottom-i];
item_2+=i;
item_3+=line_data_refined[bottom-i];
item_4+=i*i;
}
slope_photo_1=100*(item_1-(item_2*(long)item_3)/(bottom-top+1))/(item_4-(item_2*(long)item_2)/(bottom-top+1));
part_1=slope_photo*gain_slope; //gain_slope为常系数/*part_2求解*/
for(i=bottom-4,sum=0;i<=bottom;i++)
sum+=line_data_refined[i];
temp=sum/5-17;
relative_near=temp-slope_photo_1*(65-bottom)/10;
if(relative_near>36) relative_near=36;
if(relative_near<-36) relative_near=-36;
part_2=(int)relative_near*gain_out; //gain_out为常系数
/*part_3求解*/
item_1=0;
item_2=0;
item_3=0;
item_4=0;
for(i=0;i<=9;i++) {
item_1+=i*line_data_refined[top+i];
item_2+=i;
item_3+=line_data_refined[top+i];
item_4+=i*i;
}
slope_photo_2=-100*(item_1-(item_2*(long)item_3)/10)/(item_4-(item_2*(long)item_2)/10);
if(speed_now>20)temp=speed_now-20;
else temp=0;
//speed_now为小车目前速度
part_3=((slope_photo_2-slope_photo_1)*temp/10)*
gain_advance/25;
//gain_advance为设置的参数
}
3.1 part_1的求取
通过求黑线对于小车的平均相对位置的方法来控制转向,但这种方法具有灵敏度不高、适应性不强、小车侧滑时容易出错等缺点;最终采用了通过最小二乘法求图像的斜率,再由斜率求part_1值的方法。part_1即控制小车转向的主要变量。
如图9所示,通过最小二乘法求斜率,运用公式如下:
图9 最小二乘法求斜率
3.2 part_2的求取
因为图像的最近端和小车的前轮轴线之间仍有不可忽略的距离,因此摄像头最近一行的数据不能反映小车相对于黑线的距离。这里仍然通过最小二乘法的方法将图像延长到小车前轮轴线上(如图9),这样就可以将最近一行的相对位置distance_photo归算为distance_near。distance_near的值虽然和实际值仍有些误差,但经过实验数据分析,distance_near的误差在影响小车稳定性上程度比较小,比重也很小;它的最大优点就是能够反映小车相对于黑线的实际位置。
在求出distance_near后,就可以进一步求出part_2的值:
part_2=k2×distance_near(k2为常数)
3.3 part_3的求取
因为舵机的滞后性对小车的性能有很大影响,速度越高,舵机滞后性带来的负面影响就越大,在进入弯道就会出现侧滑出跑道的情况。为了避免这种情况的发生和提高小车运行速度,需要对舵机的联动机构及前轮机械结构进行调整,或者采用编程的方法使小车提前转向。part_3的引入即是第2种方法。part_3作为一个附加的校正值加在舵机上,它的大小与速度有关系,同时又与图像前端的斜率slope_front(图9)有关。关于part_3的计算如下:
其中speed是小车的运行速度。
4 结论
本文以追求稳定性为前提,以提高小车行驶速度为目标,提出了一种抗干扰能力强的图像处理算法和一种通用性强、适应性强的小车循迹算法。