• SLAM从入门到精通(a*搜路算法)


    【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】

            目前机器人常用的搜路算法主要有这么几种,迪杰斯特拉算法、a*算法、贪心算法。每一种算法都有自己的场景和优势,可以灵活选择。但一般来说,客户的场景不算很复杂的话,搜路算法越简单越好,只要能达到最终的目标即可。对于特别复杂的场景,建议也不要通过底层算法的变更来解决业务的问题,这反而是得不偿失的。所以说,这三种算法,如果没有特别原因的话,最好都实现一下,这样方便fae的同学现场部署和实施。搜路算法本身只是一个拓扑算法,它帮助我们分析了目的地本身是否可达,但是机器人能不能过去,这就两说了。

            下面,我们就看下a*算法是怎么实现的。

    1、a*算法的核心

            a*算法的核心其实就是F=G+H。其中F是总代价,G是起始点到当前点的代价,H是当前点到目标点的代价。两者加在一起,就是每次选择新插入点的标准。

    2、a*算法的流程

    a*算法的伪代码流程一般是这样的,

    1)将开始点设置为p;

    2)p点插入到封闭集当中;

    3)搜寻p的所有邻接点,如果邻接点没有在开放集或者封闭集之中,则计算该点的F值,设置该邻接点的parent为p,将临界点插入到开放集当中;

    4)判断开放集是否为空,如果为空,则搜路失败,否则继续;

    5)从开放集挑出F数值最小的点,作为寻路的下一步起始点;

    6)判断该点是否是终点,如果是,结束查找,否则继续;

    7)跳转到3继续执行。

    3、a*算法的注意事项

            整个a*算法还是不算太复杂的。需要注意的地方只有一处,那就是3)中如果发现邻接点已经在开放集中,那需要重新计算它的G值。一旦发现当前G值更小,则需要同步更新parent、G值和F值。

    4、测试代码

            算法的整个过程参考了一本ROS参考书上的python代码。大家可以实际下载下来查看一下效果。代码是用python编写,需要安装matplotlib库。

    1. import matplotlib.pyplot as plt
    2. import math
    3. class Node:
    4. def __init__(self, x, y, parent, cost, index):
    5. self.x =x
    6. self.y = y
    7. self.parent = parent
    8. self.cost = cost
    9. self.index = index
    10. def calc_path(goaln, closeset):
    11. rx,ry = [goaln.x], [goaln.y]
    12. print(closeset[-1])
    13. parentn = closeset[-1]
    14. while parentn != None:
    15. rx.append(parentn.x)
    16. ry.append(parentn.y)
    17. parentn = parentn.parent
    18. return rx, ry
    19. def astar_plan(sx, sy, gx, gy):
    20. ox,oy,xwidth,ywidth = map_generation()
    21. plt.figure('Astar algorithm')
    22. plt.plot(ox, oy, 'ks')
    23. plt.plot(sx, sy, 'bs')
    24. plt.plot(gx, gy, 'ro')
    25. motion = motion_model()
    26. openset, closeset = dict(), dict()
    27. sidx = sy*xwidth + sx
    28. gidx = gy*xwidth + gx
    29. starn = Node(sx, sy, None, 0, sidx)
    30. goaln = Node(gx, gy, None, 0, gidx)
    31. openset[sidx] = starn
    32. while 1:
    33. c_id = min(openset,key=lambda o:openset[o].cost + h_cost(openset[o], goaln))
    34. curnode = openset[c_id]
    35. if curnode.x == goaln.x and curnode.y == goaln.y:
    36. print('find goal')
    37. closeset[-1] = curnode
    38. break
    39. else:
    40. closeset[c_id] = curnode
    41. plt.plot(curnode.x, curnode.y, 'gx')
    42. if len(openset.keys())%10 == 0:
    43. plt.pause(0.01)
    44. del openset[c_id]
    45. for j in range(len(motion)):
    46. newnode = Node(curnode.x + motion[j][0],
    47. curnode.y + motion[j][1],
    48. curnode,
    49. curnode.cost + motion[j][2],
    50. c_id)
    51. n_id = index_calc(newnode, xwidth)
    52. if n_id in closeset:
    53. continue
    54. if node_verify(newnode, ox, oy):
    55. continue
    56. if n_id not in openset:
    57. openset[n_id] = newnode
    58. else:
    59. if openset[n_id].cost >= newnode.cost:
    60. openset[n_id] = newnode
    61. px,py = calc_path(goaln, closeset)
    62. return px,py
    63. def map_generation():
    64. ox,oy=[],[]
    65. for i in range(60):
    66. ox.append(i)
    67. oy.append(0)
    68. for i in range(60):
    69. ox.append(i)
    70. oy.append(60)
    71. for i in range(60):
    72. ox.append(0)
    73. oy.append(i)
    74. for i in range(60):
    75. ox.append(60)
    76. oy.append(i)
    77. for i in range(25):
    78. ox.append(i)
    79. oy.append(20)
    80. for i in range(40):
    81. ox.append(35)
    82. oy.append(i)
    83. for i in range(40):
    84. ox.append(50)
    85. oy.append(60-i)
    86. minx = min(ox)
    87. miny = min(oy)
    88. maxx = max(ox)
    89. maxy = max(oy)
    90. xwidth = maxx-minx
    91. ywidth = maxy-miny
    92. return ox,oy,xwidth,ywidth
    93. def motion_model():
    94. motion= [[1,0,1],
    95. [1,1,math.sqrt(2)],
    96. [1,-1,math.sqrt(2)],
    97. [0,1,1],
    98. [0,-1,1],
    99. [-1,1,math.sqrt(2)],
    100. [-1,0,1],
    101. [-1,-1,math.sqrt(2)]
    102. ]
    103. return motion
    104. def h_cost(node, goal):
    105. w = 1.0
    106. h = w * (abs(goal.x-node.x) + abs(goal.y-node.y))
    107. return h
    108. def index_calc(node, xwid):
    109. n_id = node.y * xwid + node.x
    110. return n_id
    111. def node_verify(node, ox, oy):
    112. if(node.x, node.y) in zip(ox, oy):
    113. return True
    114. else:
    115. return False
    116. def main():
    117. sx,sy=15,15
    118. gx,gy=55,50
    119. rx,ry=astar_plan(sx,sy,gx,gy)
    120. print(rx,ry)
    121. plt.plot(rx,ry,'r-',linewidth=3)
    122. plt.show()
    123. if __name__ == '__main__':
    124. main()

            代码中motion_model表示了当前点周围8个点的行驶代价;node_verify则是判断当前点是否在障碍物上;astar_plan是所有算法真正的入口;而map_generation则构建了一个基本的搜寻场景。

    5、运行效果图

            运行效果如下所示,供大家参考。直接用python3 astar.py运行即可,

  • 相关阅读:
    多通道LMMSE图像超分辨复原方法研究-附Matlab代码
    【AutoGPT】踩坑帖(follow李鱼皮)
    django 操作
    【Jmeter】基于JMeter开展性能测试(插件、监控、分布式压测)!
    SpringBoot整合XXL-JOB详解
    c++视觉处理---cv::Sobel()`算子
    CAP+BASE
    数据结构(八)双向循环链表
    arcgis中坡向计算工作原理说明
    服务器硬件得基础知识介绍
  • 原文地址:https://blog.csdn.net/feixiaoxing/article/details/133875544