Skip to content

Commit 79ca3fe

Browse files
authored
Merge pull request #40 from guilyx/feature/bidirectional-astar
Feature: Bidirectional A*
2 parents 18c873a + 8a15854 commit 79ca3fe

8 files changed

Lines changed: 634 additions & 0 deletions

File tree

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ Python sample codes and documents about Autonomous vehicle control algorithm. Th
2222
* [NDT Map Construction](#ndt-map-construction)
2323
* [Path Planning](#path-planning)
2424
* [A*](#a)
25+
* [Bidirectional A*](#bidirectional-a)
2526
* [Hybrid A*](#hybrid-a)
2627
* [Dijkstra](#dijkstra)
2728
* [RRT](#rrt)
@@ -113,6 +114,11 @@ Planning
113114
![](src/simulations/path_planning/astar_path_planning/astar_search.gif)
114115
Navigation
115116
![](src/simulations/path_planning/astar_path_planning/astar_navigate.gif)
117+
#### Bidirectional A*
118+
Planning
119+
![](src/simulations/path_planning/astar_bidirectional_path_planning/astar_bidirectional_search.gif)
120+
Navigation
121+
![](src/simulations/path_planning/astar_bidirectional_path_planning/astar_bidirectional_navigate.gif)
116122
#### Hybrid A*
117123
Planning
118124
![](src/simulations/path_planning/astar_hybrid_path_planning/astar_hybrid_search.gif)

src/components/plan/astar_bidirectional/astar_bidirectional_path_planner.py

Lines changed: 461 additions & 0 deletions
Large diffs are not rendered by default.
642 KB
Loading
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
"""
2+
astar_bidirectional_path_planning.py
3+
4+
Author: Auto-generated
5+
"""
6+
7+
# import path setting
8+
import numpy as np
9+
import sys
10+
from pathlib import Path
11+
12+
abs_dir_path = str(Path(__file__).absolute().parent)
13+
relative_path = "/../../../components/"
14+
relative_simulations = "/../../../simulations/"
15+
16+
17+
sys.path.append(abs_dir_path + relative_path + "visualization")
18+
sys.path.append(abs_dir_path + relative_path + "state")
19+
sys.path.append(abs_dir_path + relative_path + "vehicle")
20+
sys.path.append(abs_dir_path + relative_path + "obstacle")
21+
sys.path.append(abs_dir_path + relative_path + "mapping/grid")
22+
sys.path.append(abs_dir_path + relative_path + "course/cubic_spline_course")
23+
sys.path.append(abs_dir_path + relative_path + "control/pure_pursuit")
24+
sys.path.append(abs_dir_path + relative_path + "plan/astar_bidirectional")
25+
26+
27+
# import component modules
28+
from global_xy_visualizer import GlobalXYVisualizer
29+
from min_max import MinMax
30+
from time_parameters import TimeParameters
31+
from vehicle_specification import VehicleSpecification
32+
from state import State
33+
from four_wheels_vehicle import FourWheelsVehicle
34+
from obstacle import Obstacle
35+
from obstacle_list import ObstacleList
36+
from cubic_spline_course import CubicSplineCourse
37+
from pure_pursuit_controller import PurePursuitController
38+
from astar_bidirectional_path_planner import AStarBidirectionalPathPlanner
39+
from binary_occupancy_grid import BinaryOccupancyGrid
40+
import json
41+
42+
43+
# flag to show plot figure
44+
# when executed as unit test, this flag is set as false
45+
show_plot = True
46+
47+
48+
def main():
49+
"""
50+
Main process function
51+
"""
52+
53+
# set simulation parameters
54+
x_lim, y_lim = MinMax(-5, 55), MinMax(-20, 25)
55+
navigation_gif_path = (
56+
abs_dir_path
57+
+ relative_simulations
58+
+ "path_planning/astar_bidirectional_path_planning/astar_bidirectional_navigate.gif"
59+
)
60+
map_path = (
61+
abs_dir_path
62+
+ relative_simulations
63+
+ "path_planning/astar_bidirectional_path_planning/map.json"
64+
)
65+
path_filename = (
66+
abs_dir_path
67+
+ relative_simulations
68+
+ "path_planning/astar_bidirectional_path_planning/path.json"
69+
)
70+
search_gif_path = (
71+
abs_dir_path
72+
+ relative_simulations
73+
+ "path_planning/astar_bidirectional_path_planning/astar_bidirectional_search.gif"
74+
)
75+
76+
vis = GlobalXYVisualizer(
77+
x_lim,
78+
y_lim,
79+
TimeParameters(span_sec=25),
80+
show_zoom=False,
81+
gif_name=navigation_gif_path,
82+
)
83+
occ_grid = BinaryOccupancyGrid(
84+
x_lim, y_lim, resolution=0.5, clearance=1.5, map_path=map_path
85+
)
86+
87+
obst_list = ObstacleList()
88+
# Map for bidirectional A*: obstacles funnel both searches toward the middle.
89+
# Start (0,0) and Goal (50,-10); meeting point ~(25, -5). Bidir expands fewer nodes.
90+
# Left half: block direct path from start, force flow toward center
91+
obst_list.add_obstacle(Obstacle(State(x_m=12.0, y_m=-12.0), length_m=8, width_m=2))
92+
obst_list.add_obstacle(Obstacle(State(x_m=10.0, y_m=6.0), length_m=6, width_m=9))
93+
# Right half: block direct path from goal, force flow toward center
94+
obst_list.add_obstacle(Obstacle(State(x_m=42.0, y_m=4.0), length_m=8, width_m=9))
95+
obst_list.add_obstacle(Obstacle(State(x_m=42.0, y_m=-14.0), length_m=6, width_m=5))
96+
# Central corridor stays clear so forward and backward meet in the middle
97+
obst_list.add_obstacle(Obstacle(State(x_m=25.0, y_m=10.0), length_m=10, width_m=8))
98+
obst_list.add_obstacle(Obstacle(State(x_m=25.0, y_m=-16.0), length_m=10, width_m=3))
99+
100+
vis.add_object(obst_list)
101+
occ_grid.add_object(obst_list)
102+
occ_grid.save_map()
103+
# Easy Goal = (50,22)
104+
# Hard Goal = (50,-10)
105+
planner = AStarBidirectionalPathPlanner(
106+
(53, -15),
107+
(0, 0),
108+
map_path,
109+
weight=5.0,
110+
x_lim=x_lim,
111+
y_lim=y_lim,
112+
path_filename=path_filename,
113+
gif_name=search_gif_path,
114+
)
115+
116+
# Load sparse path from json file
117+
with open(path_filename, "r") as f:
118+
sparse_path = json.load(f)
119+
120+
# Extract x and y coordinates
121+
sparse_x = [point[0] for point in sparse_path]
122+
sparse_y = [point[1] for point in sparse_path]
123+
124+
# Use with CubicSplineCourse
125+
course = CubicSplineCourse(sparse_x, sparse_y, 20)
126+
vis.add_object(course)
127+
128+
# create vehicle instance
129+
spec = VehicleSpecification()
130+
pure_pursuit = PurePursuitController(spec, course)
131+
vehicle = FourWheelsVehicle(
132+
State(color=spec.color), spec, controller=pure_pursuit, show_zoom=False
133+
)
134+
135+
vis.add_object(vehicle)
136+
137+
# plot figure is not shown when executed as unit test
138+
if not show_plot:
139+
vis.not_show_plot()
140+
141+
# show plot figure
142+
vis.draw()
143+
144+
145+
# execute main process
146+
if __name__ == "__main__":
147+
main()
333 KB
Loading

src/simulations/path_planning/astar_bidirectional_path_planning/map.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[[53.0, -9.0], [50.5, -7.0], [47.5, -7.0], [44.5, -7.0], [41.5, -7.0], [38.5, -7.0], [35.5, -7.0], [33.0, -9.0], [30.0, -9.0], [27.0, -9.0], [24.5, -9.0], [21.5, -9.0], [18.5, -8.5], [15.5, -8.5], [12.5, -8.5], [9.5, -8.5], [6.5, -8.5], [3.5, -6.0], [2.0, -3.0], [0.0, 0.0]]
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
"""
2+
Test of Bidirectional A* path planning and navigation simulation
3+
4+
Author: Auto-generated
5+
"""
6+
7+
from pathlib import Path
8+
import sys
9+
import pytest
10+
11+
sys.path.append(str(Path(__file__).absolute().parent) + "/../src/simulations/path_planning/astar_bidirectional_path_planning")
12+
import astar_bidirectional_path_planning
13+
14+
15+
def test_simulation():
16+
astar_bidirectional_path_planning.show_plot = False
17+
18+
astar_bidirectional_path_planning.main()

0 commit comments

Comments
 (0)