当前位置:   article > 正文

智能车学习日记【一】——让小车跑正方形赛道(摄像头图像处理赛道)_智能小车舵机的作用

智能小车舵机的作用

目录

开篇

	   博主最近开始学智能车,开始时遇到了很多困难。我觉得这些问题应该也
是每一个智能车人开始都可能会遇到的,写下来分享一下,也顺便巩固一下自
身所学。如果有错误或可以改进的地方还希望多多指出交流~。
  • 1
  • 2
  • 3

这是博主的第一篇文章,如果觉得有帮助还希望点赞收藏支持一下~

舵机

      首先要说说舵机,舵机是让小车车跑好的一大重要因素,网上有很多有关不
      同种类舵机的详细原理和使用。这里我就简单说说
  • 1
  • 2
  1. 舵机的作用是控制智能车轮子转向。通过输入不同的脉冲信号来使舵机有不同大小的打角,比如你输入的pwm等于750时舵机打角位于中间,则小车直走,大于750时舵机打角偏向右边,则小车左转。
  2. 通过处理图像中线位置来给舵机输入对应脉冲信号来控制打角。先对你摄像头拍到的图像进行图像处理(摄像头原理在这不过多解释,后面会大致讲一下简单的图像处理)。比如你的屏幕中线的x坐标为50,而你图像处理后得到的中线x坐标为70,说明你的车偏右了(这里要注意我的坐标系零点是屏幕右下角),要让车左走回正,这时你就要输入对应的脉冲信号,让舵机控制车子向左转。
  3. 在写对舵机的控制前请一定要让舵机摆正!先写固定的脉冲信号让舵机打一个固定角度,然后轻推小车,小车能沿直线走,就说明摆正了,再进行之后的调试。

赛道图像处理

怎么处理赛道应该是难点之一了,这里博主只介绍直道和90°弯道,其他的可能有后续更新吧。

图像处理

 智能车(摄像头)的图像处理主要就是识别出左右边线(一般边线是黑线,外边
 是蓝布,中间赛道是白色),然后拟合出中线,让车子沿着中线跑。
  • 1
  • 2

这里我推荐新手使用左右寻线法来拟合中线,至于为什么不用八邻域法我只能说,新手阶段不需要贪那运算速度,左右寻线法写起来容易理解,能跑完赛道最重要,优化算法是之后的事情了。

代码

在这里插入图片描述
middle是存放中线x坐标的数组
left是存放左边线x坐标的数组
right是存放右边线x坐标的数组
Pixels是像素坐标数组,由摄像头读出并处理生成
pixels为1是白,为0是黑,屏幕x坐标是从0到185
这里放一个我判断左边界的部分代码,首先第0行是从中间开始往左右扫线,比如我这个第0行应该从x=93开始左右扫线 (那我这里为什么是从middle[y-1]开始呢,因为我这是从第1行开始的,我第一行中间起始点是用第0行的中线,第二行中间起始点是用第一行的中线坐标,以此类推) 。以找左边线为例子,右边线类似。从中间起始点开始向左边扫描,如果扫描到白黑黑的部分,则认定为找到左边线,将左边线记录下来。右边线也是找到白黑黑的组合,记录下左右边线。中线就是左右边线之和除2
至于我为什么还有个x==184的条件,其实这是用在弯道处,在这里插入图片描述
这是我将弯道图片上传到上位机后得到的图像,左边是原图,右边是图像处理以后的。可以发现有时左边一直到屏幕边界都还是白色,所以我让左扫描到最左边时,将x=184作为了左边界(其实还有更好的处理的方式,但这里只是介绍给新手们最基本的)。右边同理有个x == 0的边界判断。

小贴士

  1. 第一帧图像的第0行中间起始点可以选屏幕中间点,因为发车都是直道发车,一般不存在第0行中间像素点为黑的情况。之后每一行中间起始点都是前一行的中点(这样可以防止拐弯时中线丢失)。此后第二帧开始,第0行的中间起始点就选择上一帧的第2行的中点(选第几行按照自己情况而定),这样做其实也是在防止拐弯时中线丢失(中线丢失是什么情况还是希望大家可以自己去尝试一下,有时会发现拐弯到一半车子突然直行,只有自己经历过才能更好理解这些方法)
  2. 做好赛道类型判断。通过你处理后得到的中线趋势来判断现在是直道还是弯道
// 赛道类型判断
    int i;
    float sum1 = 0;
    float sum2 = 0;

    for(i=0 ; i<20 ; i++)
    {
        sum2 += (94-middle[i])*(94-middle[i]);
        sum1 += (94-middle[i]);
    }

    if(sqrt(sum2)/20 > 3.2 || sum1/20 > 18.5 || sum1 < -18.5)
    {
        choose = 1;                     //弯道
    }else
    {
        choose = 0;                     //直道
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

我这里通过图像中线和屏幕中线的方差和平均值来判断赛道类型,这么做有什么好处呢?有时你会发现,走直道时车一直在左右摇摆,就有可能你没有分类赛道,直道和弯道用的同一个PID算法,这会导致直道有点歪时小车想打角来走直线,却用的是弯道的打角,导致打角太大了,就会一直左右摇摆。以后写什么小弯道啊,环岛的也是要判断的。
下面是我直道的PD算法,直道的PD给的就很小,因为就是微调,弯道的PD要给大一点(要问为什么不写i,因为我之前忘记写了…)

float kp1 = 0.2;
float kd1 = 0.4;
void zhidao()
{

    float cha=0;
    cha = 94 - middle[17];                //与中线差值
    duty = (int)(780 - kp1*cha - kd1*(cha - last));
    if(duty>840)
        {
            duty = 840;
        }
        if(duty<700)
        {
            duty = 700;
        }
    //    systick_delay_ms(STM0,20);
        pwm_duty(ATOM0_CH6_P02_6,duty);
        pwm_duty(ATOM1_CH4_P22_3,duty_car_z);
        pwm_duty(ATOM1_CH0_P22_1,0);
        pwm_duty(ATOM1_CH6_P23_1,0);
        pwm_duty(ATOM2_CH5_P33_13,duty_car_z);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

图像处理控制舵机打角

其实控制舵机打角也是上边的代码
在这里插入图片描述
上位机直道图

    float cha=0;
    cha = 94 - middle[17];                //与中线差值
    duty = (int)(780 - kp1*cha - kd1*(cha - last));
    ...
    ...
    pwm_duty(ATOM0_CH6_P02_6,duty);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

这里的duty就是我输出给舵机的脉冲信号,来控制小车在直道时的打角

cha是屏幕中线和第17行中线的差值,用于下面的计算
last是上一次的cha值
这个第17行是根据你摄像头高度来选择的,有很多种方式取这个值
  • 1
  • 2
  • 3

最后亿点

小车最开始调试时,可以给直道和弯道不同的PWM,弯道可以慢速点过,保证平滑,
直道再加速。这里面有很多门道的,博主也在慢慢摸索。
新手想要车能跑正方形赛道,最难的应该是图像处理部分了,这部分我其实主要在
讲一些问题,原理性的可能不太详细,因为这是第一次写博客,很多想法很难表达
出来,大家可以先收藏,然后看看网上左右寻线详细原理,等到写上车后发现问题,
再来看应该会更多体会与帮助。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

我也是刚刚开始的智能车小白,希望大家能一起互帮互助,一起进步!如果觉得有帮助,还希望点赞收藏多多支持一下~

最后有一句话分享给大家和我自己:如果你的车没有撞过,就说明速度还不够快!加油智能车人!

————————————————————————————————

一年后的总结

22年10月29号更新的一点小鼓励:
如果你是从这篇文章开始看的相信你也是刚刚接触智能车(如果是大佬回顾新手村就当我没说过这句话)。回顾我这一年的智能车经历,我觉得智能车竞赛和别的竞赛最大的区别在于周期更长,细节更多。给大家分享一下我的经历和感受
有一张图很生动
在这里插入图片描述
智能车最重要的是学会解决问题的能力,剩下就坚持和经验加上好心态了。我是大一的暑假第一次接触到智能车,也就是第一次发这篇文章的时候,到大二的8月底,刚刚好一年的时间,我拿到了浙江省赛第二名和国赛第六名。很多人觉得这个比赛靠的是传承,这个我并不否认,如果有完美的传承对于这个比赛确实优势巨大,但真正能把一套好的模板传下去的学校真的很少。学长传给我的更多是经验,这个问题大概是什么原因怎么解决,比赛时要怎么安排等等。虽然代码是留了下来,但实际上学弟都懒得看学长的代码。我们的所有控制、图像代码都是自己一点点敲出来的,很多问题都要靠自己慢慢去研究解决才能积累经验。
很多时候吃饭前车子跑的飞快,饭后车子就寄了等情况层出不穷。
Alt

甚至卓老师可能还会临时变一下卦
在这里插入图片描述
在这里插入图片描述

还有就是态度端正,心态要好。每个人都会遇到很多玄学问题,不能指望别人能给你所有的完美的解决方案,更多时候需要自己去研究。很喜欢我队友在准备国赛期间说的话:”我每次睡觉前都把视频看个几遍(赛前b站有很多快车发视频和省赛的冠军车视频)“。提速阶段的优化就是看到别人的车跑的很好,再回过来思考我要怎么往他的方向去靠。
在这里插入图片描述
本人并不太聪慧,前期面对各种玄学问题没办法直接定位到具体问题,只能是笨鸟先飞,在里面倾注了大量的时间去挖掘其中的原因,智能车这一年中几乎没放过假,通宵研究什么的更是家常便饭,我也记不清有多少次在半夜里调不出好的结果就开始怀疑自己,好在时间的大量堆叠加上队友和学长的鼓励与帮助下,每个问题最终也能研究明白。我认为这段长期且痛苦枯燥的时光也为后面正式比赛时的稳健打好了基础,比赛时虽然运气很差都抽到了最差的上场次序,但车在比赛时出现的哪怕是抖动一下,哪里地方可以快一点或是不能再加速了只需看车一遍就能明白问题所在,并能快速构思出新的合适的参数方案来。
在这里插入图片描述

省赛的初赛我抽到了第四个(一共51队)出场,基础四轮组的友友肯定知道越早出场的劣势越大,线下的很多因素都是未知的,前面出场的就是给后面出场的擦干净赛道,试试看赛道哪里的反光比较严重,而且决赛出场顺序是根据初赛排名的倒序出场,要是初赛慢了相当于第二天决赛又是上去给别人试一个新赛道。当时心里多少有点难过的,但难过归难过,还是调整好心态规划好比赛时遇到不同状况该怎么解决。正式上场时也意料之内赛道很多灰尘,好在自己的低速参数非常稳定,上场后花了1分多钟把赛道都擦一遍后也是稳定完赛,稳住了自己的心态。最终也是侥幸初赛拿下了第五名,第二天决赛第二名。

这里放一下我省赛初赛第一次完赛的保命参数视频(点赞投币祝你国一

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