国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【路徑規(guī)劃】(2) A* 算法求解最短路,附python完整代碼

這篇具有很好參考價(jià)值的文章主要介紹了【路徑規(guī)劃】(2) A* 算法求解最短路,附python完整代碼。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

大家好,今天和各位分享一下機(jī)器人路徑規(guī)劃中非常經(jīng)典的 A* 算法,感興趣的點(diǎn)個(gè)關(guān)注,文末有 python 代碼,那我么開始吧。


1. 算法介紹

A* 算法是 1968 年 P.E.Hart[1]等人所提出的在全局地圖環(huán)境中所有已知情形下求解最短路徑問題的方法,由于其簡潔高效,容易實(shí)施優(yōu)點(diǎn)而受到人們的廣泛關(guān)注。但是,A*算法在實(shí)際應(yīng)用過程中也暴露出其嚴(yán)重弊端,例如:在搜索空間較大的環(huán)境下,增加了算法的執(zhí)行時(shí)間,從而大大降低了路線規(guī)劃效果;復(fù)雜環(huán)境下,由于地圖精度不高,從而減小了獲取最佳路徑的可能性;在搜索過程中存在相同 F 值無法得到最佳路線等問題。

而面對上述問題,不同的研發(fā)人員也以不同的方法以對其做出了改善,并獲得了不少研究成果。

Korf 等人[2]在 A*算法的基礎(chǔ)上構(gòu)建了迭代改進(jìn)的 IDA* 算法,在計(jì)算過程中根據(jù)迭代次數(shù)得到最優(yōu)解,解決了A*算法容易陷入盲目搜索的不足;Tran HAM[3]等人在 A*算法基礎(chǔ)上構(gòu)建了一種基于視覺的路徑規(guī)劃和導(dǎo)航算法,然后對搜索的路徑進(jìn)行優(yōu)化。Szczerba[4]等人提出了稀疏 A*算法,在傳統(tǒng) A*算法基礎(chǔ)上添加相應(yīng)的約束條件,根據(jù)不同的約束條件修改 A*算法的搜索空間,提升了路線規(guī)劃效果,大大增加了獲取最佳路徑的可能性。

參考文獻(xiàn):

[1] Hart P E, Nilsson N J, Raphael B. A formal basis for the heuristic determination of minimum cost paths[J]. IEEE transactions on Systems Science and Cybernetics, 1968, 4(2): 100-107.?

[2] Korf, ?Richard ?E. ?Depth-first ?iterative-deepening: ?an ?optimal ?admissible ?tree ?search[J]. Artificial Intelligence, 1985, 27(1):97-109.?

[3] Tran H ?A M, Ngo H Q ?T, ?Nguyen ?T ?P, ?et ?al. ?Implementation ?of ?vision-based ?autonomous mobile platform to control by A* algorithm[C]//2018 2nd International Conference on Recent Advances in Signal Processing, Telecommunications & omputing (SigTelCom). IEEE, 2018: 39-44. ?

[4] Szczerba R J, Galkowski P, Glicktein I S, et al. Robust algorithm for real-time route planning[J]. IEEE Transactions on Aerospace & Electronic Systems, 2000, 36(3):869-878. ??


2. 算法原理

經(jīng)典 A* 算法主要用在靜態(tài)且周圍環(huán)境已知的情況下,是建立在 Dijkstra 和BFS 基礎(chǔ)上的啟發(fā)式遍歷搜索算法,在路徑規(guī)劃時(shí)不僅要考慮自身與最近節(jié)點(diǎn)位置的距離(Dijkstra 實(shí)現(xiàn)),還需要考慮自身位置與目標(biāo)點(diǎn)的距離(BFS 實(shí)現(xiàn))。與傳統(tǒng)的遍歷搜索算法相比,彌補(bǔ)了搜索過程中的貪心機(jī)制,從而很好地完成路徑規(guī)劃的任務(wù)。

2.1 基本原理

A* 算法以起點(diǎn)為中心開始進(jìn)行路徑規(guī)劃,并在路徑規(guī)劃過程中擴(kuò)展周圍的鄰近節(jié)點(diǎn)。通過 A*算法公式對起始點(diǎn)到當(dāng)前位置和當(dāng)前位置到目標(biāo)點(diǎn)的代價(jià)值進(jìn)行計(jì)算。在所有的節(jié)點(diǎn)中選取代價(jià)值最小的節(jié)點(diǎn)作為當(dāng)前最優(yōu)節(jié)點(diǎn),以當(dāng)前最優(yōu)節(jié)點(diǎn)繼續(xù)搜索,直到搜索到目標(biāo)點(diǎn),最后生成一條從起始點(diǎn)到目標(biāo)點(diǎn)的路徑。

A* 算法本身遵循 821 定律,同時(shí)在搜索過程中將節(jié)點(diǎn)的狀態(tài)定義為未檢查、待檢查、已檢查三種準(zhǔn)備狀態(tài);8 是指以當(dāng)前定位點(diǎn)周圍的 8 個(gè)鄰域的代價(jià)值作為計(jì)算目標(biāo),2 是指兩個(gè)參數(shù)列表,一個(gè)是 open list 列表,存放待檢查的節(jié)點(diǎn);另外一個(gè)是 close list 列表,存放已檢查完成不再需要關(guān)注的節(jié)點(diǎn),1 是指一個(gè)計(jì)算公式,如下。?

求a到b的最短路徑,只能沿水平或垂直方向移動(dòng),,路徑規(guī)劃算法,python,A star,路徑規(guī)劃,機(jī)器人運(yùn)動(dòng),路徑選擇

其中,f(n) 是指當(dāng)前節(jié)點(diǎn) n 的全局代價(jià)值,g(n) 是指從起始點(diǎn)到當(dāng)前節(jié)點(diǎn) n 的實(shí)際代價(jià)值,h(n) 是指當(dāng)前節(jié)點(diǎn) n 到終點(diǎn)的預(yù)測值。


2.2 案例解析

A* 算法整體搜索過程如下圖所示,圖中綠色格子為尋徑起始點(diǎn),紅色格子為尋徑終止點(diǎn),藍(lán)色代表障礙物。從起始點(diǎn)開始,將其放到 open list 列表中,同時(shí)讓其作為當(dāng)前節(jié)點(diǎn)。通過當(dāng)前節(jié)點(diǎn)查找與其相鄰的 8 個(gè)鄰域節(jié)點(diǎn),如圖中帶有綠色線條的方格。8 個(gè)鄰域節(jié)點(diǎn)方格中,箭頭指向的方向?yàn)楫?dāng)前相鄰節(jié)點(diǎn) n 的父節(jié)點(diǎn),用于代價(jià)值的計(jì)算以及最終路徑的回溯。?

以起始點(diǎn)作為當(dāng)前節(jié)點(diǎn),通過 A* 算法代價(jià)公式計(jì)算相鄰節(jié)點(diǎn)的 f 值,并將起始節(jié)點(diǎn)放入 close list 列表中。起始點(diǎn)周圍每個(gè)方格節(jié)點(diǎn)的三個(gè)夾角處由數(shù)字標(biāo)識,其中左下角表示的是從起始點(diǎn)到當(dāng)前節(jié)點(diǎn) n 的真實(shí)代價(jià)值 g(n),如果起始點(diǎn)到當(dāng)前節(jié)點(diǎn) n 是在橫向上往前/后移動(dòng)了一個(gè)節(jié)點(diǎn),或者在豎直方向上往上/下移動(dòng)了一個(gè)節(jié)點(diǎn),普遍設(shè)定 g(n) 移動(dòng)一個(gè)節(jié)點(diǎn)的代價(jià)為 10;如果起始點(diǎn)到當(dāng)前節(jié)點(diǎn) n 是經(jīng)過對角方向的移動(dòng),普遍設(shè)定 g(n) 的移動(dòng)代價(jià)值為 14。右下角表示的是從當(dāng)前節(jié)點(diǎn) n 到終點(diǎn)的預(yù)估值 h(n),通過啟發(fā)函數(shù)進(jìn)行計(jì)算。左上角表示的是全局代價(jià)值 f(n)將以上計(jì)算出的 g(n)與 h(n)相加可得到對應(yīng)的 f(n)。?

求a到b的最短路徑,只能沿水平或垂直方向移動(dòng),,路徑規(guī)劃算法,python,A star,路徑規(guī)劃,機(jī)器人運(yùn)動(dòng),路徑選擇

基于以上計(jì)算,進(jìn)一步判斷當(dāng)前節(jié)點(diǎn)的 8 個(gè)鄰域節(jié)點(diǎn)是否在 open list 列表中,如果某個(gè)鄰域節(jié)點(diǎn)未在 open list 列表中,則將帶有 f? 值的鄰節(jié)點(diǎn)添加到 open?list 列表中;如果某個(gè)鄰域節(jié)點(diǎn)已經(jīng)存放在 open ?list 表中,則以當(dāng)前方格為父節(jié)點(diǎn)檢查經(jīng)由當(dāng)前父節(jié)點(diǎn)到達(dá)那個(gè)方格是否具有更小的 g 值,如果沒有不做任何操作,如果存在更小的 g 值,把那個(gè)方格的父節(jié)點(diǎn)設(shè)置為當(dāng)前方格,然后重新計(jì)算那個(gè)方格的 g 值和 f 值。判斷完成之后,獲取 open list 列表中最小代價(jià)值節(jié)點(diǎn)。從上圖中可以看出起始點(diǎn)周圍相鄰節(jié)點(diǎn)的全局代價(jià)值 f 根據(jù)從上到下、從左向右的順序分別為 124、110、104、110、90、104、90、84,從以上數(shù)字中選取 f 值最小的 84 的點(diǎn)作為當(dāng)前節(jié)點(diǎn)。?

循環(huán)上述搜索步驟,直至搜索到右側(cè)的紅色目標(biāo)點(diǎn),將目標(biāo)點(diǎn)添加到 close list 列表中。根據(jù)close list 列表中的各個(gè)節(jié)點(diǎn)按照父節(jié)點(diǎn)的指向逆序輸出,從而得到搜索路徑。如下圖所示,帶有黃色邊框的格子節(jié)點(diǎn)為最終搜索到的最佳路徑。?

求a到b的最短路徑,只能沿水平或垂直方向移動(dòng),,路徑規(guī)劃算法,python,A star,路徑規(guī)劃,機(jī)器人運(yùn)動(dòng),路徑選擇


2.3 啟發(fā)函數(shù)

在路徑規(guī)劃時(shí),通常需要尋找一些與搜索環(huán)境相關(guān)的特征信息,在計(jì)算過程中,將這些特征信息稱為啟發(fā)函數(shù)。啟發(fā)函數(shù)被用來估計(jì)從當(dāng)前節(jié)點(diǎn)到目標(biāo)節(jié)點(diǎn)生成的代價(jià)值。常用的啟發(fā)函數(shù)主要包括曼哈頓距離函數(shù)、歐氏距離函數(shù)、對角距離函數(shù)三種。?

假設(shè)起點(diǎn)的坐標(biāo)為 (??, ??)終點(diǎn)的坐標(biāo)為 (??????????, ??????????),對三種啟發(fā)函數(shù)進(jìn)行分析。?

(1)曼哈頓距離函數(shù)。曼哈頓距離為起點(diǎn)與終點(diǎn)坐標(biāo)點(diǎn)絕對值總和,公式如下:

求a到b的最短路徑,只能沿水平或垂直方向移動(dòng),,路徑規(guī)劃算法,python,A star,路徑規(guī)劃,機(jī)器人運(yùn)動(dòng),路徑選擇

(2)歐式距離函數(shù)。?歐式距離為搜索環(huán)境中起止兩節(jié)點(diǎn)間的最短直線距離,公式如下:

求a到b的最短路徑,只能沿水平或垂直方向移動(dòng),,路徑規(guī)劃算法,python,A star,路徑規(guī)劃,機(jī)器人運(yùn)動(dòng),路徑選擇

(3)對角距離函數(shù)。?對角距離首先允許沿對角線運(yùn)動(dòng),然后通過水平和垂直運(yùn)動(dòng)完成剩下路線,
或者相反。公式如下:?

沿對角線運(yùn)動(dòng)的公式:

求a到b的最短路徑,只能沿水平或垂直方向移動(dòng),,路徑規(guī)劃算法,python,A star,路徑規(guī)劃,機(jī)器人運(yùn)動(dòng),路徑選擇

?沿水平和垂直運(yùn)動(dòng)的公式:

求a到b的最短路徑,只能沿水平或垂直方向移動(dòng),,路徑規(guī)劃算法,python,A star,路徑規(guī)劃,機(jī)器人運(yùn)動(dòng),路徑選擇

將對角線、水平和垂直運(yùn)動(dòng)組合構(gòu)成的對角距離公式

求a到b的最短路徑,只能沿水平或垂直方向移動(dòng),,路徑規(guī)劃算法,python,A star,路徑規(guī)劃,機(jī)器人運(yùn)動(dòng),路徑選擇


下面對三種啟發(fā)函數(shù)做實(shí)驗(yàn),其中圖中黃色方格節(jié)點(diǎn)為尋徑起始點(diǎn),紅色方格節(jié)點(diǎn)為尋徑終點(diǎn)??瞻讌^(qū)域?yàn)榭尚凶甙踩珔^(qū),深紅色連續(xù)方格節(jié)點(diǎn)為不可通行障礙物區(qū)域。

圖中藍(lán)色曲線為從起始點(diǎn)到目標(biāo)點(diǎn)搜索的路徑,而路徑周圍黃色的方格節(jié)點(diǎn)代表在路徑搜索過程中添加到 open list 列表的節(jié)點(diǎn)。根據(jù)上述三種路徑搜索對比可知,在無障礙物情況下曼哈頓距離和對角距離運(yùn)行情況相對較好,而歐式距離搜索出的路徑不夠平滑;在存在障礙物情況下曼哈頓距離搜索路徑較平滑,歐式距離和對角距離在搜索過程中產(chǎn)生了大量的搜索節(jié)點(diǎn),搜索路徑出現(xiàn)較多的轉(zhuǎn)折點(diǎn),運(yùn)行時(shí)間較長。?

綜上所知,在 A*算法中選擇曼哈頓啟發(fā)函數(shù)不僅能減少搜索節(jié)點(diǎn)數(shù),還能能到相對平滑路徑。

求a到b的最短路徑,只能沿水平或垂直方向移動(dòng),,路徑規(guī)劃算法,python,A star,路徑規(guī)劃,機(jī)器人運(yùn)動(dòng),路徑選擇

求a到b的最短路徑,只能沿水平或垂直方向移動(dòng),,路徑規(guī)劃算法,python,A star,路徑規(guī)劃,機(jī)器人運(yùn)動(dòng),路徑選擇

求a到b的最短路徑,只能沿水平或垂直方向移動(dòng),,路徑規(guī)劃算法,python,A star,路徑規(guī)劃,機(jī)器人運(yùn)動(dòng),路徑選擇

求a到b的最短路徑,只能沿水平或垂直方向移動(dòng),,路徑規(guī)劃算法,python,A star,路徑規(guī)劃,機(jī)器人運(yùn)動(dòng),路徑選擇


3. 代碼實(shí)現(xiàn)

3.1 算法基本步驟

(1)設(shè)置 open list 列表和 close list 列表,將起始點(diǎn)存放 open list 列表中,此時(shí) close list 列表為空

(2)取出 open list 列表中 f 值最小的節(jié)點(diǎn) P 作為當(dāng)前節(jié)點(diǎn),并進(jìn)行以下操作:判斷當(dāng)前節(jié)點(diǎn) P 是否為目標(biāo)點(diǎn) end,如果點(diǎn) P 為目標(biāo)點(diǎn)尋徑結(jié)束,將目標(biāo)點(diǎn)end 的父節(jié)點(diǎn)設(shè)置為節(jié)點(diǎn) P,然后返回由目標(biāo)節(jié)點(diǎn)逆序倒推其父節(jié)點(diǎn)至起始點(diǎn)的所有節(jié)點(diǎn)組成的路徑。如果不是目標(biāo)點(diǎn),將當(dāng)前節(jié)點(diǎn) P 加入到 close list 列表中并從 open list 列表刪除,執(zhí)行步驟(3);?

(3)算法遍歷當(dāng)前節(jié)點(diǎn) P 的相鄰節(jié)點(diǎn) P',并進(jìn)行以下操作;?

(4)如果相鄰節(jié)點(diǎn) p' 不在 open list 列表中,計(jì)算 g、h 值,設(shè)置相鄰節(jié)點(diǎn) P' 的父節(jié)點(diǎn)設(shè)置為節(jié)點(diǎn) P,最后將節(jié)點(diǎn) P' 存放到 open list 列表中;?

(5)如果相鄰節(jié)點(diǎn) P' 是不可行區(qū)域或在 close list 列表中,則不做任何處理;

(6)如果相鄰節(jié)點(diǎn) P' 已在 open list 列表中,計(jì)算經(jīng)由當(dāng)前節(jié)點(diǎn) P 到達(dá)鄰節(jié)點(diǎn) P' 的 g 值是否比鄰節(jié)點(diǎn) P' 此時(shí)的 g 值更小,如果更小,則將相鄰節(jié)點(diǎn) P' 的 g 值更新為從當(dāng)前節(jié)點(diǎn) P 到相鄰節(jié)點(diǎn) P' 的 g 值,并將相鄰節(jié)點(diǎn) P' 的父節(jié)點(diǎn)設(shè)置為節(jié)點(diǎn)P;如果不會(huì)更小,則不做任何處理;?

(7)返回步驟(3),繼續(xù)處理余下的相鄰節(jié)點(diǎn);?

(8)判斷 open list 列表是否為空,如果為空,搜索結(jié)束,未找到有效路徑;若非空,執(zhí)行步驟(2)。?

重復(fù)執(zhí)行以上八步,直至找到目標(biāo)點(diǎn)。


3.2 代碼展示

左圖為節(jié)點(diǎn)搜索過程,右圖為最優(yōu)路徑

求a到b的最短路徑,只能沿水平或垂直方向移動(dòng),,路徑規(guī)劃算法,python,A star,路徑規(guī)劃,機(jī)器人運(yùn)動(dòng),路徑選擇

完整代碼如下,注釋很全,有問題在評論區(qū)留言文章來源地址http://www.zghlxwxcb.cn/news/detail-779617.html

import math
import matplotlib.pyplot as plt
min_set = 10
show_animation = True  # 繪圖

# 創(chuàng)建一個(gè)類
class Dijkstra:
    # 初始化
    def __init__(self, ox, oy, resolution, robot_radius):
        # 屬性分配
        self.min_x = None
        self.min_y = None
        self.max_x = None
        self.max_y = None
        self.x_width = None
        self.y_width = None
        self.obstacle_map = None
        
        self.resolution = resolution  # 網(wǎng)格大小(m)
        self.robot_radius = robot_radius  # 
        self.calc_obstacle_map(ox, oy)  # 繪制柵格地圖
        self.motion = self.get_motion_model()  # 機(jī)器人運(yùn)動(dòng)方式

    # 構(gòu)建節(jié)點(diǎn),每個(gè)網(wǎng)格代表一個(gè)節(jié)點(diǎn)
    class Node:
        def __init__(self, x, y, cost, parent_index):
            self.x = x  # 網(wǎng)格索引
            self.y = y
            self.cost = cost  # 路徑值
            self.parent_index = parent_index  # 該網(wǎng)格的父節(jié)點(diǎn)
        def __str__(self):
            return str(self.x) + ',' + str(self.y) + ',' + str(self.cost) + ',' + str(self.parent_index)

    # 尋找最優(yōu)路徑,網(wǎng)格起始坐標(biāo)(sx,sy),終點(diǎn)坐標(biāo)(gx,gy)
    def planning(self, sx, sy, gx, gy):
        # 節(jié)點(diǎn)初始化
        # 將已知的起點(diǎn)和終點(diǎn)坐標(biāo)形式轉(zhuǎn)化為節(jié)點(diǎn)類型,0代表路徑權(quán)重,-1代表無父節(jié)點(diǎn)
        start_node = self.Node(self.calc_xy_index(sx, self.min_x),
                               self.calc_xy_index(sy, self.min_y), 0.0, -1)
        # 終點(diǎn)
        goal_node = self.Node(self.calc_xy_index(gx, self.min_x),
                              self.calc_xy_index(gy, self.min_y), 0.0, -1)
        # 保存入庫節(jié)點(diǎn)和待計(jì)算節(jié)點(diǎn)
        open_set, closed_set = dict(), dict()
        # 先將起點(diǎn)入庫,獲取每個(gè)網(wǎng)格對應(yīng)的key
        open_set[self.calc_index(start_node)] = start_node

        # 循環(huán)
        while 1:
            # 選擇擴(kuò)展點(diǎn),添加了啟發(fā)項(xiàng),f(n)= g(n) + h(n)
            c_id = min(open_set, 
                       key=lambda o: open_set[o].cost + \
                           self.calc_heuristic(goal_node, open_set[o]))

            current = open_set[c_id]  # 從字典中取出該節(jié)點(diǎn)

            # 繪圖
            if show_animation:
                # 網(wǎng)格索引轉(zhuǎn)換為真實(shí)坐標(biāo)
                plt.plot(self.calc_position(current.x, self.min_x),
                         self.calc_position(current.y, self.min_y), 'xc')
                plt.pause(0.0001)
            
            # 判斷是否是終點(diǎn),如果選出來的損失最小的點(diǎn)是終點(diǎn)
            if current.x == goal_node.x and current.y == goal_node.y:
                # 更新終點(diǎn)的父節(jié)點(diǎn)
                goal_node.cost = current.cost
                # 更新終點(diǎn)的損失
                goal_node.parent_index = current.parent_index
                break
            
            # 在外庫中刪除該最小損失點(diǎn),把它入庫
            del open_set[c_id]
            closed_set[c_id] = current

            # 遍歷鄰接節(jié)點(diǎn)
            for move_x, move_y, move_cost in self.motion:
                # 獲取每個(gè)鄰接節(jié)點(diǎn)的節(jié)點(diǎn)坐標(biāo),到起點(diǎn)的距離,父節(jié)點(diǎn)
                node = self.Node(current.x + move_x,
                                 current.y + move_y, 
                                 current.cost + move_cost, c_id)
                # 獲取該鄰居節(jié)點(diǎn)的key
                n_id = self.calc_index(node)

                # 如果該節(jié)點(diǎn)入庫了,就看下一個(gè)
                if n_id in closed_set:
                    continue
                
                # 鄰居節(jié)點(diǎn)是否超出范圍了,是否在障礙物上
                if not self.verify_node(node):
                    continue

                # 如果該節(jié)點(diǎn)不在外庫中,就作為一個(gè)新節(jié)點(diǎn)加入到外庫
                if n_id not in open_set:
                    open_set[n_id] = node
                # 節(jié)點(diǎn)在外庫中時(shí)
                else:
                    # 如果該點(diǎn)到起點(diǎn)的距離,要小于外庫中該點(diǎn)的距離,就更新外庫中的該點(diǎn)信息,更改路徑
                    if node.cost <= open_set[n_id].cost:
                        open_set[n_id] = node
            
        # 找到終點(diǎn)
        rx, ry = self.calc_final_path(goal_node, closed_set)
        return rx, ry

    # ------------------------------ #
    # A* 的啟發(fā)函數(shù)
    # ------------------------------ #
    @staticmethod
    def calc_heuristic(n1, n2):  # n1終點(diǎn),n2當(dāng)前網(wǎng)格
        w = 1.0  # 單個(gè)啟發(fā)函數(shù)的權(quán)重,如果有多個(gè)啟發(fā)函數(shù),權(quán)重可以設(shè)置的不一樣
        d = w * math.hypot(n1.x-n2.x, n1.y-n2.y)  # 當(dāng)前網(wǎng)格和終點(diǎn)距離
        return d

    # 機(jī)器人行走的方式,每次能向周圍移動(dòng)8個(gè)網(wǎng)格移動(dòng)
    @staticmethod
    def get_motion_model():
        # [dx, dy, cost]
        motion = [[1,0,1],  # 右
                  [0,1,1],  # 上
                  [-1,0,1], # 左
                  [0,-1,1], # 下
                  [-1,-1,math.sqrt(2)], # 左下
                  [-1,1,math.sqrt(2)], # 左上
                  [1,-1,math.sqrt(2)], # 右下
                  [1,1,math.sqrt(2)]]  # 右上
        return motion

    # 繪制柵格地圖
    def calc_obstacle_map(self, ox, oy):
        # 地圖邊界坐標(biāo)
        self.min_x = round(min(ox))  # 四舍五入取整
        self.min_y = round(min(oy)) 
        self.max_x = round(max(ox))
        self.max_y = round(max(oy))
        # 地圖的x和y方向的柵格個(gè)數(shù),長度/每個(gè)網(wǎng)格的長度=網(wǎng)格個(gè)數(shù)
        self.x_width = round((self.max_x-self.min_x)/self.resolution)  # x方向網(wǎng)格個(gè)數(shù)
        self.y_width = round((self.max_y-self.min_y)/self.resolution)  # y方向網(wǎng)格個(gè)數(shù)
        # 初始化地圖,二維列表,每個(gè)網(wǎng)格的值為False
        self.obstacle_map = [[False for _ in range(self.y_width)]
                             for _ in range(self.x_width)]
        # 設(shè)置障礙物
        for ix in range(self.x_width):  # 遍歷x方向的網(wǎng)格 [0:x_width]
            x = self.calc_position(ix, self.min_x)   # 根據(jù)網(wǎng)格索引計(jì)算x坐標(biāo)位置
            for iy in range(self.y_width):  # 遍歷y方向的網(wǎng)格 [0:y_width]
                y = self.calc_position(iy, self.min_y)  # 根據(jù)網(wǎng)格索引計(jì)算y坐標(biāo)位置
                # 遍歷障礙物坐標(biāo)(實(shí)際坐標(biāo))
                for iox, ioy in zip(ox, oy):
                    # 計(jì)算障礙物和網(wǎng)格點(diǎn)之間的距離
                    d = math.hypot(iox-x, ioy-y)
                    # 膨脹障礙物,如果障礙物和網(wǎng)格之間的距離小,機(jī)器人無法通行,對障礙物膨脹
                    if d <= self.robot_radius:
                        # 將障礙物所在網(wǎng)格設(shè)置為True
                        self.obstacle_map[ix][iy] = True
                        break  # 每個(gè)障礙物膨脹一次就足夠了

    # 根據(jù)網(wǎng)格編號計(jì)算實(shí)際坐標(biāo)
    def calc_position(self, index, minp):
        # minp代表起點(diǎn)坐標(biāo),左下x或左下y
        pos = minp + index * self.resolution  # 網(wǎng)格點(diǎn)左下左下坐標(biāo)
        return pos

    # 位置坐標(biāo)轉(zhuǎn)為網(wǎng)格坐標(biāo)
    def calc_xy_index(self, position, minp):
        # (目標(biāo)位置坐標(biāo)-起點(diǎn)坐標(biāo))/一個(gè)網(wǎng)格的長度==>目標(biāo)位置的網(wǎng)格索引
        return round((position-minp) / self.resolution)

    # 給每個(gè)網(wǎng)格編號,得到每個(gè)網(wǎng)格的key
    def calc_index(self, node):
        # 從左到右增大,從下到上增大
        return node.y * self.x_width + node.x

    # 鄰居節(jié)點(diǎn)是否超出范圍
    def verify_node(self, node):
        # 根據(jù)網(wǎng)格坐標(biāo)計(jì)算實(shí)際坐標(biāo)
        px = self.calc_position(node.x, self.min_x)
        py = self.calc_position(node.y, self.min_y)
        # 判斷是否超出邊界
        if px < self.min_x:
            return False
        if py < self.min_y:
            return False
        if px >= self.max_x:
            return False
        if py >= self.max_y:
            return False
        # 節(jié)點(diǎn)是否在障礙物上,障礙物標(biāo)記為True
        if self.obstacle_map[node.x][node.y]:
            return False
        # 沒超過就返回True
        return True


    # 計(jì)算路徑, parent屬性記錄每個(gè)節(jié)點(diǎn)的父節(jié)點(diǎn)
    def calc_final_path(self, goal_node, closed_set):
        # 先存放終點(diǎn)坐標(biāo)(真實(shí)坐標(biāo))
        rx = [self.calc_position(goal_node.x, self.min_x)]
        ry = [self.calc_position(goal_node.y, self.min_y)]
        # 獲取終點(diǎn)的父節(jié)點(diǎn)索引
        parent_index = goal_node.parent_index
        # 起點(diǎn)的父節(jié)點(diǎn)==-1 
        while parent_index != -1:
            n = closed_set[parent_index]  # 在入庫中選擇父節(jié)點(diǎn)
            rx.append(self.calc_position(n.x, self.min_x))  # 節(jié)點(diǎn)的x坐標(biāo)
            ry.append(self.calc_position(n.y, self.min_y))  # 節(jié)點(diǎn)的y坐標(biāo)
            parent_index = n.parent_index  # 節(jié)點(diǎn)的父節(jié)點(diǎn)索引

        return rx, ry


def main():
    # 設(shè)置起點(diǎn)和終點(diǎn)
    sx = -5.0
    sy = -5.0
    gx = 50.0
    gy = 50.0
    # 網(wǎng)格大小
    grid_size = 2.0
    # 機(jī)器人半徑
    robot_radius = 1.0 

    # 設(shè)置障礙物位置
    ox, oy = [], []
    for i in range(-10,60):    ox.append(i); oy.append(-10.0)  # 下邊界
    for i in range(-10,60):    ox.append(60.0); oy.append(i)  # 右邊界
    for i in range(-10,61):    ox.append(i); oy.append(60.0)  # 上邊界
    for i in range(-10,61):    ox.append(-10.0); oy.append(i)  # 左邊界
    for i in range(-10,40):    ox.append(20.0); oy.append(i)  # 左圍欄
    for i in range(0,40):      ox.append(40.0); oy.append(60-i)  # 右圍欄

    # 繪圖
    if show_animation:
        plt.plot(ox, oy, '.k')  # 障礙物黑色
        plt.plot(sx, sy, 'og')  # 起點(diǎn)綠色
        plt.plot(gx, gy, 'xb')  # 終點(diǎn)藍(lán)色
        plt.grid(True)
        plt.axis('equal')  # 坐標(biāo)軸刻度間距等長

    # 實(shí)例化,傳入障礙物,網(wǎng)格大小
    dijkstra = Dijkstra(ox, oy, grid_size, robot_radius)
    # 求解路徑,返回路徑的 x 坐標(biāo)和 y 坐標(biāo)列表
    rx, ry = dijkstra.planning(sx, sy, gx, gy)

    # 繪制路徑經(jīng)過的網(wǎng)格
    if show_animation:
        plt.plot(rx, ry, '-r')
        plt.pause(0.01)
        plt.show()

if __name__ == '__main__':
    main()

到了這里,關(guān)于【路徑規(guī)劃】(2) A* 算法求解最短路,附python完整代碼的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包