-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathik_benchmarking_data_visualizer.py
executable file
·151 lines (125 loc) · 5.14 KB
/
ik_benchmarking_data_visualizer.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os
import glob
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import rclpy
from rclpy.node import Node
class DataVisualizerNode(Node):
def __init__(self):
super().__init__("data_visualizer_node")
# Allow loading the IK benchmarking data from non-current directories
# using a 'data_directory' parameter that can be passed when running the script
# the 'data_directory' parameter defaults to current directory, and if no data exist, a warning is printed
self.declare_parameter("data_directory", os.getcwd())
self.data_directory = (
self.get_parameter("data_directory").get_parameter_value().string_value
)
print(f"{'=' * 60}")
print(
f"\nThe benchmarking CSV files will be loaded from the directory:\n\n{self.data_directory}"
)
self.run_visualization()
def run_visualization(self):
data_list = self.read_ik_benchmarking_files()
# Check if the data files really exist
if not data_list:
self.get_logger().warn(
f"No IK benchmarking CSV data files found in the directory: {self.data_directory}"
)
print(f"{'=' * 60}")
rclpy.shutdown()
return
self.plot_data(data_list)
def read_ik_benchmarking_files(self):
file_pattern = os.path.join(self.data_directory, "*ik_benchmarking_data.csv")
files = glob.glob(file_pattern)
data_list = []
for file in files:
data = pd.read_csv(file)
# Convert solve_time and errors to numeric
for col in ["solve_time", "position_error", "orientation_error"]:
data[col] = pd.to_numeric(data[col], errors="coerce")
# Process the filename and remove the common suffix
file_label = os.path.basename(file).replace("_ik_benchmarking_data.csv", "")
data_list.append((file_label, data))
return data_list
def plot_data(self, data_list):
print(f"\nBenchmarking result plots will be saved in the same directory.\n")
print(f"{'=' * 60}")
# Box plot for solve times of successful trials
plt.figure(figsize=(15, 10))
all_data = []
labels = []
for file, data in data_list:
success_data = data[data["found_ik"]]
all_data.extend(success_data.dropna(subset=["solve_time"])["solve_time"])
labels.extend([file] * len(success_data))
df_for_boxplot = pd.DataFrame({"Solve Times": all_data, "Dataset": labels})
# Box plot for solve times
sns.boxplot(
x="Dataset",
y="Solve Times",
data=df_for_boxplot,
showfliers=False,
boxprops={"edgecolor": "black"},
palette="Blues",
)
plt.title("Solve Times for Successful Trials")
plt.ylabel("Microseconds")
plt.xlabel("IK Solvers")
plt.savefig(os.path.join(self.data_directory, "solve_times.png"))
# Bar chart for success rates
success_rates = [
(f'{file}\n{100 * data["found_ik"].mean():.2f}%', data["found_ik"].mean())
for file, data in data_list
]
labels, rates = zip(*success_rates)
df_for_barplot = pd.DataFrame({"Success Rates": rates, "Dataset": labels})
plt.figure(figsize=(15, 10))
sns.barplot(
x="Dataset",
y="Success Rates",
data=df_for_barplot,
edgecolor="black",
palette="Blues",
)
plt.ylim(0, 1)
plt.title("Success Rate for Each Dataset")
plt.ylabel("Rate")
plt.xlabel("IK Solvers")
plt.savefig(os.path.join(self.data_directory, "success_rates.png"))
# Box plot for position_error, and orientation_error
error_types = [("position_error", "Meters"), ("orientation_error", "Radians")]
for error_type, unit in error_types:
plt.figure(figsize=(15, 10))
all_error_data = []
error_labels = []
for file, data in data_list:
success_data = data[data["found_ik"]]
all_error_data.extend(
success_data.dropna(subset=[error_type])[error_type]
)
error_labels.extend([file] * len(success_data))
df_error_for_plot = pd.DataFrame(
{error_type: all_error_data, "Dataset": error_labels}
)
sns.boxplot(
x="Dataset",
y=error_type,
data=df_error_for_plot,
showfliers=False,
boxprops={"edgecolor": "black"},
palette="Blues",
)
plt.title(f'{error_type.replace("_", " ").title()} for Successful Trials')
plt.ylabel(f'{error_type.replace("_", " ").title()} ({unit})')
plt.xlabel("IK Solvers")
plt.savefig(os.path.join(self.data_directory, f"{error_type}.png"))
if __name__ == "__main__":
rclpy.init(args=None)
node = DataVisualizerNode()
if rclpy.ok():
rclpy.shutdown()