diff --git a/dataset_gen/src/grader/grader.py b/dataset_gen/src/grader/grader.py new file mode 100644 index 0000000..715d250 --- /dev/null +++ b/dataset_gen/src/grader/grader.py @@ -0,0 +1,131 @@ +from random import random + +from grader_config import dist_grade, metric, pos_coeff, photo_coeff +from task_config import time_limit, x_range, y_range, z_range, barriers +from task_solution import positions, photos as made_photos, used_time + + +class Point: # stub + def __init__(self): + self.x = random() + self.y = random() + self.z = random() + + +class SolutionReader: # stub for reading from solution log file + def __init__(self, drone, task): + self.time = used_time + self.photos = made_photos + self.positions = positions + + +class Grader: + def __init__(self, drones, task_id, grade_criteria): + self.drones = drones + self.task_id = task_id + self.grade_criteria = grade_criteria + self.metric = metric + self.pos_coeff = pos_coeff + self.photo_coeff = photo_coeff + + def __get_distance(self, p1: Point, p2: Point): + x = p1.x - p2.x + y = p1.y - p2.y + z = p1.z - p2.z + if self.metric == "chessboard": + return max(abs(x), abs(y), abs(z)) + elif self.metric == "taxicab": + return abs(x) + abs(y) + abs(z) + elif self.metric != "plane": + print("Unknown metric, proposed euclidean") # raise? + return (x**2 + y**2 + z**2)**0.5 + + def __get_pos(self, drone): + return Point() # stub + + def __get_expected_pos(self, drone): + return Point() # stub + + def __get_photos_count(self, drone): + return int(random()*5) # stub + + def __get_expected_photos_count(self, drone): + return 5 # stub + + def __grade_position(self): + total_grade = 0 + for drone in self.drones: + pos = self.__get_pos(drone) + expected_pos = self.__get_expected_pos(drone) + dist = self.__get_distance(pos, expected_pos) + keys = list(filter(lambda key: dist <= key, dist_grade.keys())) + key = min(keys) if keys else None + grade = dist_grade[key] if key is not None else 0 + total_grade += grade + return total_grade/len(self.drones) # return avg + + def __grade_photo(self): + total_grade = 0 + for drone in self.drones: + count_photos = self.__get_photos_count(drone) + expected_photos = self.__get_expected_photos_count(drone) + grade = count_photos/expected_photos + total_grade += grade + return total_grade/len(self.drones) # return avg + + def grade(self): + used_pos_coeff = self.pos_coeff \ + if "position" in self.grade_criteria else 0 + used_photo_coeff = self.photo_coeff \ + if "photo" in self.grade_criteria else 0 + return (used_pos_coeff*self.__grade_position() + + used_photo_coeff*self.__grade_photo()) \ + / (used_pos_coeff + used_photo_coeff) + + def check_solution(self, drone, task): + solution = SolutionReader(drone, task) + if not self.__check_time(solution): + return False + if not self.__check_borders(solution): + return False + if not self.__check_collision(solution): + return False + return True + + def __check_borders(self, solution): + positions = solution.positions + x = (min([i[0] for i in positions]), max([i[0] for i in positions])) + if x[0] < x_range[0] or x[1] > x_range[1]: + return False + y = (min([i[1] for i in positions]), max([i[1] for i in positions])) + if y[0] < y_range[0] or y[1] > y_range[1]: + return False + z = (min([i[2] for i in positions]), max([i[2] for i in positions])) + if z[0] < z_range[0] or z[1] > z_range[1]: + return False + return True + + def __check_collision(self, solution): + for position in solution.positions: + for barrier in barriers: + check = [] + for ind in range(3): + check.append(barrier["borders"][ind][0] - 0.5 < position[ind] < + barrier["borders"][ind][1] + 0.5) # drone size? + if not all(check): + continue + equation = barrier["equation"] + if abs(equation[0]*position[0] + + equation[1]*position[1] + + equation[2]*position[2] - equation[3]) < 0.5: + return False + return True + + def __check_time(self, solution): + return solution.time <= time_limit + + +for _ in range(3): + grader = Grader(['1', '2', '3'], 1, ["photo", "position"]) + print(grader.grade()) + diff --git a/dataset_gen/src/grader/grader_config.py b/dataset_gen/src/grader/grader_config.py new file mode 100644 index 0000000..0a8d15b --- /dev/null +++ b/dataset_gen/src/grader/grader_config.py @@ -0,0 +1,7 @@ +dist_grade = {1: 1, + 5: 0.9, + 10: 0.7, + 20: 0.4} +metric = "plane" # options: plane, chessboard, taxicab +pos_coeff = 1 +photo_coeff = 1 diff --git a/dataset_gen/src/grader/task_config.py b/dataset_gen/src/grader/task_config.py new file mode 100644 index 0000000..f941a4d --- /dev/null +++ b/dataset_gen/src/grader/task_config.py @@ -0,0 +1,13 @@ +time_limit = 1000 + +x_range = (-100, 100) +y_range = (-50, 50) +z_range = (-10, 10) + +# proposed format for barriers +barriers = [ + {"equation": (1, 0, 0, 5), # Ax + By + Cz = D + "borders": ((5, 5), (-12, 12), (15, 20))} +] + +photos = [((0, 0, 0), (30, 60, 90))] diff --git a/dataset_gen/src/grader/task_solution.py b/dataset_gen/src/grader/task_solution.py new file mode 100644 index 0000000..1581b92 --- /dev/null +++ b/dataset_gen/src/grader/task_solution.py @@ -0,0 +1,5 @@ +positions = [(0, 0, 0), (1, 1, 1), (3, 1, 1), (5, 0, 0), (30, 0, 0)] + +photos = [((0, 0, 0), (30, 30, 30))] + +used_time = 980.7