select_tool.cpp 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267
  1. #include "select_tool.h"
  2. #include "ant.h"
  3. #include "card_path.h"
  4. #include "log.h"
  5. #include "card.h"
  6. #include "loc_common.h"
  7. //opt_tool_main select_point_object::m_opt_tool;
  8. void select_point_object::att_initiate()
  9. {
  10. m_fitk.add_tool(30,5,5);
  11. m_fitk.add_tool(30,5,6);
  12. m_fitk.add_tool(30,10,10);
  13. m_fitk.add_tool(30,10,15);
  14. m_fitk.add_tool(20,5,6);
  15. m_fitk.add_tool(30,4,6);
  16. m_fitk.add_tool(40,4,6);
  17. m_fita.add_tool(15,5,5);
  18. m_begin=m_last=0;
  19. }
  20. //
  21. int select_point_object::select_max_solution(const float& lhs, const float& rhs, const std::vector<point> vp, loc_point& lp)
  22. {
  23. if(lhs > rhs){
  24. lp.set(vp[0]);
  25. return 0;
  26. }else{
  27. lp.set(vp[1]);
  28. return 1;
  29. }
  30. }
  31. //
  32. int select_point_object::select_min_solution(const float& lhs, const float& rhs, const std::vector<point> vp, loc_point& lp)
  33. {
  34. if(lhs < rhs){
  35. lp.set(vp[0]);
  36. return 0;
  37. }else{
  38. lp.set(vp[1]);
  39. return 1;
  40. }
  41. }
  42. loc_point select_point_object::select_solution_impl(const std::vector<point> vp,const std::vector<loc_message>&lm)
  43. {
  44. bool flag = false;
  45. loc_point lp;
  46. //如果1维pdoa定位
  47. 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());
  48. switch(lm[0].m_loc_type){
  49. case LDT_TOF:
  50. if(vp.size()==4)
  51. {
  52. m_d.grow().reset().set_source(lm[0],lm[1]);
  53. flag = true;
  54. }
  55. if(vp.size()==2 && lm[0].m_card_ct - last_ct() == 1)
  56. {
  57. m_d.grow().reset().set_source(lm[0]);
  58. flag = true;
  59. }
  60. if(flag)
  61. {
  62. if(!select_solution(vp,lm[0].m_sit.get(),lp))
  63. {
  64. m_cur_fit.reset();
  65. }
  66. }
  67. break;
  68. case LDT_PDOA:
  69. select_pdoa_solution_impl(vp, lm, lp);
  70. break;
  71. }
  72. m_ct = lm[0].m_card_ct;
  73. return lp;
  74. }
  75. bool select_point_object::select_pdoa_solution_impl(const std::vector<point> vp, const std::vector<loc_message>& lm, loc_point& lp)
  76. {
  77. switch(get_algo_index(lm[0].tool_index())){
  78. case 6:
  79. return select_pdoa_1d_solution(vp, lm, lp);
  80. break;
  81. case 7:
  82. return select_pdoa_2d_solution(vp, lm, lp);
  83. break;
  84. case 8:
  85. return select_pdoa_3d_solution(vp, lm, lp);
  86. break;
  87. }
  88. return false;
  89. }
  90. /*
  91. * 当下井方向选解策略
  92. *
  93. * */
  94. bool select_point_object::select_pdoa_solution(const std::vector<point> vp, const std::vector<loc_message>& lm, loc_point&lp, const float& pdoa)
  95. {
  96. if(1 == vp.size())
  97. {
  98. bool dir = (pdoa > EPS);
  99. 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);
  100. if(lm[0].m_sit->m_ant[0].x == lm[0].m_sit->m_ant[1].x)
  101. {
  102. if(0 == lm[0].m_sit->m_pdoa_direction){
  103. if(dir){
  104. if(vp[0].x > lm[0].m_sit->m_ant[0].x){
  105. lp.set(vp[0]);
  106. lp.m_useless = true;
  107. }else{
  108. logn_warn(3, "[pdoa] solution is not correct, card_id=%d", lm[0].m_card_id);
  109. lp.m_useless = false;
  110. }
  111. }else{
  112. if(vp[0].x < lm[0].m_sit->m_ant[0].x){
  113. lp.set(vp[0]);
  114. lp.m_useless = true;
  115. }else{
  116. logn_warn(3, "[pdoa] solution is not correct, card_id=%d", lm[0].m_card_id);
  117. lp.m_useless = false;
  118. }
  119. }
  120. }else{
  121. if(dir){
  122. if(vp[0].x < lm[0].m_sit->m_ant[0].x){
  123. lp.set(vp[0]);
  124. lp.m_useless = true;
  125. }else{
  126. lp.m_useless = false;
  127. }
  128. }else{
  129. if(vp[0].x > lm[0].m_sit->m_ant[0].x){
  130. lp.set(vp[0]);
  131. lp.m_useless = true;
  132. }else{
  133. lp.m_useless = false;
  134. }
  135. }
  136. }
  137. }else{
  138. logn_info(3, "[pdoa] select one solution, card_id=%d", lm[0].m_card_id);
  139. if(dir){
  140. }
  141. }
  142. return lp.m_useless;
  143. }else if(2 == vp.size()){
  144. // select one solution from two solution by reader and phase direction
  145. 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);
  146. bool dir = (pdoa > EPS);
  147. int max = -1, min = -1;
  148. if(0 == lm[0].m_sit->m_pdoa_direction)
  149. {
  150. if(lm[0].m_sit->m_ant[0].x == lm[0].m_sit->m_ant[1].x){
  151. 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));
  152. }else if(lm[0].m_sit->m_ant[0].y == lm[0].m_sit->m_ant[1].y){
  153. 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));
  154. }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)){
  155. 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));
  156. }
  157. }else{
  158. if(lm[0].m_sit->m_ant[0].x == lm[0].m_sit->m_ant[1].x){
  159. // 分站天线在竖直巷道
  160. 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));
  161. }else if(lm[0].m_sit->m_ant[0].y == lm[0].m_sit->m_ant[1].y){
  162. // 分站天线在水平巷道
  163. 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));
  164. }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)){
  165. 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));
  166. }
  167. }
  168. 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);
  169. }
  170. return true;
  171. }
  172. // 当出井方向切换分站选解
  173. bool select_point_object::select_pdoa_solution2(const std::vector<point> vp, const std::vector<loc_message>& lm, loc_point&lp, const float& pdoa)
  174. {
  175. if(1 == vp.size())
  176. {
  177. bool dir = (pdoa > EPS);
  178. 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);
  179. if(lm[0].m_sit->m_ant[0].x == lm[0].m_sit->m_ant[1].x)
  180. {
  181. if(0 == lm[0].m_sit->m_pdoa_direction){
  182. if(dir){
  183. if(vp[0].x > lm[0].m_sit->m_ant[0].x){
  184. lp.set(vp[0]);
  185. lp.m_useless = true;
  186. }else{
  187. logn_warn(3, "[pdoa] solution is not correct, card_id=%d", lm[0].m_card_id);
  188. lp.m_useless = false;
  189. }
  190. }else{
  191. if(vp[0].x < lm[0].m_sit->m_ant[0].x){
  192. lp.set(vp[0]);
  193. lp.m_useless = true;
  194. }else{
  195. logn_warn(3, "[pdoa] solution is not correct, card_id=%d", lm[0].m_card_id);
  196. lp.m_useless = false;
  197. }
  198. }
  199. }else{
  200. if(dir){
  201. if(vp[0].x < lm[0].m_sit->m_ant[0].x){
  202. lp.set(vp[0]);
  203. lp.m_useless = true;
  204. }else{
  205. lp.m_useless = false;
  206. }
  207. }else{
  208. if(vp[0].x > lm[0].m_sit->m_ant[0].x){
  209. lp.set(vp[0]);
  210. lp.m_useless = true;
  211. }else{
  212. lp.m_useless = false;
  213. }
  214. }
  215. }
  216. }else{
  217. logn_info(3, "[pdoa] select one solution, card_id=%d", lm[0].m_card_id);
  218. if(dir){
  219. }
  220. }
  221. return lp.m_useless;
  222. }else if(2 == vp.size()){
  223. // select one solution from two solution by reader and phase direction
  224. 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);
  225. bool dir = (pdoa > EPS);
  226. int max = -1, min = -1;
  227. if(lm[0].m_sit->m_ant[0].x == lm[0].m_sit->m_ant[1].x){
  228. 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));
  229. }else if(lm[0].m_sit->m_ant[0].y == lm[0].m_sit->m_ant[1].y){
  230. 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));
  231. }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)){
  232. 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));
  233. }
  234. 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);
  235. }
  236. return true;
  237. }
  238. /*bool select_point_object::select_pdoa_1d_solution(const std::vector<point> vp, const std::vector<loc_message>& lm, loc_point& lp)
  239. {
  240. uint64_t id = lm[0].m_card_type;
  241. id = ((id<<32) | lm[0].m_card_id);
  242. auto card = card_list::instance()->get(id);
  243. double dist_tof = lm[0].m_num_ticks * 15.65 * 2.996 * 1e-4;
  244. if((card->m_buff_size != 100 || dist_tof < SAFE) && fabs(lm[0].m_poa[1] - 10.0) < 1E-4){
  245. return false;
  246. }
  247. int idx = lm[0].tool_index();
  248. uint8_t type = idx>>4;
  249. uint8_t dim = idx&0x03;
  250. idx = type*3 + dim - 1;
  251. if(card->m_buff_size == 100 && dist_tof > SAFE && fabs(lm[0].m_poa[1] - 10.0) < 1E-4){
  252. lp.x = card->m_last_point.x;
  253. lp.y = card->m_last_point.y;
  254. double diff_time = (lm[0].m_loc_time - card->m_last_recv_time)*1.0/1000.0;
  255. double speed = get_speed(lp, card->m_last_point, diff_time) * lm[0].m_sit->m_scale;
  256. if(speed > 15.0){
  257. lp.m_useless = false;
  258. return false;
  259. }
  260. lp.m_useless = true;
  261. 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);
  262. card->m_last_pdoa_diff = card->m_pdoa_diff;
  263. card->m_last_ct = lm[0].m_card_ct;
  264. card->m_last_dist = dist_tof;
  265. card->m_cb_point.push_back(lp);
  266. card->m_last_site_id = lm[0].m_sit->m_id;
  267. card->m_last_site_dir = lm[0].m_sit->m_pdoa_direction;
  268. card->m_last_recv_time = lm[0].m_loc_time;
  269. card->m_last_point.x = lp.x;
  270. card->m_last_point.y = lp.y;
  271. lp.m_speed = card->m_speed = 0;
  272. return true;
  273. }
  274. card->m_pdoa_diff = get_pdoa(lm[0].m_poa, lm[0].m_sit->m_pdoa_offset);
  275. 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);
  276. // after a long time,there is not recvied data, then reset pdoa list
  277. 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){
  278. 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);
  279. card->clear();
  280. }
  281. //first adjust, first 5 frame, not output located point
  282. uint16_t ct = lm[0].m_card_ct;
  283. if(card->m_buff_size < 5){
  284. card->m_cb_pdoa.push_back(card->m_pdoa_diff);
  285. ++card->m_buff_size;
  286. card->m_cb_tof.push_back(dist_tof);
  287. card->m_last_ct = ct;
  288. card->m_last_dist = dist_tof;
  289. card->m_last_recv_time = lm[0].m_loc_time;
  290. return false;
  291. }
  292. // choose 3 poa's direction as the card's direction
  293. if(5 == card->m_buff_size){
  294. card->m_buff_size = 100;
  295. int positive = 0;
  296. for(int i = 0;i < 5; ++i){
  297. if(card->m_cb_pdoa[i] > 0){
  298. ++positive;
  299. }
  300. }
  301. if(positive >= 3){
  302. for(int i = 0; i < 5; ++i){
  303. if(card->m_cb_pdoa[i] < 0){
  304. card->m_cb_pdoa[i] = -1.0*card->m_cb_pdoa[i];
  305. }
  306. }
  307. }else{
  308. for(int i = 0;i < 5;++i){
  309. if(card->m_cb_pdoa[i] > 0){
  310. card->m_cb_pdoa[i] = -1.0*card->m_cb_pdoa[i];
  311. }
  312. }
  313. }
  314. }
  315. // tof filter
  316. int ct_offset = -1;
  317. float offset = 0.0f;
  318. ct_offset = ct - card->m_last_ct;
  319. offset = card->m_cb_tof[4] - dist_tof;
  320. if(1 == ct_offset)
  321. {
  322. if(offset < 0){
  323. offset = -1.0*offset;
  324. }
  325. // need call opt way
  326. if(offset > 15){
  327. // illeglal tof
  328. 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]);
  329. return false;
  330. }
  331. }
  332. card->m_last_dist = dist_tof;
  333. //card->m_cb_tof.push_back(dist_tof);
  334. 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]);
  335. //pdoa meadian filter
  336. std::array<float, 5> pdoa = {0};
  337. for(int i = 0; i < 5; ++i){
  338. pdoa[i] = card->m_cb_pdoa[i];
  339. }
  340. std::sort(pdoa.begin(), pdoa.end());
  341. float meadian_pdoa = pdoa[2];
  342. 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]);
  343. float cur_pdoa = card->m_pdoa_diff;
  344. bool change = false;
  345. if(lm[0].m_loc_time - card->m_last_recv_time < 30*1000){
  346. if(card->m_last_site_id !=0 && card->m_last_site_id != lm[0].m_sit->m_id){
  347. // pdoa change from site A to site B
  348. if(card->m_last_site_dir == 0 && lm[0].m_sit->m_pdoa_direction == 0){
  349. change = true;
  350. }else if(card->m_last_site_dir == 0 && lm[0].m_sit->m_pdoa_direction == 1){
  351. // keep same direction
  352. }else if(card->m_last_site_dir == 1 && lm[0].m_sit->m_pdoa_direction == 0){
  353. // keep same direction
  354. }else if(card->m_last_site_dir == 1 && lm[0].m_sit->m_pdoa_direction == 1){
  355. change = true;
  356. }
  357. if(change){
  358. for(int i = 0;i < 5; ++i){
  359. card->m_cb_pdoa[i] *= -1.0;
  360. }
  361. }
  362. // 下面逻辑判断当前pdoa值是否有异常,如有异常就改变方向
  363. int same_direction = 0;
  364. for(int i = 0;i < 5;++i){
  365. if(card->m_cb_pdoa[i] * cur_pdoa > 0){
  366. same_direction++;
  367. }
  368. }
  369. if(same_direction < 3){
  370. cur_pdoa*=-1;
  371. }
  372. 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));
  373. card->m_cb_pdoa.push_back(cur_pdoa);
  374. card->m_cb_tof.push_back(dist_tof);
  375. // 定位退出
  376. if(!save_pdoa_1d(card, vp, lm, lp, cur_pdoa)){
  377. return false;
  378. }
  379. return true
  380. }
  381. }
  382. // 5 meter away filter, abnormal poa
  383. //bool is_opposite = false;
  384. if(dist_tof > SAFE)
  385. {
  386. int same_direction = 0;
  387. for(int i = 0;i< 5;++i){
  388. if(card->m_cb_pdoa[i] * cur_pdoa > 0){
  389. same_direction++;
  390. }
  391. }
  392. if(same_direction < 3){
  393. 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);
  394. float last_k = 0.0f, curr_k = 0.0f, llast_k = 0.0f;
  395. llast_k = card->m_cb_tof[3] - card->m_cb_tof[2];
  396. last_k = card->m_cb_tof[4] - card->m_cb_tof[3];
  397. curr_k = dist_tof - card->m_cb_tof[4];
  398. if(curr_k > 0 && last_k < 0 && llast_k < 0)
  399. {
  400. // find the site
  401. logn_info(3, "[pdoa] card has cross the site, card_id=%d, ct=%d", lm[0].m_card_id, lm[0].m_card_ct);
  402. // 缓存切换方向
  403. }else{
  404. card->m_cb_pdoa.push_back(cur_pdoa);
  405. card->m_cb_tof.push_back(cur_tof);
  406. // 定位退出
  407. if(!save_pdoa_1d(card, vp, lm, lp, cur_pdoa)){
  408. return false;
  409. }
  410. return true
  411. }
  412. }
  413. }else{
  414. // judge the position of site
  415. 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);
  416. float last_k = 0.0f, curr_k = 0.0f, llast_k = 0.0f;
  417. llast_k = card->m_cb_tof[3] - card->m_cb_tof[2];
  418. last_k = card->m_cb_tof[4] - card->m_cb_tof[3];
  419. curr_k = dist_tof - card->m_cb_tof[4];
  420. if(curr_k > 0 && last_k < 0 && llast_k < 0)
  421. {
  422. // find the site
  423. logn_info(3, "[pdoa] card has cross the site, card_id=%d, ct=%d", lm[0].m_card_id, lm[0].m_card_ct);
  424. for(int i = 0; i < 5;++i)
  425. {
  426. card->m_cb_pdoa[i] = 100;
  427. }
  428. //如果当前值方向和中值方向相同了,认为切了方向,因为距离信息当前方向和中值方向应该不同
  429. if(((0.0 - card->m_pdoa_diff) < EPS) == ((0.0 - meadian_pdoa) < EPS))
  430. {
  431. card->m_pdoa_diff = -card->m_pdoa_diff;
  432. }
  433. }
  434. }
  435. 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]);
  436. card->m_cb_tof.push_back(dist_tof);
  437. card->m_cb_pdoa.push_back(card->m_pdoa_diff);
  438. if(!save_pdoa_1d(card, vp, lm, lp, cur_pdoa)){
  439. return false;
  440. }
  441. return true;
  442. }*/
  443. bool select_point_object::select_pdoa_1d_solution(const std::vector<point> vp, const std::vector<loc_message>& lm, loc_point& lp)
  444. {
  445. uint64_t id = lm[0].m_card_type;
  446. id = ((id<<32) | lm[0].m_card_id);
  447. auto card = card_list::instance()->get(id);
  448. double dist = lm[0].m_num_ticks * 15.65 * 2.996 * 1e-4;
  449. int idx = lm[0].tool_index();
  450. uint8_t type = idx>>4;
  451. uint8_t dim = idx&0x03;
  452. idx = type*3 + dim - 1;
  453. double pdoa = get_pdoa(lm[0].m_poa, lm[0].m_sit->m_pdoa_offset);
  454. 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);
  455. double dt = (lm[0].m_loc_time - card->m_last_recv_time)*1.0/1000.0;
  456. double speed = fabs(dist - card->m_last_dist)/dt;
  457. if(card->m_last_recv_time > 0 && fabs(dt) > 30.0)
  458. {
  459. // 直接定位
  460. 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);
  461. card->m_last_recv_time = lm[0].m_loc_time;
  462. return false;
  463. }
  464. card->m_last_recv_time = lm[0].m_loc_time;
  465. int n = card->m_vtp_dist.size();
  466. bool change_site = false;
  467. bool over_site = false;
  468. //切换基站,默认取正值
  469. if(lm[0].m_sit->m_id != card->m_last_site_id){
  470. // 切换基站要考虑两种情况
  471. // 1)入井方向的切换
  472. if(card->m_cb_stream_idx[0] < lm[0].m_sit->m_down_stream_idx){
  473. if(lm[0].m_sit->m_pdoa_direction == 0){
  474. pdoa *= (pdoa > 0?1:-1);
  475. }else{
  476. pdoa *= (pdoa < 0?-1:1);
  477. }
  478. }else{
  479. // 2)出井方向的切换
  480. if(lm[0].m_sit->m_pdoa_direction == 0){
  481. pdoa *= (pdoa < 0?1:-1);
  482. }else{
  483. pdoa *= (pdoa > 0?-1:1);
  484. }
  485. }
  486. if(!select_pdoa_solution2(vp, lm, lp, pdoa)){
  487. return false;
  488. }
  489. card->m_cb_stream_idx.push_back(lm[0].m_sit->m_down_stream_idx);
  490. card->m_last_site_id = lm[0].m_sit->m_id;
  491. card->m_vtp_dist.clear();
  492. card->m_vtp_dist.resize(0);
  493. change_site = true;
  494. card->m_over_site = false;
  495. 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);
  496. }else if(!card->m_over_site && n >= 3){
  497. // 过分站逻辑
  498. if(!select_pdoa_solution2(vp, lm, lp, pdoa)){
  499. return false;
  500. }
  501. //double dd = dist - card->m_last_dist;
  502. double d = lp.dist(card->m_last_point)*lm[0].m_sit->m_scale;
  503. 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);
  504. // 如果选出的解是正确解,即距离和测距距离相等
  505. double k1 = (card->m_vtp_dist[n-2] - card->m_vtp_dist[n-1])/dt;
  506. double k2 = (card->m_vtp_dist[n-1] - dist)/dt;
  507. logn_info(3, "[pdoa] card_id=%d, k1=%.2f, k2=%.2f, d=%.2f", lm[0].m_card_id, k1, k2, d);
  508. if(((k1 > 1 && k2 < -1) || (k1 < -1 && k2 > 1)) ||(k1*k2 < 0 && fabs(d - dist - card->m_last_dist) < 2.0)){
  509. over_site = true;
  510. card->m_over_site = true;
  511. //过基站还要分以下两种情况:
  512. //1)入井时的从正到负
  513. //2)出井时的从负到正
  514. 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]);
  515. if(card->m_cb_stream_idx[1] > card->m_cb_stream_idx[0]){
  516. //1)入井时的从正到负
  517. pdoa *= (pdoa>0?-1:1);
  518. /*if(lm[0].m_sit->m_pdoa_direction == 0){
  519. pdoa *= (pdoa<0?-1:1);
  520. }else{
  521. pdoa *= (pdoa>0?1:-1);
  522. }*/
  523. }else{
  524. //2)出井时的从负到正
  525. pdoa *= (pdoa<0?-1:1);
  526. /*if(lm[0].m_sit->m_pdoa_direction == 0){
  527. pdoa *= (pdoa<0?-1:1);
  528. }else{
  529. pdoa *= (pdoa>0?-1:1);
  530. }*/
  531. }
  532. if(!select_pdoa_solution2(vp, lm, lp, pdoa)){
  533. return false;
  534. }
  535. }
  536. }
  537. // 如果没有切换基站且没有过基站
  538. if(!change_site && !over_site){
  539. if(!select_pdoa_solution2(vp, lm, lp, pdoa)){
  540. return false;
  541. }
  542. double d = lp.dist(card->m_last_point)*lm[0].m_sit->m_scale;
  543. 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);
  544. if(fabs(d - fabs(dist - card->m_last_dist)) > 2.0){
  545. if(!card->m_last_point.empty()&&(lm[0].m_sit->m_id == card->m_last_site_id)){
  546. int idx = 0;
  547. double min = 999999.0;
  548. for(size_t i = 0;i < vp.size();++i){
  549. double d = vp[i].dist(card->m_last_point)*lm[0].m_sit->m_scale;
  550. if(fabs(d - speed*dt) < min){
  551. idx = i;
  552. min = fabs(d - speed*dt);
  553. }
  554. }
  555. lp.set(vp[idx]);
  556. }
  557. }
  558. d = lp.dist(card->m_last_point)*lm[0].m_sit->m_scale;
  559. /*if(fabs(d-dist) > 0.5 && !card->m_last_point.empty()){
  560. 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);
  561. return false;
  562. }*/
  563. logn_info(3, "[pdoa] unilateral processing, card_id=%d", lm[0].m_card_id);
  564. }
  565. lp.m_useless = true;
  566. 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);
  567. 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);
  568. if (!(card->m_isVehicleMap&&card->is_person()))
  569. {
  570. card->m_last_pdoa_diff = pdoa;
  571. card->m_last_ct = lm[0].m_card_ct;
  572. card->m_last_dist = dist;
  573. card->m_last_site_id = lm[0].m_sit->m_id;
  574. card->m_last_site_dir = lm[0].m_sit->m_pdoa_direction;
  575. card->m_last_point.x = lp.x;
  576. card->m_last_point.y = lp.y;
  577. lp.m_speed = card->m_speed = speed;
  578. card->m_cb_point.push_back(lp);
  579. card->m_vtp_dist.push_back(dist);
  580. }
  581. return true;
  582. }
  583. bool select_point_object::select_pdoa_2d_solution(const std::vector<point> vp, const std::vector<loc_message>& lm, loc_point& lp)
  584. {
  585. logn_info(3, "[pdoa] begin select 2d solution, vp's size=%d", vp.size());
  586. int i = 1;
  587. for(auto it = vp.cbegin(); it != vp.cend();++it){
  588. logn_info(3, "[pdoa] useless %d : card_id=%d, x=%.4f, y=%.4f", i, lm[0].m_card_id,(*it).x, (*it).y);
  589. ++i;
  590. }
  591. if(1 == vp.size()){
  592. lp.x = vp[0].x;
  593. lp.y = vp[0].y;
  594. lp.m_useless = true;
  595. }
  596. uint64_t id = lm[0].m_card_type;
  597. id = ((id<<32) | lm[0].m_card_id);
  598. auto card = card_list::instance()->get(id);
  599. card->m_last_point.x = lp.x;
  600. card->m_last_point.y = lp.y;
  601. return true;
  602. }
  603. bool select_point_object::select_pdoa_3d_solution(const std::vector<point> vp, const std::vector<loc_message>& lm, loc_point& lp)
  604. {
  605. return true;
  606. }
  607. int select_point_object::get_algo_index(const int& idx)
  608. {
  609. uint8_t index = 0;
  610. uint8_t type = idx>>4;
  611. uint8_t dim = idx & 0x03;
  612. index = type*3 + dim - 1;
  613. log_info("[pdoa] algo=%d", index);
  614. return index;
  615. }
  616. double select_point_object::get_speed(const loc_point& p, const point& lp, const double& offset)
  617. {
  618. double speed = -1.0;
  619. if(!(p.x <= EPS && p.y <= EPS)){
  620. speed = sqrt(pow(p.x - lp.x, 2) + pow(p.y - lp.y, 2))/offset;
  621. }
  622. 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);
  623. return speed;
  624. }
  625. double select_point_object::get_distance(const int& rid, const int& lrid)
  626. {
  627. double d = 0.0;
  628. /*auto cs = sit_list()->instance()->get(rid);
  629. auto ls = sit_list()->instance()->get(lrid);
  630. if(cs&&ls){
  631. d = cs.dist(ls);
  632. log_info("[pdoa] get distance from current site %d to last site %d", rid, lrid);
  633. }*/
  634. return d;
  635. }
  636. float select_point_object::get_pdoa(const double poa[], const double& offset)
  637. {
  638. if(poa == nullptr){
  639. return -10.0;
  640. }
  641. float poa1 = poa[0];
  642. float poa2 = poa[1];
  643. //float poa3 = poa[2];
  644. float pdoa = poa2 - poa1 - offset;
  645. while(pdoa >= TPI){
  646. pdoa -= TPI;
  647. }
  648. while(pdoa < 0){
  649. pdoa += TPI;
  650. }
  651. pdoa -= PI;
  652. return pdoa;
  653. }
  654. int select_point_object::find_last(int start)
  655. {
  656. for(int i=start,len=m_d.size();i<len;i++)
  657. {
  658. if(m_d(i).cl()>0)
  659. return i;
  660. }
  661. return -1;
  662. }
  663. int select_point_object::find_first(int start)
  664. {
  665. for(int i=start,len=m_d.size();i<len;i++)
  666. {
  667. if(m_d[i].cl()>0)
  668. return i;
  669. }
  670. return -1;
  671. }
  672. /*
  673. * 拟合过滤
  674. *
  675. * param
  676. * loc_point& c 最终保存点
  677. * const std::vector<point>& vp 可能解
  678. * const double scale 比例尺
  679. *
  680. * return
  681. *
  682. *
  683. * */
  684. bool select_point_object::filter_by_fit(loc_point & c,const std::vector<point> & vp,const double scale)
  685. {
  686. fit_result * fit = get_best_fit();
  687. if(fit==nullptr || m_begin==nullptr || fit->ke>2)
  688. return false;
  689. loc_point &f = *m_begin;
  690. std::array<solpoint,4> v;
  691. int cnt = vp.size();
  692. for(int i=0;i<cnt;i++)
  693. {
  694. v[i].set_sol(vp[i],fabs(fit->testk(c.m_time/1000.,f.dist_direct(vp[i]))));
  695. }
  696. std::sort(&v[0],&v[0]+cnt);
  697. double a = getA(fit,scale,v[1].score()-v[0].score());
  698. if(a<0)
  699. return false;
  700. if(!filter_by_acc(c,v,a))
  701. {
  702. c.set_cl(0);
  703. return true; //false?
  704. }
  705. reset_fit(vp[0].dist(v[0]));
  706. c[0]=v[0];
  707. c[1]=v[1];
  708. return true;
  709. }
  710. /*
  711. * 加速度过滤
  712. *
  713. * param
  714. * loc_point& c
  715. * std::array<solpoint, 4>& v
  716. * double e
  717. *
  718. * return
  719. *
  720. * */
  721. bool select_point_object::filter_by_acc(loc_point&c,std::array<solpoint,4>&v,double a)
  722. {
  723. if(!m_last->is_same_site(c))
  724. return true;
  725. double td=m_last->time_off(c);
  726. if(v[0].score()>a*td*td)
  727. return false;
  728. return true;
  729. }
  730. /*
  731. *
  732. * */
  733. void select_point_object::select_one_ant(loc_point &c,const std::vector<point> & vp)
  734. {
  735. int last=find_last(1);
  736. if(last>0)
  737. {
  738. loc_point&p=m_d(last);
  739. int cnt=vp.size();
  740. std::array<solpoint,4> res;
  741. //find the shortest dis
  742. for(int i=0;i<cnt;i++)
  743. res[i].set_sol(vp[i],vp[i].dist(p[0]));
  744. std::sort(&res[0],&res[0]+cnt);
  745. c[1].set(res[1]);
  746. c[0].set(res[0]);
  747. c.inc_cl(5);
  748. }
  749. }
  750. point select_point_object::select_solution0(std::vector<point> &tvp,const double scale)
  751. {
  752. loc_point&c=m_d(0);
  753. if(m_d.size()==1)
  754. {
  755. //first point ,only accpet two ants good data.
  756. if(c.cl()>0 && tvp.size()<4)
  757. {
  758. c[1]=tvp[1];
  759. return c[0]=tvp[0];
  760. }
  761. m_d.skip(1);
  762. return point(0,0);
  763. }
  764. select_solution1(c,tvp,scale);
  765. return c[0];
  766. }
  767. bool select_point_object::select_solution(const std::vector<point> &vp,const site*sit,loc_point &p)
  768. {
  769. remove_history();
  770. std::vector<point> tvp(vp.begin(),vp.end());
  771. if(vp.size()==4)
  772. {
  773. int c = 0;
  774. std::array<solpoint,4> res;
  775. for(int i=0;i<2;i++)
  776. {
  777. int x = i+2;
  778. double d=vp[i].dist(vp[x]);
  779. if(d<sit->ant_dist()*3)
  780. {
  781. res[c++].set_sol(vp[i].middle(vp[x]),d);
  782. }
  783. else
  784. {
  785. res[c++].set_sol(vp[i]);
  786. res[c++].set_sol(vp[x]);
  787. }
  788. }
  789. std::sort(&res[0],&res[0]+c);
  790. tvp.clear();
  791. for(int i=0;i<c;i++)
  792. tvp.push_back(res[i]);
  793. m_d(0).inc_cl(10);
  794. }
  795. point pt = select_solution0(tvp,sit->m_scale);
  796. if(pt.empty() || m_d.empty())
  797. return false;
  798. m_d(0).set(pt);
  799. if(!m_d(0).empty())
  800. m_d(0).m_dist=sit->dist_direct(pt);
  801. else
  802. {
  803. m_d(0).set_cl(0);
  804. if(m_last) m_d(0).m_dist=0.01*m_last->m_dist>0?1:-1;
  805. }
  806. m_d(0).m_dist1 = sit->dist_direct(pt);
  807. bool fg = revise_by_history(pt,sit,m_d(0).m_time);
  808. if(!fg)
  809. {
  810. 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);
  811. return false;
  812. }
  813. if(!card_path::inst().is_at_path(pt))
  814. {
  815. m_d(0).set_cl(0);
  816. 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);
  817. return false;
  818. }
  819. m_last=&m_d(0);
  820. if(m_line.empty() && m_d.size()>=2 && !make_line())
  821. return false;
  822. if(!m_line.contain(m_d(0),0.01) || (m_begin && !m_line.contain(m_begin->m_sol[0], 0.01)))
  823. {
  824. m_fitk.reset_data();
  825. m_fita.reset_data();
  826. m_begin=m_last=nullptr;
  827. int i0=find_last(1);
  828. if(i0==-1)
  829. return false;
  830. std::vector<point> path=card_path::inst().find_path(m_d(i0),m_d(0));
  831. m_d.skip(m_d.size()-i0);
  832. if(path.empty())
  833. {
  834. m_line.clear();
  835. return false;
  836. }
  837. m_line.set(path.back(),m_d(0));
  838. }
  839. if(!m_begin)
  840. {
  841. int idx=find_first(0);
  842. if(idx>=0) m_begin=&m_d[idx];
  843. }
  844. if(!m_last)
  845. {
  846. int idx=find_last(0);
  847. if(idx>=0) m_last=&m_d(idx);
  848. }
  849. if(m_begin && m_d(0).cl())
  850. {
  851. int lastID1=find_last(1);
  852. int lastID2=-1;
  853. if(lastID1!=-1)
  854. lastID2=find_last(lastID1+1);
  855. if(lastID2!=-1)
  856. {
  857. double t0=m_last->m_time/1000., t1=m_d(lastID1).m_time/1000., t2=m_d(lastID2).m_time/1000.;
  858. double d0=m_begin->loc_dist(*m_last), d1=m_begin->loc_dist(m_d(lastID1)), d2=m_begin->loc_dist(m_d(lastID2));
  859. double k1=(d1-d0)/(t1-t0), k2=(d2-d1)/(t2-t1);
  860. if(t0-t1<5 && t1-t2<5 && fabs(k2-k1)<0.5)
  861. {
  862. double tbegin = t0-3;
  863. while(tbegin<t1+0.5)
  864. tbegin=tbegin+1;
  865. double tk=(d0-d1)/(t0-t1), tb=d1-tk*t1; //d1+(d0-d1)/(t0-t1)*(t-t1)
  866. for(double ti=tbegin;ti<t0;ti=ti+1)
  867. {
  868. m_fitk.add(ti, tk*ti+tb);
  869. }
  870. }
  871. }
  872. m_fitk.add(m_last->m_time/1000.,m_begin->loc_dist(*m_last));
  873. if(m_d.size()>1)
  874. {
  875. int pre=find_last(1);
  876. if(pre>0)
  877. {
  878. m_fita.add(m_d(0).m_time/1000.,m_begin->loc_dist(m_d(0))-m_begin->loc_dist(m_d(pre)));
  879. }
  880. }
  881. }
  882. p.set(pt);
  883. save_k();
  884. p.m_useless=fg;
  885. return true;
  886. }
  887. bool select_point_object::make_line()
  888. {
  889. int i0=-1,i1=-1;
  890. if(-1==(i0=find_last(0)))
  891. return false;
  892. if(-1==(i1=find_last(i0+1)))
  893. return false;
  894. m_line.set(m_d(i0),m_d(i1));
  895. return true;
  896. }
  897. void select_point_object::remove_history()
  898. {
  899. loc_point&b=m_d(0);
  900. if(m_d.size()>120 || (m_d.size()>2 && m_d(1).time_off(b)>max_histime))
  901. {
  902. m_d.skip_if([&b,this](loc_point&p){
  903. return p.time_off(b)>max_histime;
  904. });
  905. m_fitk.reset_data();
  906. m_fita.reset_data();
  907. m_cur_fit.reset();
  908. m_begin=m_last=nullptr;
  909. int idx=find_first(0);
  910. if(idx<0)
  911. return;
  912. m_begin=&m_d[idx];
  913. idx=find_last(1);
  914. m_last=&m_d(idx);
  915. double dist=0,dist2=0;
  916. for(int len=std::min(15,m_d.size()-1),i=len;i>0;i--)
  917. {
  918. if(!m_d(i).cl())
  919. continue;
  920. int lastID1=find_last(i+1);
  921. int lastID2=-1;
  922. if(lastID1!=-1)
  923. lastID2=find_last(lastID1+1);
  924. if(lastID2!=-1)
  925. {
  926. double t0=m_d(i).m_time/1000., t1=m_d(lastID1).m_time/1000., t2=m_d(lastID2).m_time/1000.;
  927. double d0=m_begin->loc_dist(m_d(i)[0]), d1=m_begin->loc_dist(m_d(lastID1)[0]),
  928. d2=m_begin->loc_dist(m_d(lastID2)[0]);
  929. double k1=(d1-d0)/(t1-t0), k2=(d2-d1)/(t2-t1);
  930. if(t0-t1<5 && t1-t2<5 && fabs(k2-k1)<0.5)
  931. {
  932. double tbegin = t0-3;
  933. while(tbegin<t1+0.5)
  934. tbegin=tbegin+1;
  935. double tk=(d0-d1)/(t0-t1), tb=d1-tk*t1; //d1+(d0-d1)/(t0-t1)*(t-t1)
  936. for(double ti=tbegin;ti<t0;ti=ti+1)
  937. {
  938. m_fitk.add(ti, tk*ti+tb);
  939. }
  940. }
  941. }
  942. dist=m_begin->loc_dist(m_d(i)[0]);
  943. m_fitk.add(m_d(i).m_time/1000.,dist);
  944. if(i==len)
  945. continue;
  946. m_fita.add(m_d(i).m_time/1000.,dist-dist2);
  947. dist2=dist;
  948. }
  949. save_k();
  950. }
  951. }
  952. void select_point_object::save_k()
  953. {
  954. const fit_result*fk=best_fit_raw(0,4);
  955. if(!fk)
  956. {
  957. m_cur_fit.reset();
  958. return;
  959. }
  960. m_cur_fit=*fk;
  961. fit_result&r=m_cur_fit;
  962. card_fit*fa=&m_fita[0];
  963. if(fa->is_valid() && fa->ke<0.1 && fk->k*fa->k<0)
  964. {
  965. double dk=fa->k*fa->num_point;
  966. r.ka=fa->k;
  967. if((fk->k+dk)*fk->k<0)
  968. r.k=0;
  969. else
  970. r.k+=dk;
  971. double y=fk->k*m_fitk(0).x+fk->kb;
  972. r.kb=y-m_fitk(0).x*r.k;
  973. }
  974. }
  975. fit_result* select_point_object::best_fit_raw(int num_point,int start,int last)
  976. {
  977. card_fit*fit = nullptr;
  978. start = std::max(start,0);
  979. last = std::min(last,m_fitk.tool_size());
  980. if(last == -1)
  981. last = m_fitk.tool_size();
  982. for(int i = start; i < last; i++)
  983. {
  984. if(!m_fitk[i].is_valid())
  985. continue;
  986. if(m_fitk[i].num_point < num_point)
  987. continue;
  988. if(fit == nullptr)
  989. {
  990. fit = &m_fitk[i];
  991. continue;
  992. }
  993. if(fit->ke > m_fitk[i].ke)
  994. {
  995. fit = &m_fitk[i];
  996. }
  997. }
  998. return fit;
  999. }
  1000. select_tool::~select_tool()
  1001. {
  1002. if(m_spo !=nullptr)
  1003. delete m_spo;
  1004. }
  1005. loc_point select_tool_person_1::select_solution(const std::vector<point> vp,const std::vector<loc_message>&lm)
  1006. {
  1007. loc_point lp;
  1008. //select point.
  1009. uint8_t idx = 0;
  1010. uint8_t type = lm[0].tool_index()>>4;
  1011. uint8_t dim = lm[0].tool_index() & 0x03;
  1012. idx = type*3 + dim - 1;
  1013. //logn_info(3, "[pdoa] card_id=%d, idx=%d, dim=%d", lm[0].m_card_id, idx, dim);
  1014. if(idx == 0)
  1015. {
  1016. if(m_spo==nullptr)
  1017. m_spo = new person_point_filter(this);
  1018. lp=m_spo->select_solution_impl(vp,lm);
  1019. }
  1020. else if (idx == 2)
  1021. {
  1022. //for now..
  1023. //m_spo = new person_point_filter();
  1024. //lp=m_spo->select_solution_impl(vp,lm);
  1025. }else if(6 == idx){
  1026. // pdoa一维定位
  1027. //logn_info(3, "[pdoa] person, select_solution 1d, tool_index=%d", idx);
  1028. if(nullptr == m_spo){
  1029. m_spo= new person_point_filter(this);
  1030. }
  1031. lp = m_spo->select_solution_impl(vp, lm);
  1032. }else if(7 == idx){
  1033. // logn_info(3, "[pdoa] person, select_solution 2d, tool_index=%d", idx);
  1034. // pdoa二维定位
  1035. if(nullptr == m_spo){
  1036. m_spo = new person_point_filter(this);
  1037. }
  1038. lp = m_spo->select_solution_impl(vp, lm);
  1039. }else if(3 == idx){
  1040. }else if(4 == idx){
  1041. }else if(5 == idx){
  1042. }
  1043. else
  1044. {}
  1045. return lp;
  1046. }
  1047. loc_point select_tool_car_1::select_solution(const std::vector<point> vp,const std::vector<loc_message>&lm)
  1048. {
  1049. loc_point lp;
  1050. //select point.
  1051. uint8_t idx = 0;
  1052. uint8_t type = lm[0].tool_index()>>4;
  1053. uint8_t dim = lm[0].tool_index() & 0x03;
  1054. idx = type*3 + dim - 1;
  1055. if(idx == 0)
  1056. {
  1057. if(m_spo==nullptr)
  1058. m_spo = new car_point_filter(this);
  1059. lp=m_spo->select_solution_impl(vp,lm);
  1060. }
  1061. else if (idx == 2)
  1062. {
  1063. //for now..
  1064. //m_spo = new car_point_filter();
  1065. //lp=m_spo->select_solution_impl(vp,lm);
  1066. }else if(6 == idx){
  1067. // pdoa一维定位
  1068. if(nullptr == m_spo){
  1069. m_spo = new car_point_filter(this);
  1070. }
  1071. lp = m_spo->select_solution_impl(vp, lm);
  1072. }else if(7 == idx){
  1073. // pdoa二维定位
  1074. if(nullptr == m_spo)
  1075. {
  1076. m_spo = new car_point_filter(this);
  1077. }
  1078. lp = m_spo->select_solution_impl(vp, lm);
  1079. }else if(3 == idx){
  1080. }else if(4 == idx){
  1081. }else if(5 == idx){
  1082. }
  1083. else
  1084. {}
  1085. return lp;
  1086. }
  1087. select_tool_manage * select_tool_manage::instance()
  1088. {
  1089. static select_tool_manage stm;
  1090. return &stm;
  1091. }