A*路径规划探究

本文详细介绍了A*路径规划算法,包括其关键概念如G值、H值和openlist、closelist,以及算法的执行步骤。通过示例代码展示了如何在Python中实现A*算法,并给出了一个简单的迷宫寻路问题的解决过程。
摘要由CSDN通过智能技术生成

1.文章说明

A是常用的路径规划算法,在游戏和机器人中经常会用到,这篇文章目的在于记录A的一些原理和要点

2.A*的一些重要概念

  • 1)G:该点到起点所需代价,与历史路径有关
  • 2)H:曼哈顿距离,该点到终点的距离,与历史路径无关。
  • 3)open list: 查找最优路径,需要遍历的列表
  • 4)close list:已遍历的的点,或者是障碍物的点

3.A*的步骤

  • 1)把起点加入open list
  • 2) 重复以下步骤
  • a:遍历open list,查找F值最小的节点,把他作为当前要处理的节点
  • b:把这个节点移到close list
  • c:对当前方格的8个相邻方格的每一个方格做如下操作:
  • i)如果他是不可达的或者他在close list中,忽略他,否则
  • ii) 如果它不在open list中,把它加入open list,并且把当前方格设置为他的父亲,记录该方格的F,G,H值。
  • iii)如果他已经在open list中,检查这条路径是否是更好,用G值做参考,更小的G值,表示这是更好的路径,如果是这样,把他的父亲设置为当前方格,并重新计算他的G值和F 值。
  • iiii) 如果终点已经在open list中,此时说明路径已经找到了,退出。

demo(注,代码引用自wang.zhigang@hotmail.com)

#!/usr/bin/python​
# vim:set fileencoding=utf-8
import sys

_2dmap     = []
start      = None
end        = None
open_list  = {}
close_list = {}
map_border = ()

class Node:
    def __init__(this, father, x, y):
        if x < 0 or x >= map_border[0] or y < 0 or y >= map_border[1]:
            raise Exception("node position can't beyond the border!")

        this.father = father
        this.x = x
        this.y = y
        if father != None:
            G2father = calc_G(father, this)
            if not G2father:
                raise Exception("father is not valid!")
            this.G = G2father + father.G
            this.H = calc_H(this, end)
            this.F = this.G + this.H
        else:
            this.G = 0
            this.H = 0
            this.F = 0

    def reset_father(this, father, new_G):
        if father != None:
            this.G = new_G
            this.F = this.G + this.H

        this.father = father

def calc_G(node1, node2):
    x1 = abs(node1.x-node2.x) 
    y1 = abs(node1.y-node2.y) 
    if (x1== 1 and y1 == 0):
        return 10 # same row
    if (x1== 0 and y1 == 1):
        return 10 # same col
    if (x1== 1 and y1 == 1):
        return 14 # cross
    else:
        return 0

def calc_H(cur, end):
    return abs(end.x-cur.x) + abs(end.y-cur.y)

# NOTE 这个地方可能成为性能瓶颈
def min_F_node():
    if len(open_list) == 0:
        raise Exception("not exist path!")

    _min = 9999999999999999
    _k = (start.x, start.y)
    for k,v in open_list.items():
        if _min > v.F:
            _min = v.F
            _k = k
    return open_list[_k]

# 把相邻节点加入open list, 如果发现终点说明找到了路径
def addAdjacentIntoOpen(node):
    # 将该节点从开放列表移到关闭列表当中。
    open_list.pop((node.x, node.y))
    close_list[(node.x, node.y)] = node

    _adjacent = []
    # 相邻节点要注意边界的情况
    try:
        _adjacent.append(Node(node , node.x - 1 , node.y - 1))
    except Exception:
        pass
    try:
        _adjacent.append(Node(node , node.x     , node.y - 1))
    except Exception:
        pass
    try:
        _adjacent.append(Node(node , node.x + 1 , node.y - 1))
    except Exception:
        pass
    try:
        _adjacent.append(Node(node , node.x + 1 , node.y))
    except Exception:
        pass
    try:
        _adjacent.append(Node(node , node.x + 1 , node.y + 1))
    except Exception:
        pass
    try:
        _adjacent.append(Node(node , node.x     , node.y + 1))
    except Exception:
        pass
    try:
        _adjacent.append(Node(node , node.x - 1 , node.y + 1))
    except Exception:
        pass
    try:
        _adjacent.append(Node(node , node.x - 1 , node.y))
    except Exception:
        pass

    for a in _adjacent:
        if (a.x,a.y) == (end.x, end.y):
            new_G = calc_G(a, node) + node.G
            end.reset_father(node, new_G)
            print ("find path finish!")
            return True
        if (a.x,a.y) in close_list:
            continue

        if (a.x,a.y) not in open_list:
            open_list[(a.x,a.y)] = a
        else:
            exist_node = open_list[(a.x,a.y)]
            new_G = calc_G(a, node) + node.G
            if new_G < exist_node.G:
                exist_node.reset_father(node, new_G)

    return False

def find_the_path(start, end):
    open_list[(start.x, start.y)] = start

    the_node = start
    try:
        while not addAdjacentIntoOpen(the_node):
            the_node = min_F_node()
    except Exception:
        # path not exist
        return False

    return True

#=======================================================================
def print_map():
    print ('    Y')
    for i in range(len(_2dmap)):
        print (i),
    print
    print ('  X')
    row = 0
    for l in _2dmap:
        print ('%3d'%row,' ')
        row = row+1
        for i in l:
            print (i, ' ')
        print

def mark_path(node):
    if node.father == None:
        return

    _2dmap[node.x][node.y] = '#'
    mark_path(node.father)

def preset_map():
    global start,end,map_border
    _2dmap.append('S X . . . . . . . . . . . . . X . . . .'.split())
    _2dmap.append('. X . . . . . . . . . . . . . X . . . .'.split())
    _2dmap.append('. X . . . . . . . . . . . . . X . . . .'.split())
    _2dmap.append('. . . . . . . . . . . . . . . X . . . .'.split())
    _2dmap.append('. . . . . . . . . . . . . . . X . . . .'.split())
    _2dmap.append('. . . . . . . . . . . . . . . . . . . .'.split())
    _2dmap.append('. . . . . . . . . . . . . . . X X X X .'.split())
    _2dmap.append('. . . . . . . . . . . . . . . X . . . .'.split())
    _2dmap.append('. . . . . . . . . . . . . . . X . X X X'.split())
    _2dmap.append('. . . . . . . . . . . . . . . X . X . .'.split())
    _2dmap.append('. . . . . . . . . . . . . . . X . . . .'.split())
    _2dmap.append('. . . . . . . . . . . . . . . X . X . .'.split())
    _2dmap.append('. . . . . . . . . . . . . . . X . X . .'.split())
    _2dmap.append('. . . . . . . . . . . . . . . X . X . .'.split())
    _2dmap.append('. . . . . . . . . . . . . . . X . X . .'.split())
    _2dmap.append('. . . . . . . . . . . . . . . X . X . E'.split())
    map_border = (len(_2dmap),len(_2dmap[0]))

    row_index = 0
    for row in _2dmap:
        col_index = 0
        for n in row:
            if n == 'X':
                block_node = Node(None, row_index, col_index)
                close_list[(block_node.x, block_node.y)] = block_node
            elif n == 'S':
                start = Node(None, row_index, col_index)
            elif n == 'E':
                end = Node(None, row_index, col_index)
            col_index = col_index + 1
        row_index = row_index + 1

if __name__=='__main__':
    if len(sys.argv) < 3:
        preset_map()
    else:
        x = int(sys.argv[1])
        y = int(sys.argv[2])
        map_border = (x,y)

        _start = raw_input('pls input start point:')
        _end   = raw_input('pls input end point:')
        _start = _start.split(',')
        _end   = _end.split(',')
        _start = (int(_start[0]), int(_start[1]))
        _end   = (int(_end[0]), int(_end[1]))
        start = Node(None, _start[0], _start[1])
        end = Node(None, _end[0], _end[1])
        # gen map
        _2dmap = [['.' for i in xrange(y)] for i in xrange(x) ]
        # put start and end
        _2dmap[_start[0]][_start[1]] = 'S'
        _2dmap[_end[0]][_end[1]]     = 'E'
        # input blocks
        while True:
            _block = raw_input('input block:')
            if not _block:
                break

            _block = _block.split(',')
            _block = (int(_block[0]), int(_block[1]))
            _2dmap[_block[0]][_block[1]] = 'X'
            block_node = Node(None, _block[0], _block[1])
            close_list[(block_node.x, block_node.y)] = block_node

    print ("orignal map:")
    print_map()

    if find_the_path(start, end):
        mark_path(end.father)
        print ("found road as follow:")
        print_map()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值