当前位置:首页 > 名师导学 > 专家点拨 > 分治思想在巡线过程中的应用(图文)

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

发表日期: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

 

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

浅析心理暗示在青少年行为教育中的作用(图文)

在与许许多多学生家长交流的过程中发现,不少家长都觉得孩子难管难教,特别是处于青春期的孩子,家长们更是感到头痛。所以,本文作者在这里发表个人看法,讨论一下心理暗示在教育孩...

日期:2019-04-24

不忘初心,方得始终

不忘初心,方得始终——对知识应用能力的执着追求 长沙市一中戴胜军 从事教师这行三十多年,我了解到许多教育教学中长期存在的不足和缺陷,也一直尝试用一己之力改变...

日期:2018-06-30

机器人教育中的责任心培养

本文已发表在《创意与发明》2016年第7期上在近年从事机器人教育教学工作中,我发现当代中小学生普遍存在责任心的缺失问题,引发了我对当前教育的担忧和诸多思考。一、缺失责任...

日期:2018-06-13

论中小学机器人教练员应该具备的基本素质

【摘 要】本文重在提示中小学机器人教练员建立必要的自信心和自我重塑,提出机器人教练员一些必须具备的基本素质,提醒可能成为机器人教练员的老师和目前处于探索阶段的机器...

日期:2018-03-19

亮宁机器人特有的符号系统(图文)

使用亮宁机器人的师生,可能注意到了这样一个特色,即亮宁机器人有自己特有的一套符号系统。如果还没有发现这一特色的师生,那我们就随本文来理解为什么我们要有这套特有的符号系...

日期:2018-01-19

亮宁可视化编程平台V2.2第6讲(图文)

第6讲 循环程序 我们先来看看顺序结构的程序实例。我们先用可视化系统设置如下: 上述设置的程序运行结果是八个LED灯同时被点亮。 我们看不出八个灯的点亮语句的顺序...

日期:2017-10-09