您當前的位置:首頁 > 攝影

A*演算法Matlab演示程式碼

作者:由 肥貓大師 發表于 攝影時間:2021-01-18

演示效果:

A*演算法Matlab演示程式碼

程式碼:

% 參考文獻1《A星演算法詳解(個人認為最詳細,最通俗易懂的一個版本)》https://blog。csdn。net/hitwhylz/article/details/23089415

% 參考文獻2《A*演算法中啟發函式H的選取》https://www。jianshu。com/p/63e68b7daade

clear

clc

close

all

global

start_point

end_point

current_point

ValueSet

row

=

32

clm

=

32

NewPoint

=

@(

a

b

struct

‘x’

a

‘y’

b

);

SetKeyStr

=

@(

x

y

string

num2str

([

x

y

],

‘%03d’

));

InvalidKeyStr

=

000000

NewSearchPoint

=

@(

a

b

struct

‘key’

SetKeyStr

a

b

),

‘x’

a

‘y’

b

‘G’

0

‘H’

0

‘F’

0

‘parent_key’

InvalidKeyStr

);

HType

=

3

%啟發式搜尋代價函式型別

% 各類值設定(同樣用於染色)

ValueSet

=

struct

‘passable’

255

‘impassable’

0

‘openlist’

180

‘closelist’

120

‘start’

60

‘target’

60

‘current’

30

‘path’

60

);

% map中的值設定

map

=

ones

row

clm

*

ValueSet

passable

map

1

:),

map

end

:),

map

(:,

1

),

map

(:,

end

)]

=

deal

ValueSet

impassable

);

map

5

1

10

),

map

1

6

18

),

map

10

9

24

),

map

13

17

13

),

map

15

20

end

),

map

17

20

5

),

map

20

5

20

),

map

24

1

15

),

map

23

25

20

),

map

28

18

27

)]

=

deal

ValueSet

impassable

);

start_point

end_point

=

deal

NewPoint

3

3

),

NewPoint

30

23

));

%起始/結束點座標

map

start_point

x

start_point

y

),

map

end_point

x

end_point

y

)]

=

deal

ValueSet

start

ValueSet

target

);

% 搜尋點(周圍8個)分別為dx dy 以及移動代價(實際為sqrt(dx*dx+dy*dy))

SearchDxy

=

-

1

-

1

sqrt

2

);

0

-

1

1

1

-

1

sqrt

2

);

-

1

0

1

1

0

1

-

1

1

sqrt

2

);

0

1

1

1

1

sqrt

2

)];

% 1。起始點加入open_list

open_list

1

=

NewSearchPoint

start_point

x

start_point

y

);

% 初始狀態設定

open_list

1

)。

H

=

CalcH

start_point

x

start_point

y

end_point

x

end_point

y

HType

);

open_list

1

)。

F

=

open_list

H

open_list

=

struct2table

open_list

);

%待確定代價的點

close_list

=

[];

%已確定代價的點

current_point

=

open_list

%當前點(設定為初始點)

figure

b_find_path

=

0

% 是否發現路徑

while

~

isempty

open_list

%2。遍歷open_list,找到最小合代價F點

index_min_open_list_F

=

SearchOptimalPoint

open_list

close_list

current_point

end_point

);

current_point

=

open_list

index_min_open_list_F

:);

%最小代價F的點選中為當前點,進行後續open_list選取

open_list

index_min_open_list_F

:)

=

[];

%在open_list中將其刪除

close_list

=

close_list

current_point

];

%將其加入close_list

map

current_point

x

current_point

y

=

ValueSet

closelist

%將新加入的close_list點標記(染色)

DrawMap

map

);

%繪圖

%3。檢查是否符合退出條件

if

current_point

x

==

end_point

x

&&

current_point

y

==

end_point

y

b_find_path

=

true

break

end

%4。 檢查當前點周圍可移動點,並加入open_list中

for

search_dxy

=

SearchDxy

search_point

=

NewSearchPoint

current_point

x

+

search_dxy

1

),

current_point

y

+

search_dxy

2

));

key

=

SetKeyStr

search_point

x

search_point

y

);

% 4。1如果它是不可抵達的或者它在 close list 中,忽略它

if

search_point

x

<

=

0

||

search_point

y

<

=

0

||

map

search_point

x

search_point

y

==

ValueSet

impassable

||

map

search_point

x

search_point

y

==

ValueSet

closelist

continue

end

search_point

=

struct2table

search_point

);

search_point

G

=

current_point

G

+

search_dxy

3

);

%移動代價

search_point

H

=

CalcH

search_point

x

search_point

y

end_point

x

end_point

y

HType

);

%估算成本

search_point

F

=

search_point

G

+

search_point

H

search_point

parent_key

=

current_point

key

index_existed_in_openlist

=

find

open_list

key

==

key

1

);

%判定當前open_list中是否存在該搜尋點

% 4。2如果它不在 open list 中,把它加入 open list ,並且把當前方格設定為它的父親,記錄該方格的 F , G 和 H 值

if

map

search_point

x

search_point

y

~=

ValueSet

openlist

open_list

=

open_list

search_point

];

map

search_point

x

search_point

y

=

ValueSet

openlist

%將新加入的open_list點標記(染色)

else

% 4。3如果它已經在 open list 中,檢查這條路徑 ( 即經由當前方格到達它那裡 ) 是否更好,用 G 值作參考。更小的 G 值表示這是更好的路徑。如果是這樣,把它的父親設定為當前方格,並重新計算它的 G 和 F 值。e

if

search_point

G

<

open_list

G

index_existed_in_openlist

%若open_list中存在值的G值更大,表示由當前點到達該值更優,將原本儲存點的資訊替換為當前搜尋點資訊

open_list

index_existed_in_openlist

:)

=

search_point

% 進行替換

end

end

end

end

% 如果發現路徑,則按照parent資訊回溯路徑結果

if

b_find_path

%找到路徑

path

=

close_list

end

:);

path_step_count

=

1

map

path

x

1

),

path

y

1

))

=

ValueSet

path

while

path

parent_key

path_step_count

~=

InvalidKeyStr

path_step_count

=

path_step_count

+

1

index_parent

=

find

close_list

key

==

path

parent_key

path_step_count

-

1

),

1

);

path

path_step_count

:)

=

close_list

index_parent

:);

map

path

x

path_step_count

),

path

y

path_step_count

))

=

ValueSet

path

end

DrawMap

map

);

%繪圖

else

disp

’未找到有效路徑!‘

);

end

disp

([

’openlist數量: ‘

num2str

height

open_list

)),

’, closelist數量: ‘

num2str

height

close_list

)),

’, 總代價: ‘

num2str

path

G

1

),

’%3。2f‘

)])

%% 估算代價計算

% 參考文章《A*演算法中啟發函式H的選取》

% h_diagonal = 沿著對角線移動的步數, h_straight = 曼哈頓距離,

% 透過考慮所有的對角線移動的步數(每步耗散D2)以及剩下的直線移動的步數(每步耗散D)將這兩者結合在一起。

function

H

=

CalcH

x1, y1, x2, y2, type

if

nargin

<

5

type

=

3

end

dx

=

x2

-

x1

dy

=

y2

-

y1

switch

type

case

1

H

=

sqrt

dx

*

dx

+

dy

*

dy

);

%歐式距離 乘以係數可以加快搜索距離,但可能造成無解情況

case

2

H

=

abs

dx

+

abs

dy

);

%曼哈頓距離

case

3

h_diagonal

=

min

abs

dx

),

abs

dy

));

h_straight

=

abs

dx

+

abs

dy

);

H

=

sqrt

2

*

h_diagonal

+

h_straight

-

2

*

h_diagonal

);

%可沿對角移動時的代價函式

case

4

H

=

0

%Dijkstra演算法

end

end

%% 繪製map圖

function

DrawMap

map

global

start_point

end_point

current_point

ValueSet

% 注意這裡對map的操作只是為了顯示效果,不會影響到主函式內的map,

map

start_point

x

start_point

y

),

map

end_point

x

end_point

y

),

map

current_point

x

current_point

y

)]

=

deal

ValueSet

start

ValueSet

target

ValueSet

current

);

imagesc

map

% 注意用plot和imagesc的區別,這裡加了一個轉置

set

gca

‘XDir’

‘normal’

‘YDir’

‘normal’

);

%如果不加normal是直接顯示A的結構

pause

0。0001

);

end

%% 搜尋最小代價點

function

index_min_open_list_F

=

SearchOptimalPoint

open_list, close_list, current_point, end_point

index_min_open_list_F

=

find

open_list

F

==

min

open_list

F

));

%找到最小代價index

if

length

index_min_open_list_F

>

1

%如果有多個最小代價值,按一定規則優先選取最優解

if

height

close_list

==

1

%起點時出現,則優先選取同起始/結束連線夾角最接近者

index_min_dyaw_end

=

FindMinDyaw

current_point

end_point

current_point

open_list

index_min_open_list_F

:),

1

);

index_min_open_list_F

=

index_min_open_list_F

index_min_dyaw_end

);

else

% 否則找到與上一刻方向最接近的點

index_last

=

find

close_list

key

==

current_point

parent_key

1

);

last_point

=

close_list

index_last

:);

index_min_dyaw_last

=

FindMinDyaw

last_point

current_point

current_point

open_list

index_min_open_list_F

:));

index_min_open_list_F

=

index_min_open_list_F

index_min_dyaw_last

);

% 如果還有多個結果,優先選取同當前/結束連線夾角最接近者

if

length

index_min_open_list_F

>

1

index_min_dyaw_end

=

FindMinDyaw

current_point

end_point

current_point

open_list

index_min_open_list_F

:),

1

);

index_min_open_list_F

=

index_min_open_list_F

index_min_dyaw_end

);

end

end

end

end

%% 從候選點中選取與目標方向最接近的點

function

index_min_dyaw

=

FindMinDyaw

base_point_start, base_point_end, candidate_point_start, candidate_point_end, b_output_single

if

nargin

<

5

%是否只輸出唯一值

b_output_single

=

false

end

end_yaw

=

atan2

base_point_end

y

-

base_point_start

y

base_point_end

x

-

base_point_start

x

);

open_list_yaw

=

atan2

candidate_point_end

y

-

candidate_point_start

y

candidate_point_end

x

-

candidate_point_start

x

);

dyaw

=

abs

LimitInPi

open_list_yaw

-

end_yaw

));

if

~

b_output_single

index_min_dyaw

=

find

dyaw

==

min

dyaw

));

else

index_min_dyaw

=

find

dyaw

==

min

dyaw

),

1

‘last’

);

end

end

%% 功能:將輸入角度範圍限制在+-pi以內

function

angle

=

LimitInPi

angle

% 輸入:弧度

% 輸出:限制在+-pi以內的弧度

angle

=

mod

angle

2

*

pi

);

% 對2pi取餘

kk

=

find

abs

angle

>

pi

);

if

~

isempty

kk

angle

kk

=

angle

kk

-

sign

angle

kk

))

*

2

*

pi

end

end

標簽: point  list  open  map  end