// 秒寻科技 // 定位主控模块 // zt // 2023-03-25 #include "../../includes/includes.h" #include "./lct_public.h" // 定义仅本模块使用的全局变量 LCT_FIRSTPATH_LIST_T gLct_stFirstPathList = {0}; // 第一径数据队列 LCT_FIRSTPATH_PREDICTION_DIRECTION_DATA_T gLct_astPredictionDirectionDataList[PUB_SYS_CARRIER_NUM] = {0}; // 预测移动方向数据队列 LCT_COORDSEL_ORIGINAL_COORD_T gLct_stOriginalLctCoordList = {0}; // 原始定位坐标队列 LCT_COORDSEL_MEAN_COORD_T gLct_stMeanLctCoordList = {0}; // 平滑定位坐标队列 flt32 gLct_afMeanWeight[LCT_COORDSEL_ORIGINAL_COORD_LIST_LEN] = {0.20, 0.30, 0.50}; // 历史定位坐标权重 uint32 gLct_dwPredictionTimes = 0; // 预测次数 uint32 gLct_dwFpBaseOffset = 0; // 第一径基本偏移量 // 导出全局变量 extern PUB_SYS_STATUS_T gg_stSysStatus; // 系统运行状态 extern uint32 gg_dwFrameNo; // 全局帧号 void lct_main_init(LCT_FIRSTPATH_PARAM_T stLctFirstpathParam, LCT_COORDCAL_PARAM_T stLctCoordcalParam, LCT_COORDSEL_PARAM_T stLctCoordselParam) { // 第一径全局变量初始化 memset(&gLct_stFirstPathList, 0, sizeof(LCT_FIRSTPATH_LIST_T)); memset(&gLct_stOriginalLctCoordList, 0, sizeof(LCT_COORDSEL_ORIGINAL_COORD_T)); memset(&gLct_stMeanLctCoordList, 0, sizeof(LCT_COORDSEL_MEAN_COORD_T)); memset(gLct_astPredictionDirectionDataList, 0, sizeof(LCT_FIRSTPATH_PREDICTION_DIRECTION_DATA_T) * PUB_SYS_CARRIER_NUM); lct_firstpath_init(stLctFirstpathParam); lct_coordcal_init(stLctCoordcalParam); lct_coordsel_init(stLctCoordselParam); } // 模块全局数据结构复位 void lct_main_reset() { // 系统处于待同步状态 // if (!gg_stSysStatus.bySyncFlag || !gg_stSysStatus.byBtsCaptureFlag) if (!gg_stSysStatus.bySyncFlag) { memset(&gLct_stFirstPathList, 0, sizeof(LCT_FIRSTPATH_LIST_T)); memset(&gLct_stOriginalLctCoordList, 0, sizeof(LCT_COORDSEL_ORIGINAL_COORD_T)); memset(&gLct_stMeanLctCoordList, 0, sizeof(LCT_COORDSEL_MEAN_COORD_T)); memset(gLct_astPredictionDirectionDataList, 0, sizeof(LCT_FIRSTPATH_PREDICTION_DIRECTION_DATA_T) * PUB_SYS_CARRIER_NUM); gLct_dwPredictionTimes = 0; gg_stSysStatus.byBtsCaptureFlag = 0; // 系统处于捕获基站状态 gg_stSysStatus.byReLocationFlag = 0; // 系统进入重新定位状态 } return; } // 定位主控函数 // pstLctBtsList:一组定位基站 // pstLctDataList:定位数据 // pstCurrentLctResult:定位结果 void lct_main(PUB_LCT_BTS_LIST_T *pstLctBtsList, PUB_LOCATION_DATA_T *pstLctDataList, PUB_CURRENT_LCT_RESULT_T *pstCurrentLctResult) { uint8 byRemainder = 0; LCT_FIRSTPATH_T *pstFirstPathList = NULL; uint8 byBtsNum = 0; LCT_MINIMUM_VALUE_GROUP_T stMinimumValueGroup = {0}; // 极小值数据组 uint8 byPredictionFlag = 0; // 预测坐标成功标识符 COORD_T stPredictionCoord = {0}; // 预测坐标 uint16 wMinimumNum = 0; uint8 byCalMinimumNum = 0; uint8 byTrackMinimumNum = 0; uint8 byPredicMinimumNum = 0; LCT_COORDSEL_OPTIMUM_COORD_T stOptimumCoord = {0}; // 最优坐标 uint32 dwMainBtsId = 0; int32 dwMainBtsBuildId = 0; int32 dwMainBtsLayerId = 0; uint8 byFlag = 0; COORD_T stMeanCoord = {0}; PUB_LOCATION_DATA_T *pstLctData = NULL; uint8 byImuMoveFlag = 0; // imu计算结果,0:计算错误,1:成功,但静止,50:成功,但移动 // 模块全局数据结构复位 lct_main_reset(); // 系统已经同步并且定位基站数量至少有3个 if (gg_stSysStatus.bySyncFlag && pstLctBtsList->byBtsNum > 1) { // 当前帧需要定位 byRemainder = (gg_dwFrameNo - 1) % PUB_SYS_SLOT_NUM; if (byRemainder == 0) { // 1、 计算第一径,生成基站第一径数据组,同时镜像基站第一径数据组 lct_firstpath_main(pstLctBtsList, pstLctDataList, &gLct_stFirstPathList); // TODO测试用的代码 if (PUB_DEBUG_ENABLE) { lct_main_write_text_file(&gLct_stFirstPathList); } // 2、根据基站第一径数据组计算“极小值数据组” lct_coordcal_main(pstLctBtsList, pstLctDataList, &gLct_stFirstPathList, &byPredictionFlag, &stPredictionCoord, &stMinimumValueGroup, &wMinimumNum); // 3、根据“极小值数据组”选择最优定位坐标 if (wMinimumNum > 0) { // 选择坐标 lct_coordsel_main(&stMinimumValueGroup, byPredictionFlag, stPredictionCoord, &stOptimumCoord); // 存在有效的极小值点 if (stOptimumCoord.byResultFlag) { // 定位坐标来自预测 if (stOptimumCoord.bySourceFlag == 3) { gLct_dwPredictionTimes++; } else { gLct_dwPredictionTimes = 0; } // 连续4次使用预测坐标,则停止输出 if (gLct_dwPredictionTimes >= LCT_MAIN_MAX_USE_PREDICTION_COORD_TIMES) { pstCurrentLctResult->dwCpltFlag = 1; // 定位完成 pstCurrentLctResult->dwSuccessFlag = 1; // 定位成功 gg_stSysStatus.byBtsCaptureFlag = 0; // 系统进入基站捕获阶段 gg_stSysStatus.byReLocationFlag = 1; // 重新定位标识符置1 } else { pstCurrentLctResult->dwCpltFlag = 1; // 定位完成 pstCurrentLctResult->dwSuccessFlag = 1; // 定位成功 gg_stSysStatus.byBtsCaptureFlag = 1; // 系统进入基站跟踪阶段 gg_stSysStatus.byReLocationFlag = 0; // 重新定位标识符置0 } // 二次校验坐标(已改成在计算模块校验) // lct_main_dbcheck_coord_by_bts_polygon(&gLct_stFirstPathList, &stOptimumCoord); // 根据定位结果,更新基站第一径帧内跟踪索引 lct_main_update_bts_firstpath_trace_index(stOptimumCoord.bySourceFlag, &gLct_stFirstPathList, pstLctDataList); // 查找主站,包括所在的大楼编号、楼层编号和基站编号 lct_main_find_main_bts(&gLct_stFirstPathList, &dwMainBtsId, &dwMainBtsBuildId, &dwMainBtsLayerId); // 保存原始坐标 lct_main_save_original_coord(dwMainBtsBuildId, dwMainBtsLayerId, stOptimumCoord.stCoord, &gLct_stOriginalLctCoordList); stMeanCoord = stOptimumCoord.stCoord; // 平滑原始坐标 lct_main_mean_original_coord(&gLct_stOriginalLctCoordList, gLct_afMeanWeight, &gLct_stMeanLctCoordList, &stMeanCoord); // 计算第一径基本偏移量 lct_toa_cal_bts_first_path_index_offset(stOptimumCoord.bySourceFlag, &gLct_stFirstPathList, &gLct_stMeanLctCoordList, gLct_dwFpBaseOffset, &gLct_dwFpBaseOffset); // 根据定位坐标修改手机相对于基站的移动趋势 lct_main_update_phone_tendency(&gLct_stMeanLctCoordList, gLct_astPredictionDirectionDataList); // 通过imu计算位移,判断手机是否移动 byImuMoveFlag = imu_cal_distance_lct(); // 组织定位结果 lct_main_organize_lct_result(dwMainBtsBuildId, dwMainBtsLayerId, &gLct_stFirstPathList, &stMeanCoord, byImuMoveFlag, pstCurrentLctResult); // TODO测试 if (PUB_DEBUG_ENABLE) { printf("frame no:%d, source:%d, x :%d, y: %d\n", gg_dwFrameNo - 1, stOptimumCoord.bySourceFlag, stMeanCoord.dwX, stMeanCoord.dwY); char *filePathx = "E:\\work\\ips8000\\aplm8000sdk\\output\\coord\\coordx.bin"; char *filePathy = "E:\\work\\ips8000\\aplm8000sdk\\output\\coord\\coordy.bin"; util_write_coord_to_bin_file(filePathx, 1, (uint32 *)&stMeanCoord.dwX); util_write_coord_to_bin_file(filePathy, 1, (uint32 *)&stMeanCoord.dwY); } } // 没有有效的极小值点 else { pstCurrentLctResult->dwCpltFlag = 1; // 定位完成 pstCurrentLctResult->dwSuccessFlag = 0; // 定位失败 gg_stSysStatus.byBtsCaptureFlag = 0; // 清空定位数据中第一径数据 for (uint8 i = 0; i < PUB_SYS_CARRIER_NUM; i++) { pstLctData = &pstLctDataList[i]; pstLctData->wAheadFrameCalPahtIndex = 0; pstLctData->wAheadFrameTrackPathIndex = 0; } printf("minimum avalid\n"); } } else { pstCurrentLctResult->dwCpltFlag = 1; // 定位完成 pstCurrentLctResult->dwSuccessFlag = 0; // 定位失败 gg_stSysStatus.byBtsCaptureFlag = 0; // 清空定位数据中第一径数据 for (uint8 i = 0; i < PUB_SYS_CARRIER_NUM; i++) { pstLctData = &pstLctDataList[i]; pstLctData->wAheadFrameCalPahtIndex = 0; pstLctData->wAheadFrameTrackPathIndex = 0; } printf("no minimum\n"); } } } else { printf("error, sync flag:%d, bts num:%d\n", gg_stSysStatus.bySyncFlag, pstLctBtsList->byBtsNum); } return; } // 根据基站多边形再次校验定位坐标 void lct_main_dbcheck_coord_by_bts_polygon(LCT_FIRSTPATH_LIST_T *pstBtsFirstPathList, LCT_COORDSEL_OPTIMUM_COORD_T *pstOptimumCoord) { uint8 byFirstPathListLen = pstBtsFirstPathList->byBtsNum; // 基站数量 LCT_FIRSTPATH_T *pstFirstPathList = pstBtsFirstPathList->astFirstPath; int32 dwTemp = 0; int32 dwMinValueX = 2147483647; int32 dwMaxValueX = -2147483648; int32 dwMinValueY = 2147483647; int32 dwMaxValueY = -2147483648; uint32 dwGapX = 0; uint32 dwGapY = 0; int32 dwX = 0; int32 dwY = 0; ////计算端点坐标的最大值与最小值 for (uint8 i = 0; i < byFirstPathListLen; i++) { dwTemp = pstFirstPathList[i].dwCoordX; if (dwTemp > dwMaxValueX) { dwMaxValueX = dwTemp; } if (dwTemp < dwMinValueX) { dwMinValueX = dwTemp; } dwTemp = pstFirstPathList[i].dwCoordY; if (dwTemp > dwMaxValueY) { dwMaxValueY = dwTemp; } if (dwTemp < dwMinValueY) { dwMinValueY = dwTemp; } } // 计算基站坐标间隔 dwGapX = dwMaxValueX - dwMinValueX; dwGapY = dwMaxValueY - dwMinValueY; // 校验X坐标 dwX = pstOptimumCoord->stCoord.dwX; if (dwGapX < 350) { dwX = util_distance_gen_rand_num((dwMaxValueX + dwMinValueX) / 2, 50); } else if (dwGapX >= 350 && dwGapX < 900) { dwX = pstOptimumCoord->stCoord.dwX * 0.85; } else if (dwGapX >= 900 && dwGapX < 1500) { dwX = pstOptimumCoord->stCoord.dwX * 0.95; } // 校验Y坐标 dwY = pstOptimumCoord->stCoord.dwY; if (dwGapY < 350) { dwY = util_distance_gen_rand_num((dwMaxValueY + dwMinValueY) / 2, 50); } else if (dwGapY >= 350 && dwGapY < 900) { dwY = pstOptimumCoord->stCoord.dwY * 0.85; } else if (dwGapY >= 900 && dwGapY < 1500) { dwY = pstOptimumCoord->stCoord.dwY * 0.95; } // 修改 pstOptimumCoord->stCoord.dwX = dwX; pstOptimumCoord->stCoord.dwY = dwY; return; } // 根据一个数,在该数左右两侧范围内生成一个随机数 // dwBaseData:基数 // wRange:单边偏移 int32 lct_main_gen_rand_num(int32 dwBaseData, uint16 wRange) { int32 dwTotalRange = 2 * wRange + 1; // 总范围 int32 dwRemainder = 0; int32 randomNum = 0; // 随机数 // 初始化随机数生成器 srand(time(NULL)); // 生成随机数 dwRemainder = rand() % dwTotalRange; // 生成 [0, dwTotalRange) 范围内的随机数 randomNum = dwBaseData - wRange + dwRemainder; // 生成所需的随机数 return randomNum; } // 根据定位结果,更新基站第一径帧内跟踪索引 // byLctSourceFlag:定位使用的第一径来源 // pstBtsFirstPathList:基站第一径数据队列 // pstLctDataList:定位数据 void lct_main_update_bts_firstpath_trace_index(uint8 byLctSourceFlag, LCT_FIRSTPATH_LIST_T *pstBtsFirstPathList, PUB_LOCATION_DATA_T *pstLctDataList) { uint8 byBtsNum = pstBtsFirstPathList->byBtsNum; LCT_FIRSTPATH_T *pstFirstPathList = NULL; uint16 wFrameTraceIndex = 0; uint8 byFreqIndex = 0; PUB_LOCATION_DATA_T *pstLctData = NULL; for (uint8 i = 0; i < byBtsNum; i++) { pstFirstPathList = &pstBtsFirstPathList->astFirstPath[i]; // 最优定位坐标来自计算径 if (byLctSourceFlag == 1) { wFrameTraceIndex = pstFirstPathList->wFrameCalIndex; } // 最优定位坐标来自跟踪径 else if (byLctSourceFlag == 2) { wFrameTraceIndex = pstFirstPathList->wFrameTrackIndex; } // 最优定位坐标来自预测径 else { wFrameTraceIndex = 0; } // 跟新"跟踪径" pstFirstPathList->wFrameTrackIndex = wFrameTraceIndex; } // 将跟踪索引更新到定位数据中 for (uint8 j = 0; j < PUB_SYS_CARRIER_NUM; j++) { pstLctData = &pstLctDataList[j]; pstLctData->wAheadFrameCalPahtIndex = 0; pstLctData->wAheadFrameTrackPathIndex = 0; } for (uint8 k = 0; k < byBtsNum; k++) { pstFirstPathList = &pstBtsFirstPathList->astFirstPath[k]; byFreqIndex = pstFirstPathList->byFreqIndex; pstLctData = &pstLctDataList[byFreqIndex]; pstLctData->wAheadFrameCalPahtIndex = pstFirstPathList->wFrameCalIndex; pstLctData->wAheadFrameTrackPathIndex = pstFirstPathList->wFrameTrackIndex; } return; } // 从第一径数据队列中查找主站信息 void lct_main_find_main_bts(LCT_FIRSTPATH_LIST_T *pstFirstPathList, uint32 *pdwBtsId, int32 *pwBuildId, int32 *pdwLayerId) { LCT_FIRSTPATH_T *pstFirstPahtData = NULL; uint8 byExist = 0; for (uint8 i = 0; i < pstFirstPathList->byBtsNum; i++) { pstFirstPahtData = &pstFirstPathList->astFirstPath[i]; if (pstFirstPahtData->byMainFlag == 1) { *pdwBtsId = pstFirstPahtData->dwBtsId; *pwBuildId = pstFirstPahtData->dwBuildId; *pdwLayerId = pstFirstPahtData->dwLayerId; byExist = 1; break; } } if (!byExist) { pstFirstPahtData = &pstFirstPathList->astFirstPath[0]; *pdwBtsId = pstFirstPahtData->dwBtsId; *pwBuildId = pstFirstPahtData->dwBuildId; *pdwLayerId = pstFirstPahtData->dwLayerId; } return; } // 保存原始定位坐标 // stCoord:定位点坐标 // pstOriginalLctCoordList:原始定位坐标队列 void lct_main_save_original_coord(int32 dwBuildId, int32 dwLayerId, COORD_T stCoord, LCT_COORDSEL_ORIGINAL_COORD_T *pstOriginalLctCoordList) { uint8 byCoordListLen = pstOriginalLctCoordList->byListLen; // 原始定位坐标队列长度 // TODO(以后要修改成支持多个大楼和多个楼层) 保存大楼编号和楼层编号 gg_stSysStatus.dwBuildId = dwBuildId; gg_stSysStatus.dwLayerId = dwLayerId; // 队列没有满 if (byCoordListLen < LCT_COORDSEL_ORIGINAL_COORD_LIST_LEN) { pstOriginalLctCoordList->astCoordList[byCoordListLen] = stCoord; pstOriginalLctCoordList->byListLen++; } // 队列已满 else { // 移动队列 memmove(pstOriginalLctCoordList->astCoordList, &pstOriginalLctCoordList->astCoordList[1], sizeof(COORD_T) * (LCT_COORDSEL_ORIGINAL_COORD_LIST_LEN - 1)); pstOriginalLctCoordList->astCoordList[LCT_COORDSEL_ORIGINAL_COORD_LIST_LEN - 1] = stCoord; // 将数据插入队列尾 } return; } // 平滑原始定位坐标 // pstOriginalLctCoordList:原始定位坐标队列 // pfMeanWeightList:平滑权重 // pstMeanCoord:返回参数,平滑坐标 void lct_main_mean_original_coord(LCT_COORDSEL_ORIGINAL_COORD_T *pstOriginalLctCoordList, flt32 *pfMeanWeightList, LCT_COORDSEL_MEAN_COORD_T *pstMeanCoordList, COORD_T *pstMeanCoord) { uint8 byListLen = pstOriginalLctCoordList->byListLen; flt32 fX = 0; flt32 fY = 0; uint8 byCoordListLen = pstMeanCoordList->byListLen; // 平滑坐标队列 // 原始坐标队列长度不合法 if ((byListLen < LCT_COORDSEL_ORIGINAL_COORD_LIST_LEN)) { return; } //// 平滑坐标 for (uint8 i = 0; i < byListLen; i++) { fX += pstOriginalLctCoordList->astCoordList[i].dwX * pfMeanWeightList[i]; fY += pstOriginalLctCoordList->astCoordList[i].dwY * pfMeanWeightList[i]; } pstMeanCoord->dwX = fX; pstMeanCoord->dwY = fY; pstMeanCoord->dwZ = 120; //// 保存平滑后的坐标 // 队列没有满 if (byCoordListLen < LCT_COORDSEL_MEAN_COORD_LIST_LEN) { pstMeanCoordList->astCoordList[byCoordListLen] = *pstMeanCoord; pstMeanCoordList->byListLen++; } // 队列已满 else { // 移动队列 memmove(pstMeanCoordList->astCoordList, &pstMeanCoordList->astCoordList[1], sizeof(COORD_T) * (LCT_COORDSEL_MEAN_COORD_LIST_LEN - 1)); pstMeanCoordList->astCoordList[LCT_COORDSEL_MEAN_COORD_LIST_LEN - 1] = *pstMeanCoord; // 将数据插入队列尾 } return; } // 组织定位结果 // dwBuildId:大楼编号 // dwLayerId:楼层编号 // pstFirstPathList:定位基站第一径队列 // pstMeanCoord:平滑坐标 // pstCurrentLctResult:定位结果 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) { uint8 byBtsNum = pstFirstPathList->byBtsNum; PUB_LCT_BTS_T *pstLctBtsData = NULL; uint8 byExist = 0; // 1、 保存定位坐标坐标 pstCurrentLctResult->stCoord = *pstMeanCoord; // 2、查找定位主站并保存大楼和楼层 pstCurrentLctResult->dwBuildId = dwBuildId; pstCurrentLctResult->dwLayerId = dwLayerId; // 3、保存基站数据 pstCurrentLctResult->dwLctBtsNum = byBtsNum; // 基站数量 for (uint8 i = 0; i < byBtsNum; i++) { pstCurrentLctResult->adwBtsIdList[i] = pstFirstPathList->astFirstPath[i].dwBtsId; // 基站ID } // 4、保存IMU移动标识符 pstCurrentLctResult->dwImuMoveFlag = dwImuMoveFlag; return; } // 保存平滑坐标 // stCoord:定位点坐标 // pstMeanCoordList:平滑队列 void lct_main_save_mean_coord(COORD_T stCoord, LCT_COORDSEL_MEAN_COORD_T *pstMeanCoordList) { uint8 byCoordListLen = pstMeanCoordList->byListLen; // 平滑坐标队列 // 队列没有满 if (byCoordListLen < LCT_COORDSEL_MEAN_COORD_LIST_LEN) { pstMeanCoordList->astCoordList[byCoordListLen] = stCoord; pstMeanCoordList->byListLen++; } // 队列已满 else { // 移动队列 memmove(pstMeanCoordList->astCoordList, &pstMeanCoordList->astCoordList[1], sizeof(COORD_T) * (LCT_COORDSEL_MEAN_COORD_LIST_LEN - 1)); pstMeanCoordList->astCoordList[LCT_COORDSEL_MEAN_COORD_LIST_LEN - 1] = stCoord; // 将数据插入队列尾 } return; } // 根据定位坐标反算从站第一径相对主站第一径的偏移量 // pstAheadLctFirstPahtGroup:前一次基站第一径数据组PU // stLctCoord:定位坐标 // byPathSource:第一径源,1:计算径、2:跟踪径:3:预测径 void lct_main_adjust_firstpath_index_offset(LCT_FIRSTPATH_LIST_T *pstAheadLctFirstPahtGroup, COORD_T stLctCoord, uint8 byPathSource, PUB_LOCATION_DATA_T *pstLctDataList) { uint8 byBtsNum = pstAheadLctFirstPahtGroup->byBtsNum; LCT_FIRSTPATH_T stMainBtsFirstPath = {0}; LCT_FIRSTPATH_T *pstSlaveBtsFirstPath = NULL; uint8 byMainFlag = 0; flt32 fMainTimeLen = 0; int32 dwMainAbsoluteIndex = 0; flt32 fSlaveTimeLen = 0; int32 dwSlaveAbsoluteIndex = 0; flt32 fDelayDiff = 0; int32 xx = 0; int32 yy = 0; int32 zz = 0; flt32 fDistance = 0; int32 dwTimeOffset = 0; int32 dwSampleOffset = 0; int32 dwIndexOffset = 0; // 找主站 for (uint8 i = 0; i < byBtsNum; i++) { stMainBtsFirstPath = pstAheadLctFirstPahtGroup->astFirstPath[i]; if (stMainBtsFirstPath.byMainFlag == 1) { byMainFlag = 1; break; } } // 未找到主站 if (!byMainFlag) { return; } // 计算主站传输时长 xx = stLctCoord.dwX - stMainBtsFirstPath.dwCoordX; yy = stLctCoord.dwY - stMainBtsFirstPath.dwCoordY; zz = stLctCoord.dwZ - stMainBtsFirstPath.dwCoordZ; fDistance = sqrt(xx * xx + yy * yy + zz * zz); fMainTimeLen = fDistance / 100 / PUB_AUDIO_SPEED * 1000; // 单位毫秒 // 计算从站与主站间的时延差,并反算索引偏差 for (uint8 j = 0; j < byBtsNum; j++) { pstSlaveBtsFirstPath = &pstAheadLctFirstPahtGroup->astFirstPath[j]; // 当前站是从站 if (pstSlaveBtsFirstPath->byMainFlag == 2) { // 计算定位点到从站间的传输时长 xx = stLctCoord.dwX - pstSlaveBtsFirstPath->dwCoordX; yy = stLctCoord.dwY - pstSlaveBtsFirstPath->dwCoordY; zz = stLctCoord.dwZ - pstSlaveBtsFirstPath->dwCoordZ; fDistance = sqrt(xx * xx + yy * yy + zz * zz); fSlaveTimeLen = fDistance / 100 / PUB_AUDIO_SPEED * 1000; // 从站传输时长,单位毫秒 // 定位点到主站与到从站间的时长差 fDelayDiff = (fSlaveTimeLen - fMainTimeLen); // 毫秒 // 计算从站第一径与主站第一径的索引偏差(绝对偏移) dwTimeOffset = (int32)(48 * fDelayDiff); if (byPathSource == 1) { dwMainAbsoluteIndex = stMainBtsFirstPath.dwCalPathIndex; dwSlaveAbsoluteIndex = pstSlaveBtsFirstPath->dwCalPathIndex; } else if (byPathSource == 2) { dwMainAbsoluteIndex = stMainBtsFirstPath.dwTrackPathIndex; dwSlaveAbsoluteIndex = pstSlaveBtsFirstPath->dwTrackPathIndex; } else { dwMainAbsoluteIndex = stMainBtsFirstPath.dwCalPathIndex * 0.4 + stMainBtsFirstPath.dwTrackPathIndex * 0.6; dwSlaveAbsoluteIndex = pstSlaveBtsFirstPath->dwCalPathIndex * 0.4 + pstSlaveBtsFirstPath->dwTrackPathIndex * 0.6; } // 采样索引偏移(通过第一径估算的偏移) dwSampleOffset = dwSlaveAbsoluteIndex - dwMainAbsoluteIndex; // 估算偏移与绝对偏移之差 dwIndexOffset = dwSampleOffset - dwTimeOffset; // 调整定位数据队列索引 lct_main_adjust_slave_bts_list_index(pstSlaveBtsFirstPath->byFreqIndex, pstLctDataList, pstSlaveBtsFirstPath->dwBtsId, dwIndexOffset); // 调整帧内第一径索引 lct_main_adjust_frame_index(pstSlaveBtsFirstPath, dwIndexOffset); } } return; } // 调整从站定位数据队列索引 // byFreqIndex:从站频率索引 // dwBtsId:基站ID // dwIndexOffset:从站相对与主站的偏移 void lct_main_adjust_slave_bts_list_index(uint8 byFreqIndex, PUB_LOCATION_DATA_T *pstLocationDataList, uint32 dwBtsId, int32 dwIndexOffset) { PUB_LOCATION_DATA_T *pstLocationData = NULL; uint8 byFlag = 0; int32 dwIndex = 0; // 遍历队列查找从站 for (uint8 i = 0; i < PUB_SYS_CARRIER_NUM; i++) { pstLocationData = &pstLocationDataList[i]; if (pstLocationData->dwSetBtsId == dwBtsId && i == byFreqIndex) { byFlag = 1; break; } } // 从站存在,则调整队列索引,包括变频索引,定位开始索引和最后一帧定位数据索引 if (byFlag) { // 队列往前调整(绝对索引) if (dwIndexOffset > 0) { // 调整变频索引 pstLocationData->dwDdcIndex -= dwIndexOffset; // 调整定位索引 dwIndex = pstLocationData->dwLocationIndex - dwIndexOffset; if (dwIndex >= 0) { pstLocationData->dwLocationIndex = dwIndex; } else { pstLocationData->dwLocationIndex = PUB_LCT_DATA_LIST_LEN + dwIndex; } // 调整定位数据最后一帧的开始索引 dwIndex = pstLocationData->dwFourthLocationIndex - dwIndexOffset; if (dwIndex >= 0) { pstLocationData->dwFourthLocationIndex = dwIndex; } else { pstLocationData->dwFourthLocationIndex = PUB_LCT_DATA_LIST_LEN + dwIndex; } } // 队列往后调整 else { dwIndexOffset = abs(dwIndexOffset); // 调整变频索引 pstLocationData->dwDdcIndex += dwIndexOffset; // 调整定位索引 dwIndex = pstLocationData->dwLocationIndex + dwIndexOffset; if (dwIndex >= PUB_LCT_DATA_LIST_LEN) { pstLocationData->dwLocationIndex = dwIndex - PUB_LCT_DATA_LIST_LEN; } else { pstLocationData->dwLocationIndex = dwIndex; } // 调整定位数据最后一帧的开始索引 dwIndex = pstLocationData->dwFourthLocationIndex + dwIndexOffset; if (dwIndex >= PUB_LCT_DATA_LIST_LEN) { pstLocationData->dwFourthLocationIndex = dwIndex - PUB_LCT_DATA_LIST_LEN; } else { pstLocationData->dwFourthLocationIndex = dwIndex; } } } } // 调整帧内第一径索引 // pstSlaveBtsFirstPath:从站定位数据 // dwIndexOffset:索引偏移 void lct_main_adjust_frame_index(LCT_FIRSTPATH_T *pstSlaveBtsFirstPath, int32 dwIndexOffset) { // 索引往左调整 if (dwIndexOffset > 0) { pstSlaveBtsFirstPath->wFrameCalIndex -= dwIndexOffset; if (pstSlaveBtsFirstPath->wFrameTrackIndex > 0) { pstSlaveBtsFirstPath->wFrameTrackIndex -= dwIndexOffset; } } // 索引往右调整 else { dwIndexOffset = abs(dwIndexOffset); pstSlaveBtsFirstPath->wFrameCalIndex += dwIndexOffset; if (pstSlaveBtsFirstPath->wFrameTrackIndex > 0) { pstSlaveBtsFirstPath->wFrameTrackIndex += dwIndexOffset; } } } // 把第一径写入文本文件中 void lct_main_write_text_file(LCT_FIRSTPATH_LIST_T *pstFirstPahtGroup) { LCT_MAIN_TEST_FIRST_PATH_T stTmp = {0}; LCT_FIRSTPATH_T stFirstPath = {0}; char *pFilePaht = "E:\\work\\ips8000\\aplm8000sdk\\output\\firstpath\\firstpath.txt"; for (uint8 i = 0; i < pstFirstPahtGroup->byBtsNum; i++) { stFirstPath = pstFirstPahtGroup->astFirstPath[i]; stTmp.dwFrameNo = gg_dwFrameNo - 1; stTmp.dwFreqIndex = stFirstPath.byFreqIndex; stTmp.dwMaxValue = (uint32)stFirstPath.fMaxAmplValue; // stTmp.dwFrameCalIndex = stFirstPath.wFrameCalIndex; stTmp.dwCalDdcIndex = stFirstPath.dwCalPathIndex; // stTmp.dwFrameTrackIndex = stFirstPath.wFrameTrackIndex; stTmp.dwTrackDdcIndex = stFirstPath.dwTrackPathIndex; // 写入文件中 util_write_real_number_to_txt_file(pFilePaht, sizeof(LCT_MAIN_TEST_FIRST_PATH_T) / 4, (uint32 *)(&stTmp)); } return; } // 修改手机相对于基站的移动趋势 // pstMeanLctCoordList:定位坐标平滑队列 // pstPredictionDirectionDataList:预测手机移动方向数据队列 void lct_main_update_phone_tendency(LCT_COORDSEL_MEAN_COORD_T *pstMeanLctCoordList, LCT_FIRSTPATH_PREDICTION_DIRECTION_DATA_T *pstPredictionDirectionDataList) { LCT_FIRSTPATH_PREDICTION_DIRECTION_DATA_T *pstDirectionData = NULL; flt32 fDistanceC = 0; // 基站到当前一点的距离 flt32 fDistanceA = 0; // 基站到前一点的距离 uint8 byLen = pstMeanLctCoordList->byListLen; if (byLen < 2) { return; } COORD_T stPointC = pstMeanLctCoordList->astCoordList[byLen - 1]; COORD_T stPointA = pstMeanLctCoordList->astCoordList[byLen - 2]; for (uint8 i = 0; i < PUB_SYS_CARRIER_NUM; i++) { pstDirectionData = &pstPredictionDirectionDataList[i]; if (pstDirectionData->byValidFlag) { fDistanceC = util_distance_cal_p2p_distance(pstDirectionData->dwCoordX, pstDirectionData->dwCoordY, stPointC.dwX, stPointC.dwY); fDistanceA = util_distance_cal_p2p_distance(pstDirectionData->dwCoordX, pstDirectionData->dwCoordY, stPointA.dwX, stPointA.dwY); if (fDistanceC > fDistanceA) { pstDirectionData->byDirectionTendency = 2; } else if (fDistanceC < fDistanceA) { pstDirectionData->byDirectionTendency = 1; } else { pstDirectionData->byDirectionTendency = 0; } } } }