lct_main.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829
  1. // 秒寻科技
  2. // 定位主控模块
  3. // zt
  4. // 2023-03-25
  5. #include "../../includes/includes.h"
  6. #include "./lct_public.h"
  7. // 定义仅本模块使用的全局变量
  8. LCT_FIRSTPATH_LIST_T gLct_stFirstPathList = {0}; // 第一径数据队列
  9. LCT_FIRSTPATH_PREDICTION_DIRECTION_DATA_T gLct_astPredictionDirectionDataList[PUB_SYS_CARRIER_NUM] = {0}; // 预测移动方向数据队列
  10. LCT_COORDSEL_ORIGINAL_COORD_T gLct_stOriginalLctCoordList = {0}; // 原始定位坐标队列
  11. LCT_COORDSEL_MEAN_COORD_T gLct_stMeanLctCoordList = {0}; // 平滑定位坐标队列
  12. flt32 gLct_afMeanWeight[LCT_COORDSEL_ORIGINAL_COORD_LIST_LEN] = {0.20, 0.30, 0.50}; // 历史定位坐标权重
  13. uint32 gLct_dwPredictionTimes = 0; // 预测次数
  14. uint32 gLct_dwFpBaseOffset = 0; // 第一径基本偏移量
  15. // 导出全局变量
  16. extern PUB_SYS_STATUS_T gg_stSysStatus; // 系统运行状态
  17. extern uint32 gg_dwFrameNo; // 全局帧号
  18. void lct_main_init(LCT_FIRSTPATH_PARAM_T stLctFirstpathParam, LCT_COORDCAL_PARAM_T stLctCoordcalParam, LCT_COORDSEL_PARAM_T stLctCoordselParam)
  19. {
  20. // 第一径全局变量初始化
  21. memset(&gLct_stFirstPathList, 0, sizeof(LCT_FIRSTPATH_LIST_T));
  22. memset(&gLct_stOriginalLctCoordList, 0, sizeof(LCT_COORDSEL_ORIGINAL_COORD_T));
  23. memset(&gLct_stMeanLctCoordList, 0, sizeof(LCT_COORDSEL_MEAN_COORD_T));
  24. memset(gLct_astPredictionDirectionDataList, 0, sizeof(LCT_FIRSTPATH_PREDICTION_DIRECTION_DATA_T) * PUB_SYS_CARRIER_NUM);
  25. lct_firstpath_init(stLctFirstpathParam);
  26. lct_coordcal_init(stLctCoordcalParam);
  27. lct_coordsel_init(stLctCoordselParam);
  28. }
  29. // 模块全局数据结构复位
  30. void lct_main_reset()
  31. {
  32. // 系统处于待同步状态
  33. // if (!gg_stSysStatus.bySyncFlag || !gg_stSysStatus.byBtsCaptureFlag)
  34. if (!gg_stSysStatus.bySyncFlag)
  35. {
  36. memset(&gLct_stFirstPathList, 0, sizeof(LCT_FIRSTPATH_LIST_T));
  37. memset(&gLct_stOriginalLctCoordList, 0, sizeof(LCT_COORDSEL_ORIGINAL_COORD_T));
  38. memset(&gLct_stMeanLctCoordList, 0, sizeof(LCT_COORDSEL_MEAN_COORD_T));
  39. memset(gLct_astPredictionDirectionDataList, 0, sizeof(LCT_FIRSTPATH_PREDICTION_DIRECTION_DATA_T) * PUB_SYS_CARRIER_NUM);
  40. gLct_dwPredictionTimes = 0;
  41. gg_stSysStatus.byBtsCaptureFlag = 0; // 系统处于捕获基站状态
  42. gg_stSysStatus.byReLocationFlag = 0; // 系统进入重新定位状态
  43. }
  44. return;
  45. }
  46. // 定位主控函数
  47. // pstLctBtsList:一组定位基站
  48. // pstLctDataList:定位数据
  49. // pstCurrentLctResult:定位结果
  50. void lct_main(PUB_LCT_BTS_LIST_T *pstLctBtsList, PUB_LOCATION_DATA_T *pstLctDataList, PUB_CURRENT_LCT_RESULT_T *pstCurrentLctResult)
  51. {
  52. uint8 byRemainder = 0;
  53. LCT_FIRSTPATH_T *pstFirstPathList = NULL;
  54. uint8 byBtsNum = 0;
  55. LCT_MINIMUM_VALUE_GROUP_T stMinimumValueGroup = {0}; // 极小值数据组
  56. uint8 byPredictionFlag = 0; // 预测坐标成功标识符
  57. COORD_T stPredictionCoord = {0}; // 预测坐标
  58. uint16 wMinimumNum = 0;
  59. uint8 byCalMinimumNum = 0;
  60. uint8 byTrackMinimumNum = 0;
  61. uint8 byPredicMinimumNum = 0;
  62. LCT_COORDSEL_OPTIMUM_COORD_T stOptimumCoord = {0}; // 最优坐标
  63. uint32 dwMainBtsId = 0;
  64. int32 dwMainBtsBuildId = 0;
  65. int32 dwMainBtsLayerId = 0;
  66. uint8 byFlag = 0;
  67. COORD_T stMeanCoord = {0};
  68. PUB_LOCATION_DATA_T *pstLctData = NULL;
  69. uint8 byImuMoveFlag = 0; // imu计算结果,0:计算错误,1:成功,但静止,50:成功,但移动
  70. // 模块全局数据结构复位
  71. lct_main_reset();
  72. // 系统已经同步并且定位基站数量至少有3个
  73. if (gg_stSysStatus.bySyncFlag && pstLctBtsList->byBtsNum > 1)
  74. {
  75. // 当前帧需要定位
  76. byRemainder = (gg_dwFrameNo - 1) % PUB_SYS_SLOT_NUM;
  77. if (byRemainder == 0)
  78. {
  79. // 1、 计算第一径,生成基站第一径数据组,同时镜像基站第一径数据组
  80. lct_firstpath_main(pstLctBtsList, pstLctDataList, &gLct_stFirstPathList);
  81. // TODO测试用的代码
  82. if (PUB_DEBUG_ENABLE)
  83. {
  84. lct_main_write_text_file(&gLct_stFirstPathList);
  85. }
  86. // 2、根据基站第一径数据组计算“极小值数据组”
  87. lct_coordcal_main(pstLctBtsList, pstLctDataList, &gLct_stFirstPathList, &byPredictionFlag, &stPredictionCoord, &stMinimumValueGroup, &wMinimumNum);
  88. // 3、根据“极小值数据组”选择最优定位坐标
  89. if (wMinimumNum > 0)
  90. {
  91. // 选择坐标
  92. lct_coordsel_main(&stMinimumValueGroup, byPredictionFlag, stPredictionCoord, &stOptimumCoord);
  93. // 存在有效的极小值点
  94. if (stOptimumCoord.byResultFlag)
  95. {
  96. // 定位坐标来自预测
  97. if (stOptimumCoord.bySourceFlag == 3)
  98. {
  99. gLct_dwPredictionTimes++;
  100. }
  101. else
  102. {
  103. gLct_dwPredictionTimes = 0;
  104. }
  105. // 连续4次使用预测坐标,则停止输出
  106. if (gLct_dwPredictionTimes >= LCT_MAIN_MAX_USE_PREDICTION_COORD_TIMES)
  107. {
  108. pstCurrentLctResult->dwCpltFlag = 1; // 定位完成
  109. pstCurrentLctResult->dwSuccessFlag = 1; // 定位成功
  110. gg_stSysStatus.byBtsCaptureFlag = 0; // 系统进入基站捕获阶段
  111. gg_stSysStatus.byReLocationFlag = 1; // 重新定位标识符置1
  112. }
  113. else
  114. {
  115. pstCurrentLctResult->dwCpltFlag = 1; // 定位完成
  116. pstCurrentLctResult->dwSuccessFlag = 1; // 定位成功
  117. gg_stSysStatus.byBtsCaptureFlag = 1; // 系统进入基站跟踪阶段
  118. gg_stSysStatus.byReLocationFlag = 0; // 重新定位标识符置0
  119. }
  120. // 二次校验坐标(已改成在计算模块校验)
  121. // lct_main_dbcheck_coord_by_bts_polygon(&gLct_stFirstPathList, &stOptimumCoord);
  122. // 根据定位结果,更新基站第一径帧内跟踪索引
  123. lct_main_update_bts_firstpath_trace_index(stOptimumCoord.bySourceFlag, &gLct_stFirstPathList, pstLctDataList);
  124. // 查找主站,包括所在的大楼编号、楼层编号和基站编号
  125. lct_main_find_main_bts(&gLct_stFirstPathList, &dwMainBtsId, &dwMainBtsBuildId, &dwMainBtsLayerId);
  126. // 保存原始坐标
  127. lct_main_save_original_coord(dwMainBtsBuildId, dwMainBtsLayerId, stOptimumCoord.stCoord, &gLct_stOriginalLctCoordList);
  128. stMeanCoord = stOptimumCoord.stCoord;
  129. // 平滑原始坐标
  130. lct_main_mean_original_coord(&gLct_stOriginalLctCoordList, gLct_afMeanWeight, &gLct_stMeanLctCoordList, &stMeanCoord);
  131. // 计算第一径基本偏移量
  132. lct_toa_cal_bts_first_path_index_offset(stOptimumCoord.bySourceFlag, &gLct_stFirstPathList, &gLct_stMeanLctCoordList, gLct_dwFpBaseOffset, &gLct_dwFpBaseOffset);
  133. // 根据定位坐标修改手机相对于基站的移动趋势
  134. lct_main_update_phone_tendency(&gLct_stMeanLctCoordList, gLct_astPredictionDirectionDataList);
  135. // 通过imu计算位移,判断手机是否移动
  136. byImuMoveFlag = imu_cal_distance_lct();
  137. // 组织定位结果
  138. lct_main_organize_lct_result(dwMainBtsBuildId, dwMainBtsLayerId, &gLct_stFirstPathList, &stMeanCoord, byImuMoveFlag, pstCurrentLctResult);
  139. // TODO测试
  140. if (PUB_DEBUG_ENABLE)
  141. {
  142. printf("frame no:%d, source:%d, x :%d, y: %d\n", gg_dwFrameNo - 1, stOptimumCoord.bySourceFlag, stMeanCoord.dwX, stMeanCoord.dwY);
  143. char *filePathx = "E:\\work\\ips8000\\aplm8000sdk\\output\\coord\\coordx.bin";
  144. char *filePathy = "E:\\work\\ips8000\\aplm8000sdk\\output\\coord\\coordy.bin";
  145. util_write_coord_to_bin_file(filePathx, 1, (uint32 *)&stMeanCoord.dwX);
  146. util_write_coord_to_bin_file(filePathy, 1, (uint32 *)&stMeanCoord.dwY);
  147. }
  148. }
  149. // 没有有效的极小值点
  150. else
  151. {
  152. pstCurrentLctResult->dwCpltFlag = 1; // 定位完成
  153. pstCurrentLctResult->dwSuccessFlag = 0; // 定位失败
  154. gg_stSysStatus.byBtsCaptureFlag = 0;
  155. // 清空定位数据中第一径数据
  156. for (uint8 i = 0; i < PUB_SYS_CARRIER_NUM; i++)
  157. {
  158. pstLctData = &pstLctDataList[i];
  159. pstLctData->wAheadFrameCalPahtIndex = 0;
  160. pstLctData->wAheadFrameTrackPathIndex = 0;
  161. }
  162. printf("minimum avalid\n");
  163. }
  164. }
  165. else
  166. {
  167. pstCurrentLctResult->dwCpltFlag = 1; // 定位完成
  168. pstCurrentLctResult->dwSuccessFlag = 0; // 定位失败
  169. gg_stSysStatus.byBtsCaptureFlag = 0;
  170. // 清空定位数据中第一径数据
  171. for (uint8 i = 0; i < PUB_SYS_CARRIER_NUM; i++)
  172. {
  173. pstLctData = &pstLctDataList[i];
  174. pstLctData->wAheadFrameCalPahtIndex = 0;
  175. pstLctData->wAheadFrameTrackPathIndex = 0;
  176. }
  177. printf("no minimum\n");
  178. }
  179. }
  180. }
  181. else
  182. {
  183. printf("error, sync flag:%d, bts num:%d\n", gg_stSysStatus.bySyncFlag, pstLctBtsList->byBtsNum);
  184. }
  185. return;
  186. }
  187. // 根据基站多边形再次校验定位坐标
  188. void lct_main_dbcheck_coord_by_bts_polygon(LCT_FIRSTPATH_LIST_T *pstBtsFirstPathList, LCT_COORDSEL_OPTIMUM_COORD_T *pstOptimumCoord)
  189. {
  190. uint8 byFirstPathListLen = pstBtsFirstPathList->byBtsNum; // 基站数量
  191. LCT_FIRSTPATH_T *pstFirstPathList = pstBtsFirstPathList->astFirstPath;
  192. int32 dwTemp = 0;
  193. int32 dwMinValueX = 2147483647;
  194. int32 dwMaxValueX = -2147483648;
  195. int32 dwMinValueY = 2147483647;
  196. int32 dwMaxValueY = -2147483648;
  197. uint32 dwGapX = 0;
  198. uint32 dwGapY = 0;
  199. int32 dwX = 0;
  200. int32 dwY = 0;
  201. ////计算端点坐标的最大值与最小值
  202. for (uint8 i = 0; i < byFirstPathListLen; i++)
  203. {
  204. dwTemp = pstFirstPathList[i].dwCoordX;
  205. if (dwTemp > dwMaxValueX)
  206. {
  207. dwMaxValueX = dwTemp;
  208. }
  209. if (dwTemp < dwMinValueX)
  210. {
  211. dwMinValueX = dwTemp;
  212. }
  213. dwTemp = pstFirstPathList[i].dwCoordY;
  214. if (dwTemp > dwMaxValueY)
  215. {
  216. dwMaxValueY = dwTemp;
  217. }
  218. if (dwTemp < dwMinValueY)
  219. {
  220. dwMinValueY = dwTemp;
  221. }
  222. }
  223. // 计算基站坐标间隔
  224. dwGapX = dwMaxValueX - dwMinValueX;
  225. dwGapY = dwMaxValueY - dwMinValueY;
  226. // 校验X坐标
  227. dwX = pstOptimumCoord->stCoord.dwX;
  228. if (dwGapX < 350)
  229. {
  230. dwX = util_distance_gen_rand_num((dwMaxValueX + dwMinValueX) / 2, 50);
  231. }
  232. else if (dwGapX >= 350 && dwGapX < 900)
  233. {
  234. dwX = pstOptimumCoord->stCoord.dwX * 0.85;
  235. }
  236. else if (dwGapX >= 900 && dwGapX < 1500)
  237. {
  238. dwX = pstOptimumCoord->stCoord.dwX * 0.95;
  239. }
  240. // 校验Y坐标
  241. dwY = pstOptimumCoord->stCoord.dwY;
  242. if (dwGapY < 350)
  243. {
  244. dwY = util_distance_gen_rand_num((dwMaxValueY + dwMinValueY) / 2, 50);
  245. }
  246. else if (dwGapY >= 350 && dwGapY < 900)
  247. {
  248. dwY = pstOptimumCoord->stCoord.dwY * 0.85;
  249. }
  250. else if (dwGapY >= 900 && dwGapY < 1500)
  251. {
  252. dwY = pstOptimumCoord->stCoord.dwY * 0.95;
  253. }
  254. // 修改
  255. pstOptimumCoord->stCoord.dwX = dwX;
  256. pstOptimumCoord->stCoord.dwY = dwY;
  257. return;
  258. }
  259. // 根据一个数,在该数左右两侧范围内生成一个随机数
  260. // dwBaseData:基数
  261. // wRange:单边偏移
  262. int32 lct_main_gen_rand_num(int32 dwBaseData, uint16 wRange)
  263. {
  264. int32 dwTotalRange = 2 * wRange + 1; // 总范围
  265. int32 dwRemainder = 0;
  266. int32 randomNum = 0; // 随机数
  267. // 初始化随机数生成器
  268. srand(time(NULL));
  269. // 生成随机数
  270. dwRemainder = rand() % dwTotalRange; // 生成 [0, dwTotalRange) 范围内的随机数
  271. randomNum = dwBaseData - wRange + dwRemainder; // 生成所需的随机数
  272. return randomNum;
  273. }
  274. // 根据定位结果,更新基站第一径帧内跟踪索引
  275. // byLctSourceFlag:定位使用的第一径来源
  276. // pstBtsFirstPathList:基站第一径数据队列
  277. // pstLctDataList:定位数据
  278. void lct_main_update_bts_firstpath_trace_index(uint8 byLctSourceFlag, LCT_FIRSTPATH_LIST_T *pstBtsFirstPathList, PUB_LOCATION_DATA_T *pstLctDataList)
  279. {
  280. uint8 byBtsNum = pstBtsFirstPathList->byBtsNum;
  281. LCT_FIRSTPATH_T *pstFirstPathList = NULL;
  282. uint16 wFrameTraceIndex = 0;
  283. uint8 byFreqIndex = 0;
  284. PUB_LOCATION_DATA_T *pstLctData = NULL;
  285. for (uint8 i = 0; i < byBtsNum; i++)
  286. {
  287. pstFirstPathList = &pstBtsFirstPathList->astFirstPath[i];
  288. // 最优定位坐标来自计算径
  289. if (byLctSourceFlag == 1)
  290. {
  291. wFrameTraceIndex = pstFirstPathList->wFrameCalIndex;
  292. }
  293. // 最优定位坐标来自跟踪径
  294. else if (byLctSourceFlag == 2)
  295. {
  296. wFrameTraceIndex = pstFirstPathList->wFrameTrackIndex;
  297. }
  298. // 最优定位坐标来自预测径
  299. else
  300. {
  301. wFrameTraceIndex = 0;
  302. }
  303. // 跟新"跟踪径"
  304. pstFirstPathList->wFrameTrackIndex = wFrameTraceIndex;
  305. }
  306. // 将跟踪索引更新到定位数据中
  307. for (uint8 j = 0; j < PUB_SYS_CARRIER_NUM; j++)
  308. {
  309. pstLctData = &pstLctDataList[j];
  310. pstLctData->wAheadFrameCalPahtIndex = 0;
  311. pstLctData->wAheadFrameTrackPathIndex = 0;
  312. }
  313. for (uint8 k = 0; k < byBtsNum; k++)
  314. {
  315. pstFirstPathList = &pstBtsFirstPathList->astFirstPath[k];
  316. byFreqIndex = pstFirstPathList->byFreqIndex;
  317. pstLctData = &pstLctDataList[byFreqIndex];
  318. pstLctData->wAheadFrameCalPahtIndex = pstFirstPathList->wFrameCalIndex;
  319. pstLctData->wAheadFrameTrackPathIndex = pstFirstPathList->wFrameTrackIndex;
  320. }
  321. return;
  322. }
  323. // 从第一径数据队列中查找主站信息
  324. void lct_main_find_main_bts(LCT_FIRSTPATH_LIST_T *pstFirstPathList, uint32 *pdwBtsId, int32 *pwBuildId, int32 *pdwLayerId)
  325. {
  326. LCT_FIRSTPATH_T *pstFirstPahtData = NULL;
  327. uint8 byExist = 0;
  328. for (uint8 i = 0; i < pstFirstPathList->byBtsNum; i++)
  329. {
  330. pstFirstPahtData = &pstFirstPathList->astFirstPath[i];
  331. if (pstFirstPahtData->byMainFlag == 1)
  332. {
  333. *pdwBtsId = pstFirstPahtData->dwBtsId;
  334. *pwBuildId = pstFirstPahtData->dwBuildId;
  335. *pdwLayerId = pstFirstPahtData->dwLayerId;
  336. byExist = 1;
  337. break;
  338. }
  339. }
  340. if (!byExist)
  341. {
  342. pstFirstPahtData = &pstFirstPathList->astFirstPath[0];
  343. *pdwBtsId = pstFirstPahtData->dwBtsId;
  344. *pwBuildId = pstFirstPahtData->dwBuildId;
  345. *pdwLayerId = pstFirstPahtData->dwLayerId;
  346. }
  347. return;
  348. }
  349. // 保存原始定位坐标
  350. // stCoord:定位点坐标
  351. // pstOriginalLctCoordList:原始定位坐标队列
  352. void lct_main_save_original_coord(int32 dwBuildId, int32 dwLayerId, COORD_T stCoord, LCT_COORDSEL_ORIGINAL_COORD_T *pstOriginalLctCoordList)
  353. {
  354. uint8 byCoordListLen = pstOriginalLctCoordList->byListLen; // 原始定位坐标队列长度
  355. // TODO(以后要修改成支持多个大楼和多个楼层) 保存大楼编号和楼层编号
  356. gg_stSysStatus.dwBuildId = dwBuildId;
  357. gg_stSysStatus.dwLayerId = dwLayerId;
  358. // 队列没有满
  359. if (byCoordListLen < LCT_COORDSEL_ORIGINAL_COORD_LIST_LEN)
  360. {
  361. pstOriginalLctCoordList->astCoordList[byCoordListLen] = stCoord;
  362. pstOriginalLctCoordList->byListLen++;
  363. }
  364. // 队列已满
  365. else
  366. {
  367. // 移动队列
  368. memmove(pstOriginalLctCoordList->astCoordList, &pstOriginalLctCoordList->astCoordList[1], sizeof(COORD_T) * (LCT_COORDSEL_ORIGINAL_COORD_LIST_LEN - 1));
  369. pstOriginalLctCoordList->astCoordList[LCT_COORDSEL_ORIGINAL_COORD_LIST_LEN - 1] = stCoord; // 将数据插入队列尾
  370. }
  371. return;
  372. }
  373. // 平滑原始定位坐标
  374. // pstOriginalLctCoordList:原始定位坐标队列
  375. // pfMeanWeightList:平滑权重
  376. // pstMeanCoord:返回参数,平滑坐标
  377. void lct_main_mean_original_coord(LCT_COORDSEL_ORIGINAL_COORD_T *pstOriginalLctCoordList, flt32 *pfMeanWeightList, LCT_COORDSEL_MEAN_COORD_T *pstMeanCoordList, COORD_T *pstMeanCoord)
  378. {
  379. uint8 byListLen = pstOriginalLctCoordList->byListLen;
  380. flt32 fX = 0;
  381. flt32 fY = 0;
  382. uint8 byCoordListLen = pstMeanCoordList->byListLen; // 平滑坐标队列
  383. // 原始坐标队列长度不合法
  384. if ((byListLen < LCT_COORDSEL_ORIGINAL_COORD_LIST_LEN))
  385. {
  386. return;
  387. }
  388. //// 平滑坐标
  389. for (uint8 i = 0; i < byListLen; i++)
  390. {
  391. fX += pstOriginalLctCoordList->astCoordList[i].dwX * pfMeanWeightList[i];
  392. fY += pstOriginalLctCoordList->astCoordList[i].dwY * pfMeanWeightList[i];
  393. }
  394. pstMeanCoord->dwX = fX;
  395. pstMeanCoord->dwY = fY;
  396. pstMeanCoord->dwZ = 120;
  397. //// 保存平滑后的坐标
  398. // 队列没有满
  399. if (byCoordListLen < LCT_COORDSEL_MEAN_COORD_LIST_LEN)
  400. {
  401. pstMeanCoordList->astCoordList[byCoordListLen] = *pstMeanCoord;
  402. pstMeanCoordList->byListLen++;
  403. }
  404. // 队列已满
  405. else
  406. {
  407. // 移动队列
  408. memmove(pstMeanCoordList->astCoordList, &pstMeanCoordList->astCoordList[1], sizeof(COORD_T) * (LCT_COORDSEL_MEAN_COORD_LIST_LEN - 1));
  409. pstMeanCoordList->astCoordList[LCT_COORDSEL_MEAN_COORD_LIST_LEN - 1] = *pstMeanCoord; // 将数据插入队列尾
  410. }
  411. return;
  412. }
  413. // 组织定位结果
  414. // dwBuildId:大楼编号
  415. // dwLayerId:楼层编号
  416. // pstFirstPathList:定位基站第一径队列
  417. // pstMeanCoord:平滑坐标
  418. // pstCurrentLctResult:定位结果
  419. void lct_main_organize_lct_result(int32 dwBuildId, int32 dwLayerId, LCT_FIRSTPATH_LIST_T *pstFirstPathList, COORD_T *pstMeanCoord, uint32 dwImuMoveFlag, PUB_CURRENT_LCT_RESULT_T *pstCurrentLctResult)
  420. {
  421. uint8 byBtsNum = pstFirstPathList->byBtsNum;
  422. PUB_LCT_BTS_T *pstLctBtsData = NULL;
  423. uint8 byExist = 0;
  424. // 1、 保存定位坐标坐标
  425. pstCurrentLctResult->stCoord = *pstMeanCoord;
  426. // 2、查找定位主站并保存大楼和楼层
  427. pstCurrentLctResult->dwBuildId = dwBuildId;
  428. pstCurrentLctResult->dwLayerId = dwLayerId;
  429. // 3、保存基站数据
  430. pstCurrentLctResult->dwLctBtsNum = byBtsNum; // 基站数量
  431. for (uint8 i = 0; i < byBtsNum; i++)
  432. {
  433. pstCurrentLctResult->adwBtsIdList[i] = pstFirstPathList->astFirstPath[i].dwBtsId; // 基站ID
  434. }
  435. // 4、保存IMU移动标识符
  436. pstCurrentLctResult->dwImuMoveFlag = dwImuMoveFlag;
  437. return;
  438. }
  439. // 保存平滑坐标
  440. // stCoord:定位点坐标
  441. // pstMeanCoordList:平滑队列
  442. void lct_main_save_mean_coord(COORD_T stCoord, LCT_COORDSEL_MEAN_COORD_T *pstMeanCoordList)
  443. {
  444. uint8 byCoordListLen = pstMeanCoordList->byListLen; // 平滑坐标队列
  445. // 队列没有满
  446. if (byCoordListLen < LCT_COORDSEL_MEAN_COORD_LIST_LEN)
  447. {
  448. pstMeanCoordList->astCoordList[byCoordListLen] = stCoord;
  449. pstMeanCoordList->byListLen++;
  450. }
  451. // 队列已满
  452. else
  453. {
  454. // 移动队列
  455. memmove(pstMeanCoordList->astCoordList, &pstMeanCoordList->astCoordList[1], sizeof(COORD_T) * (LCT_COORDSEL_MEAN_COORD_LIST_LEN - 1));
  456. pstMeanCoordList->astCoordList[LCT_COORDSEL_MEAN_COORD_LIST_LEN - 1] = stCoord; // 将数据插入队列尾
  457. }
  458. return;
  459. }
  460. // 根据定位坐标反算从站第一径相对主站第一径的偏移量
  461. // pstAheadLctFirstPahtGroup:前一次基站第一径数据组PU
  462. // stLctCoord:定位坐标
  463. // byPathSource:第一径源,1:计算径、2:跟踪径:3:预测径
  464. void lct_main_adjust_firstpath_index_offset(LCT_FIRSTPATH_LIST_T *pstAheadLctFirstPahtGroup, COORD_T stLctCoord, uint8 byPathSource, PUB_LOCATION_DATA_T *pstLctDataList)
  465. {
  466. uint8 byBtsNum = pstAheadLctFirstPahtGroup->byBtsNum;
  467. LCT_FIRSTPATH_T stMainBtsFirstPath = {0};
  468. LCT_FIRSTPATH_T *pstSlaveBtsFirstPath = NULL;
  469. uint8 byMainFlag = 0;
  470. flt32 fMainTimeLen = 0;
  471. int32 dwMainAbsoluteIndex = 0;
  472. flt32 fSlaveTimeLen = 0;
  473. int32 dwSlaveAbsoluteIndex = 0;
  474. flt32 fDelayDiff = 0;
  475. int32 xx = 0;
  476. int32 yy = 0;
  477. int32 zz = 0;
  478. flt32 fDistance = 0;
  479. int32 dwTimeOffset = 0;
  480. int32 dwSampleOffset = 0;
  481. int32 dwIndexOffset = 0;
  482. // 找主站
  483. for (uint8 i = 0; i < byBtsNum; i++)
  484. {
  485. stMainBtsFirstPath = pstAheadLctFirstPahtGroup->astFirstPath[i];
  486. if (stMainBtsFirstPath.byMainFlag == 1)
  487. {
  488. byMainFlag = 1;
  489. break;
  490. }
  491. }
  492. // 未找到主站
  493. if (!byMainFlag)
  494. {
  495. return;
  496. }
  497. // 计算主站传输时长
  498. xx = stLctCoord.dwX - stMainBtsFirstPath.dwCoordX;
  499. yy = stLctCoord.dwY - stMainBtsFirstPath.dwCoordY;
  500. zz = stLctCoord.dwZ - stMainBtsFirstPath.dwCoordZ;
  501. fDistance = sqrt(xx * xx + yy * yy + zz * zz);
  502. fMainTimeLen = fDistance / 100 / PUB_AUDIO_SPEED * 1000; // 单位毫秒
  503. // 计算从站与主站间的时延差,并反算索引偏差
  504. for (uint8 j = 0; j < byBtsNum; j++)
  505. {
  506. pstSlaveBtsFirstPath = &pstAheadLctFirstPahtGroup->astFirstPath[j];
  507. // 当前站是从站
  508. if (pstSlaveBtsFirstPath->byMainFlag == 2)
  509. {
  510. // 计算定位点到从站间的传输时长
  511. xx = stLctCoord.dwX - pstSlaveBtsFirstPath->dwCoordX;
  512. yy = stLctCoord.dwY - pstSlaveBtsFirstPath->dwCoordY;
  513. zz = stLctCoord.dwZ - pstSlaveBtsFirstPath->dwCoordZ;
  514. fDistance = sqrt(xx * xx + yy * yy + zz * zz);
  515. fSlaveTimeLen = fDistance / 100 / PUB_AUDIO_SPEED * 1000; // 从站传输时长,单位毫秒
  516. // 定位点到主站与到从站间的时长差
  517. fDelayDiff = (fSlaveTimeLen - fMainTimeLen); // 毫秒
  518. // 计算从站第一径与主站第一径的索引偏差(绝对偏移)
  519. dwTimeOffset = (int32)(48 * fDelayDiff);
  520. if (byPathSource == 1)
  521. {
  522. dwMainAbsoluteIndex = stMainBtsFirstPath.dwCalPathIndex;
  523. dwSlaveAbsoluteIndex = pstSlaveBtsFirstPath->dwCalPathIndex;
  524. }
  525. else if (byPathSource == 2)
  526. {
  527. dwMainAbsoluteIndex = stMainBtsFirstPath.dwTrackPathIndex;
  528. dwSlaveAbsoluteIndex = pstSlaveBtsFirstPath->dwTrackPathIndex;
  529. }
  530. else
  531. {
  532. dwMainAbsoluteIndex = stMainBtsFirstPath.dwCalPathIndex * 0.4 + stMainBtsFirstPath.dwTrackPathIndex * 0.6;
  533. dwSlaveAbsoluteIndex = pstSlaveBtsFirstPath->dwCalPathIndex * 0.4 + pstSlaveBtsFirstPath->dwTrackPathIndex * 0.6;
  534. }
  535. // 采样索引偏移(通过第一径估算的偏移)
  536. dwSampleOffset = dwSlaveAbsoluteIndex - dwMainAbsoluteIndex;
  537. // 估算偏移与绝对偏移之差
  538. dwIndexOffset = dwSampleOffset - dwTimeOffset;
  539. // 调整定位数据队列索引
  540. lct_main_adjust_slave_bts_list_index(pstSlaveBtsFirstPath->byFreqIndex, pstLctDataList, pstSlaveBtsFirstPath->dwBtsId, dwIndexOffset);
  541. // 调整帧内第一径索引
  542. lct_main_adjust_frame_index(pstSlaveBtsFirstPath, dwIndexOffset);
  543. }
  544. }
  545. return;
  546. }
  547. // 调整从站定位数据队列索引
  548. // byFreqIndex:从站频率索引
  549. // dwBtsId:基站ID
  550. // dwIndexOffset:从站相对与主站的偏移
  551. void lct_main_adjust_slave_bts_list_index(uint8 byFreqIndex, PUB_LOCATION_DATA_T *pstLocationDataList, uint32 dwBtsId, int32 dwIndexOffset)
  552. {
  553. PUB_LOCATION_DATA_T *pstLocationData = NULL;
  554. uint8 byFlag = 0;
  555. int32 dwIndex = 0;
  556. // 遍历队列查找从站
  557. for (uint8 i = 0; i < PUB_SYS_CARRIER_NUM; i++)
  558. {
  559. pstLocationData = &pstLocationDataList[i];
  560. if (pstLocationData->dwSetBtsId == dwBtsId && i == byFreqIndex)
  561. {
  562. byFlag = 1;
  563. break;
  564. }
  565. }
  566. // 从站存在,则调整队列索引,包括变频索引,定位开始索引和最后一帧定位数据索引
  567. if (byFlag)
  568. {
  569. // 队列往前调整(绝对索引)
  570. if (dwIndexOffset > 0)
  571. {
  572. // 调整变频索引
  573. pstLocationData->dwDdcIndex -= dwIndexOffset;
  574. // 调整定位索引
  575. dwIndex = pstLocationData->dwLocationIndex - dwIndexOffset;
  576. if (dwIndex >= 0)
  577. {
  578. pstLocationData->dwLocationIndex = dwIndex;
  579. }
  580. else
  581. {
  582. pstLocationData->dwLocationIndex = PUB_LCT_DATA_LIST_LEN + dwIndex;
  583. }
  584. // 调整定位数据最后一帧的开始索引
  585. dwIndex = pstLocationData->dwFourthLocationIndex - dwIndexOffset;
  586. if (dwIndex >= 0)
  587. {
  588. pstLocationData->dwFourthLocationIndex = dwIndex;
  589. }
  590. else
  591. {
  592. pstLocationData->dwFourthLocationIndex = PUB_LCT_DATA_LIST_LEN + dwIndex;
  593. }
  594. }
  595. // 队列往后调整
  596. else
  597. {
  598. dwIndexOffset = abs(dwIndexOffset);
  599. // 调整变频索引
  600. pstLocationData->dwDdcIndex += dwIndexOffset;
  601. // 调整定位索引
  602. dwIndex = pstLocationData->dwLocationIndex + dwIndexOffset;
  603. if (dwIndex >= PUB_LCT_DATA_LIST_LEN)
  604. {
  605. pstLocationData->dwLocationIndex = dwIndex - PUB_LCT_DATA_LIST_LEN;
  606. }
  607. else
  608. {
  609. pstLocationData->dwLocationIndex = dwIndex;
  610. }
  611. // 调整定位数据最后一帧的开始索引
  612. dwIndex = pstLocationData->dwFourthLocationIndex + dwIndexOffset;
  613. if (dwIndex >= PUB_LCT_DATA_LIST_LEN)
  614. {
  615. pstLocationData->dwFourthLocationIndex = dwIndex - PUB_LCT_DATA_LIST_LEN;
  616. }
  617. else
  618. {
  619. pstLocationData->dwFourthLocationIndex = dwIndex;
  620. }
  621. }
  622. }
  623. }
  624. // 调整帧内第一径索引
  625. // pstSlaveBtsFirstPath:从站定位数据
  626. // dwIndexOffset:索引偏移
  627. void lct_main_adjust_frame_index(LCT_FIRSTPATH_T *pstSlaveBtsFirstPath, int32 dwIndexOffset)
  628. {
  629. // 索引往左调整
  630. if (dwIndexOffset > 0)
  631. {
  632. pstSlaveBtsFirstPath->wFrameCalIndex -= dwIndexOffset;
  633. if (pstSlaveBtsFirstPath->wFrameTrackIndex > 0)
  634. {
  635. pstSlaveBtsFirstPath->wFrameTrackIndex -= dwIndexOffset;
  636. }
  637. }
  638. // 索引往右调整
  639. else
  640. {
  641. dwIndexOffset = abs(dwIndexOffset);
  642. pstSlaveBtsFirstPath->wFrameCalIndex += dwIndexOffset;
  643. if (pstSlaveBtsFirstPath->wFrameTrackIndex > 0)
  644. {
  645. pstSlaveBtsFirstPath->wFrameTrackIndex += dwIndexOffset;
  646. }
  647. }
  648. }
  649. // 把第一径写入文本文件中
  650. void lct_main_write_text_file(LCT_FIRSTPATH_LIST_T *pstFirstPahtGroup)
  651. {
  652. LCT_MAIN_TEST_FIRST_PATH_T stTmp = {0};
  653. LCT_FIRSTPATH_T stFirstPath = {0};
  654. char *pFilePaht = "E:\\work\\ips8000\\aplm8000sdk\\output\\firstpath\\firstpath.txt";
  655. for (uint8 i = 0; i < pstFirstPahtGroup->byBtsNum; i++)
  656. {
  657. stFirstPath = pstFirstPahtGroup->astFirstPath[i];
  658. stTmp.dwFrameNo = gg_dwFrameNo - 1;
  659. stTmp.dwFreqIndex = stFirstPath.byFreqIndex;
  660. stTmp.dwMaxValue = (uint32)stFirstPath.fMaxAmplValue;
  661. // stTmp.dwFrameCalIndex = stFirstPath.wFrameCalIndex;
  662. stTmp.dwCalDdcIndex = stFirstPath.dwCalPathIndex;
  663. // stTmp.dwFrameTrackIndex = stFirstPath.wFrameTrackIndex;
  664. stTmp.dwTrackDdcIndex = stFirstPath.dwTrackPathIndex;
  665. // 写入文件中
  666. util_write_real_number_to_txt_file(pFilePaht, sizeof(LCT_MAIN_TEST_FIRST_PATH_T) / 4, (uint32 *)(&stTmp));
  667. }
  668. return;
  669. }
  670. // 修改手机相对于基站的移动趋势
  671. // pstMeanLctCoordList:定位坐标平滑队列
  672. // pstPredictionDirectionDataList:预测手机移动方向数据队列
  673. void lct_main_update_phone_tendency(LCT_COORDSEL_MEAN_COORD_T *pstMeanLctCoordList, LCT_FIRSTPATH_PREDICTION_DIRECTION_DATA_T *pstPredictionDirectionDataList)
  674. {
  675. LCT_FIRSTPATH_PREDICTION_DIRECTION_DATA_T *pstDirectionData = NULL;
  676. flt32 fDistanceC = 0; // 基站到当前一点的距离
  677. flt32 fDistanceA = 0; // 基站到前一点的距离
  678. uint8 byLen = pstMeanLctCoordList->byListLen;
  679. if (byLen < 2)
  680. {
  681. return;
  682. }
  683. COORD_T stPointC = pstMeanLctCoordList->astCoordList[byLen - 1];
  684. COORD_T stPointA = pstMeanLctCoordList->astCoordList[byLen - 2];
  685. for (uint8 i = 0; i < PUB_SYS_CARRIER_NUM; i++)
  686. {
  687. pstDirectionData = &pstPredictionDirectionDataList[i];
  688. if (pstDirectionData->byValidFlag)
  689. {
  690. fDistanceC = util_distance_cal_p2p_distance(pstDirectionData->dwCoordX, pstDirectionData->dwCoordY, stPointC.dwX, stPointC.dwY);
  691. fDistanceA = util_distance_cal_p2p_distance(pstDirectionData->dwCoordX, pstDirectionData->dwCoordY, stPointA.dwX, stPointA.dwY);
  692. if (fDistanceC > fDistanceA)
  693. {
  694. pstDirectionData->byDirectionTendency = 2;
  695. }
  696. else if (fDistanceC < fDistanceA)
  697. {
  698. pstDirectionData->byDirectionTendency = 1;
  699. }
  700. else
  701. {
  702. pstDirectionData->byDirectionTendency = 0;
  703. }
  704. }
  705. }
  706. }