Skip to content

Commit 73f8f0e

Browse files
committed
roll back RRT and update parking_planning
1 parent f021b81 commit 73f8f0e

12 files changed

Lines changed: 507 additions & 554 deletions

GEMstack/knowledge/defaults/computation_graph.yaml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,15 @@ components:
4343
- mission_planning: # added by summoning team
4444
inputs: all
4545
outputs: [mission, task]
46-
- parking_planning: # added by summoning team
46+
- parking_type_planning: # added by summoning team
4747
inputs: all
4848
outputs: intent
49-
- parking_trajectory_planning: # added by summoning team
49+
- parking_planning: # added by summoning team
5050
inputs: all
51-
outputs: [trajectory, intent, mission]
52-
- leave_parking_trajectory_planning: # added by summoning team
51+
outputs: [route, intent]
52+
- leave_parking_planning: # added by summoning team
5353
inputs: all
54-
outputs: [trajectory, intent, mission]
54+
outputs: [route, intent]
5555
- route_planning:
5656
inputs: all
5757
outputs: [route, mission]

GEMstack/onboard/planning/RRT.py

Lines changed: 102 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44
import random
55
import math
66

7-
DEBUG = False
8-
97
class Obstacle:
108
def __init__(self,x=0,y=0,r=0.2):
119
self.x = x
@@ -20,52 +18,100 @@ def __init__(self, x=0, y=0, heading = None):
2018
self.parent = None
2119
self.cost = float('inf') # Cost to reach this node
2220

21+
OFFSET = 0.8 # meter
22+
23+
OBSTACLE_LIST = []
24+
25+
# return euclidean distance between two point/obstacle
26+
def distance(a,b):
27+
return math.sqrt(math.pow(a.x-b.x,2) + math.pow(a.y-b.y,2))
28+
29+
# return angel within -pi to pi
30+
def angle_norm(angle):
31+
return (angle + math.pi) % (2 * math.pi) - math.pi
32+
33+
# return absolute value of angle difference within 0 to pi
34+
def angle_diff(a,b):
35+
a = angle_norm(a)
36+
b = angle_norm(b)
37+
diff = a - b
38+
return abs(angle_norm(diff))
39+
40+
# return the angle in oppsite direction
41+
def angle_inverse(angle):
42+
angle = angle_norm(angle)
43+
if angle < 0:
44+
return angle + math.pi
45+
return angle-math.pi
46+
47+
def is_valid(point):
48+
for obstacle in OBSTACLE_LIST:
49+
if distance(point, obstacle) < obstacle.radius + OFFSET:
50+
return False
51+
return True
52+
53+
# return the nearest point in the tree
54+
def Nearest(tree,sample_p):
55+
min = 10000000
56+
nearest_p = None
57+
for point in tree:
58+
d = distance(point,sample_p)
59+
if d < min:
60+
min = d
61+
nearest_p = point
62+
return nearest_p
63+
64+
# calculate the point heading based on parent point
65+
def heading(parent,p2):
66+
delta = np.array([p2.x,p2.y]) - np.array([parent.x,parent.y])
67+
return math.atan2(delta[1],delta[0])
68+
69+
# create a point that is one step size away from nearest point toward the sample point
70+
def LocalPlanner(nearest_p,sample_p, step_size=0.5):
71+
dist = distance(nearest_p,sample_p)
72+
if dist < step_size:
73+
return sample_p
74+
direction = np.array([sample_p.x,sample_p.y]) - np.array([nearest_p.x,nearest_p.y])
75+
delta = (direction / dist) * step_size
76+
new_p = Point()
77+
new_p.x = nearest_p.x + delta[0]
78+
new_p.y = nearest_p.y + delta[1]
79+
new_p.parent = nearest_p
80+
new_p.cost = dist
81+
return new_p
82+
2383
class BiRRT:
24-
def __init__(self, start : list, goal : list, obstacles : list, MAP_SIZE : list):
84+
def __init__(self, start : list, goal : list, obstacles : list, map : list):
2585

2686
self.path = []
2787
self.tree_from_start = []
2888
self.tree_from_end = []
2989

30-
# start position (current vehicle position)
3190
self.start_point = Point(x = start[0],y = start[1],heading = start[2])
91+
self.end_point = Point(x = goal[0],y = goal[1],heading = goal[2])
3292

33-
# desire position (reverse heading for building tree)
34-
# (will revert back after route found)
35-
self.end_point = Point(x = goal[0],y = goal[1],heading = self.angle_inverse(goal[2]))
36-
37-
# obstacles and map boundary
38-
self.OBSTACLE_LIST = []
93+
OBSTACLE_LIST = []
3994
for i in range(len(obstacles)):
40-
self.OBSTACLE_LIST.append(Obstacle(obstacles[i][0], obstacles[i][1], r = 0.2))
41-
42-
# min distace of vehicle center to obstacle
43-
# should be roughly 1/2 of vehicle width
44-
self.OFFSET = 0.8 # meter
95+
OBSTACLE_LIST.append(Obstacle(obstacles[i][0], obstacles[i][1], r = 0.2))
4596

46-
# max iteration size for performing route search
4797
self.MAX_Iteration = 20000
48-
49-
# step size for local planner
5098
self.step_size = 0.5 # meter
51-
52-
# radius for determine neighbor node
5399
self.search_r = 1.3 # meter
54-
55-
# angle limit for vehicle turning per step size
56100
self.heading_limit = math.pi/6 # limit the heading change in route
101+
self.goal_sample_rate = 0.1 # rate to check area near end-goal
57102

58103
# Map boundary
59-
self.MAP_X_LOW = MAP_SIZE[0] # meter
60-
self.MAP_X_HIGH = MAP_SIZE[1] # meter
61-
self.MAP_Y_LOW = MAP_SIZE[2] # meter
62-
self.MAP_Y_HIGH = MAP_SIZE[3] # meter
104+
self.MAP_X_LOW = map[0] # meter
105+
self.MAP_X_HIGH = map[1] # meter
106+
self.MAP_Y_LOW = map[2] # meter
107+
self.MAP_Y_HIGH = map[3] # meter
63108

64109
def search(self):
65110
# initialize two tree
66111
self.tree_from_start.append(self.start_point)
67112
self.tree_from_end.append(self.end_point)
68113

114+
# self.start_time = time.time()
69115
# perform search within max number of iterration
70116
for iterration in range(self.MAX_Iteration):
71117
# uniformly sample a point within in the map
@@ -81,34 +127,33 @@ def search(self):
81127
tree_a = self.tree_from_end
82128
tree_b = self.tree_from_start
83129
Direction = "backward"
84-
85-
if DEBUG:
86-
print(Direction + " AT {} Interation".format(iterration))
130+
131+
print(Direction + " AT {} Interation".format(iterration))
87132
# find nearest point in the tree
88-
nearest_point_a = self.Nearest(tree_a, sample_p)
133+
nearest_point_a = Nearest(tree_a, sample_p)
89134
# use local planner to move one step size
90-
new_p = self.LocalPlanner(nearest_point_a, sample_p, self.step_size)
135+
new_p = LocalPlanner(nearest_point_a, sample_p, self.step_size)
91136
# check collision
92-
if not self.is_valid(new_p):
137+
if not is_valid(new_p):
93138
continue
94139
# check if there exist previous point with less cost to new point
95140
neighbor_points = self.Neighbors(new_p,tree_a)
96-
min_cost = nearest_point_a.cost + self.distance(new_p,nearest_point_a)
141+
min_cost = nearest_point_a.cost + distance(new_p,nearest_point_a)
97142
parent_p = nearest_point_a
98143
for point in neighbor_points:
99-
curr_cost = point.cost + self.distance(point, new_p)
144+
curr_cost = point.cost + distance(point, new_p)
100145
if curr_cost < min_cost:
101146
min_cost = curr_cost
102147
parent_p = point
103148
# update point's paraent
104149
new_p.cost = min_cost
105150
new_p.parent = parent_p
106-
new_p.heading = self.heading(parent_p,new_p)
151+
new_p.heading = heading(parent_p,new_p)
107152

108153
# check heading limit and collision
109-
if self.angle_diff(new_p.heading,new_p.parent.heading) > (self.heading_limit):
154+
if angle_diff(new_p.heading,new_p.parent.heading) > (self.heading_limit):
110155
continue
111-
if not self.is_valid(new_p):
156+
if not is_valid(new_p):
112157
continue
113158

114159
# point is valid, add to tree
@@ -118,43 +163,43 @@ def search(self):
118163
for point in neighbor_points:
119164
if point == parent_p:
120165
continue
121-
if new_p.cost + self.distance(new_p,point) < point.cost:
166+
if new_p.cost + distance(new_p,point) < point.cost:
122167
# check heading limit
123-
if self.angle_diff(new_p.heading,point.heading) > (self.heading_limit):
168+
if angle_diff(new_p.heading,point.heading) > (self.heading_limit):
124169
continue
125-
if self.angle_diff(new_p.heading,self.heading(new_p,point)) > (self.heading_limit):
170+
if angle_diff(new_p.heading,heading(new_p,point)) > (self.heading_limit):
126171
continue
127-
if self.angle_diff(point.heading,self.heading(new_p,point)) > (self.heading_limit):
172+
if angle_diff(point.heading,heading(new_p,point)) > (self.heading_limit):
128173
continue
129174
point.parent = new_p
130-
point.cost = new_p.cost + self.distance(new_p, point)
131-
point.heading = self.heading(new_p,point)
175+
point.cost = new_p.cost + distance(new_p, point)
176+
point.heading = heading(new_p,point)
132177

133178
# find nearest point in another tree
134-
nearest_point_b = self.Nearest(tree_b, new_p)
179+
nearest_point_b = Nearest(tree_b, new_p)
135180

136181
# check if two tree can be connected
137-
if self.distance(new_p,nearest_point_b) > self.step_size:
182+
if distance(new_p,nearest_point_b) > self.step_size:
138183
continue
139184
# check heading limit
140-
if self.angle_diff(new_p.heading,self.angle_inverse(nearest_point_b.heading)) > (self.heading_limit):
185+
if angle_diff(new_p.heading,angle_inverse(nearest_point_b.heading)) > (self.heading_limit):
141186
continue
142-
if self.angle_diff(new_p.heading,self.heading(new_p,nearest_point_b)) > (self.heading_limit):
187+
if angle_diff(new_p.heading,heading(new_p,nearest_point_b)) > (self.heading_limit):
143188
continue
144-
if self.angle_diff(nearest_point_b.heading,self.heading(nearest_point_b,new_p)) > (self.heading_limit):
189+
if angle_diff(nearest_point_b.heading,heading(nearest_point_b,new_p)) > (self.heading_limit):
145190
continue
146191

147192
# check if there exist another point that can connect two tree with less cost
148193
neighbor_points = self.Neighbors(new_p,tree_b)
149-
min_cost = new_p.cost + nearest_point_b.cost + self.distance(new_p,nearest_point_a)
194+
min_cost = new_p.cost + nearest_point_b.cost + distance(new_p,nearest_point_a)
150195
for point in neighbor_points:
151-
curr_cost = new_p.cost + point.cost + self.distance(point, new_p)
196+
curr_cost = new_p.cost + point.cost + distance(point, new_p)
152197
if curr_cost < min_cost:
153-
if self.angle_diff(new_p.heading,self.angle_inverse(point.heading)) > (self.heading_limit):
198+
if angle_diff(new_p.heading,angle_inverse(point.heading)) > (self.heading_limit):
154199
continue
155-
if self.angle_diff(new_p.heading,self.heading(new_p,point)) > (self.heading_limit):
200+
if angle_diff(new_p.heading,heading(new_p,point)) > (self.heading_limit):
156201
continue
157-
if self.angle_diff(point.heading,self.heading(point,new_p)) > (self.heading_limit):
202+
if angle_diff(point.heading,heading(point,new_p)) > (self.heading_limit):
158203
continue
159204
min_cost = curr_cost
160205
nearest_point_b = point
@@ -170,7 +215,7 @@ def search(self):
170215
def Neighbors(self,sample_p,tree):
171216
neighbor_points = []
172217
for point in tree:
173-
if self.distance(point, sample_p) <= self.search_r:
218+
if distance(point, sample_p) <= self.search_r:
174219
neighbor_points.append(point)
175220
return neighbor_points
176221

@@ -185,70 +230,11 @@ def trace_path(self,point_a,point_b):
185230
point_b = point_temp
186231

187232
while point_a is not None:
188-
path_start.append([point_a.x,point_a.y,point_a.heading])
233+
path_start.append(point_a)
189234
point_a = point_a.parent
190235
while point_b is not None:
191-
point_b.heading = self.angle_inverse(point_b.heading)
192-
path_end.append([point_b.x,point_b.y,point_b.heading])
236+
point_b.heading = angle_inverse(point_b.heading)
237+
path_end.append(point_b)
193238
point_b = point_b.parent
194239

195240
self.path = path_start[::-1] + path_end
196-
197-
# return euclidean distance between two point/obstacle
198-
def distance(self,a,b):
199-
return math.sqrt(math.pow(a.x-b.x,2) + math.pow(a.y-b.y,2))
200-
201-
# return angel within -pi to pi
202-
def angle_norm(self,angle):
203-
return (angle + math.pi) % (2 * math.pi) - math.pi
204-
205-
# return absolute value of angle difference within 0 to pi
206-
def angle_diff(self,a,b):
207-
a = self.angle_norm(a)
208-
b = self.angle_norm(b)
209-
diff = a - b
210-
return abs(self.angle_norm(diff))
211-
212-
# return the angle in oppsite direction
213-
def angle_inverse(self,angle):
214-
angle = self.angle_norm(angle)
215-
if angle < 0:
216-
return angle + math.pi
217-
return angle-math.pi
218-
219-
# check if the point/move is collision free
220-
def is_valid(self,point):
221-
for obstacle in self.OBSTACLE_LIST:
222-
if self.distance(point, obstacle) < obstacle.radius + self.OFFSET:
223-
return False
224-
return True
225-
226-
# return the nearest point in the tree
227-
def Nearest(self,tree,sample_p):
228-
min = 10000000
229-
nearest_p = None
230-
for point in tree:
231-
d = self.distance(point,sample_p)
232-
if d < min:
233-
min = d
234-
nearest_p = point
235-
return nearest_p
236-
237-
# calculate the point heading based on parent point
238-
def heading(self,parent,p2):
239-
delta = np.array([p2.x,p2.y]) - np.array([parent.x,parent.y])
240-
return math.atan2(delta[1],delta[0])
241-
242-
# create a point that is one step size away from nearest point toward the sample point
243-
def LocalPlanner(self,nearest_p,sample_p, step_size=0.5):
244-
dist = self.distance(nearest_p,sample_p)
245-
if dist < step_size:
246-
return sample_p
247-
direction = np.array([sample_p.x,sample_p.y]) - np.array([nearest_p.x,nearest_p.y])
248-
delta = (direction / dist) * step_size
249-
new_p = Point()
250-
new_p.x = nearest_p.x + delta[0]
251-
new_p.y = nearest_p.y + delta[1]
252-
new_p.parent = nearest_p
253-
new_p.cost = dist
254-
return new_p

0 commit comments

Comments
 (0)