select_tool.cpp 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264
  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. card->m_last_pdoa_diff = pdoa;
  569. card->m_last_ct = lm[0].m_card_ct;
  570. card->m_last_dist = dist;
  571. card->m_last_site_id = lm[0].m_sit->m_id;
  572. card->m_last_site_dir = lm[0].m_sit->m_pdoa_direction;
  573. card->m_last_point.x = lp.x;
  574. card->m_last_point.y = lp.y;
  575. lp.m_speed = card->m_speed = speed;
  576. card->m_cb_point.push_back(lp);
  577. card->m_vtp_dist.push_back(dist);
  578. return true;
  579. }
  580. bool select_point_object::select_pdoa_2d_solution(const std::vector<point> vp, const std::vector<loc_message>& lm, loc_point& lp)
  581. {
  582. logn_info(3, "[pdoa] begin select 2d solution, vp's size=%d", vp.size());
  583. int i = 1;
  584. for(auto it = vp.cbegin(); it != vp.cend();++it){
  585. logn_info(3, "[pdoa] useless %d : card_id=%d, x=%.4f, y=%.4f", i, lm[0].m_card_id,(*it).x, (*it).y);
  586. ++i;
  587. }
  588. if(1 == vp.size()){
  589. lp.x = vp[0].x;
  590. lp.y = vp[0].y;
  591. lp.m_useless = true;
  592. }
  593. uint64_t id = lm[0].m_card_type;
  594. id = ((id<<32) | lm[0].m_card_id);
  595. auto card = card_list::instance()->get(id);
  596. card->m_last_point.x = lp.x;
  597. card->m_last_point.y = lp.y;
  598. return true;
  599. }
  600. bool select_point_object::select_pdoa_3d_solution(const std::vector<point> vp, const std::vector<loc_message>& lm, loc_point& lp)
  601. {
  602. return true;
  603. }
  604. int select_point_object::get_algo_index(const int& idx)
  605. {
  606. uint8_t index = 0;
  607. uint8_t type = idx>>4;
  608. uint8_t dim = idx & 0x03;
  609. index = type*3 + dim - 1;
  610. log_info("[pdoa] algo=%d", index);
  611. return index;
  612. }
  613. double select_point_object::get_speed(const loc_point& p, const point& lp, const double& offset)
  614. {
  615. double speed = -1.0;
  616. if(!(p.x <= EPS && p.y <= EPS)){
  617. speed = sqrt(pow(p.x - lp.x, 2) + pow(p.y - lp.y, 2))/offset;
  618. }
  619. 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);
  620. return speed;
  621. }
  622. double select_point_object::get_distance(const int& rid, const int& lrid)
  623. {
  624. double d = 0.0;
  625. /*auto cs = sit_list()->instance()->get(rid);
  626. auto ls = sit_list()->instance()->get(lrid);
  627. if(cs&&ls){
  628. d = cs.dist(ls);
  629. log_info("[pdoa] get distance from current site %d to last site %d", rid, lrid);
  630. }*/
  631. return d;
  632. }
  633. float select_point_object::get_pdoa(const double poa[], const double& offset)
  634. {
  635. if(poa == nullptr){
  636. return -10.0;
  637. }
  638. float poa1 = poa[0];
  639. float poa2 = poa[1];
  640. //float poa3 = poa[2];
  641. float pdoa = poa2 - poa1 - offset;
  642. while(pdoa >= TPI){
  643. pdoa -= TPI;
  644. }
  645. while(pdoa < 0){
  646. pdoa += TPI;
  647. }
  648. pdoa -= PI;
  649. return pdoa;
  650. }
  651. int select_point_object::find_last(int start)
  652. {
  653. for(int i=start,len=m_d.size();i<len;i++)
  654. {
  655. if(m_d(i).cl()>0)
  656. return i;
  657. }
  658. return -1;
  659. }
  660. int select_point_object::find_first(int start)
  661. {
  662. for(int i=start,len=m_d.size();i<len;i++)
  663. {
  664. if(m_d[i].cl()>0)
  665. return i;
  666. }
  667. return -1;
  668. }
  669. /*
  670. * 拟合过滤
  671. *
  672. * param
  673. * loc_point& c 最终保存点
  674. * const std::vector<point>& vp 可能解
  675. * const double scale 比例尺
  676. *
  677. * return
  678. *
  679. *
  680. * */
  681. bool select_point_object::filter_by_fit(loc_point & c,const std::vector<point> & vp,const double scale)
  682. {
  683. fit_result * fit = get_best_fit();
  684. if(fit==nullptr || m_begin==nullptr || fit->ke>2)
  685. return false;
  686. loc_point &f = *m_begin;
  687. std::array<solpoint,4> v;
  688. int cnt = vp.size();
  689. for(int i=0;i<cnt;i++)
  690. {
  691. v[i].set_sol(vp[i],fabs(fit->testk(c.m_time/1000.,f.dist_direct(vp[i]))));
  692. }
  693. std::sort(&v[0],&v[0]+cnt);
  694. double a = getA(fit,scale,v[1].score()-v[0].score());
  695. if(a<0)
  696. return false;
  697. if(!filter_by_acc(c,v,a))
  698. {
  699. c.set_cl(0);
  700. return true; //false?
  701. }
  702. reset_fit(vp[0].dist(v[0]));
  703. c[0]=v[0];
  704. c[1]=v[1];
  705. return true;
  706. }
  707. /*
  708. * 加速度过滤
  709. *
  710. * param
  711. * loc_point& c
  712. * std::array<solpoint, 4>& v
  713. * double e
  714. *
  715. * return
  716. *
  717. * */
  718. bool select_point_object::filter_by_acc(loc_point&c,std::array<solpoint,4>&v,double a)
  719. {
  720. if(!m_last->is_same_site(c))
  721. return true;
  722. double td=m_last->time_off(c);
  723. if(v[0].score()>a*td*td)
  724. return false;
  725. return true;
  726. }
  727. /*
  728. *
  729. * */
  730. void select_point_object::select_one_ant(loc_point &c,const std::vector<point> & vp)
  731. {
  732. int last=find_last(1);
  733. if(last>0)
  734. {
  735. loc_point&p=m_d(last);
  736. int cnt=vp.size();
  737. std::array<solpoint,4> res;
  738. //find the shortest dis
  739. for(int i=0;i<cnt;i++)
  740. res[i].set_sol(vp[i],vp[i].dist(p[0]));
  741. std::sort(&res[0],&res[0]+cnt);
  742. c[1].set(res[1]);
  743. c[0].set(res[0]);
  744. c.inc_cl(5);
  745. }
  746. }
  747. point select_point_object::select_solution0(std::vector<point> &tvp,const double scale)
  748. {
  749. loc_point&c=m_d(0);
  750. if(m_d.size()==1)
  751. {
  752. //first point ,only accpet two ants good data.
  753. if(c.cl()>0 && tvp.size()<4)
  754. {
  755. c[1]=tvp[1];
  756. return c[0]=tvp[0];
  757. }
  758. m_d.skip(1);
  759. return point(0,0);
  760. }
  761. select_solution1(c,tvp,scale);
  762. return c[0];
  763. }
  764. bool select_point_object::select_solution(const std::vector<point> &vp,const site*sit,loc_point &p)
  765. {
  766. remove_history();
  767. std::vector<point> tvp(vp.begin(),vp.end());
  768. if(vp.size()==4)
  769. {
  770. int c = 0;
  771. std::array<solpoint,4> res;
  772. for(int i=0;i<2;i++)
  773. {
  774. int x = i+2;
  775. double d=vp[i].dist(vp[x]);
  776. if(d<sit->ant_dist()*3)
  777. {
  778. res[c++].set_sol(vp[i].middle(vp[x]),d);
  779. }
  780. else
  781. {
  782. res[c++].set_sol(vp[i]);
  783. res[c++].set_sol(vp[x]);
  784. }
  785. }
  786. std::sort(&res[0],&res[0]+c);
  787. tvp.clear();
  788. for(int i=0;i<c;i++)
  789. tvp.push_back(res[i]);
  790. m_d(0).inc_cl(10);
  791. }
  792. point pt = select_solution0(tvp,sit->m_scale);
  793. if(pt.empty() || m_d.empty())
  794. return false;
  795. m_d(0).set(pt);
  796. if(!m_d(0).empty())
  797. m_d(0).m_dist=sit->dist_direct(pt);
  798. else
  799. {
  800. m_d(0).set_cl(0);
  801. if(m_last) m_d(0).m_dist=0.01*m_last->m_dist>0?1:-1;
  802. }
  803. m_d(0).m_dist1 = sit->dist_direct(pt);
  804. bool fg = revise_by_history(pt,sit,m_d(0).m_time);
  805. if(!fg)
  806. {
  807. 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);
  808. return false;
  809. }
  810. if(!card_path::inst().is_at_path(pt))
  811. {
  812. m_d(0).set_cl(0);
  813. 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);
  814. return false;
  815. }
  816. m_last=&m_d(0);
  817. if(m_line.empty() && m_d.size()>=2 && !make_line())
  818. return false;
  819. if(!m_line.contain(m_d(0),0.01) || (m_begin && !m_line.contain(m_begin->m_sol[0], 0.01)))
  820. {
  821. m_fitk.reset_data();
  822. m_fita.reset_data();
  823. m_begin=m_last=nullptr;
  824. int i0=find_last(1);
  825. if(i0==-1)
  826. return false;
  827. std::vector<point> path=card_path::inst().find_path(m_d(i0),m_d(0));
  828. m_d.skip(m_d.size()-i0);
  829. if(path.empty())
  830. {
  831. m_line.clear();
  832. return false;
  833. }
  834. m_line.set(path.back(),m_d(0));
  835. }
  836. if(!m_begin)
  837. {
  838. int idx=find_first(0);
  839. if(idx>=0) m_begin=&m_d[idx];
  840. }
  841. if(!m_last)
  842. {
  843. int idx=find_last(0);
  844. if(idx>=0) m_last=&m_d(idx);
  845. }
  846. if(m_begin && m_d(0).cl())
  847. {
  848. int lastID1=find_last(1);
  849. int lastID2=-1;
  850. if(lastID1!=-1)
  851. lastID2=find_last(lastID1+1);
  852. if(lastID2!=-1)
  853. {
  854. double t0=m_last->m_time/1000., t1=m_d(lastID1).m_time/1000., t2=m_d(lastID2).m_time/1000.;
  855. double d0=m_begin->loc_dist(*m_last), d1=m_begin->loc_dist(m_d(lastID1)), d2=m_begin->loc_dist(m_d(lastID2));
  856. double k1=(d1-d0)/(t1-t0), k2=(d2-d1)/(t2-t1);
  857. if(t0-t1<5 && t1-t2<5 && fabs(k2-k1)<0.5)
  858. {
  859. double tbegin = t0-3;
  860. while(tbegin<t1+0.5)
  861. tbegin=tbegin+1;
  862. double tk=(d0-d1)/(t0-t1), tb=d1-tk*t1; //d1+(d0-d1)/(t0-t1)*(t-t1)
  863. for(double ti=tbegin;ti<t0;ti=ti+1)
  864. {
  865. m_fitk.add(ti, tk*ti+tb);
  866. }
  867. }
  868. }
  869. m_fitk.add(m_last->m_time/1000.,m_begin->loc_dist(*m_last));
  870. if(m_d.size()>1)
  871. {
  872. int pre=find_last(1);
  873. if(pre>0)
  874. {
  875. m_fita.add(m_d(0).m_time/1000.,m_begin->loc_dist(m_d(0))-m_begin->loc_dist(m_d(pre)));
  876. }
  877. }
  878. }
  879. p.set(pt);
  880. save_k();
  881. p.m_useless=fg;
  882. return true;
  883. }
  884. bool select_point_object::make_line()
  885. {
  886. int i0=-1,i1=-1;
  887. if(-1==(i0=find_last(0)))
  888. return false;
  889. if(-1==(i1=find_last(i0+1)))
  890. return false;
  891. m_line.set(m_d(i0),m_d(i1));
  892. return true;
  893. }
  894. void select_point_object::remove_history()
  895. {
  896. loc_point&b=m_d(0);
  897. if(m_d.size()>120 || (m_d.size()>2 && m_d(1).time_off(b)>max_histime))
  898. {
  899. m_d.skip_if([&b,this](loc_point&p){
  900. return p.time_off(b)>max_histime;
  901. });
  902. m_fitk.reset_data();
  903. m_fita.reset_data();
  904. m_cur_fit.reset();
  905. m_begin=m_last=nullptr;
  906. int idx=find_first(0);
  907. if(idx<0)
  908. return;
  909. m_begin=&m_d[idx];
  910. idx=find_last(1);
  911. m_last=&m_d(idx);
  912. double dist=0,dist2=0;
  913. for(int len=std::min(15,m_d.size()-1),i=len;i>0;i--)
  914. {
  915. if(!m_d(i).cl())
  916. continue;
  917. int lastID1=find_last(i+1);
  918. int lastID2=-1;
  919. if(lastID1!=-1)
  920. lastID2=find_last(lastID1+1);
  921. if(lastID2!=-1)
  922. {
  923. double t0=m_d(i).m_time/1000., t1=m_d(lastID1).m_time/1000., t2=m_d(lastID2).m_time/1000.;
  924. double d0=m_begin->loc_dist(m_d(i)[0]), d1=m_begin->loc_dist(m_d(lastID1)[0]),
  925. d2=m_begin->loc_dist(m_d(lastID2)[0]);
  926. double k1=(d1-d0)/(t1-t0), k2=(d2-d1)/(t2-t1);
  927. if(t0-t1<5 && t1-t2<5 && fabs(k2-k1)<0.5)
  928. {
  929. double tbegin = t0-3;
  930. while(tbegin<t1+0.5)
  931. tbegin=tbegin+1;
  932. double tk=(d0-d1)/(t0-t1), tb=d1-tk*t1; //d1+(d0-d1)/(t0-t1)*(t-t1)
  933. for(double ti=tbegin;ti<t0;ti=ti+1)
  934. {
  935. m_fitk.add(ti, tk*ti+tb);
  936. }
  937. }
  938. }
  939. dist=m_begin->loc_dist(m_d(i)[0]);
  940. m_fitk.add(m_d(i).m_time/1000.,dist);
  941. if(i==len)
  942. continue;
  943. m_fita.add(m_d(i).m_time/1000.,dist-dist2);
  944. dist2=dist;
  945. }
  946. save_k();
  947. }
  948. }
  949. void select_point_object::save_k()
  950. {
  951. const fit_result*fk=best_fit_raw(0,4);
  952. if(!fk)
  953. {
  954. m_cur_fit.reset();
  955. return;
  956. }
  957. m_cur_fit=*fk;
  958. fit_result&r=m_cur_fit;
  959. card_fit*fa=&m_fita[0];
  960. if(fa->is_valid() && fa->ke<0.1 && fk->k*fa->k<0)
  961. {
  962. double dk=fa->k*fa->num_point;
  963. r.ka=fa->k;
  964. if((fk->k+dk)*fk->k<0)
  965. r.k=0;
  966. else
  967. r.k+=dk;
  968. double y=fk->k*m_fitk(0).x+fk->kb;
  969. r.kb=y-m_fitk(0).x*r.k;
  970. }
  971. }
  972. fit_result* select_point_object::best_fit_raw(int num_point,int start,int last)
  973. {
  974. card_fit*fit = nullptr;
  975. start = std::max(start,0);
  976. last = std::min(last,m_fitk.tool_size());
  977. if(last == -1)
  978. last = m_fitk.tool_size();
  979. for(int i = start; i < last; i++)
  980. {
  981. if(!m_fitk[i].is_valid())
  982. continue;
  983. if(m_fitk[i].num_point < num_point)
  984. continue;
  985. if(fit == nullptr)
  986. {
  987. fit = &m_fitk[i];
  988. continue;
  989. }
  990. if(fit->ke > m_fitk[i].ke)
  991. {
  992. fit = &m_fitk[i];
  993. }
  994. }
  995. return fit;
  996. }
  997. select_tool::~select_tool()
  998. {
  999. if(m_spo !=nullptr)
  1000. delete m_spo;
  1001. }
  1002. loc_point select_tool_person_1::select_solution(const std::vector<point> vp,const std::vector<loc_message>&lm)
  1003. {
  1004. loc_point lp;
  1005. //select point.
  1006. uint8_t idx = 0;
  1007. uint8_t type = lm[0].tool_index()>>4;
  1008. uint8_t dim = lm[0].tool_index() & 0x03;
  1009. idx = type*3 + dim - 1;
  1010. //logn_info(3, "[pdoa] card_id=%d, idx=%d, dim=%d", lm[0].m_card_id, idx, dim);
  1011. if(idx == 0)
  1012. {
  1013. if(m_spo==nullptr)
  1014. m_spo = new person_point_filter(this);
  1015. lp=m_spo->select_solution_impl(vp,lm);
  1016. }
  1017. else if (idx == 2)
  1018. {
  1019. //for now..
  1020. //m_spo = new person_point_filter();
  1021. //lp=m_spo->select_solution_impl(vp,lm);
  1022. }else if(6 == idx){
  1023. // pdoa一维定位
  1024. //logn_info(3, "[pdoa] person, select_solution 1d, tool_index=%d", idx);
  1025. if(nullptr == m_spo){
  1026. m_spo= new person_point_filter(this);
  1027. }
  1028. lp = m_spo->select_solution_impl(vp, lm);
  1029. }else if(7 == idx){
  1030. // logn_info(3, "[pdoa] person, select_solution 2d, tool_index=%d", idx);
  1031. // pdoa二维定位
  1032. if(nullptr == m_spo){
  1033. m_spo = new person_point_filter(this);
  1034. }
  1035. lp = m_spo->select_solution_impl(vp, lm);
  1036. }else if(3 == idx){
  1037. }else if(4 == idx){
  1038. }else if(5 == idx){
  1039. }
  1040. else
  1041. {}
  1042. return lp;
  1043. }
  1044. loc_point select_tool_car_1::select_solution(const std::vector<point> vp,const std::vector<loc_message>&lm)
  1045. {
  1046. loc_point lp;
  1047. //select point.
  1048. uint8_t idx = 0;
  1049. uint8_t type = lm[0].tool_index()>>4;
  1050. uint8_t dim = lm[0].tool_index() & 0x03;
  1051. idx = type*3 + dim - 1;
  1052. if(idx == 0)
  1053. {
  1054. if(m_spo==nullptr)
  1055. m_spo = new car_point_filter(this);
  1056. lp=m_spo->select_solution_impl(vp,lm);
  1057. }
  1058. else if (idx == 2)
  1059. {
  1060. //for now..
  1061. //m_spo = new car_point_filter();
  1062. //lp=m_spo->select_solution_impl(vp,lm);
  1063. }else if(6 == idx){
  1064. // pdoa一维定位
  1065. if(nullptr == m_spo){
  1066. m_spo = new car_point_filter(this);
  1067. }
  1068. lp = m_spo->select_solution_impl(vp, lm);
  1069. }else if(7 == idx){
  1070. // pdoa二维定位
  1071. if(nullptr == m_spo)
  1072. {
  1073. m_spo = new car_point_filter(this);
  1074. }
  1075. lp = m_spo->select_solution_impl(vp, lm);
  1076. }else if(3 == idx){
  1077. }else if(4 == idx){
  1078. }else if(5 == idx){
  1079. }
  1080. else
  1081. {}
  1082. return lp;
  1083. }
  1084. select_tool_manage * select_tool_manage::instance()
  1085. {
  1086. static select_tool_manage stm;
  1087. return &stm;
  1088. }