select_tool.cpp 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587
  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. #include "GaussianFilter/GaussianFilter_emxAPI.h"
  8. #include <deque>
  9. #include "load_raw.h"
  10. #include "tool_time.h"
  11. //opt_tool_main select_point_object::m_opt_tool;
  12. void select_point_object::att_initiate()
  13. {
  14. m_fitk.add_tool(30,5,5);
  15. m_fitk.add_tool(30,5,6);
  16. m_fitk.add_tool(30,10,10);
  17. m_fitk.add_tool(30,10,15);
  18. m_fitk.add_tool(20,5,6);
  19. m_fitk.add_tool(30,4,6);
  20. m_fitk.add_tool(40,4,6);
  21. m_fita.add_tool(15,5,5);
  22. m_begin=m_last=0;
  23. }
  24. //
  25. int select_point_object::select_max_solution(const float& lhs, const float& rhs, const std::vector<point> vp, loc_point& lp)
  26. {
  27. if(lhs > rhs){
  28. lp.set(vp[0]);
  29. return 0;
  30. }else{
  31. lp.set(vp[1]);
  32. return 1;
  33. }
  34. }
  35. //
  36. int select_point_object::select_min_solution(const float& lhs, const float& rhs, const std::vector<point> vp, loc_point& lp)
  37. {
  38. if(lhs < rhs){
  39. lp.set(vp[0]);
  40. return 0;
  41. }else{
  42. lp.set(vp[1]);
  43. return 1;
  44. }
  45. }
  46. loc_point select_point_object::select_solution_impl(const std::vector<point> vp,const std::vector<loc_message>&lm)
  47. {
  48. bool flag = false;
  49. loc_point lp;
  50. //如果1维pdoa定位
  51. 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());
  52. switch(lm[0].m_loc_type){
  53. case LDT_TOF:
  54. if(vp.size()==4)
  55. {
  56. m_d.grow().reset().set_source(lm[0],lm[1]);
  57. flag = true;
  58. }
  59. if(vp.size()==2 && lm[0].m_card_ct - last_ct() == 1)
  60. {
  61. m_d.grow().reset().set_source(lm[0]);
  62. flag = true;
  63. }
  64. if(flag)
  65. {
  66. if(!select_solution(vp,lm[0].m_sit.get(),lp))
  67. {
  68. m_cur_fit.reset();
  69. }
  70. }
  71. break;
  72. case LDT_PDOA:
  73. select_pdoa_solution_impl(vp, lm, lp);
  74. break;
  75. }
  76. m_ct = lm[0].m_card_ct;
  77. return lp;
  78. }
  79. bool select_point_object::select_pdoa_solution_impl(const std::vector<point> vp, const std::vector<loc_message>& lm, loc_point& lp)
  80. {
  81. switch(get_algo_index(lm[0].tool_index())){
  82. case 6:
  83. if(lm[0].m_sync_ct){
  84. return select_pdoa_1d_solution_original(vp, lm, lp);
  85. }else{
  86. return select_pdoa_1d_solution(vp, lm, lp);
  87. }
  88. break;
  89. case 7:
  90. return select_pdoa_2d_solution(vp, lm, lp);
  91. break;
  92. case 8:
  93. return select_pdoa_3d_solution(vp, lm, lp);
  94. break;
  95. }
  96. return false;
  97. }
  98. /*
  99. * 当下井方向选解策略
  100. *
  101. * */
  102. bool select_point_object::select_pdoa_solution(const std::vector<point> vp, const std::vector<loc_message>& lm, loc_point&lp, const float& pdoa)
  103. {
  104. if(1 == vp.size())
  105. {
  106. bool dir = (pdoa > EPS);
  107. 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);
  108. if(lm[0].m_sit->m_ant[0].x == lm[0].m_sit->m_ant[1].x)
  109. {
  110. if(0 == lm[0].m_sit->m_pdoa_direction){
  111. if(dir){
  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. }else{
  120. if(vp[0].x < lm[0].m_sit->m_ant[0].x){
  121. lp.set(vp[0]);
  122. lp.m_useless = true;
  123. }else{
  124. logn_warn(3, "[pdoa] solution is not correct, card_id=%d", lm[0].m_card_id);
  125. lp.m_useless = false;
  126. }
  127. }
  128. }else{
  129. if(dir){
  130. if(vp[0].x < lm[0].m_sit->m_ant[0].x){
  131. lp.set(vp[0]);
  132. lp.m_useless = true;
  133. }else{
  134. lp.m_useless = false;
  135. }
  136. }else{
  137. if(vp[0].x > lm[0].m_sit->m_ant[0].x){
  138. lp.set(vp[0]);
  139. lp.m_useless = true;
  140. }else{
  141. lp.m_useless = false;
  142. }
  143. }
  144. }
  145. }else{
  146. logn_info(3, "[pdoa] select one solution, card_id=%d", lm[0].m_card_id);
  147. if(dir){
  148. }
  149. }
  150. return lp.m_useless;
  151. }else if(2 == vp.size()){
  152. // select one solution from two solution by reader and phase direction
  153. 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);
  154. bool dir = (pdoa > EPS);
  155. int max = -1, min = -1;
  156. if(0 == lm[0].m_sit->m_pdoa_direction)
  157. {
  158. if(lm[0].m_sit->m_ant[0].x == lm[0].m_sit->m_ant[1].x){
  159. 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));
  160. }else if(lm[0].m_sit->m_ant[0].y == lm[0].m_sit->m_ant[1].y){
  161. 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));
  162. }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)){
  163. 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));
  164. }
  165. }else{
  166. if(lm[0].m_sit->m_ant[0].x == lm[0].m_sit->m_ant[1].x){
  167. // 分站天线在竖直巷道
  168. 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));
  169. }else if(lm[0].m_sit->m_ant[0].y == lm[0].m_sit->m_ant[1].y){
  170. // 分站天线在水平巷道
  171. 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));
  172. }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)){
  173. 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));
  174. }
  175. }
  176. 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);
  177. }
  178. return true;
  179. }
  180. /* 当出井方向切换分站选解
  181. 本方法是根据之前通过距离的半径圆和基站路径集线段相交算出来的两个定位结果(即相交点),通过pdoa的正负
  182. 进一步确认正确的定位坐标是那个相交点。
  183. 输入:vp,两个定位结果(需要结果pdoa值的左右方向判断来推算出正确的定位结果),
  184. 两个point (100,100),(100,200)
  185. 是之前通过距离和基站路径集推算出来。
  186. 输入:lm,定位卡的相关信息
  187. 输入:pdoa,pdoa值
  188. 输出:lp,选解的结果(根据pdoa的正负从vp两个point里面选出一个定位坐标结果)
  189. 返回值:选解是否成功
  190. 作者:祝云飞
  191. */
  192. bool select_point_object::select_pdoa_solution2(const std::vector<point> vp, const std::vector<loc_message>& lm, loc_point&lp, const float& pdoa)
  193. {
  194. if(1 == vp.size())
  195. {
  196. bool dir = (pdoa > EPS);
  197. 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);
  198. if(lm[0].m_sit->m_ant[0].x == lm[0].m_sit->m_ant[1].x)
  199. {
  200. if(0 == lm[0].m_sit->m_pdoa_direction){
  201. if(dir){
  202. if(vp[0].x > lm[0].m_sit->m_ant[0].x){
  203. lp.set(vp[0]);
  204. lp.m_useless = true;
  205. }else{
  206. logn_warn(3, "[pdoa] solution is not correct, card_id=%d", lm[0].m_card_id);
  207. lp.m_useless = false;
  208. }
  209. }else{
  210. if(vp[0].x < lm[0].m_sit->m_ant[0].x){
  211. lp.set(vp[0]);
  212. lp.m_useless = true;
  213. }else{
  214. logn_warn(3, "[pdoa] solution is not correct, card_id=%d", lm[0].m_card_id);
  215. lp.m_useless = false;
  216. }
  217. }
  218. }else{
  219. if(dir){
  220. if(vp[0].x < lm[0].m_sit->m_ant[0].x){
  221. lp.set(vp[0]);
  222. lp.m_useless = true;
  223. }else{
  224. lp.m_useless = false;
  225. }
  226. }else{
  227. if(vp[0].x > lm[0].m_sit->m_ant[0].x){
  228. lp.set(vp[0]);
  229. lp.m_useless = true;
  230. }else{
  231. lp.m_useless = false;
  232. }
  233. }
  234. }
  235. }else{
  236. logn_info(3, "[pdoa] select one solution, card_id=%d", lm[0].m_card_id);
  237. if(dir){
  238. }
  239. if (0 == lm[0].m_sit->m_pdoa_direction) {
  240. if (dir) {
  241. if (vp[0].x > lm[0].m_sit->m_ant[0].x) {
  242. lp.set(vp[0]);
  243. lp.m_useless = true;
  244. }
  245. else {
  246. logn_warn(3, "[pdoa] solution is not correct, card_id=%d", lm[0].m_card_id);
  247. lp.m_useless = false;
  248. }
  249. }
  250. else {
  251. if (vp[0].x < lm[0].m_sit->m_ant[0].x) {
  252. lp.set(vp[0]);
  253. lp.m_useless = true;
  254. }
  255. else {
  256. logn_warn(3, "[pdoa] solution is not correct, card_id=%d", lm[0].m_card_id);
  257. lp.m_useless = false;
  258. }
  259. }
  260. }
  261. else {
  262. if (dir) {
  263. if (vp[0].x < lm[0].m_sit->m_ant[0].x) {
  264. lp.set(vp[0]);
  265. lp.m_useless = true;
  266. }
  267. else {
  268. lp.m_useless = false;
  269. }
  270. }
  271. else {
  272. if (vp[0].x > lm[0].m_sit->m_ant[0].x) {
  273. lp.set(vp[0]);
  274. lp.m_useless = true;
  275. }
  276. else {
  277. lp.m_useless = false;
  278. }
  279. }
  280. }
  281. }
  282. return lp.m_useless;
  283. }else if(2 == vp.size()){
  284. // select one solution from two solution by reader and phase direction
  285. 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);
  286. bool dir = (pdoa > EPS);
  287. int max = -1, min = -1;
  288. if(lm[0].m_sit->m_ant[0].x == lm[0].m_sit->m_ant[1].x){
  289. 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));
  290. }else if(lm[0].m_sit->m_ant[0].y == lm[0].m_sit->m_ant[1].y){
  291. 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));
  292. }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)){
  293. 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));
  294. }
  295. 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);
  296. }
  297. return true;
  298. }
  299. /*bool select_point_object::select_pdoa_1d_solution(const std::vector<point> vp, const std::vector<loc_message>& lm, loc_point& lp)
  300. {
  301. uint64_t id = lm[0].m_card_type;
  302. id = ((id<<32) | lm[0].m_card_id);
  303. auto card = card_list::instance()->get(id);
  304. double dist_tof = lm[0].m_num_ticks * 15.65 * 2.996 * 1e-4;
  305. if((card->m_buff_size != 100 || dist_tof < SAFE) && fabs(lm[0].m_poa[1] - 10.0) < 1E-4){
  306. return false;
  307. }
  308. int idx = lm[0].tool_index();
  309. uint8_t type = idx>>4;
  310. uint8_t dim = idx&0x03;
  311. idx = type*3 + dim - 1;
  312. if(card->m_buff_size == 100 && dist_tof > SAFE && fabs(lm[0].m_poa[1] - 10.0) < 1E-4){
  313. lp.x = card->m_last_point.x;
  314. lp.y = card->m_last_point.y;
  315. double diff_time = (lm[0].m_loc_time - card->m_last_recv_time)*1.0/1000.0;
  316. double speed = get_speed(lp, card->m_last_point, diff_time) * lm[0].m_sit->m_scale;
  317. if(speed > 15.0){
  318. lp.m_useless = false;
  319. return false;
  320. }
  321. lp.m_useless = true;
  322. 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);
  323. card->m_last_pdoa_diff = card->m_pdoa_diff;
  324. card->m_last_ct = lm[0].m_card_ct;
  325. card->m_last_dist = dist_tof;
  326. card->m_cb_point.push_back(lp);
  327. card->m_last_site_id = lm[0].m_sit->m_id;
  328. card->m_last_site_dir = lm[0].m_sit->m_pdoa_direction;
  329. card->m_last_recv_time = lm[0].m_loc_time;
  330. card->m_last_point.x = lp.x;
  331. card->m_last_point.y = lp.y;
  332. lp.m_speed = card->m_speed = 0;
  333. return true;
  334. }
  335. card->m_pdoa_diff = get_pdoa(lm[0].m_poa, lm[0].m_sit->m_pdoa_offset);
  336. 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);
  337. // after a long time,there is not recvied data, then reset pdoa list
  338. 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){
  339. 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);
  340. card->clear();
  341. }
  342. //first adjust, first 5 frame, not output located point
  343. uint16_t ct = lm[0].m_card_ct;
  344. if(card->m_buff_size < 5){
  345. card->m_cb_pdoa.push_back(card->m_pdoa_diff);
  346. ++card->m_buff_size;
  347. card->m_cb_tof.push_back(dist_tof);
  348. card->m_last_ct = ct;
  349. card->m_last_dist = dist_tof;
  350. card->m_last_recv_time = lm[0].m_loc_time;
  351. return false;
  352. }
  353. // choose 3 poa's direction as the card's direction
  354. if(5 == card->m_buff_size){
  355. card->m_buff_size = 100;
  356. int positive = 0;
  357. for(int i = 0;i < 5; ++i){
  358. if(card->m_cb_pdoa[i] > 0){
  359. ++positive;
  360. }
  361. }
  362. if(positive >= 3){
  363. for(int i = 0; i < 5; ++i){
  364. if(card->m_cb_pdoa[i] < 0){
  365. card->m_cb_pdoa[i] = -1.0*card->m_cb_pdoa[i];
  366. }
  367. }
  368. }else{
  369. for(int i = 0;i < 5;++i){
  370. if(card->m_cb_pdoa[i] > 0){
  371. card->m_cb_pdoa[i] = -1.0*card->m_cb_pdoa[i];
  372. }
  373. }
  374. }
  375. }
  376. // tof filter
  377. int ct_offset = -1;
  378. float offset = 0.0f;
  379. ct_offset = ct - card->m_last_ct;
  380. offset = card->m_cb_tof[4] - dist_tof;
  381. if(1 == ct_offset)
  382. {
  383. if(offset < 0){
  384. offset = -1.0*offset;
  385. }
  386. // need call opt way
  387. if(offset > 15){
  388. // illeglal tof
  389. 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]);
  390. return false;
  391. }
  392. }
  393. card->m_last_dist = dist_tof;
  394. //card->m_cb_tof.push_back(dist_tof);
  395. 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]);
  396. //pdoa meadian filter
  397. std::array<float, 5> pdoa = {0};
  398. for(int i = 0; i < 5; ++i){
  399. pdoa[i] = card->m_cb_pdoa[i];
  400. }
  401. std::sort(pdoa.begin(), pdoa.end());
  402. float meadian_pdoa = pdoa[2];
  403. 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]);
  404. float cur_pdoa = card->m_pdoa_diff;
  405. bool change = false;
  406. if(lm[0].m_loc_time - card->m_last_recv_time < 30*1000){
  407. if(card->m_last_site_id !=0 && card->m_last_site_id != lm[0].m_sit->m_id){
  408. // pdoa change from site A to site B
  409. if(card->m_last_site_dir == 0 && lm[0].m_sit->m_pdoa_direction == 0){
  410. change = true;
  411. }else if(card->m_last_site_dir == 0 && lm[0].m_sit->m_pdoa_direction == 1){
  412. // keep same direction
  413. }else if(card->m_last_site_dir == 1 && lm[0].m_sit->m_pdoa_direction == 0){
  414. // keep same direction
  415. }else if(card->m_last_site_dir == 1 && lm[0].m_sit->m_pdoa_direction == 1){
  416. change = true;
  417. }
  418. if(change){
  419. for(int i = 0;i < 5; ++i){
  420. card->m_cb_pdoa[i] *= -1.0;
  421. }
  422. }
  423. // 下面逻辑判断当前pdoa值是否有异常,如有异常就改变方向
  424. int same_direction = 0;
  425. for(int i = 0;i < 5;++i){
  426. if(card->m_cb_pdoa[i] * cur_pdoa > 0){
  427. same_direction++;
  428. }
  429. }
  430. if(same_direction < 3){
  431. cur_pdoa*=-1;
  432. }
  433. 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));
  434. card->m_cb_pdoa.push_back(cur_pdoa);
  435. card->m_cb_tof.push_back(dist_tof);
  436. // 定位退出
  437. if(!save_pdoa_1d(card, vp, lm, lp, cur_pdoa)){
  438. return false;
  439. }
  440. return true
  441. }
  442. }
  443. // 5 meter away filter, abnormal poa
  444. //bool is_opposite = false;
  445. if(dist_tof > SAFE)
  446. {
  447. int same_direction = 0;
  448. for(int i = 0;i< 5;++i){
  449. if(card->m_cb_pdoa[i] * cur_pdoa > 0){
  450. same_direction++;
  451. }
  452. }
  453. if(same_direction < 3){
  454. 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);
  455. float last_k = 0.0f, curr_k = 0.0f, llast_k = 0.0f;
  456. llast_k = card->m_cb_tof[3] - card->m_cb_tof[2];
  457. last_k = card->m_cb_tof[4] - card->m_cb_tof[3];
  458. curr_k = dist_tof - card->m_cb_tof[4];
  459. if(curr_k > 0 && last_k < 0 && llast_k < 0)
  460. {
  461. // find the site
  462. logn_info(3, "[pdoa] card has cross the site, card_id=%d, ct=%d", lm[0].m_card_id, lm[0].m_card_ct);
  463. // 缓存切换方向
  464. }else{
  465. card->m_cb_pdoa.push_back(cur_pdoa);
  466. card->m_cb_tof.push_back(cur_tof);
  467. // 定位退出
  468. if(!save_pdoa_1d(card, vp, lm, lp, cur_pdoa)){
  469. return false;
  470. }
  471. return true
  472. }
  473. }
  474. }else{
  475. // judge the position of site
  476. 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);
  477. float last_k = 0.0f, curr_k = 0.0f, llast_k = 0.0f;
  478. llast_k = card->m_cb_tof[3] - card->m_cb_tof[2];
  479. last_k = card->m_cb_tof[4] - card->m_cb_tof[3];
  480. curr_k = dist_tof - card->m_cb_tof[4];
  481. if(curr_k > 0 && last_k < 0 && llast_k < 0)
  482. {
  483. // find the site
  484. logn_info(3, "[pdoa] card has cross the site, card_id=%d, ct=%d", lm[0].m_card_id, lm[0].m_card_ct);
  485. for(int i = 0; i < 5;++i)
  486. {
  487. card->m_cb_pdoa[i] = 100;
  488. }
  489. //如果当前值方向和中值方向相同了,认为切了方向,因为距离信息当前方向和中值方向应该不同
  490. if(((0.0 - card->m_pdoa_diff) < EPS) == ((0.0 - meadian_pdoa) < EPS))
  491. {
  492. card->m_pdoa_diff = -card->m_pdoa_diff;
  493. }
  494. }
  495. }
  496. 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]);
  497. card->m_cb_tof.push_back(dist_tof);
  498. card->m_cb_pdoa.push_back(card->m_pdoa_diff);
  499. if(!save_pdoa_1d(card, vp, lm, lp, cur_pdoa)){
  500. return false;
  501. }
  502. return true;
  503. }*/
  504. /*
  505. * 选择一维定位的解,不采用任何优化方法
  506. *
  507. * 参数
  508. * const std::vector<point> vp 可能定位解
  509. * const std::vector<loc_message>& lm 定位原始数据集
  510. * loc_point& lp 保存最终定位解
  511. *
  512. * 返回值
  513. * true表示成功选解,false表示选解失败
  514. *
  515. * */
  516. bool select_point_object::select_pdoa_1d_solution_original(const std::vector<point> vp, const std::vector<loc_message>& lm, loc_point& lp)
  517. {
  518. uint64_t id = lm[0].m_card_type;
  519. id = ((id << 32) | lm[0].m_card_id);
  520. auto card = card_list::instance()->get(id);
  521. double dist = lm[0].m_num_ticks * 15.65 * 2.996 * 1e-4;
  522. double pdoa = get_pdoa(lm[0].m_poa, lm[0].m_sit->m_pdoa_offset);
  523. logn_info(3, "[pdoa_o] card_id=%d, pdoa=%.2f, dist=%.2f, vp0x=%.2f, vp0y=%.2f, vp1x=%.2f, vp2y=%.2f", lm[0].m_card_id, pdoa, dist, vp[0].x, vp[0].y, vp[1].x, vp[1].y);
  524. double dt = (lm[0].m_loc_time - card->m_last_recv_time)*1.0 / 1000.0;
  525. double speed = fabs(dist - card->m_last_dist) / dt;
  526. if (!select_pdoa_solution2(vp, lm, lp, pdoa)) {
  527. return false;
  528. }
  529. logn_info(3, "[pdoa_o] card_id=%d, ct=%d, useless=%d, x=%.4f, y=%.4f, speed=%.3f, d=%.2f", lm[0].m_card_id, lm[0].m_card_ct, 1, lp.x, lp.y, speed);
  530. lp.m_useless = true;
  531. card->m_last_pdoa_diff = pdoa;
  532. card->m_last_ct = lm[0].m_card_ct;
  533. card->m_last_dist = dist;
  534. card->m_last_site_id = lm[0].m_sit->m_id;
  535. card->m_last_site_dir = lm[0].m_sit->m_pdoa_direction;
  536. card->m_last_point.x = lp.x;
  537. card->m_last_point.y = lp.y;
  538. lp.m_speed = card->m_speed = speed;
  539. card->m_cb_point.push_back(lp);
  540. card->m_vtp_dist.push_back(dist);
  541. return true;
  542. }
  543. /*
  544. * 选择一维定位的解,不采用任何优化方法
  545. *
  546. * 参数
  547. * const std::vector<point> vp 可能定位解
  548. * const std::vector<loc_message>& lm 定位原始数据集
  549. * loc_point& lp 保存最终定位解
  550. *
  551. * 返回值
  552. * true表示成功选解,false表示选解失败
  553. *
  554. * */
  555. /*pdoa一维定位算法
  556. card_location_base::on_location 调用进来的
  557. 作用:计算pdoa值(距离、角度)和定位结果lp(是传给web的最后的结果)
  558. 输入:
  559. vp:距离数据(已经根据硬件读来的数据中算出了两个解,根据距离求出的位于基站两边的同距离的两个解)
  560. lm:卡信息相关数据消息输入
  561. 输出:算出角度,然后判断左右方向。
  562. lp,含有x、y坐标
  563. added by zengminguo
  564. 从vp中取出
  565. 处理:算出pdoa的正负值,判断左右方向。算出角度。
  566. */
  567. bool select_point_object::select_pdoa_1d_solution(const std::vector<point> vp, const std::vector<loc_message>& lm, loc_point& lp)
  568. {
  569. uint64_t id = lm[0].m_card_type;
  570. id = ((id<<32) | lm[0].m_card_id);
  571. auto card = card_list::instance()->get(id);
  572. double dist = lm[0].m_num_ticks * 15.65 * 2.996 * 1e-4;
  573. int idx = lm[0].tool_index();
  574. uint8_t type = idx>>4;
  575. uint8_t dim = idx&0x03;
  576. idx = type*3 + dim - 1;
  577. double pdoa = get_pdoa(lm[0].m_poa, lm[0].m_sit->m_pdoa_offset);
  578. card->m_pdoa_diff = pdoa;
  579. {
  580. if (card->m_last_site_id != lm[0].m_sit->m_id)
  581. {
  582. card->m_gaussian_count = 5;
  583. card->deqInput.clear();
  584. }
  585. if (card->deqInput.size() >= 20)
  586. {
  587. card->deqInput.pop_front();
  588. }
  589. card->deqInput.push_back(card->m_pdoa_diff);
  590. double pdoaInput[20];
  591. double pdoaOutput[20];
  592. int iIndex = 0;
  593. for (std::deque<double>::iterator iter = card->deqInput.begin(); iter != card->deqInput.end(); iter++)
  594. {
  595. pdoaInput[iIndex] = *iter;
  596. iIndex++;
  597. }
  598. //通过滤波计算出pdoa的正负值,使得左右判断准确,然后通过左右计算出最终定位坐标结果
  599. //现在默认采用高斯滤波(离基站近的时候)加移动均值滤波(非离基站近距离)的方式,使得定位效果最好。
  600. // added by zengminguo 20220424
  601. auto pdoaGaussian = card->m_pdoa_diff;
  602. emxArray_real_T* vecInput = emxCreateWrapper_real_T(pdoaInput, 1, card->deqInput.size());
  603. emxArray_real_T* vecOutput = emxCreateWrapper_real_T(pdoaOutput, 1, card->deqInput.size());
  604. card->m_gaussian_filter.GaussianFilter(vecInput, vecOutput);
  605. pdoaGaussian = pdoaOutput[card->deqInput.size() - 1];
  606. auto pdoaMovAvg = card->m_pdoa_diff;
  607. pdoaMovAvg = card->m_mov_avg_filter.MovAvgFilter(pdoaMovAvg);
  608. if (pdoaGaussian*card->m_last_pdoa_diff < 0)//反向
  609. {
  610. if (dist < 25 || card->m_gaussian_count>0)//在过站区域
  611. {
  612. card->m_pdoa_diff = pdoaGaussian;
  613. card->m_gaussian_count > 0 ? card->m_gaussian_count-- : card->m_gaussian_count;
  614. }
  615. else
  616. {
  617. if (fabs(pdoaMovAvg) >= 0.5)
  618. {
  619. card->m_pdoa_diff = pdoaMovAvg;
  620. }
  621. else
  622. {
  623. card->m_pdoa_diff = card->m_last_pdoa_diff;
  624. }
  625. }
  626. }
  627. else
  628. {
  629. card->m_pdoa_diff = pdoaGaussian;
  630. }
  631. }
  632. //pdoa = card->m_pdoa_diff; //先分析原始数据,不滤波
  633. // 1,进行新基站的时候,方向的稳定性,前5次判断基站的方向。通过5条,谁多是哪个方向。(前5秒的数据也给web)值高河之前的动画解决卡顿问题。
  634. // 后台采集介绍下。数据、接口、怎么编码 地图。做5个插值保证平滑。没有进一步定位了,
  635. // 2,只要我这个车辆的方向一直负方向,遇到正置负。唯一特例规则正负10米内,认。换了之后就一直为正。
  636. if (card->m_last_site_id != lm[0].m_sit->m_id)
  637. {
  638. card->m_count_plus = 0;
  639. card->m_count_minus = 0;
  640. card->m_site_crossed = false;
  641. }
  642. if (fabs(card->m_count_plus) + fabs(card->m_count_minus) < 5)
  643. {
  644. if (pdoa > 0)
  645. {
  646. card->m_count_plus++;
  647. }
  648. else
  649. {
  650. card->m_count_minus++;
  651. }
  652. }
  653. if (fabs(dist) > 10.0&&card->m_site_crossed == false)
  654. {
  655. if (card->m_count_plus > card->m_count_minus)
  656. {
  657. card->m_direction = 1.0;
  658. }
  659. else
  660. {
  661. card->m_direction = -1.0;
  662. }
  663. }
  664. else if (fabs(dist) <= 10.0&&fabs(card->m_last_dist) > 10.0)
  665. {
  666. card->m_direction_changing = true;
  667. }
  668. if (card->m_direction_changing)//正处于跨站状态
  669. {
  670. if (pdoa*card->m_last_pdoa_diff < 0.0)//反向
  671. {
  672. card->m_direction = card->m_direction*(-1.0);
  673. card->m_direction_changing = false;
  674. card->m_site_crossed = true;
  675. }
  676. }
  677. pdoa = fabs(pdoa)*card->m_direction;
  678. //card->m_last_pdoa_diff = card->m_pdoa_diff;
  679. 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);
  680. // 距离 zengmg
  681. lp.m_dist = (pdoa > 0 ? 1 : -1)*dist;
  682. auto loc_time = lm[0].m_loc_time;
  683. if (load_raw::m_is_history)
  684. {
  685. if (load_raw::m_vec_date.size() > load_raw::m_index)
  686. {
  687. loc_time = tool_time::to_time(load_raw::m_vec_date[load_raw::m_index]);
  688. }
  689. }
  690. // 计算速度逻辑
  691. //double dt = (loc_time - card->m_last_recv_time)*1.0 / 1000.0;
  692. double dt = (lm[0].m_time_tmp - card->m_time_tmp_last)*1.0 / 1000.0;
  693. if (dt == 0)
  694. {
  695. dt = 1;
  696. }
  697. double speed = fabs(dist - card->m_last_dist) / dt;
  698. lp.m_speed = speed;
  699. card->m_last_recv_time = loc_time;
  700. // 计算角度逻辑
  701. do
  702. {
  703. float b = 0.075;
  704. float d = 0.5*b;
  705. float p = pdoa * b / (2.0*3.1415926);
  706. //logn_info(3, "[pdoa] before adjust, p = %.4f, pdoa_old=%.4f", p, pdoa);
  707. p = -2919.8*pow(p, 4.0) - 88.74*pow(p, 3.0) + 5.6182*p*p + 1.1041*p - 0.00079884;
  708. //p = -0.0222*pow(p, 4.0) + 0.0328*pow(p, 3.0) + 0.0729*p*p + 0.854*p + 0.0111;
  709. //p *= 0.01;
  710. float alpha = p / d;
  711. if (fabs(alpha) > 1.0) {
  712. //logn_info(3, "[pdoa] p>d, alpha=%.4f, p=%.4f, d=%.4f", alpha, p, d);
  713. break;
  714. }
  715. double angle = acos(alpha) * 180 / 3.14;
  716. //logn_info(3, "[pdoa] angle=%.2f", angle);
  717. lp.m_angle = angle;
  718. } while (0);
  719. if (lm[0].m_sit->m_pdoa_direction == 1) {
  720. pdoa *= -1;
  721. }
  722. if (!select_pdoa_solution2(vp, lm, lp, pdoa)) {
  723. log_info("[select_point_object] select_pdoa_solution2 error");
  724. return false;
  725. }
  726. card->m_time = time(0) * 1000;
  727. lp.m_useless = true;
  728. log_info("[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);
  729. log_info("[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);
  730. if (false)
  731. {
  732. if (card->m_last_recv_time > 0 && fabs(dt) > 30.0)
  733. {
  734. // 直接定位
  735. 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);
  736. card->m_last_recv_time = lm[0].m_loc_time;
  737. return false;
  738. }
  739. card->m_last_recv_time = lm[0].m_loc_time;
  740. int n = card->m_vtp_dist.size();
  741. bool change_site = false;
  742. bool over_site = false;
  743. //切换基站,默认取正值
  744. if (lm[0].m_sit->m_id != card->m_last_site_id) {
  745. // 切换基站要考虑两种情况
  746. // 1)入井方向的切换
  747. if (card->m_cb_stream_idx[0] < lm[0].m_sit->m_down_stream_idx) {
  748. if (lm[0].m_sit->m_pdoa_direction == 0) {
  749. pdoa *= (pdoa > 0 ? 1 : -1);
  750. }
  751. else {
  752. pdoa *= (pdoa < 0 ? -1 : 1);
  753. }
  754. }
  755. else {
  756. // 2)出井方向的切换
  757. if (lm[0].m_sit->m_pdoa_direction == 0) {
  758. pdoa *= (pdoa < 0 ? 1 : -1);
  759. }
  760. else {
  761. pdoa *= (pdoa > 0 ? -1 : 1);
  762. }
  763. }
  764. if (!select_pdoa_solution2(vp, lm, lp, pdoa)) {
  765. return false;
  766. }
  767. card->m_cb_stream_idx.push_back(lm[0].m_sit->m_down_stream_idx);
  768. card->m_last_site_id = lm[0].m_sit->m_id;
  769. card->m_vtp_dist.clear();
  770. card->m_vtp_dist.resize(0);
  771. change_site = true;
  772. card->m_over_site = false;
  773. 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);
  774. }
  775. else if (!card->m_over_site && n >= 3) {
  776. // 过分站逻辑
  777. if (!select_pdoa_solution2(vp, lm, lp, pdoa)) {
  778. return false;
  779. }
  780. //double dd = dist - card->m_last_dist;
  781. double d = lp.dist(card->m_last_point)*lm[0].m_sit->m_scale;
  782. 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);
  783. // 如果选出的解是正确解,即距离和测距距离相等
  784. double k1 = (card->m_vtp_dist[n - 2] - card->m_vtp_dist[n - 1]) / dt;
  785. double k2 = (card->m_vtp_dist[n - 1] - dist) / dt;
  786. logn_info(3, "[pdoa] card_id=%d, k1=%.2f, k2=%.2f, d=%.2f", lm[0].m_card_id, k1, k2, d);
  787. if (((k1 > 1 && k2 < -1) || (k1 < -1 && k2 > 1)) || (k1*k2 < 0 && fabs(d - dist - card->m_last_dist) < 2.0)) {
  788. over_site = true;
  789. card->m_over_site = true;
  790. //过基站还要分以下两种情况:
  791. //1)入井时的从正到负
  792. //2)出井时的从负到正
  793. 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]);
  794. if (card->m_cb_stream_idx[1] > card->m_cb_stream_idx[0]) {
  795. //1)入井时的从正到负
  796. pdoa *= (pdoa > 0 ? -1 : 1);
  797. /*if(lm[0].m_sit->m_pdoa_direction == 0){
  798. pdoa *= (pdoa<0?-1:1);
  799. }else{
  800. pdoa *= (pdoa>0?1:-1);
  801. }*/
  802. }
  803. else {
  804. //2)出井时的从负到正
  805. pdoa *= (pdoa < 0 ? -1 : 1);
  806. /*if(lm[0].m_sit->m_pdoa_direction == 0){
  807. pdoa *= (pdoa<0?-1:1);
  808. }else{
  809. pdoa *= (pdoa>0?-1:1);
  810. }*/
  811. }
  812. if (!select_pdoa_solution2(vp, lm, lp, pdoa)) {
  813. return false;
  814. }
  815. }
  816. }
  817. // 如果没有切换基站且没有过基站
  818. if (!change_site && !over_site) {
  819. if (!select_pdoa_solution2(vp, lm, lp, pdoa)) {
  820. return false;
  821. }
  822. double d = lp.dist(card->m_last_point)*lm[0].m_sit->m_scale;
  823. 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);
  824. if (fabs(d - fabs(dist - card->m_last_dist)) > 2.0) {
  825. if (!card->m_last_point.empty() && (lm[0].m_sit->m_id == card->m_last_site_id)) {
  826. int idx = 0;
  827. double min = 999999.0;
  828. for (size_t i = 0; i < vp.size(); ++i) {
  829. double d = vp[i].dist(card->m_last_point)*lm[0].m_sit->m_scale;
  830. if (fabs(d - speed * dt) < min) {
  831. idx = i;
  832. min = fabs(d - speed * dt);
  833. }
  834. }
  835. lp.set(vp[idx]);
  836. }
  837. }
  838. d = lp.dist(card->m_last_point)*lm[0].m_sit->m_scale;
  839. /*if(fabs(d-dist) > 0.5 && !card->m_last_point.empty()){
  840. 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);
  841. return false;
  842. }*/
  843. logn_info(3, "[pdoa] unilateral processing, card_id=%d", lm[0].m_card_id);
  844. }
  845. lp.m_useless = true;
  846. 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);
  847. 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);
  848. }
  849. if (!(card->m_isVehicleMap&&card->is_person()))
  850. {
  851. card->m_last_pdoa_diff = pdoa;
  852. card->m_last_ct = lm[0].m_card_ct;
  853. card->m_last_dist = dist;
  854. card->m_last_site_id = lm[0].m_sit->m_id;
  855. card->m_last_site_dir = lm[0].m_sit->m_pdoa_direction;
  856. card->m_last_point.x = lp.x;
  857. card->m_last_point.y = lp.y;
  858. int cell_index_diff = int(dist);
  859. int cell_index_current = lm[0].m_sit->m_cell_index - cell_index_diff;
  860. card->m_cell_index = cell_index_current;
  861. lp.m_speed = card->m_speed = speed;
  862. card->m_cb_point.push_back(lp);
  863. card->m_vtp_dist.push_back(dist);
  864. }
  865. return true;
  866. }
  867. bool select_point_object::select_pdoa_2d_solution(const std::vector<point> vp, const std::vector<loc_message>& lm, loc_point& lp)
  868. {
  869. logn_info(3, "[pdoa] begin select 2d solution, vp's size=%d", vp.size());
  870. int i = 1;
  871. for(auto it = vp.cbegin(); it != vp.cend();++it){
  872. logn_info(3, "[pdoa] useless %d : card_id=%d, x=%.4f, y=%.4f", i, lm[0].m_card_id,(*it).x, (*it).y);
  873. ++i;
  874. }
  875. if(1 == vp.size()){
  876. lp.x = vp[0].x;
  877. lp.y = vp[0].y;
  878. lp.m_useless = true;
  879. }
  880. uint64_t id = lm[0].m_card_type;
  881. id = ((id<<32) | lm[0].m_card_id);
  882. auto card = card_list::instance()->get(id);
  883. card->m_last_point.x = lp.x;
  884. card->m_last_point.y = lp.y;
  885. return true;
  886. }
  887. bool select_point_object::select_pdoa_3d_solution(const std::vector<point> vp, const std::vector<loc_message>& lm, loc_point& lp)
  888. {
  889. return true;
  890. }
  891. int select_point_object::get_algo_index(const int& idx)
  892. {
  893. uint8_t index = 0;
  894. uint8_t type = idx>>4;
  895. uint8_t dim = idx & 0x03;
  896. index = type*3 + dim - 1;
  897. log_info("[pdoa] algo=%d", index);
  898. return index;
  899. }
  900. double select_point_object::get_speed(const loc_point& p, const point& lp, const double& offset)
  901. {
  902. double speed = -1.0;
  903. if(!(p.x <= EPS && p.y <= EPS)){
  904. speed = sqrt(pow(p.x - lp.x, 2) + pow(p.y - lp.y, 2))/offset;
  905. }
  906. 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);
  907. return speed;
  908. }
  909. double select_point_object::get_distance(const int& rid, const int& lrid)
  910. {
  911. double d = 0.0;
  912. /*auto cs = sit_list()->instance()->get(rid);
  913. auto ls = sit_list()->instance()->get(lrid);
  914. if(cs&&ls){
  915. d = cs.dist(ls);
  916. log_info("[pdoa] get distance from current site %d to last site %d", rid, lrid);
  917. }*/
  918. return d;
  919. }
  920. float select_point_object::get_pdoa(const double poa[], const double& offset)
  921. {
  922. if(poa == nullptr){
  923. return -10.0;
  924. }
  925. float poa1 = poa[0];
  926. float poa2 = poa[1];
  927. //float poa3 = poa[2];
  928. float pdoa = poa2 - poa1 - offset;
  929. while(pdoa >= TPI){
  930. pdoa -= TPI;
  931. }
  932. while(pdoa < 0){
  933. pdoa += TPI;
  934. }
  935. pdoa -= PI;
  936. return pdoa;
  937. }
  938. int select_point_object::find_last(int start)
  939. {
  940. for(int i=start,len=m_d.size();i<len;i++)
  941. {
  942. if(m_d(i).cl()>0)
  943. return i;
  944. }
  945. return -1;
  946. }
  947. int select_point_object::find_first(int start)
  948. {
  949. for(int i=start,len=m_d.size();i<len;i++)
  950. {
  951. if(m_d[i].cl()>0)
  952. return i;
  953. }
  954. return -1;
  955. }
  956. /*
  957. * 拟合过滤
  958. *
  959. * param
  960. * loc_point& c 最终保存点
  961. * const std::vector<point>& vp 可能解
  962. * const double scale 比例尺
  963. *
  964. * return
  965. *
  966. *
  967. * */
  968. bool select_point_object::filter_by_fit(loc_point & c,const std::vector<point> & vp,const double scale)
  969. {
  970. fit_result * fit = get_best_fit();
  971. if(fit==nullptr || m_begin==nullptr || fit->ke>2)
  972. return false;
  973. loc_point &f = *m_begin;
  974. std::array<solpoint,4> v;
  975. int cnt = vp.size();
  976. for(int i=0;i<cnt;i++)
  977. {
  978. v[i].set_sol(vp[i],fabs(fit->testk(c.m_time/1000.,f.dist_direct(vp[i]))));
  979. }
  980. std::sort(&v[0],&v[0]+cnt);
  981. double a = getA(fit,scale,v[1].score()-v[0].score());
  982. if(a<0)
  983. return false;
  984. if(!filter_by_acc(c,v,a))
  985. {
  986. c.set_cl(0);
  987. return true; //false?
  988. }
  989. reset_fit(vp[0].dist(v[0]));
  990. c[0]=v[0];
  991. c[1]=v[1];
  992. return true;
  993. }
  994. /*
  995. * 加速度过滤
  996. *
  997. * param
  998. * loc_point& c
  999. * std::array<solpoint, 4>& v
  1000. * double e
  1001. *
  1002. * return
  1003. *
  1004. * */
  1005. bool select_point_object::filter_by_acc(loc_point&c,std::array<solpoint,4>&v,double a)
  1006. {
  1007. if(!m_last->is_same_site(c))
  1008. return true;
  1009. double td=m_last->time_off(c);
  1010. if(v[0].score()>a*td*td)
  1011. return false;
  1012. return true;
  1013. }
  1014. /*
  1015. *
  1016. * */
  1017. void select_point_object::select_one_ant(loc_point &c,const std::vector<point> & vp)
  1018. {
  1019. int last=find_last(1);
  1020. if(last>0)
  1021. {
  1022. loc_point&p=m_d(last);
  1023. int cnt=vp.size();
  1024. std::array<solpoint,4> res;
  1025. //find the shortest dis
  1026. for(int i=0;i<cnt;i++)
  1027. res[i].set_sol(vp[i],vp[i].dist(p[0]));
  1028. std::sort(&res[0],&res[0]+cnt);
  1029. c[1].set(res[1]);
  1030. c[0].set(res[0]);
  1031. c.inc_cl(5);
  1032. }
  1033. }
  1034. point select_point_object::select_solution0(std::vector<point> &tvp,const double scale)
  1035. {
  1036. loc_point&c=m_d(0);
  1037. if(m_d.size()==1)
  1038. {
  1039. //first point ,only accpet two ants good data.
  1040. if(c.cl()>0 && tvp.size()<4)
  1041. {
  1042. c[1]=tvp[1];
  1043. return c[0]=tvp[0];
  1044. }
  1045. m_d.skip(1);
  1046. return point(0,0);
  1047. }
  1048. select_solution1(c,tvp,scale);
  1049. return c[0];
  1050. }
  1051. bool select_point_object::select_solution(const std::vector<point> &vp,const site*sit,loc_point &p)
  1052. {
  1053. remove_history();
  1054. std::vector<point> tvp(vp.begin(),vp.end());
  1055. if(vp.size()==4)
  1056. {
  1057. int c = 0;
  1058. std::array<solpoint,4> res;
  1059. for(int i=0;i<2;i++)
  1060. {
  1061. int x = i+2;
  1062. double d=vp[i].dist(vp[x]);
  1063. if(d<sit->ant_dist()*3)
  1064. {
  1065. res[c++].set_sol(vp[i].middle(vp[x]),d);
  1066. }
  1067. else
  1068. {
  1069. res[c++].set_sol(vp[i]);
  1070. res[c++].set_sol(vp[x]);
  1071. }
  1072. }
  1073. std::sort(&res[0],&res[0]+c);
  1074. tvp.clear();
  1075. for(int i=0;i<c;i++)
  1076. tvp.push_back(res[i]);
  1077. m_d(0).inc_cl(10);
  1078. }
  1079. point pt = select_solution0(tvp,sit->m_scale);
  1080. if(pt.empty() || m_d.empty())
  1081. return false;
  1082. m_d(0).set(pt);
  1083. if(!m_d(0).empty())
  1084. m_d(0).m_dist=sit->dist_direct(pt);
  1085. else
  1086. {
  1087. m_d(0).set_cl(0);
  1088. if(m_last) m_d(0).m_dist=0.01*m_last->m_dist>0?1:-1;
  1089. }
  1090. m_d(0).m_dist1 = sit->dist_direct(pt);
  1091. bool fg = revise_by_history(pt,sit,m_d(0).m_time);
  1092. if(!fg)
  1093. {
  1094. 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);
  1095. return false;
  1096. }
  1097. if(!card_path::inst().is_at_path(pt))
  1098. {
  1099. m_d(0).set_cl(0);
  1100. 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);
  1101. return false;
  1102. }
  1103. m_last=&m_d(0);
  1104. if(m_line.empty() && m_d.size()>=2 && !make_line())
  1105. return false;
  1106. if(!m_line.contain(m_d(0),0.01) || (m_begin && !m_line.contain(m_begin->m_sol[0], 0.01)))
  1107. {
  1108. m_fitk.reset_data();
  1109. m_fita.reset_data();
  1110. m_begin=m_last=nullptr;
  1111. int i0=find_last(1);
  1112. if(i0==-1)
  1113. return false;
  1114. std::vector<point> path=card_path::inst().find_path(m_d(i0),m_d(0));
  1115. m_d.skip(m_d.size()-i0);
  1116. if(path.empty())
  1117. {
  1118. m_line.clear();
  1119. return false;
  1120. }
  1121. m_line.set(path.back(),m_d(0));
  1122. }
  1123. if(!m_begin)
  1124. {
  1125. int idx=find_first(0);
  1126. if(idx>=0) m_begin=&m_d[idx];
  1127. }
  1128. if(!m_last)
  1129. {
  1130. int idx=find_last(0);
  1131. if(idx>=0) m_last=&m_d(idx);
  1132. }
  1133. if(m_begin && m_d(0).cl())
  1134. {
  1135. int lastID1=find_last(1);
  1136. int lastID2=-1;
  1137. if(lastID1!=-1)
  1138. lastID2=find_last(lastID1+1);
  1139. if(lastID2!=-1)
  1140. {
  1141. double t0=m_last->m_time/1000., t1=m_d(lastID1).m_time/1000., t2=m_d(lastID2).m_time/1000.;
  1142. double d0=m_begin->loc_dist(*m_last), d1=m_begin->loc_dist(m_d(lastID1)), d2=m_begin->loc_dist(m_d(lastID2));
  1143. double k1=(d1-d0)/(t1-t0), k2=(d2-d1)/(t2-t1);
  1144. if(t0-t1<5 && t1-t2<5 && fabs(k2-k1)<0.5)
  1145. {
  1146. double tbegin = t0-3;
  1147. while(tbegin<t1+0.5)
  1148. tbegin=tbegin+1;
  1149. double tk=(d0-d1)/(t0-t1), tb=d1-tk*t1; //d1+(d0-d1)/(t0-t1)*(t-t1)
  1150. for(double ti=tbegin;ti<t0;ti=ti+1)
  1151. {
  1152. m_fitk.add(ti, tk*ti+tb);
  1153. }
  1154. }
  1155. }
  1156. m_fitk.add(m_last->m_time/1000.,m_begin->loc_dist(*m_last));
  1157. if(m_d.size()>1)
  1158. {
  1159. int pre=find_last(1);
  1160. if(pre>0)
  1161. {
  1162. m_fita.add(m_d(0).m_time/1000.,m_begin->loc_dist(m_d(0))-m_begin->loc_dist(m_d(pre)));
  1163. }
  1164. }
  1165. }
  1166. p.set(pt);
  1167. save_k();
  1168. p.m_useless=fg;
  1169. return true;
  1170. }
  1171. bool select_point_object::make_line()
  1172. {
  1173. int i0=-1,i1=-1;
  1174. if(-1==(i0=find_last(0)))
  1175. return false;
  1176. if(-1==(i1=find_last(i0+1)))
  1177. return false;
  1178. m_line.set(m_d(i0),m_d(i1));
  1179. return true;
  1180. }
  1181. void select_point_object::remove_history()
  1182. {
  1183. loc_point&b=m_d(0);
  1184. if(m_d.size()>120 || (m_d.size()>2 && m_d(1).time_off(b)>max_histime))
  1185. {
  1186. m_d.skip_if([&b,this](loc_point&p){
  1187. return p.time_off(b)>max_histime;
  1188. });
  1189. m_fitk.reset_data();
  1190. m_fita.reset_data();
  1191. m_cur_fit.reset();
  1192. m_begin=m_last=nullptr;
  1193. int idx=find_first(0);
  1194. if(idx<0)
  1195. return;
  1196. m_begin=&m_d[idx];
  1197. idx=find_last(1);
  1198. m_last=&m_d(idx);
  1199. double dist=0,dist2=0;
  1200. for(int len=std::min(15,m_d.size()-1),i=len;i>0;i--)
  1201. {
  1202. if(!m_d(i).cl())
  1203. continue;
  1204. int lastID1=find_last(i+1);
  1205. int lastID2=-1;
  1206. if(lastID1!=-1)
  1207. lastID2=find_last(lastID1+1);
  1208. if(lastID2!=-1)
  1209. {
  1210. double t0=m_d(i).m_time/1000., t1=m_d(lastID1).m_time/1000., t2=m_d(lastID2).m_time/1000.;
  1211. double d0=m_begin->loc_dist(m_d(i)[0]), d1=m_begin->loc_dist(m_d(lastID1)[0]),
  1212. d2=m_begin->loc_dist(m_d(lastID2)[0]);
  1213. double k1=(d1-d0)/(t1-t0), k2=(d2-d1)/(t2-t1);
  1214. if(t0-t1<5 && t1-t2<5 && fabs(k2-k1)<0.5)
  1215. {
  1216. double tbegin = t0-3;
  1217. while(tbegin<t1+0.5)
  1218. tbegin=tbegin+1;
  1219. double tk=(d0-d1)/(t0-t1), tb=d1-tk*t1; //d1+(d0-d1)/(t0-t1)*(t-t1)
  1220. for(double ti=tbegin;ti<t0;ti=ti+1)
  1221. {
  1222. m_fitk.add(ti, tk*ti+tb);
  1223. }
  1224. }
  1225. }
  1226. dist=m_begin->loc_dist(m_d(i)[0]);
  1227. m_fitk.add(m_d(i).m_time/1000.,dist);
  1228. if(i==len)
  1229. continue;
  1230. m_fita.add(m_d(i).m_time/1000.,dist-dist2);
  1231. dist2=dist;
  1232. }
  1233. save_k();
  1234. }
  1235. }
  1236. void select_point_object::save_k()
  1237. {
  1238. const fit_result*fk=best_fit_raw(0,4);
  1239. if(!fk)
  1240. {
  1241. m_cur_fit.reset();
  1242. return;
  1243. }
  1244. m_cur_fit=*fk;
  1245. fit_result&r=m_cur_fit;
  1246. card_fit*fa=&m_fita[0];
  1247. if(fa->is_valid() && fa->ke<0.1 && fk->k*fa->k<0)
  1248. {
  1249. double dk=fa->k*fa->num_point;
  1250. r.ka=fa->k;
  1251. if((fk->k+dk)*fk->k<0)
  1252. r.k=0;
  1253. else
  1254. r.k+=dk;
  1255. double y=fk->k*m_fitk(0).x+fk->kb;
  1256. r.kb=y-m_fitk(0).x*r.k;
  1257. }
  1258. }
  1259. fit_result* select_point_object::best_fit_raw(int num_point,int start,int last)
  1260. {
  1261. card_fit*fit = nullptr;
  1262. start = std::max(start,0);
  1263. last = std::min(last,m_fitk.tool_size());
  1264. if(last == -1)
  1265. last = m_fitk.tool_size();
  1266. for(int i = start; i < last; i++)
  1267. {
  1268. if(!m_fitk[i].is_valid())
  1269. continue;
  1270. if(m_fitk[i].num_point < num_point)
  1271. continue;
  1272. if(fit == nullptr)
  1273. {
  1274. fit = &m_fitk[i];
  1275. continue;
  1276. }
  1277. if(fit->ke > m_fitk[i].ke)
  1278. {
  1279. fit = &m_fitk[i];
  1280. }
  1281. }
  1282. return fit;
  1283. }
  1284. select_tool::~select_tool()
  1285. {
  1286. if(m_spo !=nullptr)
  1287. delete m_spo;
  1288. }
  1289. loc_point select_tool_person_1::select_solution(const std::vector<point> vp,const std::vector<loc_message>&lm)
  1290. {
  1291. loc_point lp;
  1292. //select point.
  1293. uint8_t idx = 0;
  1294. uint8_t type = lm[0].tool_index()>>4;
  1295. uint8_t dim = lm[0].tool_index() & 0x03;
  1296. idx = type*3 + dim - 1;
  1297. //logn_info(3, "[pdoa] card_id=%d, idx=%d, dim=%d", lm[0].m_card_id, idx, dim);
  1298. if(idx == 0)
  1299. {
  1300. if(m_spo==nullptr)
  1301. m_spo = new person_point_filter(this);
  1302. lp=m_spo->select_solution_impl(vp,lm);
  1303. }
  1304. else if (idx == 2)
  1305. {
  1306. //for now..
  1307. //m_spo = new person_point_filter();
  1308. //lp=m_spo->select_solution_impl(vp,lm);
  1309. }else if(6 == idx){
  1310. // pdoa一维定位
  1311. //logn_info(3, "[pdoa] person, select_solution 1d, tool_index=%d", idx);
  1312. if(nullptr == m_spo){
  1313. m_spo= new person_point_filter(this);
  1314. }
  1315. lp = m_spo->select_solution_impl(vp, lm);
  1316. }else if(7 == idx){
  1317. // logn_info(3, "[pdoa] person, select_solution 2d, tool_index=%d", idx);
  1318. // pdoa二维定位
  1319. if(nullptr == m_spo){
  1320. m_spo = new person_point_filter(this);
  1321. }
  1322. lp = m_spo->select_solution_impl(vp, lm);
  1323. }else if(3 == idx){
  1324. }else if(4 == idx){
  1325. }else if(5 == idx){
  1326. }
  1327. else
  1328. {}
  1329. return lp;
  1330. }
  1331. loc_point select_tool_car_1::select_solution(const std::vector<point> vp,const std::vector<loc_message>&lm)
  1332. {
  1333. loc_point lp;
  1334. //select point.
  1335. uint8_t idx = 0;
  1336. uint8_t type = lm[0].tool_index()>>4;
  1337. uint8_t dim = lm[0].tool_index() & 0x03;
  1338. dim = 1;// modified by zengminguo 矿上默认为一维
  1339. idx = type*3 + dim - 1;
  1340. if(idx == 0)
  1341. {
  1342. if(m_spo==nullptr)
  1343. m_spo = new car_point_filter(this);
  1344. lp=m_spo->select_solution_impl(vp,lm);
  1345. }
  1346. else if (idx == 2)
  1347. {
  1348. //for now..
  1349. //m_spo = new car_point_filter();
  1350. //lp=m_spo->select_solution_impl(vp,lm);
  1351. }else if(6 == idx){
  1352. // pdoa一维定位
  1353. if(nullptr == m_spo){
  1354. m_spo = new car_point_filter(this);
  1355. }
  1356. lp = m_spo->select_solution_impl(vp, lm);
  1357. }else if(7 == idx){
  1358. // pdoa二维定位
  1359. if(nullptr == m_spo)
  1360. {
  1361. m_spo = new car_point_filter(this);
  1362. }
  1363. lp = m_spo->select_solution_impl(vp, lm);
  1364. }else if(3 == idx){
  1365. }else if(4 == idx){
  1366. }else if(5 == idx){
  1367. }
  1368. else
  1369. {}
  1370. return lp;
  1371. }
  1372. select_tool_manage * select_tool_manage::instance()
  1373. {
  1374. static select_tool_manage stm;
  1375. return &stm;
  1376. }