当前位置:首页 > 特色课程 > 编程技术 > 分治思想在巡线过程中的应用(图文)

分治思想在巡线过程中的应用(图文)

发表日期:2017-02-17 09:39:20文章编辑:亮宁电子浏览次数: 标签:    

 一、预备知识

  分治思想也称分治算法,指在面对一个信息量大、结构复杂的问题时,将这个问题拆分成若干个相对简单、易于处理的小问题,再根据各个小问题的具体特点和情况,采取针对性处理,分而治之,从而更为合理、高效、准确的处理复杂问题的程序编写方法。

二、理论分析

  在巡线过程中遇到路口时,我们总是习惯于用2个以上的灰度传感器(排除最中间和左右两个传感器同时看到的情况)检测到黑线作为条件来判断路口。这种方法在一定的误差条件下的确是合理可行的,然而实际上,机器人在巡线的过程中遇到路口的形式是多种多样的(如图1),我们仅用一些简单的条件来判断所有的路口,必然对准确性和稳定性,和处理效率都可能带来较大的冲击。

  例如在图2所示的路口1中,最靠左边的两个传感器正常情况下是不会看到黑线的,而我们的路口判断条件中还是包含了它们看到黑线的情况,这样不仅出现了无效的语句,还增加了平时巡线过程中误判路口的可能性。同理,在图2所示的路口2中,只有中间和最左边的传感器可以同时看到黑线,相较于我们常用的路口判断,其条件的准确性就值得商榷。

  因此,如果想要进一步提高机器人判断路口的准确率和稳定性,则需要对每一个不同的路口,针对其特点单独设计判断条件。路口判断变得更加准确,也会进一步降低非路口巡线过程中误判的可能性,从而提高整个巡线过程的稳定性。

无标题.png

1.多种多样的路口

 

1.png

2.路口分析

 因此,我们把整个赛道以路口为分界点分成若干个小的赛道,每个小的赛道包含两个部分的内容:非路口巡线(基本巡线)和路口巡线两个部分。其中基本巡线总是一样的,为了方便起见,我们会用一个子程序来编写这部分内容,具体见之后的程序分析。而路口巡线则是根据这部分路口的特点,单独写出判断条件,进行针对性处理。以上即是分治法在巡线过程中的具体体现。

三、程序详解

 如图3所示,我们按路口把要走的路线分成5段。每段从基本巡线开始到处理完路口结束,然后紧接着下一段的基本巡线,从而实现段与段的衔接,完成整个巡线过程。

22.png

3.路线分段示例

 

程序如下:

#include <LNDZ.h>

int ll,l,m,r,rr,n;

void findline()

//子程序定义,findline为程序名,花括号内的语句即是之后调用该子程序时将会运行的内容。

//子程序定义需要写在init()函数之前,程序的内容在定义时不会被运行,仅仅是为之后调用做准备。

//该子程序的内容就是基本巡线代码。

{

                ll=AR(4)<619;//这里的值只是示例,具体值需实测。

                 l=AR(2)<632;

               m=AR(1)<509;

                 r=AR(3)<644;

                rr=AR(5)<684;

                n=ll+l+m+r+rr;

                if(ll==0) motor(-40,40);

                else if(l==0) motor(0,40);

                else if(m==0) motor(40,40);

                else if(r==0) motor(40,0);

                else if(rr==0) motor(40,-40);

}

void init()

{

                B_start();

                motor(40,40);

                delay(150);   //冲出起始的路口

                while(1)

               //while循环语句,小括号内是循环判断条件,判断条件成立返回1,循环继续,条件不成立返回0,循环跳出。

              //当小括号内为非0的常数时,如123100等,则表示条件总是成立的,循环一直进行,除非用break中断循环。

                     {

                             findline();

                          //调用基本巡线子程序,计算机自动运行定义时花括号内的所有内容,用于完成看到路口前的巡线过程。

                             if(n<2)

                           //第一个路口为十字路口,任意4个或5个传感器看到即可认为看到路口。

                                   {

                                       motor(40,40);

                                       beep(150);

                                       break;   //break语句用于结束上一个while循环,不然程序无法转入下一段。

                                   }

                   }//到此为止,第一段的巡线结束。

                    while(2)

                    //括号内的数字只要不是0都可以,这里用2仅仅是为了方便我们判断这是第几个路口的程序。

                          {

                                   findline();   //每一个小段都需要一个基本巡线代码,别忘了。

                                   if(m+r+rr==0||m+rr==0||r+rr==0)//根据路口特点写判断条件

                                   {

                                            motor(40,0);

                                            beep(200);

                                            break;

                                   }

                          }

                     while(3)

                        {

                              findline();

                             if(l+r==0||ll+rr==0)

                                  {

                                          motor(40,0);

                                          beep(200);

                                          break;

                                  }

                        }

                     while(4)

                        {

                               findline();

                               if(m+rr==0)

                                   {

                                         motor(40,0);

                                         beep(200);

                                         break;

                                    }

                       }

                 while(5)

                      {

                              findline();

                              if(n<2)

                                 {

                                      motor(0,0);

                                      break;

                                 }

                     }

}

void repeat()

{

}

注意事项:

1、因为我们自己构造了单独的循环指令,所以只需要顺序执行,程序放在init()里即可。如果我们要放入repeat()函数中,还需要在最后加上while(1);,用于结束repeat()函数循环,不然程序又将重头开始。

2、在子程序中,我们把传感器实时检测路况和调节电机速度合在了一起,作为基本巡线部分。而一旦我们需要根据路况的不同,在各部分采用不同的电机速度时,就要将该子程序拆分为两个子程序:一个检测路况void check(),一个控制电机速度void find1()。如果我们需要不同的电机速度,只需要再定义一个void find2(),把其中的电机速度加以修改,然后根据情况确定调用哪一个。

  例如,在图3所示路线中,第一和第二段都是直线,我们可以把速度加快,从而节约时间;而在后几段路线中,路口、弯道较多,我们需要适当降低速度,保证稳定性。

程序如下:

#include <LNDZ.h>

int ll,l,m,r,rr,n;

void check()  //检测路况的子程序   

{

           ll=AR(4)<619;//这里的值只是示例,具体的值需要自己测。

            l=AR(2)<632;

          m=AR(1)<509;

            r=AR(3)<644;

           rr=AR(5)<684;

           n=ll+l+m+r+rr;

 }

void find1()   //电机速度较快的巡线子程序。

{

           if(ll==0) motor(-40,40);

           else if(l==0) motor(0,40);

           else if(m==0) motor(60,60);

           else if(r==0) motor(40,0);

           else if(rr==0) motor(40,-40);

}

void find2()//电机速度较慢的巡线子程序。

{

          if(ll==0) motor(-40,40);

         else if(l==0) motor(0,40);

         else if(m==0) motor(40,40);

         else if(r==0) motor(40,0);

         else if(rr==0) motor(40,-40);

}

void init()

{

         B_start();

        motor(40,40);

        delay(150);

        while(1)

            {

                 check();

                 find1();//同时调用两个子程序,加起来就组成了非路口的巡线程序。

                 if(n<2)

                     {

                            motor(40,40);

                            beep(150);

                            break;

                      }

           }

       while(2)

           {

                  check();

                  find1();

                  if(m+r+rr==0||m+rr==0||r+rr==0)

                        {

                                motor(40,0);

                                beep(200);

                                break;

                        }

          }

      while(3)

            {

                  check();

                  find2();//进入第三段巡线过程,因为路口多,所以调用电机速度较慢的find2()

                  if(l+r==0||ll+rr==0)

                          {

                                  motor(40,0);

                                  beep(200);

                                  break; 

                          }

          }

     while(4)

           {

                   check();

                   find2();

                   if(m+rr==0)

                          {

                                motor(40,0);

                                beep(200);

                                break;

                          }

          }

       while(5)

             {

                   check();

                   find2(); 

                   if(n<2)

                         {

                                motor(0,0);

                                break;

                         }

             }

}

void repeat()

{

}

 

3、我们把一些功能单独写成一个函数是有优势的。它使程序结构条理更为清晰,反复调用时更为方便,也符合程序结构化、模块化的思想。

4、利用分治思想,巡线程序被分成了一段一段的功能模块,虽然略显重复,但当出现错误、或进行细节调试时,就突显优势了。

 

四、路口判断示例。

  如何根据不同的路口写出合理的路口判断条件是分治法巡线的关键。如果写的条件过于苛刻,则可能容易漏过路口,造成漏判。如果写的条件太宽松,则可能会在非路口巡线过程中把一些弯道误判为路口。因此,在我们写路口判断条件时m+r==0m+l==0两种条件因为在转弯的过程中特别容易满足,造成误判的几率特别大,所以尽可能不要使用。

     这里提供了一些路口判断条件的参考,具体要怎么选择需要我们反复测试而定,直到找到一个最合理的方案。(n=ll+l+m+r+rr; n=0时,是所有传感器都遇到黑线)

weqw.png

 

如没特殊注明,文章均为亮宁电子原创,转载请注明出处
相关新闻

分治思想在巡线过程中的应用(图文)

一、预备知识 分治思想也称分治算法,指在面对一个信息量大、结构复杂的问题时,将这个问题拆分成若干个相对简单、易于处理的小问题,再根据各个小问题的具体特点和情况,采取...

日期:2017-02-17

数学在机器人制作中的应用(2)

数学表达式在机器人程序中的重要应用 数学是个神奇的东西,它可以使问题简单化。学习机器人,如果有较好的数学基础,能帮助你更加清晰地分析问题和处理问题。 下面是对寻线的程序中表达式书写的分析。 void check(...

日期:2016-10-31

系统函数使用说明

程序中必须引用LNDZ.h头文件(#include<LNDZ.h>)。 Ver 1.00 Beep蜂鸣器 beep(蜂鸣时长); 如:beep(200),//鸣叫200毫秒 屏幕输入输出函数 用USB将主板与电脑相连并下载程序后,用菜单tools下的Serial monitor命令,将弹出程...

日期:2016-10-31

亮宁可视化编程应用第二讲

第二讲 函数调用与引用变量 这一讲,我们来用可视化界面编写一些实用的程序。 例一,我想让机器人蜂鸣器连续发声0.3秒,设置步骤如下: 第一步设置变量名为t,并赋初始值为300毫秒; 第二步设置蜂鸣器开启; ...

日期:2016-10-31

亮宁可视化编程应用第三讲

第三讲 设备说明与应用 大部分接设备,与单片机的联结方式不止一种,有些设备,一次性也可能不止接入一个,所以通常要用不同的标识来区分同一种设备,同时指明接入的方式。例如: ser1.attach(9); ser2.attach(...

日期:2016-10-31

亮宁可视化编程应用第四讲

第四讲 分支结构与注释语句 为了讲解分支结构,先我们来做些准备工作。 先在四轮小车结构前方添加红外接收传感器(上有五个黑色红外接收二极管的板子)。接线方法是,VCC(白线)、GND(黑线)将其与主板相连,提供传感器电源...

日期:2016-10-31