Skip to content

Commit 8c3b4b0

Browse files
Merge pull request #273 from JdeRobot/issue-272
Edge case for lap percentage
2 parents f00e132 + 5b07708 commit 8c3b4b0

File tree

3 files changed

+48
-29
lines changed

3 files changed

+48
-29
lines changed

behavior_metrics/pilot.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,6 @@ def initialize_robot(self):
109109

110110
def stop_interfaces(self):
111111
"""Function that kill the current interfaces of the robot. For reloading purposes."""
112-
113112
if self.sensors:
114113
self.sensors.kill()
115114
if self.actuators:
@@ -228,7 +227,6 @@ def finish_line(self):
228227
dist = (self.start_pose - current_point) ** 2
229228
dist = np.sum(dist, axis=0)
230229
dist = np.sqrt(dist)
231-
# print(dist)
232230
if dist < self.max_distance:
233231
return True
234232
return False

behavior_metrics/utils/controller.py

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,6 @@ def get_data(self, frame_id):
9191
try:
9292
with self.__data_loc:
9393
data = self.data.get(frame_id, None)
94-
# self.data[frame_id] = None
9594
except Exception:
9695
pass
9796

@@ -184,10 +183,11 @@ def record_stats(self, perfect_lap_filename, stats_record_dir_path, world_counte
184183
current_brain_head, current_brain_tail = os.path.split(self.pilot.configuration.brain_path[brain_counter])
185184
else:
186185
current_brain_head, current_brain_tail = os.path.split(self.pilot.configuration.brain_path)
187-
self.metrics = {}
188-
self.metrics['world'] = current_world_tail
189-
self.metrics['brain_path'] = current_brain_tail
190-
self.metrics['robot_type'] = self.pilot.configuration.robot_type
186+
self.metrics = {
187+
'world': current_world_tail,
188+
'brain_path': current_brain_tail,
189+
'robot_type': self.pilot.configuration.robot_type
190+
}
191191
if hasattr(self.pilot.configuration, 'experiment_model'):
192192
if brain_counter is not None:
193193
self.metrics['experiment_model'] = self.pilot.configuration.experiment_model[brain_counter]
@@ -224,16 +224,14 @@ def stop_record_stats(self, pitch_error=False):
224224
while os.path.isfile(self.stats_filename + '.active'):
225225
pass
226226

227-
checkpoints = []
228227
metrics_str = json.dumps(self.metrics)
229228
with rosbag.Bag(self.stats_filename, 'a') as bag:
230229
metadata_msg = String(data=metrics_str)
231230
bag.write('/metadata', metadata_msg, rospy.Time(bag.get_end_time()))
232231
bag.close()
233232
perfect_lap_checkpoints, circuit_diameter = metrics.read_perfect_lap_rosbag(self.perfect_lap_filename)
234233
if not pitch_error:
235-
self.lap_statistics = metrics.lap_percentage_completed(self.stats_filename, perfect_lap_checkpoints,
236-
circuit_diameter)
234+
self.lap_statistics = metrics.get_statistics(self.stats_filename, perfect_lap_checkpoints, circuit_diameter)
237235
else:
238236
self.lap_statistics = {'percentage_completed': 0, 'average_speed': 0, 'lap_seconds': 0,
239237
'circuit_diameter': 0, 'position_deviation_mae': 0,

behavior_metrics/utils/metrics.py

Lines changed: 42 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ def read_perfect_lap_rosbag(ground_truth_lap_file):
9191
return perfect_lap_checkpoints, circuit_diameter
9292

9393

94-
def lap_percentage_completed(stats_filename, perfect_lap_checkpoints, circuit_diameter):
94+
def get_statistics(stats_filename, perfect_lap_checkpoints, circuit_diameter):
9595
lap_statistics = {}
9696
bag_reader = bagreader(stats_filename)
9797
csv_files = []
@@ -104,20 +104,17 @@ def lap_percentage_completed(stats_filename, perfect_lap_checkpoints, circuit_di
104104
checkpoints = []
105105
for index, row in dataframe_pose.iterrows():
106106
checkpoints.append(row)
107+
107108
data_file = stats_filename.split('.bag')[0] + '/clock.csv'
108109
dataframe_pose = pd.read_csv(data_file)
109110
clock_points = []
110111
for index, row in dataframe_pose.iterrows():
111112
clock_points.append(row)
112-
113-
end_point = checkpoints[len(checkpoints) - 1]
114113
start_clock = clock_points[0]
115-
lap_statistics['completed_distance'] = circuit_distance_completed(checkpoints, end_point)
116114
lap_point = 0
117115
start_point = checkpoints[0]
118116
previous_lap_point = 0
119117
laps = 0
120-
ckp_iter = 0
121118
for ckp_iter, point in enumerate(checkpoints):
122119
if ckp_iter != 0 and point['header.stamp.secs'] - 10 > start_point['header.stamp.secs'] \
123120
and is_finish_line(point, start_point):
@@ -128,8 +125,28 @@ def lap_percentage_completed(stats_filename, perfect_lap_checkpoints, circuit_di
128125
previous_lap_point = ckp_iter
129126
seconds_start = start_clock['clock.secs']
130127
seconds_end = clock_points[len(clock_points) - 1]['clock.secs']
128+
129+
lap_statistics = get_distance_completed(lap_statistics, checkpoints)
130+
lap_statistics = get_average_speed(lap_statistics, seconds_start, seconds_end)
131+
lap_statistics = get_percentage_completed(lap_statistics, checkpoints, perfect_lap_checkpoints, seconds_start, seconds_end, laps)
132+
lap_statistics = get_lap_completed_stats(lap_statistics, circuit_diameter, previous_lap_point, lap_point)
133+
134+
shutil.rmtree(stats_filename.split('.bag')[0])
135+
return lap_statistics
136+
137+
138+
def get_distance_completed(lap_statistics, checkpoints):
139+
end_point = checkpoints[len(checkpoints) - 1]
140+
lap_statistics['completed_distance'] = circuit_distance_completed(checkpoints, end_point)
141+
return lap_statistics
142+
143+
144+
def get_average_speed(lap_statistics, seconds_start, seconds_end):
131145
lap_statistics['average_speed'] = lap_statistics['completed_distance'] / (seconds_end - seconds_start)
146+
return lap_statistics
132147

148+
149+
def get_percentage_completed(lap_statistics, checkpoints, perfect_lap_checkpoints, seconds_start, seconds_end, laps):
133150
# Find last and first checkpoints for retrieving percentage completed
134151
first_checkpoint = checkpoints[0]
135152
first_checkpoint = np.array([first_checkpoint['pose.pose.position.x'], first_checkpoint['pose.pose.position.y']])
@@ -155,26 +172,15 @@ def lap_percentage_completed(stats_filename, perfect_lap_checkpoints, circuit_di
155172
if dist < min_distance_last:
156173
min_distance_last = dist
157174
last_perfect_checkpoint_position = i
158-
159175
if first_perfect_checkpoint_position > last_perfect_checkpoint_position and lap_statistics['completed_distance'] > MIN_COMPLETED_DISTANCE_EXPERIMENT and seconds_end - seconds_start > MIN_EXPERIMENT_TIME:
160176
lap_statistics['percentage_completed'] = (((len(perfect_lap_checkpoints) - first_perfect_checkpoint_position + last_perfect_checkpoint_position) / len(perfect_lap_checkpoints)) * 100) + laps * 100
161177
else:
162178
if seconds_end - seconds_start > MIN_EXPERIMENT_TIME:
163-
lap_statistics['percentage_completed'] = (((last_perfect_checkpoint_position - first_perfect_checkpoint_position) / len(perfect_lap_checkpoints)) * 100) + laps * 100
179+
lap_statistics['percentage_completed'] = (((last_perfect_checkpoint_position - first_perfect_checkpoint_position) / len(
180+
perfect_lap_checkpoints)) * 100) + laps * 100
164181
else:
165182
lap_statistics['percentage_completed'] = (((last_perfect_checkpoint_position - first_perfect_checkpoint_position) / len(perfect_lap_checkpoints)) * 100)
166183
lap_statistics = get_robot_position_deviation_score(perfect_lap_checkpoints, checkpoints, lap_statistics)
167-
168-
# If lap is completed, add more statistic information
169-
if type(lap_point) is not int and lap_statistics['percentage_completed'] > LAP_COMPLETED_PERCENTAGE:
170-
seconds_start = start_clock['clock.secs']
171-
seconds_end = clock_points[int(len(clock_points) * (ckp_iter / len(checkpoints)))]['clock.secs']
172-
lap_statistics['lap_seconds'] = seconds_end - seconds_start
173-
lap_statistics['circuit_diameter'] = circuit_diameter
174-
else:
175-
logger.info('Lap not completed')
176-
177-
shutil.rmtree(stats_filename.split('.bag')[0])
178184
return lap_statistics
179185

180186

@@ -258,4 +264,21 @@ def get_robot_position_deviation_score(perfect_lap_checkpoints, checkpoints, lap
258264
lap_statistics['position_deviation_mae'] = sum(min_dists) / len(min_dists)
259265
lap_statistics['position_deviation_total_err'] = sum(min_dists)
260266

261-
return lap_statistics
267+
return lap_statistics
268+
269+
270+
def get_lap_completed_stats(lap_statistics, circuit_diameter, previous_lap_point, lap_point):
271+
# If lap is completed, add more statistic information
272+
if type(lap_point) is not int and lap_statistics['percentage_completed'] > LAP_COMPLETED_PERCENTAGE:
273+
if abs(((lap_statistics['completed_distance'] / circuit_diameter) * 100) - lap_statistics['percentage_completed']) > 5:
274+
logger.info('Error in experiment! The actual lap percentage and the approximated one are different.')
275+
lap_statistics['percentage_completed'] = (lap_statistics['completed_distance'] / circuit_diameter) * 100
276+
else:
277+
seconds_start = start_clock['clock.secs']
278+
seconds_end = clock_points[int(len(clock_points) * (previous_lap_point / len(checkpoints)))]['clock.secs']
279+
lap_statistics['lap_seconds'] = seconds_end - seconds_start
280+
lap_statistics['circuit_diameter'] = circuit_diameter
281+
else:
282+
logger.info('Lap not completed')
283+
284+
return lap_statistics

0 commit comments

Comments
 (0)