예제 #1
0
    def get_dynamic_simulation_data(self, simulation):
        """
        Reads simulation dictionary and pulls out info for Static Simulation data:

        Args:
          simulation: a dictionary {"metadata":{....}, "data": [list of data_dicts]}

        Returns:
          A list containing the broadcasted GpsData points in order
        """
        gps_data_list = []
        start_time = self.parse_time(simulation["metadata"]["start_time"])
        for data_point in simulation["data"]:
            x, y, z = float(data_point["x"]), float(data_point["y"]), float(
                data_point["z"])
            time_from_zero = float(data_point["time_from_zero"])
            lat, lon, alt = utils.cartesian_to_geodetic(x, y, z)
            time_stamp = start_time + timedelta(seconds=time_from_zero)
            # calculate speed for the point
            if gps_data_list:
                previous_point = gps_data_list[-1]
                time_elapsed = (time_stamp -
                                previous_point.time).total_seconds()
                distance = utils.calculate_distance(
                    (lat, lon),
                    (previous_point.latitude, previous_point.longitude))
                speed = distance / time_elapsed
            else:
                speed = 0.0  # first point has speed of zero
            gps_data_list.append(GpsData(lat, lon, alt, speed, time_stamp))

        return gps_data_list
예제 #2
0
    def test_calculate_distance_returns_correct_value(self):
        coordinate_1 = (37.1111, -122.1111)
        coordinate_2 = (40.7777, -125.7777)

        result = utils.calculate_distance(coordinate_1, coordinate_2)

        self.assertAlmostEqual(result, 516346.3, places=1)
예제 #3
0
def find_lineup_naive(set1, set2):
    """
    Initial naive implementation to find lineup between two data sets.

    Finds the point in the secondary data set closest to the start of the
    primary data set, and then uses those starting indices to find the offset
    with the lowest mean distance in the range of points around it index-wise
    in the data set

    Args:
        set1: GpsDataSet object
        set2: GpsDataSet object

    Returns:
        The indexes of the starting points in each data set
    """
    sets = [set1, set2]
    starting_indexes = [0, 0]
    set1_start_time = set1.gps_data_list[0].time
    set2_start_time = set2.gps_data_list[0].time
    if set1_start_time > set2_start_time:
        later_start_time = set1_start_time
        primary_set_index = 0
        secondary_set_index = 1
    else:
        later_start_time = set2_start_time
        primary_set_index = 1
        secondary_set_index = 0

    smallest_time_difference = None
    for i, data_point in enumerate(sets[secondary_set_index].gps_data_list):
        time_difference = abs(
            (data_point.time - later_start_time).total_seconds())
        if smallest_time_difference is None or time_difference < smallest_time_difference:
            smallest_time_difference = time_difference
            starting_indexes[secondary_set_index] = i
    best_index = 0
    best_mean_distance = None
    for offset in range(-100, 100):
        distances = []
        moving_index = starting_indexes[secondary_set_index] + offset
        if moving_index >= 0:
            primary_points = sets[primary_set_index].gps_data_list
            secondary_points = sets[secondary_set_index].gps_data_list[
                moving_index:]
            for primary_point, secondary_point in zip(primary_points,
                                                      secondary_points):
                location1 = (primary_point.latitude, primary_point.longitude)
                location2 = (secondary_point.latitude,
                             secondary_point.longitude)
                distances.append(utils.calculate_distance(
                    location1, location2))
        if distances and (best_mean_distance == None
                          or np.mean(distances) < best_mean_distance):
            best_mean_distance = np.mean(distances)
            best_index = moving_index
    print("optimal mean distance: " + str(best_mean_distance))
    starting_indexes[secondary_set_index] = best_index
    return starting_indexes
    def get_deviation_dataframe(self):
        """
        Extracts and returns deviation for each valid timestamp & other information.

        Returns:
            A pandas dataframe including the shared timestamp with the offset included,
            the deviations of lat/lon, the difference in speed, the difference in
            altitude, and the original timestamps for each set
        """
        if self.deviations_dataframe is not None: 
            return self.deviations_dataframe

        time_list, distance_deviation_list, speed_deviation_list, altitude_deviation_list= [], [], [], []
        set1_time_list, set2_time_list = [], []
        set1_average_signal_list, set2_average_signal_list, signal_deviation_list = [], [], []

        for timestamp in self.offset_mapping_1:
            if timestamp in self.offset_mapping_2:
                time_list.append(timestamp)

                # Get the mapping pair of data points in each dataset
                point1 = self.offset_mapping_1[timestamp][0]
                point2 = self.offset_mapping_2[timestamp][0]

                # Calculate the distance deviation
                location1 = (point1.latitude, point1.longitude)
                location2 = (point2.latitude, point2.longitude)
                distance_deviation_list.append(utils.calculate_distance(location1, location2))

                # Calculate the speed differentials
                speed_deviation_list.append(point2.speed - point1.speed)

                # Calculate the altitude differentials
                if point1.altitude is None or point2.altitude is None:
                    altitude_deviation_list.append(None)
                else:
                    altitude_deviation_list.append(point2.altitude - point1.altitude)

                # Append the original timestamp in each dataset
                set1_time_list.append(point1.time)
                set2_time_list.append(point2.time)

                # Append the average signal if have
                set1_average_signal_list.append(point1.average_signal)
                set2_average_signal_list.append(point2.average_signal)
                signal_deviation_list.append(point2.average_signal - point1.average_signal)


        self.deviations_dataframe = pd.DataFrame({"Common Timestamp": time_list,
                                                  "Distance Deviations": distance_deviation_list,
                                                  "Speed Deviations": speed_deviation_list,
                                                  "Altitude Deviations": altitude_deviation_list,
                                                  "Set 1 Timestamp": set1_time_list,
                                                  "Set 2 Timestamp": set2_time_list,
                                                  "Set 1 Average Signal": set1_average_signal_list,
                                                  "Set 2 Average Signal": set2_average_signal_list,
                                                  "Signal Deviations": signal_deviation_list})
        return self.deviations_dataframe
예제 #5
0
def find_optimal_offset(primary_set, secondary_set, start_time,
                        offset_range_length, point_checking_range_length):
    """
    Find optimal offset from offset range to shift the secondary set

    Finds the optimal offset meaning, an offset that is in the given offset
    range to check and that also has overlap between the two sets. If the
    mean distance is over 100m, it returns None, since this indicates sets
    that do not align even if their timestamps can be shifted to align. 

    Args:
        primary_set: dictionary in format {DateTime: [GpsData,], ...}
        secondary_set: dictionary in format {DateTime: [GpsData,], ...}
        start_time: Datetime to start calculation at
        offset_range: int, how many offset values to check i.e. the range of 
                      (-offset_range//2, offset_range//2)
        point_checking_range: int, how many points around the start to use in the deviation
                              mean calculations
        primary_set_index: which set (1 or 2) is the primary (i.e. not being shifted)

    Returns:
        int, the offset in seconds that should be applied to the secondary
        data set if an optimal offset exists,
        None otherwise
    """
    optimal_offset = 0
    optimal_mean_distance = MEAN_DISTANCE_THRESHOLD + 1

    for offset in range(-offset_range_length // 2, offset_range_length // 2):
        distances = []
        skipped_point_count = 0
        for i in range(-point_checking_range_length // 2,
                       point_checking_range_length // 2):
            # apply offset to secondary set
            primary_time = start_time + timedelta(seconds=i)
            secondary_time = start_time + timedelta(seconds=i + offset)

            if primary_time in primary_set and secondary_time in secondary_set:
                # if more than one point at that time, choose first one
                # TODO(ameles) consider if more complex downsampling needed
                primary_point = primary_set[primary_time][0]
                secondary_point = secondary_set[secondary_time][0]
                location1 = (primary_point.latitude, primary_point.longitude)
                location2 = (secondary_point.latitude,
                             secondary_point.longitude)
                distances.append(utils.calculate_distance(
                    location1, location2))
            else:
                skipped_point_count += 1

        if distances and np.mean(distances) < optimal_mean_distance:
            optimal_mean_distance = np.mean(distances)
            optimal_offset = offset

    print("optimal mean distance: " + str(optimal_mean_distance))
    if optimal_mean_distance is None or optimal_mean_distance > MEAN_DISTANCE_THRESHOLD:
        return None
    return optimal_offset
예제 #6
0
    def test_calculate_distance_returns_zero_for_same_coordinate(self):
        coordinate_1 = (37.1111, -122.1124)

        result = utils.calculate_distance(coordinate_1, coordinate_1)

        self.assertAlmostEqual(result, 0.0, places=8)
예제 #7
0
    def parse_xml_trkpts(self, root) -> []:
        """
        Helper function to parse trkpts in xml file
        """
        xml_gpsdatalist = []

        trk = root.find(PREFIX_URL + 'trk')
        if trk is None:
            LOGGER.debug('trk is None, could not parse trkpts.')
            return None

        trkseg = trk.find(PREFIX_URL + 'trkseg')
        if trkseg is None:
            LOGGER.debug('trkseg is None, could not parse trkpts.')
            return None

        if len(trkseg) == 0:
            LOGGER.debug('trkseg is empty, could not parse trkpts.')
            return None

        # Get the start location
        first_trkpt = trkseg[0]
        prev_location = (first_trkpt.get('lat'), first_trkpt.get('lon'))

        # Get every track point information
        for trkpt in trkseg:
            # Get the latitude and longitude
            lat = float(trkpt.get('lat'))
            lon = float(trkpt.get('lon'))

            # Calculate the distance from previous location, not considering the altitude for now
            cur_location = (lat, lon)
            distance = utils.calculate_distance(cur_location, prev_location)
            prev_location = cur_location

            # Get the altitude, speed and time
            alt, speed, tz_time = None, None, None
            sat = 0
            first_signal, second_signal, third_signal, forth_signal, average_signal = 0.0, 0.0, 0.0, 0.0, 0.0

            for data in trkpt.iter():
                if data.tag == PREFIX_URL + 'ele':
                    alt = float(data.text)
                elif data.tag == PREFIX_URL + 'speed':
                    speed = float(data.text)
                elif data.tag == PREFIX_URL + 'time':
                    tz_time = self.parse_time(data.text)
                elif data.tag == PREFIX_URL + 'sat':
                    sat = int(data.text)
                elif data.tag == PREFIX_URL + 'signal01':
                    first_signal = float(data.text)
                elif data.tag == PREFIX_URL + 'signal02':
                    second_signal = float(data.text)
                elif data.tag == PREFIX_URL + 'signal03':
                    third_signal = float(data.text)
                elif data.tag == PREFIX_URL + 'signal04':
                    forth_signal = float(data.text)
                elif data.tag == PREFIX_URL + 'average':
                    average_signal = float(data.text)

            data_point = GpsData(latitude=lat,
                                 longitude=lon,
                                 altitude=alt,
                                 speed=speed,
                                 time=tz_time,
                                 distance=distance,
                                 satellites=sat,
                                 first_signal=first_signal,
                                 second_signal=second_signal,
                                 third_signal=third_signal,
                                 forth_signal=forth_signal,
                                 average_signal=average_signal)

            xml_gpsdatalist.append(data_point)

        return xml_gpsdatalist