def max_score(self): xc_score = 0 xc_distance = 0 xc_type = None xc_points = [] for v1 in self._groups[0].vertices: for v2 in self._groups[1].vertices: for v3 in self._groups[2].vertices: legs = [ distance(v1, v2), distance(v2, v3), distance(v3, v1) ] dist = sum(legs) if self.is_closed(tol=0.05 * dist): if min(legs) / dist > 0.28: # TODO check coefficient ? current_score = 0.0014 * dist current_type = 'FAI triangle' else: current_score = 0.0012 * dist current_type = 'flat triangle' else: current_score = 0.001 * dist current_type = '3 points' if current_score > xc_score: xc_score = current_score xc_type = current_type xc_distance = dist xc_points = [v1, v2, v3] return xc_points, xc_distance, xc_type, xc_score
def __init__(self, lat, lon, p1=None, p2=None, radius=None): self.lat = lat self.lon = lon if radius is not None: self.radius = radius self.start_angle = -180 self.end_angle = 180 else: # why these two distances are not necessary equal is a mystery self.radius = max(distance(self, p1), distance(self, p2)) # FIXME maybe angles are ordered and should not be exchanged, check clockwise argument p1_heading = heading(self, p1) p2_heading = heading(self, p2) self.start_angle = min(p1_heading, p2_heading) self.end_angle = max(p1_heading, p2_heading)
def tasklen(angles, position, waypoints): dist = 0 for theta, wp in zip(angles, waypoints): proj = destination(wp, wp.radius, theta) dist += distance(proj, position) position = proj return dist
def is_closed(self, tol=2000): if self._closed: return True for p1 in self._before: for p2 in self._after: if distance(p1, p2) < tol: self._closed = True return True return False
def optimize(position, waypoints, prev_opti=None): x0 = np.zeros(len(waypoints)) if prev_opti is None else prev_opti result = minimize(tasklen, x0, args=(position, waypoints), tol=OPTIMIZER_PRECISION) distances = [] fast_waypoints = [Turnpoint(position.lat, position.lon)] for theta, wp in zip(result.x, waypoints): proj = destination(wp, wp.radius, theta) distances.append(distance(proj, fast_waypoints[-1])) fast_waypoints.append(Turnpoint(proj[0], proj[1])) return Opti(sum(distances), distances, fast_waypoints, result.x)
def __init__(self, task): # try to base64 decode the task if not os.path.isfile(task): try: task = base64.b64decode(task) task = json.loads(task) except TypeError: logging.debug(f'Task is not base64') else: with open(task, 'r') as f: task = json.load(f) # try to parse with every implemented format, raise if no match for task_format in [ taskparse.XCTask, taskparse.PWCATask, taskparse.RawTask, taskparse.pygclibTask ]: try: task = task_format(task) break except (KeyError, TypeError): logging.debug(f'Task format does not fit into {task_format}') if not hasattr(task, 'takeoff'): raise NotImplementedError('Task format not recognized') self.__dict__.update(task.__dict__) # if the goal is a line, we need a to compute its validation with the following technique # we compute the heading between the goal and the first previous turnpoint which has a different center # during validation, we compute the heading between the pilot and the goal center # when the absolute difference between these two headings is greater than 90~ish° (and is inside the goal radius), the goal is validated # not only does this allow us to validate goal line, but it also helps drawing goal lines in TaskCreator by directly having the line normal direction if self.goal_style == 'LINE': index_last_turnpoint = -2 while distance(self.turnpoints[index_last_turnpoint], self.turnpoints[-1]) < 1: index_last_turnpoint -= 1 self.last_leg_heading = heading( self.turnpoints[index_last_turnpoint], self.turnpoints[-1]) self.opti = optimize(self.takeoff, self.turnpoints)
def triangle_length(points, flight): total_distance = distance(flight[points[0]], flight[points[1]]) total_distance += distance(flight[points[1]], flight[points[2]]) total_distance += distance(flight[points[2]], flight[points[0]]) return -total_distance
def __eq__(self, other): return distance(*self.bounds) == distance(*other.bounds)
def __gt__(self, other): return distance(*self.bounds) > distance(*other.bounds)
def __lt__(self, other): return distance(*self.bounds) < distance(*other.bounds)
def __contains__(self, point): return (distance(self, point) < self.radius) and ( self.start_angle <= heading(self, point) <= self.end_angle)
def __contains__(self, point): return distance(self, point) < self.radius
def close_enough(self, wpt): # TODO delete when proper task validation return abs(distance(self, wpt) - wpt.radius) < 10 + wpt.radius * TOLERANCE