巡线问题小议
本帖最后由 微笑的rockets 于 2018-5-31 11:18 编辑今天在群里有老师询问怎样写巡线路口的问题,试着简单的回答了一下。
然后突然想到,可能真的有很多人其实对这个还是有疑问,于是斗胆将自己不成熟的想法发布上来,抛砖引玉,希望大家能批评指正。
问题是由这张图引起的。
如果让机器人知道在第二个路口转弯。
我觉得想要解决这样的问题,首先要分析地图。
于是我把这个地图进行了简化,也就是二值化。把黑色的定义为1,把白色的定义为0,于是有了下图。
那我们就可以进行分析了
想象一下,你现在有一个读数据的设备,读取的数据按队列进入,
读入到010表示在直线上
读入111表示到了横线上
读入010表示又到了直线上
且前面读到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 提供了他写的巡线代码。我们后面将以他的代码为基础进一步的改进。
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={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=digitalRead(A0);
sensor=digitalRead(A1);
sensor=digitalRead(A2);
sensor=digitalRead(A3);
sensor=digitalRead(A4);
if((sensor==0)&&(sensor==0)&&(sensor==0)&&(sensor==0)&&(sensor==1))
error=4;
else if((sensor==0)&&(sensor==0)&&(sensor==0)&&(sensor==1)&&(sensor==1))
error=3;
else if((sensor==0)&&(sensor==0)&&(sensor==0)&&(sensor==1)&&(sensor==0))
error=2;
else if((sensor==0)&&(sensor==0)&&(sensor==1)&&(sensor==1)&&(sensor==0))
error=1;
else if((sensor==0)&&(sensor==0)&&(sensor==1)&&(sensor==0)&&(sensor==0))
error=0;
else if((sensor==0)&&(sensor==1)&&(sensor==1)&&(sensor==0)&&(sensor==0))
error=-1;
else if((sensor==0)&&(sensor==1)&&(sensor==0)&&(sensor==0)&&(sensor==0))
error=-2;
else if((sensor==1)&&(sensor==1)&&(sensor==0)&&(sensor==0)&&(sensor==0))
error=-3;
else if((sensor==1)&&(sensor==0)&&(sensor==0)&&(sensor==0)&&(sensor==0))
error=-4;
else if((sensor==0)&&(sensor==0)&&(sensor==0)&&(sensor==0)&&(sensor==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);
}
参考文献:
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
根据这个思路提示,最好的办法就是用小车反复实践验证,5.1来试一试 理论正解,建议传感器数量可以多加几个,更方便解读。 不错的分享
页:
[1]