# 相扑机器人2--机器人的状态

巡线机器人系列中,如果你的朋友问你,机器人在干嘛呢?你回答他:机器人在巡线。朋友看了一会,称赞:机器人做的很好!
现在你的朋友又问你。你回答:机器人在相扑。一会儿之后,朋友追问道:相扑就是一直转圈圈?
你可以更详细地回道:它现在正在不停地搜索目标,或者在躲避胶带、在进攻敌人。

# 情景分析

  1. 你的朋友只观察了一小段时间,所以他只看到了机器人其中的一个状态(搜索)。这与之前编程的机器人不一样。巡线机器人只做一件事情,行动都是由传感器来直接决定的,如果传感器发生变化,立刻修改机器人的行动就行。相扑机器人做3件事情:搜索目标,进攻敌人,躲避胶带。搜索目标的时候,检测到目标应该进攻。而碰到胶带的时候,检测到目标就要视而不见了。这种差异是因为机器人当前所做的事情不同造成的。机器人一个时候只能做一件事情,符合一定条件之后,就会放下当前的事情,去做另外一件。机器人正在做什么我们叫做机器人的状态。目前看来有3个状态,搜索状态,进攻状态,躲避状态。
  2. 上一节,机器人在胶带附近搜索目标时遇到了困难。搜索碰到胶带之后,要躲避胶带,机器人向相反的方向转弯。离开胶带以后,就应该搜索目标。这时方向已经设置好了,那么在没有发现目标或者再次碰到胶带之前,最好的策略就是保持转弯方向不变。而另外一个躲避胶带的方式是后退,那就要特别处理一下。要变成转弯,之后就开始搜索。同样地前进攻击目标,碰到胶带也要特殊处理。特殊处理要等到离开胶带,或者丢失目标以后再处理。我们可以while循环,一直等到条件合适,再设置机器人转弯。

# 流程解析

  1. 读取传感器,并判断是否碰到胶带,是否发现目标,保存到变量。
  2. 如果碰到胶带,并且两个传感器都在胶带上
    • 机器人开始后退
    • 用while等待后退至完全离开胶带(注意,要重新读取传感器)
    • 脱离胶带后机器人开始转弯进入搜索状态
  3. 如果只有一边碰到胶带,机器人向相反的方向转弯,并不需要等待离开胶带。因为离开胶带以后也是要保持现在的方向,没什么可以做的。
  4. 没有碰到胶带,目标存在,机器人前进进攻目标。并用while来等待丢失目标,或者碰到胶带。(注意,要重新读取传感器)
  5. 如果是因为碰到胶带而离开了while循环,不做处理,再次进入loop函数时,由碰到胶带的代码来处理。如果是因为目标丢失,则要控制机器人开始转弯,进入搜索状态。
  6. 重复执行以上步骤
uml diagram

# 参考程序

只需要修改loop函数

void loop() {
    readSensor();
    if (SL || SR) {
        if (SL && SR) { //两个传感器都碰到了胶带
            while (SL || SR) {  //循环等待离开胶带
                L.backward(150);  //后退
                R.backward(150);
                readSensor();  //读传感器,更新状态变量
            }
            if (random(2)) {//离开胶带后,随机转弯
                L.forward(100);  //右转
                R.backward(100);
            } else {
                L.backward(100);  //左转
                R.forward(100);
            }
        } else if (SL) {     //左边传感器碰到胶带
            L.forward(100);  //右转
            R.backward(100);
        } else if (SR) {      //右边传感器碰到胶带
            L.backward(100);  //左转
            R.forward(100);
        }
    } else {  //没有碰到胶带
        if (SU) { //发现目标
            L.forward(150);  //前进
            R.forward(150);  //前进
            while (SU) { //等待丢失目标
                readSensor();
                if (SL || SR) break;
            }
            //如果是因为丢失目标退出while,需要设置机器人转弯
            if (!(SL || SR)) {
                if (random(2)) {
                    L.forward(100);  //右转
                    R.backward(100);
                } else {
                    L.backward(100);  //左转
                    R.forward(100);
                }
            }
            // 如果是碰到胶带退出while,留给碰到胶带的代码处理。
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

# 运行结果

机器人放置在胶带围成的区域中心,打开电源,尝试放个纸盒在中间,机器人对纸盒发起进攻。在胶带附近搜索时,也可以正常搜索全部范围了。程序达到了我们的预期。

# 程序解读

我们用while循环来等待离开胶带、丢失目标,然后转弯进入搜索状态。但是while过程中还需要考虑传感器情况。所以代码显得比较冗长。并且如果传感器增加,或者逻辑增加。代码就会更复杂。例如我们还想要使用遥控器来控制,那么所有的while里面都要加上遥控器的判断代码。例如机器人对着一个目标进攻过程碰到胶带(目标已经出界了),我们要找新的目标,就要先等待丢失现在的目标,再等待发现新目标。代码的逻辑就会越来越复杂。

# ArduinoIDE操作视频