1

寻路模块 (1)

终于要挑战寻路模块,虽然我是在重复造轮子,但看一下别人的轮子怎么造也是很重要的,所以
在这之前首先搜索下,看看有什么现成的思路和代码,收获如下:

两种寻路逻辑

有两种寻路逻辑, 随机碰撞和路径规划,考虑到:

a. 随机碰撞似乎需要不少经验/实验数据才能达到不错的效果,我缺经验/数据呢
b. 现在我拥有一个接近于理想环境的情况,更便于路径规划
c. 随机碰撞得到的路径不漂亮,搞不好还漏了边边角角,不符合我的美学价值观

所以决定用路径规划

一些路径规划的方法

这篇文章介绍了一些路径规划的方法

a. 人工智能:本来是想用办法来做的,毕竟算是用过matlab的人(但忘光光了),但后来发现学习成本有点高,就放弃了……
b. 人工势场法:看上去也不简单,也放弃……
c. 栅格法:说明了地图形态(含障碍物),但并没有说明具体走法,有些怀疑小编或者作者的逻辑能力。话说我的地图就是栅格形式(用点/坐标来表示格子)
d. 模板模型法:很容易理解,就是有几种走法,按情况调用。就决定用这个办法了

决定算法

按上面模板模型法的思路,去搜关键字(Complete coverage path planning等),看了2篇论文和一些科普文章
这篇文章引起了我的注意,这篇论文说的是基于A*算法来实现完全路径覆盖,里面还有两个走法,分别是U-turn Search和 Internal Spiral Search,形象地说就是U型走法和回形走法
从文章结论看,U型走法配合A*算法的效果似乎不错(重复率低),那么我也按这个办法来吧
具体来说就是U型走法清扫一次,然后通过A*算法走到最近的未清洁点,如此反复直到所有点都被清洁/走过
虽然这不是全局最优解,但还是先以实现为目标努力吧

实现算法 (U型走法)

A*算法稍微有些复杂,之后再开篇文章写,我先写U型走法的部分,思路:

  1. 需要两个U型走法,一个朝右,一个朝左,除了朝左右不同之外其他相同
  2. 以U型朝右走法为例,先尝试往上下移动,“碰墙”后朝右移动一格,然后掉头,如此反复直到无法往右
  3. 由于U型走法具有反复的特性,如果发现下一步要走的点/格子已经走过了,就要停下来

path_finding代码1,先写上面3里提到的判断方法
篇幅起见,我这里只写一个判断上方格子是否走过的方法:

def judge_up_passed(self):
    x, y = self.current_coordinate
    up_coordinate = (x, y + 1)
    if up_coordinate in self.path_log:
        return True
    else:
        return False

path_finding代码2,U型朝右走法:

def u_turn_toward_right(self):
    rollback = False
    while True:
        if (self.judge_up_passable() == False) and (self.judge_down_passable() == False) and (
            self.judge_right_passable() == True):
            self.move_right()

        if rollback == False:
            while self.judge_up_passable() == True and self.judge_up_passed() == False:
                self.move_up()
            if self.judge_right_passable() == True and self.judge_right_passed() == False:
                self.move_right()
                rollback = True
            else:
                rollback = True

        if rollback == True:
            while self.judge_down_passable() == True and self.judge_down_passed() == False:
                self.move_down()
            if self.judge_right_passable() == True and self.judge_right_passed() == False:
                self.move_right()
                rollback = False
            else:
                rollback = False
                break

之后在main中添加方法

    from path_finding import *
    Robot.u_turn_toward_right = u_turn_toward_right
    Robot.u_turn_toward_left = u_turn_toward_left
    Robot.judge_up_passed = judge_up_passed
    Robot.judge_down_passed = judge_down_passed
    Robot.judge_left_passed = judge_left_passed
    Robot.judge_right_passed = judge_right_passed

测试

接着看一下写的U型走法效果如何,在main中测一下

...
    robot.u_turn_toward_right()
    print(robot.path_log)
    print(len(robot.path_log))

然后自己按着path_log看一下U型走得如何,按第一篇文章中的地图,没有意外的话,应该是82步


阿薛
45 声望9 粉丝

超懒