Skip to content

Commit 9786fd4

Browse files
RRT with a goal approach added
1 parent 2f0f2a6 commit 9786fd4

File tree

1 file changed

+49
-22
lines changed

1 file changed

+49
-22
lines changed

RRT.py

Lines changed: 49 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,16 @@
33
import math
44
import numpy as np
55
import argparse
6+
import time
7+
import sys
68

79
# Command line arguments
810
parser = argparse.ArgumentParser(description='Implements the RRT algorithm.')
911
parser.add_argument('-o', '--obstacles', type=bool, action=argparse.BooleanOptionalAction, metavar='', required=False, help='Obstacles on the map')
1012
parser.add_argument('-n', '--nodes', type=int, metavar='', required=False, help='Maximum number of nodes')
1113
parser.add_argument('-e', '--epsilon', type=float, metavar='', required=False, help='Step size')
14+
parser.add_argument('-init', '--x_init', nargs='+', type=int, metavar='', required=False, help='Initial node position in x and y respectively')
15+
parser.add_argument('-goal', '--x_goal', nargs='+', type=int, metavar='', required=False, help='Goal node position in x and y respectively')
1216
parser.add_argument('-srn', '--show_random_nodes', type=bool, action=argparse.BooleanOptionalAction, metavar='', required=False, help='Show random nodes on screen')
1317
parser.add_argument('-snn', '--show_new_nodes', type=bool, action=argparse.BooleanOptionalAction, metavar='', required=False, help='Show new nodes on screen')
1418
args = parser.parse_args()
@@ -17,7 +21,7 @@
1721
WIDTH, HEIGHT = 640, 480
1822
WINDOW = pygame.display.set_mode(size=(WIDTH, HEIGHT))
1923
pygame.display.set_caption('RRT')
20-
FPS = 0.1
24+
FPS = 60
2125

2226
# Colors
2327
WHITE = (255, 255, 255)
@@ -28,15 +32,8 @@
2832
BROWN = (189, 154, 122)
2933

3034
# RRT parameters
31-
if not args.nodes == None:
32-
MAX_NODES = args.nodes
33-
else:
34-
MAX_NODES = 5000 # Default maximum number of nodes/vertices
35-
36-
if not args.epsilon == None:
37-
EPSILON = args.epsilon
38-
else:
39-
EPSILON = 7.0 # Default step size
35+
MAX_NODES = args.nodes if not args.nodes is None else 5000 # Default maximum number of nodes/vertices
36+
EPSILON = args.epsilon if not args.epsilon is None else 7.0 # Default step size
4037

4138
def draw_window():
4239
"""Draw the window all white."""
@@ -55,10 +52,12 @@ def draw_obstacles():
5552
All the rectangle obstacles.
5653
"""
5754
obstacles = []
58-
obstacle1 = pygame.Rect((WIDTH//2 + 10, HEIGHT//2 - 45, 90, 90))
59-
obstacle2 = pygame.Rect((WIDTH//2 - 100, HEIGHT//2 - 45, 90, 90))
55+
obstacle1 = pygame.Rect((WIDTH//2 + 90, HEIGHT//2 - 45, 90, 90))
56+
obstacle2 = pygame.Rect((WIDTH//2 - 180, HEIGHT//2 - 45, 90, 90))
6057
pygame.draw.rect(surface=WINDOW, color=RED, rect=obstacle1)
6158
pygame.draw.rect(surface=WINDOW, color=RED, rect=obstacle2)
59+
60+
# Just decoration borders in black
6261
pygame.draw.rect(surface=WINDOW, color=BLACK, rect=obstacle1, width=2)
6362
pygame.draw.rect(surface=WINDOW, color=BLACK, rect=obstacle2, width=2)
6463

@@ -160,7 +159,7 @@ def nearest_neighbor(tree, x_rand):
160159

161160
return x_near
162161

163-
def new_state(x_rand, x_near):
162+
def new_state(x_rand, x_near, x_goal):
164163
"""Advances a small step (EPSILON) towards the random node.
165164
166165
Takes small step (EPSILON) from the nearest node to the
@@ -174,20 +173,30 @@ def new_state(x_rand, x_near):
174173
Coordinate of the random node generated.
175174
x_near : tuple
176175
Coordinate of the nearest neighbor node.
176+
x_goal : tuple
177+
Coordinate of the goal node.
177178
178179
Returns
179180
-------
180181
tuple
181182
Coordinate of the new node generated between the nearest
182183
and random nodes.
183184
"""
185+
global is_goal_reached
186+
184187
if euclidean_distance(x_near, x_rand) < EPSILON:
188+
if abs(x_rand[0] - x_goal[0]) < EPSILON and abs(x_rand[1] - x_goal[1]) < EPSILON: # Check if goal is reached
189+
is_goal_reached = True
190+
185191
# Keep that shortest distance from x_near to x_rand
186192
return x_rand
187193
else:
188194
px, py = x_rand[0] - x_near[0], x_rand[1] - x_near[1]
189195
theta = math.atan2(py, px)
190-
x_new = x_near[0] + EPSILON*math.cos(theta), x_near[1] + EPSILON*math.sin(theta)
196+
x_new = x_near[0] + EPSILON*math.cos(theta), x_near[1] + EPSILON*math.sin(theta)
197+
198+
if abs(x_new[0] - x_goal[0]) < EPSILON and abs(x_new[1] - x_goal[1]) < EPSILON: # Check if goal is reached
199+
is_goal_reached = True
191200

192201
return x_new
193202

@@ -211,20 +220,29 @@ def generate_parents(values, parent):
211220
parent : list
212221
Ordered collection of the parents.
213222
"""
214-
parent_value = values[min_distance] # Value neares node
223+
parent_value = values[min_distance] # Value nearest node
215224
parent_index = len(parent) # Used to be the index of the parent list
216225
parent.insert(parent_index, parent_value)
217226

227+
if is_goal_reached:
228+
# Insert in the very last index the last value recorded plus one
229+
parent.insert(parent_index+1, values[-1]+1)
230+
218231
return parent
219232

220233

221234
def main(has_obstacles, show_random_nodes, show_new_nodes):
235+
global is_goal_reached
236+
222237
clock = pygame.time.Clock()
223238
run = True
239+
is_goal_reached = False
240+
is_simulation_finished = False
224241
tree = [] # Tree list containing all the nodes/vertices
225-
parent = [] # Parent list of each each node/vertex
242+
parent = [] # Parent list of each each node/vertex
226243
values = [] # Values list of each node/vertex
227-
x_init = WINDOW.get_rect().center # Initial node
244+
x_init = args.x_init if not args.x_init is None else WINDOW.get_rect().center # Initial node
245+
x_goal = args.x_goal if not args.x_goal is None else (540, 380) # Goal node
228246
tree.append(x_init) # Append initial node
229247
parent.append(0) # Append initial parent
230248
draw_window()
@@ -243,13 +261,14 @@ def main(has_obstacles, show_random_nodes, show_new_nodes):
243261

244262
x_rand = generate_random_node() # Random node
245263
x_near = nearest_neighbor(tree, x_rand) # Nearest neighbor to the random node
246-
x_new = new_state(x_rand, x_near) # New node
264+
x_new = new_state(x_rand, x_near, x_goal) # New node
247265
tree.append(x_new)
248266

249267
# Draw points and lines to the visualization
250268
pygame.draw.circle(surface=WINDOW, color=BLUE, center=x_init, radius=3)
269+
pygame.draw.circle(surface=WINDOW, color=RED, center=x_goal, radius=3)
251270

252-
if has_obstacles:
271+
if has_obstacles and not is_simulation_finished:
253272
collision_free = is_free(point=x_new, obstacles=obstacles, tree=tree) # Check collision
254273
if collision_free:
255274
# Append current node value and place it in the parent list
@@ -262,8 +281,12 @@ def main(has_obstacles, show_random_nodes, show_new_nodes):
262281
pygame.draw.circle(surface=WINDOW, color=BROWN, center=x_new, radius=2)
263282

264283
pygame.draw.line(surface=WINDOW, color=BLACK, start_pos=x_near, end_pos=x_new)
265-
node_value += 1 # Increment value for the next randomly generated node
266-
else:
284+
node_value += 1 # Increment the value for the next randomly generated node
285+
286+
if is_goal_reached:
287+
pygame.draw.line(surface=WINDOW, color=BLACK, start_pos=x_new, end_pos=x_goal)
288+
is_simulation_finished = True
289+
elif not is_simulation_finished:
267290
# Append current node value and place it in the parent list
268291
values.append(node_value)
269292
parent = generate_parents(values, parent)
@@ -276,11 +299,15 @@ def main(has_obstacles, show_random_nodes, show_new_nodes):
276299
pygame.draw.line(surface=WINDOW, color=BLACK, start_pos=x_near, end_pos=x_new)
277300
node_value += 1 # Increment value for the next randomly generated node
278301

302+
if is_goal_reached:
303+
pygame.draw.line(surface=WINDOW, color=BLACK, start_pos=x_new, end_pos=x_goal)
304+
is_simulation_finished = True
305+
279306
pygame.display.update()
280-
281307
k += 1
282308

283309
pygame.quit()
310+
sys.exit()
284311

285312
if __name__ == '__main__':
286313
main(has_obstacles=args.obstacles, show_random_nodes=args.show_random_nodes, show_new_nodes=args.show_new_nodes)

0 commit comments

Comments
 (0)