PDR/3.BackUp/PDR-Origin-Version/src/pdr_trackSmooth.c

310 lines
11 KiB
C
Raw Normal View History

2022-09-15 16:35:25 +08:00
/******************** (C) COPYRIGHT 2020 VIVO************************************
* File Name : simulator_location_pdr.c
* Department : Sensor Algorithm Team
* Current Version : V1.2
* Author : ZhangJingrui@vivo.com
* Date of Issued : 2020.7.4
* Comments : PDR
********************************************************************************/
/* Header File Including -----------------------------------------------------*/
#include <stdlib.h>
#include <math.h>
#include <float.h>
#include <stddef.h>
#include <string.h>
#include "pdr_trackSmooth.h"
#include "pdr_linearFit.h"
#include "pdr_util.h"
/* Global Variable Definition ------------------------------------------------*/
/* 轨迹平滑历史输入点存储缓冲区 */
static LatLng *SmoothBuffer = NULL; //最新的点在[0]索引处
static size_t SmoothBufferSize = 0;
static size_t elemTrail = 0;
/* 输出点缓存 */
// #define OUTPUT_BUFFER_SIZE 5
static LatLng *OutputBuffer = NULL;
static size_t outputTrail = 0;
static size_t outputBufferSize = 0;
/* 拐点存储 */
static LatLng InflectionPoint = {0,0};
/* 直线拟合缓存区 */
static LatLng fittingDock[FITTING_DOCK_SIZE] = {{0,0}};
static size_t dockTrail = 0;
/* 条件阈值 */
const double thresholdDis = 5; // 拐点判断阈值
const double thresholdFittingDockSparsity = 1; // 直线拟合样本输入点间的稀疏度(即间隙)
const double thresholdFittingDis = 1; // 拟合直线更新阈值
const double half = 0.5;
/* Function Declaration ------------------------------------------------------*/
/**----------------------------------------------------------------------
* Function : pushBuffer
* Description : buffer
* Date : 2020/7/4 yuanlin_rjyb@vivo.com
*---------------------------------------------------------------------**/
static void pushBuffer(LatLng inLoc){
size_t i;
for (i = outputBufferSize - 1; i > 0; --i){
OutputBuffer[i] = OutputBuffer[i-1];
}
OutputBuffer[0] = inLoc;
if(outputTrail < outputBufferSize)
++outputTrail;
}
/**----------------------------------------------------------------------
* Function : trackSmoothingSlideWindowSet
* Description : 使
*
* Input : slideWindowSize:
* Output : size : 0,0
* 0
* Date : 2020/7/4 yuanlin_rjyb@vivo.com
*---------------------------------------------------------------------**/
int setTrackSmoothWindow(size_t slideWindowSize)
{
LatLng *ptr = NULL;
size_t smoothBufferMallocRes = 0;
size_t OutputBufferMallocRes = 0;
ptr = (LatLng *)malloc( sizeof(LatLng) * slideWindowSize);
if (ptr != NULL)
{
smoothBufferMallocRes = slideWindowSize;
if (SmoothBuffer != NULL)
{
free(SmoothBuffer);
SmoothBuffer = NULL;
SmoothBufferSize = 0;
}
SmoothBuffer = ptr;
SmoothBufferSize = slideWindowSize;
memset(SmoothBuffer, 0, sizeof(LatLng)*SmoothBufferSize);
elemTrail = 0;
}
else
{
smoothBufferMallocRes = 0;
}
ptr = NULL;
ptr = (LatLng *)malloc( sizeof(LatLng) * slideWindowSize);
if( ptr != NULL)
{
OutputBufferMallocRes = slideWindowSize;
if(OutputBuffer != NULL)
{
free(OutputBuffer);
OutputBuffer = NULL;
outputBufferSize = 0;
}
OutputBuffer = ptr;
outputBufferSize = slideWindowSize;
memset(OutputBuffer, 0, sizeof(LatLng)*outputBufferSize);
outputTrail = 0;
}
else
{
OutputBufferMallocRes = 0;
}
/* 不论是否重新调整SmoothBuffer和SmoothBufferSize都会重置fittingDock和dockTrail*/
memset(fittingDock, 0, sizeof(LatLng)*FITTING_DOCK_SIZE);
dockTrail = 0;
return (int)((smoothBufferMallocRes && OutputBufferMallocRes)? slideWindowSize: 0);
}
/**----------------------------------------------------------------------
* Function : trackSmoothing
* Description : 使
* Input : lat:
* lon:
* Output : outLat:
* outLon:
* return:
* Date : 2020/7/4 yuanlin_rjyb@vivo.com
*---------------------------------------------------------------------**/
int pdr_trackSmooth(double lat, double lon, double *outLat, double *outLon)
{
size_t i;
double distance;
LatLng outLatLng;
LatLng projPointLatLng;
double fittingDockLat[FITTING_DOCK_SIZE] = { 0 };
double fittingDockLon[FITTING_DOCK_SIZE] = { 0 };
LatLng tmp_lla = { 0 };
double a = 0; double b = 0; /* y = a*x + b */
// double sumLat = 0; double sumLon = 0;
int ret;
LatLng fittingProjPoint;
double distanceFitting;
if( SmoothBuffer == NULL || SmoothBufferSize <= 1)
{
*outLat = lat;
*outLon = lon;
return 1;
}
/* 配置各个缓冲区、列表的相应内容和参数*/
/* 将SmoothBuffer右移以插入新数据 */
for (i = SmoothBufferSize -1 ; i > 0 ; --i){
SmoothBuffer[i] = SmoothBuffer[i-1];
}
SmoothBuffer[0].lat = lat;
SmoothBuffer[0].lon = lon;
if (elemTrail == 0) { /* 当第一个点输入时,将其设置为第一个拐点 */
InflectionPoint.lat = lat;
InflectionPoint.lon = lon;
}
/* 及时更新elemTrail */
if (elemTrail < SmoothBufferSize ) {
++elemTrail;
}
/* 初始化用于集合的存储点数组fittingDock[FITTING_DOCK_SIZE]*/
if (dockTrail < FITTING_DOCK_SIZE) {
if (dockTrail > 0)
{ /*当不是fittingDock的首个元素时要注意fittingDock输入样本的稀疏度*/
tmp_lla.lat = lat;
tmp_lla.lon = lon;
distance = calDistance(tmp_lla, fittingDock[dockTrail - 1]);
if (distance >= thresholdFittingDockSparsity) {
fittingDock[dockTrail].lat = lat;
fittingDock[dockTrail].lon = lon;
if (dockTrail < outputBufferSize)
++dockTrail;
}
}
else
{ /*当本次输入的坐标点是fittingDock的首个元素直接将此坐标点作为拟合直线的起点*/
fittingDock[dockTrail].lat = lat;
fittingDock[dockTrail].lon = lon;
if (dockTrail < outputBufferSize)
++dockTrail;
}
}
/* 平滑处理逻辑开始 */
if(elemTrail < 3 ) //计算拐点的前提是输入点至少有3个
{
*outLat = lat;
*outLon = lon;
outLatLng.lat = lat;
outLatLng.lon = lon;
pushBuffer(outLatLng);
}
else
{
projPointLatLng = ProjPointOfLatLng(SmoothBuffer[1], InflectionPoint, SmoothBuffer[0]);
distance = calDistance(SmoothBuffer[1], projPointLatLng);
/*判断SmoothBuffer[1]到预测直线的距离distance根据距离的大小执行不同的逻辑*/
if( distance > thresholdDis)
{
/*输入坐标点被判断为拐点后要更新拐点清空拟合点集fittingDock*/
/* 输出点(lat, lon) */
outLatLng.lat = SmoothBuffer[1].lat;
outLatLng.lon = SmoothBuffer[1].lon;
pushBuffer(outLatLng);
/* 将(lat, lon)作为新的拐点更新 InflectionPoint */
InflectionPoint.lat = lat;
InflectionPoint.lon = lon;
/* 拐点更新后重新设置fittingDock中的数值内容 */
memset(fittingDock, 0, sizeof(LatLng) * FITTING_DOCK_SIZE);
fittingDock[0].lat = lat;
fittingDock[0].lon = lon;
dockTrail = 1;
}
else
{
/*当输入点被判断为非拐点后根据拟合点集fittingDock的大小执行不同的逻辑*/
if( dockTrail >= FITTING_DOCK_SIZE)
{
for ( i = 0 ; i < FITTING_DOCK_SIZE ; ++i)
{
fittingDockLat[i] = fittingDock[i].lat;
fittingDockLon[i] = fittingDock[i].lon;
}
ret = linearLeastSquaresFit(fittingDockLat, fittingDockLon, FITTING_DOCK_SIZE, &a, &b);
fittingProjPoint = SmoothBuffer[1];
if (ret == 0) /* ret==0表示直线拟合成功 */
{
fittingProjPoint.lat = (a*(SmoothBuffer[1].lon - b) + SmoothBuffer[1].lat) / (vivopow(a, 2) + 1);
fittingProjPoint.lon = a*fittingProjPoint.lat + b;
}
distanceFitting = calDistance(SmoothBuffer[1], fittingProjPoint);
if( distanceFitting > thresholdFittingDis)
{
// //FIXME: 射线拟合可能有逻辑漏洞,修复。
// dockTrail = 2;
// fittingDock[1] = fittingProjPoint;
// //fittingDock[1] = SmoothBuffer[1]; //TEST
// LatLng outLatLng = {lat, lon}; //有问题,漏更一个点
// pushBuffer(outLatLng);
//TODO: 测试新的添点策略
dockTrail = 2; /* remove the elements whose the index >= 3 */
fittingDock[1] = SmoothBuffer[1];
outLatLng.lat = SmoothBuffer[1].lat;
outLatLng.lon = SmoothBuffer[1].lon;
pushBuffer(outLatLng);
}
else
{
outLatLng.lat = fittingProjPoint.lat;
outLatLng.lon = fittingProjPoint.lon;
pushBuffer(outLatLng);
}
}else{
/*当fittingDock未被装满则说明当前输入点不符合fittingDock的输入条件直接将其输入以保证实时性*/
outLatLng.lat = lat;
outLatLng.lon = lon;
pushBuffer(outLatLng);
}
}
/* 2019-05-22 平滑改动:由均值滤波变成加权求和*/
double factor = 0;
if (outputTrail > 1)
{
factor = half / (outputTrail - 1);
}
double sumLat = 0; double sumLon = 0;
for (i = 0; i < outputTrail; ++i)
{
sumLat += OutputBuffer[i].lat * factor;
sumLon += OutputBuffer[i].lon * factor;
}
*outLat = sumLat + OutputBuffer[0].lat * (half - factor);
*outLon = sumLon + OutputBuffer[0].lon * (half - factor);
}
return 0;
}
/**----------------------------------------------------------------------
* Function : trackSmoothSlideWindowFree
* Description : 使
* Date : 2020/7/4 yuanlin_rjyb@vivo.com
*---------------------------------------------------------------------**/
int freeTrackSmooth(void)
{
if ( SmoothBuffer != NULL)
{
free(SmoothBuffer);
SmoothBuffer = NULL;
SmoothBufferSize = 0;
elemTrail = 0;
}
if ( OutputBuffer != NULL)
{
free(OutputBuffer);
OutputBuffer = NULL;
outputBufferSize = 0;
outputTrail = 0;
}
return 0;
}