Beispiel #1
0
    def crossed_line(self, fix1, fix2):

        distance1 = calculate_distance(fix1, self.fix)
        distance2 = calculate_distance(fix2, self.fix)

        if not self.is_line:
            raise ValueError('Calling crossed_line on a sector!')
        else:
            if distance2 > self.r_max and distance1 > self.r_max:
                return False
            else:  # either both within circle or only one, leading to small amount of false positives
                bearing1 = calculate_bearing(self.fix, fix1)
                bearing2 = calculate_bearing(self.fix, fix2)

                angle_wrt_orientation1 = abs(
                    calculate_bearing_difference(self.orientation_angle,
                                                 bearing1))
                angle_wrt_orientation2 = abs(
                    calculate_bearing_difference(self.orientation_angle,
                                                 bearing2))

                if self.sector_orientation == "next":  # start line
                    return angle_wrt_orientation1 < 90 < angle_wrt_orientation2
                elif self.sector_orientation == "previous":  # finish line
                    return angle_wrt_orientation2 < 90 < angle_wrt_orientation1
                else:
                    raise ValueError(
                        "A line with this orientation is not implemented!")
Beispiel #2
0
    def determine_outlanding_distance(self, outlanding_leg, fix):

        previous_waypoint = self.waypoints[outlanding_leg]
        next_waypoint = self.waypoints[outlanding_leg + 1]

        # outlanding distance = distance between tps minus distance from next tp to outlanding
        outlanding_dist = calculate_distance(previous_waypoint.fix, next_waypoint.fix)
        outlanding_dist -= calculate_distance(next_waypoint.fix, fix)

        return outlanding_dist if outlanding_dist > 0 else 0
Beispiel #3
0
    def _calculate_distance_completed_leg(self, leg, start_tp_fix, end_tp_fix):
        if leg == 0:  # take start-point of task
            start = self.waypoints[0]
            distance = calculate_distance(start.fix, end_tp_fix)

            if start.distance_correction == 'shorten_legs':
                distance -= start.r_max
        elif leg == self.no_legs - 1:  # take finish-point of task
            finish = self.waypoints[-1]
            distance = calculate_distance(start_tp_fix, finish.fix)

            if finish.distance_correction == 'shorten_legs':
                distance -= finish.r_max
        else:
            distance = calculate_distance(start_tp_fix, end_tp_fix)

        return distance
Beispiel #4
0
    def _calculate_distance_outlanding_leg(self, leg, start_tp_fix,
                                           outlanding_fix):
        if leg == 0:
            tp1 = self.waypoints[leg + 1]

            bearing = calculate_bearing(start_tp_fix, outlanding_fix)
            closest_area_fix = calculate_destination(start_tp_fix, tp1.r_max,
                                                     bearing)

            distance = calculate_distance(self.start.fix, closest_area_fix)
            distance -= calculate_distance(outlanding_fix, closest_area_fix)

        elif leg == self.no_legs - 1:  # take finish-point of task
            distance = calculate_distance(start_tp_fix, self.finish.fix)
            distance -= calculate_distance(self.finish.fix, outlanding_fix)

        else:
            tp1 = self.waypoints[leg + 1]

            bearing = calculate_bearing(tp1.fix, outlanding_fix)
            closest_area_fix = calculate_destination(tp1.fix, tp1.r_max,
                                                     bearing)

            if leg == 0:
                distance = calculate_distance(self.start.fix, closest_area_fix)
            else:
                distance = calculate_distance(start_tp_fix, closest_area_fix)
            distance -= calculate_distance(outlanding_fix, closest_area_fix)

        return distance
Beispiel #5
0
    def calculate_task_distances(self):

        distances = list()
        for leg in range(self.no_legs):

            begin = self.waypoints[leg]
            end = self.waypoints[leg+1]  # next is built in name
            distance = calculate_distance(begin.fix, end.fix)

            if begin.distance_correction is "shorten_legs":
                if end.distance_correction is "shorten_legs":
                    distance = Task.distance_shortened_leg(distance, begin, end, "begin")
                    distance = Task.distance_shortened_leg(distance, begin, end, "end")
                elif end.distance_correction is "move_tp":
                    distance = Task.distance_moved_turnpoint(distance, begin, end, "end")
                    distance = Task.distance_shortened_leg(distance, begin, end, "begin")
                elif end.distance_correction is None:
                    distance = Task.distance_shortened_leg(distance, begin, end, "begin")
                else:
                    raise ValueError("This distance correction does not exist: %s" % end.distance_correction)

            elif begin.distance_correction is "move_tp":
                if end.distance_correction is "shorten_legs":
                    distance = Task.distance_moved_turnpoint(distance, begin, end, "begin")
                    distance = Task.distance_shortened_leg(distance, begin, end, "end")
                elif end.distance_correction is "move_tp":
                    distance = Task.distance_moved_turnpoint(distance, begin, end, "begin")
                    distance = Task.distance_moved_turnpoint(distance, begin, end, "both_end")
                elif end.distance_correction is None:
                    distance = Task.distance_moved_turnpoint(distance, begin, end, "begin")
                else:
                    raise ValueError("This distance correction does not exist: %s" % end.distance_correction)

            elif begin.distance_correction is None:
                if end.distance_correction is "shorten_legs":
                    distance = Task.distance_shortened_leg(distance, begin, end, "end")
                elif end.distance_correction is "move_tp":
                    distance = Task.distance_moved_turnpoint(distance, begin, end, "end")
                elif end.distance_correction is None:
                    pass
                else:
                    raise ValueError("This distance correction does not exist: %s" % end.distance_correction)

            else:
                raise ValueError("This distance correction does not exist: %s" % self.waypoints[leg].distance_correction)

            distances.append(distance)

        return distances
Beispiel #6
0
    def inside_sector(self, fix):

        distance = calculate_distance(fix, self.fix)
        bearing = calculate_bearing(self.fix, fix)

        angle_wrt_orientation = abs(calculate_bearing_difference(self.orientation_angle, bearing))

        if self.is_line:
            raise ValueError('Calling inside_sector on a line')
        elif self.r_min is not None:
            inside_outer_sector = self.r_min - self.SEEYOU_SECTOR_MARGIN < distance < self.r_max + self.SEEYOU_SECTOR_MARGIN and angle_wrt_orientation < self.angle_max
            inside_inner_sector = distance < self.r_min and angle_wrt_orientation < self.angle_min
            return inside_outer_sector or inside_inner_sector
        else:  # self.r_min is None
            return distance < self.r_max + self.SEEYOU_SECTOR_MARGIN and (180 - angle_wrt_orientation) < self.angle_max
Beispiel #7
0
    def distance_moved_turnpoint(distance,
                                 begin,
                                 end,
                                 moved_point,
                                 move_direction='reduce'):
        from math import sqrt, cos, pi, acos

        if moved_point == "begin":
            moved = begin
            other = end
            angle_reduction = 0
        elif moved_point == "end":
            moved = end
            other = begin
            angle_reduction = 0
        elif moved_point == "both_end":
            moved = end
            other = begin
            original_distance = calculate_distance(begin.fix, end.fix)

            distance_moved_current = begin.r_max if begin.angle_max == 180 else begin.r_min
            angle_reduction = abs(
                acos((distance_moved_current**2 - distance**2 -
                      original_distance**2) /
                     (-2 * distance * original_distance))) * 180 / pi
        else:
            raise ValueError("Displaced point is not recognized: %s" %
                             moved_point)

        displacement_dist = moved.r_max if moved.angle_max == 180 else moved.r_min
        bearing1 = moved.orientation_angle
        bearing2 = calculate_bearing(other.fix, other.fix)

        if move_direction == 'increase':
            angle = 180 - abs(calculate_bearing_difference(
                bearing1, bearing2)) - angle_reduction
        else:
            angle = abs(calculate_bearing_difference(
                bearing1, bearing2)) - angle_reduction
        distance = sqrt(distance**2 + displacement_dist**2 - 2 * distance *
                        displacement_dist * cos(angle * pi / 180))

        return distance
Beispiel #8
0
 def _calculate_nominal_distances(self):
     distances = list()
     for start_waypoint, end_waypoint in double_iterator(self.waypoints):
         distance = calculate_distance(start_waypoint.fix, end_waypoint.fix)
         distances.append(distance)
     return distances
    def analyse(self, trace):

        # To prevent circular import with flight_phases
        from opensoar.thermals.flight_phases import Phase

        cruise = True
        possible_thermal_fixes = list()
        possible_cruise_fixes = list()
        sharp_thermal_entry_found = False
        turning_left = True
        total_bearing_change = 0

        # Start with first phase
        phases = [Phase(cruise, trace[0:2])]

        for fix_minus2, fix_minus1, fix in triple_iterator(trace):

            time_minus2 = fix_minus2['time']
            time_minus1 = fix_minus1['time']
            time = fix['time']

            bearing_change = calculate_bearing_change(fix_minus2, fix_minus1,
                                                      fix)
            delta_t = (0.5 * seconds_time_difference(time_minus1, time) +
                       0.5 * seconds_time_difference(time_minus2, time))
            bearing_change_rate = bearing_change / delta_t

            if cruise:

                continuing_left = turning_left and bearing_change_rate < self.MINIMUM_BEARING_CHANGE_RATE
                continuing_right = not turning_left and bearing_change_rate > -self.MINIMUM_BEARING_CHANGE_RATE

                if continuing_left or continuing_right:

                    total_bearing_change += bearing_change

                    if len(possible_thermal_fixes) == 0:
                        possible_thermal_fixes = [fix]
                    else:
                        if not sharp_thermal_entry_found and abs(
                                bearing_change_rate
                        ) > self.CRUISE_THRESHOLD_BEARINGRATE:
                            sharp_thermal_entry_found = True
                            phases[-1].fixes.extend(possible_thermal_fixes)
                            possible_thermal_fixes = [fix]
                        else:
                            possible_thermal_fixes.append(fix)

                else:  # sign change
                    total_bearing_change = bearing_change
                    sharp_thermal_entry_found = False

                    if len(possible_thermal_fixes) == 0:
                        phases[-1].fixes.append(fix)
                    else:
                        phases[-1].fixes.extend([*possible_thermal_fixes, fix])
                        possible_thermal_fixes = list()

                    turning_left = bearing_change_rate < 0

                if abs(total_bearing_change
                       ) > self.CRUISE_THRESHOLD_BEARINGTOT:
                    cruise = False
                    phases[-1].fixes.append(possible_thermal_fixes[0])
                    phases.append(Phase(cruise, possible_thermal_fixes))

                    possible_thermal_fixes = list()
                    sharp_thermal_entry_found = False
                    total_bearing_change = 0

            else:  # thermal

                if abs(bearing_change_rate
                       ) > self.THERMAL_THRESHOLD_BEARINGRATE:
                    if len(possible_cruise_fixes) != 0:
                        phases[-1].fixes.extend([*possible_cruise_fixes, fix])
                        possible_cruise_fixes = list()
                    else:
                        phases[-1].fixes.append(fix)

                else:  # possible cruise

                    if len(possible_cruise_fixes) == 0:
                        possible_cruise_fixes = [fix]
                        total_bearing_change = bearing_change
                    else:
                        possible_cruise_fixes.append(fix)
                        total_bearing_change += bearing_change

                    delta_t = seconds_time_difference(
                        possible_cruise_fixes[0]['time'], time)
                    cruise_distance = calculate_distance(
                        possible_cruise_fixes[0], fix)
                    temp_bearing_rate_avg = 0 if delta_t == 0 else total_bearing_change / delta_t

                    if (cruise_distance > self.THERMAL_THRESHOLD_DISTANCE
                            and abs(temp_bearing_rate_avg) <
                            self.THERMAL_THRESHOLD_BEARINGRATE_AVG):

                        cruise = True
                        phases[-1].fixes.append(possible_cruise_fixes[0])
                        phases.append(Phase(cruise, possible_cruise_fixes))
                        possible_cruise_fixes = list()
                        total_bearing_change = 0

        # add possible fixes at the end
        if cruise:
            if len(possible_thermal_fixes) != 0:
                phases[-1].fixes.extend(possible_thermal_fixes)
        else:
            if len(possible_cruise_fixes) != 0:
                phases[-1].fixes.extend(possible_cruise_fixes)

        return phases
Beispiel #10
0
    def test_calculate_distance_equal_fixes(self):

        fix1 = dict(lat=52.331783333333334, lon=6.249083333333333)
        fix2 = dict(lat=52.331783333333334, lon=6.249083333333333)

        self.assertEqual(calculate_distance(fix1, fix2), 0)
Beispiel #11
0
    def determine_performance(self, task, trip, phases, gps_altitude):

        thermal_altitude_gain_tot = 0
        thermal_altitude_loss_tot = 0
        thermal_time_tot = 0
        thermal_distance_tot = 0
        thermal_drift_tot = 0
        cruise_time_tot = 0
        cruise_distance_tot = 0
        cruise_height_diff_tot = 0
        task_time_tot = 0

        for leg in range(trip.completed_legs()):

            thermal_altitude_gain = 0
            thermal_altitude_loss = 0
            thermal_time = 0
            thermal_distance = 0
            thermal_drift = 0
            cruise_time = 0
            cruise_distance = 0
            cruise_height_diff = 0
            task_time = 0

            for i, phase in enumerate(phases.all_phases(leg)):

                # take refined start
                if leg == 0 and i == 0:
                    phase_duration = seconds_time_difference(
                        trip.refined_start_time, phase.fixes[-1]['time'])
                else:
                    phase_duration = seconds_time_difference_fixes(
                        phase.fixes[0], phase.fixes[-1])

                phase_distance_traveled = total_distance_travelled(phase.fixes)

                task_time += phase_duration
                if phase.is_cruise:
                    cruise_time += phase_duration
                    cruise_distance += phase_distance_traveled
                    cruise_height_diff += height_difference_fixes(
                        phase.fixes[0], phase.fixes[-1], gps_altitude)
                else:
                    thermal_time += phase_duration
                    thermal_distance += phase_distance_traveled
                    gain, loss = altitude_gain_and_loss(
                        phase.fixes, gps_altitude)
                    thermal_altitude_gain += gain
                    thermal_altitude_loss += loss
                    thermal_drift += calculate_distance(
                        phase.fixes[0], phase.fixes[-1])

            # write to total performance values
            thermal_altitude_gain_tot += thermal_altitude_gain
            thermal_altitude_loss_tot += thermal_altitude_loss
            thermal_time_tot += thermal_time
            thermal_distance_tot += thermal_distance
            thermal_drift_tot += thermal_drift
            cruise_time_tot += cruise_time
            cruise_distance_tot += cruise_distance
            cruise_height_diff_tot += cruise_height_diff
            task_time_tot += task_time

            self.write_perfs(leg, thermal_altitude_gain, thermal_altitude_loss,
                             thermal_time, thermal_distance, thermal_drift,
                             cruise_time, cruise_distance, cruise_height_diff,
                             task_time)

        if isinstance(task,
                      AAT) and task_time_tot < task.t_min.total_seconds():
            task_time_tot = task.t_min.total_seconds()

        self.write_perfs(-1, thermal_altitude_gain_tot,
                         thermal_altitude_loss_tot, thermal_time_tot,
                         thermal_distance_tot, thermal_drift_tot,
                         cruise_time_tot, cruise_distance_tot,
                         cruise_height_diff_tot, task_time_tot)