|
| 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() |
0 commit comments