2018-4-25 10:44:55 [显示全部楼层]
7817浏览
查看: 7817|回复: 3

[讨论] 巡线问题小议

[复制链接]
本帖最后由 微笑的rockets 于 2018-5-31 11:18 编辑

今天在群里有老师询问怎样写巡线路口的问题,试着简单的回答了一下。
然后突然想到,可能真的有很多人其实对这个还是有疑问,于是斗胆将自己不成熟的想法发布上来,抛砖引玉,希望大家能批评指正。
巡线问题小议图1
问题是由这张图引起的。
如果让机器人知道在第二个路口转弯。
我觉得想要解决这样的问题,首先要分析地图。
于是我把这个地图进行了简化,也就是二值化。把黑色的定义为1,把白色的定义为0,于是有了下图。
巡线问题小议图2
那我们就可以进行分析了
想象一下,你现在有一个读数据的设备,读取的数据按队列进入,


读入到010表示在直线上


巡线问题小议图3
读入111表示到了横线上

巡线问题小议图4
读入010表示又到了直线上

巡线问题小议图5
且前面读到111表示过路口,计数加1

直到读到又一个010且前面读到111表示又过了一个路口,计数加1,发现计数现在为2,转弯

于是这个问题应该这样就解决了。

那么扩展开来说,是不是当我们读到了
类似于
010
111
010
这样的一个数组就表示是一个路口呢?
于是,只要和这个数组进行比对,凡是和这个相同的就是路口


如果,我们给定更多的特征数组,进行比对,是不是就可以有更多的方法了。
比如如果读到
000
000
000
那接下来做什么动作?
比如读到
000
100
100
做什么动作?
----------------------------------------------------------------------------------------------------------------------------
在巡线的过程中还有一个问题,也会经常碰到,那就是到底多少个传感器才够?
我觉得回答这个问题,其实还蛮困难的。
我来试着回答一下吧。
其实根据上面的那个图,我们可以认为最简单的巡线,一个巡线传感器就可以了。只要确保传感器时刻读取到的线是1即可。
非1的时候,我们通过各种方法找到1即可。但在实际操作的过程中个,会发现非常的困难,你非1的时候,到底是左转还是右转?都是非常纠结的问题。
那我们引入另外一个传感器,就变成了两个。这里就出现了4种情况。
11   线上
00   线外
10   偏右
01   偏左
那对应的情况正如上表所列,只要对应给出相应的处理方法就可以了。所以理论上两个也能解决问题,是吗?
但是地图上突然出现了十字交叉路口,路口和路上的情况是一致的,不是吗?
显然两个传感器无法很好的解决这个问题。为什么是无法很好的解决呢?
因为其实如果想象一下,你扫动读取,就可以获得一个区间的数据,但是就需要很多数据的处理,会形成更复杂的问题。
于是我们可以再增加一个传感器。
于是我们获得了一个这样的数据情况表。
000    线外
001    更偏左
010    中线
011    偏左
100    更偏右
101    夹角
110    偏右
111    路口
因此有了这张真值表,我们也清楚的了解到我们车的状况。
所以我们是不是可以大致认为巡线3个就够了呢?我的理解,大致上差不多了。
但是,这里出现了但是,为了能更好的巡线,我们总是倾向用更多的传感器,这是为什么呢?
这里就要说到分辨率的问题,我们将地图抽象成了一张由0和1组成的表格,我们按尺寸来划分,就会发现,当我把一个个的像素编程数字,那点和点之间的距离就非常的关键。
这和我们机器人所安装传感器的位置和距离息息相关。如果我的线只有1cm,我传感器的安装距离就要尽可能的在这个范围内。超过了这个范围,可能得到的数据表就完全和他的行为不一致了。
越多的传感器电位,可以帮助机器更好的进行控制,比如在驱动电机的时候可以引入PID的控制,让运动更准更稳。

前几天和同事在聊天,不知道为什么讨论到了巡线的一些问题,同事指出巡线没有那么的理想化,我的想法是,我们先在理想条件下理清思路,然后再一点点加上限制条件,或者增加辅助功能就可以更好的解决问题。
类似于机器人的外形,传感器的位置,转弯半径等都需要在后面的程序中考虑到。

另外在程序中,我们经常会用到if……else……等方法或者switch等语句来实现以上这种操作。最近看到翁凯老师的一些观点,觉得用在这里特别的合适。
翁凯老师认为,在高级语言端应该将数据或者状态和逻辑进行一个分离。用表的方式来重构之前if……else……,switch……case……等代码。

而我觉得在巡线小车的场景里,这样的操作给整个程序编写带来的好处应该说是非常有价值的。
如果我们将这个逻辑代码和数据分离后,我们的整个的操作,其实就是为不同的状态找到处理的数据。

这么说突然觉得是查找表格的节奏。感觉好像简单了很多的样子。

在人工智能的领域,通过人工智能来进行状态的判断,建立不同的数据处理模式,自动的建立数据和状态的联系,感觉好像找到了新的解法。

以上做了一些关于逻辑层面,数据层面的分析。后期会考虑将实际的搭建和电机控制等思考逐步补充进来。

随手写了一些不成熟的想法,希望能给大家带来一些不同的思路。
如果有任何问题,也欢迎大家批评。

感谢@Angelo 提供了他写的巡线代码。我们后面将以他的代码为基础进一步的改进。
[mw_shl_code=cpp,true]float Kp=0,Ki=0,Kd=0;
float error=0, P=0, I=0, D=0, PID_value=0;
float previous_error=0, previous_I=0;
int sensor[5]={0, 0, 0, 0, 0};
int initial_motor_speed=100;

void read_sensor_values(void);
void calculate_pid(void);
void motor_control(void);

void setup()
{
pinMode(9,OUTPUT); //PWM Pin 1
pinMode(10,OUTPUT); //PWM Pin 2
pinMode(4,OUTPUT); //Left Motor Pin 1
pinMode(5,OUTPUT); //Left Motor Pin 2
pinMode(6,OUTPUT); //Right Motor Pin 1
pinMode(7,OUTPUT);  //Right Motor Pin 2
Serial.begin(9600); //Enable Serial Communications
}

void loop()
{
    read_sensor_values();
    calculate_pid();
    motor_control();
}

void read_sensor_values()
{
  sensor[0]=digitalRead(A0);
  sensor[1]=digitalRead(A1);
  sensor[2]=digitalRead(A2);
  sensor[3]=digitalRead(A3);
  sensor[4]=digitalRead(A4);
  
  if((sensor[0]==0)&&(sensor[1]==0)&&(sensor[2]==0)&&(sensor[4]==0)&&(sensor[4]==1))
  error=4;
  else if((sensor[0]==0)&&(sensor[1]==0)&&(sensor[2]==0)&&(sensor[4]==1)&&(sensor[4]==1))
  error=3;
  else if((sensor[0]==0)&&(sensor[1]==0)&&(sensor[2]==0)&&(sensor[4]==1)&&(sensor[4]==0))
  error=2;
  else if((sensor[0]==0)&&(sensor[1]==0)&&(sensor[2]==1)&&(sensor[4]==1)&&(sensor[4]==0))
  error=1;
  else if((sensor[0]==0)&&(sensor[1]==0)&&(sensor[2]==1)&&(sensor[4]==0)&&(sensor[4]==0))
  error=0;
  else if((sensor[0]==0)&&(sensor[1]==1)&&(sensor[2]==1)&&(sensor[4]==0)&&(sensor[4]==0))
  error=-1;
  else if((sensor[0]==0)&&(sensor[1]==1)&&(sensor[2]==0)&&(sensor[4]==0)&&(sensor[4]==0))
  error=-2;
  else if((sensor[0]==1)&&(sensor[1]==1)&&(sensor[2]==0)&&(sensor[4]==0)&&(sensor[4]==0))
  error=-3;
  else if((sensor[0]==1)&&(sensor[1]==0)&&(sensor[2]==0)&&(sensor[4]==0)&&(sensor[4]==0))
  error=-4;
  else if((sensor[0]==0)&&(sensor[1]==0)&&(sensor[2]==0)&&(sensor[4]==0)&&(sensor[4]==0))
    if(error==-4) error=-5;
    else error=5;

}

void calculate_pid()
{
    P = error;
    I = I + previous_I;
    D = error-previous_error;
   
    PID_value = (Kp*P) + (Ki*I) + (Kd*D);
   
    previous_I=I;
    previous_error=error;
}

void motor_control()
{
    // Calculating the effective motor speed:
    int left_motor_speed = initial_motor_speed-PID_value;
    int right_motor_speed = initial_motor_speed+PID_value;
   
    // The motor speed should not exceed the max PWM value
    constrain(left_motor_speed,0,255);
    constrain(right_motor_speed,0,255);
        
        analogWrite(9,initial_motor_speed-PID_value);   //Left Motor Speed
    analogWrite(10,initial_motor_speed+PID_value);  //Right Motor Speed
    //following lines of code are to make the bot move forward
    /*The pin numbers and high, low values might be different
    depending on your connections */
    digitalWrite(4,HIGH);
    digitalWrite(5,LOW);
    digitalWrite(6,LOW);
    digitalWrite(7,HIGH);
}[/mw_shl_code]

参考文献:

https://www.zhihu.com/question/37943171/answer/119525120
https://mc.dfrobot.com.cn/forum.p ... =%E5%B7%A1%E7%BA%BF
https://github.com/samvrit/Proje ... ollower/pid/pid.pde



安卓机器人  中级技神

发表于 2018-4-26 07:58:14

根据这个思路提示,最好的办法就是用小车反复实践验证,5.1来试一试
回复

使用道具 举报

青出于蓝  初级技师

发表于 2019-8-24 17:55:26

理论正解,建议传感器数量可以多加几个,更方便解读。
回复

使用道具 举报

gada888  版主

发表于 2019-8-25 09:25:03

不错的分享
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail