diff --git a/README.md b/README.md index be2ba5d..26a7966 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,15 @@ +## Requirements +pip install scikit-fuzzy + +pip install --upgrade numpy + +pip install tensorflow keras gym + +pip install tensorflow or pip install tensorflow==2.10.0 # rrt -Collection of rrt-based algorithms that scale to n-dimensions: +Collection of rrt-based algorithms in 3-dimensions: - rrt -- rrt* (rrt-star) -- rrt* (bidirectional) -- rrt* (bidriectional, lazy shortening) -- rrt connect + Utilizes [R-trees](https://en.wikipedia.org/wiki/R-tree) to improve performance by avoiding point-wise collision-checking and distance-checking. @@ -37,14 +42,8 @@ Assign resolution of edges: ### Examples Visualization examples can be found for rrt and rrt* in both 2 and 3 dimensions. -- [2D RRT](https://plot.ly/~szanlongo/79/plot/) + - [3D RRT](https://plot.ly/~szanlongo/81/plot/) -- [2D RRT*](https://plot.ly/~szanlongo/83/plot/) -- [3D RRT*](https://plot.ly/~szanlongo/89/plot/) -- [2D Bidirectional RRT*](https://plot.ly/~szanlongo/85/plot/) -- [3D Bidirectional RRT*](https://plot.ly/~szanlongo/87/plot/) -- [2D Heuristic Bidirectional RRT*](https://plot.ly/~szanlongo/91/plot/) -- [3D Heuristic Bidirectional RRT*](https://plot.ly/~szanlongo/93/plot/) ## Contributing @@ -54,12 +53,3 @@ Visualization examples can be found for rrt and rrt* in both 2 and 3 dimensions. 4. Push to the branch: `git push origin my-new-feature` 5. Submit a pull request :D -## References - -1. Steven Michael Lavalle. [Planning Algorithms.](https://lavalle.pl/planning/) New York (Ny), Cambridge University Press, 2014, pp. 228–237, lavalle.pl/planning/. -2. LaValle, Steven. "[Rapidly-exploring random trees: A new tool for path planning.](https://msl.cs.uiuc.edu/~lavalle/papers/Lav98c.pdf)" Research Report 9811 (1998). -3. Kuffner, James J., and Steven M. LaValle. "[RRT-connect: An efficient approach to single-query path planning.](https://www.cs.cmu.edu/afs/cs/academic/class/15494-s14/readings/kuffner_icra2000.pdf)" Proceedings 2000 ICRA. Millennium Conference. IEEE International Conference on Robotics and Automation. Symposia Proceedings (Cat. No. 00CH37065). Vol. 2. IEEE, 2000. - -## License - -[MIT License](https://github.com/motion-planning/rrt-algorithms/blob/master/LICENSE) diff --git a/examples/rrt/dqn_model.h5 b/examples/rrt/dqn_model.h5 new file mode 100644 index 0000000..e69de29 diff --git a/examples/rrt/example.h5 b/examples/rrt/example.h5 new file mode 100644 index 0000000..359722e Binary files /dev/null and b/examples/rrt/example.h5 differ diff --git a/examples/rrt/rrt_3d.py b/examples/rrt/rrt_3d.py index 13f6d34..83f418b 100644 --- a/examples/rrt/rrt_3d.py +++ b/examples/rrt/rrt_3d.py @@ -1,18 +1,22 @@ # This file is subject to the terms and conditions defined in # file 'LICENSE', which is part of this source code package. import numpy as np +import sys +sys.path.append('/home/dell/rrt-algorithms') from rrt_algorithms.rrt.rrt import RRT -from rrt_algorithms.search_space.search_space import SearchSpace -from rrt_algorithms.utilities.plotting import Plot +from rrt_algorithms.search_space.search_space0 import SearchSpace +from rrt_algorithms.utilities.plotting0 import Plot + + X_dimensions = np.array([(0, 100), (0, 100), (0, 100)]) # dimensions of Search Space # obstacles Obstacles = np.array( - [(20, 20, 20, 40, 40, 40), (20, 20, 60, 40, 40, 80), (20, 60, 20, 40, 80, 40), (60, 60, 20, 80, 80, 40), + [(10, 10, 10, 15, 15, 15),(20, 20, 20, 30, 30, 30),(30, 30, 30, 35, 35, 35), (1, 2, 6, 4, 4, 8), (20, 60, 20, 25, 65, 25), (60, 60, 20, 80, 80, 40), (60, 20, 20, 80, 40, 40), (60, 20, 60, 80, 40, 80), (20, 60, 60, 40, 80, 80), (60, 60, 60, 80, 80, 80)]) x_init = (0, 0, 0) # starting location -x_goal = (100, 100, 100) # goal location +x_goal = (8, 50, 50) # goal location q = 8 # length of tree edges r = 1 # length of smallest edge to check for intersection with obstacles diff --git a/examples/rrt/rrt_3d_cylinder1.py b/examples/rrt/rrt_3d_cylinder1.py new file mode 100644 index 0000000..ec173d2 --- /dev/null +++ b/examples/rrt/rrt_3d_cylinder1.py @@ -0,0 +1,54 @@ +import numpy as np +from rtree import index # Import the index module from the rtree package +import sys +sys.path.append('/home/dell/rrt-algorithms') + +from rrt_algorithms.rrt.rrt import RRT +from rrt_algorithms.search_space.search_space import SearchSpace +from rrt_algorithms.utilities.plotting import Plot +import matplotlib.pyplot as plt +from mpl_toolkits.mplot3d.art3d import Poly3DCollection +#import numpy as np +# Define the search space dimensions +X_dimensions = np.array([(0, 100), (0, 100), (0, 100)]) + +# Define cylindrical obstacles +obstacles = [ + (10, 82, 0, 85, 15), + (80, 20, 0, 60, 19), + (10, 30, 0, 90, 15), + (80, 80, 0, 70, 22), + (50, 50, 0, 50, 22), # Cylinder at (50, 50) with height 15 along z-axis and radius 5 + ] +# Define initial and goal positions +x_init = (-2, 0, 0) # Starting location +x_goal = (80, 80, 100) # Goal location + +# Define RRT parameters +q = 30 # Length of tree edges +r = 1 # Length of smallest edge to check for intersection with obstacles +max_samples = 1024 # Max number of samples to take before timing out +prc = 0.1 # Probability of checking for a connection to goal + +# Create the search space +X = SearchSpace(X_dimensions, obstacles) +print("Does SearchSpace have obstacle_free method?", hasattr(X, 'obstacle_free')) + +# Create RRT search +rrt = RRT(X, q, x_init, x_goal, max_samples, r, prc) +path = rrt.rrt_search() + +# Plotting setup +plot = Plot("rrt_3d") + + + +# Plot the RRT tree, path, and cylindrical obstacles +plot.plot_tree(X, rrt.trees) +if path is not None: + plot.plot_path(X, path) +plot.plot_obstacles(X, obstacles) # Plot the cylindrical obstacles +plot.plot_start(X, x_init) +plot.plot_goal(X, x_goal) +plot.draw(auto_open=True) + diff --git a/examples/rrt/rrt_3d_cylinder2.py b/examples/rrt/rrt_3d_cylinder2.py new file mode 100644 index 0000000..3e4eab5 --- /dev/null +++ b/examples/rrt/rrt_3d_cylinder2.py @@ -0,0 +1,72 @@ +import numpy as np +from rtree import index # Import the index module from the rtree package +import sys +sys.path.append('/home/dell/rrt-algorithms') + +from rrt_algorithms.rrt.rrt import RRT +from rrt_algorithms.search_space.search_space import SearchSpace +from rrt_algorithms.utilities.plotting import Plot +import matplotlib.pyplot as plt +from mpl_toolkits.mplot3d.art3d import Poly3DCollection + +# Define the search space dimensions +X_dimensions = np.array([(0, 100), (0, 100), (0, 100)]) + +# Define cylindrical obstacles +obstacles = [ + (10, 82, 0, 85, 15), + (80, 20, 0, 60, 19), + (10, 30, 0, 90, 15), + (80, 80, 0, 70, 22), + (50, 50, 0, 50, 22), # Cylinder at (50, 50) with height 15 along z-axis and radius 5 +] + +# Define initial and goal positions +x_init = (-2, 0, 0) # Starting location +x_intermediate = (50, 50, 100) # Intermediate goal location +x_goal = (80, 80, 100) # Final goal location + +# Define RRT parameters +q = 30 # Length of tree edges +r = 1 # Length of smallest edge to check for intersection with obstacles +max_samples = 1024 # Max number of samples to take before timing out +prc = 0.1 # Probability of checking for a connection to goal + +# Create the search space +X = SearchSpace(X_dimensions, obstacles) + +# First RRT search: from x_init to x_intermediate +print("Starting RRT search from initial point to intermediate goal...") +rrt = RRT(X, q, x_init, x_intermediate, max_samples, r, prc) +path1 = rrt.rrt_search() + +# If a path is found to the intermediate goal, continue to the final goal +if path1 is not None: + # Second RRT search: from x_intermediate to x_goal + print("Starting RRT search from intermediate goal to final goal...") + rrt = RRT(X, q, x_intermediate, x_goal, max_samples, r, prc) + path2 = rrt.rrt_search() + + # Combine the two paths + if path2 is not None: + path = path1 + path2[1:] # Combine paths, avoiding duplicate point at x_intermediate + else: + print("Could not find a path to the final goal.") + path = path1 # Use only the first path +else: + print("Could not find a path to the intermediate goal.") + path = None + +# Plotting setup +plot = Plot("rrt_3d") + +# Plot the RRT tree, path, and cylindrical obstacles +plot.plot_tree(X, rrt.trees) +if path is not None: + plot.plot_path(X, path) +plot.plot_obstacles(X, obstacles) # Plot the cylindrical obstacles +plot.plot_start(X, x_init) +plot.plot_goal(X, x_intermediate, color="pink") # Plot the intermediate goal in pink +plot.plot_goal(X, x_goal, color="green") # Plot the final goal in green +plot.draw(auto_open=True) + diff --git a/examples/rrt/rrt_3d_cylinder3.py b/examples/rrt/rrt_3d_cylinder3.py new file mode 100644 index 0000000..1db477f --- /dev/null +++ b/examples/rrt/rrt_3d_cylinder3.py @@ -0,0 +1,81 @@ +import numpy as np +from rtree import index # Import the index module from the rtree package +import sys +sys.path.append('/home/dell/rrt-algorithms') + +from rrt_algorithms.rrt.rrt import RRT +from rrt_algorithms.search_space.search_space import SearchSpace +from rrt_algorithms.utilities.plotting import Plot +import matplotlib.pyplot as plt +from mpl_toolkits.mplot3d.art3d import Poly3DCollection + +# Define the search space dimensions +X_dimensions = np.array([(0, 100), (0, 100), (0, 100)]) + +# Define cylindrical obstacles +obstacles = [ + (10, 82, 0, 85, 15), + (80, 20, 0, 60, 19), + (10, 30, 0, 90, 15), + (80, 80, 0, 70, 22), + (50, 50, 0, 50, 22), # Cylinder at (50, 50) with height 15 along z-axis and radius 5 +] + +# Define initial and goal positions +x_init = (-2, 0, 0) # Starting location +x_intermediate = (50, 50, 100) # First intermediate goal location +x_second_goal = (70, 20, 100) # Second intermediate goal location +x_final_goal = (80, 80, 100) # Final goal location + +# Define RRT parameters +q = 30 # Length of tree edges +r = 1 # Length of smallest edge to check for intersection with obstacles +max_samples = 1024 # Max number of samples to take before timing out +prc = 0.1 # Probability of checking for a connection to goal + +# Create the search space +X = SearchSpace(X_dimensions, obstacles) + +# First RRT search: from x_init to x_intermediate +print("Starting RRT search from initial point to first intermediate goal...") +rrt = RRT(X, q, x_init, x_intermediate, max_samples, r, prc) +path1 = rrt.rrt_search() + +# If a path is found to the first intermediate goal, continue to the second intermediate goal +if path1 is not None: + print("Starting RRT search from first intermediate goal to second intermediate goal...") + rrt = RRT(X, q, x_intermediate, x_second_goal, max_samples, r, prc) + path2 = rrt.rrt_search() + + if path2 is not None: + print("Starting RRT search from second intermediate goal to final goal...") + rrt = RRT(X, q, x_second_goal, x_final_goal, max_samples, r, prc) + path3 = rrt.rrt_search() + + # Combine all paths + if path3 is not None: + path = path1 + path2[1:] + path3[1:] # Combine paths, avoiding duplicate points + else: + print("Could not find a path to the final goal.") + path = path1 + path2[1:] # Use the first two paths + else: + print("Could not find a path to the second intermediate goal.") + path = path1 # Use only the first path +else: + print("Could not find a path to the first intermediate goal.") + path = None + +# Plotting setup +plot = Plot("rrt_3d") + +# Plot the RRT tree, path, and cylindrical obstacles +plot.plot_tree(X, rrt.trees) +if path is not None: + plot.plot_path(X, path) +plot.plot_obstacles(X, obstacles) # Plot the cylindrical obstacles +plot.plot_start(X, x_init) +plot.plot_goal(X, x_intermediate, color="pink") # Plot the first intermediate goal in pink +plot.plot_goal(X, x_second_goal, color="blue") # Plot the second intermediate goal in blue +plot.plot_goal(X, x_final_goal, color="green") # Plot the final goal in green +plot.draw(auto_open=True) + diff --git a/examples/rrt/rrt_3d_cylinder_DWA.py b/examples/rrt/rrt_3d_cylinder_DWA.py new file mode 100644 index 0000000..c38be27 --- /dev/null +++ b/examples/rrt/rrt_3d_cylinder_DWA.py @@ -0,0 +1,98 @@ +import numpy as np +from rtree import index +import sys +sys.path.append('/home/dell/rrt-algorithms') + +from rrt_algorithms.rrt.rrt import RRT +from rrt_algorithms.search_space.search_space import SearchSpace +from rrt_algorithms.utilities.plotting import Plot +from rrt_algorithms.dwa_algorithm.DWA import DWA # Assuming you have a DWA implementation + +# Define the search space dimensions and obstacles +X_dimensions = np.array([(0, 100), (0, 100), (0, 100)]) +obstacles = [ + (10, 82, 0, 85, 15), + (80, 20, 0, 60, 19), + (10, 30, 0, 90, 15), + (80, 80, 0, 70, 22), + (50, 50, 0, 50, 22), +] + +# Initial and goal positions +x_init = (-2, 0, 0) +x_intermediate = (50, 50, 100) +x_second_goal = (70, 20, 100) +x_final_goal = (80, 80, 100) + +# RRT parameters +q = 30 +r = 1 +max_samples = 1024 +prc = 0.1 + +# DWA parameters +dwa_params = { + 'max_speed': 1.0, + 'min_speed': 0.0, + 'max_yaw_rate': 40.0 * np.pi / 180.0, + 'max_accel': 0.2, + 'v_reso': 0.01, + 'yaw_rate_reso': 0.1 * np.pi / 180.0, + 'dt': 0.1, + 'predict_time': 3.0, + 'to_goal_cost_gain': 1.0, + 'speed_cost_gain': 1.0, + 'obstacle_cost_gain': 1.0, +} + +# Create the search space +X = SearchSpace(X_dimensions, obstacles) + +# RRT pathfinding to first intermediate goal +print("RRT to first intermediate goal...") +rrt = RRT(X, q, x_init, x_intermediate, max_samples, r, prc) +path1 = rrt.rrt_search() + +if path1 is not None: + print("RRT to second intermediate goal...") + rrt = RRT(X, q, x_intermediate, x_second_goal, max_samples, r, prc) + path2 = rrt.rrt_search() + + if path2 is not None: + print("RRT to final goal...") + rrt = RRT(X, q, x_second_goal, x_final_goal, max_samples, r, prc) + path3 = rrt.rrt_search() + + # Combine all paths + if path3 is not None: + path = path1 + path2[1:] + path3[1:] + else: + path = path1 + path2[1:] + else: + path = path1 +else: + path = None + +# Apply DWA for local optimization along the RRT path +if path is not None: + dwa = DWA(dwa_params) + optimized_path = [] + + for i in range(len(path) - 1): + start_point = path[i] + (0.0, 0.0) # Initialize v and w to 0, using tuple + end_point = path[i + 1] + + local_path = dwa.plan(start_point, end_point, X, obstacles) + optimized_path.extend(local_path) + +# Plotting +plot = Plot("rrt_dwa_3d") +plot.plot_tree(X, rrt.trees) +if optimized_path is not None: + plot.plot_path(X, optimized_path) +plot.plot_obstacles(X, obstacles) +plot.plot_start(X, x_init) +plot.plot_goal(X, x_intermediate, color="pink") +plot.plot_goal(X, x_second_goal, color="blue") +plot.plot_goal(X, x_final_goal, color="green") +plot.draw(auto_open=True) diff --git a/examples/rrt/rrt_3d_cylinder_DWA1.py b/examples/rrt/rrt_3d_cylinder_DWA1.py new file mode 100644 index 0000000..c38be27 --- /dev/null +++ b/examples/rrt/rrt_3d_cylinder_DWA1.py @@ -0,0 +1,98 @@ +import numpy as np +from rtree import index +import sys +sys.path.append('/home/dell/rrt-algorithms') + +from rrt_algorithms.rrt.rrt import RRT +from rrt_algorithms.search_space.search_space import SearchSpace +from rrt_algorithms.utilities.plotting import Plot +from rrt_algorithms.dwa_algorithm.DWA import DWA # Assuming you have a DWA implementation + +# Define the search space dimensions and obstacles +X_dimensions = np.array([(0, 100), (0, 100), (0, 100)]) +obstacles = [ + (10, 82, 0, 85, 15), + (80, 20, 0, 60, 19), + (10, 30, 0, 90, 15), + (80, 80, 0, 70, 22), + (50, 50, 0, 50, 22), +] + +# Initial and goal positions +x_init = (-2, 0, 0) +x_intermediate = (50, 50, 100) +x_second_goal = (70, 20, 100) +x_final_goal = (80, 80, 100) + +# RRT parameters +q = 30 +r = 1 +max_samples = 1024 +prc = 0.1 + +# DWA parameters +dwa_params = { + 'max_speed': 1.0, + 'min_speed': 0.0, + 'max_yaw_rate': 40.0 * np.pi / 180.0, + 'max_accel': 0.2, + 'v_reso': 0.01, + 'yaw_rate_reso': 0.1 * np.pi / 180.0, + 'dt': 0.1, + 'predict_time': 3.0, + 'to_goal_cost_gain': 1.0, + 'speed_cost_gain': 1.0, + 'obstacle_cost_gain': 1.0, +} + +# Create the search space +X = SearchSpace(X_dimensions, obstacles) + +# RRT pathfinding to first intermediate goal +print("RRT to first intermediate goal...") +rrt = RRT(X, q, x_init, x_intermediate, max_samples, r, prc) +path1 = rrt.rrt_search() + +if path1 is not None: + print("RRT to second intermediate goal...") + rrt = RRT(X, q, x_intermediate, x_second_goal, max_samples, r, prc) + path2 = rrt.rrt_search() + + if path2 is not None: + print("RRT to final goal...") + rrt = RRT(X, q, x_second_goal, x_final_goal, max_samples, r, prc) + path3 = rrt.rrt_search() + + # Combine all paths + if path3 is not None: + path = path1 + path2[1:] + path3[1:] + else: + path = path1 + path2[1:] + else: + path = path1 +else: + path = None + +# Apply DWA for local optimization along the RRT path +if path is not None: + dwa = DWA(dwa_params) + optimized_path = [] + + for i in range(len(path) - 1): + start_point = path[i] + (0.0, 0.0) # Initialize v and w to 0, using tuple + end_point = path[i + 1] + + local_path = dwa.plan(start_point, end_point, X, obstacles) + optimized_path.extend(local_path) + +# Plotting +plot = Plot("rrt_dwa_3d") +plot.plot_tree(X, rrt.trees) +if optimized_path is not None: + plot.plot_path(X, optimized_path) +plot.plot_obstacles(X, obstacles) +plot.plot_start(X, x_init) +plot.plot_goal(X, x_intermediate, color="pink") +plot.plot_goal(X, x_second_goal, color="blue") +plot.plot_goal(X, x_final_goal, color="green") +plot.draw(auto_open=True) diff --git a/examples/rrt/rrt_3d_cylinder_DWA2.py b/examples/rrt/rrt_3d_cylinder_DWA2.py new file mode 100644 index 0000000..23bc735 --- /dev/null +++ b/examples/rrt/rrt_3d_cylinder_DWA2.py @@ -0,0 +1,158 @@ +import numpy as np +import time +from rtree import index +import sys +sys.path.append('/home/dell/rrt-algorithms') + +from rrt_algorithms.rrt.rrt import RRT +from rrt_algorithms.search_space.search_space import SearchSpace +from rrt_algorithms.utilities.plotting import Plot +from rrt_algorithms.dwa_algorithm.DWA import DWA + +# Define the search space dimensions and obstacles +X_dimensions = np.array([(0, 100), (0, 100), (0, 100)]) +obstacles = [ + (10, 82, 0, 85, 15), + (80, 20, 0, 60, 19), + (10, 30, 0, 90, 15), + (80, 80, 0, 70, 22), + (50, 50, 0, 50, 22), +] + +# Initial and goal positions +x_init = (50, 50, -2) +x_intermediate = (50, 50, 100) +x_second_goal = (200, 60, 100) +x_final_goal = (80, 80, 100) + +# RRT parameters +q = 30 +r = 1 +max_samples = 1024 +prc = 0.1 + +# DWA parameters +dwa_params = { + 'max_speed': 1.0, + 'min_speed': 0.0, + 'max_yaw_rate': 40.0 * np.pi / 180.0, + 'max_accel': 0.2, + 'v_reso': 0.01, + 'yaw_rate_reso': 0.1 * np.pi / 180.0, + 'dt': 0.1, + 'predict_time': 3.0, + 'to_goal_cost_gain': 1.0, + 'speed_cost_gain': 1.0, + 'obstacle_cost_gain': 1.0, +} + +# Create the search space +X = SearchSpace(X_dimensions, obstacles) + +def path_length(path): + return sum(np.linalg.norm(np.array(path[i+1]) - np.array(path[i])) for i in range(len(path) - 1)) + +def path_smoothness(path): + total_curvature = 0.0 + for i in range(1, len(path) - 1): + vec1 = np.array(path[i]) - np.array(path[i-1]) + vec2 = np.array(path[i+1]) - np.array(path[i]) + angle = np.arccos(np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2))) + total_curvature += angle + return total_curvature + +def min_obstacle_clearance(path, obstacles): + min_clearance = float('inf') + for point in path: + for obs in obstacles: + clearance = np.linalg.norm(np.array(point[:2]) - np.array(obs[:2])) - obs[4] + if clearance < min_clearance: + min_clearance = clearance + return min_clearance + +def compute_energy_usage(path, velocity): + energy = 0.0 + for i in range(1, len(path)): + distance = np.linalg.norm(np.array(path[i]) - np.array(path[i-1])) + energy += distance * velocity + return energy + +# RRT pathfinding to first intermediate goal +print("RRT to first intermediate goal...") +start_time = time.time() +rrt = RRT(X, q, x_init, x_intermediate, max_samples, r, prc) +path1 = rrt.rrt_search() +rrt_time = time.time() - start_time + +if path1 is not None: + print("RRT to second intermediate goal...") + rrt = RRT(X, q, x_intermediate, x_second_goal, max_samples, r, prc) + path2 = rrt.rrt_search() + + if path2 is not None: + print("RRT to final goal...") + rrt = RRT(X, q, x_second_goal, x_final_goal, max_samples, r, prc) + path3 = rrt.rrt_search() + + # Combine all paths + if path3 is not None: + path = path1 + path2[1:] + path3[1:] + else: + path = path1 + path2[1:] + else: + path = path1 +else: + path = None + +# Apply DWA for local optimization along the RRT path +if path is not None: + dwa = DWA(dwa_params) + optimized_path = [] + + start_time = time.time() + for i in range(len(path) - 1): + start_point = path[i] + (0.0, 0.0) # Initialize v and w to 0, using tuple + end_point = path[i + 1] + + local_path = dwa.plan(start_point, end_point, X, obstacles) + optimized_path.extend(local_path) + dwa_time = time.time() - start_time + + # Metrics + rrt_path_length = path_length(path) + dwa_path_length = path_length(optimized_path) + + rrt_smoothness = path_smoothness(path) + dwa_smoothness = path_smoothness(optimized_path) + + rrt_clearance = min_obstacle_clearance(path, obstacles) + dwa_clearance = min_obstacle_clearance(optimized_path, obstacles) + + average_velocity = dwa_params['max_speed'] # Assume max speed for energy calculation + rrt_energy = compute_energy_usage(path, average_velocity) + dwa_energy = compute_energy_usage(optimized_path, average_velocity) + + # Print Metrics + print(f"RRT Path Length: {rrt_path_length}") + print(f"DWA Optimized Path Length: {dwa_path_length}") + print(f"RRT Path Smoothness: {rrt_smoothness}") + print(f"DWA Optimized Path Smoothness: {dwa_smoothness}") + print(f"RRT Path Minimum Clearance: {rrt_clearance}") + print(f"DWA Optimized Path Minimum Clearance: {dwa_clearance}") + print(f"RRT Path Energy Usage: {rrt_energy}") + print(f"DWA Optimized Path Energy Usage: {dwa_energy}") + print(f"RRT Path Computation Time: {rrt_time} seconds") + print(f"DWA Optimized Path Computation Time: {dwa_time} seconds") + + # Plotting + plot = Plot("rrt_dwa_3d") + plot.plot_tree(X, rrt.trees) + if optimized_path is not None: + plot.plot_path(X, optimized_path, color='blue') + plot.plot_obstacles(X, obstacles) + plot.plot_start(X, x_init) + plot.plot_goal(X, x_intermediate, color="pink") + plot.plot_goal(X, x_second_goal, color="blue") + plot.plot_goal(X, x_final_goal, color="green") + plot.draw(auto_open=True) + diff --git a/examples/rrt/rrt_3d_cylinder_DWA3.py b/examples/rrt/rrt_3d_cylinder_DWA3.py new file mode 100644 index 0000000..5ece2bc --- /dev/null +++ b/examples/rrt/rrt_3d_cylinder_DWA3.py @@ -0,0 +1,159 @@ +import numpy as np +import time +from rtree import index +import sys +sys.path.append('/home/dell/rrt-algorithms') + +from rrt_algorithms.rrt.rrt import RRT +from rrt_algorithms.search_space.search_space import SearchSpace +from rrt_algorithms.utilities.plotting import Plot +from rrt_algorithms.dwa_algorithm.DWA import DWA + +# Define the search space dimensions and obstacles +X_dimensions = np.array([(0, 100), (0, 100), (0, 100)]) +obstacles = [ + (10, 82, 0, 85, 15), + (80, 20, 0, 60, 19), + (10, 30, 0, 90, 15), + (80, 80, 0, 70, 22), + (50, 50, 0, 50, 22), +] + +# Initial and goal positions +x_init = (50, 50, -2) +x_intermediate = (50, 50, 100) +x_second_goal = (20, 60, 100) +x_final_goal = (100, 100, 0) + +# RRT parameters +q = 60 +r = 1 +max_samples = 1024 +prc = 0.1 + +# DWA parameters +dwa_params = { + 'max_speed': 1.0, + 'min_speed': 0.0, + 'max_yaw_rate': 40.0 * np.pi / 180.0, + 'max_accel': 0.3, # Increase acceleration to reach optimal speed faster + 'v_reso': 0.05, # Increase resolution for speed and yaw rate + 'yaw_rate_reso': 0.2 * np.pi / 180.0, + 'dt': 0.1, + 'predict_time': 2.0, # Reduce prediction time to speed up computation + 'to_goal_cost_gain': 1.5, # Increase goal cost to prioritize reaching the goal + 'speed_cost_gain': 0.5, # Decrease speed cost to allow faster speeds + 'obstacle_cost_gain': 1.0, +} + + +# Create the search space +X = SearchSpace(X_dimensions, obstacles) + +def path_length(path): + return sum(np.linalg.norm(np.array(path[i+1]) - np.array(path[i])) for i in range(len(path) - 1)) + +def path_smoothness(path): + total_curvature = 0.0 + for i in range(1, len(path) - 1): + vec1 = np.array(path[i]) - np.array(path[i-1]) + vec2 = np.array(path[i+1]) - np.array(path[i]) + angle = np.arccos(np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2))) + total_curvature += angle + return total_curvature + +def min_obstacle_clearance(path, obstacles): + min_clearance = float('inf') + for point in path: + for obs in obstacles: + clearance = np.linalg.norm(np.array(point[:2]) - np.array(obs[:2])) - obs[4] + if clearance < min_clearance: + min_clearance = clearance + return min_clearance + +def compute_energy_usage(path, velocity): + energy = 0.0 + for i in range(1, len(path)): + distance = np.linalg.norm(np.array(path[i]) - np.array(path[i-1])) + energy += distance * velocity + return energy + +# RRT pathfinding to first intermediate goal +print("RRT to first intermediate goal...") +start_time = time.time() +rrt = RRT(X, q, x_init, x_intermediate, max_samples, r, prc) +path1 = rrt.rrt_search() +rrt_time = time.time() - start_time + +if path1 is not None: + print("RRT to second intermediate goal...") + rrt = RRT(X, q, x_intermediate, x_second_goal, max_samples, r, prc) + path2 = rrt.rrt_search() + + if path2 is not None: + print("RRT to final goal...") + rrt = RRT(X, q, x_second_goal, x_final_goal, max_samples, r, prc) + path3 = rrt.rrt_search() + + # Combine all paths + if path3 is not None: + path = path1 + path2[1:] + path3[1:] + else: + path = path1 + path2[1:] + else: + path = path1 +else: + path = None + +# Apply DWA for local optimization along the RRT path +if path is not None: + dwa = DWA(dwa_params) + optimized_path = [] + + start_time = time.time() + for i in range(len(path) - 1): + start_point = path[i] + (0.0, 0.0) # Initialize v and w to 0, using tuple + end_point = path[i + 1] + + local_path = dwa.plan(start_point, end_point, X, obstacles) + optimized_path.extend(local_path) + dwa_time = time.time() - start_time + + # Metrics + rrt_path_length = path_length(path) + dwa_path_length = path_length(optimized_path) + + rrt_smoothness = path_smoothness(path) + dwa_smoothness = path_smoothness(optimized_path) + + rrt_clearance = min_obstacle_clearance(path, obstacles) + dwa_clearance = min_obstacle_clearance(optimized_path, obstacles) + + average_velocity = dwa_params['max_speed'] # Assume max speed for energy calculation + rrt_energy = compute_energy_usage(path, average_velocity) + dwa_energy = compute_energy_usage(optimized_path, average_velocity) + + # Print Metrics + print(f"RRT Path Length: {rrt_path_length}") + print(f"DWA Optimized Path Length: {dwa_path_length}") + print(f"RRT Path Smoothness: {rrt_smoothness}") + print(f"DWA Optimized Path Smoothness: {dwa_smoothness}") + print(f"RRT Path Minimum Clearance: {rrt_clearance}") + print(f"DWA Optimized Path Minimum Clearance: {dwa_clearance}") + print(f"RRT Path Energy Usage: {rrt_energy}") + print(f"DWA Optimized Path Energy Usage: {dwa_energy}") + print(f"RRT Path Computation Time: {rrt_time} seconds") + print(f"DWA Optimized Path Computation Time: {dwa_time} seconds") + + # Plotting + plot = Plot("rrt_dwa_3d") + plot.plot_tree(X, rrt.trees) + plot.plot_path(X, path, color='red') # Plot the original RRT path in red + plot.plot_path(X, optimized_path, color='blue') # Plot the optimized path in blue + plot.plot_obstacles(X, obstacles) + plot.plot_start(X, x_init) + plot.plot_goal(X, x_intermediate, color="pink") + plot.plot_goal(X, x_second_goal, color="blue") + plot.plot_goal(X, x_final_goal, color="green") + plot.draw(auto_open=True) + diff --git a/examples/rrt/rrt_3d_cylinder_DWA_BVH.py b/examples/rrt/rrt_3d_cylinder_DWA_BVH.py new file mode 100644 index 0000000..c0ba27c --- /dev/null +++ b/examples/rrt/rrt_3d_cylinder_DWA_BVH.py @@ -0,0 +1,159 @@ +import numpy as np +import time +from rtree import index +import sys +sys.path.append('/home/dell/rrt-algorithms') + +from rrt_algorithms.rrt.rrt import RRT +from rrt_algorithms.search_space.search_space1 import SearchSpace +from rrt_algorithms.utilities.plotting import Plot +from rrt_algorithms.dwa_algorithm.DWA import DWA + +# Define the search space dimensions and obstacles +# Define the search space dimensions and obstacles +X_dimensions = np.array([(0, 100), (0, 100), (0, 100)]) +obstacles = [ + (10, 82, 0, 85, 15), + (80, 20, 0, 60, 19), + (10, 30, 0, 90, 15), + (80, 80, 0, 70, 22), + (50, 50, 0, 50, 22), +] + +# Initial and goal positions +x_init = (50, 50, -2) +x_intermediate = (50, 50, 100) +x_second_goal = (20, 60, 100) +x_final_goal = (100, 100, 10) + +# RRT parameters +q = 500 +r = 1 +max_samples = 1024 +prc = 0.1 + +# DWA parameters +dwa_params = { + 'max_speed': 1.0, + 'min_speed': 0.0, + 'max_yaw_rate': 40.0 * np.pi / 180.0, + 'max_accel': 0.3, # Increase acceleration to reach optimal speed faster + 'v_reso': 0.05, # Increase resolution for speed and yaw rate + 'yaw_rate_reso': 0.2 * np.pi / 180.0, + 'dt': 0.1, + 'predict_time': 2.0, # Reduce prediction time to speed up computation + 'to_goal_cost_gain': 1.5, # Increase goal cost to prioritize reaching the goal + 'speed_cost_gain': 0.5, # Decrease speed cost to allow faster speeds + 'obstacle_cost_gain': 1.0, +} + +# Create the search space with efficient collision checking +X = SearchSpace(X_dimensions, obstacles) + +def path_length(path): + return sum(np.linalg.norm(np.array(path[i+1]) - np.array(path[i])) for i in range(len(path) - 1)) + +def path_smoothness(path): + total_curvature = 0.0 + for i in range(1, len(path) - 1): + vec1 = np.array(path[i]) - np.array(path[i-1]) + vec2 = np.array(path[i+1]) - np.array(path[i]) + angle = np.arccos(np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2))) + total_curvature += angle + return total_curvature + +def min_obstacle_clearance(path, obstacles): + min_clearance = float('inf') + for point in path: + for obs in obstacles: + clearance = np.linalg.norm(np.array(point[:2]) - np.array(obs[:2])) - obs[4] + if clearance < min_clearance: + min_clearance = clearance + return min_clearance + +def compute_energy_usage(path, velocity): + energy = 0.0 + for i in range(1, len(path)): + distance = np.linalg.norm(np.array(path[i]) - np.array(path[i-1])) + energy += distance * velocity + return energy + +# RRT pathfinding to first intermediate goal +print("RRT to first intermediate goal...") +start_time = time.time() +rrt = RRT(X, q, x_init, x_intermediate, max_samples, r, prc) +path1 = rrt.rrt_search() +rrt_time = time.time() - start_time + +if path1 is not None: + print("RRT to second intermediate goal...") + rrt = RRT(X, q, x_intermediate, x_second_goal, max_samples, r, prc) + path2 = rrt.rrt_search() + + if path2 is not None: + print("RRT to final goal...") + rrt = RRT(X, q, x_second_goal, x_final_goal, max_samples, r, prc) + path3 = rrt.rrt_search() + + # Combine all paths + if path3 is not None: + path = path1 + path2[1:] + path3[1:] + else: + path = path1 + path2[1:] + else: + path = path1 +else: + path = None + +# Apply DWA for local optimization along the RRT path +if path is not None: + dwa = DWA(dwa_params) + optimized_path = [] + + start_time = time.time() + for i in range(len(path) - 1): + start_point = path[i] + (0.0, 0.0) # Initialize v and w to 0, using tuple + end_point = path[i + 1] + + local_path = dwa.plan(start_point, end_point, X, obstacles) + optimized_path.extend(local_path) + dwa_time = time.time() - start_time + + # Metrics + rrt_path_length = path_length(path) + dwa_path_length = path_length(optimized_path) + + rrt_smoothness = path_smoothness(path) + dwa_smoothness = path_smoothness(optimized_path) + + rrt_clearance = min_obstacle_clearance(path, obstacles) + dwa_clearance = min_obstacle_clearance(optimized_path, obstacles) + + average_velocity = dwa_params['max_speed'] # Assume max speed for energy calculation + rrt_energy = compute_energy_usage(path, average_velocity) + dwa_energy = compute_energy_usage(optimized_path, average_velocity) + + # Print Metrics + print(f"RRT Path Length: {rrt_path_length}") + print(f"DWA Optimized Path Length: {dwa_path_length}") + print(f"RRT Path Smoothness: {rrt_smoothness}") + print(f"DWA Optimized Path Smoothness: {dwa_smoothness}") + print(f"RRT Path Minimum Clearance: {rrt_clearance}") + print(f"DWA Optimized Path Minimum Clearance: {dwa_clearance}") + print(f"RRT Path Energy Usage: {rrt_energy}") + print(f"DWA Optimized Path Energy Usage: {dwa_energy}") + print(f"RRT Path Computation Time: {rrt_time} seconds") + print(f"DWA Optimized Path Computation Time: {dwa_time} seconds") + + # Plotting + plot = Plot("rrt_dwa_3d") + plot.plot_tree(X, rrt.trees) + plot.plot_path(X, path, color='red') # Plot the original RRT path in red + plot.plot_path(X, optimized_path, color='blue') # Plot the optimized path in blue + plot.plot_obstacles(X, obstacles) + plot.plot_start(X, x_init) + plot.plot_goal(X, x_intermediate, color="pink") + plot.plot_goal(X, x_second_goal, color="blue") + plot.plot_goal(X, x_final_goal, color="green") + plot.draw(auto_open=True) + diff --git a/examples/rrt/rrt_3d_cylinder_DWA_BVH_1.py b/examples/rrt/rrt_3d_cylinder_DWA_BVH_1.py new file mode 100644 index 0000000..286de86 --- /dev/null +++ b/examples/rrt/rrt_3d_cylinder_DWA_BVH_1.py @@ -0,0 +1,179 @@ +# This file is subject to the terms and conditions defined in +# file 'LICENSE', which is part of this source code package. +#the RRT and DWA algorithms function with the optimized collision checking using Bounding Volume Hierarchies (BVH). +#BVH Implementation: We use an R-tree (a type of BVH) to store axis-aligned bounding boxes (AABB) for each obstacle. This allows us to quickly identify which obstacles might intersect with a given point or path segment. +#Efficient Collision Checking: Instead of checking every obstacle for collision, we first use the BVH to narrow down the list to only those obstacles whose bounding boxes intersect with the point or path segment in question. +#Integration with DWA: The code remains the same in terms of how paths are generated and optimized, but now the collision checking is more efficient, leading to faster overall performance. +#All obstacles (both random and predefined) need to be properly registered in the SearchSpace so that the collision checking functions (obstacle_free and collision_free) are aware of all obstacles. +# the script avoids both static and dynamic obstacles, it starts from orange dot and its final goal is green. +import numpy as np +import time +from rtree import index +import sys +import uuid + +sys.path.append('/home/dell/rrt-algorithms') + +from rrt_algorithms.rrt.rrt import RRT +from rrt_algorithms.search_space.search_space1 import SearchSpace +from rrt_algorithms.utilities.plotting1 import Plot +from rrt_algorithms.dwa_algorithm.DWA1 import DWA +from rrt_algorithms.utilities.obstacle_generation1 import generate_random_cylindrical_obstacles + +# Define the search space dimensions +X_dimensions = np.array([(0, 100), (0, 100), (0, 100)]) + +# Initial and goal positions +x_init = (50, 50, -2) +x_intermediate = (50, 50, 100) +x_second_goal = (20, 60, 100) +x_final_goal = (100, 100, 10) + +# Create the search space +X = SearchSpace(X_dimensions) + +# Generate random obstacles using the SearchSpace object +n = 7 # Number of random obstacles +Obstacles = generate_random_cylindrical_obstacles(X, x_init, x_final_goal, n) + +# Predefined static obstacles +static_obstacles = [ + (10, 82, 0, 85, 15), + (80, 20, 0, 60, 19), + (10, 30, 0, 90, 15), + (80, 80, 0, 70, 20), + (50, 50, 0, 50, 13), +] + +# Combine predefined and random obstacles +all_obstacles = static_obstacles + Obstacles + +# Initialize the SearchSpace with all obstacles +X = SearchSpace(X_dimensions, all_obstacles) + +# RRT parameters +q = 700 +r = 1 +max_samples = 1024 +prc = 0.1 + +# DWA parameters +dwa_params = { + 'max_speed': 1.0, + 'min_speed': 0.0, + 'max_yaw_rate': 40.0 * np.pi / 180.0, + 'max_accel': 0.3, # Increase acceleration to reach optimal speed faster + 'v_reso': 0.05, # Increase resolution for speed and yaw rate + 'yaw_rate_reso': 0.2 * np.pi / 180.0, + 'dt': 0.1, + 'predict_time': 2.0, # Reduce prediction time to speed up computation + 'to_goal_cost_gain': 1.5, # Increase goal cost to prioritize reaching the goal + 'speed_cost_gain': 0.5, # Decrease speed cost to allow faster speeds + 'obstacle_cost_gain': 1.0, +} +def path_length(path): + return sum(np.linalg.norm(np.array(path[i+1]) - np.array(path[i])) for i in range(len(path) - 1)) + +def path_smoothness(path): + total_curvature = 0.0 + for i in range(1, len(path) - 1): + vec1 = np.array(path[i]) - np.array(path[i-1]) + vec2 = np.array(path[i+1]) - np.array(path[i]) + angle = np.arccos(np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2))) + total_curvature += angle + return total_curvature + +def min_obstacle_clearance(path, obstacles): + min_clearance = float('inf') + for point in path: + for obs in obstacles: + clearance = np.linalg.norm(np.array(point[:2]) - np.array(obs[:2])) - obs[4] + if clearance < min_clearance: + min_clearance = clearance + return min_clearance + +def compute_energy_usage(path, velocity): + energy = 0.0 + for i in range(1, len(path)): + distance = np.linalg.norm(np.array(path[i]) - np.array(path[i-1])) + energy += distance * velocity + return energy + +# RRT pathfinding to first intermediate goal +print("RRT to first intermediate goal...") +start_time = time.time() +rrt = RRT(X, q, x_init, x_intermediate, max_samples, r, prc) +path1 = rrt.rrt_search() +rrt_time = time.time() - start_time + +if path1 is not None: + print("RRT to second intermediate goal...") + rrt = RRT(X, q, x_intermediate, x_second_goal, max_samples, r, prc) + path2 = rrt.rrt_search() + + if path2 is not None: + print("RRT to final goal...") + rrt = RRT(X, q, x_second_goal, x_final_goal, max_samples, r, prc) + path3 = rrt.rrt_search() + + # Combine all paths + if path3 is not None: + path = path1 + path2[1:] + path3[1:] + else: + path = path1 + path2[1:] + else: + path = path1 +else: + path = None + +# Apply DWA for local optimization along the RRT path +if path is not None: + dwa = DWA(dwa_params) + optimized_path = [] + + start_time = time.time() + for i in range(len(path) - 1): + start_point = path[i] + (0.0, 0.0) # Initialize v and w to 0, using tuple + end_point = path[i + 1] + + local_path = dwa.plan(start_point, end_point, X, all_obstacles) + optimized_path.extend(local_path) + dwa_time = time.time() - start_time + + # Metrics + rrt_path_length = path_length(path) + dwa_path_length = path_length(optimized_path) + + rrt_smoothness = path_smoothness(path) + dwa_smoothness = path_smoothness(optimized_path) + + rrt_clearance = min_obstacle_clearance(path, all_obstacles) + dwa_clearance = min_obstacle_clearance(optimized_path, all_obstacles) + + average_velocity = dwa_params['max_speed'] # Assume max speed for energy calculation + rrt_energy = compute_energy_usage(path, average_velocity) + dwa_energy = compute_energy_usage(optimized_path, average_velocity) + + # Print Metrics + print(f"RRT Path Length: {rrt_path_length}") + print(f"DWA Optimized Path Length: {dwa_path_length}") + print(f"RRT Path Smoothness: {rrt_smoothness}") + print(f"DWA Optimized Path Smoothness: {dwa_smoothness}") + print(f"RRT Path Minimum Clearance: {rrt_clearance}") + print(f"DWA Optimized Path Minimum Clearance: {dwa_clearance}") + print(f"RRT Path Energy Usage: {rrt_energy}") + print(f"DWA Optimized Path Energy Usage: {dwa_energy}") + print(f"RRT Path Computation Time: {rrt_time} seconds") + print(f"DWA Optimized Path Computation Time: {dwa_time} seconds") + + # Plotting + plot = Plot("rrt_dwa_3d") + plot.plot_tree(X, rrt.trees) + plot.plot_path(X, path, color='red') # Plot the original RRT path in red + plot.plot_path(X, optimized_path, color='blue') # Plot the optimized path in blue + plot.plot_obstacles(X, all_obstacles) + plot.plot_start(X, x_init) + plot.plot_goal(X, x_intermediate, color="pink") + plot.plot_goal(X, x_second_goal, color="blue") + plot.plot_goal(X, x_final_goal, color="green") + plot.draw(auto_open=True) diff --git a/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size+1.py b/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size+1.py new file mode 100644 index 0000000..e082ffb --- /dev/null +++ b/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size+1.py @@ -0,0 +1,175 @@ +# Texpanding the radius of the obstacles by the radius of the drone (10 cm) to ensure that the drone does not collide with any obstacles. This adjustment effectively treats the drone as a point but expands the obstacles to account for the drone's size. +import numpy as np +import time +from rtree import index +import sys +import uuid +import numpy as np +import skfuzzy as fuzz +from skfuzzy import control as ctrl +sys.path.append('/home/dell/rrt-algorithms') + +from rrt_algorithms.rrt.rrt import RRT +from rrt_algorithms.search_space.search_space2 import SearchSpace +from rrt_algorithms.utilities.plotting2 import Plot +from rrt_algorithms.dwa_algorithm.DWA2 import DWA +from rrt_algorithms.dwa_algorithm.DWA2 import FuzzyController +from rrt_algorithms.utilities.obstacle_generation2 import generate_random_cylindrical_obstacles + + +# Define the search space dimensions +X_dimensions = np.array([(0, 100), (0, 100), (0, 100)]) +# Initial and goal positions +x_init = (50, 50, -2) +x_intermediate = (50, 50, 100) +x_second_goal = (20, 60, 100) +x_final_goal = (0, 0, 0) +#x_final_goal = (100, 100, 40) +# Create the search space +X = SearchSpace(X_dimensions) + +# Generate random obstacles +n = 7 # Number of random obstacles +Obstacles = generate_random_cylindrical_obstacles(X, x_init, x_final_goal, n) + +# Define static obstacles +obstacles = [ + (10, 82, 0, 85, 15), + (80, 20, 0, 60, 19), + (10, 30, 0, 90, 15), + (80, 80, 0, 70, 22), + (50, 50, 0, 50, 22), +] + +# Combine static and randomly generated obstacles into one list +all_obstacles = obstacles + Obstacles +# Initialize the SearchSpace with all obstacles +X = SearchSpace(X_dimensions, all_obstacles) + +# RRT parameters +q = 700 +r = 1 +max_samples = 1024 +prc = 0.1 + +# DWA parameters +dwa_params = { + 'max_speed': 1.0, + 'min_speed': 0.0, + 'max_yaw_rate': 40.0 * np.pi / 180.0, + 'max_accel': 0.3, + 'v_reso': 0.05, + 'yaw_rate_reso': 0.2 * np.pi / 180.0, + 'dt': 0.1, + 'predict_time': 2.0, + 'to_goal_cost_gain': 1.5, + 'speed_cost_gain': 0.5, + 'obstacle_cost_gain': 1.0, +} + +def path_length(path): + return sum(np.linalg.norm(np.array(path[i+1]) - np.array(path[i])) for i in range(len(path) - 1)) + +def path_smoothness(path): + total_curvature = 0.0 + for i in range(1, len(path) - 1): + vec1 = np.array(path[i]) - np.array(path[i-1]) + vec2 = np.array(path[i+1]) - np.array(path[i]) + angle = np.arccos(np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2))) + total_curvature += angle + return total_curvature + +def min_obstacle_clearance(path, obstacles): + min_clearance = float('inf') + for point in path: + for obs in obstacles: + clearance = np.linalg.norm(np.array(point[:2]) - np.array(obs[:2])) - obs[4] + if clearance < min_clearance: + min_clearance = clearance + return min_clearance + +def compute_energy_usage(path, velocity): + energy = 0.0 + for i in range(1, len(path)): + distance = np.linalg.norm(np.array(path[i]) - np.array(path[i-1])) + energy += distance * velocity + return energy + +# RRT pathfinding to first intermediate goal +print("RRT to first intermediate goal...") +start_time = time.time() +rrt = RRT(X, q, x_init, x_intermediate, max_samples, r, prc) +path1 = rrt.rrt_search() +rrt_time = time.time() - start_time + +if path1 is not None: + print("RRT to second intermediate goal...") + rrt = RRT(X, q, x_intermediate, x_second_goal, max_samples, r, prc) + path2 = rrt.rrt_search() + + if path2 is not None: + print("RRT to final goal...") + rrt = RRT(X, q, x_second_goal, x_final_goal, max_samples, r, prc) + path3 = rrt.rrt_search() + + # Combine all paths + if path3 is not None: + path = path1 + path2[1:] + path3[1:] + else: + path = path1 + path2[1:] + else: + path = path1 +else: + path = None + +# Apply DWA for local optimization along the RRT path +if path is not None: + dwa = DWA(dwa_params) + optimized_path = [] + + start_time = time.time() + for i in range(len(path) - 1): + start_point = path[i] + (0.0, 0.0) # Initialize v and w to 0, using tuple + end_point = path[i + 1] + + local_path = dwa.plan(start_point, end_point, X, all_obstacles) + optimized_path.extend(local_path) + dwa_time = time.time() - start_time + + # Metrics + rrt_path_length = path_length(path) + dwa_path_length = path_length(optimized_path) + + rrt_smoothness = path_smoothness(path) + dwa_smoothness = path_smoothness(optimized_path) + + rrt_clearance = min_obstacle_clearance(path, all_obstacles) + dwa_clearance = min_obstacle_clearance(optimized_path, all_obstacles) + + average_velocity = dwa_params['max_speed'] + rrt_energy = compute_energy_usage(path, average_velocity) + dwa_energy = compute_energy_usage(optimized_path, average_velocity) + + # Print Metrics + print(f"RRT Path Length: {rrt_path_length}") + print(f"DWA Optimized Path Length: {dwa_path_length}") + print(f"RRT Path Smoothness: {rrt_smoothness}") + print(f"DWA Optimized Path Smoothness: {dwa_smoothness}") + print(f"RRT Path Minimum Clearance: {rrt_clearance}") + print(f"DWA Optimized Path Minimum Clearance: {dwa_clearance}") + print(f"RRT Path Energy Usage: {rrt_energy}") + print(f"DWA Optimized Path Energy Usage: {dwa_energy}") + print(f"RRT Path Computation Time: {rrt_time} seconds") + print(f"DWA Optimized Path Computation Time: {dwa_time} seconds") + + # Plotting + plot = Plot("rrt_dwa_3d") + plot.plot_tree(X, rrt.trees) + plot.plot_path(X, path, color='red') # Plot the original RRT path in red + plot.plot_path(X, optimized_path, color='blue') # Plot the optimized path in blue + plot.plot_obstacles(X, all_obstacles) + plot.plot_start(X, x_init) + plot.plot_goal(X, x_intermediate, color="pink") + plot.plot_goal(X, x_second_goal, color="blue") + plot.plot_goal(X, x_final_goal, color="green") + plot.draw(auto_open=True) diff --git a/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size+2.py b/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size+2.py new file mode 100644 index 0000000..53c9c17 --- /dev/null +++ b/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size+2.py @@ -0,0 +1,207 @@ +# Texpanding the radius of the obstacles by the radius of the drone (10 cm) to ensure that the drone does not collide with any obstacles. This adjustment effectively treats the drone as a point but expands the obstacles to account for the drone's size. +import numpy as np +import time +from rtree import index +import sys +import uuid +import numpy as np +import skfuzzy as fuzz +from skfuzzy import control as ctrl +sys.path.append('/home/dell/rrt-algorithms') + +from rrt_algorithms.rrt.rrt import RRT +from rrt_algorithms.search_space.search_space2 import SearchSpace +from rrt_algorithms.utilities.plotting2 import Plot +from rrt_algorithms.dwa_algorithm.DWA3 import DWA, FuzzyController +from rrt_algorithms.dqn_algorithm.DQN import DQNAgent +from rrt_algorithms.dqn_algorithm.DQN import DroneEnv +from rrt_algorithms.utilities.obstacle_generation2 import generate_random_cylindrical_obstacles +from tensorflow.keras.models import load_model + +# Define the search space dimensions +X_dimensions = np.array([(0, 100), (0, 100), (0, 100)]) +X = SearchSpace(X_dimensions) +# Initial and goal positions +x_init = (50, 50, -2) +x_intermediate = (50, 50, 100) +x_second_goal = (20, 60, 100) +x_final_goal = (0, 0, 0) +#x_final_goal = (100, 100, 40) +# Create the search space + + +# Generate random obstacles +n = 7 # Number of random obstacles +Obstacles = generate_random_cylindrical_obstacles(X, x_init, x_final_goal, n) + +# Define static obstacles +obstacles = [ + (10, 82, 0, 85, 15), + (80, 20, 0, 60, 19), + (10, 30, 0, 90, 15), + (80, 80, 0, 70, 22), + (50, 50, 0, 50, 22), +] + +# Combine static and randomly generated obstacles into one list +all_obstacles = obstacles + Obstacles +# Initialize the SearchSpace with all obstacles +X = SearchSpace(X_dimensions, all_obstacles) + +# RRT parameters +q = 700 +r = 1 +max_samples = 1024 +prc = 0.1 + +# DWA parameters +dwa_params = { + 'max_speed': 1.0, + 'min_speed': 0.0, + 'max_yaw_rate': 40.0 * np.pi / 180.0, + 'max_accel': 0.3, + 'v_reso': 0.05, + 'yaw_rate_reso': 0.2 * np.pi / 180.0, + 'dt': 0.1, + 'predict_time': 2.0, + 'to_goal_cost_gain': 1.5, + 'speed_cost_gain': 0.5, + 'obstacle_cost_gain': 1.0, +} +def compute_energy_usage(path, velocity): + energy = 0.0 + for i in range(1, len(path)): + distance = np.linalg.norm(np.array(path[i]) - np.array(path[i-1])) + energy += distance * velocity + return energy + +def min_obstacle_clearance(path, obstacles): + min_clearance = float('inf') + for point in path: + for obs in obstacles: + clearance = np.linalg.norm(np.array(point[:2]) - np.array(obs[:2])) - obs[4] + if clearance < min_clearance: + min_clearance = clearance + return min_clearance + +def path_length(path): + return sum(np.linalg.norm(np.array(path[i+1]) - np.array(path[i])) for i in range(len(path) - 1)) + +def path_smoothness(path): + total_curvature = 0.0 + for i in range(1, len(path) - 1): + vec1 = np.array(path[i]) - np.array(path[i-1]) + vec2 = np.array(path[i+1]) - np.array(path[i]) + angle = np.arccos(np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2))) + total_curvature += angle + return total_curvature + +# RRT pathfinding to first intermediate goal +print("RRT to first intermediate goal...") +start_time = time.time() +rrt = RRT(X, q, x_init, x_intermediate, max_samples, r, prc) +path1 = rrt.rrt_search() +rrt_time = time.time() - start_time + +if path1 is not None: + print("RRT to second intermediate goal...") + rrt = RRT(X, q, x_intermediate, x_second_goal, max_samples, r, prc) + path2 = rrt.rrt_search() + + if path2 is not None: + print("RRT to final goal...") + rrt = RRT(X, q, x_second_goal, x_final_goal, max_samples, r, prc) + path3 = rrt.rrt_search() + + # Combine all paths + if path3 is not None: + path = path1 + path2[1:] + path3[1:] + else: + path = path1 + path2[1:] + else: + path = path1 +else: + path = None + +# Apply DWA for local optimization along the RRT path +if path is not None: + dwa = DWA(dwa_params) + optimized_path = [] + + start_time = time.time() + for i in range(len(path) - 1): + start_point = path[i] + (0.0, 0.0) # Initialize v and w to 0, using tuple + end_point = path[i + 1] + + local_path = dwa.plan(start_point, end_point, X, all_obstacles) + optimized_path.extend(local_path) + dwa_time = time.time() - start_time + +# Metrics calculation and plotting +rrt_path_length = path_length(path) +dwa_path_length = path_length(optimized_path) + +rrt_smoothness = path_smoothness(path) +dwa_smoothness = path_smoothness(optimized_path) + +rrt_clearance = min_obstacle_clearance(path, all_obstacles) +dwa_clearance = min_obstacle_clearance(optimized_path, all_obstacles) + +average_velocity = dwa_params['max_speed'] +rrt_energy = compute_energy_usage(path, average_velocity) +dwa_energy = compute_energy_usage(optimized_path, average_velocity) +# Initialize the DroneEnv environment + +# Training the DQN +env = DroneEnv(X, x_init, x_final_goal, all_obstacles, dwa_params) +env.train(episodes=500) +# After training, use the learned policy in your DWA +state = env.reset() +done = False +optimized_path = [] + +while not done: + action = env.agent.act(state) + next_state, _, done = env.step(action) + optimized_path.append(next_state) + state = next_state + +# Initialize the DQN Agent +agent = DQNAgent(env.state_size, env.action_size) + +# Train the DQN agent +#agent.train(env, episodes=10) + +# Save the trained model +agent.model.save("dqn_model.keras") +# Print Metrics +print(f"RRT Path Length: {rrt_path_length}") +print(f"DWA Optimized Path Length: {dwa_path_length}") +print(f"RRT Path Smoothness: {rrt_smoothness}") +print(f"DWA Optimized Path Smoothness: {dwa_smoothness}") +print(f"RRT Path Minimum Clearance: {rrt_clearance}") +print(f"DWA Optimized Path Minimum Clearance: {dwa_clearance}") +print(f"RRT Path Energy Usage: {rrt_energy}") +print(f"DWA Optimized Path Energy Usage: {dwa_energy}") + + +# Plotting +plot = Plot("rrt_dwa_3d") +plot.plot_tree(X, rrt.trees) +plot.plot_path(X, path, color='red') # Plot the original RRT path in red +for point in optimized_path: + print("Point in optimized_path:", point) + +# Filter out incorrectly structured points (e.g., points that aren't tuples or lists with at least two elements) +filtered_optimized_path = [point for point in optimized_path if isinstance(point, (list, tuple)) and len(point) >= 2] + +# Now plot using the filtered path +plot.plot_path(X, filtered_optimized_path, color='blue') # Plot the optimized path in blue + +plot.plot_obstacles(X, all_obstacles) +plot.plot_start(X, x_init) +plot.plot_goal(X, x_intermediate, color="pink") +plot.plot_goal(X, x_second_goal, color="blue") +plot.plot_goal(X, x_final_goal, color="green") +plot.draw(auto_open=True) + diff --git a/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size+3.py b/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size+3.py new file mode 100644 index 0000000..68c7588 --- /dev/null +++ b/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size+3.py @@ -0,0 +1,382 @@ +# Texpanding the radius of the obstacles by the radius of the drone (10 cm) to ensure that the drone does not collide with any obstacles. This adjustment effectively treats the drone as a point but expands the obstacles to account for the drone's size. +import numpy as np +import time +from rtree import index +import sys +import uuid +import numpy as np +import skfuzzy as fuzz +from skfuzzy import control as ctrl +sys.path.append('/home/dell/rrt-algorithms') +import random +from rrt_algorithms.rrt.rrt import RRT +from rrt_algorithms.search_space.search_space2 import SearchSpace +from rrt_algorithms.utilities.plotting2 import Plot +from rrt_algorithms.dwa_algorithm.DWA3 import DWA, FuzzyController +from rrt_algorithms.dqn_algorithm.DQN import DQNAgent +from rrt_algorithms.dqn_algorithm.DQN import DroneEnv +from rrt_algorithms.utilities.obstacle_generation2 import generate_random_cylindrical_obstacles +from tensorflow.keras.models import load_model + +# Define the search space dimensions +X_dimensions = np.array([(0, 100), (0, 100), (0, 100)]) +X = SearchSpace(X_dimensions) +# Initial and goal positions +x_init = (50, 50, -2) +x_intermediate = (50, 50, 100) +x_second_goal = (20, 60, 100) +x_final_goal = (0, 0, 0) +#x_final_goal = (100, 100, 40) +# Create the search space + + +# Generate random obstacles +n = 7 # Number of random obstacles +Obstacles = generate_random_cylindrical_obstacles(X, x_init, x_final_goal, n) + +# Define static obstacles +obstacles = [ + (10, 82, 0, 85, 15), + (80, 20, 0, 60, 19), + (10, 30, 0, 90, 15), + (80, 80, 0, 70, 22), + (50, 50, 0, 50, 22), +] + +# Combine static and randomly generated obstacles into one list +all_obstacles = obstacles + Obstacles +# Initialize the SearchSpace with all obstacles +X = SearchSpace(X_dimensions, all_obstacles) + +# RRT parameters +q = 700 +r = 1 +max_samples = 1024 +prc = 0.1 + +# DWA parameters +dwa_params = { + 'max_speed': 1.0, + 'min_speed': 0.0, + 'max_yaw_rate': 40.0 * np.pi / 180.0, + 'max_accel': 0.3, + 'v_reso': 0.05, + 'yaw_rate_reso': 0.2 * np.pi / 180.0, + 'dt': 0.1, + 'predict_time': 2.0, + 'to_goal_cost_gain': 1.5, + 'speed_cost_gain': 0.5, + 'obstacle_cost_gain': 1.0, +} +def compute_energy_usage(path, velocity): + energy = 0.0 + for i in range(1, len(path)): + distance = np.linalg.norm(np.array(path[i]) - np.array(path[i-1])) + energy += distance * velocity + return energy + +def min_obstacle_clearance(path, obstacles): + min_clearance = float('inf') + for point in path: + for obs in obstacles: + clearance = np.linalg.norm(np.array(point[:2]) - np.array(obs[:2])) - obs[4] + if clearance < min_clearance: + min_clearance = clearance + return min_clearance + +def path_length(path): + return sum(np.linalg.norm(np.array(path[i+1]) - np.array(path[i])) for i in range(len(path) - 1)) + +def path_smoothness(path): + total_curvature = 0.0 + for i in range(1, len(path) - 1): + vec1 = np.array(path[i]) - np.array(path[i-1]) + vec2 = np.array(path[i+1]) - np.array(path[i]) + angle = np.arccos(np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2))) + total_curvature += angle + return total_curvature + + +# Adaptive Large Neighborhood Search (ALNS) Functions +def alns_optimize_path(path, X, all_obstacles, max_iterations=100): + """ + Optimize the path using ALNS with adaptive neighborhoods. + :param path: Initial path to optimize. + :param X: Search space object. + :param all_obstacles: List of all obstacles in the environment. + :param max_iterations: Maximum number of iterations for ALNS. + :return: Optimized path. + """ + neighborhoods = [segment_change, detour_addition, direct_connection] + neighborhood_scores = {segment_change: 1.0, detour_addition: 1.0, direct_connection: 1.0} + current_path = path.copy() + + for _ in range(max_iterations): + # Select neighborhood adaptively + neighborhood = random.choices(neighborhoods, weights=neighborhood_scores.values())[0] + new_path = neighborhood(current_path, X, all_obstacles) + + # Evaluate the new path + new_path_length = path_length(new_path) + current_path_length = path_length(current_path) + + if new_path_length < current_path_length: + current_path = new_path + neighborhood_scores[neighborhood] *= 1.1 # Reward successful neighborhood + else: + neighborhood_scores[neighborhood] *= 0.9 # Penalize unsuccessful neighborhood + + return current_path + +def segment_change(path, X, all_obstacles, r=1): + if len(path) < 3: + return path + + i = random.randint(0, len(path) - 3) + j = random.randint(i + 2, len(path) - 1) + + x_a = path[i] + x_b = path[j] + + spatial_x_a = np.array(x_a[:3]) + spatial_x_b = np.array(x_b[:3]) + + new_point_spatial = spatial_x_a + (spatial_x_b - spatial_x_a) / 2 + new_point = list(new_point_spatial) + list(x_a[3:]) + + if X.collision_free(spatial_x_a, new_point_spatial, r) and X.collision_free(new_point_spatial, spatial_x_b, r): + new_path = path[:i + 1] + [new_point] + path[j:] + return new_path + + return path + +def detour_addition(path, X, all_obstacles, r=1): + if len(path) < 2: + return path + + i = random.randint(0, len(path) - 2) + x_a = path[i] + x_b = path[i + 1] + + spatial_x_a = np.array(x_a[:3]) + spatial_x_b = np.array(x_b[:3]) + + detour_point_3d = spatial_x_a + (np.random.rand(3) - 0.5) * 2 * r + detour_point = list(detour_point_3d) + list(x_a[3:]) + + if X.collision_free(spatial_x_a, detour_point_3d, r) and X.collision_free(detour_point_3d, spatial_x_b, r): + new_path = path[:i + 1] + [detour_point] + path[i + 1:] + return new_path + + return path + + +def direct_connection(path, X, all_obstacles, r=1): + """ + Directly connect two non-adjacent points to shorten the path. + """ + if len(path) < 3: + return path # Can't directly connect if there aren't enough points + + new_path = path.copy() + i = random.randint(0, len(path) - 3) # Select a random starting point + j = random.randint(i + 2, len(path) - 1) # Select a random ending point + + x_a = path[i][:3] # Extract only the spatial coordinates (x, y, z) + x_b = path[j][:3] # Extract only the spatial coordinates (x, y, z) + + if X.collision_free(x_a, x_b, r): + new_path = new_path[:i + 1] + new_path[j:] # Remove the points between i and j + + return new_path + + + +# RRT pathfinding to the first intermediate goal +print("RRT to first intermediate goal...") +start_time = time.time() +rrt = RRT(X, q, x_init, x_intermediate, max_samples, r, prc) +path1 = rrt.rrt_search() +rrt_time = time.time() - start_time + +if path1 is not None: + print("RRT to second intermediate goal...") + rrt = RRT(X, q, x_intermediate, x_second_goal, max_samples, r, prc) + path2 = rrt.rrt_search() + + if path2 is not None: + print("RRT to final goal...") + rrt = RRT(X, q, x_second_goal, x_final_goal, max_samples, r, prc) + path3 = rrt.rrt_search() + + # Combine all paths + if path3 is not None: + path = path1 + path2[1:] + path3[1:] + else: + path = path1 + path2[1:] + else: + path = path1 +else: + path = None + +# Apply DWA for local optimization along the RRT path +if path is not None: + dwa = DWA(dwa_params) + optimized_path = [] + + start_time = time.time() + for i in range(len(path) - 1): + start_point = path[i] + (0.0, 0.0) # Initialize v and w to 0, using tuple + end_point = path[i + 1] + + local_path = dwa.plan(start_point, end_point, X, all_obstacles) + optimized_path.extend(local_path) + dwa_time = time.time() - start_time + + # Apply ALNS for global path optimization + alns_optimized_path = alns_optimize_path(optimized_path, X, all_obstacles, max_iterations=100) + + # Ensure all paths are correctly formatted and flatten nested structures + def validate_and_correct_path(path): + corrected_path = [] + for idx, point in enumerate(path): + if isinstance(point, (list, tuple)) and len(point) >= 2: + if isinstance(point[0], (list, tuple)): + point = [item for sublist in point for item in sublist] + corrected_path.append(point[:3]) # Ensure only the first three elements are used + else: + raise ValueError(f"Point {idx} in path is incorrectly formatted: {point}") + return corrected_path + + # Validate and correct paths + optimized_path = validate_and_correct_path(optimized_path) + alns_optimized_path = validate_and_correct_path(alns_optimized_path) + + # Metrics calculation + rrt_path_length = path_length(path) + dwa_path_length = path_length(optimized_path) + alns_path_length = path_length(alns_optimized_path) + + rrt_smoothness = path_smoothness(path) + dwa_smoothness = path_smoothness(optimized_path) + alns_smoothness = path_smoothness(alns_optimized_path) + + rrt_clearance = min_obstacle_clearance(path, all_obstacles) + dwa_clearance = min_obstacle_clearance(optimized_path, all_obstacles) + alns_clearance = min_obstacle_clearance(alns_optimized_path, all_obstacles) + + average_velocity = dwa_params['max_speed'] + rrt_energy = compute_energy_usage(path, average_velocity) + dwa_energy = compute_energy_usage(optimized_path, average_velocity) + alns_energy = compute_energy_usage(alns_optimized_path, average_velocity) + # Training the DQN + env = DroneEnv(X, x_init, x_final_goal, all_obstacles, dwa_params) + env.train(episodes=10) + # After training, use the learned policy in your DWA + + # Initialize the DroneEnv environment for path optimization + state = env.reset() + done = False + optimized_path = [] +agent = DQNAgent(env.state_size, env.action_size) + + + + + + +while not done: + action = agent.act(state) + next_state, _, done = env.step(action) + optimized_path.append(next_state) + state = next_state + # Save the trained DQN model + #agent = DQNAgent(env.state_size, env.action_size) + # Save the trained model + agent.model.save("dqn_model.keras") + print("DQN model saved as dqn_model.keras") + + + + + + # Print Metrics + print(f"RRT Path Length: {rrt_path_length}") + print(f"DWA Optimized Path Length: {dwa_path_length}") + print(f"ALNS Optimized Path Length: {alns_path_length}") + print(f"RRT Path Smoothness: {rrt_smoothness}") + print(f"DWA Optimized Path Smoothness: {dwa_smoothness}") + print(f"ALNS Optimized Path Smoothness: {alns_smoothness}") + print(f"RRT Path Minimum Clearance: {rrt_clearance}") + print(f"DWA Optimized Path Minimum Clearance: {dwa_clearance}") + print(f"ALNS Optimized Path Minimum Clearance: {alns_clearance}") + print(f"RRT Path Energy Usage: {rrt_energy}") + print(f"DWA Optimized Path Energy Usage: {dwa_energy}") + print(f"ALNS Optimized Path Energy Usage: {alns_energy}") + + +def inspect_and_print_path(path): + """ + Inspects and prints the structure of the path for debugging. + """ + for idx, point in enumerate(path): + print(f"Point {idx} in path: {point} (Type: {type(point)})") + if isinstance(point, (list, tuple)): + for sub_idx, sub_point in enumerate(point): + print(f" Sub-point {sub_idx}: {sub_point} (Type: {type(sub_point)})") +def inspect_path(path, path_name): + if path is None or len(path) == 0: + print(f"{path_name} is empty or None.") + else: + print(f"{path_name} contains {len(path)} points. Sample points: {path[:5]}") + +# Inspect paths +inspect_path(path1, "RRT Path 1") +inspect_path(path2, "RRT Path 2") +inspect_path(path3, "RRT Path 3") +inspect_path(optimized_path, "DWA Optimized Path") +inspect_path(alns_optimized_path, "ALNS Optimized Path") + +def flatten_path_points(path): + """ + Flattens any nested numpy arrays in the path and ensures that each point is a list or tuple with at least three elements. + Returns a cleaned and flattened path. + """ + cleaned_path = [] + for idx, point in enumerate(path): + if isinstance(point, np.ndarray): + # Flatten the array and convert to a list + flat_point = point.flatten().tolist() + if len(flat_point) >= 3: + cleaned_path.append(flat_point[:3]) # Take only the first three elements (x, y, z) + else: + raise ValueError(f"Point {idx} in optimized_path is incorrectly formatted: {flat_point}") + else: + raise ValueError(f"Point {idx} in optimized_path is not a list or tuple: {point}") + return cleaned_path + +# Apply the flattening function to optimized_path before plotting +try: + optimized_path = flatten_path_points(optimized_path) +except ValueError as e: + print(f"Error encountered during flattening: {e}") + + +# Debug the flattened path points +for idx, point in enumerate(optimized_path): + print(f"Point {idx} in optimized_path after flattening: {point}") + +# Plotting +plot = Plot("rrt_dwa_alns_3d") + +# Your existing plotting code follows +plot.plot_tree(X, rrt.trees) +plot.plot_path(X, path, color='red') # Plot the original RRT path in red +plot.plot_path(X, optimized_path, color='blue') # Plot the DWA optimized path in blue +plot.plot_path(X, alns_optimized_path, color='green') # Plot the ALNS optimized path in green +plot.plot_obstacles(X, all_obstacles) # Now this line should work +plot.plot_start(X, x_init) +plot.plot_goal(X, x_intermediate, color="pink") +plot.plot_goal(X, x_second_goal, color="blue") +plot.plot_goal(X, x_final_goal, color="green") +plot.draw(auto_open=True) diff --git a/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size+4.py b/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size+4.py new file mode 100644 index 0000000..47d25a7 --- /dev/null +++ b/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size+4.py @@ -0,0 +1,326 @@ +# Texpanding the radius of the obstacles by the radius of the drone (10 cm) to ensure that the drone does not collide with any obstacles. This adjustment effectively treats the drone as a point but expands the obstacles to account for the drone's size. +import numpy as np +import time +from rtree import index +import sys +import uuid +import numpy as np +import skfuzzy as fuzz +from skfuzzy import control as ctrl +sys.path.append('/home/dell/rrt-algorithms') +import random +import matplotlib.pyplot as plt +from matplotlib.animation import FuncAnimation +from rrt_algorithms.rrt.rrt import RRT +from rrt_algorithms.search_space.search_space2 import SearchSpace +from rrt_algorithms.utilities.plotting2 import Plot +from rrt_algorithms.dwa_algorithm.DWA3 import DWA, FuzzyController +from rrt_algorithms.dqn_algorithm.DQN import DQNAgent +from rrt_algorithms.dqn_algorithm.DQN import DroneEnv +from rrt_algorithms.utilities.obstacle_generation2 import generate_random_cylindrical_obstacles +from tensorflow.keras.models import load_model + +# Define the search space dimensions +X_dimensions = np.array([(0, 100), (0, 100), (0, 100)]) +X = SearchSpace(X_dimensions) +# Initial and goal positions +x_init = (50, 50, -2) +x_intermediate = (50, 50, 100) +x_second_goal = (20, 60, 100) +x_final_goal = (0, 0, 0) +#x_final_goal = (100, 100, 40) +# Create the search space + + +# Generate random obstacles +n = 10 # Number of random obstacles +Obstacles = generate_random_cylindrical_obstacles(X, x_init, x_final_goal, n) + +# Define static obstacles +obstacles = [ + (10, 82, 0, 85, 15), + (80, 20, 0, 60, 19), + (10, 30, 0, 90, 15), + (80, 80, 0, 70, 22), + (50, 50, 0, 50, 22), +] + +# Combine static and randomly generated obstacles into one list +all_obstacles = obstacles + Obstacles +# Initialize the SearchSpace with all obstacles +X = SearchSpace(X_dimensions, all_obstacles) + +# RRT parameters +q = 500 # Extension length +r = 1 +max_samples = 4000 # Maximum samples +prc = 0.1 # Probability of choosing goal as the next point + +# DWA parameters +dwa_params = { + 'max_speed': 2.0, + 'min_speed': 0.0, + 'max_yaw_rate': 40.0 * np.pi / 180.0, + 'max_accel': 0.3, + 'v_reso': 0.05, + 'yaw_rate_reso': 0.2 * np.pi / 180.0, + 'dt': 0.1, + 'predict_time': 2.0, + 'to_goal_cost_gain': 1.5, + 'speed_cost_gain': 0.5, + 'obstacle_cost_gain': 1.0, +} + +# Functions for computing metrics +def compute_energy_usage(path, velocity): + energy = 0.0 + for i in range(1, len(path)): + distance = np.linalg.norm(np.array(path[i]) - np.array(path[i-1])) + energy += distance * velocity + return energy + +def min_obstacle_clearance(path, obstacles): + min_clearance = float('inf') + for point in path: + for obs in obstacles: + clearance = np.linalg.norm(np.array(point[:2]) - np.array(obs[:2])) - obs[4] + if clearance < min_clearance: + min_clearance = clearance + return min_clearance + +def path_length(path): + return sum(np.linalg.norm(np.array(path[i+1]) - np.array(path[i])) for i in range(len(path) - 1)) + +def path_smoothness(path): + total_curvature = 0.0 + for i in range(1, len(path) - 1): + vec1 = np.array(path[i]) - np.array(path[i-1]) + vec2 = np.array(path[i+1]) - np.array(path[i]) + angle = np.arccos(np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2))) + total_curvature += angle + return total_curvature + +# ALNS functions +def alns_optimize_path(path, X, all_obstacles, max_iterations=100): + neighborhoods = [segment_change, detour_addition, direct_connection] + neighborhood_scores = {segment_change: 1.0, detour_addition: 1.0, direct_connection: 1.0} + current_path = path.copy() + + for _ in range(max_iterations): + neighborhood = random.choices(neighborhoods, weights=neighborhood_scores.values())[0] + new_path = neighborhood(current_path, X, all_obstacles) + + if path_length(new_path) < path_length(current_path): + current_path = new_path + neighborhood_scores[neighborhood] *= 1.1 # Reward successful neighborhood + else: + neighborhood_scores[neighborhood] *= 0.9 # Penalize unsuccessful neighborhood + + return current_path + +def segment_change(path, X, all_obstacles, r=1): + if len(path) < 3: + return path + + i = random.randint(0, len(path) - 3) + j = random.randint(i + 2, len(path) - 1) + + x_a = path[i] + x_b = path[j] + + spatial_x_a = np.array(x_a[:3]) + spatial_x_b = np.array(x_b[:3]) + + new_point_spatial = spatial_x_a + (spatial_x_b - spatial_x_a) / 2 + new_point = list(new_point_spatial) + list(x_a[3:]) + + if X.collision_free(spatial_x_a, new_point_spatial, r) and X.collision_free(new_point_spatial, spatial_x_b, r): + new_path = path[:i + 1] + [new_point] + path[j:] + return new_path + + return path + +def detour_addition(path, X, all_obstacles, r=1): + if len(path) < 2: + return path + + i = random.randint(0, len(path) - 2) + x_a = path[i] + x_b = path[i + 1] + + spatial_x_a = np.array(x_a[:3]) + spatial_x_b = np.array(x_b[:3]) + + detour_point_3d = spatial_x_a + (np.random.rand(3) - 0.5) * 2 * r + detour_point = list(detour_point_3d) + list(x_a[3:]) + + if X.collision_free(spatial_x_a, detour_point_3d, r) and X.collision_free(detour_point_3d, spatial_x_b, r): + new_path = path[:i + 1] + [detour_point] + path[i + 1:] + return new_path + + return path + +def direct_connection(path, X, all_obstacles, r=1): + if len(path) < 3: + return path + + new_path = path.copy() + i = random.randint(0, len(path) - 3) + j = random.randint(i + 2, len(path) - 1) + + x_a = path[i][:3] + x_b = path[j][:3] + + if X.collision_free(x_a, x_b, r): + new_path = new_path[:i + 1] + new_path[j:] + + return new_path + +# Continuous Learning Loop Parameters +episodes = 10 # Number of training episodes +optimize_every = 10 # Frequency of re-optimization and re-training +# Initialize DQN Agent +env = DroneEnv(X, x_init, x_final_goal, all_obstacles, dwa_params) +try: + agent = DQNAgent(env.state_size, env.action_size) + agent.model = load_model("dqn_model.keras") + print("Loaded existing DQN model.") +except: + agent = DQNAgent(env.state_size, env.action_size) + print("Initialized new DQN model.") + +# Lists to store paths for animation +paths_to_animate = [] + +# Training Loop +for episode in range(episodes): + print(f"Episode: {episode + 1}/{episodes}") + + state = env.reset() + done = False + episode_path = [] + + # RRT Pathfinding to the goals + print("RRT pathfinding...") + rrt = RRT(X, q, x_init, x_intermediate, max_samples, r, prc) + path1 = rrt.rrt_search() + + if path1 is not None: + rrt = RRT(X, q, x_intermediate, x_second_goal, max_samples, r, prc) + path2 = rrt.rrt_search() + + if path2 is not None: + rrt = RRT(X, q, x_second_goal, x_final_goal, max_samples, r, prc) + path3 = rrt.rrt_search() + + if path3 is not None: + path = path1 + path2[1:] + path3[1:] + else: + path = path1 + path2[1:] + else: + path = path1 + else: + path = None + + if path is not None: + print("Optimizing path with DWA...") + dwa = DWA(dwa_params) + optimized_path = [] + + for i in range(len(path) - 1): + start_point = path[i] + (0.0, 0.0) + end_point = path[i + 1] + local_path = dwa.plan(start_point, end_point, X, all_obstacles) + optimized_path.extend(local_path) + + print("Optimizing path with ALNS...") + alns_optimized_path = alns_optimize_path(optimized_path, X, all_obstacles, max_iterations=100) + + paths_to_animate.append(alns_optimized_path) + + for idx, point in enumerate(alns_optimized_path): + action = agent.act(state) + next_state, reward, done = env.step(action) + agent.remember(state, action, reward, next_state, done) + episode_path.append(next_state) + state = next_state + + if (episode + 1) % optimize_every == 0: + print("Re-training the DQN model...") + agent.replay(32) + agent.model.save("dqn_model.keras") + + # Metrics calculation + rrt_path_length = path_length(path) + dwa_path_length = path_length(optimized_path) + alns_path_length = path_length(alns_optimized_path) + + rrt_smoothness = path_smoothness(path) + dwa_smoothness = path_smoothness(optimized_path) + alns_smoothness = path_smoothness(alns_optimized_path) + + rrt_clearance = min_obstacle_clearance(path, all_obstacles) + dwa_clearance = min_obstacle_clearance(optimized_path, all_obstacles) + alns_clearance = min_obstacle_clearance(alns_optimized_path, all_obstacles) + + average_velocity = dwa_params['max_speed'] + rrt_energy = compute_energy_usage(path, average_velocity) + dwa_energy = compute_energy_usage(optimized_path, average_velocity) + alns_energy = compute_energy_usage(alns_optimized_path, average_velocity) + + # Print Metrics + print(f"RRT Path Length: {rrt_path_length}") + print(f"DWA Optimized Path Length: {dwa_path_length}") + print(f"ALNS Optimized Path Length: {alns_path_length}") + print(f"RRT Path Smoothness: {rrt_smoothness}") + print(f"DWA Optimized Path Smoothness: {dwa_smoothness}") + print(f"ALNS Optimized Path Smoothness: {alns_smoothness}") + print(f"RRT Path Minimum Clearance: {rrt_clearance}") + print(f"DWA Optimized Path Minimum Clearance: {dwa_clearance}") + print(f"ALNS Optimized Path Minimum Clearance: {alns_clearance}") + print(f"RRT Path Energy Usage: {rrt_energy}") + print(f"DWA Optimized Path Energy Usage: {dwa_energy}") + print(f"ALNS Optimized Path Energy Usage: {alns_energy}") + else: + print("No path found, skipping episode.") + +# Plotting and Animation +fig = plt.figure() +ax = fig.add_subplot(111, projection='3d') + +# Function to draw cylindrical obstacles +def draw_cylinder(ax, center_x, center_y, z_min, z_max, radius, color='red', alpha=0.5): + z = np.linspace(z_min, z_max, 100) + theta = np.linspace(0, 2*np.pi, 100) + theta_grid, z_grid = np.meshgrid(theta, z) + x_grid = radius * np.cos(theta_grid) + center_x + y_grid = radius * np.sin(theta_grid) + center_y + ax.plot_surface(x_grid, y_grid, z_grid, color=color, alpha=alpha) + +# Function to update the plot +def update(num): + ax.clear() + ax.set_xlim(0, 100) + ax.set_ylim(0, 100) + ax.set_zlim(0, 100) + ax.set_xlabel('X') + ax.set_ylabel('Y') + ax.set_zlabel('Z') + ax.set_title(f"Path Optimization - Episode {num + 1}") + + path = paths_to_animate[num] + x_vals = [point[0] for point in path] + y_vals = [point[1] for point in path] + z_vals = [point[2] for point in path] + ax.plot(x_vals, y_vals, z_vals, color='green') + + for obs in all_obstacles: + draw_cylinder(ax, obs[0], obs[1], obs[2], obs[3], obs[4]) + + ax.scatter(x_init[0], x_init[1], x_init[2], c='blue', marker='o', label="Start") + ax.scatter(x_intermediate[0], x_intermediate[1], x_intermediate[2], c='pink', marker='^', label="Intermediate Goal") + ax.scatter(x_second_goal[0], x_second_goal[1], x_second_goal[2], c='purple', marker='s', label="Second Goal") + ax.scatter(x_final_goal[0], x_final_goal[1], x_final_goal[2], c='yellow', marker='*', label="Final Goal") + +ani = FuncAnimation(fig, update, frames=len(paths_to_animate), interval=10000, repeat=False) +plt.show() diff --git a/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size+5.py b/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size+5.py new file mode 100644 index 0000000..fd93781 --- /dev/null +++ b/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size+5.py @@ -0,0 +1,334 @@ +import numpy as np +import time +from rtree import index +import sys +import uuid +import numpy as np +import skfuzzy as fuzz +from skfuzzy import control as ctrl +import random +from tensorflow.keras.models import load_model + +sys.path.append('/home/dell/rrt-algorithms') + +from rrt_algorithms.rrt.rrt import RRT +from rrt_algorithms.search_space.search_space2 import SearchSpace +from rrt_algorithms.utilities.plotting2 import Plot +from rrt_algorithms.dwa_algorithm.DWA3 import DWA, FuzzyController +from rrt_algorithms.dqn_algorithm.DQN import DQNAgent +from rrt_algorithms.dqn_algorithm.DQN import DroneEnv +from rrt_algorithms.utilities.obstacle_generation2 import generate_random_cylindrical_obstacles + +# Define the search space dimensions +X_dimensions = np.array([(0, 100), (0, 100), (0, 100)]) +X = SearchSpace(X_dimensions) + +# Initial and goal positions +x_init = (50, 50, -2) +x_intermediate = (50, 50, 100) +x_second_goal = (20, 60, 100) +x_final_goal = (0, 0, 0) + +# Generate random obstacles +n = 7 # Number of random obstacles +Obstacles = generate_random_cylindrical_obstacles(X, x_init, x_final_goal, n) + +# Define static obstacles +obstacles = [ + (10, 82, 0, 85, 15), + (80, 20, 0, 60, 19), + (10, 30, 0, 90, 15), + (80, 80, 0, 70, 22), + (50, 50, 0, 50, 22), +] + +# Combine static and randomly generated obstacles into one list +all_obstacles = obstacles + Obstacles +# Initialize the SearchSpace with all obstacles +X = SearchSpace(X_dimensions, all_obstacles) + +# RRT parameters +q = 700 +r = 1 +max_samples = 2024 +prc = 0.1 + +# DWA parameters +dwa_params = { + 'max_speed': 1.0, + 'min_speed': 0.0, + 'max_yaw_rate': 40.0 * np.pi / 180.0, + 'max_accel': 0.3, + 'v_reso': 0.05, + 'yaw_rate_reso': 0.2 * np.pi / 180.0, + 'dt': 0.1, + 'predict_time': 2.0, + 'to_goal_cost_gain': 1.5, + 'speed_cost_gain': 0.5, + 'obstacle_cost_gain': 1.0, +} + +def compute_energy_usage(path, velocity): + energy = 0.0 + for i in range(1, len(path)): + distance = np.linalg.norm(np.array(path[i]) - np.array(path[i-1])) + energy += distance * velocity + return energy + +def min_obstacle_clearance(path, obstacles): + min_clearance = float('inf') + for point in path: + for obs in obstacles: + clearance = np.linalg.norm(np.array(point[:2]) - np.array(obs[:2])) - obs[4] + if clearance < min_clearance: + min_clearance = clearance + return min_clearance + +def path_length(path): + return sum(np.linalg.norm(np.array(path[i+1]) - np.array(path[i])) for i in range(len(path) - 1)) + +def path_smoothness(path): + total_curvature = 0.0 + for i in range(1, len(path) - 1): + vec1 = np.array(path[i]) - np.array(path[i-1]) + vec2 = np.array(path[i+1]) - np.array(path[i]) + angle = np.arccos(np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2))) + total_curvature += angle + return total_curvature + + +# Adaptive Large Neighborhood Search (ALNS) Functions +def alns_optimize_path(path, X, all_obstacles, max_iterations=100): + neighborhoods = [segment_change, detour_addition, direct_connection] + neighborhood_scores = {segment_change: 1.0, detour_addition: 1.0, direct_connection: 1.0} + current_path = path.copy() + + for _ in range(max_iterations): + # Select neighborhood adaptively + neighborhood = random.choices(neighborhoods, weights=neighborhood_scores.values())[0] + new_path = neighborhood(current_path, X, all_obstacles) + + # Evaluate the new path + new_path_length = path_length(new_path) + current_path_length = path_length(current_path) + + if new_path_length < current_path_length: + current_path = new_path + neighborhood_scores[neighborhood] *= 1.1 # Reward successful neighborhood + else: + neighborhood_scores[neighborhood] *= 0.9 # Penalize unsuccessful neighborhood + + return current_path + +def segment_change(path, X, all_obstacles, r=1): + if len(path) < 3: + return path + + i = random.randint(0, len(path) - 3) + j = random.randint(i + 2, len(path) - 1) + + x_a = path[i] + x_b = path[j] + + spatial_x_a = np.array(x_a[:3]) + spatial_x_b = np.array(x_b[:3]) + + new_point_spatial = spatial_x_a + (spatial_x_b - spatial_x_a) / 2 + new_point = list(new_point_spatial) + list(x_a[3:]) + + if X.collision_free(spatial_x_a, new_point_spatial, r) and X.collision_free(new_point_spatial, spatial_x_b, r): + new_path = path[:i + 1] + [new_point] + path[j:] + return new_path + + return path + +def detour_addition(path, X, all_obstacles, r=1): + if len(path) < 2: + return path + + i = random.randint(0, len(path) - 2) + x_a = path[i] + x_b = path[i + 1] + + spatial_x_a = np.array(x_a[:3]) + spatial_x_b = np.array(x_b[:3]) + + detour_point_3d = spatial_x_a + (np.random.rand(3) - 0.5) * 2 * r + detour_point = list(detour_point_3d) + list(x_a[3:]) + + if X.collision_free(spatial_x_a, detour_point_3d, r) and X.collision_free(detour_point_3d, spatial_x_b, r): + new_path = path[:i + 1] + [detour_point] + path[i + 1:] + return new_path + + return path + + +def direct_connection(path, X, all_obstacles, r=1): + if len(path) < 3: + return path # Can't directly connect if there aren't enough points + + new_path = path.copy() + i = random.randint(0, len(path) - 3) # Select a random starting point + j = random.randint(i + 2, len(path) - 1) # Select a random ending point + + x_a = path[i][:3] # Extract only the spatial coordinates (x, y, z) + x_b = path[j][:3] # Extract only the spatial coordinates (x, y, z) + + if X.collision_free(x_a, x_b, r): + new_path = new_path[:i + 1] + new_path[j:] # Remove the points between i and j + + return new_path + +# RRT pathfinding to the first intermediate goal +print("RRT to first intermediate goal...") +start_time = time.time() +rrt = RRT(X, q, x_init, x_intermediate, max_samples, r, prc) +path1 = rrt.rrt_search() +rrt_time = time.time() - start_time + +if path1 is not None: + print("RRT to second intermediate goal...") + rrt = RRT(X, q, x_intermediate, x_second_goal, max_samples, r, prc) + path2 = rrt.rrt_search() + + if path2 is not None: + print("RRT to final goal...") + rrt = RRT(X, q, x_second_goal, x_final_goal, max_samples, r, prc) + path3 = rrt.rrt_search() + + # Combine all paths + if path3 is not None: + path = path1 + path2[1:] + path3[1:] + else: + path = path1 + path2[1:] + else: + path = path1 +else: + path = None + +# Apply DWA for local optimization along the RRT path +if path is not None: + dwa = DWA(dwa_params) + optimized_path = [] + + start_time = time.time() + for i in range(len(path) - 1): + start_point = path[i] + (0.0, 0.0) # Initialize v and w to 0, using tuple + end_point = path[i + 1] + + local_path = dwa.plan(start_point, end_point, X, all_obstacles) + optimized_path.extend(local_path) + dwa_time = time.time() - start_time + + # Apply ALNS for global path optimization + alns_optimized_path = alns_optimize_path(optimized_path, X, all_obstacles, max_iterations=100) + + # Ensure all paths are correctly formatted and flatten nested structures + def validate_and_correct_path(path): + corrected_path = [] + for idx, point in enumerate(path): + if isinstance(point, (list, tuple)) and len(point) >= 2: + if isinstance(point[0], (list, tuple)): + point = [item for sublist in point for item in sublist] + corrected_path.append(point[:3]) # Ensure only the first three elements are used + else: + raise ValueError(f"Point {idx} in path is incorrectly formatted: {point}") + return corrected_path + + # Validate and correct paths + optimized_path = validate_and_correct_path(optimized_path) + alns_optimized_path = validate_and_correct_path(alns_optimized_path) + + # Metrics calculation + rrt_path_length = path_length(path) + dwa_path_length = path_length(optimized_path) + alns_path_length = path_length(alns_optimized_path) + + rrt_smoothness = path_smoothness(path) + dwa_smoothness = path_smoothness(optimized_path) + alns_smoothness = path_smoothness(alns_optimized_path) + + rrt_clearance = min_obstacle_clearance(path, all_obstacles) + dwa_clearance = min_obstacle_clearance(optimized_path, all_obstacles) + alns_clearance = min_obstacle_clearance(alns_optimized_path, all_obstacles) + + average_velocity = dwa_params['max_speed'] + rrt_energy = compute_energy_usage(path, average_velocity) + dwa_energy = compute_energy_usage(optimized_path, average_velocity) + alns_energy = compute_energy_usage(alns_optimized_path, average_velocity) + +# Training the DQN +env = DroneEnv(X, x_init, x_final_goal, all_obstacles, dwa_params) +env.train(episodes=10) +# After training, use the learned policy in your DWA + +# Initialize the DroneEnv environment for path optimization +state = env.reset() +done = False +optimized_path = [] +agent = DQNAgent(env.state_size, env.action_size) + +while not done: + action = agent.act(state) + next_state, _, done = env.step(action) + optimized_path.append(next_state) + state = next_state + +# Save the trained DQN model +agent.model.save("dqn_model.keras") +print("DQN model saved as dqn_model.keras") + +# Print Metrics +print(f"RRT Path Length: {rrt_path_length}") +print(f"DWA Optimized Path Length: {dwa_path_length}") +print(f"ALNS Optimized Path Length: {alns_path_length}") +print(f"RRT Path Smoothness: {rrt_smoothness}") +print(f"DWA Optimized Path Smoothness: {dwa_smoothness}") +print(f"ALNS Optimized Path Smoothness: {alns_smoothness}") +print(f"RRT Path Minimum Clearance: {rrt_clearance}") +print(f"DWA Optimized Path Minimum Clearance: {dwa_clearance}") +print(f"ALNS Optimized Path Minimum Clearance: {alns_clearance}") +print(f"RRT Path Energy Usage: {rrt_energy}") +print(f"DWA Optimized Path Energy Usage: {dwa_energy}") +print(f"ALNS Optimized Path Energy Usage: {alns_energy}") + +# Ensure the final paths are properly flattened and structured +def flatten_path_points(path): + cleaned_path = [] + for idx, point in enumerate(path): + if isinstance(point, np.ndarray): + # Flatten the array and convert to a list + flat_point = point.flatten().tolist() + if len(flat_point) >= 3: + cleaned_path.append(flat_point[:3]) # Take only the first three elements (x, y, z) + else: + raise ValueError(f"Point {idx} in optimized_path is incorrectly formatted: {flat_point}") + else: + raise ValueError(f"Point {idx} in optimized_path is not a list or tuple: {point}") + return cleaned_path + +# Apply the flattening function to optimized_path before plotting +try: + optimized_path = flatten_path_points(optimized_path) +except ValueError as e: + print(f"Error encountered during flattening: {e}") + +# Plotting +plot = Plot("rrt_dwa_alns_3d") + +# Plotting the paths +plot.plot_tree(X, rrt.trees) # Plot the RRT search tree +plot.plot_path(X, path, color='red') # Plot the original RRT path in red +plot.plot_path(X, optimized_path, color='blue') # Plot the DWA optimized path in blue +plot.plot_path(X, alns_optimized_path, color='green') # Plot the ALNS optimized path in green +plot.plot_obstacles(X, all_obstacles) # Plot all obstacles + +# Plot the start and goal positions +plot.plot_start(X, x_init) +plot.plot_goal(X, x_intermediate, color="pink") +plot.plot_goal(X, x_second_goal, color="blue") +plot.plot_goal(X, x_final_goal, color="green") + +# Draw the plot +plot.draw(auto_open=True) + diff --git a/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size+7.png b/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size+7.png new file mode 100644 index 0000000..e9f3ab3 Binary files /dev/null and b/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size+7.png differ diff --git a/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size+7.py b/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size+7.py new file mode 100644 index 0000000..34620ed --- /dev/null +++ b/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size+7.py @@ -0,0 +1,390 @@ +import numpy as np +import time +from rtree import index +import sys +import uuid +import numpy as np +import skfuzzy as fuzz +from skfuzzy import control as ctrl +import random +from tensorflow.keras.models import load_model +import matplotlib.pyplot as plt +import matplotlib.animation as animation + +sys.path.append('/home/dell/rrt-algorithms') + +from rrt_algorithms.rrt.rrt import RRT +from rrt_algorithms.search_space.search_space2 import SearchSpace +from rrt_algorithms.utilities.plotting2 import Plot +from rrt_algorithms.dwa_algorithm.DWA3 import DWA, FuzzyController +from rrt_algorithms.dqn_algorithm.DQN import DQNAgent +from rrt_algorithms.dqn_algorithm.DQN import DroneEnv +from rrt_algorithms.utilities.obstacle_generation2 import generate_random_cylindrical_obstacles + +# Define the search space dimensions +X_dimensions = np.array([(0, 100), (0, 100), (0, 100)]) +X = SearchSpace(X_dimensions) + +# Initial and goal positions +x_init = (50, 50, -2) +x_intermediate = (50, 50, 100) +x_second_goal = (20, 60, 100) +x_final_goal = (0, 0, 0) + +# Generate random obstacles +n = 7 # Number of random obstacles +Obstacles = generate_random_cylindrical_obstacles(X, x_init, x_final_goal, n) + +# Define static obstacles +obstacles = [ + (10, 82, 0, 85, 15), + (80, 20, 0, 60, 19), + (10, 30, 0, 90, 15), + (80, 80, 0, 70, 22), + (50, 50, 0, 50, 22), +] + +# Combine static and randomly generated obstacles into one list +all_obstacles = obstacles + Obstacles +# Initialize the SearchSpace with all obstacles +X = SearchSpace(X_dimensions, all_obstacles) + +# RRT parameters +q = 700 +r = 1 +max_samples = 2024 +prc = 0.1 + +# DWA parameters +dwa_params = { + 'max_speed': 1.0, + 'min_speed': 0.0, + 'max_yaw_rate': 40.0 * np.pi / 180.0, + 'max_accel': 0.3, + 'v_reso': 0.05, + 'yaw_rate_reso': 0.2 * np.pi / 180.0, + 'dt': 0.1, + 'predict_time': 2.0, + 'to_goal_cost_gain': 1.5, + 'speed_cost_gain': 0.5, + 'obstacle_cost_gain': 1.0, +} + +def compute_energy_usage(path, velocity): + energy = 0.0 + for i in range(1, len(path)): + distance = np.linalg.norm(np.array(path[i]) - np.array(path[i-1])) + energy += distance * velocity + return energy + +def min_obstacle_clearance(path, obstacles): + min_clearance = float('inf') + for point in path: + for obs in obstacles: + clearance = np.linalg.norm(np.array(point[:2]) - np.array(obs[:2])) - obs[4] + if clearance < min_clearance: + min_clearance = clearance + return min_clearance + +def path_length(path): + return sum(np.linalg.norm(np.array(path[i+1]) - np.array(path[i])) for i in range(len(path) - 1)) + +def path_smoothness(path): + total_curvature = 0.0 + for i in range(1, len(path) - 1): + vec1 = np.array(path[i]) - np.array(path[i-1]) + vec2 = np.array(path[i+1]) - np.array(path[i]) + angle = np.arccos(np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2))) + total_curvature += angle + return total_curvature + + +# Adaptive Large Neighborhood Search (ALNS) Functions +def alns_optimize_path(path, X, all_obstacles, max_iterations=100): + neighborhoods = [segment_change, detour_addition, direct_connection] + neighborhood_scores = {segment_change: 1.0, detour_addition: 1.0, direct_connection: 1.0} + current_path = path.copy() + + for _ in range(max_iterations): + # Select neighborhood adaptively + neighborhood = random.choices(neighborhoods, weights=neighborhood_scores.values())[0] + new_path = neighborhood(current_path, X, all_obstacles) + + # Evaluate the new path + new_path_length = path_length(new_path) + current_path_length = path_length(current_path) + + if new_path_length < current_path_length: + current_path = new_path + neighborhood_scores[neighborhood] *= 1.1 # Reward successful neighborhood + else: + neighborhood_scores[neighborhood] *= 0.9 # Penalize unsuccessful neighborhood + + return current_path + +def segment_change(path, X, all_obstacles, r=1): + if len(path) < 3: + return path + + i = random.randint(0, len(path) - 3) + j = random.randint(i + 2, len(path) - 1) + + x_a = path[i] + x_b = path[j] + + spatial_x_a = np.array(x_a[:3]) + spatial_x_b = np.array(x_b[:3]) + + new_point_spatial = spatial_x_a + (spatial_x_b - spatial_x_a) / 2 + new_point = list(new_point_spatial) + list(x_a[3:]) + + if X.collision_free(spatial_x_a, new_point_spatial, r) and X.collision_free(new_point_spatial, spatial_x_b, r): + new_path = path[:i + 1] + [new_point] + path[j:] + return new_path + + return path + +def detour_addition(path, X, all_obstacles, r=1): + if len(path) < 2: + return path + + i = random.randint(0, len(path) - 2) + x_a = path[i] + x_b = path[i + 1] + + spatial_x_a = np.array(x_a[:3]) + spatial_x_b = np.array(x_b[:3]) + + detour_point_3d = spatial_x_a + (np.random.rand(3) - 0.5) * 2 * r + detour_point = list(detour_point_3d) + list(x_a[3:]) + + if X.collision_free(spatial_x_a, detour_point_3d, r) and X.collision_free(detour_point_3d, spatial_x_b, r): + new_path = path[:i + 1] + [detour_point] + path[i + 1:] + return new_path + + return path + + +def direct_connection(path, X, all_obstacles, r=1): + if len(path) < 3: + return path # Can't directly connect if there aren't enough points + + new_path = path.copy() + i = random.randint(0, len(path) - 3) # Select a random starting point + j = random.randint(i + 2, len(path) - 1) # Select a random ending point + + x_a = path[i][:3] # Extract only the spatial coordinates (x, y, z) + x_b = path[j][:3] # Extract only the spatial coordinates (x, y, z) + + if X.collision_free(x_a, x_b, r): + new_path = new_path[:i + 1] + new_path[j:] # Remove the points between i and j + + return new_path + +def find_closest_point(path, goal): + distances = [np.linalg.norm(np.array(p[:3]) - np.array(goal)) for p in path] + return np.argmin(distances) + +# RRT pathfinding to the first intermediate goal +print("RRT to first intermediate goal...") +start_time = time.time() +rrt = RRT(X, q, x_init, x_intermediate, max_samples, r, prc) +path1 = rrt.rrt_search() +rrt_time = time.time() - start_time + +if path1 is not None: + print("RRT to second intermediate goal...") + rrt = RRT(X, q, x_intermediate, x_second_goal, max_samples, r, prc) + path2 = rrt.rrt_search() + + if path2 is not None: + print("RRT to final goal...") + rrt = RRT(X, q, x_second_goal, x_final_goal, max_samples, r, prc) + path3 = rrt.rrt_search() + + # Combine all paths + if path3 is not None: + path = path1 + path2[1:] + path3[1:] + else: + path = path1 + path2[1:] + else: + path = path1 +else: + path = None + +# Apply DWA for local optimization along the RRT path +if path is not None: + dwa = DWA(dwa_params) + optimized_path = [] + + start_time = time.time() + for i in range(len(path) - 1): + start_point = path[i] + (0.0, 0.0) # Initialize v and w to 0, using tuple + end_point = path[i + 1] + + local_path = dwa.plan(start_point, end_point, X, all_obstacles) + optimized_path.extend(local_path) + dwa_time = time.time() - start_time + + # Apply ALNS optimization to each segment of the path + print("Applying ALNS optimization...") + alns_optimized_path = [] + + # Find the closest points to the goals + index_intermediate = find_closest_point(optimized_path, x_intermediate) + index_second_goal = find_closest_point(optimized_path, x_second_goal) + + # Segment 1: Start to Intermediate + segment1 = optimized_path[:index_intermediate + 1] + alns_optimized_segment1 = alns_optimize_path(segment1, X, all_obstacles, max_iterations=100) + + # Segment 2: Intermediate to Second Goal + segment2 = optimized_path[index_intermediate:index_second_goal + 1] + alns_optimized_segment2 = alns_optimize_path(segment2, X, all_obstacles, max_iterations=100) + + # Segment 3: Second Goal to Final Goal + segment3 = optimized_path[index_second_goal:] + alns_optimized_segment3 = alns_optimize_path(segment3, X, all_obstacles, max_iterations=100) + + # Combine the ALNS-optimized segments + alns_optimized_path = alns_optimized_segment1 + alns_optimized_segment2[1:] + alns_optimized_segment3[1:] + + # Ensure all paths are correctly formatted and flatten nested structures + def validate_and_correct_path(path): + corrected_path = [] + for idx, point in enumerate(path): + if isinstance(point, (list, tuple)) and len(point) >= 2: + if isinstance(point[0], (list, tuple)): + point = [item for sublist in point for item in sublist] + corrected_path.append(point[:3]) # Ensure only the first three elements are used + else: + raise ValueError(f"Point {idx} in path is incorrectly formatted: {point}") + return corrected_path + + # Validate and correct paths + optimized_path = validate_and_correct_path(optimized_path) + alns_optimized_path = validate_and_correct_path(alns_optimized_path) + +# Metrics calculation +rrt_path_length = path_length(path) +dwa_path_length = path_length(optimized_path) +alns_path_length = path_length(alns_optimized_path) + +rrt_smoothness = path_smoothness(path) +dwa_smoothness = path_smoothness(optimized_path) +alns_smoothness = path_smoothness(alns_optimized_path) + +rrt_clearance = min_obstacle_clearance(path, all_obstacles) +dwa_clearance = min_obstacle_clearance(optimized_path, all_obstacles) +alns_clearance = min_obstacle_clearance(alns_optimized_path, all_obstacles) + +average_velocity = dwa_params['max_speed'] +rrt_energy = compute_energy_usage(path, average_velocity) +dwa_energy = compute_energy_usage(optimized_path, average_velocity) +alns_energy = compute_energy_usage(alns_optimized_path, average_velocity) + + +# Training the DQN +env = DroneEnv(X, x_init, x_final_goal, all_obstacles, dwa_params) +env.train(episodes=10) +# After training, use the learned policy in your DWA + +# Initialize the DroneEnv environment for path optimization +state = env.reset() +done = False +ml_path = [] +agent = DQNAgent(env.state_size, env.action_size) + +while not done: + action = agent.act(state) + next_state, _, done = env.step(action) + ml_path.append(next_state) + state = next_state + +# Save the trained DQN model +agent.model.save("dqn_model.keras") +print("DQN model saved as dqn_model.keras") + +# Print Metrics +print(f"RRT Path Length: {rrt_path_length}") +print(f"DWA Optimized Path Length: {dwa_path_length}") +print(f"ALNS Optimized Path Length: {alns_path_length}") +print(f"RRT Path Smoothness: {rrt_smoothness}") +print(f"DWA Optimized Path Smoothness: {dwa_smoothness}") +print(f"ALNS Optimized Path Smoothness: {alns_smoothness}") +print(f"RRT Path Minimum Clearance: {rrt_clearance}") +print(f"DWA Optimized Path Minimum Clearance: {dwa_clearance}") +print(f"ALNS Optimized Path Minimum Clearance: {alns_clearance}") + +# Ensure the final paths are properly flattened and structured +def flatten_path_points(path): + cleaned_path = [] + for idx, point in enumerate(path): + if isinstance(point, np.ndarray): + flat_point = point.flatten().tolist() + if len(flat_point) >= 3: + cleaned_path.append(flat_point[:3]) # Take only the first three elements (x, y, z) + else: + raise ValueError(f"Point {idx} in optimized_path is incorrectly formatted: {flat_point}") + elif isinstance(point, (list, tuple)) and len(point) >= 3: + cleaned_path.append(point[:3]) # Handle lists or tuples directly + else: + raise ValueError(f"Point {idx} in optimized_path is not correctly formatted: {point}") + return np.array(cleaned_path) + +# Apply the flattening function to optimized_path before plotting +try: + optimized_path = flatten_path_points(optimized_path) + ml_path = flatten_path_points(ml_path) +except ValueError as e: + print(f"Error encountered during flattening: {e}") + +# Plotting and Animation + +# First figure: RRT, DWA, ALNS paths with ML path +fig = plt.figure() +ax = fig.add_subplot(111, projection='3d') +ax.set_xlim(X_dimensions[0]) +ax.set_ylim(X_dimensions[1]) +ax.set_zlim(X_dimensions[2]) + +# Plot the RRT, DWA, and ALNS paths as dashed lines +ax.plot(*zip(*path), linestyle='--', color='red', label="RRT Path") +ax.plot(*zip(*optimized_path), linestyle='--', color='blue', label="DWA Optimized Path") +ax.plot(*zip(*alns_optimized_path), linestyle='--', color='green', label="ALNS Optimized Path") + +# Plot the ML path +ax.plot(*zip(*ml_path), color='orange', label="ML Path") + +# Plot static obstacles +for obs in all_obstacles: + x_center, y_center, z_min, z_max, radius = obs + u = np.linspace(0, 2 * np.pi, 100) + v = np.linspace(z_min, z_max, 100) + x = radius * np.outer(np.cos(u), np.ones(len(v))) + x_center + y = radius * np.outer(np.sin(u), np.ones(len(v))) + y_center + z = np.outer(np.ones(len(u)), v) + ax.plot_surface(x, y, z, color='gray', alpha=0.3) + +# Plot start and goal points +ax.scatter(*x_init, color='magenta', label="Start") +ax.scatter(*x_intermediate, color='pink', label="Intermediate Goal") +ax.scatter(*x_second_goal, color='cyan', label="Second Goal") +ax.scatter(*x_final_goal, color='green', label="Final Goal") + +# Animation of the ML path on the same figure +drone_path_line, = ax.plot([], [], [], color='orange', linewidth=2) + +def update_line(num, ml_path, line): + line.set_data(ml_path[:num, 0], ml_path[:num, 1]) + line.set_3d_properties(ml_path[:num, 2]) + return line, + +ani = animation.FuncAnimation( + fig, update_line, frames=len(ml_path), fargs=(np.array(ml_path), drone_path_line), interval=100, blit=True +) + +# Add legend and show the figure +ax.legend() +plt.show() + diff --git a/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size+8.png b/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size+8.png new file mode 100644 index 0000000..7a9e1f8 Binary files /dev/null and b/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size+8.png differ diff --git a/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size+8.py b/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size+8.py new file mode 100644 index 0000000..b9e4f32 --- /dev/null +++ b/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size+8.py @@ -0,0 +1,398 @@ +import numpy as np +import time +from rtree import index +import sys +import uuid +import skfuzzy as fuzz +from skfuzzy import control as ctrl +import random +from tensorflow.keras.models import load_model +import matplotlib.pyplot as plt +import matplotlib.animation as animation + +sys.path.append('/home/dell/rrt-algorithms') + +from rrt_algorithms.rrt.rrt import RRT +from rrt_algorithms.search_space.search_space2 import SearchSpace +from rrt_algorithms.utilities.plotting2 import Plot +from rrt_algorithms.dwa_algorithm.DWA3 import DWA, FuzzyController +from rrt_algorithms.dqn_algorithm.DQN import DQNAgent +from rrt_algorithms.dqn_algorithm.DQN import DroneEnv +from rrt_algorithms.utilities.obstacle_generation2 import generate_random_cylindrical_obstacles + +# Define the search space dimensions +X_dimensions = np.array([(0, 100), (0, 100), (0, 100)]) +X = SearchSpace(X_dimensions) + +# Initial and goal positions +x_init = (50, 50, -2) +x_intermediate = (50, 50, 100) +x_second_goal = (20, 60, 100) +x_final_goal = (0, 0, 0) + +# Generate random obstacles +n = 7 # Number of random obstacles +Obstacles = generate_random_cylindrical_obstacles(X, x_init, x_final_goal, n) + +# Define static obstacles +obstacles = [ + (10, 82, 0, 85, 15), + (80, 20, 0, 60, 19), + (10, 30, 0, 90, 15), + (80, 80, 0, 70, 22), + (50, 50, 0, 50, 22), +] + +# Combine static and randomly generated obstacles into one list +all_obstacles = obstacles + Obstacles +# Initialize the SearchSpace with all obstacles +X = SearchSpace(X_dimensions, all_obstacles) + +# RRT parameters +q = 700 +r = 1 +max_samples = 2024 +prc = 0.1 + +# DWA parameters +dwa_params = { + 'max_speed': 1.0, + 'min_speed': 0.0, + 'max_yaw_rate': 40.0 * np.pi / 180.0, + 'max_accel': 0.3, + 'v_reso': 0.05, + 'yaw_rate_reso': 0.2 * np.pi / 180.0, + 'dt': 0.1, + 'predict_time': 2.0, + 'to_goal_cost_gain': 1.5, + 'speed_cost_gain': 0.5, + 'obstacle_cost_gain': 1.0, +} + +def compute_energy_usage(path, velocity): + energy = 0.0 + for i in range(1, len(path)): + distance = np.linalg.norm(np.array(path[i]) - np.array(path[i-1])) + energy += distance * velocity + return energy + +def min_obstacle_clearance(path, obstacles): + min_clearance = float('inf') + for point in path: + for obs in obstacles: + clearance = np.linalg.norm(np.array(point[:2]) - np.array(obs[:2])) - obs[4] + if clearance < min_clearance: + min_clearance = clearance + return min_clearance + +def path_length(path): + return sum(np.linalg.norm(np.array(path[i+1]) - np.array(path[i])) for i in range(len(path) - 1)) + +def path_smoothness(path): + total_curvature = 0.0 + for i in range(1, len(path) - 1): + vec1 = np.array(path[i]) - np.array(path[i-1]) + vec2 = np.array(path[i+1]) - np.array(path[i]) + angle = np.arccos(np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2))) + total_curvature += angle + return total_curvature + + +# Adaptive Large Neighborhood Search (ALNS) Functions +def alns_optimize_path(path, X, all_obstacles, max_iterations=100): + neighborhoods = [segment_change, detour_addition, direct_connection] + neighborhood_scores = {segment_change: 1.0, detour_addition: 1.0, direct_connection: 1.0} + current_path = path.copy() + + for _ in range(max_iterations): + # Select neighborhood adaptively + neighborhood = random.choices(neighborhoods, weights=neighborhood_scores.values())[0] + new_path = neighborhood(current_path, X, all_obstacles) + + # Evaluate the new path + new_path_length = path_length(new_path) + current_path_length = path_length(current_path) + + if new_path_length < current_path_length: + current_path = new_path + neighborhood_scores[neighborhood] *= 1.1 # Reward successful neighborhood + else: + neighborhood_scores[neighborhood] *= 0.9 # Penalize unsuccessful neighborhood + + return current_path + +def segment_change(path, X, all_obstacles, r=1): + if len(path) < 3: + return path + + i = random.randint(0, len(path) - 3) + j = random.randint(i + 2, len(path) - 1) + + x_a = path[i] + x_b = path[j] + + spatial_x_a = np.array(x_a[:3]) + spatial_x_b = np.array(x_b[:3]) + + new_point_spatial = spatial_x_a + (spatial_x_b - spatial_x_a) / 2 + new_point = list(new_point_spatial) + list(x_a[3:]) + + if X.collision_free(spatial_x_a, new_point_spatial, r) and X.collision_free(new_point_spatial, spatial_x_b, r): + new_path = path[:i + 1] + [new_point] + path[j:] + return new_path + + return path + +def detour_addition(path, X, all_obstacles, r=1): + if len(path) < 2: + return path + + i = random.randint(0, len(path) - 2) + x_a = path[i] + x_b = path[i + 1] + + spatial_x_a = np.array(x_a[:3]) + spatial_x_b = np.array(x_b[:3]) + + detour_point_3d = spatial_x_a + (np.random.rand(3) - 0.5) * 2 * r + detour_point = list(detour_point_3d) + list(x_a[3:]) + + if X.collision_free(spatial_x_a, detour_point_3d, r) and X.collision_free(detour_point_3d, spatial_x_b, r): + new_path = path[:i + 1] + [detour_point] + path[i + 1:] + return new_path + + return path + + +def direct_connection(path, X, all_obstacles, r=1): + if len(path) < 3: + return path # Can't directly connect if there aren't enough points + + new_path = path.copy() + i = random.randint(0, len(path) - 3) # Select a random starting point + j = random.randint(i + 2, len(path) - 1) # Select a random ending point + + x_a = path[i][:3] # Extract only the spatial coordinates (x, y, z) + x_b = path[j][:3] # Extract only the spatial coordinates (x, y, z) + + if X.collision_free(x_a, x_b, r): + new_path = new_path[:i + 1] + new_path[j:] # Remove the points between i and j + + return new_path + +def find_closest_point(path, goal): + distances = [np.linalg.norm(np.array(p[:3]) - np.array(goal)) for p in path] + return np.argmin(distances) + +# RRT pathfinding to the first intermediate goal +print("RRT to first intermediate goal...") +start_time = time.time() +rrt = RRT(X, q, x_init, x_intermediate, max_samples, r, prc) +path1 = rrt.rrt_search() +rrt_time = time.time() - start_time + +if path1 is not None: + print("RRT to second intermediate goal...") + rrt = RRT(X, q, x_intermediate, x_second_goal, max_samples, r, prc) + path2 = rrt.rrt_search() + + if path2 is not None: + print("RRT to final goal...") + rrt = RRT(X, q, x_second_goal, x_final_goal, max_samples, r, prc) + path3 = rrt.rrt_search() + + # Combine all paths + if path3 is not None: + path = path1 + path2[1:] + path3[1:] + else: + path = path1 + path2[1:] + else: + path = path1 +else: + path = None + +# Apply DWA for local optimization along the RRT path +if path is not None: + dwa = DWA(dwa_params) + optimized_path = [] + + start_time = time.time() + for i in range(len(path) - 1): + start_point = path[i] + (0.0, 0.0) # Initialize v and w to 0, using tuple + end_point = path[i + 1] + + local_path = dwa.plan(start_point, end_point, X, all_obstacles) + optimized_path.extend(local_path) + dwa_time = time.time() - start_time + + # Apply ALNS optimization to each segment of the path + print("Applying ALNS optimization...") + alns_optimized_path = [] + + # Find the closest points to the goals + index_intermediate = find_closest_point(optimized_path, x_intermediate) + index_second_goal = find_closest_point(optimized_path, x_second_goal) + + # Segment 1: Start to Intermediate + segment1 = optimized_path[:index_intermediate + 1] + alns_optimized_segment1 = alns_optimize_path(segment1, X, all_obstacles, max_iterations=100) + + # Segment 2: Intermediate to Second Goal + segment2 = optimized_path[index_intermediate:index_second_goal + 1] + alns_optimized_segment2 = alns_optimize_path(segment2, X, all_obstacles, max_iterations=100) + + # Segment 3: Second Goal to Final Goal + segment3 = optimized_path[index_second_goal:] + alns_optimized_segment3 = alns_optimize_path(segment3, X, all_obstacles, max_iterations=100) + + # Combine the ALNS-optimized segments + alns_optimized_path = alns_optimized_segment1 + alns_optimized_segment2[1:] + alns_optimized_segment3[1:] + + # Ensure all paths are correctly formatted and flatten nested structures + def validate_and_correct_path(path): + corrected_path = [] + for idx, point in enumerate(path): + if isinstance(point, (list, tuple)) and len(point) >= 2: + if isinstance(point[0], (list, tuple)): + point = [item for sublist in point for item in sublist] + corrected_path.append(point[:3]) # Ensure only the first three elements are used + else: + raise ValueError(f"Point {idx} in path is incorrectly formatted: {point}") + return corrected_path + + # Validate and correct paths + optimized_path = validate_and_correct_path(optimized_path) + alns_optimized_path = validate_and_correct_path(alns_optimized_path) + +# Metrics calculation +rrt_path_length = path_length(path) +dwa_path_length = path_length(optimized_path) +alns_path_length = path_length(alns_optimized_path) + +rrt_smoothness = path_smoothness(path) +dwa_smoothness = path_smoothness(optimized_path) +alns_smoothness = path_smoothness(alns_optimized_path) + +rrt_clearance = min_obstacle_clearance(path, all_obstacles) +dwa_clearance = min_obstacle_clearance(optimized_path, all_obstacles) +alns_clearance = min_obstacle_clearance(alns_optimized_path, all_obstacles) + +average_velocity = dwa_params['max_speed'] +rrt_energy = compute_energy_usage(path, average_velocity) +dwa_energy = compute_energy_usage(optimized_path, average_velocity) +alns_energy = compute_energy_usage(alns_optimized_path, average_velocity) + + +# Training the DQN +env = DroneEnv(X, x_init, x_final_goal, all_obstacles, dwa_params) +env.train(episodes=10) +# After training, use the learned policy in your DWA + +# Initialize the DroneEnv environment for path optimization +state = env.reset() +done = False +ml_path = [] +agent = DQNAgent(env.state_size, env.action_size) + +while not done: + action = agent.act(state) + next_state, _, done = env.step(action) + ml_path.append(next_state) + state = next_state + +# Convert ml_path to a numpy array +ml_path = np.array(ml_path) + +# Check if ml_path has valid data +if ml_path.size == 0: + print("ML path is empty. Ensure the DQN agent is working correctly.") +else: + print("ML path:", ml_path) + +# Save the trained DQN model +agent.model.save("dqn_model.keras") +print("DQN model saved as dqn_model.keras") + +# Print Metrics +print(f"RRT Path Length: {rrt_path_length}") +print(f"DWA Optimized Path Length: {dwa_path_length}") +print(f"ALNS Optimized Path Length: {alns_path_length}") +print(f"RRT Path Smoothness: {rrt_smoothness}") +print(f"DWA Optimized Path Smoothness: {dwa_smoothness}") +print(f"ALNS Optimized Path Smoothness: {alns_smoothness}") +print(f"RRT Path Minimum Clearance: {rrt_clearance}") +print(f"DWA Optimized Path Minimum Clearance: {dwa_clearance}") +print(f"ALNS Optimized Path Minimum Clearance: {alns_clearance}") + +# Ensure the final paths are properly flattened and structured +def flatten_path_points(path): + cleaned_path = [] + for idx, point in enumerate(path): + if isinstance(point, np.ndarray): + flat_point = point.flatten().tolist() + if len(flat_point) >= 3: + cleaned_path.append(flat_point[:3]) # Take only the first three elements (x, y, z) + else: + raise ValueError(f"Point {idx} in optimized_path is incorrectly formatted: {flat_point}") + elif isinstance(point, (list, tuple)) and len(point) >= 3: + cleaned_path.append(point[:3]) # Handle lists or tuples directly + else: + raise ValueError(f"Point {idx} in optimized_path is not correctly formatted: {point}") + return np.array(cleaned_path) + +# Apply the flattening function to optimized_path before plotting +try: + optimized_path = flatten_path_points(optimized_path) + ml_path = flatten_path_points(ml_path) +except ValueError as e: + print(f"Error encountered during flattening: {e}") + +# Plotting and Animation + +# First figure: RRT, DWA, ALNS paths with ML path +fig = plt.figure() +ax = fig.add_subplot(111, projection='3d') +ax.set_xlim(X_dimensions[0]) +ax.set_ylim(X_dimensions[1]) +ax.set_zlim(X_dimensions[2]) + +# Plot the RRT, DWA, and ALNS paths as dashed lines +ax.plot(*zip(*path), linestyle='--', color='red', label="RRT Path") +ax.plot(*zip(*optimized_path), linestyle='--', color='blue', label="DWA Optimized Path") +ax.plot(*zip(*alns_optimized_path), linestyle='--', color='green', label="ALNS Optimized Path") + +# Plot the ML path +ax.plot(*ml_path.T, color='black', label="ML Path") + +# Plot static obstacles +for obs in all_obstacles: + x_center, y_center, z_min, z_max, radius = obs + u = np.linspace(0, 2 * np.pi, 100) + v = np.linspace(z_min, z_max, 100) + x = radius * np.outer(np.cos(u), np.ones(len(v))) + x_center + y = radius * np.outer(np.sin(u), np.ones(len(v))) + y_center + z = np.outer(np.ones(len(u)), v) + ax.plot_surface(x, y, z, color='gray', alpha=0.3) + +# Plot start and goal points +ax.scatter(*x_init, color='magenta', label="Start") +ax.scatter(*x_intermediate, color='pink', label="Intermediate Goal") +ax.scatter(*x_second_goal, color='cyan', label="Second Goal") +ax.scatter(*x_final_goal, color='green', label="Final Goal") + +# Animation of the ML path on the same figure +drone_path_line, = ax.plot([], [], [], color='orange', linewidth=2) + +def update_line(num, ml_path, line): + line.set_data(ml_path[:num, 0], ml_path[:num, 1]) + line.set_3d_properties(ml_path[:num, 2]) + return line, + +ani = animation.FuncAnimation( + fig, update_line, frames=len(ml_path), fargs=(ml_path, drone_path_line), interval=100, blit=True +) + +# Add legend and show the figure +ax.legend() +plt.show() + diff --git a/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size.py b/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size.py new file mode 100644 index 0000000..79d1a7a --- /dev/null +++ b/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size.py @@ -0,0 +1,171 @@ +# Texpanding the radius of the obstacles by the radius of the drone (10 cm) to ensure that the drone does not collide with any obstacles. This adjustment effectively treats the drone as a point but expands the obstacles to account for the drone's size. +import numpy as np +import time +from rtree import index +import sys +import uuid + +sys.path.append('/home/dell/rrt-algorithms') + +from rrt_algorithms.rrt.rrt import RRT +from rrt_algorithms.search_space.search_space2 import SearchSpace +from rrt_algorithms.utilities.plotting2 import Plot +from rrt_algorithms.dwa_algorithm.DWA2 import DWA +from rrt_algorithms.utilities.obstacle_generation2 import generate_random_cylindrical_obstacles + +# Define the search space dimensions +X_dimensions = np.array([(0, 100), (0, 100), (0, 100)]) +# Initial and goal positions +x_init = (50, 50, -2) +x_intermediate = (50, 50, 100) +x_second_goal = (20, 60, 100) +x_final_goal = (0, 0, 0) +#x_final_goal = (100, 100, 40) +# Create the search space +X = SearchSpace(X_dimensions) + +# Generate random obstacles +n = 7 # Number of random obstacles +Obstacles = generate_random_cylindrical_obstacles(X, x_init, x_final_goal, n) + +# Define static obstacles +obstacles = [ + (10, 82, 0, 85, 15), + (80, 20, 0, 60, 19), + (10, 30, 0, 90, 15), + (80, 80, 0, 70, 22), + (50, 50, 0, 50, 22), +] + +# Combine static and randomly generated obstacles into one list +all_obstacles = obstacles + Obstacles +# Initialize the SearchSpace with all obstacles +X = SearchSpace(X_dimensions, all_obstacles) + +# RRT parameters +q = 700 +r = 1 +max_samples = 1024 +prc = 0.1 + +# DWA parameters +dwa_params = { + 'max_speed': 1.0, + 'min_speed': 0.0, + 'max_yaw_rate': 40.0 * np.pi / 180.0, + 'max_accel': 0.3, + 'v_reso': 0.05, + 'yaw_rate_reso': 0.2 * np.pi / 180.0, + 'dt': 0.1, + 'predict_time': 2.0, + 'to_goal_cost_gain': 1.5, + 'speed_cost_gain': 0.5, + 'obstacle_cost_gain': 1.0, +} + +def path_length(path): + return sum(np.linalg.norm(np.array(path[i+1]) - np.array(path[i])) for i in range(len(path) - 1)) + +def path_smoothness(path): + total_curvature = 0.0 + for i in range(1, len(path) - 1): + vec1 = np.array(path[i]) - np.array(path[i-1]) + vec2 = np.array(path[i+1]) - np.array(path[i]) + angle = np.arccos(np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2))) + total_curvature += angle + return total_curvature + +def min_obstacle_clearance(path, obstacles): + min_clearance = float('inf') + for point in path: + for obs in obstacles: + clearance = np.linalg.norm(np.array(point[:2]) - np.array(obs[:2])) - obs[4] + if clearance < min_clearance: + min_clearance = clearance + return min_clearance + +def compute_energy_usage(path, velocity): + energy = 0.0 + for i in range(1, len(path)): + distance = np.linalg.norm(np.array(path[i]) - np.array(path[i-1])) + energy += distance * velocity + return energy + +# RRT pathfinding to first intermediate goal +print("RRT to first intermediate goal...") +start_time = time.time() +rrt = RRT(X, q, x_init, x_intermediate, max_samples, r, prc) +path1 = rrt.rrt_search() +rrt_time = time.time() - start_time + +if path1 is not None: + print("RRT to second intermediate goal...") + rrt = RRT(X, q, x_intermediate, x_second_goal, max_samples, r, prc) + path2 = rrt.rrt_search() + + if path2 is not None: + print("RRT to final goal...") + rrt = RRT(X, q, x_second_goal, x_final_goal, max_samples, r, prc) + path3 = rrt.rrt_search() + + # Combine all paths + if path3 is not None: + path = path1 + path2[1:] + path3[1:] + else: + path = path1 + path2[1:] + else: + path = path1 +else: + path = None + +# Apply DWA for local optimization along the RRT path +if path is not None: + dwa = DWA(dwa_params) + optimized_path = [] + + start_time = time.time() + for i in range(len(path) - 1): + start_point = path[i] + (0.0, 0.0) # Initialize v and w to 0, using tuple + end_point = path[i + 1] + + local_path = dwa.plan(start_point, end_point, X, all_obstacles) + optimized_path.extend(local_path) + dwa_time = time.time() - start_time + + # Metrics + rrt_path_length = path_length(path) + dwa_path_length = path_length(optimized_path) + + rrt_smoothness = path_smoothness(path) + dwa_smoothness = path_smoothness(optimized_path) + + rrt_clearance = min_obstacle_clearance(path, all_obstacles) + dwa_clearance = min_obstacle_clearance(optimized_path, all_obstacles) + + average_velocity = dwa_params['max_speed'] + rrt_energy = compute_energy_usage(path, average_velocity) + dwa_energy = compute_energy_usage(optimized_path, average_velocity) + + # Print Metrics + print(f"RRT Path Length: {rrt_path_length}") + print(f"DWA Optimized Path Length: {dwa_path_length}") + print(f"RRT Path Smoothness: {rrt_smoothness}") + print(f"DWA Optimized Path Smoothness: {dwa_smoothness}") + print(f"RRT Path Minimum Clearance: {rrt_clearance}") + print(f"DWA Optimized Path Minimum Clearance: {dwa_clearance}") + print(f"RRT Path Energy Usage: {rrt_energy}") + print(f"DWA Optimized Path Energy Usage: {dwa_energy}") + print(f"RRT Path Computation Time: {rrt_time} seconds") + print(f"DWA Optimized Path Computation Time: {dwa_time} seconds") + + # Plotting + plot = Plot("rrt_dwa_3d") + plot.plot_tree(X, rrt.trees) + plot.plot_path(X, path, color='red') # Plot the original RRT path in red + plot.plot_path(X, optimized_path, color='blue') # Plot the optimized path in blue + plot.plot_obstacles(X, all_obstacles) + plot.plot_start(X, x_init) + plot.plot_goal(X, x_intermediate, color="pink") + plot.plot_goal(X, x_second_goal, color="blue") + plot.plot_goal(X, x_final_goal, color="green") + plot.draw(auto_open=True) diff --git a/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size_10.png b/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size_10.png new file mode 100644 index 0000000..5acca41 Binary files /dev/null and b/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size_10.png differ diff --git a/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size_10.py b/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size_10.py new file mode 100644 index 0000000..0826fe2 --- /dev/null +++ b/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size_10.py @@ -0,0 +1,554 @@ +#generate random poisitions: +import numpy as np +import time +from rtree import index +import sys +import uuid +import skfuzzy as fuzz +from skfuzzy import control as ctrl +import random +from tensorflow.keras.models import load_model +import matplotlib.pyplot as plt +import matplotlib.animation as animation + +sys.path.append('/home/dell/rrt-algorithms') + +from rrt_algorithms.rrt.rrt import RRT +from rrt_algorithms.search_space.search_space2 import SearchSpace +from rrt_algorithms.utilities.plotting2 import Plot +from rrt_algorithms.dwa_algorithm.DWA3 import DWA, FuzzyController +from rrt_algorithms.dqn_algorithm.DQN import DQNAgent +from rrt_algorithms.dqn_algorithm.DQN import DroneEnv +from rrt_algorithms.utilities.obstacle_generation2 import generate_random_cylindrical_obstacles + +# Define the search space dimensions +X_dimensions = np.array([(0, 100), (0, 100), (0, 100)]) +X = SearchSpace(X_dimensions) + +# Helper function to generate random positions +def generate_random_position(dimensions): + x_min, x_max = dimensions[0] + y_min, y_max = dimensions[1] + z_min, z_max = dimensions[2] + return ( + random.uniform(x_min, x_max), + random.uniform(y_min, y_max), + random.uniform(z_min, z_max) + ) + +# Initial and goal positions (Randomized) +x_init = generate_random_position(X_dimensions) # Random starting position +x_intermediate = generate_random_position(X_dimensions) # Random intermediate goal +x_second_goal = generate_random_position(X_dimensions) # Random second goal +x_final_goal = generate_random_position(X_dimensions) # Random final goal + +# Generate random obstacles +n = 7 # Number of random obstacles +Obstacles = generate_random_cylindrical_obstacles(X, x_init, x_final_goal, n) + +# Define static obstacles +obstacles = [ + (10, 82, 0, 85, 15), + (80, 20, 0, 60, 19), + (10, 30, 0, 90, 15), + (80, 80, 0, 70, 22), + (50, 50, 0, 50, 22), +] + +# Combine static and randomly generated obstacles into one list +all_obstacles = obstacles + Obstacles + +# Initialize the SearchSpace with all obstacles +X = SearchSpace(X_dimensions, all_obstacles) + +# RRT parameters +q = 300 +r = 1 +max_samples = 2024 +prc = 0.1 + +# DWA parameters +dwa_params = { + 'max_speed': 1.0, + 'min_speed': 0.0, + 'max_yaw_rate': 40.0 * np.pi / 180.0, + 'max_accel': 0.3, + 'v_reso': 0.05, + 'yaw_rate_reso': 0.2 * np.pi / 180.0, + 'dt': 0.1, + 'predict_time': 2.0, + 'to_goal_cost_gain': 1.5, + 'speed_cost_gain': 0.5, + 'obstacle_cost_gain': 1.0, +} + +def compute_energy_usage(path, velocity): + energy = 0.0 + for i in range(1, len(path)): + distance = np.linalg.norm(np.array(path[i]) - np.array(path[i-1])) + energy += distance * velocity + return energy + +def min_obstacle_clearance(path, obstacles): + min_clearance = float('inf') + for point in path: + for obs in obstacles: + clearance = np.linalg.norm(np.array(point[:2]) - np.array(obs[:2])) - obs[4] + if clearance < min_clearance: + min_clearance = clearance + return min_clearance + +def path_length(path): + return sum(np.linalg.norm(np.array(path[i+1]) - np.array(path[i])) for i in range(len(path) - 1)) + +def path_smoothness(path): + total_curvature = 0.0 + for i in range(1, len(path) - 1): + vec1 = np.array(path[i]) - np.array(path[i-1]) + vec2 = np.array(path[i+1]) - np.array(path[i]) + angle = np.arccos(np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2))) + total_curvature += angle + return total_curvature + + +# Adaptive Large Neighborhood Search (ALNS) Functions +def alns_optimize_path(path, X, all_obstacles, max_iterations=100): + neighborhoods = [segment_change, detour_addition, direct_connection] + neighborhood_scores = {segment_change: 1.0, detour_addition: 1.0, direct_connection: 1.0} + current_path = path.copy() + + for _ in range(max_iterations): + neighborhood = random.choices(neighborhoods, weights=neighborhood_scores.values())[0] + new_path = neighborhood(current_path, X, all_obstacles) + + new_path_length = path_length(new_path) + current_path_length = path_length(current_path) + + if new_path_length < current_path_length: + current_path = new_path + neighborhood_scores[neighborhood] *= 1.1 # Reward successful neighborhood + else: + neighborhood_scores[neighborhood] *= 0.9 # Penalize unsuccessful neighborhood + + return current_path + +def segment_change(path, X, all_obstacles, r=1): + if len(path) < 3: + return path + + i = random.randint(0, len(path) - 3) + j = random.randint(i + 2, len(path) - 1) + + x_a = path[i] + x_b = path[j] + + spatial_x_a = np.array(x_a[:3]) + spatial_x_b = np.array(x_b[:3]) + + new_point_spatial = spatial_x_a + (spatial_x_b - spatial_x_a) / 2 + new_point = list(new_point_spatial) + list(x_a[3:]) + + if X.collision_free(spatial_x_a, new_point_spatial, r) and X.collision_free(new_point_spatial, spatial_x_b, r): + new_path = path[:i + 1] + [new_point] + path[j:] + return new_path + + return path + +def detour_addition(path, X, all_obstacles, r=1): + if len(path) < 2: + return path + + i = random.randint(0, len(path) - 2) + x_a = path[i] + x_b = path[i + 1] + + spatial_x_a = np.array(x_a[:3]) + spatial_x_b = np.array(x_b[:3]) + + detour_point_3d = spatial_x_a + (np.random.rand(3) - 0.5) * 2 * r + detour_point = list(detour_point_3d) + list(x_a[3:]) + + if X.collision_free(spatial_x_a, detour_point_3d, r) and X.collision_free(detour_point_3d, spatial_x_b, r): + new_path = path[:i + 1] + [detour_point] + path[i + 1:] + return new_path + + return path + +def direct_connection(path, X, all_obstacles, r=1): + if len(path) < 3: + return path # Can't directly connect if there aren't enough points + + new_path = path.copy() + i = random.randint(0, len(path) - 3) + j = random.randint(i + 2, len(path) - 1) + + x_a = path[i][:3] + x_b = path[j][:3] + + if X.collision_free(x_a, x_b, r): + new_path = new_path[:i + 1] + new_path[j:] + + return new_path + +def find_closest_point(path, goal): + distances = [np.linalg.norm(np.array(p[:3]) - np.array(goal)) for p in path] + return np.argmin(distances) + + +#adjust speed as required + +def is_inside_obstacle(point, obstacles): + """ + Check if a point is inside any obstacle. + Assumes obstacles are represented as (x_center, y_center, z_min, z_max, radius). + """ + for obs in obstacles: + x_center, y_center, z_min, z_max, radius = obs + distance = np.linalg.norm(np.array(point[:2]) - np.array([x_center, y_center])) + if distance < radius and z_min <= point[2] <= z_max: + return True + return False + +# Speed calculation and adjustment function +def calculate_required_speed(distance, time): + if time > 0: + return distance / time + return float('inf') # Infinite speed if no time constraint + +def adjust_speed_to_reach_goal(path, total_time, dwa_params, label, ax=None): + if path is None or len(path) == 0: + print(f"Warning: No path found for {label}, skipping speed adjustment.") + return + + path_length_value = path_length(path) + required_speed = calculate_required_speed(path_length_value, total_time) + + # Clip speed to the maximum allowable speed + adjusted_speed = min(required_speed, dwa_params['max_speed']) + dwa_params['max_speed'] = adjusted_speed + + # Print speed in terminal + print(f"Adjusted speed for {label}: {adjusted_speed:.2f} units/s (Distance: {path_length_value:.2f} units, Time: {total_time} s)") + + # Annotate speed on the plot + if ax is not None: + midpoint = np.mean(path, axis=0) + ax.text(midpoint[0], midpoint[1], midpoint[2], f"Speed: {adjusted_speed:.2f} u/s", color='black', fontsize=10) + +# Function to calculate path length +def path_length(path): + return sum(np.linalg.norm(np.array(path[i+1]) - np.array(path[i])) for i in range(len(path) - 1)) + +# Function to try RRT to a goal and return the path +def try_rrt_to_goal(X, q, start, goal, max_samples, r, prc, obstacles): + rrt = RRT(X, q, start, goal, max_samples, r, prc) + path = rrt.rrt_search() + if path is None: + print(f"RRT failed to find a path to {goal}.") + return path + +# RRT pathfinding to goals +specified_time_intermediate = 20 +specified_time_second = 30 +specified_time_final = 50 + + +print("RRT to first intermediate goal...") +start_time = time.time() +path1 = try_rrt_to_goal(X, q, x_init, x_intermediate, max_samples, r, prc, all_obstacles) +rrt_time = time.time() - start_time + +if path1 is not None: + adjust_speed_to_reach_goal(path1, specified_time_intermediate, dwa_params,"intermediate goal") # Adjust speed for the intermediate goal + + print("RRT to second intermediate goal...") + path2 = try_rrt_to_goal(X, q, x_intermediate, x_second_goal, max_samples, r, prc, all_obstacles) + + if path2 is not None: + adjust_speed_to_reach_goal(path2, specified_time_second, dwa_params,"second goal") # Adjust speed for the second goal + + print("RRT to final goal...") + path3 = try_rrt_to_goal(X, q, x_second_goal, x_final_goal, max_samples, r, prc, all_obstacles) + + # Combine all paths + if path3 is not None: + adjust_speed_to_reach_goal(path3, specified_time_final, dwa_params,"final goal") # Adjust speed for the final goal + path = path1 + path2[1:] + path3[1:] + else: + path = path1 + path2[1:] + else: + path = path1 +else: + path = None + +# Before calculating the path length, check if the path is valid (not None) +if path is not None: + # Calculate and print path length + rrt_path_length = path_length(path) + print(f"RRT Path Length: {rrt_path_length:.2f}") +else: + print("Error: RRT failed to find a valid path. Path length calculation skipped.") + + +# Apply DWA for local optimization along the RRT path +if path is not None: + dwa = DWA(dwa_params) + optimized_path = [] + + start_time = time.time() + for i in range(len(path) - 1): + start_point = path[i] + (0.0, 0.0) + end_point = path[i + 1] + + local_path = dwa.plan(start_point, end_point, X, all_obstacles) + optimized_path.extend(local_path) + dwa_time = time.time() - start_time + + # Apply ALNS optimization to each segment of the path + print("Applying ALNS optimization...") + alns_optimized_path = [] + + index_intermediate = find_closest_point(optimized_path, x_intermediate) + index_second_goal = find_closest_point(optimized_path, x_second_goal) + + segment1 = optimized_path[:index_intermediate + 1] + alns_optimized_segment1 = alns_optimize_path(segment1, X, all_obstacles, max_iterations=100) + + segment2 = optimized_path[index_intermediate:index_second_goal + 1] + alns_optimized_segment2 = alns_optimize_path(segment2, X, all_obstacles, max_iterations=100) + + segment3 = optimized_path[index_second_goal:] + alns_optimized_segment3 = alns_optimize_path(segment3, X, all_obstacles, max_iterations=100) + + alns_optimized_path = alns_optimized_segment1 + alns_optimized_segment2[1:] + alns_optimized_segment3[1:] + + def validate_and_correct_path(path): + corrected_path = [] + for idx, point in enumerate(path): + if isinstance(point, (list, tuple)) and len(point) >= 2: + if isinstance(point[0], (list, tuple)): + point = [item for sublist in point for item in sublist] + corrected_path.append(point[:3]) + else: + raise ValueError(f"Point {idx} in path is incorrectly formatted: {point}") + return corrected_path + + optimized_path = validate_and_correct_path(optimized_path) + alns_optimized_path = validate_and_correct_path(alns_optimized_path) + +# Continue the rest of your code as before... + + + +# Metrics calculation +rrt_path_length = path_length(path) +dwa_path_length = path_length(optimized_path) +alns_path_length = path_length(alns_optimized_path) + +rrt_smoothness = path_smoothness(path) +dwa_smoothness = path_smoothness(optimized_path) +alns_smoothness = path_smoothness(alns_optimized_path) + +rrt_clearance = min_obstacle_clearance(path, all_obstacles) +dwa_clearance = min_obstacle_clearance(optimized_path, all_obstacles) +alns_clearance = min_obstacle_clearance(alns_optimized_path, all_obstacles) + +average_velocity = dwa_params['max_speed'] +rrt_energy = compute_energy_usage(path, average_velocity) +dwa_energy = compute_energy_usage(optimized_path, average_velocity) +alns_energy = compute_energy_usage(alns_optimized_path, average_velocity) + + +# Training the DQN +env = DroneEnv(X, x_init, x_final_goal, all_obstacles, dwa_params) +env.train(episodes=20) +# After training, use the learned policy in your DWA + +# Initialize the DroneEnv environment for path optimization +state = env.reset() +done = False +ml_path = [] +agent = DQNAgent(env.state_size, env.action_size) + +while not done: + action = agent.act(state) + next_state, _, done = env.step(action) + ml_path.append(next_state) + state = next_state + +# Convert ml_path to a numpy array +ml_path = np.array(ml_path) + +# Check if ml_path has valid data +if ml_path.size == 0: + print("ML path is empty. Ensure the DQN agent is working correctly.") +else: + print("ML path:", ml_path) + +# Save the trained DQN model +agent.model.save("dqn_model.keras") +print("DQN model saved as dqn_model.keras") + +# Print Metrics +print(f"RRT Path Length: {rrt_path_length}") +print(f"DWA Optimized Path Length: {dwa_path_length}") +print(f"ALNS Optimized Path Length: {alns_path_length}") +print(f"RRT Path Smoothness: {rrt_smoothness}") +print(f"DWA Optimized Path Smoothness: {dwa_smoothness}") +print(f"ALNS Optimized Path Smoothness: {alns_smoothness}") +print(f"RRT Path Minimum Clearance: {rrt_clearance}") +print(f"DWA Optimized Path Minimum Clearance: {dwa_clearance}") +print(f"ALNS Optimized Path Minimum Clearance: {alns_clearance}") + +# Ensure the final paths are properly flattened and structured +def flatten_path_points(path): + cleaned_path = [] + for idx, point in enumerate(path): + if isinstance(point, np.ndarray): + flat_point = point.flatten().tolist() + if len(flat_point) >= 3: + cleaned_path.append(flat_point[:3]) # Take only the first three elements (x, y, z) + else: + raise ValueError(f"Point {idx} in optimized_path is incorrectly formatted: {flat_point}") + elif isinstance(point, (list, tuple)) and len(point) >= 3: + cleaned_path.append(point[:3]) # Handle lists or tuples directly + else: + raise ValueError(f"Point {idx} in optimized_path is not correctly formatted: {point}") + return np.array(cleaned_path) + +# Apply the flattening function to optimized_path before plotting +try: + optimized_path = flatten_path_points(optimized_path) + ml_path = flatten_path_points(ml_path) +except ValueError as e: + print(f"Error encountered during flattening: {e}") + +# Plotting and Animation + +# First figure: RRT, DWA, ALNS paths with ML path +fig = plt.figure() +ax = fig.add_subplot(111, projection='3d') +ax.set_xlim(X_dimensions[0]) +ax.set_ylim(X_dimensions[1]) +ax.set_zlim(X_dimensions[2]) + +# Plot the RRT, DWA, and ALNS paths as dashed lines +ax.plot(*zip(*path), linestyle='--', color='red', label="RRT Path") +ax.plot(*zip(*optimized_path), linestyle='--', color='blue', label="DWA Optimized Path") +ax.plot(*zip(*alns_optimized_path), linestyle='--', color='green', label="ALNS Optimized Path") + +# Plot the ML path +ax.plot(*ml_path.T, color='black', label="ML Path") + +# Plot static obstacles +for obs in all_obstacles: + x_center, y_center, z_min, z_max, radius = obs + u = np.linspace(0, 2 * np.pi, 100) + v = np.linspace(z_min, z_max, 100) + x = radius * np.outer(np.cos(u), np.ones(len(v))) + x_center + y = radius * np.outer(np.sin(u), np.ones(len(v))) + y_center + z = np.outer(np.ones(len(u)), v) + ax.plot_surface(x, y, z, color='gray', alpha=0.3) + +# Plot start and goal points +ax.scatter(*x_init, color='magenta', label="Start") +ax.scatter(*x_intermediate, color='pink', label="Intermediate Goal") +ax.scatter(*x_second_goal, color='cyan', label="Second Goal") +ax.scatter(*x_final_goal, color='green', label="Final Goal") + +# Animation of the ML path on the same figure +drone_path_line, = ax.plot([], [], [], color='orange', linewidth=2) + +def update_line(num, ml_path, line): + line.set_data(ml_path[:num, 0], ml_path[:num, 1]) + line.set_3d_properties(ml_path[:num, 2]) + return line, + +ani = animation.FuncAnimation( + fig, update_line, frames=len(ml_path), fargs=(ml_path, drone_path_line), interval=100, blit=True +) + +# Add legend and show the figure +ax.legend() +plt.show() +# Plot static obstacles +for obs in all_obstacles: + x_center, y_center, z_min, z_max, radius = obs + u = np.linspace(0, 2 * np.pi, 100) + v = np.linspace(z_min, z_max, 100) + x = radius * np.outer(np.cos(u), np.ones(len(v))) + x_center + y = radius * np.outer(np.sin(u), np.ones(len(v))) + y_center + z = np.outer(np.ones(len(u)), v) + ax.plot_surface(x, y, z, color='gray', alpha=0.3) + +print("RRT to first intermediate goal...") +path1 = try_rrt_to_goal(X, 500, x_init, x_intermediate, 4024, 1, 0.1, all_obstacles) + +if path1 is not None: + adjust_speed_to_reach_goal(path1, specified_time_intermediate, dwa_params, "Intermediate Goal", ax) + ax.plot(*zip(*path1), linestyle='--', color='red', label="RRT to Intermediate") + + print("RRT to second intermediate goal...") + path2 = try_rrt_to_goal(X, 500, x_intermediate, x_second_goal, 4024, 1, 0.1, all_obstacles) + + if path2 is not None: + adjust_speed_to_reach_goal(path2, specified_time_second, dwa_params, "Second Goal", ax) + ax.plot(*zip(*path2), linestyle='--', color='blue', label="RRT to Second Goal") + + print("RRT to final goal...") + path3 = try_rrt_to_goal(X, 500, x_second_goal, x_final_goal, 4024, 1, 0.1, all_obstacles) + + if path3 is not None: + adjust_speed_to_reach_goal(path3, specified_time_final, dwa_params, "Final Goal", ax) + ax.plot(*zip(*path3), linestyle='--', color='green', label="RRT to Final Goal") + else: + print("Failed to reach the final goal.") + else: + print("Failed to reach the second goal.") +else: + print("Failed to reach the intermediate goal.") + +# Apply DWA for local optimization along the RRT path +if path1 is not None and path2 is not None and path3 is not None: + dwa = DWA(dwa_params) + optimized_path = [] + + for i in range(len(path1) - 1): + start_point = path1[i] + (0.0, 0.0) + end_point = path1[i + 1] + local_path = dwa.plan(start_point, end_point, X, all_obstacles) + optimized_path.extend(local_path) + + # Adjust speed for the DWA optimized path + adjust_speed_to_reach_goal(optimized_path, specified_time_final, dwa_params, "DWA Optimized Path", ax) + ax.plot(*zip(*optimized_path), linestyle='--', color='cyan', label="DWA Optimized Path") + +# Training the DQN +env = DroneEnv(X, x_init, x_final_goal, all_obstacles, dwa_params) +env.train(episodes=10) + +# Initialize the DroneEnv environment for path optimization +state = env.reset() +done = False +ml_path = [] +agent = DQNAgent(env.state_size, env.action_size) + +while not done: + action = agent.act(state) + next_state, _, done = env.step(action) + ml_path.append(next_state) + state = next_state + +# Convert ml_path to a numpy array +ml_path = np.array(ml_path) + +# Check if ml_path has valid data +if ml_path.size == 0: + print("ML path is empty. Ensure the DQN agent is working correctly.") +else: + ax.plot(*ml_path.T, color='black', label="ML Path") + ax.legend() + +# Show the plot +plt.show() + diff --git a/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size_11.py b/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size_11.py new file mode 100644 index 0000000..687fbd1 --- /dev/null +++ b/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size_11.py @@ -0,0 +1,535 @@ +#generate random poisitions: +import numpy as np +import time +from rtree import index +import sys +import uuid +import skfuzzy as fuzz +from skfuzzy import control as ctrl +import random +from tensorflow.keras.models import load_model +import matplotlib.pyplot as plt +import matplotlib.animation as animation + +sys.path.append('/home/dell/rrt-algorithms') + +from rrt_algorithms.rrt.rrt import RRT +from rrt_algorithms.search_space.search_space2 import SearchSpace +from rrt_algorithms.utilities.plotting2 import Plot +from rrt_algorithms.dwa_algorithm.DWA3 import DWA, FuzzyController +from rrt_algorithms.dqn_algorithm.DQN import DQNAgent +from rrt_algorithms.dqn_algorithm.DQN import DroneEnv +from rrt_algorithms.utilities.obstacle_generation2 import generate_random_cylindrical_obstacles + +# Define the search space dimensions +X_dimensions = np.array([(0, 100), (0, 100), (0, 100)]) +X = SearchSpace(X_dimensions) + +# Helper function to generate random positions +def generate_random_position(dimensions): + x_min, x_max = dimensions[0] + y_min, y_max = dimensions[1] + z_min, z_max = dimensions[2] + return ( + random.uniform(x_min, x_max), + random.uniform(y_min, y_max), + random.uniform(z_min, z_max) + ) + +# Initial and goal positions (Randomized) +x_init = generate_random_position(X_dimensions) # Random starting position +x_intermediate = generate_random_position(X_dimensions) # Random intermediate goal +x_second_goal = generate_random_position(X_dimensions) # Random second goal +x_final_goal = generate_random_position(X_dimensions) # Random final goal + +# Generate random obstacles +n = 7 # Number of random obstacles +Obstacles = generate_random_cylindrical_obstacles(X, x_init, x_final_goal, n) + +# Define static obstacles +obstacles = [ + (10, 82, 0, 85, 15), + (80, 20, 0, 60, 19), + (10, 30, 0, 90, 15), + (80, 80, 0, 70, 22), + (50, 50, 0, 50, 22), +] + +# Combine static and randomly generated obstacles into one list +all_obstacles = obstacles + Obstacles + +# Initialize the SearchSpace with all obstacles +X = SearchSpace(X_dimensions, all_obstacles) + +# RRT parameters +q = 300 +r = 1 +max_samples = 2024 +prc = 0.1 + +# DWA parameters +dwa_params = { + 'max_speed': 1.0, + 'min_speed': 0.0, + 'max_yaw_rate': 40.0 * np.pi / 180.0, + 'max_accel': 0.3, + 'v_reso': 0.05, + 'yaw_rate_reso': 0.2 * np.pi / 180.0, + 'dt': 0.1, + 'predict_time': 2.0, + 'to_goal_cost_gain': 1.5, + 'speed_cost_gain': 0.5, + 'obstacle_cost_gain': 1.0, +} + +def compute_energy_usage(path, velocity): + energy = 0.0 + for i in range(1, len(path)): + distance = np.linalg.norm(np.array(path[i]) - np.array(path[i-1])) + energy += distance * velocity + return energy + +def min_obstacle_clearance(path, obstacles): + min_clearance = float('inf') + for point in path: + for obs in obstacles: + clearance = np.linalg.norm(np.array(point[:2]) - np.array(obs[:2])) - obs[4] + if clearance < min_clearance: + min_clearance = clearance + return min_clearance + +def path_length(path): + return sum(np.linalg.norm(np.array(path[i+1]) - np.array(path[i])) for i in range(len(path) - 1)) + +def path_smoothness(path): + total_curvature = 0.0 + for i in range(1, len(path) - 1): + vec1 = np.array(path[i]) - np.array(path[i-1]) + vec2 = np.array(path[i+1]) - np.array(path[i]) + angle = np.arccos(np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2))) + total_curvature += angle + return total_curvature + + +# Adaptive Large Neighborhood Search (ALNS) Functions +def alns_optimize_path(path, X, all_obstacles, max_iterations=100): + neighborhoods = [segment_change, detour_addition, direct_connection] + neighborhood_scores = {segment_change: 1.0, detour_addition: 1.0, direct_connection: 1.0} + current_path = path.copy() + + for _ in range(max_iterations): + neighborhood = random.choices(neighborhoods, weights=neighborhood_scores.values())[0] + new_path = neighborhood(current_path, X, all_obstacles) + + new_path_length = path_length(new_path) + current_path_length = path_length(current_path) + + if new_path_length < current_path_length: + current_path = new_path + neighborhood_scores[neighborhood] *= 1.1 # Reward successful neighborhood + else: + neighborhood_scores[neighborhood] *= 0.9 # Penalize unsuccessful neighborhood + + return current_path + +def segment_change(path, X, all_obstacles, r=1): + if len(path) < 3: + return path + + i = random.randint(0, len(path) - 3) + j = random.randint(i + 2, len(path) - 1) + + x_a = path[i] + x_b = path[j] + + spatial_x_a = np.array(x_a[:3]) + spatial_x_b = np.array(x_b[:3]) + + new_point_spatial = spatial_x_a + (spatial_x_b - spatial_x_a) / 2 + new_point = list(new_point_spatial) + list(x_a[3:]) + + if X.collision_free(spatial_x_a, new_point_spatial, r) and X.collision_free(new_point_spatial, spatial_x_b, r): + new_path = path[:i + 1] + [new_point] + path[j:] + return new_path + + return path + +def detour_addition(path, X, all_obstacles, r=1): + if len(path) < 2: + return path + + i = random.randint(0, len(path) - 2) + x_a = path[i] + x_b = path[i + 1] + + spatial_x_a = np.array(x_a[:3]) + spatial_x_b = np.array(x_b[:3]) + + detour_point_3d = spatial_x_a + (np.random.rand(3) - 0.5) * 2 * r + detour_point = list(detour_point_3d) + list(x_a[3:]) + + if X.collision_free(spatial_x_a, detour_point_3d, r) and X.collision_free(detour_point_3d, spatial_x_b, r): + new_path = path[:i + 1] + [detour_point] + path[i + 1:] + return new_path + + return path + +def direct_connection(path, X, all_obstacles, r=1): + if len(path) < 3: + return path # Can't directly connect if there aren't enough points + + new_path = path.copy() + i = random.randint(0, len(path) - 3) + j = random.randint(i + 2, len(path) - 1) + + x_a = path[i][:3] + x_b = path[j][:3] + + if X.collision_free(x_a, x_b, r): + new_path = new_path[:i + 1] + new_path[j:] + + return new_path + +def find_closest_point(path, goal): + distances = [np.linalg.norm(np.array(p[:3]) - np.array(goal)) for p in path] + return np.argmin(distances) + + +#adjust speed as required + +def is_inside_obstacle(point, obstacles): + """ + Check if a point is inside any obstacle. + Assumes obstacles are represented as (x_center, y_center, z_min, z_max, radius). + """ + for obs in obstacles: + x_center, y_center, z_min, z_max, radius = obs + distance = np.linalg.norm(np.array(point[:2]) - np.array([x_center, y_center])) + if distance < radius and z_min <= point[2] <= z_max: + return True + return False + +# Speed calculation and adjustment function +def calculate_required_speed(distance, time): + if time > 0: + return distance / time + return float('inf') # Infinite speed if no time constraint + +def adjust_speed_to_reach_goal(path, total_time, dwa_params, label, ax=None): + if path is None or len(path) == 0: + print(f"Warning: No path found for {label}, skipping speed adjustment.") + return + + path_length_value = path_length(path) + required_speed = calculate_required_speed(path_length_value, total_time) + + # Clip speed to the maximum allowable speed + adjusted_speed = min(required_speed, dwa_params['max_speed']) + dwa_params['max_speed'] = adjusted_speed + + # Print speed in terminal + print(f"Adjusted speed for {label}: {adjusted_speed:.2f} units/s (Distance: {path_length_value:.2f} units, Time: {total_time} s)") + + # Annotate speed on the plot + if ax is not None: + midpoint = np.mean(path, axis=0) + ax.text(midpoint[0], midpoint[1], midpoint[2], f"Speed: {adjusted_speed:.2f} u/s", color='black', fontsize=10) + +# Function to calculate path length +def path_length(path): + return sum(np.linalg.norm(np.array(path[i+1]) - np.array(path[i])) for i in range(len(path) - 1)) + +# Function to try RRT to a goal and return the path +def try_rrt_to_goal(X, q, start, goal, max_samples, r, prc, obstacles): + rrt = RRT(X, q, start, goal, max_samples, r, prc) + path = rrt.rrt_search() + if path is None: + print(f"RRT failed to find a path to {goal}.") + return path + +# RRT pathfinding to goals +specified_time_intermediate = 20 +specified_time_second = 30 +specified_time_final = 50 + + +print("RRT to first intermediate goal...") +start_time = time.time() +path1 = try_rrt_to_goal(X, q, x_init, x_intermediate, max_samples, r, prc, all_obstacles) +rrt_time = time.time() - start_time + +if path1 is not None: + adjust_speed_to_reach_goal(path1, specified_time_intermediate, dwa_params,"Intermediate Goal") # Adjust speed for the intermediate goal + + print("RRT to second intermediate goal...") + path2 = try_rrt_to_goal(X, q, x_intermediate, x_second_goal, max_samples, r, prc, all_obstacles) + + if path2 is not None: + adjust_speed_to_reach_goal(path2, specified_time_second, dwa_params,"Second Goal") # Adjust speed for the second goal + + print("RRT to final goal...") + path3 = try_rrt_to_goal(X, q, x_second_goal, x_final_goal, max_samples, r, prc, all_obstacles) + + # Combine all paths + if path3 is not None: + adjust_speed_to_reach_goal(path3, specified_time_final, dwa_params,"Final Goal") + # Adjust speed for the final goal + path = path1 + path2[1:] + path3[1:] + else: + path = path1 + path2[1:] + else: + path = path1 +else: + path = None + +# Before calculating the path length, check if the path is valid (not None) +if path is not None: + # Calculate and print path length + rrt_path_length = path_length(path) + print(f"RRT Path Length: {rrt_path_length:.2f}") +else: + print("Error: RRT failed to find a valid path. Path length calculation skipped.") + + +# Apply DWA for local optimization along the RRT path +if path is not None: + dwa = DWA(dwa_params) + optimized_path = [] + + start_time = time.time() + for i in range(len(path) - 1): + start_point = path[i] + (0.0, 0.0) + end_point = path[i + 1] + + local_path = dwa.plan(start_point, end_point, X, all_obstacles) + optimized_path.extend(local_path) + dwa_time = time.time() - start_time + + # Apply ALNS optimization to each segment of the path + print("Applying ALNS optimization...") + alns_optimized_path = [] + + index_intermediate = find_closest_point(optimized_path, x_intermediate) + index_second_goal = find_closest_point(optimized_path, x_second_goal) + + segment1 = optimized_path[:index_intermediate + 1] + alns_optimized_segment1 = alns_optimize_path(segment1, X, all_obstacles, max_iterations=100) + + segment2 = optimized_path[index_intermediate:index_second_goal + 1] + alns_optimized_segment2 = alns_optimize_path(segment2, X, all_obstacles, max_iterations=100) + + segment3 = optimized_path[index_second_goal:] + alns_optimized_segment3 = alns_optimize_path(segment3, X, all_obstacles, max_iterations=100) + + alns_optimized_path = alns_optimized_segment1 + alns_optimized_segment2[1:] + alns_optimized_segment3[1:] + + def validate_and_correct_path(path): + corrected_path = [] + for idx, point in enumerate(path): + if isinstance(point, (list, tuple)) and len(point) >= 2: + if isinstance(point[0], (list, tuple)): + point = [item for sublist in point for item in sublist] + corrected_path.append(point[:3]) + else: + raise ValueError(f"Point {idx} in path is incorrectly formatted: {point}") + return corrected_path + + optimized_path = validate_and_correct_path(optimized_path) + alns_optimized_path = validate_and_correct_path(alns_optimized_path) + +# Continue the rest of your code as before... + + + +# Metrics calculation +rrt_path_length = path_length(path) +dwa_path_length = path_length(optimized_path) +alns_path_length = path_length(alns_optimized_path) + +rrt_smoothness = path_smoothness(path) +dwa_smoothness = path_smoothness(optimized_path) +alns_smoothness = path_smoothness(alns_optimized_path) + +rrt_clearance = min_obstacle_clearance(path, all_obstacles) +dwa_clearance = min_obstacle_clearance(optimized_path, all_obstacles) +alns_clearance = min_obstacle_clearance(alns_optimized_path, all_obstacles) + +average_velocity = dwa_params['max_speed'] +rrt_energy = compute_energy_usage(path, average_velocity) +dwa_energy = compute_energy_usage(optimized_path, average_velocity) +alns_energy = compute_energy_usage(alns_optimized_path, average_velocity) + + +# Training the DQN +env = DroneEnv(X, x_init, x_final_goal, all_obstacles, dwa_params) +env.train(episodes=20) +# After training, use the learned policy in your DWA + +# Initialize the DroneEnv environment for path optimization +state = env.reset() +done = False +ml_path = [] +agent = DQNAgent(env.state_size, env.action_size) + +while not done: + action = agent.act(state) + next_state, _, done = env.step(action) + ml_path.append(next_state) + state = next_state + +# Convert ml_path to a numpy array +ml_path = np.array(ml_path) + +# Check if ml_path has valid data +if ml_path.size == 0: + print("ML path is empty. Ensure the DQN agent is working correctly.") +else: + print("ML path:", ml_path) + +# Save the trained DQN model +agent.model.save("dqn_model.keras") +print("DQN model saved as dqn_model.keras") + +# Print Metrics +print(f"RRT Path Length: {rrt_path_length}") +print(f"DWA Optimized Path Length: {dwa_path_length}") +print(f"ALNS Optimized Path Length: {alns_path_length}") +print(f"RRT Path Smoothness: {rrt_smoothness}") +print(f"DWA Optimized Path Smoothness: {dwa_smoothness}") +print(f"ALNS Optimized Path Smoothness: {alns_smoothness}") +print(f"RRT Path Minimum Clearance: {rrt_clearance}") +print(f"DWA Optimized Path Minimum Clearance: {dwa_clearance}") +print(f"ALNS Optimized Path Minimum Clearance: {alns_clearance}") + +# Ensure the final paths are properly flattened and structured +def flatten_path_points(path): + cleaned_path = [] + for idx, point in enumerate(path): + if isinstance(point, np.ndarray): + flat_point = point.flatten().tolist() + if len(flat_point) >= 3: + cleaned_path.append(flat_point[:3]) # Take only the first three elements (x, y, z) + else: + raise ValueError(f"Point {idx} in optimized_path is incorrectly formatted: {flat_point}") + elif isinstance(point, (list, tuple)) and len(point) >= 3: + cleaned_path.append(point[:3]) # Handle lists or tuples directly + else: + raise ValueError(f"Point {idx} in optimized_path is not correctly formatted: {point}") + return np.array(cleaned_path) + +# Apply the flattening function to optimized_path before plotting +try: + optimized_path = flatten_path_points(optimized_path) + ml_path = flatten_path_points(ml_path) +except ValueError as e: + print(f"Error encountered during flattening: {e}") + + + +# Time calculation function +def calculate_time_to_goal(path_length, speed): + """Calculate the time it takes to reach the goal given the path length and speed.""" + if speed <= 0: + raise ValueError("Speed must be positive to calculate time.") + return path_length / speed + +# Function to print time to reach the goal for each method +def print_time_to_goal(label, path_length, speed): + time_to_goal = calculate_time_to_goal(path_length, speed) + print(f"{label} Time to Goal: {time_to_goal:.2f} seconds") + return time_to_goal + +# Now include the time calculation and improvement comparison +if path is not None: + rrt_path_length = path_length(path) + dwa_path_length = path_length(optimized_path) + alns_path_length = path_length(alns_optimized_path) + + # Assuming max speed for each method (adjusted by algorithms) + rrt_speed = dwa_params['max_speed'] # RRT typically uses the DWA's max speed + dwa_speed = dwa_params['max_speed'] + alns_speed = dwa_params['max_speed'] + + # Machine learning (ML) path speed + ml_speed = dwa_params['max_speed'] # Assuming ML also uses DWA's speed for comparison + + # Print and calculate the time for each algorithm + rrt_time = print_time_to_goal("RRT", rrt_path_length, rrt_speed) + dwa_time = print_time_to_goal("DWA Optimized", dwa_path_length, dwa_speed) + alns_time = print_time_to_goal("ALNS Optimized", alns_path_length, alns_speed) + + # If ML path is valid, calculate its time to goal + if ml_path.size > 0: + ml_path_length = path_length(ml_path) + ml_time = print_time_to_goal("Machine Learning Optimized", ml_path_length, ml_speed) + else: + ml_time = None + print("ML path is not valid for time calculation.") + + # Improvement analysis + print("\n--- Improvement Analysis ---") + if ml_time is not None: + improvement_from_rrt = rrt_time - ml_time + improvement_from_dwa = dwa_time - ml_time + improvement_from_alns = alns_time - ml_time + + print(f"Improvement from RRT: {improvement_from_rrt:.2f} seconds") + print(f"Improvement from DWA: {improvement_from_dwa:.2f} seconds") + print(f"Improvement from ALNS: {improvement_from_alns:.2f} seconds") + else: + print("ML time improvement calculation skipped due to invalid ML path.") + +# The rest of the code (plotting, animation) remains the same as before. + +# Plotting and Animation + +# First figure: RRT, DWA, ALNS paths with ML path +fig = plt.figure() +ax = fig.add_subplot(111, projection='3d') +ax.set_xlim(X_dimensions[0]) +ax.set_ylim(X_dimensions[1]) +ax.set_zlim(X_dimensions[2]) + +# Plot the RRT, DWA, and ALNS paths as dashed lines +ax.plot(*zip(*path), linestyle='--', color='red', label="RRT Path") +ax.plot(*zip(*optimized_path), linestyle='--', color='blue', label="DWA Optimized Path") +ax.plot(*zip(*alns_optimized_path), linestyle='--', color='green', label="ALNS Optimized Path") + +# Plot the ML path +ax.plot(*ml_path.T, color='black', label="ML Path") + +# Plot static obstacles +for obs in all_obstacles: + x_center, y_center, z_min, z_max, radius = obs + u = np.linspace(0, 2 * np.pi, 100) + v = np.linspace(z_min, z_max, 100) + x = radius * np.outer(np.cos(u), np.ones(len(v))) + x_center + y = radius * np.outer(np.sin(u), np.ones(len(v))) + y_center + z = np.outer(np.ones(len(u)), v) + ax.plot_surface(x, y, z, color='gray', alpha=0.3) + +# Plot start and goal points +ax.scatter(*x_init, color='magenta', label="Start") +ax.scatter(*x_intermediate, color='pink', label="Intermediate Goal") +ax.scatter(*x_second_goal, color='cyan', label="Second Goal") +ax.scatter(*x_final_goal, color='green', label="Final Goal") + +# Animation of the ML path on the same figure +drone_path_line, = ax.plot([], [], [], color='orange', linewidth=2) + +def update_line(num, ml_path, line): + line.set_data(ml_path[:num, 0], ml_path[:num, 1]) + line.set_3d_properties(ml_path[:num, 2]) + return line, + +ani = animation.FuncAnimation( + fig, update_line, frames=len(ml_path), fargs=(ml_path, drone_path_line), interval=100, blit=True +) + +# Add legend and show the figure +ax.legend() +plt.show() + + + + diff --git a/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size_9+3.png b/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size_9+3.png new file mode 100644 index 0000000..aa70853 Binary files /dev/null and b/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size_9+3.png differ diff --git a/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size_9.py b/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size_9.py new file mode 100644 index 0000000..da88516 --- /dev/null +++ b/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size_9.py @@ -0,0 +1,434 @@ +#generate random poisitions: +import numpy as np +import time +from rtree import index +import sys +import uuid +import skfuzzy as fuzz +from skfuzzy import control as ctrl +import random +from tensorflow.keras.models import load_model +import matplotlib.pyplot as plt +import matplotlib.animation as animation + +sys.path.append('/home/dell/rrt-algorithms') + +from rrt_algorithms.rrt.rrt import RRT +from rrt_algorithms.search_space.search_space2 import SearchSpace +from rrt_algorithms.utilities.plotting2 import Plot +from rrt_algorithms.dwa_algorithm.DWA3 import DWA, FuzzyController +from rrt_algorithms.dqn_algorithm.DQN import DQNAgent +from rrt_algorithms.dqn_algorithm.DQN import DroneEnv +from rrt_algorithms.utilities.obstacle_generation2 import generate_random_cylindrical_obstacles + +# Define the search space dimensions +X_dimensions = np.array([(0, 100), (0, 100), (0, 100)]) +X = SearchSpace(X_dimensions) + +# Helper function to generate random positions +def generate_random_position(dimensions): + x_min, x_max = dimensions[0] + y_min, y_max = dimensions[1] + z_min, z_max = dimensions[2] + return ( + random.uniform(x_min, x_max), + random.uniform(y_min, y_max), + random.uniform(z_min, z_max) + ) + +# Initial and goal positions (Randomized) +x_init = generate_random_position(X_dimensions) # Random starting position +x_intermediate = generate_random_position(X_dimensions) # Random intermediate goal +x_second_goal = generate_random_position(X_dimensions) # Random second goal +x_final_goal = generate_random_position(X_dimensions) # Random final goal + +# Generate random obstacles +n = 7 # Number of random obstacles +Obstacles = generate_random_cylindrical_obstacles(X, x_init, x_final_goal, n) + +# Define static obstacles +obstacles = [ + (10, 82, 0, 85, 15), + (80, 20, 0, 60, 19), + (10, 30, 0, 90, 15), + (80, 80, 0, 70, 22), + (50, 50, 0, 50, 22), +] + +# Combine static and randomly generated obstacles into one list +all_obstacles = obstacles + Obstacles + +# Initialize the SearchSpace with all obstacles +X = SearchSpace(X_dimensions, all_obstacles) + +# RRT parameters +q = 700 +r = 1 +max_samples = 4024 +prc = 0.1 + +# DWA parameters +dwa_params = { + 'max_speed': 1.0, + 'min_speed': 0.0, + 'max_yaw_rate': 40.0 * np.pi / 180.0, + 'max_accel': 0.3, + 'v_reso': 0.05, + 'yaw_rate_reso': 0.2 * np.pi / 180.0, + 'dt': 0.1, + 'predict_time': 2.0, + 'to_goal_cost_gain': 1.5, + 'speed_cost_gain': 0.5, + 'obstacle_cost_gain': 1.0, +} + +def compute_energy_usage(path, velocity): + energy = 0.0 + for i in range(1, len(path)): + distance = np.linalg.norm(np.array(path[i]) - np.array(path[i-1])) + energy += distance * velocity + return energy + +def min_obstacle_clearance(path, obstacles): + min_clearance = float('inf') + for point in path: + for obs in obstacles: + clearance = np.linalg.norm(np.array(point[:2]) - np.array(obs[:2])) - obs[4] + if clearance < min_clearance: + min_clearance = clearance + return min_clearance + +def path_length(path): + return sum(np.linalg.norm(np.array(path[i+1]) - np.array(path[i])) for i in range(len(path) - 1)) + +def path_smoothness(path): + total_curvature = 0.0 + for i in range(1, len(path) - 1): + vec1 = np.array(path[i]) - np.array(path[i-1]) + vec2 = np.array(path[i+1]) - np.array(path[i]) + angle = np.arccos(np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2))) + total_curvature += angle + return total_curvature + + +# Adaptive Large Neighborhood Search (ALNS) Functions +def alns_optimize_path(path, X, all_obstacles, max_iterations=100): + neighborhoods = [segment_change, detour_addition, direct_connection] + neighborhood_scores = {segment_change: 1.0, detour_addition: 1.0, direct_connection: 1.0} + current_path = path.copy() + + for _ in range(max_iterations): + neighborhood = random.choices(neighborhoods, weights=neighborhood_scores.values())[0] + new_path = neighborhood(current_path, X, all_obstacles) + + new_path_length = path_length(new_path) + current_path_length = path_length(current_path) + + if new_path_length < current_path_length: + current_path = new_path + neighborhood_scores[neighborhood] *= 1.1 # Reward successful neighborhood + else: + neighborhood_scores[neighborhood] *= 0.9 # Penalize unsuccessful neighborhood + + return current_path + +def segment_change(path, X, all_obstacles, r=1): + if len(path) < 3: + return path + + i = random.randint(0, len(path) - 3) + j = random.randint(i + 2, len(path) - 1) + + x_a = path[i] + x_b = path[j] + + spatial_x_a = np.array(x_a[:3]) + spatial_x_b = np.array(x_b[:3]) + + new_point_spatial = spatial_x_a + (spatial_x_b - spatial_x_a) / 2 + new_point = list(new_point_spatial) + list(x_a[3:]) + + if X.collision_free(spatial_x_a, new_point_spatial, r) and X.collision_free(new_point_spatial, spatial_x_b, r): + new_path = path[:i + 1] + [new_point] + path[j:] + return new_path + + return path + +def detour_addition(path, X, all_obstacles, r=1): + if len(path) < 2: + return path + + i = random.randint(0, len(path) - 2) + x_a = path[i] + x_b = path[i + 1] + + spatial_x_a = np.array(x_a[:3]) + spatial_x_b = np.array(x_b[:3]) + + detour_point_3d = spatial_x_a + (np.random.rand(3) - 0.5) * 2 * r + detour_point = list(detour_point_3d) + list(x_a[3:]) + + if X.collision_free(spatial_x_a, detour_point_3d, r) and X.collision_free(detour_point_3d, spatial_x_b, r): + new_path = path[:i + 1] + [detour_point] + path[i + 1:] + return new_path + + return path + +def direct_connection(path, X, all_obstacles, r=1): + if len(path) < 3: + return path # Can't directly connect if there aren't enough points + + new_path = path.copy() + i = random.randint(0, len(path) - 3) + j = random.randint(i + 2, len(path) - 1) + + x_a = path[i][:3] + x_b = path[j][:3] + + if X.collision_free(x_a, x_b, r): + new_path = new_path[:i + 1] + new_path[j:] + + return new_path + +def find_closest_point(path, goal): + distances = [np.linalg.norm(np.array(p[:3]) - np.array(goal)) for p in path] + return np.argmin(distances) + + +def is_inside_obstacle(point, obstacles): + """ + Check if a point is inside any obstacle. + Assumes obstacles are represented as (x_center, y_center, z_min, z_max, radius). + """ + for obs in obstacles: + x_center, y_center, z_min, z_max, radius = obs + distance = np.linalg.norm(np.array(point[:2]) - np.array([x_center, y_center])) + if distance < radius and z_min <= point[2] <= z_max: + return True + return False + +# Function to try RRT to a goal and return the path or None +def try_rrt_to_goal(X, q, start, goal, max_samples, r, prc, obstacles): + if is_inside_obstacle(goal, obstacles): + print(f"Destination {goal} is inside an obstacle and not achievable.") + return None + else: + rrt = RRT(X, q, start, goal, max_samples, r, prc) + return rrt.rrt_search() + +# RRT pathfinding to the first intermediate goal +print("RRT to first intermediate goal...") +start_time = time.time() +path1 = try_rrt_to_goal(X, q, x_init, x_intermediate, max_samples, r, prc, all_obstacles) +rrt_time = time.time() - start_time + +if path1 is not None: + print("RRT to second intermediate goal...") + path2 = try_rrt_to_goal(X, q, x_intermediate, x_second_goal, max_samples, r, prc, all_obstacles) + + if path2 is not None: + print("RRT to final goal...") + path3 = try_rrt_to_goal(X, q, x_second_goal, x_final_goal, max_samples, r, prc, all_obstacles) + + # Combine all paths + if path3 is not None: + path = path1 + path2[1:] + path3[1:] + else: + path = path1 + path2[1:] + else: + path = path1 +else: + path = None + +# Before calculating the path length, check if the path is valid (not None) +if path is not None: + # Calculate and print path length + rrt_path_length = path_length(path) + print(f"RRT Path Length: {rrt_path_length}") +else: + print("Error: RRT failed to find a valid path. Path length calculation skipped.") + + +# Apply DWA for local optimization along the RRT path +if path is not None: + dwa = DWA(dwa_params) + optimized_path = [] + + start_time = time.time() + for i in range(len(path) - 1): + start_point = path[i] + (0.0, 0.0) + end_point = path[i + 1] + + local_path = dwa.plan(start_point, end_point, X, all_obstacles) + optimized_path.extend(local_path) + dwa_time = time.time() - start_time + + # Apply ALNS optimization to each segment of the path + print("Applying ALNS optimization...") + alns_optimized_path = [] + + index_intermediate = find_closest_point(optimized_path, x_intermediate) + index_second_goal = find_closest_point(optimized_path, x_second_goal) + + segment1 = optimized_path[:index_intermediate + 1] + alns_optimized_segment1 = alns_optimize_path(segment1, X, all_obstacles, max_iterations=100) + + segment2 = optimized_path[index_intermediate:index_second_goal + 1] + alns_optimized_segment2 = alns_optimize_path(segment2, X, all_obstacles, max_iterations=100) + + segment3 = optimized_path[index_second_goal:] + alns_optimized_segment3 = alns_optimize_path(segment3, X, all_obstacles, max_iterations=100) + + alns_optimized_path = alns_optimized_segment1 + alns_optimized_segment2[1:] + alns_optimized_segment3[1:] + + def validate_and_correct_path(path): + corrected_path = [] + for idx, point in enumerate(path): + if isinstance(point, (list, tuple)) and len(point) >= 2: + if isinstance(point[0], (list, tuple)): + point = [item for sublist in point for item in sublist] + corrected_path.append(point[:3]) + else: + raise ValueError(f"Point {idx} in path is incorrectly formatted: {point}") + return corrected_path + + optimized_path = validate_and_correct_path(optimized_path) + alns_optimized_path = validate_and_correct_path(alns_optimized_path) + +# Continue the rest of your code as before... + + + +# Metrics calculation +rrt_path_length = path_length(path) +dwa_path_length = path_length(optimized_path) +alns_path_length = path_length(alns_optimized_path) + +rrt_smoothness = path_smoothness(path) +dwa_smoothness = path_smoothness(optimized_path) +alns_smoothness = path_smoothness(alns_optimized_path) + +rrt_clearance = min_obstacle_clearance(path, all_obstacles) +dwa_clearance = min_obstacle_clearance(optimized_path, all_obstacles) +alns_clearance = min_obstacle_clearance(alns_optimized_path, all_obstacles) + +average_velocity = dwa_params['max_speed'] +rrt_energy = compute_energy_usage(path, average_velocity) +dwa_energy = compute_energy_usage(optimized_path, average_velocity) +alns_energy = compute_energy_usage(alns_optimized_path, average_velocity) + + +# Training the DQN +env = DroneEnv(X, x_init, x_final_goal, all_obstacles, dwa_params) +env.train(episodes=50) +# After training, use the learned policy in your DWA + +# Initialize the DroneEnv environment for path optimization +state = env.reset() +done = False +ml_path = [] +agent = DQNAgent(env.state_size, env.action_size) + +while not done: + action = agent.act(state) + next_state, _, done = env.step(action) + ml_path.append(next_state) + state = next_state + +# Convert ml_path to a numpy array +ml_path = np.array(ml_path) + +# Check if ml_path has valid data +if ml_path.size == 0: + print("ML path is empty. Ensure the DQN agent is working correctly.") +else: + print("ML path:", ml_path) + +# Save the trained DQN model +agent.model.save("dqn_model.keras") +print("DQN model saved as dqn_model.keras") + +# Print Metrics +print(f"RRT Path Length: {rrt_path_length}") +print(f"DWA Optimized Path Length: {dwa_path_length}") +print(f"ALNS Optimized Path Length: {alns_path_length}") +print(f"RRT Path Smoothness: {rrt_smoothness}") +print(f"DWA Optimized Path Smoothness: {dwa_smoothness}") +print(f"ALNS Optimized Path Smoothness: {alns_smoothness}") +print(f"RRT Path Minimum Clearance: {rrt_clearance}") +print(f"DWA Optimized Path Minimum Clearance: {dwa_clearance}") +print(f"ALNS Optimized Path Minimum Clearance: {alns_clearance}") + +# Ensure the final paths are properly flattened and structured +def flatten_path_points(path): + cleaned_path = [] + for idx, point in enumerate(path): + if isinstance(point, np.ndarray): + flat_point = point.flatten().tolist() + if len(flat_point) >= 3: + cleaned_path.append(flat_point[:3]) # Take only the first three elements (x, y, z) + else: + raise ValueError(f"Point {idx} in optimized_path is incorrectly formatted: {flat_point}") + elif isinstance(point, (list, tuple)) and len(point) >= 3: + cleaned_path.append(point[:3]) # Handle lists or tuples directly + else: + raise ValueError(f"Point {idx} in optimized_path is not correctly formatted: {point}") + return np.array(cleaned_path) + +# Apply the flattening function to optimized_path before plotting +try: + optimized_path = flatten_path_points(optimized_path) + ml_path = flatten_path_points(ml_path) +except ValueError as e: + print(f"Error encountered during flattening: {e}") + +# Plotting and Animation + +# First figure: RRT, DWA, ALNS paths with ML path +fig = plt.figure() +ax = fig.add_subplot(111, projection='3d') +ax.set_xlim(X_dimensions[0]) +ax.set_ylim(X_dimensions[1]) +ax.set_zlim(X_dimensions[2]) + +# Plot the RRT, DWA, and ALNS paths as dashed lines +ax.plot(*zip(*path), linestyle='--', color='red', label="RRT Path") +ax.plot(*zip(*optimized_path), linestyle='--', color='blue', label="DWA Optimized Path") +ax.plot(*zip(*alns_optimized_path), linestyle='--', color='green', label="ALNS Optimized Path") + +# Plot the ML path +ax.plot(*ml_path.T, color='black', label="ML Path") + +# Plot static obstacles +for obs in all_obstacles: + x_center, y_center, z_min, z_max, radius = obs + u = np.linspace(0, 2 * np.pi, 100) + v = np.linspace(z_min, z_max, 100) + x = radius * np.outer(np.cos(u), np.ones(len(v))) + x_center + y = radius * np.outer(np.sin(u), np.ones(len(v))) + y_center + z = np.outer(np.ones(len(u)), v) + ax.plot_surface(x, y, z, color='gray', alpha=0.3) + +# Plot start and goal points +ax.scatter(*x_init, color='magenta', label="Start") +ax.scatter(*x_intermediate, color='pink', label="Intermediate Goal") +ax.scatter(*x_second_goal, color='cyan', label="Second Goal") +ax.scatter(*x_final_goal, color='green', label="Final Goal") + +# Animation of the ML path on the same figure +drone_path_line, = ax.plot([], [], [], color='orange', linewidth=2) + +def update_line(num, ml_path, line): + line.set_data(ml_path[:num, 0], ml_path[:num, 1]) + line.set_3d_properties(ml_path[:num, 2]) + return line, + +ani = animation.FuncAnimation( + fig, update_line, frames=len(ml_path), fargs=(ml_path, drone_path_line), interval=100, blit=True +) + +# Add legend and show the figure +ax.legend() +plt.show() + + diff --git a/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size_9_1.png b/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size_9_1.png new file mode 100644 index 0000000..9491a69 Binary files /dev/null and b/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size_9_1.png differ diff --git a/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size_9_2.png b/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size_9_2.png new file mode 100644 index 0000000..5ec921c Binary files /dev/null and b/examples/rrt/rrt_3d_cylinder_DWA_BVH_1_drone_size_9_2.png differ diff --git a/examples/rrt/rrt_3d_with_random_obstacles.py b/examples/rrt/rrt_3d_with_random_obstacles.py index 380d706..dfee03a 100644 --- a/examples/rrt/rrt_3d_with_random_obstacles.py +++ b/examples/rrt/rrt_3d_with_random_obstacles.py @@ -1,11 +1,12 @@ # This file is subject to the terms and conditions defined in # file 'LICENSE', which is part of this source code package. import numpy as np - +import sys +sys.path.append('/home/dell/rrt-algorithms') from rrt_algorithms.rrt.rrt import RRT -from rrt_algorithms.search_space.search_space import SearchSpace +from rrt_algorithms.search_space.search_space0 import SearchSpace from rrt_algorithms.utilities.obstacle_generation import generate_random_obstacles -from rrt_algorithms.utilities.plotting import Plot +from rrt_algorithms.utilities.plotting0 import Plot X_dimensions = np.array([(0, 100), (0, 100), (0, 100)]) # dimensions of Search Space x_init = (0, 0, 0) # starting location diff --git a/examples/rrt/test.py b/examples/rrt/test.py new file mode 100644 index 0000000..517c76d --- /dev/null +++ b/examples/rrt/test.py @@ -0,0 +1,29 @@ +import h5py +import numpy as np + +# Sample data +data = np.random.random((100, 100)) +def print_h5_structure(name, obj): + """Function to print the structure of an HDF5 file.""" + if isinstance(obj, h5py.Group): + print(f"{name} (Group)") + elif isinstance(obj, h5py.Dataset): + print(f"{name} (Dataset) - Shape: {obj.shape} - Dtype: {obj.dtype}") +# Writing data to an HDF5 file +file_path = "example.h5" + +with h5py.File(file_path, "w") as h5file: + # Creating a dataset in the file + h5file.create_dataset("dataset_name", data=data) + # Optionally flush data to disk + h5file.flush() + +# Verify that data was written correctly +with h5py.File(file_path, "r") as h5file: + if "dataset_name" in h5file: + dataset = h5file["dataset_name"] + print("Data shape:", dataset.shape) + print("Sample data:", dataset[:5, :5]) + else: + print("Dataset not found in the file.") + diff --git a/examples/rrt_bid/rrt_star_bid_2d.py b/examples/rrt_bid/rrt_star_bid_2d.py deleted file mode 100644 index 9f7827d..0000000 --- a/examples/rrt_bid/rrt_star_bid_2d.py +++ /dev/null @@ -1,38 +0,0 @@ -# This file is subject to the terms and conditions defined in -# file 'LICENSE', which is part of this source code package. -import numpy as np - -from rrt_algorithms.rrt.rrt_star_bid import RRTStarBidirectional -from rrt_algorithms.search_space.search_space import SearchSpace -from rrt_algorithms.utilities.plotting import Plot - -X_dimensions = np.array([(0, 100), (0, 100)]) # dimensions of Search Space -# obstacles -Obstacles = np.array([(20, 20, 40, 40), (20, 60, 40, 80), - (60, 20, 80, 40), (60, 60, 80, 80)]) -x_init = (0, 0) # starting location -x_goal = (100, 100) # goal location - -q = 8 # length of tree edges -r = 1 # length of smallest edge to check for intersection with obstacles -max_samples = 1024 # max number of samples to take before timing out -rewire_count = 32 # optional, number of nearby branches to rewire -prc = 0.1 # probability of checking for a connection to goal - -# create Search Space -X = SearchSpace(X_dimensions, Obstacles) - -# create rrt_search -rrt = RRTStarBidirectional( - X, q, x_init, x_goal, max_samples, r, prc, rewire_count) -path = rrt.rrt_star_bidirectional() - -# plot -plot = Plot("rrt_star_bid_2d") -plot.plot_tree(X, rrt.trees) -if path is not None: - plot.plot_path(X, path) -plot.plot_obstacles(X, Obstacles) -plot.plot_start(X, x_init) -plot.plot_goal(X, x_goal) -plot.draw(auto_open=True) diff --git a/examples/rrt_bid/rrt_star_bid_3d.py b/examples/rrt_bid/rrt_star_bid_3d.py deleted file mode 100644 index 1ce2d40..0000000 --- a/examples/rrt_bid/rrt_star_bid_3d.py +++ /dev/null @@ -1,39 +0,0 @@ -# This file is subject to the terms and conditions defined in -# file 'LICENSE', which is part of this source code package. -import numpy as np - -from rrt_algorithms.rrt.rrt_star_bid import RRTStarBidirectional -from rrt_algorithms.search_space.search_space import SearchSpace -from rrt_algorithms.utilities.plotting import Plot - -X_dimensions = np.array([(0, 100), (0, 100), (0, 100)]) # dimensions of Search Space -# obstacles -Obstacles = np.array( - [(20, 20, 20, 40, 40, 40), (20, 20, 60, 40, 40, 80), (20, 60, 20, 40, 80, 40), (60, 60, 20, 80, 80, 40), - (60, 20, 20, 80, 40, 40), (60, 20, 60, 80, 40, 80), (20, 60, 60, 40, 80, 80), (60, 60, 60, 80, 80, 80)]) -x_init = (0, 0, 0) # starting location -x_goal = (100, 100, 100) # goal location - -q = 8 # length of tree edges -r = 1 # length of smallest edge to check for intersection with obstacles -max_samples = 1024 # max number of samples to take before timing out -rewire_count = 32 # optional, number of nearby branches to rewire -prc = 0.01 # probability of checking for a connection to goal - -# create Search Space -X = SearchSpace(X_dimensions, Obstacles) - -# create rrt_search -rrt = RRTStarBidirectional( - X, q, x_init, x_goal, max_samples, r, prc, rewire_count) -path = rrt.rrt_star_bidirectional() - -# plot -plot = Plot("rrt_star_bid_3d") -plot.plot_tree(X, rrt.trees) -if path is not None: - plot.plot_path(X, path) -plot.plot_obstacles(X, Obstacles) -plot.plot_start(X, x_init) -plot.plot_goal(X, x_goal) -plot.draw(auto_open=True) diff --git a/examples/rrt_bid_h/rrt_star_bid_h_2d.py b/examples/rrt_bid_h/rrt_star_bid_h_2d.py deleted file mode 100644 index 7cf3ec4..0000000 --- a/examples/rrt_bid_h/rrt_star_bid_h_2d.py +++ /dev/null @@ -1,37 +0,0 @@ -# This file is subject to the terms and conditions defined in -# file 'LICENSE', which is part of this source code package. -import numpy as np - -from rrt_algorithms.rrt.rrt_star_bid_h import RRTStarBidirectionalHeuristic -from rrt_algorithms.search_space.search_space import SearchSpace -from rrt_algorithms.utilities.plotting import Plot - -X_dimensions = np.array([(0, 100), (0, 100)]) # dimensions of Search Space -# obstacles -Obstacles = np.array([(20, 20, 40, 40), (20, 60, 40, 80), - (60, 20, 80, 40), (60, 60, 80, 80)]) -x_init = (0, 0) # starting location -x_goal = (100, 100) # goal location - -q = 8 # length of tree edges -r = 1 # length of smallest edge to check for intersection with obstacles -max_samples = 1024 # max number of samples to take before timing out -rewire_count = 32 # optional, number of nearby branches to rewire -prc = 0.01 # probability of checking for a connection to goal - -# create Search Space -X = SearchSpace(X_dimensions, Obstacles) - -# create rrt_search -rrt = RRTStarBidirectionalHeuristic(X, q, x_init, x_goal, max_samples, r, prc, rewire_count) -path = rrt.rrt_star_bid_h() - -# plot -plot = Plot("rrt_star_bid_h_2d") -plot.plot_tree(X, rrt.trees) -if path is not None: - plot.plot_path(X, path) -plot.plot_obstacles(X, Obstacles) -plot.plot_start(X, x_init) -plot.plot_goal(X, x_goal) -plot.draw(auto_open=True) diff --git a/examples/rrt_bid_h/rrt_star_bid_h_3d.py b/examples/rrt_bid_h/rrt_star_bid_h_3d.py deleted file mode 100644 index 35f1b81..0000000 --- a/examples/rrt_bid_h/rrt_star_bid_h_3d.py +++ /dev/null @@ -1,38 +0,0 @@ -# This file is subject to the terms and conditions defined in -# file 'LICENSE', which is part of this source code package. -import numpy as np - -from rrt_algorithms.rrt.rrt_star_bid_h import RRTStarBidirectionalHeuristic -from rrt_algorithms.search_space.search_space import SearchSpace -from rrt_algorithms.utilities.plotting import Plot - -X_dimensions = np.array([(0, 100), (0, 100), (0, 100)]) # dimensions of Search Space -# obstacles -Obstacles = np.array( - [(20, 20, 20, 40, 40, 40), (20, 20, 60, 40, 40, 80), (20, 60, 20, 40, 80, 40), (60, 60, 20, 80, 80, 40), - (60, 20, 20, 80, 40, 40), (60, 20, 60, 80, 40, 80), (20, 60, 60, 40, 80, 80), (60, 60, 60, 80, 80, 80)]) -x_init = (0, 0, 0) # starting location -x_goal = (100, 100, 100) # goal location - -q = 8 # length of tree edges -r = 1 # length of smallest edge to check for intersection with obstacles -max_samples = 1024 # max number of samples to take before timing out -rewire_count = 32 # optional, number of nearby branches to rewire -prc = 0.01 # probability of checking for a connection to goal - -# create Search Space -X = SearchSpace(X_dimensions, Obstacles) - -# create rrt_search -rrt = RRTStarBidirectionalHeuristic(X, q, x_init, x_goal, max_samples, r, prc, rewire_count) -path = rrt.rrt_star_bid_h() - -# plot -plot = Plot("rrt_star_bid_h_3d") -plot.plot_tree(X, rrt.trees) -if path is not None: - plot.plot_path(X, path) -plot.plot_obstacles(X, Obstacles) -plot.plot_start(X, x_init) -plot.plot_goal(X, x_goal) -plot.draw(auto_open=True) diff --git a/examples/rrt_bid_h/rrt_star_bid_h_3d_with_random_obstacles.py b/examples/rrt_bid_h/rrt_star_bid_h_3d_with_random_obstacles.py deleted file mode 100644 index 794aee6..0000000 --- a/examples/rrt_bid_h/rrt_star_bid_h_3d_with_random_obstacles.py +++ /dev/null @@ -1,38 +0,0 @@ -# This file is subject to the terms and conditions defined in -# file 'LICENSE', which is part of this source code package. -import numpy as np - -from rrt_algorithms.rrt.rrt_star_bid_h import RRTStarBidirectionalHeuristic -from rrt_algorithms.search_space.search_space import SearchSpace -from rrt_algorithms.utilities.obstacle_generation import generate_random_obstacles -from rrt_algorithms.utilities.plotting import Plot - -X_dimensions = np.array([(0, 100), (0, 100), (0, 100)]) # dimensions of Search Space -# obstacles -x_init = (0, 0, 0) # starting location -x_goal = (100, 100, 100) # goal location - -q = 8 # length of tree edges -r = 1 # length of smallest edge to check for intersection with obstacles -max_samples = 1024 # max number of samples to take before timing out -rewire_count = 32 # optional, number of nearby branches to rewire -prc = 0.01 # probability of checking for a connection to goal - -# create Search Space -X = SearchSpace(X_dimensions) -n = 50 -Obstacles = generate_random_obstacles(X, x_init, x_goal, n) - -# create rrt_search -rrt = RRTStarBidirectionalHeuristic(X, q, x_init, x_goal, max_samples, r, prc, rewire_count) -path = rrt.rrt_star_bid_h() - -# plot -plot = Plot("rrt_star_bid_h_3d_with_random_obstacles") -plot.plot_tree(X, rrt.trees) -if path is not None: - plot.plot_path(X, path) -plot.plot_obstacles(X, Obstacles) -plot.plot_start(X, x_init) -plot.plot_goal(X, x_goal) -plot.draw(auto_open=True) diff --git a/examples/rrt_connect/rrt_connect_2d.py b/examples/rrt_connect/rrt_connect_2d.py deleted file mode 100644 index 0c6f37d..0000000 --- a/examples/rrt_connect/rrt_connect_2d.py +++ /dev/null @@ -1,35 +0,0 @@ -# This file is subject to the terms and conditions defined in -# file 'LICENSE', which is part of this source code package. -import numpy as np - -from rrt_algorithms.rrt.rrt_connect import RRTConnect -from rrt_algorithms.search_space.search_space import SearchSpace -from rrt_algorithms.utilities.plotting import Plot - -X_dimensions = np.array([(0, 100), (0, 100)]) # dimensions of Search Space -# obstacles -Obstacles = np.array([(20, 20, 40, 40), (20, 60, 40, 80), - (60, 20, 80, 40), (60, 60, 80, 80)]) -x_init = (0, 0) # starting location -x_goal = (100, 100) # goal location - -q = 2 # length of tree edges -r = 0.5 # length of smallest edge to check for intersection with obstacles -max_samples = 1024 # max number of samples to take before timing out -prc = 0.1 # probability of checking for a connection to goal - -# create search space -X = SearchSpace(X_dimensions, Obstacles) - -# create rrt_search -rrt_connect = RRTConnect(X, q, x_init, x_goal, max_samples, r, prc) -path = rrt_connect.rrt_connect() -# plot -plot = Plot("rrt_connect2d") -plot.plot_tree(X, rrt_connect.trees) -if path is not None: - plot.plot_path(X, path) -plot.plot_obstacles(X, Obstacles) -plot.plot_start(X, x_init) -plot.plot_goal(X, x_goal) -plot.draw(auto_open=True) diff --git a/examples/rrt_connect/rrt_connect_2d_with_random_obstacles.py b/examples/rrt_connect/rrt_connect_2d_with_random_obstacles.py deleted file mode 100644 index 5ed0a09..0000000 --- a/examples/rrt_connect/rrt_connect_2d_with_random_obstacles.py +++ /dev/null @@ -1,35 +0,0 @@ -# This file is subject to the terms and conditions defined in -# file 'LICENSE', which is part of this source code package. -import numpy as np - -from rrt_algorithms.rrt.rrt_connect import RRTConnect -from rrt_algorithms.search_space.search_space import SearchSpace -from rrt_algorithms.utilities.obstacle_generation import generate_random_obstacles -from rrt_algorithms.utilities.plotting import Plot - -X_dimensions = np.array([(0, 100), (0, 100)]) # dimensions of Search Space -x_init = (0, 0) # starting location -x_goal = (100, 100) # goal location - -q = 2 # length of tree edges -r = 0.5 # length of smallest edge to check for intersection with obstacles -max_samples = 2048 # max number of samples to take before timing out -prc = 0.1 # probability of checking for a connection to goal - -# create search space -X = SearchSpace(X_dimensions) -n = 50 -Obstacles = generate_random_obstacles(X, x_init, x_goal, n) - -# create rrt_search -rrt_connect = RRTConnect(X, q, x_init, x_goal, max_samples, r, prc) -path = rrt_connect.rrt_connect() -# plot -plot = Plot("rrt_connect_2d_with_random_obstacles") -plot.plot_tree(X, rrt_connect.trees) -if path is not None: - plot.plot_path(X, path) -plot.plot_obstacles(X, Obstacles) -plot.plot_start(X, x_init) -plot.plot_goal(X, x_goal) -plot.draw(auto_open=True) diff --git a/examples/rrt_connect/rrt_connect_3d.py b/examples/rrt_connect/rrt_connect_3d.py deleted file mode 100644 index feaf20c..0000000 --- a/examples/rrt_connect/rrt_connect_3d.py +++ /dev/null @@ -1,36 +0,0 @@ -# This file is subject to the terms and conditions defined in -# file 'LICENSE', which is part of this source code package. -import numpy as np - -from rrt_algorithms.rrt.rrt_connect import RRTConnect -from rrt_algorithms.search_space.search_space import SearchSpace -from rrt_algorithms.utilities.plotting import Plot - -X_dimensions = np.array([(0, 100), (0, 100), (0, 100)]) # dimensions of Search Space -# obstacles -Obstacles = np.array( - [(20, 20, 20, 40, 40, 40), (20, 20, 60, 40, 40, 80), (20, 60, 20, 40, 80, 40), (60, 60, 20, 80, 80, 40), - (60, 20, 20, 80, 40, 40), (60, 20, 60, 80, 40, 80), (20, 60, 60, 40, 80, 80), (60, 60, 60, 80, 80, 80)]) -x_init = (0, 0, 0) # starting location -x_goal = (100, 100, 100) # goal location - -q = 2 # length of tree edges -r = 0.5 # length of smallest edge to check for intersection with obstacles -max_samples = 1024 # max number of samples to take before timing out -prc = 0.1 # probability of checking for a connection to goal - -# create search space -X = SearchSpace(X_dimensions, Obstacles) - -# create rrt_search -rrt_connect = RRTConnect(X, q, x_init, x_goal, max_samples, r, prc) -path = rrt_connect.rrt_connect() -# plot -plot = Plot("rrt_connect_3d") -plot.plot_tree(X, rrt_connect.trees) -if path is not None: - plot.plot_path(X, path) -plot.plot_obstacles(X, Obstacles) -plot.plot_start(X, x_init) -plot.plot_goal(X, x_goal) -plot.draw(auto_open=True) diff --git a/examples/rrt_connect/rrt_connect_3d_with_random_obstacles.py b/examples/rrt_connect/rrt_connect_3d_with_random_obstacles.py deleted file mode 100644 index ba992ba..0000000 --- a/examples/rrt_connect/rrt_connect_3d_with_random_obstacles.py +++ /dev/null @@ -1,36 +0,0 @@ -# This file is subject to the terms and conditions defined in -# file 'LICENSE', which is part of this source code package. -import numpy as np - -from rrt_algorithms.rrt.rrt_connect import RRTConnect -from rrt_algorithms.search_space.search_space import SearchSpace -from rrt_algorithms.utilities.obstacle_generation import generate_random_obstacles -from rrt_algorithms.utilities.plotting import Plot - -X_dimensions = np.array([(0, 100), (0, 100), (0, 100)]) # dimensions of Search Space -# obstacles -x_init = (0, 0, 0) # starting location -x_goal = (100, 100, 100) # goal location - -q = 2 # length of tree edges -r = 0.5 # length of smallest edge to check for intersection with obstacles -max_samples = 1024 # max number of samples to take before timing out -prc = 0.1 # probability of checking for a connection to goal - -# create search space -X = SearchSpace(X_dimensions) -n = 50 -Obstacles = generate_random_obstacles(X, x_init, x_goal, n) - -# create rrt_search -rrt_connect = RRTConnect(X, q, x_init, x_goal, max_samples, r, prc) -path = rrt_connect.rrt_connect() -# plot -plot = Plot("rrt_connect_3d_with_random_obstacles") -plot.plot_tree(X, rrt_connect.trees) -if path is not None: - plot.plot_path(X, path) -plot.plot_obstacles(X, Obstacles) -plot.plot_start(X, x_init) -plot.plot_goal(X, x_goal) -plot.draw(auto_open=True) diff --git a/examples/rrt_star/rrt_star_2d.py b/examples/rrt_star/rrt_star_2d.py deleted file mode 100644 index 2fd9093..0000000 --- a/examples/rrt_star/rrt_star_2d.py +++ /dev/null @@ -1,37 +0,0 @@ -# This file is subject to the terms and conditions defined in -# file 'LICENSE', which is part of this source code package. -import numpy as np - -from rrt_algorithms.rrt.rrt_star import RRTStar -from rrt_algorithms.search_space.search_space import SearchSpace -from rrt_algorithms.utilities.plotting import Plot - -X_dimensions = np.array([(0, 100), (0, 100)]) # dimensions of Search Space -# obstacles -Obstacles = np.array([(20, 20, 40, 40), (20, 60, 40, 80), - (60, 20, 80, 40), (60, 60, 80, 80)]) -x_init = (0, 0) # starting location -x_goal = (100, 100) # goal location - -q = 8 # length of tree edges -r = 1 # length of smallest edge to check for intersection with obstacles -max_samples = 1024 # max number of samples to take before timing out -rewire_count = 32 # optional, number of nearby branches to rewire -prc = 0.1 # probability of checking for a connection to goal - -# create Search Space -X = SearchSpace(X_dimensions, Obstacles) - -# create rrt_search -rrt = RRTStar(X, q, x_init, x_goal, max_samples, r, prc, rewire_count) -path = rrt.rrt_star() - -# plot -plot = Plot("rrt_star_2d") -plot.plot_tree(X, rrt.trees) -if path is not None: - plot.plot_path(X, path) -plot.plot_obstacles(X, Obstacles) -plot.plot_start(X, x_init) -plot.plot_goal(X, x_goal) -plot.draw(auto_open=True) diff --git a/examples/rrt_star/rrt_star_2d_with_random_obstacles.py b/examples/rrt_star/rrt_star_2d_with_random_obstacles.py deleted file mode 100644 index 9c0cd4e..0000000 --- a/examples/rrt_star/rrt_star_2d_with_random_obstacles.py +++ /dev/null @@ -1,36 +0,0 @@ -# This file is subject to the terms and conditions defined in -# file 'LICENSE', which is part of this source code package. -import numpy as np - -from rrt_algorithms.rrt.rrt_star import RRTStar -from rrt_algorithms.search_space.search_space import SearchSpace -from rrt_algorithms.utilities.obstacle_generation import generate_random_obstacles -from rrt_algorithms.utilities.plotting import Plot - -X_dimensions = np.array([(0, 100), (0, 100)]) # dimensions of Search Space -x_init = (0, 0) # starting location -x_goal = (100, 100) # goal location - -q = 8 # length of tree edges -r = 1 # length of smallest edge to check for intersection with obstacles -max_samples = 1024 # max number of samples to take before timing out -rewire_count = 32 # optional, number of nearby branches to rewire -prc = 0.1 # probability of checking for a connection to goal - -# create Search Space -X = SearchSpace(X_dimensions) -n = 50 -Obstacles = generate_random_obstacles(X, x_init, x_goal, n) -# create rrt_search -rrt = RRTStar(X, q, x_init, x_goal, max_samples, r, prc, rewire_count) -path = rrt.rrt_star() - -# plot -plot = Plot("rrt_star_2d_with_random_obstacles") -plot.plot_tree(X, rrt.trees) -if path is not None: - plot.plot_path(X, path) -plot.plot_obstacles(X, Obstacles) -plot.plot_start(X, x_init) -plot.plot_goal(X, x_goal) -plot.draw(auto_open=True) diff --git a/examples/rrt_star/rrt_star_3d.py b/examples/rrt_star/rrt_star_3d.py deleted file mode 100644 index 4b6e6d6..0000000 --- a/examples/rrt_star/rrt_star_3d.py +++ /dev/null @@ -1,38 +0,0 @@ -# This file is subject to the terms and conditions defined in -# file 'LICENSE', which is part of this source code package. -import numpy as np - -from rrt_algorithms.rrt.rrt_star import RRTStar -from rrt_algorithms.search_space.search_space import SearchSpace -from rrt_algorithms.utilities.plotting import Plot - -X_dimensions = np.array([(0, 100), (0, 100), (0, 100)]) # dimensions of Search Space -# obstacles -Obstacles = np.array( - [(20, 20, 20, 40, 40, 40), (20, 20, 60, 40, 40, 80), (20, 60, 20, 40, 80, 40), (60, 60, 20, 80, 80, 40), - (60, 20, 20, 80, 40, 40), (60, 20, 60, 80, 40, 80), (20, 60, 60, 40, 80, 80), (60, 60, 60, 80, 80, 80)]) -x_init = (0, 0, 0) # starting location -x_goal = (100, 100, 100) # goal location - -q = 8 # length of tree edges -r = 1 # length of smallest edge to check for intersection with obstacles -max_samples = 1024 # max number of samples to take before timing out -rewire_count = 32 # optional, number of nearby branches to rewire -prc = 0.1 # probability of checking for a connection to goal - -# create Search Space -X = SearchSpace(X_dimensions, Obstacles) - -# create rrt_search -rrt = RRTStar(X, q, x_init, x_goal, max_samples, r, prc, rewire_count) -path = rrt.rrt_star() - -# plot -plot = Plot("rrt_star_3d") -plot.plot_tree(X, rrt.trees) -if path is not None: - plot.plot_path(X, path) -plot.plot_obstacles(X, Obstacles) -plot.plot_start(X, x_init) -plot.plot_goal(X, x_goal) -plot.draw(auto_open=True) diff --git a/examples/rrt_star/rrt_star_3d_with_random_obstacles.py b/examples/rrt_star/rrt_star_3d_with_random_obstacles.py deleted file mode 100644 index b1bf49b..0000000 --- a/examples/rrt_star/rrt_star_3d_with_random_obstacles.py +++ /dev/null @@ -1,37 +0,0 @@ -# This file is subject to the terms and conditions defined in -# file 'LICENSE', which is part of this source code package. -import numpy as np - -from rrt_algorithms.rrt.rrt_star import RRTStar -from rrt_algorithms.search_space.search_space import SearchSpace -from rrt_algorithms.utilities.obstacle_generation import generate_random_obstacles -from rrt_algorithms.utilities.plotting import Plot - -X_dimensions = np.array([(0, 100), (0, 100), (0, 100)]) # dimensions of Search Space -x_init = (0, 0, 0) # starting location -x_goal = (100, 100, 100) # goal location - -q = 8 # length of tree edges -r = 1 # length of smallest edge to check for intersection with obstacles -max_samples = 1024 # max number of samples to take before timing out -rewire_count = 32 # optional, number of nearby branches to rewire -prc = 0.1 # probability of checking for a connection to goal - -# create Search Space -X = SearchSpace(X_dimensions) -n = 50 -Obstacles = generate_random_obstacles(X, x_init, x_goal, n) -# create rrt_search -rrt = RRTStar(X, q, x_init, x_goal, max_samples, r, prc, rewire_count) -path = rrt.rrt_star() - -# plot -plot = Plot("rrt_star_3d_with_random_obstacles") -plot.plot_tree(X, rrt.trees) -if path is not None: - plot.plot_path(X, path) -plot.plot_obstacles(X, Obstacles) - -plot.plot_start(X, x_init) -plot.plot_goal(X, x_goal) -plot.draw(auto_open=True) diff --git a/output/1 b/output/1 new file mode 100644 index 0000000..53752db --- /dev/null +++ b/output/1 @@ -0,0 +1 @@ +output diff --git a/output/visualizations/12 b/output/visualizations/12 new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/output/visualizations/12 @@ -0,0 +1 @@ + diff --git a/output/visualizations/5th_iteration.png b/output/visualizations/5th_iteration.png new file mode 100644 index 0000000..1534a06 Binary files /dev/null and b/output/visualizations/5th_iteration.png differ diff --git a/output/visualizations/6th_iteration.png b/output/visualizations/6th_iteration.png new file mode 100644 index 0000000..2835282 Binary files /dev/null and b/output/visualizations/6th_iteration.png differ diff --git a/output/visualizations/6th_iteration_.png b/output/visualizations/6th_iteration_.png new file mode 100644 index 0000000..4d99828 Binary files /dev/null and b/output/visualizations/6th_iteration_.png differ diff --git a/output/visualizations/7TH_Iteration.png b/output/visualizations/7TH_Iteration.png new file mode 100644 index 0000000..301ad9b Binary files /dev/null and b/output/visualizations/7TH_Iteration.png differ diff --git a/output/visualizations/8th_iteration.png b/output/visualizations/8th_iteration.png new file mode 100644 index 0000000..4ade0cb Binary files /dev/null and b/output/visualizations/8th_iteration.png differ diff --git a/output/visualizations/rrt_3d.html b/output/visualizations/rrt_3d.html new file mode 100644 index 0000000..fbefbd4 --- /dev/null +++ b/output/visualizations/rrt_3d.html @@ -0,0 +1,14 @@ + +
+ +