Skip to content

Commit ad80b6c

Browse files
committed
Some basic test cases for astar and parking.
1 parent 5fad281 commit ad80b6c

2 files changed

Lines changed: 203 additions & 7 deletions

File tree

testing/test_astar.py

Lines changed: 110 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,118 @@
88
import matplotlib.pyplot as plt
99
import numpy as np
1010

11-
def test_astar_planning():
12-
heuristic = lambda x,y: np.linalg.norm(np.array(x)-np.array(y))
13-
test_configs = ((0,0,0), (5,5,0)) #start and goal configurations
11+
def plot_path(start_config, goal_config, path=None):
12+
"""Helper function to visualize the path"""
13+
plt.figure(figsize=(8, 8))
14+
15+
# Plot start and goal
16+
plt.plot(start_config[0], start_config[1], 'go', markersize=10, label='Start')
17+
plt.plot(goal_config[0], goal_config[1], 'ro', markersize=10, label='Goal')
18+
19+
# Plot path if available
20+
if path:
21+
path = np.array(path)
22+
plt.plot(path[:, 0], path[:, 1], 'b.-', label='Path')
23+
24+
plt.grid(True)
25+
plt.axis('equal')
26+
plt.legend()
27+
plt.title('A* Path Planning Test')
28+
plt.xlabel('X (meters)')
29+
plt.ylabel('Y (meters)')
30+
plt.show()
1431

15-
planner = Astar(None, None, heuristic)
32+
def euclidean_heuristic(current, goal):
33+
"""Simple Euclidean distance heuristic"""
34+
return np.linalg.norm(np.array(current) - np.array(goal))
1635

17-
test_traj = planner(*test_configs)
18-
print(test_traj)
36+
def test_straight_line():
37+
"""Test 1: Simple straight line path"""
38+
print("\nTest 1: Straight Line Path")
39+
start = (0, 0, 0)
40+
goal = (5, 0, 0)
41+
42+
planner = Astar(start, goal, euclidean_heuristic)
43+
path = planner(start, goal)
44+
45+
assert path is not False, "Planner failed to find path"
46+
assert len(path) > 0, "Path is empty"
47+
48+
print("Path found:", path)
49+
plot_path(start, goal, path)
50+
return path
1951

52+
def test_diagonal_path():
53+
"""Test 2: Diagonal path"""
54+
print("\nTest 2: Diagonal Path")
55+
start = (0, 0, 0)
56+
goal = (3, 3, 0)
57+
58+
planner = Astar(start, goal, euclidean_heuristic)
59+
path = planner(start, goal)
60+
61+
assert path is not False, "Planner failed to find path"
62+
assert len(path) > 0, "Path is empty"
63+
64+
print("Path found:", path)
65+
plot_path(start, goal, path)
66+
return path
67+
68+
def test_path_length():
69+
"""Test 3: Verify path length is reasonable"""
70+
print("\nTest 3: Path Length Test")
71+
start = (0, 0, 0)
72+
goal = (2, 2, 0)
73+
74+
planner = Astar(start, goal, euclidean_heuristic)
75+
path = planner(start, goal)
76+
77+
# Check if path exists
78+
assert path is not False, "Planner failed to find path"
79+
80+
# Check if path length is reasonable
81+
path_length = 0
82+
for i in range(len(path)-1):
83+
path_length += euclidean_heuristic(path[i], path[i+1])
84+
85+
# Path length should be close to the direct distance
86+
direct_distance = euclidean_heuristic(start, goal)
87+
assert path_length <= direct_distance * 1.5, "Path is too long"
88+
89+
print(f"Path length: {path_length:.2f}")
90+
print(f"Direct distance: {direct_distance:.2f}")
91+
plot_path(start, goal, path)
92+
return path
93+
94+
def test_start_goal_same():
95+
"""Test 4: Start and goal at same position"""
96+
print("\nTest 4: Start and Goal Same Position")
97+
start = (1, 1, 0)
98+
goal = (1, 1, 0)
99+
100+
planner = Astar(start, goal, euclidean_heuristic)
101+
path = planner(start, goal)
102+
103+
assert path is not False, "Planner failed to find path"
104+
assert len(path) > 0, "Path is empty"
105+
assert path[0] == start and path[-1] == goal, "Path should contain at least start/goal"
106+
107+
print("Path found:", path)
108+
plot_path(start, goal, path)
109+
return path
110+
111+
def run_all_tests():
112+
"""Run all test cases"""
113+
try:
114+
test_straight_line()
115+
test_diagonal_path()
116+
test_path_length()
117+
test_start_goal_same()
118+
print("\nAll tests passed successfully!")
119+
except AssertionError as e:
120+
print(f"\nTest failed: {str(e)}")
121+
except Exception as e:
122+
print(f"\nUnexpected error: {str(e)}")
20123

21124
if __name__ == '__main__':
22-
test_astar_planning()
125+
run_all_tests()

testing/test_parallel_parking.py

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import sys
2+
import os
3+
sys.path.append(os.getcwd())
4+
5+
from GEMstack.state import Path, ObjectFrameEnum
6+
from GEMstack.onboard.planning.hybrid_astar import Astar
7+
import matplotlib.pyplot as plt
8+
import numpy as np
9+
10+
def plot_parking_scenario(start_config, goal_config, path=None, obstacles=None):
11+
"""
12+
Visualize the parking scenario including start position, goal position, obstacles, and path
13+
"""
14+
plt.figure(figsize=(10, 6))
15+
16+
# Plot start position
17+
plt.plot(start_config[0], start_config[1], 'go', markersize=10, label='Start')
18+
plt.arrow(start_config[0], start_config[1],
19+
np.cos(start_config[2]), np.sin(start_config[2]),
20+
head_width=0.1, color='g')
21+
22+
# Plot goal position
23+
plt.plot(goal_config[0], goal_config[1], 'ro', markersize=10, label='Goal')
24+
plt.arrow(goal_config[0], goal_config[1],
25+
np.cos(goal_config[2]), np.sin(goal_config[2]),
26+
head_width=0.1, color='r')
27+
28+
# Plot obstacles if provided
29+
if obstacles is not None:
30+
for obs in obstacles:
31+
plt.plot(obs[0], obs[1], 'ks', markersize=20)
32+
33+
# Plot path if provided
34+
if path is not None:
35+
path = np.array(path)
36+
plt.plot(path[:, 0], path[:, 1], 'b-', label='Planned Path')
37+
38+
plt.grid(True)
39+
plt.axis('equal')
40+
plt.legend()
41+
plt.title('Parallel Parking Scenario')
42+
plt.xlabel('X (meters)')
43+
plt.ylabel('Y (meters)')
44+
plt.show()
45+
46+
def euclidean_distance_heuristic(current, goal):
47+
"""
48+
Calculate Euclidean distance between current and goal configurations
49+
Also considers heading difference as part of the heuristic
50+
"""
51+
pos_distance = np.linalg.norm(np.array(current[:2]) - np.array(goal[:2]))
52+
angle_diff = abs(current[2] - goal[2])
53+
angle_diff = min(angle_diff, 2*np.pi - angle_diff)
54+
55+
# Weight for combining position and angle differences
56+
angle_weight = 0.5
57+
return pos_distance + angle_weight * angle_diff
58+
59+
def test_parallel_parking():
60+
# Define start and goal configurations [x, y, heading]
61+
# Start: Vehicle is parallel to the road
62+
start_config = (0, 0, 0) # (x=0, y=0, heading=0 radians)
63+
64+
# Goal: Vehicle is in the parking spot
65+
goal_config = (-2, -2, -np.pi/2) # (x=-2, y=-2, heading=-90 degrees)
66+
67+
# Create obstacles representing parked cars
68+
obstacles = [
69+
(-2, 0), # Car in front of parking spot
70+
(-2, -4) # Car behind parking spot
71+
]
72+
73+
# Initialize planner
74+
planner = Astar(start_config, goal_config, euclidean_distance_heuristic)
75+
76+
# Run the planner
77+
path = planner(start_config, goal_config)
78+
79+
if path:
80+
print("Path found successfully!")
81+
print("Path points:", path)
82+
83+
# Visualize the scenario and solution
84+
plot_parking_scenario(start_config, goal_config, path, obstacles)
85+
else:
86+
print("No valid path found!")
87+
88+
def main():
89+
print("Testing Hybrid A* Parallel Parking Planner...")
90+
test_parallel_parking()
91+
92+
if __name__ == '__main__':
93+
main()

0 commit comments

Comments
 (0)