基于STM32F103的树莓派ROS小车——全局路径规划之Dijkstra算法

Dijkstra

Dijkstra算法概念:
基本思想:由近到远把所有点的最短路径算出来。
算法解析:从起点向四周辐射,由近到远一层一层遍历所有的点,直到包含目标点所在层级。然后将所有可行路径进行计算比较,筛选出绝对最佳路径。
优点:最终得到的路径一定是最佳路径。
缺点:因为Dijkstra算法需要遍历所有的点,所以程序运行时间较长。

Dijkstra算法过程讲解:
情景假设:从起点开始

1.每次走一格,不能跨格
2.共有8个相邻栅格可以走
3.若走(上/下/左/右)计路程为:2
4.若走(左上/左下/右下/右上)计路程为:3

5.设置两个列表(或者数组)
openlist=[ ]        ——存放待确定路径的点
closedlist=[ ]    ——存放已确定路径的点
6.每个点都记录自己的父节点,下标表示
7.为了方便讲解 起点称S点 相邻8个点以A-H称呼
8.已放进closedlist的点不走,因已确定路径

具体过程:

①:起点为S点,计算周围点,父节点为S
②:取一个最小值的点作第二步中心点;从openlist取出,放入closedlist计算中心点周围8个点,累计路程;若点已存在openlist,取路程小的方案。
③:取一个最小值的点作第三步中心点,重复第二步步骤。
④:取一个最小值的点作第四步中心点,重复步骤。
⑤:取一个最小值的点作第五步中心点,重复步骤。
⑥:取一个最小值的点作第六步中心点,重复步骤。

 ......重复步骤

 伪代码:

获取起点坐标、目标点坐标,把起点放进openlist
while (openlist不为空列表)
{    取openlist中路程最小的点为中心点,从openlist剔除,放入closedlist
    if (中心点是目标点)
        {从目标点开始通过父节点反推,提取出路径,break跳出循环}
    else         {遍历相邻的八个点
            {if(点已存在closedlist中  or  遇到障碍物 )
                {跳过,不计算这个点}
            else
                {累计路径
                if(点已存在openlist中)
                    if(累计路程<原来记录的路程)
                        {替换数据}
                else {加入openlist}
            }
        openlist从小到大排序
    }
}

完整代码送上:

# -- coding: utf-8 --
import math, sys, pygame, random
from math import *
from pygame import *
import time

Astar = 0
Dijkstra = 1
#模式选择: Dijkstra or Astar
mode = Astar

GAME_LEVEL =1  #障碍物等级,目前可选项为0或1
delay_sec = 0   #算法延时,单位:秒;可设置延时来观察学习路径规划的逐步实现过程
#颜色RGB值
grey = (169, 169, 169)
blue = (0, 0, 255)
red = (255, 0, 0)
black = (0, 0, 0)
green = (0, 255, 0)
yellow = (255, 255, 0)
orange = (255, 165, 0)
bg_color = (255, 255, 255)
purple = (160, 32, 240)
#初始化相关
pygame.init()
screen = pygame.display.set_mode((800, 600))
fpsClock = pygame.time.Clock()

#定义Node类,用于存储每个节点信息
class Node(object):
    def __init__(self, point, parent, d, f):
        super(Node, self).__init__()
        self.point = point      #节点坐标
        self.parent = parent    #父节点对象地址
        self.d = d      #Astar算法下:起点至该节点的确定距离;Dijkstra算法下:起点至该节点的估算距离
        self.f = f      #Astar算法下:f = d + h  d为上述确定距离,h为该节点到目标节点的估算距离(欧几里得距离或曼哈顿距离);Dijkstra算法下此参数置零

#初始化栅格
def init_grid():
    start_point = [0, 0]
    end_point = [0, 600]
    i = 20
    while start_point[0] <= 800:
        pygame.draw.line(screen, grey, start_point, end_point)
        start_point[0] += i
        end_point[0] += i 
    
    start_point = [0, 0]
    end_point = [800, 0]
    while start_point[1] <= 600:
        pygame.draw.line(screen, grey, start_point, end_point)
        start_point[1] += i
        end_point[1] += i 

#判断栅格
def judge_in_grid(p):
    p0 = int(p[0]/20)
    p1 = int(p[1]/20)
    rect1 = ((p0*20, p1*20), (20,20))
    return rect1

#初始化障碍物
def init_obstacles(configNum):
    global rectObs
    rectObs = []
    if configNum == 0:
        rectObs.append(pygame.Rect((300,200),(200,200)))
    if configNum == 1:
        rectObs.append(pygame.Rect((100,100),(100,340)))
        rectObs.append(pygame.Rect((320,240),(160,160)))
        rectObs.append(pygame.Rect((500,60),(200,100)))
    for rect in rectObs:
        pygame.draw.rect(screen, black, rect)

#节点与障碍物碰撞检测
def collides(p):    #check if point collides with the obstacle
    for rect in rectObs:
        if rect.collidepoint(p) == True:
            return True
    return False

#复位函数
def reset():
    screen.fill(bg_color)
    init_grid()
    init_obstacles(GAME_LEVEL)

#文本打印
def text_display(text0, rect, colour, Size):
    fontObj = pygame.font.Font(None,Size)
    textSurfaceObj = fontObj.render(text0,True,colour)
    textRectObj = textSurfaceObj.get_rect()
    textRectObj.center=(10+(rect[0][0]),10+(rect[0][1]))
    screen.blit(textSurfaceObj,textRectObj)

#欧几里得距离,计算量大
def Euclid(p1, p2):
    m = ((p1[0]-p2[0])*(p1[0]-p2[0])+(p1[1]-p2[1])*(p1[1]-p2[1]))**0.5
    return m

#曼哈顿距离,计算量小,简单
def Manhattan(p1, p2):
    m = abs(p1[0]-p2[0])+abs(p1[1]-p2[1])
    return m

#Astar估算函数
def evaluation_Astar(ynode, goalPoint):
    judge_open = False
    judge_close = False
    if collides(ynode.point) == True:
        return
    if ynode.point[0] < 0 or ynode.point[1] < 0:
        return
    ynode.f = ynode.d*1+0.1*Manhattan(ynode.point, goalPoint.point)
    for p in openlist:
        if p.point == ynode.point:
            judge_open = True
            index_open = openlist.index(p)
    for p in closelist:
        if p.point == ynode.point:
            judge_close = True
            index_close = closelist.index(p)
    if judge_close == True:
        return
    if judge_open == False:
        openlist.append(ynode)
        pygame.draw.rect(screen, (255*abs(1-float(ynode.d)*1.2/140), 255*abs(1-float(ynode.d)*1.2/140), 255), (ynode.point, (20, 20)))
        text_display(str(int(ynode.d)), (ynode.point, (20, 20)), black, 15)
        pygame.display.flip()
    else:
        if openlist[index_open].d > ynode.d:
            openlist[index_open] = ynode

#Dijkstra估算函数
def evaluation_Dijkstra(ynode, goalPoint):
    judge_open = False
    judge_close = False
    if collides(ynode.point) == True:
        return
    if ynode.point[0] < 0 or ynode.point[1] < 0:
        return
    for p in closelist:
        if p.point == ynode.point:
            judge_close = True
            index_close = closelist.index(p)
    if judge_close == True:
        return
    for p in openlist:
        if p.point == ynode.point:
            judge_open = True
            index_open = openlist.index(p)
    if judge_open == True:
        if openlist[index_open].d > ynode.d:
            openlist[index_open] = ynode
    else:
        openlist.append(ynode)
        pygame.draw.rect(screen, (255*abs(1-float(ynode.d)*1.2/140), 255*abs(1-float(ynode.d)*1.2/140), 255), (ynode.point, (20, 20)))
        text_display(str(ynode.d), (ynode.point, (20, 20)), black, 15)
        pygame.display.flip()

#程序主要函数
def run_game():
    currentState = 'init'
    initPoseSet = False
    goalPoseSet = False
    global openlist
    openlist = []
    global closelist
    closelist = []
    reset()
    #主循环
    while True:
        #处理不同currentState状态下的工作,其中包括规划路径的实现
        if currentState == 'init':
            print('goal point not yet set')
            pygame.display.set_caption('Select Starting Point and then Goal Point')
            fpsClock.tick(10)
        elif currentState == 'lookingForGoal':
            run = True
            while(len(openlist) != 0):
                for event in pygame.event.get():
                    if event.type == MOUSEBUTTONDOWN :
                        if run == True:
                            run = False
                        else:
                            run = True
                if run == True:
                    xnode = openlist[0]
                    if xnode.point == goalPoint.point:
                        pygame.draw.rect(screen, orange, (xnode.point, (20, 20)))
                        text_display("G",(xnode.point, (20, 20)), black, 32)
                        currentState = 'goalFound'
                        flag = 1
                        goalNode = xnode
                        break
                    closelist.append(xnode)
                    del openlist[0]
                    if delay_sec > 0:
                        pygame.draw.circle(screen, red, (xnode.point[0]+10, xnode.point[1]+10), 2)
                    i = 0
                    while i < 8:
                        if i == 0:
                            ynode = Node((xnode.point[0],xnode.point[1]-20), xnode, xnode.d+2, 0)
                        elif i == 1:
                            ynode = Node((xnode.point[0],xnode.point[1]+20), xnode, xnode.d+2, 0)
                        elif i == 2:
                            ynode = Node((xnode.point[0]-20,xnode.point[1]), xnode, xnode.d+2, 0)
                        elif i == 3:
                            ynode = Node((xnode.point[0]+20,xnode.point[1]), xnode, xnode.d+2, 0)
                        elif i == 4:
                            ynode = Node((xnode.point[0]-20,xnode.point[1]-20), xnode, xnode.d+3, 0)
                        elif i == 5:
                            ynode = Node((xnode.point[0]+20,xnode.point[1]-20), xnode, xnode.d+3, 0)
                        elif i == 6:
                            ynode = Node((xnode.point[0]+20,xnode.point[1]+20), xnode, xnode.d+3, 0)
                        elif i == 7:
                            ynode = Node((xnode.point[0]-20,xnode.point[1]+20), xnode, xnode.d+3, 0)
                        if mode == 0:
                            evaluation_Astar(ynode, goalPoint)
                        elif mode == 1:
                            evaluation_Dijkstra(ynode, goalPoint)
                        i += 1
                    for i in range(0, len(openlist)-1):
                        for j in range(0, len(openlist)-1-i):
                            if mode == 0:
                                data_j = openlist[j].f
                                data_j1 = openlist[j+1].f
                            elif mode == 1:
                                data_j = openlist[j].d
                                data_j1 = openlist[j+1].d
                            if data_j > data_j1:
                                temp = openlist[j]
                                openlist[j] = openlist[j+1]
                                openlist[j+1] = temp
                    pygame.display.flip()
                    for i in range(0, len(openlist)):
                        print(str(openlist[i].point)+"\t--- d = "+str(openlist[i].d)+"  &  f = "+str(openlist[i].f))
                        print("parent:"+str(openlist[i].parent.point))
                    print("-------------------")
                    time.sleep(delay_sec)
                if len(openlist) == 0:
                    print('False to find the path')
        elif currentState == 'goalFound':
            if flag == 1:
                print('goalFound!!!!!!')
                currNode = goalNode.parent
                print("******************")
                print("startPoint = "+(str(initialPoint.point)))
                print("goalPoint = "+(str(goalPoint.point)))
                print("******************")
                for i in range(0, len(closelist)):
                    print(str(closelist[i].point)+"\t--- d = "+str(closelist[i].d)+"  &  f = "+str(closelist[i].f))
                    if i > 0:
                        print("parent:"+str(closelist[i].parent.point))
            while currNode.parent != None:
                pygame.draw.rect(screen, green, (currNode.point, (20, 20)))
                text_display(str(currNode.d), (currNode.point, (20, 20)), black, 15)
                currNode = currNode.parent
                flag = 0
                pygame.display.flip()
                time.sleep(float(delay_sec)/2)
            fpsClock.tick(10)
        #处理鼠标事件
        for event in pygame.event.get():
            if event.type == pygame.QUIT or (event.type == KEYUP and event.key == K_ESCAPE):
                sys.exit()
            if event.type == MOUSEBUTTONDOWN:
                if currentState == 'init':
                    rect = judge_in_grid(event.pos)
                    if initPoseSet == False:
                        if collides(event.pos) == False:
                            initialPoint = Node(rect[0], None, 0, 0)
                            
                            pygame.draw.rect(screen, red, rect)
                            text_display("S",rect, black, 32)
                            initPoseSet = True
                    elif  goalPoseSet == False:
                        if collides(event.pos) == False:
                            if rect[0] != initialPoint.point:
                                goalPoint = Node(rect[0],None, 0, 0)
                                print("******************")
                                print("startPoint = "+(str(initialPoint.point)))
                                print("goalPoint = "+(str(goalPoint.point)))
                                print("******************")
                                if mode == 0:
                                    initialPoint.f = initialPoint.d+0.1*Manhattan(goalPoint.point, initialPoint.point)
                                openlist.append(initialPoint)
                                pygame.draw.rect(screen, orange, rect)
                                text_display("G",rect, black, 32)
                                goalPoseSet = True
                                currentState = 'lookingForGoal'
                else:
                    currentState = 'init'
                    initPoseSet = False
                    goalPoseSet = False
                    openlist = []
                    closelist = []
                    reset()
        init_grid()
        pygame.display.flip()
        
if __name__ == '__main__':
    run_game()

猜你喜欢

转载自blog.csdn.net/weixin_63861197/article/details/130935006