heyoujue commited on
Commit
0dbe5a4
·
1 Parent(s): 365dfe6

show both plots at the same time

Browse files
flight_environment.py CHANGED
@@ -150,7 +150,7 @@ class FlightEnvironment:
150
  ax.scatter(xs[0], ys[0], zs[0], s=40)
151
  ax.scatter(xs[-1], ys[-1], zs[-1], s=40)
152
  self.set_axes_equal(ax)
153
- plt.show()
154
 
155
 
156
  def set_axes_equal(self,ax):
 
150
  ax.scatter(xs[0], ys[0], zs[0], s=40)
151
  ax.scatter(xs[-1], ys[-1], zs[-1], s=40)
152
  self.set_axes_equal(ax)
153
+ plt.show(block=False)
154
 
155
 
156
  def set_axes_equal(self,ax):
main.py CHANGED
@@ -1,9 +1,9 @@
1
  from flight_environment import FlightEnvironment
2
- from planners.rrt_planner import rrt_planner
3
  from planners.trajectory_generator import plan_trajectory_through_path, plot_trajectory
4
  from plot_plotly import plot_cylinders
5
 
6
- env = FlightEnvironment(50)
7
  start = (1,2,0)
8
  goal = (18,18,3)
9
 
@@ -20,12 +20,13 @@ goal = (18,18,3)
20
  path = rrt_planner(env, start, goal, step_size=1)
21
 
22
  # --------------------------------------------------------------------------------------------------- #
 
23
 
24
- # Matplotlib (laggy)
25
  plot_cylinders(env, path)
26
 
27
- # Plotly
28
- # env.plot_cylinders(path)
29
 
30
  # --------------------------------------------------------------------------------------------------- #
31
  # Call your trajectory planning algorithm here. The algorithm should
 
1
  from flight_environment import FlightEnvironment
2
+ from planners.path_planner import rrt_planner
3
  from planners.trajectory_generator import plan_trajectory_through_path, plot_trajectory
4
  from plot_plotly import plot_cylinders
5
 
6
+ env = FlightEnvironment(200)
7
  start = (1,2,0)
8
  goal = (18,18,3)
9
 
 
20
  path = rrt_planner(env, start, goal, step_size=1)
21
 
22
  # --------------------------------------------------------------------------------------------------- #
23
+ # 3D env plot, choose one - Plotly or Matplotlib - comment the other
24
 
25
+ # Plotly
26
  plot_cylinders(env, path)
27
 
28
+ # Matplotlib (laggy)
29
+ #env.plot_cylinders(path)
30
 
31
  # --------------------------------------------------------------------------------------------------- #
32
  # Call your trajectory planning algorithm here. The algorithm should
planners/path_planner.py CHANGED
@@ -1,12 +1,99 @@
1
- """
2
- In this file, you should implement your own path planning class or function.
3
- Within your implementation, you may call `env.is_collide()` and `env.is_outside()`
4
- to verify whether candidate path points collide with obstacles or exceed the
5
- environment boundaries.
6
-
7
- You are required to write the path planning algorithm by yourself. Copying or calling
8
- any existing path planning algorithms from others is strictly
9
- prohibited. Please avoid using external packages beyond common Python libraries
10
- such as `numpy`, `math`, or `scipy`. If you must use additional packages, you
11
- must clearly explain the reason in your report.
12
- """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from dataclasses import dataclass
2
+ import numpy as np
3
+ import time
4
+
5
+ def is_segment_collision_free(env, p1, p2, step=0.1):
6
+ """Return True if straight segment p1->p2 is free.
7
+ - env: FlightEnvironment instance
8
+ - p1,p2: iterable (x,y,z)
9
+ - step: distance between samples along the segment (meters)
10
+ """
11
+ dist = np.linalg.norm(p2 - p1)
12
+ if dist == 0:
13
+ return not env.is_collide(tuple(p1)) and not env.is_collide(tuple(p1))
14
+ n = max(1, int(np.ceil(dist / step)))
15
+ for i in range(n + 1):
16
+ t = i / n
17
+ p = p1 * (1 - t) + p2 * t
18
+ if env.is_outside(tuple(p)) or env.is_collide(tuple(p)):
19
+ return False
20
+ return True
21
+
22
+ def rrt_planner(env, start, goal, max_iters=10000, step_size=1.0, goal_tolerance=0.8, goal_sample_rate=0.1):
23
+ """
24
+ Basic RRT planner in continuous 3D space.
25
+ Returns a path as an (N x 3) numpy array from start to goal (inclusive).
26
+ """
27
+ start = np.array(start, dtype=float)
28
+ goal = np.array(goal, dtype=float)
29
+
30
+ # quick checks
31
+ if env.is_outside(tuple(start)) or env.is_collide(tuple(start)):
32
+ raise RuntimeError("Start is invalid (outside or in collision).")
33
+ if env.is_outside(tuple(goal)) or env.is_collide(tuple(goal)):
34
+ raise RuntimeError("Goal is invalid (outside or in collision).")
35
+
36
+ # recorded statistics stored here, can be inspected later
37
+ stats = dict(collisions=0)
38
+ tstart = time.time()
39
+
40
+ @dataclass
41
+ class Node:
42
+ point: np.ndarray
43
+ parent: np.ndarray = None
44
+
45
+ # environment bounds
46
+ Xmax, Ymax, Zmax = env.space_size
47
+
48
+ nodes = [Node(start)]
49
+
50
+ for it in range(max_iters):
51
+ # sample random point sometimes, otherwise take goal (->bias)
52
+ if np.random.rand() < goal_sample_rate:
53
+ sample = goal.copy()
54
+ else:
55
+ sample = np.array([np.random.uniform(0, Xmax),
56
+ np.random.uniform(0, Ymax),
57
+ np.random.uniform(0, Zmax)])
58
+ # find nearest node
59
+ dists = [np.linalg.norm(node.point - sample) for node in nodes]
60
+ nearest_idx = int(np.argmin(dists))
61
+ nearest = nodes[nearest_idx]
62
+
63
+ direction = sample - nearest.point
64
+ norm = np.linalg.norm(direction)
65
+ if norm == 0:
66
+ continue
67
+ direction = direction / norm
68
+
69
+ new_point = nearest.point + direction * min(step_size, norm)
70
+
71
+ # ensure within bounds
72
+ if env.is_outside(tuple(new_point)):
73
+ continue
74
+
75
+ # check collision along segment
76
+ if not is_segment_collision_free(env, nearest.point, new_point, step=step_size / 5.0):
77
+ stats["collisions"]+=1
78
+ continue
79
+
80
+ new_node = Node(new_point, nearest)
81
+ nodes.append(new_node)
82
+
83
+ # check if we reached goal
84
+ if np.linalg.norm(new_point - goal) <= goal_tolerance:
85
+ # try connect directly to goal
86
+ if is_segment_collision_free(env, new_point, goal, step=step_size / 5.0):
87
+ goal_node = Node(goal, new_node)
88
+ nodes.append(goal_node)
89
+ # reconstruct path
90
+ path_nodes = []
91
+ cur = goal_node
92
+ while cur is not None:
93
+ path_nodes.append(cur.point)
94
+ cur = cur.parent
95
+ path = np.array(path_nodes[::-1])
96
+ print("reached goal", len(nodes), "nodes", len(path), "waypoints, avoided", stats['collisions'], "collisions", f'{time.time()-tstart:.2f}', "seconds")
97
+ return path
98
+
99
+ raise RuntimeError(f"RRT failed to find a path within the given iterations. {stats=}")
planners/rrt_planner.py DELETED
@@ -1,99 +0,0 @@
1
- from dataclasses import dataclass
2
- import numpy as np
3
- import time
4
-
5
- def is_segment_collision_free(env, p1, p2, step=0.1):
6
- """Return True if straight segment p1->p2 is free.
7
- - env: FlightEnvironment instance
8
- - p1,p2: iterable (x,y,z)
9
- - step: distance between samples along the segment (meters)
10
- """
11
- dist = np.linalg.norm(p2 - p1)
12
- if dist == 0:
13
- return not env.is_collide(tuple(p1)) and not env.is_collide(tuple(p1))
14
- n = max(1, int(np.ceil(dist / step)))
15
- for i in range(n + 1):
16
- t = i / n
17
- p = p1 * (1 - t) + p2 * t
18
- if env.is_outside(tuple(p)) or env.is_collide(tuple(p)):
19
- return False
20
- return True
21
-
22
- def rrt_planner(env, start, goal, max_iters=10000, step_size=1.0, goal_tolerance=0.8, goal_sample_rate=0.1):
23
- """
24
- Basic RRT planner in continuous 3D space.
25
- Returns a path as an (N x 3) numpy array from start to goal (inclusive).
26
- """
27
- start = np.array(start, dtype=float)
28
- goal = np.array(goal, dtype=float)
29
-
30
- # quick checks
31
- if env.is_outside(tuple(start)) or env.is_collide(tuple(start)):
32
- raise RuntimeError("Start is invalid (outside or in collision).")
33
- if env.is_outside(tuple(goal)) or env.is_collide(tuple(goal)):
34
- raise RuntimeError("Goal is invalid (outside or in collision).")
35
-
36
- # recorded statistics stored here, can be inspected later
37
- stats = dict(collisions=0)
38
- tstart = time.time()
39
-
40
- @dataclass
41
- class Node:
42
- point: np.ndarray
43
- parent: np.ndarray = None
44
-
45
- # environment bounds
46
- Xmax, Ymax, Zmax = env.space_size
47
-
48
- nodes = [Node(start)]
49
-
50
- for it in range(max_iters):
51
- # sample random point sometimes, otherwise take goal (->bias)
52
- if np.random.rand() < goal_sample_rate:
53
- sample = goal.copy()
54
- else:
55
- sample = np.array([np.random.uniform(0, Xmax),
56
- np.random.uniform(0, Ymax),
57
- np.random.uniform(0, Zmax)])
58
- # find nearest node
59
- dists = [np.linalg.norm(node.point - sample) for node in nodes]
60
- nearest_idx = int(np.argmin(dists))
61
- nearest = nodes[nearest_idx]
62
-
63
- direction = sample - nearest.point
64
- norm = np.linalg.norm(direction)
65
- if norm == 0:
66
- continue
67
- direction = direction / norm
68
-
69
- new_point = nearest.point + direction * min(step_size, norm)
70
-
71
- # ensure within bounds
72
- if env.is_outside(tuple(new_point)):
73
- continue
74
-
75
- # check collision along segment
76
- if not is_segment_collision_free(env, nearest.point, new_point, step=step_size / 5.0):
77
- stats["collisions"]+=1
78
- continue
79
-
80
- new_node = Node(new_point, nearest)
81
- nodes.append(new_node)
82
-
83
- # check if we reached goal
84
- if np.linalg.norm(new_point - goal) <= goal_tolerance:
85
- # try connect directly to goal
86
- if is_segment_collision_free(env, new_point, goal, step=step_size / 5.0):
87
- goal_node = Node(goal, new_node)
88
- nodes.append(goal_node)
89
- # reconstruct path
90
- path_nodes = []
91
- cur = goal_node
92
- while cur is not None:
93
- path_nodes.append(cur.point)
94
- cur = cur.parent
95
- path = np.array(path_nodes[::-1])
96
- print("reached goal", len(nodes), "nodes", len(path), "waypoints", f'{time.time()-tstart:.2f}', "seconds")
97
- return path
98
-
99
- raise RuntimeError(f"RRT failed to find a path within the given iterations. {stats=}")