def _preprocess(self): """ removing points that are within 2 sigma_z of the previous included point The justification for this step is that until we see a point that is at least 2sigma_z away from its temporal predecessor, our confidence is low that the apparent movement is due to actual vehicle movement and not noise Returns: """ new_traj = list() lat_r_pre = None # latitude in radius lon_r_pre = None # longitude in radius for i in range(len(self.trajectory)): # dist have lat before lon, however dataset provide lon before lat. lat_r, lon_r = angle2radian(self.trajectory[i][2]), angle2radian( self.trajectory[i][1]) if lat_r_pre is None or dist(lat_r, lon_r, lat_r_pre, lon_r_pre) > 2 * self.sigma_z: # if distance > 2*sigma_z, take this point into calculation, otherwise remove it new_traj.append(self.trajectory[i]) lat_r_pre = lat_r lon_r_pre = lon_r self.trajectory = np.vstack(new_traj)
def _point_edge_dist(self, lon, lat, edge): lat_origin = angle2radian(self.rd_nwk.nodes[edge[0]]['lat']) lon_origin = angle2radian(self.rd_nwk.nodes[edge[0]]['lon']) lat_dest = angle2radian(self.rd_nwk.nodes[edge[1]]['lat']) lon_dest = angle2radian(self.rd_nwk.nodes[edge[1]]['lon']) a = dist(angle2radian(lat), angle2radian(lon), lat_origin, lon_origin) b = dist(angle2radian(lat), angle2radian(lon), lat_dest, lon_dest) c = dist(lat_origin, lon_origin, lat_dest, lon_dest) # if origin point is the closest if b**2 > a**2 + c**2: return a, edge[0] # distance, point # if destination point is the closest elif a**2 > b**2 + c**2: return b, edge[1] if c == 0: return a, edge[0] # otherwise, calculate the Vertical length p = (a + b + c) / 2 s = math.sqrt(p * math.fabs(p - a) * math.fabs(p - b) * math.fabs(p - c)) return 2 * s / c, None
def _set_lon_lat_radius(self, lon, lat): """ get longitude range & latitude range (because radius is actually achieved by a grid search) Args: lon: longitude local lat: latitude local self.r Returns: self.lon_r self.lat_r """ # lat_r self.lat_r = radian2angle(self.r / R_EARTH) # lon_r r_prime = R_EARTH * math.cos(angle2radian(lat)) self.lon_r = radian2angle(self.r / r_prime)
def _load_geo_and_rel(self): """ 加载.geo文件,格式[geo_id, type, coordinates, properties(若干列)] 加载.rel文件,格式[rel_id, type, origin_id, destination_id, properties(若干列)], .rel文件用来表示路网数据 Returns: self.rd_nwk: networkx.MultiDiGraph """ # init road network, which is the result of this function self.rd_nwk = nx.DiGraph(name="road network") # load geo and rel file geofile = pd.read_csv(self.data_path + self.geo_file + '.geo') relfile = pd.read_csv(self.data_path + self.rel_file + '.rel') geo_num = geofile.shape[0] # check type geo in rel file and LineString in geo file if not ['geo'] == self.config['rel']['including_types']: raise ValueError('.rel file should include geo type in Map Matching task!') if not ['LineString'] == self.config['geo']['including_types']: raise ValueError('.geo file should include LineString type in Map Matching task!') # get properties columns = relfile.columns.tolist()[4:] # use UnionSet to get nodes node_set = UnionSet(2 * geo_num) for index, row in relfile.iterrows(): # origin and destination from_id = int(row[2]) to_id = int(row[3]) node_set.union(from_id, to_id + geo_num) # generate MultiDigraph for index, row in geofile.iterrows(): geo_id = int(row['geo_id']) coordinate = eval(row['coordinates']) origin_node = node_set.find(geo_id + geo_num) dest_node = node_set.find(geo_id) if origin_node not in self.rd_nwk.nodes: self.rd_nwk.add_node(origin_node, lon=coordinate[0][0], lat=coordinate[0][1]) if dest_node not in self.rd_nwk.nodes: self.rd_nwk.add_node(dest_node, lon=coordinate[1][0], lat=coordinate[1][1]) # add edge self.rd_nwk.add_edge(origin_node, dest_node) feature_dct = dict() for i, column in enumerate(columns): feature_dct[column] = row[i + 4] if 'distance' not in feature_dct.keys(): feature_dct['distance'] = dist( angle2radian(self.rd_nwk.nodes[origin_node]['lat']), angle2radian(self.rd_nwk.nodes[origin_node]['lon']), angle2radian(self.rd_nwk.nodes[dest_node]['lat']), angle2radian(self.rd_nwk.nodes[dest_node]['lon']) ) feature_dct['geo_id'] = geo_id self.rd_nwk.edges[origin_node, dest_node].update(feature_dct) # logger self._logger.info("Loaded file " + self.geo_file + '.geo' + ', num_nodes=' + str(geo_num)) self._logger.info("Loaded file " + self.rel_file + '.rel, num_roads=' + str(len(self.rd_nwk)))
def _score_matrix(self): sub_static_matrices = list() # for every GPS sample for i in range(len(self.candidates)): # current candidates: self.candidates[i] # prev candidates: self.candidates[j] # no current candidates if i == 0: continue if len(self.candidates[i]) == 0: sub_static_matrix = np.zeros((1, 1)) sub_static_matrices.append(sub_static_matrix) continue # if there are current candidates, find prev index j j = i - 1 while j >= 0 and len(self.candidates[j]) == 0: j -= 1 # j >= 0, calculate score of candidates of GPS sample i if j < 0: sub_static_matrix = np.zeros((1, 1)) sub_static_matrices.append(sub_static_matrix) continue sub_static_matrix = np.zeros((len(self.candidates[j].items()), len(self.candidates[i].items()))) n = 0 for edge, dct in self.candidates[i].items(): m = 0 for edge_pre, dct_pre in self.candidates[j].items(): sub_static_matrix[m][n] = dct['N'] * dct_pre['V'][edge] * ( 1 if 'T' not in dct_pre.keys() else dct_pre['T'][edge]) m += 1 n += 1 sub_static_matrices.append(sub_static_matrix) traj_lon_lat = self.trajectory[:, 1:3] self.traj_points = [] for i in range(len(traj_lon_lat)): W = [] j = 0 while j < len(traj_lon_lat): if i == j: j += 1 continue lon_i, lat_i = traj_lon_lat[i, :] lon_j, lat_j = traj_lon_lat[j, :] euclid_distance = dist(angle2radian(lat_i), angle2radian(lon_i), angle2radian(lat_j), angle2radian(lon_j)) W.append(pow(math.e, -(euclid_distance**2 / self.beta**2))) j += 1 fai = [] self.sub_static_matrices = sub_static_matrices self.W = W for k in range(len(W)): fai.append(sub_static_matrices[k] * W[k]) traj_point = { "time": self.trajectory[i][0], "lon": self.trajectory[i][1], "lat": self.trajectory[i][2], "fai": fai, "candidates": self.candidates[i] } self.traj_points.append( traj_point) # Φ(fai) is the weighted score matrix
def _transmission_probability(self): """ Returns: """ i = 1 while i < len(self.candidates): # j and k j = i - 1 if len(self.candidates[i]) == 0: k = i + 1 while len( self.candidates[k]) == 0 and k < len(self.candidates): k += 1 if k == len(self.candidates): break else: k = i d = dist(angle2radian(self.trajectory[j][2]), angle2radian(self.trajectory[j][1]), angle2radian(self.trajectory[k][2]), angle2radian(self.trajectory[k][1])) for edge_j, dct_j in self.candidates[j].items(): for edge_k, dct_k in self.candidates[k].items(): brng_jk = init_bearing(angle2radian(self.trajectory[j][2]), angle2radian(self.trajectory[j][1]), angle2radian(self.trajectory[k][2]), angle2radian(self.trajectory[k][1])) brng_edge_j = init_bearing( angle2radian(self.rd_nwk.nodes[edge_j[0]]['lat']), angle2radian(self.rd_nwk.nodes[edge_j[0]]['lon']), angle2radian(self.rd_nwk.nodes[edge_j[1]]['lat']), angle2radian(self.rd_nwk.nodes[edge_j[1]]['lon']), ) try: if dct_j['node'] is not None and dct_k[ 'node'] is not None: result = d / nx.astar_path_length( self.rd_nwk, dct_j['node'], dct_k['node'], weight='distance') elif dct_j['node'] is not None: nd2_origin = edge_k[0] lon, lat = self.rd_nwk.nodes[nd2_origin][ 'lon'], self.rd_nwk.nodes[nd2_origin]['lat'] path_len = nx.astar_path_length(self.rd_nwk, dct_j['node'], nd2_origin, weight='distance') path_len += math.sqrt( math.fabs( dist(angle2radian(self.trajectory[k][2]), angle2radian(self.trajectory[k][1]), angle2radian(lat), angle2radian(lon)) **2 - dct_k['distance']**2)) if edge_j[1] == dct_j['edge']: path_len += self.rd_nwk[edge_j[0]][ edge_j[1]]['distance'] * 2 result = d / path_len elif dct_k['node'] is not None: nd1_destination = edge_j[1] lon, lat = self.rd_nwk.nodes[nd1_destination][ 'lon'], self.rd_nwk.nodes[nd1_destination][ 'lat'] path_len = nx.astar_path_length(self.rd_nwk, nd1_destination, dct_k['node'], weight='distance') path_len += math.sqrt( math.fabs( dist(angle2radian(self.trajectory[j][2]), angle2radian(self.trajectory[j][1]), angle2radian(lat), angle2radian(lon)) **2 - dct_j['distance']**2)) if edge_k[1] == dct_k['node']: path_len += self.rd_nwk[edge_k[0]][ edge_k[1]]['distance'] * 2 result = d / path_len else: if edge_j == edge_k and math.fabs(brng_edge_j - brng_jk) < 90: result = 1 else: nd1_destination = edge_j[1] lon1, lat1 = self.rd_nwk.nodes[nd1_destination]['lon'], \ self.rd_nwk.nodes[nd1_destination]['lat'] nd2_origin = edge_k[0] lon2, lat2 = self.rd_nwk.nodes[nd2_origin][ 'lon'], self.rd_nwk.nodes[nd2_origin][ 'lat'] result = d / (nx.astar_path_length( self.rd_nwk, nd1_destination, nd2_origin, weight='distance' ) + math.sqrt( math.fabs( dist( angle2radian(self.trajectory[j][2]), angle2radian(self.trajectory[j][1] ), angle2radian(lat1), angle2radian(lon1))**2 - dct_j['distance']**2) ) + math.sqrt( math.fabs( dist( angle2radian(self.trajectory[k][2]), angle2radian(self.trajectory[k][1] ), angle2radian(lat2), angle2radian(lon2))**2 - dct_k['distance']**2))) if 'V' in dct_j.keys(): dct_j['V'][edge_k] = min(result, 1) else: dct_j['V'] = {edge_k: min(result, 1)} except: if 'V' in dct_j.keys(): dct_j['V'][edge_k] = 0 else: dct_j['V'] = {edge_k: 0} i += 1