Nav2 Navigation Stack - humble  humble
ROS 2 Navigation Stack
process_data.py
1 #! /usr/bin/env python3
2 # Copyright 2022 Joshua Wallace
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 
16 import numpy as np
17 import math
18 
19 import os
20 from ament_index_python.packages import get_package_share_directory
21 import pickle
22 
23 import seaborn as sns
24 import matplotlib.pylab as plt
25 from tabulate import tabulate
26 
27 
28 def getPaths(results):
29  paths = []
30  for result in results:
31  for path in result:
32  paths.append(path.path)
33  return paths
34 
35 
36 def getTimes(results):
37  times = []
38  for result in results:
39  for time in result:
40  times.append(time.planning_time.nanosec/1e09 + time.planning_time.sec)
41  return times
42 
43 
44 def getMapCoordsFromPaths(paths, resolution):
45  coords = []
46  for path in paths:
47  x = []
48  y = []
49  for pose in path.poses:
50  x.append(pose.pose.position.x/resolution)
51  y.append(pose.pose.position.y/resolution)
52  coords.append(x)
53  coords.append(y)
54  return coords
55 
56 
57 def getPathLength(path):
58  path_length = 0
59  x_prev = path.poses[0].pose.position.x
60  y_prev = path.poses[0].pose.position.y
61  for i in range(1, len(path.poses)):
62  x_curr = path.poses[i].pose.position.x
63  y_curr = path.poses[i].pose.position.y
64  path_length = path_length + math.sqrt((x_curr-x_prev)**2 + (y_curr-y_prev)**2)
65  x_prev = x_curr
66  y_prev = y_curr
67  return path_length
68 
69 
70 def plotResults(costmap, paths):
71  coords = getMapCoordsFromPaths(paths, costmap.metadata.resolution)
72  data = np.asarray(costmap.data)
73  data.resize(costmap.metadata.size_y, costmap.metadata.size_x)
74  data = np.where(data <= 253, 0, data)
75 
76  plt.figure(3)
77  ax = sns.heatmap(data, cmap='Greys', cbar=False)
78  for i in range(0, len(coords), 2):
79  ax.plot(coords[i], coords[i+1], linewidth=0.7)
80  plt.axis('off')
81  ax.set_aspect('equal', 'box')
82  plt.show()
83 
84 
85 def averagePathCost(paths, costmap, num_of_planners):
86  coords = getMapCoordsFromPaths(paths, costmap.metadata.resolution)
87  data = np.asarray(costmap.data)
88  data.resize(costmap.metadata.size_y, costmap.metadata.size_x)
89 
90  average_path_costs = []
91  for i in range(num_of_planners):
92  average_path_costs.append([])
93 
94  k = 0
95  for i in range(0, len(coords), 2):
96  costs = []
97  for j in range(len(coords[i])):
98  costs.append(data[math.floor(coords[i+1][j])][math.floor(coords[i][j])])
99  average_path_costs[k % num_of_planners].append(sum(costs)/len(costs))
100  k += 1
101 
102  return average_path_costs
103 
104 
105 def maxPathCost(paths, costmap, num_of_planners):
106  coords = getMapCoordsFromPaths(paths, costmap.metadata.resolution)
107  data = np.asarray(costmap.data)
108  data.resize(costmap.metadata.size_y, costmap.metadata.size_x)
109 
110  max_path_costs = []
111  for i in range(num_of_planners):
112  max_path_costs.append([])
113 
114  k = 0
115  for i in range(0, len(coords), 2):
116  max_cost = 0
117  for j in range(len(coords[i])):
118  cost = data[math.floor(coords[i+1][j])][math.floor(coords[i][j])]
119  if max_cost < cost:
120  max_cost = cost
121  max_path_costs[k % num_of_planners].append(max_cost)
122  k += 1
123 
124  return max_path_costs
125 
126 
127 def main():
128 
129  print("Read data")
130  with open(os.getcwd() + '/results.pickle', 'rb') as f:
131  results = pickle.load(f)
132 
133  with open(os.getcwd() + '/planners.pickle', 'rb') as f:
134  planners = pickle.load(f)
135 
136  with open(os.getcwd() + '/costmap.pickle', 'rb') as f:
137  costmap = pickle.load(f)
138 
139  paths = getPaths(results)
140  path_lengths = []
141 
142  for path in paths:
143  path_lengths.append(getPathLength(path))
144  path_lengths = np.asarray(path_lengths)
145  total_paths = len(paths)
146 
147  path_lengths.resize((int(total_paths/len(planners)), len(planners)))
148  path_lengths = path_lengths.transpose()
149 
150  times = getTimes(results)
151  times = np.asarray(times)
152  times.resize((int(total_paths/len(planners)), len(planners)))
153  times = np.transpose(times)
154 
155  # Costs
156  average_path_costs = np.asarray(averagePathCost(paths, costmap, len(planners)))
157  max_path_costs = np.asarray(maxPathCost(paths, costmap, len(planners)))
158 
159  # Generate table
160  planner_table = [['Planner', 'Average path length (m)', 'Average Time (s)',
161  'Average cost', 'Max cost']]
162 
163  for i in range(0, len(planners)):
164  planner_table.append([planners[i], np.average(path_lengths[i]), np.average(times[i]),
165  np.average(average_path_costs[i]), np.average(max_path_costs[i])])
166 
167  # Visualize results
168  print(tabulate(planner_table))
169  plotResults(costmap, paths)
170 
171 
172 if __name__ == '__main__':
173  main()