def cal_candidate_point(raw_pt, rn, edge): """ Get attributes of candidate point """ u, v = edge coords = rn[u][v][ 'coords'] # GPS points in road segment, may be larger than 2 candidates = [ project_pt_to_segment(coords[i], coords[i + 1], raw_pt) for i in range(len(coords) - 1) ] idx, (projection, coor_rate, dist) = min(enumerate(candidates), key=lambda x: x[1][2]) # enumerate return idx and (), x[1] --> () x[1][2] --> dist. get smallest error project edge offset = 0.0 for i in range(idx): offset += distance( coords[i], coords[i + 1]) # make the road distance more accurately offset += distance( coords[idx], projection) # distance of road start position and projected point if rn[u][v]['length'] == 0: rate = 0 # print(u, v) else: rate = offset / rn[u][v][ 'length'] # rate of whole road, coor_rate is the rate of coords. return CandidatePoint(projection.lat, projection.lng, rn[u][v]['eid'], dist, offset, rate)
def check_dis_loss(predict, target, trg_len): """ Calculate MAE and RMSE between predicted and targeted GPS sequence. Args: ----- predict = [seq len, batch size, 2] target = [seq len, batch size, 2] trg_len = [batch size] if not considering target length, the loss will smaller than the real one. predict and target have been removed sos Returns: ------- MAE of a batch in meter. RMSE of a batch in meter. """ predict = predict.permute(1, 0, 2) # [batch size, seq len, 2] target = target.permute(1, 0, 2) # [batch size, seq len, 2] bs = predict.size(0) ls_dis = [] for bs_i in range(bs): for len_i in range(trg_len[bs_i] - 1): pre = SPoint(predict[bs_i, len_i][0], predict[bs_i, len_i][1]) trg = SPoint(target[bs_i, len_i][0], target[bs_i, len_i][1]) dis = distance(pre, trg) ls_dis.append(dis) ls_dis = np.array(ls_dis) mae = ls_dis.mean() rmse = np.sqrt((ls_dis**2).mean()) return mae, rmse
def get_distance(pt_list): dist = 0.0 pre_pt = pt_list[0] for pt in pt_list[1:]: tmp_dist = distance(pre_pt, pt) dist += tmp_dist pre_pt = pt return dist
def get_interp_list(self, num_pts, cur_mm_pt, pre_mm_pt, ttl_dis, two_points_eids, two_points_coords, rn_dict): interp_list = [] unit_ts = (cur_mm_pt.time - pre_mm_pt.time) / (num_pts + 1) for n in range(int(num_pts)): new_time = pre_mm_pt.time + (n + 1) * unit_ts move_dis = (ttl_dis / num_pts) * n + pre_mm_pt.data['candi_pt'].offset # get eid and offset pre_road_dist, road_dist = 0, 0 for i in range(len(two_points_eids)): if i > 0: pre_road_dist += rn_dict[two_points_eids[i - 1]]['length'] road_dist += rn_dict[two_points_eids[i]]['length'] if move_dis <= road_dist: insert_eid = two_points_eids[i] insert_offset = move_dis - pre_road_dist break # get lat and lng dist, pre_dist = 0, 0 for i in range(len(two_points_coords) - 1): if i > 0: pre_dist += distance(two_points_coords[i - 1][0], two_points_coords[i][0]) dist += distance(two_points_coords[i][0], two_points_coords[i + 1][0]) if dist >= move_dis: coor_rate = (move_dis - pre_dist) / distance( two_points_coords[i][0], two_points_coords[i + 1][0]) project_pt = cal_loc_along_line( two_points_coords[i][0], two_points_coords[i + 1][0], coor_rate) break data = { 'candi_pt': CandidatePoint(project_pt.lat, project_pt.lng, insert_eid, 0, insert_offset, 0) } interp_list.append( STPoint(project_pt.lat, project_pt.lng, new_time, data)) return interp_list
def rate2gps(rn_dict, eid, rate, parameters): """ Convert road rate to GPS on the road segment. Since one road contains several coordinates, iteratively computing length can be more accurate. Args: ----- rn_dict: dictionary of road network eid,rate: single value from model prediction Returns: -------- project_pt: projected GPS point on the road segment. """ eid = eid.tolist() # convert tensor to normal value rate = rate.tolist() if eid <= 0 or rate < 0 or eid > (parameters.id_size - 1) or rate > 1: # force eid and rate in the right range return SPoint(0, 0) coords = rn_dict[eid]['coords'] offset = rn_dict[eid]['length'] * rate dist = 0 # temp distance for coords pre_dist = 0 # coords distance is smaller than offset if rate == 1.0: return coords[-1] if rate == 0.0: return coords[0] for i in range(len(coords) - 1): if i > 0: pre_dist += distance(coords[i - 1], coords[i]) dist += distance(coords[i], coords[i + 1]) if dist >= offset: coor_rate = (offset - pre_dist) / distance(coords[i], coords[i + 1]) project_pt = cal_loc_along_line(coords[i], coords[i + 1], coor_rate) break return project_pt
def compute_transition_probabilities(self, prev_time_step, time_step, probabilities): linear_dist = distance(prev_time_step.observation, time_step.observation) for prev_candi_pt in prev_time_step.candidates: for cur_candi_pt in time_step.candidates: path_dist, path = find_shortest_path(self.rn, prev_candi_pt, cur_candi_pt, self.routing_weight) # invalid transition has no transition probability if path is not None: time_step.add_road_path(prev_candi_pt, cur_candi_pt, path) time_step.add_transition_log_probability(prev_candi_pt, cur_candi_pt, probabilities.transition_log_probability(path_dist, linear_dist))
def filter(self, traj): pt_list = traj.pt_list if len(pt_list) <= 1: return None remove_inds = [] for i in range(1, len(pt_list) - 1): time_span_pre = (pt_list[i].time - pt_list[i - 1].time).total_seconds() dist_pre = distance(pt_list[i - 1], pt_list[i]) time_span_next = (pt_list[i + 1].time - pt_list[i].time).total_seconds() dist_next = distance(pt_list[i], pt_list[i + 1]) speed_pre = dist_pre / time_span_pre speed_next = dist_next / time_span_next # the first point is outlier if i == 1 and speed_pre > self.max_speed > speed_next: remove_inds.append(0) # the last point is outlier elif i == len( pt_list) - 2 and speed_next > self.max_speed >= speed_pre: remove_inds.append(len(pt_list) - 1) # middle point is outlier elif speed_pre > self.max_speed and speed_next > self.max_speed: remove_inds.append(i) clean_pt_list = [] for j in range(len(pt_list)): if j in remove_inds: continue clean_pt_list.append(pt_list[j]) if len(clean_pt_list) > 1: # return Trajectory(traj.oid, self.get_tid(traj.oid, pt_list), pt_list) return Trajectory(traj.oid, traj.tid, pt_list) else: return None
def filter(self, traj): """ When previous speed and next speed both are larger than max speed, then considering it as outlier. Replace outlier with mean value. The range is defined by window size. consider about the boundary. make sure noise value is in the middle. Args: ----- traj: Trajectory(). a single trajectory Returns: -------- new_traj: Trajectory(). replace noise with mean or median """ pt_list = traj.pt_list.copy() if len(pt_list) <= 1: return None for i in range(1, len(pt_list) - 1): time_span_pre = (pt_list[i].time - pt_list[i - 1].time).total_seconds() dist_pre = distance(pt_list[i - 1], pt_list[i]) time_span_next = (pt_list[i + 1].time - pt_list[i].time).total_seconds() dist_next = distance(pt_list[i], pt_list[i + 1]) # compute current speed speed_pre = dist_pre / time_span_pre speed_next = dist_next / time_span_next # if the first point is noise if i == 1 and speed_pre > self.max_speed > speed_next: lat = pt_list[i].lat * 2 - pt_list[i + 1].lat lng = pt_list[i].lng * 2 - pt_list[i + 1].lng pt_list[0] = STPoint(lat, lng, pt_list[0].time) # if the last point is noise elif i == len( pt_list) - 2 and speed_next > self.max_speed >= speed_pre: lat = pt_list[i - 1].lat * 2 - pt_list[i - 2].lat lng = pt_list[i - 1].lng * 2 - pt_list[i - 2].lng pt_list[i + 1] = STPoint(lat, lng, pt_list[i].time) # if the middle point is noise elif speed_pre > self.max_speed and speed_next > self.max_speed: pt_list[i] = STPoint(0, 0, pt_list[i].time) lats, lngs = [], [] # fix index bug. make sure index_i is in the middle. wind_size = self.win_size if self.win_size > i: wind_size = i elif self.win_size > len(pt_list) - 1 - i: wind_size = len(pt_list) - 1 - i for pt in pt_list[i - wind_size:i + wind_size + 1]: lats.append(pt.lat) lngs.append(pt.lng) lat = sum(lats) / (len(lats) - 1) lng = sum(lngs) / (len(lngs) - 1) pt_list[i] = STPoint(lat, lng, pt_list[i].time) if len(pt_list) > 1: # return Trajectory(traj.oid, self.get_tid(traj.oid, pt_list), pt_list) return Trajectory(traj.oid, traj.tid, pt_list) else: return None
def check_rn_dis_loss(predict_gps, predict_id, predict_rate, target_gps, target_id, target_rate, trg_len, rn, raw_rn_dict, new2raw_rid_dict): """ Calculate road network based MAE and RMSE between predicted and targeted GPS sequence. Args: ----- predict_gps = [seq len, batch size, 2] predict_id = [seq len, batch size, id one hot output dim] predict_rates = [seq len, batch size] target_gps = [seq len, batch size, 2] target_id = [seq len, batch size] target_rates = [seq len, batch size] trg_len = [batch size] if not considering target length, the loss will smaller than the real one. predict and target have been removed sos Returns: ------- MAE of a batch in meter. RMSE of a batch in meter. """ seq_len = target_id.size(0) batch_size = target_id.size(1) predict_gps = predict_gps.permute(1, 0, 2) predict_id = predict_id.permute(1, 0, 2) predict_rate = predict_rate.permute(1, 0) target_gps = target_gps.permute(1, 0, 2) target_id = target_id.permute(1, 0) target_rate = target_rate.permute(1, 0) ls_dis, rn_ls_dis = [], [] for bs in range(batch_size): for len_i in range(trg_len[bs] - 1): # don't calculate padding points pre_rid = predict_id[bs, len_i].argmax() convert_pre_rid = new2raw_rid_dict[pre_rid.tolist()] pre_rate = predict_rate[bs, len_i] pre_offset = raw_rn_dict[convert_pre_rid]['length'] * pre_rate pre_candi_pt = CandidatePoint(predict_gps[bs, len_i][0], predict_gps[bs, len_i][1], convert_pre_rid, 0, pre_offset, pre_rate) trg_rid = target_id[bs, len_i] convert_trg_rid = new2raw_rid_dict[trg_rid.tolist()] trg_rate = target_rate[bs, len_i] trg_offset = raw_rn_dict[convert_trg_rid]['length'] * trg_rate trg_candi_pt = CandidatePoint(target_gps[bs, len_i][0], target_gps[bs, len_i][1], convert_trg_rid, 0, trg_offset, trg_rate) if pre_candi_pt.lat == trg_candi_pt.lat and pre_candi_pt.lng == trg_candi_pt.lng: rn_dis = 0 dis = 0 else: rn_dis, _ = min( find_shortest_path(rn, pre_candi_pt, trg_candi_pt), find_shortest_path(rn, trg_candi_pt, pre_candi_pt)) if type(rn_dis) is not float: rn_dis = rn_dis.tolist() dis = distance(pre_candi_pt, trg_candi_pt) if rn_dis == np.inf: rn_dis = 1000 rn_ls_dis.append(rn_dis) ls_dis.append(dis) ls_dis = np.array(ls_dis) rn_ls_dis = np.array(rn_ls_dis) mae = ls_dis.mean() rmse = np.sqrt((ls_dis**2).mean()) rn_mae = rn_ls_dis.mean() rn_rmse = np.sqrt((rn_ls_dis**2).mean()) return mae, rmse, rn_mae, rn_rmse
def heuristic(node1, node2): return distance(SPoint(node1[1], node1[0]), SPoint(node2[1], node2[0]))