寻路模块 (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型走法的部分,思路:
- 需要两个U型走法,一个朝右,一个朝左,除了朝左右不同之外其他相同
- 以U型朝右走法为例,先尝试往上下移动,“碰墙”后朝右移动一格,然后掉头,如此反复直到无法往右
- 由于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步