#include "select_tool.h" #include "ant.h" #include "card_path.h" #include "log.h" #include "card.h" #include "loc_common.h" //opt_tool_main select_point_object::m_opt_tool; void select_point_object::att_initiate() { m_fitk.add_tool(30,5,5); m_fitk.add_tool(30,5,6); m_fitk.add_tool(30,10,10); m_fitk.add_tool(30,10,15); m_fitk.add_tool(20,5,6); m_fitk.add_tool(30,4,6); m_fitk.add_tool(40,4,6); m_fita.add_tool(15,5,5); m_begin=m_last=0; } // int select_point_object::select_max_solution(const float& lhs, const float& rhs, const std::vector vp, loc_point& lp) { if(lhs > rhs){ lp.set(vp[0]); return 0; }else{ lp.set(vp[1]); return 1; } } // int select_point_object::select_min_solution(const float& lhs, const float& rhs, const std::vector vp, loc_point& lp) { if(lhs < rhs){ lp.set(vp[0]); return 0; }else{ lp.set(vp[1]); return 1; } } loc_point select_point_object::select_solution_impl(const std::vector vp,const std::vector&lm) { bool flag = false; loc_point lp; //如果1维pdoa定位 logn_info(3, "select_solution_impl status, dims=%d, loc_type=%d, vp's size=%d", lm[0].m_sit->m_num_dims, lm[0].m_loc_type, vp.size()); switch(lm[0].m_loc_type){ case LDT_TOF: if(vp.size()==4) { m_d.grow().reset().set_source(lm[0],lm[1]); flag = true; } if(vp.size()==2 && lm[0].m_card_ct - last_ct() == 1) { m_d.grow().reset().set_source(lm[0]); flag = true; } if(flag) { if(!select_solution(vp,lm[0].m_sit.get(),lp)) { m_cur_fit.reset(); } } break; case LDT_PDOA: select_pdoa_solution_impl(vp, lm, lp); break; } m_ct = lm[0].m_card_ct; return lp; } bool select_point_object::select_pdoa_solution_impl(const std::vector vp, const std::vector& lm, loc_point& lp) { switch(get_algo_index(lm[0].tool_index())){ case 6: return select_pdoa_1d_solution(vp, lm, lp); break; case 7: return select_pdoa_2d_solution(vp, lm, lp); break; case 8: return select_pdoa_3d_solution(vp, lm, lp); break; } return false; } /* * 当下井方向选解策略 * * */ bool select_point_object::select_pdoa_solution(const std::vector vp, const std::vector& lm, loc_point&lp, const float& pdoa) { if(1 == vp.size()) { bool dir = (pdoa > EPS); logn_info(3,"[pdoa] card_id=%d, ct=%d, vp0x=%.4f, vp0y=%.4f", lm[0].m_card_id, lm[0].m_card_ct, vp[0].x, vp[0].y); if(lm[0].m_sit->m_ant[0].x == lm[0].m_sit->m_ant[1].x) { if(0 == lm[0].m_sit->m_pdoa_direction){ if(dir){ if(vp[0].x > lm[0].m_sit->m_ant[0].x){ lp.set(vp[0]); lp.m_useless = true; }else{ logn_warn(3, "[pdoa] solution is not correct, card_id=%d", lm[0].m_card_id); lp.m_useless = false; } }else{ if(vp[0].x < lm[0].m_sit->m_ant[0].x){ lp.set(vp[0]); lp.m_useless = true; }else{ logn_warn(3, "[pdoa] solution is not correct, card_id=%d", lm[0].m_card_id); lp.m_useless = false; } } }else{ if(dir){ if(vp[0].x < lm[0].m_sit->m_ant[0].x){ lp.set(vp[0]); lp.m_useless = true; }else{ lp.m_useless = false; } }else{ if(vp[0].x > lm[0].m_sit->m_ant[0].x){ lp.set(vp[0]); lp.m_useless = true; }else{ lp.m_useless = false; } } } }else{ logn_info(3, "[pdoa] select one solution, card_id=%d", lm[0].m_card_id); if(dir){ } } return lp.m_useless; }else if(2 == vp.size()){ // select one solution from two solution by reader and phase direction logn_info(3, "[pdoa] select one solution from 2, card_id=%d, ct=%d, site_dir=%d, vp0x=%.4f, vp0y=%.4f, vp1x=%.4f, vp1y=%.4f", lm[0].m_card_id, lm[0].m_card_ct, lm[0].m_sit->m_pdoa_direction, vp[0].x, vp[0].y, vp[1].x, vp[1].y); bool dir = (pdoa > EPS); int max = -1, min = -1; if(0 == lm[0].m_sit->m_pdoa_direction) { if(lm[0].m_sit->m_ant[0].x == lm[0].m_sit->m_ant[1].x){ dir?(max = select_max_solution(vp[0].x, vp[1].x, vp, lp)):(min = select_min_solution(vp[0].x, vp[1].x, vp, lp)); }else if(lm[0].m_sit->m_ant[0].y == lm[0].m_sit->m_ant[1].y){ dir?(max = select_max_solution(vp[0].x, vp[1].x, vp, lp)):(min = select_min_solution(vp[0].x, vp[1].x, vp, lp)); }else if((lm[0].m_sit->m_ant[0].x != lm[0].m_sit->m_ant[1].x) && (lm[0].m_sit->m_ant[0].y != lm[0].m_sit->m_ant[1].y)){ dir?(max = select_max_solution(vp[0].x, vp[1].x, vp, lp)):(min = select_min_solution(vp[0].x, vp[1].x, vp, lp)); } }else{ if(lm[0].m_sit->m_ant[0].x == lm[0].m_sit->m_ant[1].x){ // 分站天线在竖直巷道 dir?(min = select_min_solution(vp[0].y, vp[1].y, vp, lp)):(max = select_max_solution(vp[0].y, vp[1].y, vp, lp)); }else if(lm[0].m_sit->m_ant[0].y == lm[0].m_sit->m_ant[1].y){ // 分站天线在水平巷道 dir?(min = select_min_solution(vp[0].x, vp[1].x, vp, lp)):(max = select_max_solution(vp[0].x, vp[1].x, vp, lp)); }else if((lm[0].m_sit->m_ant[0].x != lm[0].m_sit->m_ant[1].x) && (lm[0].m_sit->m_ant[0].y != lm[0].m_sit->m_ant[1].y)){ dir?(min = select_min_solution(vp[0].x, vp[1].x, vp, lp)):(max = select_max_solution(vp[0].x, vp[1].x, vp, lp)); } } logn_info(3, "[pdoa] card_id=%d, cur_pdoa=%.2f, dir=%s site_dir=%d, min=%d, max=%d", lm[0].m_card_id, pdoa, (dir?"true":"false"), lm[0].m_sit->m_pdoa_direction, min, max); } return true; } // 当出井方向切换分站选解 bool select_point_object::select_pdoa_solution2(const std::vector vp, const std::vector& lm, loc_point&lp, const float& pdoa) { if(1 == vp.size()) { bool dir = (pdoa > EPS); logn_info(3,"[pdoa] card_id=%d, ct=%d, vp0x=%.4f, vp0y=%.4f", lm[0].m_card_id, lm[0].m_card_ct, vp[0].x, vp[0].y); if(lm[0].m_sit->m_ant[0].x == lm[0].m_sit->m_ant[1].x) { if(0 == lm[0].m_sit->m_pdoa_direction){ if(dir){ if(vp[0].x > lm[0].m_sit->m_ant[0].x){ lp.set(vp[0]); lp.m_useless = true; }else{ logn_warn(3, "[pdoa] solution is not correct, card_id=%d", lm[0].m_card_id); lp.m_useless = false; } }else{ if(vp[0].x < lm[0].m_sit->m_ant[0].x){ lp.set(vp[0]); lp.m_useless = true; }else{ logn_warn(3, "[pdoa] solution is not correct, card_id=%d", lm[0].m_card_id); lp.m_useless = false; } } }else{ if(dir){ if(vp[0].x < lm[0].m_sit->m_ant[0].x){ lp.set(vp[0]); lp.m_useless = true; }else{ lp.m_useless = false; } }else{ if(vp[0].x > lm[0].m_sit->m_ant[0].x){ lp.set(vp[0]); lp.m_useless = true; }else{ lp.m_useless = false; } } } }else{ logn_info(3, "[pdoa] select one solution, card_id=%d", lm[0].m_card_id); if(dir){ } } return lp.m_useless; }else if(2 == vp.size()){ // select one solution from two solution by reader and phase direction logn_info(3, "[pdoa] select one solution from 2, card_id=%d, ct=%d, site_dir=%d, vp0x=%.4f, vp0y=%.4f, vp1x=%.4f, vp1y=%.4f", lm[0].m_card_id, lm[0].m_card_ct, lm[0].m_sit->m_pdoa_direction, vp[0].x, vp[0].y, vp[1].x, vp[1].y); bool dir = (pdoa > EPS); int max = -1, min = -1; if(lm[0].m_sit->m_ant[0].x == lm[0].m_sit->m_ant[1].x){ dir?(max = select_max_solution(vp[0].y, vp[1].y, vp, lp)):(min = select_min_solution(vp[0].y, vp[1].y, vp, lp)); }else if(lm[0].m_sit->m_ant[0].y == lm[0].m_sit->m_ant[1].y){ dir?(max = select_max_solution(vp[0].y, vp[1].y, vp, lp)):(min = select_min_solution(vp[0].y, vp[1].y, vp, lp)); }else if((lm[0].m_sit->m_ant[0].x != lm[0].m_sit->m_ant[1].x) && (lm[0].m_sit->m_ant[0].y != lm[0].m_sit->m_ant[1].y)){ dir?(max = select_max_solution(vp[0].y, vp[1].y, vp, lp)):(min = select_min_solution(vp[0].y, vp[1].y, vp, lp)); } logn_info(3, "[pdoa] card_id=%d, cur_pdoa=%.2f, dir=%s site_dir=%d, min=%d, max=%d", lm[0].m_card_id, pdoa, (dir?"true":"false"), lm[0].m_sit->m_pdoa_direction, min, max); } return true; } /*bool select_point_object::select_pdoa_1d_solution(const std::vector vp, const std::vector& lm, loc_point& lp) { uint64_t id = lm[0].m_card_type; id = ((id<<32) | lm[0].m_card_id); auto card = card_list::instance()->get(id); double dist_tof = lm[0].m_num_ticks * 15.65 * 2.996 * 1e-4; if((card->m_buff_size != 100 || dist_tof < SAFE) && fabs(lm[0].m_poa[1] - 10.0) < 1E-4){ return false; } int idx = lm[0].tool_index(); uint8_t type = idx>>4; uint8_t dim = idx&0x03; idx = type*3 + dim - 1; if(card->m_buff_size == 100 && dist_tof > SAFE && fabs(lm[0].m_poa[1] - 10.0) < 1E-4){ lp.x = card->m_last_point.x; lp.y = card->m_last_point.y; double diff_time = (lm[0].m_loc_time - card->m_last_recv_time)*1.0/1000.0; double speed = get_speed(lp, card->m_last_point, diff_time) * lm[0].m_sit->m_scale; if(speed > 15.0){ lp.m_useless = false; return false; } lp.m_useless = true; logn_info(3, "[pdoa] solution info: card_id=%d, ct=%d, useless=%d, locate_x=%.4f, locate_y=%.4f, speed=%.3f, opt=true", lm[0].m_card_id, lm[0].m_card_ct, lp.m_useless, lp.x, lp.y, speed); card->m_last_pdoa_diff = card->m_pdoa_diff; card->m_last_ct = lm[0].m_card_ct; card->m_last_dist = dist_tof; card->m_cb_point.push_back(lp); card->m_last_site_id = lm[0].m_sit->m_id; card->m_last_site_dir = lm[0].m_sit->m_pdoa_direction; card->m_last_recv_time = lm[0].m_loc_time; card->m_last_point.x = lp.x; card->m_last_point.y = lp.y; lp.m_speed = card->m_speed = 0; return true; } card->m_pdoa_diff = get_pdoa(lm[0].m_poa, lm[0].m_sit->m_pdoa_offset); logn_info(3, "[pdoa] card_id=%d, pdoa=%.3f, poa[0]=%.3f, poa[1]=%.3f, poa[2]=%.3f, offset=%.4f, dist=%.3f", id, card->m_pdoa_diff, lm[0].m_poa[0], lm[0].m_poa[1], lm[0].m_poa[2], lm[0].m_sit->m_pdoa_offset, dist_tof); // after a long time,there is not recvied data, then reset pdoa list if(((card->m_last_dist < SAFE && dist_tof >= SAFE) || (lm[0].m_loc_time - card->m_last_recv_time > 30*1000)) && card->m_buff_size == 100){ logn_info(3, "[pdoa] reset pdoa buffer, card_id=%d, cur_dist=%.3f, cur_time=%lld, last_dist=%.3f, last_time=%lld", lm[0].m_card_id, dist_tof, lm[0].m_loc_time, card->m_last_dist, card->m_last_recv_time); card->clear(); } //first adjust, first 5 frame, not output located point uint16_t ct = lm[0].m_card_ct; if(card->m_buff_size < 5){ card->m_cb_pdoa.push_back(card->m_pdoa_diff); ++card->m_buff_size; card->m_cb_tof.push_back(dist_tof); card->m_last_ct = ct; card->m_last_dist = dist_tof; card->m_last_recv_time = lm[0].m_loc_time; return false; } // choose 3 poa's direction as the card's direction if(5 == card->m_buff_size){ card->m_buff_size = 100; int positive = 0; for(int i = 0;i < 5; ++i){ if(card->m_cb_pdoa[i] > 0){ ++positive; } } if(positive >= 3){ for(int i = 0; i < 5; ++i){ if(card->m_cb_pdoa[i] < 0){ card->m_cb_pdoa[i] = -1.0*card->m_cb_pdoa[i]; } } }else{ for(int i = 0;i < 5;++i){ if(card->m_cb_pdoa[i] > 0){ card->m_cb_pdoa[i] = -1.0*card->m_cb_pdoa[i]; } } } } // tof filter int ct_offset = -1; float offset = 0.0f; ct_offset = ct - card->m_last_ct; offset = card->m_cb_tof[4] - dist_tof; if(1 == ct_offset) { if(offset < 0){ offset = -1.0*offset; } // need call opt way if(offset > 15){ // illeglal tof logn_info(3, "[pdoa] the distance's is bigger than 15, card_id=%d, ct=%d, cur_dist=%.3f, last_ct=%d, last_dist=%.3f", lm[0].m_card_id, lm[0].m_card_ct, dist_tof, card->m_last_ct, card->m_cb_tof[4]); return false; } } card->m_last_dist = dist_tof; //card->m_cb_tof.push_back(dist_tof); logn_info(3, "[pdoa] normal, card_id=%d, ct=%d, cur_dist=%.3f, last_ct=%d, last_dist=%.3f", lm[0].m_card_id, lm[0].m_card_ct, dist_tof, card->m_last_ct, card->m_cb_tof[4]); //pdoa meadian filter std::array pdoa = {0}; for(int i = 0; i < 5; ++i){ pdoa[i] = card->m_cb_pdoa[i]; } std::sort(pdoa.begin(), pdoa.end()); float meadian_pdoa = pdoa[2]; logn_info(3, "[pdoa] card_id=%d, ct=%d, before pdoa filter: meadian_pdoa=%.4f, cur_pdoa=%.4f, last_pdoa=%.4f, pdoa[0]=%.4f, pdoa[1]=%.4f, pdoa[2]=%.4f, pdoa[3]=%.4f, pdoa[4]=%.4f", lm[0].m_card_id, lm[0].m_card_ct, meadian_pdoa, card->m_pdoa_diff, card->m_last_pdoa_diff, card->m_cb_pdoa[0], card->m_cb_pdoa[1], card->m_cb_pdoa[2], card->m_cb_pdoa[3], card->m_cb_pdoa[4]); float cur_pdoa = card->m_pdoa_diff; bool change = false; if(lm[0].m_loc_time - card->m_last_recv_time < 30*1000){ if(card->m_last_site_id !=0 && card->m_last_site_id != lm[0].m_sit->m_id){ // pdoa change from site A to site B if(card->m_last_site_dir == 0 && lm[0].m_sit->m_pdoa_direction == 0){ change = true; }else if(card->m_last_site_dir == 0 && lm[0].m_sit->m_pdoa_direction == 1){ // keep same direction }else if(card->m_last_site_dir == 1 && lm[0].m_sit->m_pdoa_direction == 0){ // keep same direction }else if(card->m_last_site_dir == 1 && lm[0].m_sit->m_pdoa_direction == 1){ change = true; } if(change){ for(int i = 0;i < 5; ++i){ card->m_cb_pdoa[i] *= -1.0; } } // 下面逻辑判断当前pdoa值是否有异常,如有异常就改变方向 int same_direction = 0; for(int i = 0;i < 5;++i){ if(card->m_cb_pdoa[i] * cur_pdoa > 0){ same_direction++; } } if(same_direction < 3){ cur_pdoa*=-1; } logn_info(3, "[pdoa] card_id=%d, change site from %d to %d, pdoa change status=%d", lm[0].m_card_id, card->m_last_site_id, lm[0].m_sit->m_id, (change?1:0)); card->m_cb_pdoa.push_back(cur_pdoa); card->m_cb_tof.push_back(dist_tof); // 定位退出 if(!save_pdoa_1d(card, vp, lm, lp, cur_pdoa)){ return false; } return true } } // 5 meter away filter, abnormal poa //bool is_opposite = false; if(dist_tof > SAFE) { int same_direction = 0; for(int i = 0;i< 5;++i){ if(card->m_cb_pdoa[i] * cur_pdoa > 0){ same_direction++; } } if(same_direction < 3){ logn_info(3, "[pdoa] at 5m away, the pdoa is opposite, card_id=%d, ct=%d, old_pdoa=%.3f", lm[0].m_card_id, lm[0].m_card_ct, cur_pdoa); float last_k = 0.0f, curr_k = 0.0f, llast_k = 0.0f; llast_k = card->m_cb_tof[3] - card->m_cb_tof[2]; last_k = card->m_cb_tof[4] - card->m_cb_tof[3]; curr_k = dist_tof - card->m_cb_tof[4]; if(curr_k > 0 && last_k < 0 && llast_k < 0) { // find the site logn_info(3, "[pdoa] card has cross the site, card_id=%d, ct=%d", lm[0].m_card_id, lm[0].m_card_ct); // 缓存切换方向 }else{ card->m_cb_pdoa.push_back(cur_pdoa); card->m_cb_tof.push_back(cur_tof); // 定位退出 if(!save_pdoa_1d(card, vp, lm, lp, cur_pdoa)){ return false; } return true } } }else{ // judge the position of site logn_info(3, "[pdoa] 5m in, card_id=%d, ct=%d, distance=%.4f", lm[0].m_card_id, lm[0].m_card_ct, dist_tof); float last_k = 0.0f, curr_k = 0.0f, llast_k = 0.0f; llast_k = card->m_cb_tof[3] - card->m_cb_tof[2]; last_k = card->m_cb_tof[4] - card->m_cb_tof[3]; curr_k = dist_tof - card->m_cb_tof[4]; if(curr_k > 0 && last_k < 0 && llast_k < 0) { // find the site logn_info(3, "[pdoa] card has cross the site, card_id=%d, ct=%d", lm[0].m_card_id, lm[0].m_card_ct); for(int i = 0; i < 5;++i) { card->m_cb_pdoa[i] = 100; } //如果当前值方向和中值方向相同了,认为切了方向,因为距离信息当前方向和中值方向应该不同 if(((0.0 - card->m_pdoa_diff) < EPS) == ((0.0 - meadian_pdoa) < EPS)) { card->m_pdoa_diff = -card->m_pdoa_diff; } } } logn_info(3, "[pdoa] after pdoa filter, card_id=%d, ct=%d, current_pf=%.4f, last_pf=%.4f, cb[0]=%.4f, cb[1]= %.4f, cb[2]=%.4f, cb[3]=%.4f, cb[4]=%.4f, meadian=%.4f, tof[0]=%.4f, tof[1]=%.4f, tof[2]=%.4f, tof[3]=%.4f, tof[4]=%.4f", lm[0].m_card_id, lm[0].m_card_ct, card->m_pdoa_diff, card->m_last_pdoa_diff, card->m_cb_pdoa[0], card->m_cb_pdoa[1], card->m_cb_pdoa[2], card->m_cb_pdoa[3], card->m_cb_pdoa[4], meadian_pdoa, card->m_cb_tof[0], card->m_cb_tof[1], card->m_cb_tof[2], card->m_cb_tof[3], card->m_cb_tof[4]); card->m_cb_tof.push_back(dist_tof); card->m_cb_pdoa.push_back(card->m_pdoa_diff); if(!save_pdoa_1d(card, vp, lm, lp, cur_pdoa)){ return false; } return true; }*/ bool select_point_object::select_pdoa_1d_solution(const std::vector vp, const std::vector& lm, loc_point& lp) { uint64_t id = lm[0].m_card_type; id = ((id<<32) | lm[0].m_card_id); auto card = card_list::instance()->get(id); double dist = lm[0].m_num_ticks * 15.65 * 2.996 * 1e-4; int idx = lm[0].tool_index(); uint8_t type = idx>>4; uint8_t dim = idx&0x03; idx = type*3 + dim - 1; double pdoa = get_pdoa(lm[0].m_poa, lm[0].m_sit->m_pdoa_offset); logn_info(3, "[pdoa] card_id=%d, pdoa=%.2f, dist=%.2f, vp0x=%.2f, vp0y=%.2f, vp1x=%.2f, vp1y=%.2f", lm[0].m_card_id, pdoa, dist, vp[0].x, vp[0].y, vp[1].x, vp[1].y); double dt = (lm[0].m_loc_time - card->m_last_recv_time)*1.0/1000.0; double speed = fabs(dist - card->m_last_dist)/dt; if(card->m_last_recv_time > 0 && fabs(dt) > 30.0) { // 直接定位 logn_info(3, "[pdoa] card_id=%d, pdoa=%.2f, dt=%.2f, speed=%.2f, last_time=%llu", lm[0].m_card_id, pdoa, dt, speed, card->m_last_recv_time); card->m_last_recv_time = lm[0].m_loc_time; return false; } card->m_last_recv_time = lm[0].m_loc_time; int n = card->m_vtp_dist.size(); bool change_site = false; bool over_site = false; //切换基站,默认取正值 if(lm[0].m_sit->m_id != card->m_last_site_id){ // 切换基站要考虑两种情况 // 1)入井方向的切换 if(card->m_cb_stream_idx[0] < lm[0].m_sit->m_down_stream_idx){ if(lm[0].m_sit->m_pdoa_direction == 0){ pdoa *= (pdoa > 0?1:-1); }else{ pdoa *= (pdoa < 0?-1:1); } }else{ // 2)出井方向的切换 if(lm[0].m_sit->m_pdoa_direction == 0){ pdoa *= (pdoa < 0?1:-1); }else{ pdoa *= (pdoa > 0?-1:1); } } if(!select_pdoa_solution2(vp, lm, lp, pdoa)){ return false; } card->m_cb_stream_idx.push_back(lm[0].m_sit->m_down_stream_idx); card->m_last_site_id = lm[0].m_sit->m_id; card->m_vtp_dist.clear(); card->m_vtp_dist.resize(0); change_site = true; card->m_over_site = false; logn_info(3, "[pdoa] change site, card_id=%d, last_site=%d, last_dist=%.2f, cur_site=%d, cur_dist=%.2f", lm[0].m_card_id, card->m_last_site_id, card->m_last_dist, lm[0].m_sit->m_id, dist); }else if(!card->m_over_site && n >= 3){ // 过分站逻辑 if(!select_pdoa_solution2(vp, lm, lp, pdoa)){ return false; } //double dd = dist - card->m_last_dist; double d = lp.dist(card->m_last_point)*lm[0].m_sit->m_scale; logn_info(3, "[pdoa] origin info, card_id=%d, ox=%.2f, oy=%.2f, lx=%.2f, ly=%.2f, d=%.2f, dt=%.2f", lm[0].m_card_id, lp.x, lp.y, card->m_last_point.x, card->m_last_point.y, d, dt); // 如果选出的解是正确解,即距离和测距距离相等 double k1 = (card->m_vtp_dist[n-2] - card->m_vtp_dist[n-1])/dt; double k2 = (card->m_vtp_dist[n-1] - dist)/dt; logn_info(3, "[pdoa] card_id=%d, k1=%.2f, k2=%.2f, d=%.2f", lm[0].m_card_id, k1, k2, d); if(((k1 > 1 && k2 < -1) || (k1 < -1 && k2 > 1)) ||(k1*k2 < 0 && fabs(d - dist - card->m_last_dist) < 2.0)){ over_site = true; card->m_over_site = true; //过基站还要分以下两种情况: //1)入井时的从正到负 //2)出井时的从负到正 logn_info(3, "[pdoa] card_id=%d, cur_idx=%d, last_idx=%d", lm[0].m_card_id, card->m_cb_stream_idx[0], card->m_cb_stream_idx[1]); if(card->m_cb_stream_idx[1] > card->m_cb_stream_idx[0]){ //1)入井时的从正到负 pdoa *= (pdoa>0?-1:1); /*if(lm[0].m_sit->m_pdoa_direction == 0){ pdoa *= (pdoa<0?-1:1); }else{ pdoa *= (pdoa>0?1:-1); }*/ }else{ //2)出井时的从负到正 pdoa *= (pdoa<0?-1:1); /*if(lm[0].m_sit->m_pdoa_direction == 0){ pdoa *= (pdoa<0?-1:1); }else{ pdoa *= (pdoa>0?-1:1); }*/ } if(!select_pdoa_solution2(vp, lm, lp, pdoa)){ return false; } } } // 如果没有切换基站且没有过基站 if(!change_site && !over_site){ if(!select_pdoa_solution2(vp, lm, lp, pdoa)){ return false; } double d = lp.dist(card->m_last_point)*lm[0].m_sit->m_scale; logn_info(3, "[pdoa] select solution, card_id=%d, x=%.2f, y =%.2f, last_x=%.2f, last_y=%.2f, d=%.2f, pd=%.2f, dt=%.2f", lm[0].m_card_id, lp.x, lp.y, card->m_last_point.x, card->m_last_point.y, dist, d, dt); if(fabs(d - fabs(dist - card->m_last_dist)) > 2.0){ if(!card->m_last_point.empty()&&(lm[0].m_sit->m_id == card->m_last_site_id)){ int idx = 0; double min = 999999.0; for(size_t i = 0;i < vp.size();++i){ double d = vp[i].dist(card->m_last_point)*lm[0].m_sit->m_scale; if(fabs(d - speed*dt) < min){ idx = i; min = fabs(d - speed*dt); } } lp.set(vp[idx]); } } d = lp.dist(card->m_last_point)*lm[0].m_sit->m_scale; /*if(fabs(d-dist) > 0.5 && !card->m_last_point.empty()){ logn_info(3, "[pdoa] card_id=%d, d=%.2f, dist=%.2f, lp.x=%.2f, lp.y=%.2f , solution is not correct!", lm[0].m_card_id, d, dist, lp.x, lp.y); return false; }*/ logn_info(3, "[pdoa] unilateral processing, card_id=%d", lm[0].m_card_id); } lp.m_useless = true; logn_info(3, "[pdoa] card_id=%d, ct=%d, pdoa=%.2f, dd=%.2f, dt=%.2f", lm[0].m_card_id, lm[0].m_card_ct, pdoa, dt*speed, dt); logn_info(3, "[pdoa] solution info: card_id=%d, ct=%d, useless=%d, locate_x=%.4f, locate_y=%.4f, speed=%.3f, d=%.2f", lm[0].m_card_id, lm[0].m_card_ct, lp.m_useless, lp.x, lp.y, speed, dt*speed); if (!(card->m_isVehicleMap&&card->is_person())) { card->m_last_pdoa_diff = pdoa; card->m_last_ct = lm[0].m_card_ct; card->m_last_dist = dist; card->m_last_site_id = lm[0].m_sit->m_id; card->m_last_site_dir = lm[0].m_sit->m_pdoa_direction; card->m_last_point.x = lp.x; card->m_last_point.y = lp.y; lp.m_speed = card->m_speed = speed; card->m_cb_point.push_back(lp); card->m_vtp_dist.push_back(dist); } return true; } bool select_point_object::select_pdoa_2d_solution(const std::vector vp, const std::vector& lm, loc_point& lp) { logn_info(3, "[pdoa] begin select 2d solution, vp's size=%d", vp.size()); int i = 1; for(auto it = vp.cbegin(); it != vp.cend();++it){ logn_info(3, "[pdoa] useless %d : card_id=%d, x=%.4f, y=%.4f", i, lm[0].m_card_id,(*it).x, (*it).y); ++i; } if(1 == vp.size()){ lp.x = vp[0].x; lp.y = vp[0].y; lp.m_useless = true; } uint64_t id = lm[0].m_card_type; id = ((id<<32) | lm[0].m_card_id); auto card = card_list::instance()->get(id); card->m_last_point.x = lp.x; card->m_last_point.y = lp.y; return true; } bool select_point_object::select_pdoa_3d_solution(const std::vector vp, const std::vector& lm, loc_point& lp) { return true; } int select_point_object::get_algo_index(const int& idx) { uint8_t index = 0; uint8_t type = idx>>4; uint8_t dim = idx & 0x03; index = type*3 + dim - 1; log_info("[pdoa] algo=%d", index); return index; } double select_point_object::get_speed(const loc_point& p, const point& lp, const double& offset) { double speed = -1.0; if(!(p.x <= EPS && p.y <= EPS)){ speed = sqrt(pow(p.x - lp.x, 2) + pow(p.y - lp.y, 2))/offset; } logn_info(3, "[pdoa] calc_speed, p.x=%.3f, p.y=%.3f, lp.x=%.3f, lp.y=%.3f, diff_time=%lld", p.x, p.y, lp.x, lp.y, offset); return speed; } double select_point_object::get_distance(const int& rid, const int& lrid) { double d = 0.0; /*auto cs = sit_list()->instance()->get(rid); auto ls = sit_list()->instance()->get(lrid); if(cs&&ls){ d = cs.dist(ls); log_info("[pdoa] get distance from current site %d to last site %d", rid, lrid); }*/ return d; } float select_point_object::get_pdoa(const double poa[], const double& offset) { if(poa == nullptr){ return -10.0; } float poa1 = poa[0]; float poa2 = poa[1]; //float poa3 = poa[2]; float pdoa = poa2 - poa1 - offset; while(pdoa >= TPI){ pdoa -= TPI; } while(pdoa < 0){ pdoa += TPI; } pdoa -= PI; return pdoa; } int select_point_object::find_last(int start) { for(int i=start,len=m_d.size();i0) return i; } return -1; } int select_point_object::find_first(int start) { for(int i=start,len=m_d.size();i0) return i; } return -1; } /* * 拟合过滤 * * param * loc_point& c 最终保存点 * const std::vector& vp 可能解 * const double scale 比例尺 * * return * * * */ bool select_point_object::filter_by_fit(loc_point & c,const std::vector & vp,const double scale) { fit_result * fit = get_best_fit(); if(fit==nullptr || m_begin==nullptr || fit->ke>2) return false; loc_point &f = *m_begin; std::array v; int cnt = vp.size(); for(int i=0;itestk(c.m_time/1000.,f.dist_direct(vp[i])))); } std::sort(&v[0],&v[0]+cnt); double a = getA(fit,scale,v[1].score()-v[0].score()); if(a<0) return false; if(!filter_by_acc(c,v,a)) { c.set_cl(0); return true; //false? } reset_fit(vp[0].dist(v[0])); c[0]=v[0]; c[1]=v[1]; return true; } /* * 加速度过滤 * * param * loc_point& c * std::array& v * double e * * return * * */ bool select_point_object::filter_by_acc(loc_point&c,std::array&v,double a) { if(!m_last->is_same_site(c)) return true; double td=m_last->time_off(c); if(v[0].score()>a*td*td) return false; return true; } /* * * */ void select_point_object::select_one_ant(loc_point &c,const std::vector & vp) { int last=find_last(1); if(last>0) { loc_point&p=m_d(last); int cnt=vp.size(); std::array res; //find the shortest dis for(int i=0;i &tvp,const double scale) { loc_point&c=m_d(0); if(m_d.size()==1) { //first point ,only accpet two ants good data. if(c.cl()>0 && tvp.size()<4) { c[1]=tvp[1]; return c[0]=tvp[0]; } m_d.skip(1); return point(0,0); } select_solution1(c,tvp,scale); return c[0]; } bool select_point_object::select_solution(const std::vector &vp,const site*sit,loc_point &p) { remove_history(); std::vector tvp(vp.begin(),vp.end()); if(vp.size()==4) { int c = 0; std::array res; for(int i=0;i<2;i++) { int x = i+2; double d=vp[i].dist(vp[x]); if(dant_dist()*3) { res[c++].set_sol(vp[i].middle(vp[x]),d); } else { res[c++].set_sol(vp[i]); res[c++].set_sol(vp[x]); } } std::sort(&res[0],&res[0]+c); tvp.clear(); for(int i=0;im_scale); if(pt.empty() || m_d.empty()) return false; m_d(0).set(pt); if(!m_d(0).empty()) m_d(0).m_dist=sit->dist_direct(pt); else { m_d(0).set_cl(0); if(m_last) m_d(0).m_dist=0.01*m_last->m_dist>0?1:-1; } m_d(0).m_dist1 = sit->dist_direct(pt); bool fg = revise_by_history(pt,sit,m_d(0).m_time); if(!fg) { log_warn("out of site path:t=%ld,sit=%d,card_id=%d,ct=%d,tof1=%d,tof2=%d,pt=(%f,%f)\n", m_d(0).m_time, m_d(0).m_sid,m_d(0).m_cid,m_d(0).m_ct, m_d(0).m_tof[0], m_d(0).m_tof[1], pt.x, pt.y); return false; } if(!card_path::inst().is_at_path(pt)) { m_d(0).set_cl(0); log_warn("out of path:t=%ld,sit=%d,card_id=%d,ct=%d,tof1=%d,tof2=%d,pt=(%f,%f)\n", m_d(0).m_time, m_d(0).m_sid,m_d(0).m_cid,m_d(0).m_ct, m_d(0).m_tof[0], m_d(0).m_tof[1], pt.x, pt.y); return false; } m_last=&m_d(0); if(m_line.empty() && m_d.size()>=2 && !make_line()) return false; if(!m_line.contain(m_d(0),0.01) || (m_begin && !m_line.contain(m_begin->m_sol[0], 0.01))) { m_fitk.reset_data(); m_fita.reset_data(); m_begin=m_last=nullptr; int i0=find_last(1); if(i0==-1) return false; std::vector path=card_path::inst().find_path(m_d(i0),m_d(0)); m_d.skip(m_d.size()-i0); if(path.empty()) { m_line.clear(); return false; } m_line.set(path.back(),m_d(0)); } if(!m_begin) { int idx=find_first(0); if(idx>=0) m_begin=&m_d[idx]; } if(!m_last) { int idx=find_last(0); if(idx>=0) m_last=&m_d(idx); } if(m_begin && m_d(0).cl()) { int lastID1=find_last(1); int lastID2=-1; if(lastID1!=-1) lastID2=find_last(lastID1+1); if(lastID2!=-1) { double t0=m_last->m_time/1000., t1=m_d(lastID1).m_time/1000., t2=m_d(lastID2).m_time/1000.; double d0=m_begin->loc_dist(*m_last), d1=m_begin->loc_dist(m_d(lastID1)), d2=m_begin->loc_dist(m_d(lastID2)); double k1=(d1-d0)/(t1-t0), k2=(d2-d1)/(t2-t1); if(t0-t1<5 && t1-t2<5 && fabs(k2-k1)<0.5) { double tbegin = t0-3; while(tbeginm_time/1000.,m_begin->loc_dist(*m_last)); if(m_d.size()>1) { int pre=find_last(1); if(pre>0) { m_fita.add(m_d(0).m_time/1000.,m_begin->loc_dist(m_d(0))-m_begin->loc_dist(m_d(pre))); } } } p.set(pt); save_k(); p.m_useless=fg; return true; } bool select_point_object::make_line() { int i0=-1,i1=-1; if(-1==(i0=find_last(0))) return false; if(-1==(i1=find_last(i0+1))) return false; m_line.set(m_d(i0),m_d(i1)); return true; } void select_point_object::remove_history() { loc_point&b=m_d(0); if(m_d.size()>120 || (m_d.size()>2 && m_d(1).time_off(b)>max_histime)) { m_d.skip_if([&b,this](loc_point&p){ return p.time_off(b)>max_histime; }); m_fitk.reset_data(); m_fita.reset_data(); m_cur_fit.reset(); m_begin=m_last=nullptr; int idx=find_first(0); if(idx<0) return; m_begin=&m_d[idx]; idx=find_last(1); m_last=&m_d(idx); double dist=0,dist2=0; for(int len=std::min(15,m_d.size()-1),i=len;i>0;i--) { if(!m_d(i).cl()) continue; int lastID1=find_last(i+1); int lastID2=-1; if(lastID1!=-1) lastID2=find_last(lastID1+1); if(lastID2!=-1) { double t0=m_d(i).m_time/1000., t1=m_d(lastID1).m_time/1000., t2=m_d(lastID2).m_time/1000.; double d0=m_begin->loc_dist(m_d(i)[0]), d1=m_begin->loc_dist(m_d(lastID1)[0]), d2=m_begin->loc_dist(m_d(lastID2)[0]); double k1=(d1-d0)/(t1-t0), k2=(d2-d1)/(t2-t1); if(t0-t1<5 && t1-t2<5 && fabs(k2-k1)<0.5) { double tbegin = t0-3; while(tbeginloc_dist(m_d(i)[0]); m_fitk.add(m_d(i).m_time/1000.,dist); if(i==len) continue; m_fita.add(m_d(i).m_time/1000.,dist-dist2); dist2=dist; } save_k(); } } void select_point_object::save_k() { const fit_result*fk=best_fit_raw(0,4); if(!fk) { m_cur_fit.reset(); return; } m_cur_fit=*fk; fit_result&r=m_cur_fit; card_fit*fa=&m_fita[0]; if(fa->is_valid() && fa->ke<0.1 && fk->k*fa->k<0) { double dk=fa->k*fa->num_point; r.ka=fa->k; if((fk->k+dk)*fk->k<0) r.k=0; else r.k+=dk; double y=fk->k*m_fitk(0).x+fk->kb; r.kb=y-m_fitk(0).x*r.k; } } fit_result* select_point_object::best_fit_raw(int num_point,int start,int last) { card_fit*fit = nullptr; start = std::max(start,0); last = std::min(last,m_fitk.tool_size()); if(last == -1) last = m_fitk.tool_size(); for(int i = start; i < last; i++) { if(!m_fitk[i].is_valid()) continue; if(m_fitk[i].num_point < num_point) continue; if(fit == nullptr) { fit = &m_fitk[i]; continue; } if(fit->ke > m_fitk[i].ke) { fit = &m_fitk[i]; } } return fit; } select_tool::~select_tool() { if(m_spo !=nullptr) delete m_spo; } loc_point select_tool_person_1::select_solution(const std::vector vp,const std::vector&lm) { loc_point lp; //select point. uint8_t idx = 0; uint8_t type = lm[0].tool_index()>>4; uint8_t dim = lm[0].tool_index() & 0x03; idx = type*3 + dim - 1; //logn_info(3, "[pdoa] card_id=%d, idx=%d, dim=%d", lm[0].m_card_id, idx, dim); if(idx == 0) { if(m_spo==nullptr) m_spo = new person_point_filter(this); lp=m_spo->select_solution_impl(vp,lm); } else if (idx == 2) { //for now.. //m_spo = new person_point_filter(); //lp=m_spo->select_solution_impl(vp,lm); }else if(6 == idx){ // pdoa一维定位 //logn_info(3, "[pdoa] person, select_solution 1d, tool_index=%d", idx); if(nullptr == m_spo){ m_spo= new person_point_filter(this); } lp = m_spo->select_solution_impl(vp, lm); }else if(7 == idx){ // logn_info(3, "[pdoa] person, select_solution 2d, tool_index=%d", idx); // pdoa二维定位 if(nullptr == m_spo){ m_spo = new person_point_filter(this); } lp = m_spo->select_solution_impl(vp, lm); }else if(3 == idx){ }else if(4 == idx){ }else if(5 == idx){ } else {} return lp; } loc_point select_tool_car_1::select_solution(const std::vector vp,const std::vector&lm) { loc_point lp; //select point. uint8_t idx = 0; uint8_t type = lm[0].tool_index()>>4; uint8_t dim = lm[0].tool_index() & 0x03; idx = type*3 + dim - 1; if(idx == 0) { if(m_spo==nullptr) m_spo = new car_point_filter(this); lp=m_spo->select_solution_impl(vp,lm); } else if (idx == 2) { //for now.. //m_spo = new car_point_filter(); //lp=m_spo->select_solution_impl(vp,lm); }else if(6 == idx){ // pdoa一维定位 if(nullptr == m_spo){ m_spo = new car_point_filter(this); } lp = m_spo->select_solution_impl(vp, lm); }else if(7 == idx){ // pdoa二维定位 if(nullptr == m_spo) { m_spo = new car_point_filter(this); } lp = m_spo->select_solution_impl(vp, lm); }else if(3 == idx){ }else if(4 == idx){ }else if(5 == idx){ } else {} return lp; } select_tool_manage * select_tool_manage::instance() { static select_tool_manage stm; return &stm; }