整理计步器

PDRHistoryBranch
詹力 2023-02-25 22:43:50 +08:00
parent 5bd0ca97f2
commit d20b742a36
51 changed files with 9729 additions and 377 deletions

View File

@ -1,25 +1,10 @@
#pragma once
/******************** (C) COPYRIGHT 2017 Geek************************************
* File Name : Steps_Algorithm.h
/******************** (C) COPYRIGHT 2023 Geek************************************
* File Name : Pedometer.h
* Department : Sensor Team
* Current Version : V1.0
* Author : Xiaoyong Li
* Date of Issued : 2017.05.8
* Comments: step counter algorithm added
********************************************************************************
* THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR REFERENCE OR
* EDUCATION. AS A RESULT, Geek SOFTWARE SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
********************************************************************************
* Release Log
*
* Comments: step counter algorithm released
* Version Number : V1.0
* Author : Xiaoyong Li
* Date of Issued : 2017.05.8
* Current Version : V1.0.0
* Author : logzhan
* Date of Issued : 2023.02.24
*******************************************************************************/
#ifdef __cplusplus
@ -29,66 +14,45 @@ extern "C" {
#define _STEPS_ALGORITHM_H_
#include "pdr_sensor.h"
#define ACC_SAMPLE_RATE_100HZ
//#define ACC_SAMPLE_RATE_25HZ
#define IMU_SAMPLE_FREQ 100 // IMU采样频率100Hz
#define MS2S 1000 // 秒转毫秒单位
#ifdef ACC_SAMPLE_RATE_25HZ
#define DownResampleTimes 1
#define ACC_SAMPLE_TIME 40
#define SAMPLE_TIME_MIN 36
#else
#define DOWN_SAMPLE_TIMES 4
#define ACC_SAMPLE_TIME 10 //origin acc sampleFrequency is 100 hz
#define GYRO_SAMPLE_TIME 10
#define SAMPLE_TIME_MIN 9
#endif
#define DOWN_SAMPLE_NUM 4 // 降采样数量
#define ACC_SAMPLE_TIME MS2S / IMU_SAMPLE_FREQ // ACC采样间隔10ms
#define GYRO_SAMPLE_TIME MS2S / IMU_SAMPLE_FREQ // GYR采样间隔10ms
#define SAMPLE_TIME_MIN 9
#define SampleFrequency 25
#define SampleFrequencyFour 100
#define SampleFrequencydouble 50
#define SampleFrequencyOPF (37.5l)
#define SampleFrequencySix 150
#define AvergeFilterOrder 5
#define AxisNumber 4
#define FiltDifNumber 4
#define AxisNumberFiltOut 16 //(AxisNumber * FiltDifNumber)
#define AxisNumberStepSaveState 20 //(AxisNumberFiltOut + FiltDifNumber)
#define AccelerationNumber 39
#define ORI_ACC_SAMPLE_RATE 100 //origin acc sampleFrequency is 100 hz
#define WIN_LENGTH_AVE_DEVI 50 //
#define PI2A (180/3.1415926)
//#define NSTOS 1000000000
#define MS2S 1000
#define PEDOMETER_FREQ IMU_SAMPLE_FREQ / DOWN_SAMPLE_NUM // 计步器的频率是
#define SampleFrequencyFour 100
#define SampleFrequencydouble 50
#define SampleFrequencyOPF (37.5l)
#define SampleFrequencySix 150
#define AvergeFilterOrder 5
#define AXIS_NUM 4 // 轴的数量有4个: x、y、z、xyz
#define FILTER_NUM 4
#define FiltDifNumber 4
#define FILTER_AXIS_NUM AXIS_NUM * FILTER_NUM // 轴数量4滤波器数量4总共16轴滤波器输出
#define AxisNumberStepSaveState 20 // AxisNumberFiltOut + FiltDifNumber
#define ACC_BUFF_NUM 39
#define WIN_LENGTH_AVE_DEVI 50 //
#define PI2A (180/3.1415926)
#define STARTSTEPS 8
#define ACC_INSPECT_TIMEWIDTH 200 //origin acc sampleFrequency is 100 hz
#define ACC_INSPECT_TIMEWIDTH 200 // Origin acc sampleFrequency is 100 hz
#define WINDOW_LENGTH_MIN2MAX (ACC_INSPECT_TIMEWIDTH/2 - 1) //25hz , 1 second
//#define WINDOW_LENGTH_IN_VEHICLE
#define STARTSTEPS 8
/*#define PLATFORM_ANDROID_QCOM_AP*/
/*#define PLATFORM_ANDROID_QCOM_ADSP*/
#define PLATFORM_PC_WINDOWS
//#define PLATFORM_PC_LINUX
#if defined PLATFORM_ANDROID_QCOM_ADSP
#define STEPLIB_MEMSET SNS_OS_MEMSET
#if 1
#define SAM_STEP_LIB_NAME "steplib"
#define SAM_STEP_LIB_MSG_0(msg) UMSG(MSG_SSID_SNS,DBG_ERROR_PRIO, SAM_STEP_LIB_NAME" - "msg)
#define SAM_STEP_LIB_MSG_1(msg,p1) UMSG_1(MSG_SSID_SNS,DBG_ERROR_PRIO, SAM_STEP_LIB_NAME" - "msg,p1)
#define SAM_STEP_LIB_MSG_2(msg,p1,p2) UMSG_2(MSG_SSID_SNS,DBG_ERROR_PRIO, SAM_STEP_LIB_NAME" - "msg,p1,p2)
#define SAM_STEP_LIB_MSG_3(msg,p1,p2,p3) UMSG_3(MSG_SSID_SNS,DBG_ERROR_PRIO, SAM_STEP_LIB_NAME" - "msg,p1,p2,p3)
#define SAM_STEP_LIB_MSG_4(msg,p1,p2,p3,p4) UMSG_4(MSG_SSID_SNS,DBG_ERROR_PRIO, SAM_STEP_LIB_NAME" - "msg,p1,p2,p3,p4)
#else
#define SAM_STEP_LIB_MSG_0(msg)
#define SAM_STEP_LIB_MSG_1(msg,p1)
#define SAM_STEP_LIB_MSG_2(msg,p1,p2)
#define SAM_STEP_LIB_MSG_3(msg,p1,p2,p3)
#define SAM_STEP_LIB_MSG_4(msg,p1,p2,p3,p4)
#endif
#elif defined PLATFORM_ANDROID_QCOM_AP || defined PLATFORM_PC_WINDOWS || defined PLATFORM_PC_LINUX || defined PLATFORM_ANDROID_MTK || defined PLATFORM_ANDROID_QCOM_SLPI845
#define STEPLIB_MEMSET memset
@ -108,38 +72,39 @@ typedef struct {
double walk;
double walkRealTime;
double nD;
}stepsDfine;
}StepsDefine_t;
typedef enum {
nonSteps = 0,
walk,
}enumState;
run,
}StepState_t;
typedef struct {
unsigned char sign;
enumState state;
StepState_t state;
unsigned long long stateStartTime;
unsigned long long stepsStartTime;
}stateNowDfine;
typedef struct {
enumState state;
StepState_t state;
unsigned long long startTimeStamp;
}stateDfine;
}StateDef_t;
typedef struct {
int flag;
double ax;
double ay;
double az;
}downSample;
}DownSample_t;
/**---------------------------------------------------------------------
* Function : getPedometerLibVersion
* Function : Pedometer_GetVersion
* Description :
* Date : 2020/2/20
* Date : 2023/02/24
*---------------------------------------------------------------------**/
const char* GetPedometerVersion(void);
const char* Pedometer_GetVersion(void);
/**---------------------------------------------------------------------
* Function : initPedometer
@ -149,28 +114,28 @@ const char* GetPedometerVersion(void);
void Pedometer_Init(void);
/**---------------------------------------------------------------------
* Function : reinitPedometer
* Description : PDR ÖØгõʼ»¯¼Æ²½Æ÷
* Date : 2020/2/20 logzhan
* Function : Pedometer_ReInit
* Description :
* Date : 2023/02/24 logzhan
*---------------------------------------------------------------------**/
void reinitPedometer(void);
void Pedometer_ReInit(void);
/**---------------------------------------------------------------------
* Function : updatePedometer
* Function : PedometerUpdate
* Description : PDR ,
* Date : 2020/2/1 logzhan
* Date : 2023/02/25 logzhan
*---------------------------------------------------------------------**/
void PedometerUpdate(IMU_t* ss_data, unsigned long* step);
void Steps_State_Detect(enumState* state);
void Pedometer_Update(IMU_t* ss_data, unsigned long* step);
void Pedometer_GetState(StepState_t* state);
/**---------------------------------------------------------------------
* Function : detVehicleMode
* Function : DetVehicleMode
* Description : PDR ,
* Date : 2020/2/1 logzhan
* Date : 2023/02/24 logzhan
*---------------------------------------------------------------------**/
void detVehicleMode(double ax, double ay, double az);
void DetVehicleMode(double ax, double ay, double az);
#endif
#ifdef __cplusplus
}

View File

@ -134,7 +134,7 @@ int InsLocationUpdate(IMU_t* ImuData, EKFPara_t* Ekf) {
if (pdr.MotionType == DETECTOR_TYPE_HANDHELD)pdr.motionFreq = 0.1f;
// 计步器输入传感器数据占10%的运行时间
PedometerUpdate(ImuData, &pdr.steps);
Pedometer_Update(ImuData, &pdr.steps);
// ----- Filter Initialization ------- //
if (pdr.sysStatus == IS_INITIAL) {

View File

@ -14,62 +14,57 @@
const static char* Pedometer_Version = "Pedometer.1.0.0.20230224";
static void Steps_Acc_Save(double ax, double ay, double az);
static void AccBufferUpdate(double ax, double ay, double az);
static void State_Detect(unsigned long long timeStamp);
static void Steps_Filt(void);
static void Pedometer_Filter(void);
static void Steps_Feature(void);
static void Steps_Rcording(unsigned long long timeStamp);
static double stepsFiltAcc[AxisNumber][AccelerationNumber];
static double AccBuffer[AXIS_NUM][ACC_BUFF_NUM];
static float AccData[ACC_INSPECT_TIMEWIDTH] = { 0 };
static float lastAccZ = 0;
static unsigned int ReceivedHowManyAcc = 0;
static double SumAcc = 0;
static double DifFiltCoefficientOne[5] = { 0.0123456790123457, 0.0493827160493827, 0.123456790123457, 0.197530864197531, 0.234567901234568 };
static double DifFiltCoefficientTwo[9] = { 0.0016, 0.0064, 0.016, 0.032, 0.056, 0.0832, 0.1088, 0.128, 0.136 };
static double DifFiltCoefficientThree[13] = { 0.000416493127863390, 0.00166597251145356, 0.00416493127863390, 0.00832986255726780, 0.0145772594752187, 0.0233236151603498, 0.0349854227405248, 0.0483132028321533, 0.0620574760516451, 0.0749687630154102, 0.0857975843398584, 0.0932944606413994, 0.0962099125364431 };
static double DifFiltCoefficientFour[17] = { 0.000152415790275873, 0.000609663161103490, 0.00152415790275873, 0.00304831580551745, 0.00533455265965554, 0.00853528425544886, 0.0128029263831733, 0.0182898948331047, 0.0251486053955190, 0.0329218106995885, 0.0411522633744856, 0.0493827160493827, 0.0571559213534522, 0.0640146319158665, 0.0695016003657979, 0.0731595793324188, 0.0745313214449017 };
static double DifFiltCoefficient1[5] = { 0.0123456790123457, 0.0493827160493827, 0.123456790123457, 0.197530864197531, 0.234567901234568 };
static double DifFiltCoefficient2[9] = { 0.0016, 0.0064, 0.016, 0.032, 0.056, 0.0832, 0.1088, 0.128, 0.136 };
static double DifFiltCoefficient3[13] = { 0.000416493127863390, 0.00166597251145356, 0.00416493127863390, 0.00832986255726780, 0.0145772594752187, 0.0233236151603498, 0.0349854227405248, 0.0483132028321533, 0.0620574760516451, 0.0749687630154102, 0.0857975843398584, 0.0932944606413994, 0.0962099125364431 };
static double DifFiltCoefficient4[17] = { 0.000152415790275873, 0.000609663161103490, 0.00152415790275873, 0.00304831580551745, 0.00533455265965554, 0.00853528425544886, 0.0128029263831733, 0.0182898948331047, 0.0251486053955190, 0.0329218106995885, 0.0411522633744856, 0.0493827160493827, 0.0571559213534522, 0.0640146319158665, 0.0695016003657979, 0.0731595793324188, 0.0745313214449017 };
static double DifFiltOutput[AxisNumberFiltOut][5];
static double OutputFilt[AxisNumberFiltOut][2];
static double StepLcVar[AxisNumberFiltOut][3];
static char StepReFeature[AxisNumberFiltOut] = { 0 };
static double StepFetureAmp[AxisNumberFiltOut][8];
static unsigned short StepFetureTime[AxisNumberFiltOut][8];
static double DifFiltOutput[FILTER_AXIS_NUM][5];
static double OutputFilt[FILTER_AXIS_NUM][2];
static double StepLcVar[FILTER_AXIS_NUM][3];
static char StepReFeature[FILTER_AXIS_NUM] = { 0 };
static double StepFetureAmp[FILTER_AXIS_NUM][8];
static unsigned short StepFetureTime[FILTER_AXIS_NUM][8];
static double StepRecordeState[AxisNumberStepSaveState][4];
static double StepRecordeStateTime[AxisNumberStepSaveState][9];
static unsigned long long timeStampSave[AxisNumberStepSaveState][2];
static unsigned short StepMaxTime = 100;
/*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>IJ<EFBFBD><C4B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ40ms,25HZ*/
static unsigned short StepMinTime = 10;
static unsigned long long timeStamp = 0;
static unsigned long long timeStamp_in_vehicle = 0;
static char Flag_whether_in_vehicle = 0;
static char Flag_step_exist = 0;
static double AvergeFiltSave[AxisNumber - 1][AvergeFilterOrder]/* = { 0 }*/;
stepsDfine Steps = { 0, 0 };
stepsRe ReSteps = { 0 };
downSample DownSample = { 0, 0, 0, 0 };
static double StateDetectLcvar[5] = { 0 };
static enumState stateLcVar[2] = { nonSteps, nonSteps };
static double AvergeFiltSave[AXIS_NUM - 1][AvergeFilterOrder];
StepsDefine_t Steps = { 0, 0 };
stepsRe ReSteps = { 0 };
DownSample_t DownSample = { 0, 0, 0, 0 };
static double StateDetectLcVar[5] = { 0 };
static StepState_t stateLcVar[2] = { nonSteps, nonSteps };
stateNowDfine stateNow;
stateDfine Restate;
StateDef_t Restate;
/**---------------------------------------------------------------------
* Function : GetPedometerVersion
* Function : Pedometer_GetVersion
* Description :
* Date : 2023/02/24
*---------------------------------------------------------------------**/
const char* GetPedometerVersion(void)
{
const char* Pedometer_GetVersion(void){
return Pedometer_Version;
}
@ -80,7 +75,7 @@ const char* GetPedometerVersion(void)
*---------------------------------------------------------------------**/
void Pedometer_Init(void)
{
STEPLIB_MEMSET(stepsFiltAcc, 0, sizeof(stepsFiltAcc));
STEPLIB_MEMSET(AccBuffer, 0, sizeof(AccBuffer));
STEPLIB_MEMSET(DifFiltOutput, 0, sizeof(DifFiltOutput));
STEPLIB_MEMSET(OutputFilt, 0, sizeof(OutputFilt));
STEPLIB_MEMSET(StepLcVar, 0, sizeof(StepLcVar));
@ -95,7 +90,7 @@ void Pedometer_Init(void)
timeStamp = 0;
STEPLIB_MEMSET(&Steps, 0, sizeof(Steps));
STEPLIB_MEMSET(&ReSteps, 0, sizeof(ReSteps));
STEPLIB_MEMSET(StateDetectLcvar, 0, sizeof(StateDetectLcvar));
STEPLIB_MEMSET(StateDetectLcVar, 0, sizeof(StateDetectLcVar));
STEPLIB_MEMSET(stateLcVar, 0, sizeof(stateLcVar));
STEPLIB_MEMSET(&stateNow, 0, sizeof(stateNow));
STEPLIB_MEMSET(&Restate, 0, sizeof(Restate));
@ -113,42 +108,41 @@ void Pedometer_Init(void)
* Description : PDR
* Date : 2020/2/20 logzhan
*---------------------------------------------------------------------**/
void reinitPedometer(void)
void Pedometer_ReInit(void)
{
timeStamp = 0;
STEPLIB_MEMSET(&Steps, 0, sizeof(Steps));
STEPLIB_MEMSET(&ReSteps, 0, sizeof(ReSteps));
}
/**---------------------------------------------------------------------
* Function : updatePedometer
* Function : Pedometer_Update
* Description : PDR ,
* Date : 2020/2/1 logzhan
* Date : 2023/02/25 logzhan
*---------------------------------------------------------------------**/
void PedometerUpdate(IMU_t* ss_data, unsigned long* step)
void Pedometer_Update(IMU_t* imu, unsigned long* step)
{
unsigned char k = 0;
// 检测当前是否属于开车状态, 这个函数也是相对耗时的, 这个函数只用
// 了加速度计的z轴, 是不是存在问题?
detVehicleMode(ss_data->acc.s[0], ss_data->acc.s[1], ss_data->acc.s[2]);
DetVehicleMode(imu->acc.s[0], imu->acc.s[1], imu->acc.s[2]);
timeStamp += ACC_SAMPLE_TIME;
DownSample.ax += ss_data->acc.s[0] / 9.8;
DownSample.ay += ss_data->acc.s[1] / 9.8;
DownSample.az += ss_data->acc.s[2] / 9.8;
DownSample.ax += imu->acc.s[0] / 9.8;
DownSample.ay += imu->acc.s[1] / 9.8;
DownSample.az += imu->acc.s[2] / 9.8;
DownSample.flag++;
if (DownSample.flag == DOWN_SAMPLE_TIMES)
if (DownSample.flag == DOWN_SAMPLE_NUM)
{
if (Restate.startTimeStamp == 0)
{
Restate.startTimeStamp = timeStamp;
}
DownSample.ax /= DOWN_SAMPLE_TIMES;
DownSample.ay /= DOWN_SAMPLE_TIMES;
DownSample.az /= DOWN_SAMPLE_TIMES;
DownSample.ax /= DOWN_SAMPLE_NUM;
DownSample.ay /= DOWN_SAMPLE_NUM;
DownSample.az /= DOWN_SAMPLE_NUM;
for (k = 0; k < AvergeFilterOrder - 1; k++)
{
AvergeFiltSave[0][k] = AvergeFiltSave[0][k + 1];
@ -170,15 +164,15 @@ void PedometerUpdate(IMU_t* ss_data, unsigned long* step)
DownSample.ay /= AvergeFilterOrder;
DownSample.az /= AvergeFilterOrder;
// 计步器的加速度更新
Steps_Acc_Save(DownSample.ax, DownSample.ay, DownSample.az);
// 计步器缓存Buffer更新
AccBufferUpdate(DownSample.ax, DownSample.ay, DownSample.az);
// 计步器状态检测
State_Detect(timeStamp);
if (StateDetectLcvar[4] < 0.5l)
if (StateDetectLcVar[4] < 0.5l)
{
// 滤波处理
Steps_Filt();
Pedometer_Filter();
// 计步特征
Steps_Feature();
// 步数记录
@ -189,7 +183,8 @@ void PedometerUpdate(IMU_t* ss_data, unsigned long* step)
}
// 如果计步标志位不存在,那么不计步数
if (Flag_step_exist == 0){
timeStamp = timeStamp + 1; //vehicle for debug
// vehicle for debug
timeStamp = timeStamp + 1;
}
else if (llabs((long long)(timeStamp - timeStamp_in_vehicle)) > 500)
{
@ -204,7 +199,7 @@ void PedometerUpdate(IMU_t* ss_data, unsigned long* step)
* Description : PDR ,
* Date : 2020/2/1 logzhan
*---------------------------------------------------------------------**/
void detVehicleMode(double ax, double ay, double az)
void DetVehicleMode(double ax, double ay, double az)
{
int t;
int index_move;
@ -291,156 +286,101 @@ void detVehicleMode(double ax, double ay, double az)
}
static void Steps_Acc_Save(double ax, double ay, double az)
/**---------------------------------------------------------------------
* Function : AccBufferUpdate
* Description : AccBuffer
* Date : 2023/02/25
*---------------------------------------------------------------------**/
static void AccBufferUpdate(double ax, double ay, double az)
{
short i, j;
for (i = 0; i < AxisNumber; i++){
for (j = 0; j < (AccelerationNumber - 1); j++){
stepsFiltAcc[i][j] = stepsFiltAcc[i][j + 1];
for (uint8_t i = 0; i < AXIS_NUM; i++){
for (uint8_t j = 0; j < (ACC_BUFF_NUM - 1); j++){
AccBuffer[i][j] = AccBuffer[i][j + 1];
}
}
stepsFiltAcc[0][AccelerationNumber - 1] = ax;
stepsFiltAcc[1][AccelerationNumber - 1] = ay;
stepsFiltAcc[2][AccelerationNumber - 1] = az;
stepsFiltAcc[3][AccelerationNumber - 1] = (sqrt(ax*ax + ay*ay + az*az));
AccBuffer[0][ACC_BUFF_NUM - 1] = ax;
AccBuffer[1][ACC_BUFF_NUM - 1] = ay;
AccBuffer[2][ACC_BUFF_NUM - 1] = az;
AccBuffer[3][ACC_BUFF_NUM - 1] = sqrt(ax*ax + ay*ay + az*az);
}
/*
DifFiltOutput <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ16*5
OutputFilt <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ16*2
0 filter one and acc x
1 filter one and acc y
2 filter one and acc z
3 filter one and acc xyz
4 filter two and acc x
5 filter two and acc y
6 filter two and acc z
7 filter two and acc xyz
8 filter three and acc x
9 filter three and acc y
10 filter three and acc z
11 filter three and acc xyz
12 filter four and acc x
13 filter four and acc y
14 filter four and acc z
15 filter four and acc xyz
*/
static void Steps_Filt(void)//filter bank
/**---------------------------------------------------------------------
* Function : Pedometer_Filter
* Description : ,4x,y,z,mod(x,y,z)
* 16
* Date : 2023/02/25
*---------------------------------------------------------------------**/
static void Pedometer_Filter(void)
{
short i, j;
double FiltSum;
for (i = 0; i < AxisNumberFiltOut; i++)
{
for (i = 0; i < FILTER_AXIS_NUM; i++){
DifFiltOutput[i][0] = DifFiltOutput[i][1];
DifFiltOutput[i][1] = DifFiltOutput[i][2];
DifFiltOutput[i][2] = DifFiltOutput[i][3];
DifFiltOutput[i][3] = DifFiltOutput[i][4];
OutputFilt[i][0] = OutputFilt[i][1];
OutputFilt[i][0] = OutputFilt[i][1];
}
for (i = 0; i < AxisNumber; i++)
{
for (i = 0; i < AXIS_NUM; i++){
FiltSum = 0;
/*filterϵ<72><CFB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ5*/
for (j = 0; j < 4; j++)
{
FiltSum += DifFiltCoefficientOne[j] * (stepsFiltAcc[i][15 + j] + stepsFiltAcc[i][23 - j]);
FiltSum += DifFiltCoefficient1[j] * (AccBuffer[i][15 + j] + AccBuffer[i][23 - j]);
}
FiltSum += DifFiltCoefficientOne[4] * stepsFiltAcc[i][19];
FiltSum += DifFiltCoefficient1[4] * AccBuffer[i][19];
DifFiltOutput[i][4] = (FiltSum);
FiltSum = 0;
/*filterϵ<72><CFB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ9*/
for (j = 0; j < 8; j++)
{
FiltSum += DifFiltCoefficientTwo[j] * (stepsFiltAcc[i][11 + j] + stepsFiltAcc[i][27 - j]);
FiltSum += DifFiltCoefficient2[j] * (AccBuffer[i][11 + j] + AccBuffer[i][27 - j]);
}
FiltSum += DifFiltCoefficientTwo[8] * stepsFiltAcc[i][19];
DifFiltOutput[i + AxisNumber][4] = (FiltSum);
FiltSum += DifFiltCoefficient2[8] * AccBuffer[i][19];
DifFiltOutput[i + AXIS_NUM][4] = (FiltSum);
FiltSum = 0;
/*filterϵ<72><CFB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ13*/
for (j = 0; j < 12; j++)
{
FiltSum += DifFiltCoefficientThree[j] * (stepsFiltAcc[i][7 + j] + stepsFiltAcc[i][31 - j]);
for (j = 0; j < 12; j++){
FiltSum += DifFiltCoefficient3[j] * (AccBuffer[i][7 + j] + AccBuffer[i][31 - j]);
}
FiltSum += DifFiltCoefficientThree[12] * stepsFiltAcc[i][19];
DifFiltOutput[i + AxisNumber * 2][4] = (FiltSum);
FiltSum += DifFiltCoefficient3[12] * AccBuffer[i][19];
DifFiltOutput[i + AXIS_NUM * 2][4] = (FiltSum);
FiltSum = 0;
/*filterϵ<72><CFB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ17*/
for (j = 0; j < 16; j++)
{
FiltSum += DifFiltCoefficientFour[j] * (stepsFiltAcc[i][3 + j] + stepsFiltAcc[i][35 - j]);
for (j = 0; j < 16; j++){
FiltSum += DifFiltCoefficient4[j] * (AccBuffer[i][3 + j] + AccBuffer[i][35 - j]);
}
FiltSum += DifFiltCoefficientFour[16] * stepsFiltAcc[i][19];
DifFiltOutput[i + AxisNumber * 3][4] = (FiltSum);
FiltSum += DifFiltCoefficient4[16] * AccBuffer[i][19];
DifFiltOutput[i + AXIS_NUM * 3][4] = (FiltSum);
}
for (i = 0; i < AxisNumberFiltOut; i++)
{
// 更新16个轴计步器的输出结果
for (i = 0; i < FILTER_AXIS_NUM; i++){
OutputFilt[i][1] = DifFiltOutput[i][4];
}
}
/*
StepLcVar <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ16*3
StepLcVar[nA][0]<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.<EFBFBD><EFBFBD>¼<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
StepLcVar[nA][1]<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>½<EFBFBD><EFBFBD>ı<EFBFBD>־<EFBFBD><EFBFBD>1:<EFBFBD><EFBFBD><EFBFBD><EFBFBD> -1:<EFBFBD>½<EFBFBD> 0:<EFBFBD><EFBFBD>ʼֵ
StepLcVar[nA][2]<EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>򲨹ȵķ<EFBFBD>ֵ
StepFetureAmp <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ16*8 <EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD><EFBFBD>ֵ
StepFetureTime <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ16*8 <EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
StepReFeature <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ16*1
0 filter one and acc x
1 filter one and acc y
2 filter one and acc z
3 filter one and acc xyz
4 filter two and acc x
5 filter two and acc y
6 filter two and acc z
7 filter two and acc xyz
8 filter three and acc x
9 filter three and acc y
10 filter three and acc z
11 filter three and acc xyz
12 filter four and acc x
13 filter four and acc y
14 filter four and acc z
15 filter four and acc xyz
*/
static void Steps_Feature(void)
{
short nA, nB;
for (nA = 0; nA < AxisNumberFiltOut; nA++)
for (nA = 0; nA < FILTER_AXIS_NUM; nA++)
{
/*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.ÿ<>μӣ<CEBC>*/
StepLcVar[nA][0] = StepLcVar[nA][0] + 1;
/*<2A>Ҳ<EFBFBD><D2B2>ȣ<EFBFBD><C8A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(StepLcVar[nA][1] <1)<29><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(OutputFilt[nA][1] > OutputFilt[nA][0])<29><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ұߵ<D2B1><DFB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> StepLcVar[nA][1] = 1*/
if ((StepLcVar[nA][1] < 1) && ((OutputFilt[nA][1] > OutputFilt[nA][0]) || ((OutputFilt[nA][1] == OutputFilt[nA][0]) && (StepLcVar[nA][1] == 1))))
if ((StepLcVar[nA][1] < 1) && ((OutputFilt[nA][1] > OutputFilt[nA][0]) ||
((OutputFilt[nA][1] == OutputFilt[nA][0]) && (StepLcVar[nA][1] == 1))))
{
for (nB = 0; nB < 7; nB++)
{
StepFetureAmp[nA][nB] = StepFetureAmp[nA][nB + 1];
}
/*<2A><EFBFBD><E6B4A2><EFBFBD>ֵ=<3D><>һ<EFBFBD>β<EFBFBD><CEB2><EFBFBD>ֵ-<2D><>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD>ֵ*/
StepFetureAmp[nA][7] = StepLcVar[nA][2] - OutputFilt[nA][0];
/*<2A><EFBFBD><E6B4A2>ǰ<EFBFBD><C7B0><EFBFBD>ȵķ<C8B5>ֵ*/
StepLcVar[nA][2] = OutputFilt[nA][0];
for (nB = 0; nB < 7; nB++)
{
StepFetureTime[nA][nB] = StepFetureTime[nA][nB + 1];
}
/*<2A><EFBFBD><E6B4A2><EFBFBD>ļ<EFBFBD><C4BC>ʱ<EFBFBD><CAB1>*/
StepFetureTime[nA][7] = (unsigned short)(StepLcVar[nA][0]);
/*<2A>ҵ<EFBFBD><D2B5><EFBFBD><EFBFBD>Ⱥ󣬼<C8BA><F3A3ACBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
StepLcVar[nA][0] = 0;
/*<2A>ҵ<EFBFBD><D2B5><EFBFBD><EFBFBD>Ⱥ󣬼<C8BA>¼<EFBFBD><C2BC><EFBFBD><EFBFBD>״̬*/
StepLcVar[nA][1] = 1;
StepReFeature[nA] = 1;
}
@ -451,19 +391,14 @@ static void Steps_Feature(void)
{
StepFetureAmp[nA][nB] = StepFetureAmp[nA][nB + 1];
}
/*<2A><EFBFBD><E6B4A2><EFBFBD>ֵ=<3D><>һ<EFBFBD>β<EFBFBD><CEB2><EFBFBD>ֵ-<2D><>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD>ֵ*/
StepFetureAmp[nA][7] = OutputFilt[nA][0] - StepLcVar[nA][2];
/*<2A><EFBFBD><E6B4A2>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD>ķ<EFBFBD>ֵ*/
StepLcVar[nA][2] = OutputFilt[nA][0];
for (nB = 0; nB < 7; nB++)
{
StepFetureTime[nA][nB] = StepFetureTime[nA][nB + 1];
}
/*<2A><EFBFBD><E6B4A2><EFBFBD>ļ<EFBFBD><C4BC>ʱ<EFBFBD><CAB1>*/
StepFetureTime[nA][7] = (unsigned short)(StepLcVar[nA][0]);
/*<2A>ҵ<EFBFBD><D2B5><EFBFBD><EFBFBD><EFBFBD>󣬼<EFBFBD><F3A3ACBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
StepLcVar[nA][0] = 0;
/*<2A>ҵ<EFBFBD><D2B5><EFBFBD><EFBFBD>Ⱥ󣬼<C8BA>¼<EFBFBD>Ͻ<EFBFBD>״̬*/
StepLcVar[nA][1] = -1;
StepReFeature[nA] = 1;
}
@ -477,10 +412,10 @@ static void Steps_Rcording(unsigned long long timeStamp)
double StepFetureAmp12, StepFetureAmp34, StepFetureAmp56, StepFetureAmp78, StepFetureAmp14, StepFetureAmp58, StepFetureAmp18;
unsigned short StepFetureTime12, StepFetureTime34, StepFetureTime56, StepFetureTime78, StepFetureTime14, StepFetureTime58, StepFetureTime38, StepFetureTime18;
int j;
for (nC = AxisNumber; nC < AxisNumberStepSaveState; nC++)
for (nC = AXIS_NUM; nC < AxisNumberStepSaveState; nC++)
{
if ((StepRecordeStateTime[nC][4] > 5) && ((nD == 0) || (nD > StepRecordeStateTime[nC][5] / StepRecordeStateTime[nC][4])) && (nC != AxisNumberFiltOut))
if ((StepRecordeStateTime[nC][4] > 5) && ((nD == 0) || (nD > StepRecordeStateTime[nC][5] / StepRecordeStateTime[nC][4])) && (nC != FILTER_AXIS_NUM))
{
nD = StepRecordeStateTime[nC][5] / StepRecordeStateTime[nC][4];
}
@ -488,23 +423,23 @@ static void Steps_Rcording(unsigned long long timeStamp)
if (nD > 0)
{
for (nC = 0; nC < AxisNumber - 1; nC++) // nC<AxisNumber;
for (nC = 0; nC < AXIS_NUM - 1; nC++) // nC<AxisNumber;
{
if ((StepRecordeStateTime[nC][4] > 5) && (nD > StepRecordeStateTime[nC][5] / StepRecordeStateTime[nC][4]))
{
nD = StepRecordeStateTime[nC][5] / StepRecordeStateTime[nC][4];
}
}
nC = AxisNumberFiltOut;
nC = FILTER_AXIS_NUM;
if ((StepRecordeStateTime[nC][4] > 5) && (nD > StepRecordeStateTime[nC][5] / StepRecordeStateTime[nC][4]))
{
nD = StepRecordeStateTime[nC][5] / StepRecordeStateTime[nC][4];
}
}
Differ_Sum = 0;
for (j = 0; j < AccelerationNumber; j++)
for (j = 0; j < ACC_BUFF_NUM; j++)
{
Differ_Sum = Differ_Sum + fabs(stepsFiltAcc[3][j + 1] - stepsFiltAcc[3][j]);
Differ_Sum = Differ_Sum + fabs(AccBuffer[3][j + 1] - AccBuffer[3][j]);
}
nC = 3; //20180917,nC=4 to 3;
@ -522,7 +457,7 @@ static void Steps_Rcording(unsigned long long timeStamp)
}
}
for (nA = 0; nA < AxisNumberFiltOut; nA++)
for (nA = 0; nA < FILTER_AXIS_NUM; nA++)
{
if (StepReFeature[nA] == 1)
{
@ -550,17 +485,17 @@ static void Steps_Rcording(unsigned long long timeStamp)
StepRecordeStateTime[nA][3] = StepRecordeStateTime[nA][3] + StepFetureTime[nA][7];
/*(nA % 4 == 3)Ϊ<>ϼ<EFBFBD><CFBC>ٶȾ<D9B6><C8BE>˲<EFBFBD><CBB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ*/
if ((nA % 4 == 3) && (StepRecordeState[AxisNumberFiltOut + nA / 4][2] < 30))
if ((nA % 4 == 3) && (StepRecordeState[FILTER_AXIS_NUM + nA / 4][2] < 30))
{
StepRecordeState[AxisNumberFiltOut + nA / 4][2] = StepRecordeState[AxisNumberFiltOut + nA / 4][2] + 0.51;
StepRecordeStateTime[AxisNumberFiltOut + nA / 4][2] = StepRecordeStateTime[AxisNumberFiltOut + nA / 4][2] + StepFetureTime[nA][7];
StepRecordeState[AxisNumberFiltOut + nA / 4][3] = StepRecordeState[AxisNumberFiltOut + nA / 4][3] + 0.51;
StepRecordeStateTime[AxisNumberFiltOut + nA / 4][3] = StepRecordeStateTime[AxisNumberFiltOut + nA / 4][3] + StepFetureTime[nA][7];
StepRecordeState[FILTER_AXIS_NUM + nA / 4][2] = StepRecordeState[FILTER_AXIS_NUM + nA / 4][2] + 0.51;
StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][2] = StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][2] + StepFetureTime[nA][7];
StepRecordeState[FILTER_AXIS_NUM + nA / 4][3] = StepRecordeState[FILTER_AXIS_NUM + nA / 4][3] + 0.51;
StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][3] = StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][3] + StepFetureTime[nA][7];
}
}
/*0.1538 0.1445 0.1352 0.1260 0.1167 0.1075 0.0982 0.0890 0.0798 0.0705 0.0612 0.0520 0.0427 0.0335 0.0243 0.0150*/
thred = 0.015 + ((AxisNumberFiltOut - nA - 1) / AxisNumber) * 0.037;//dynamic threshold
thred = 0.015 + ((FILTER_AXIS_NUM - nA - 1) / AXIS_NUM) * 0.037;//dynamic threshold
if (StepRecordeStateTime[nA][6] < 60) //25
{
@ -576,15 +511,15 @@ static void Steps_Rcording(unsigned long long timeStamp)
/*(nA % 4 == 3)Ϊ<>ϼ<EFBFBD><CFBC>ٶȾ<D9B6><C8BE>˲<EFBFBD><CBB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ*/
if (nA % 4 == 3)
{
if (StepRecordeStateTime[AxisNumberFiltOut + nA / 4][6] < 25)
if (StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][6] < 25)
{
StepRecordeStateTime[AxisNumberFiltOut + nA / 4][6]++;
StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][6]++;
}
else
{
StepRecordeStateTime[AxisNumberFiltOut + nA / 4][4] = 0;
StepRecordeStateTime[AxisNumberFiltOut + nA / 4][5] = 0;
StepRecordeStateTime[AxisNumberFiltOut + nA / 4][7] = 0;
StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][4] = 0;
StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][5] = 0;
StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][7] = 0;
}
if ((fabs(StepFetureAmp[nA][2] - StepFetureAmp[nA][3]) / (StepFetureAmp34) < 0.15l)
&& (fabs(StepFetureAmp[nA][3] - StepFetureAmp[nA][4]) / (StepFetureAmp[nA][3] + StepFetureAmp[nA][4]) < 0.15l)
@ -600,15 +535,15 @@ static void Steps_Rcording(unsigned long long timeStamp)
&& (StepFetureTime58 > StepMinTime)
&& (StepFetureTime58 < StepMaxTime))
{
StepRecordeStateTime[AxisNumberFiltOut + nA / 4][8] = SampleFrequency * 3.0 / StepFetureTime38;
timeStampSave[AxisNumberFiltOut + nA / 4][1] = timeStamp;
if (StepRecordeState[AxisNumberFiltOut + nA / 4][0] == 0)
StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][8] = PEDOMETER_FREQ * 3.0 / StepFetureTime38;
timeStampSave[FILTER_AXIS_NUM + nA / 4][1] = timeStamp;
if (StepRecordeState[FILTER_AXIS_NUM + nA / 4][0] == 0)
{
StepRecordeState[AxisNumberFiltOut + nA / 4][0] = StepRecordeState[AxisNumberFiltOut + nA / 4][0] + 3;
StepRecordeStateTime[AxisNumberFiltOut + nA / 4][0] = StepRecordeStateTime[AxisNumberFiltOut + nA / 4][0] + StepFetureTime38;
StepRecordeState[AxisNumberFiltOut + nA / 4][1] = StepRecordeState[AxisNumberFiltOut + nA / 4][1] + 3;
StepRecordeStateTime[AxisNumberFiltOut + nA / 4][1] = StepRecordeStateTime[AxisNumberFiltOut + nA / 4][1] + StepFetureTime38;
timeStampSave[AxisNumberFiltOut + nA / 4][0] = timeStamp - (unsigned long)(StepFetureTime38 * 1000 / SampleFrequency);
StepRecordeState[FILTER_AXIS_NUM + nA / 4][0] = StepRecordeState[FILTER_AXIS_NUM + nA / 4][0] + 3;
StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][0] = StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][0] + StepFetureTime38;
StepRecordeState[FILTER_AXIS_NUM + nA / 4][1] = StepRecordeState[FILTER_AXIS_NUM + nA / 4][1] + 3;
StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][1] = StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][1] + StepFetureTime38;
timeStampSave[FILTER_AXIS_NUM + nA / 4][0] = timeStamp - (unsigned long)(StepFetureTime38 * 1000 / PEDOMETER_FREQ);
}
else
{
@ -618,78 +553,78 @@ static void Steps_Rcording(unsigned long long timeStamp)
&& ((ABS_INT(StepFetureTime[nA][5] - StepFetureTime[nA][7]) < 0.2 * (StepFetureTime[nA][5] + StepFetureTime[nA][7])) || (ABS_INT(StepFetureTime[nA][5] - StepFetureTime[nA][7]) < 5)))
{
if ((StepRecordeStateTime[AxisNumberFiltOut + nA / 4][7] > 0) && (fabs(StepFetureTime38 / 3.0 - StepRecordeStateTime[AxisNumberFiltOut + nA / 4][7]) > 0.2 * StepRecordeStateTime[AxisNumberFiltOut + nA / 4][7]))
if ((StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][7] > 0) && (fabs(StepFetureTime38 / 3.0 - StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][7]) > 0.2 * StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][7]))
{
StepRecordeStateTime[AxisNumberFiltOut + nA / 4][4] = 0;
StepRecordeStateTime[AxisNumberFiltOut + nA / 4][5] = 0;
StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][4] = 0;
StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][5] = 0;
}
if (StepRecordeStateTime[AxisNumberFiltOut + nA / 4][6] >= 6)
if (StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][6] >= 6)
{
StepRecordeStateTime[AxisNumberFiltOut + nA / 4][4] = StepRecordeStateTime[AxisNumberFiltOut + nA / 4][4] + 3;
StepRecordeStateTime[AxisNumberFiltOut + nA / 4][5] = StepRecordeStateTime[AxisNumberFiltOut + nA / 4][5] + StepFetureTime38;
StepRecordeStateTime[AxisNumberFiltOut + nA / 4][6] = 0;
StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][4] = StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][4] + 3;
StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][5] = StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][5] + StepFetureTime38;
StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][6] = 0;
}
StepRecordeStateTime[AxisNumberFiltOut + nA / 4][7] = StepFetureTime38 / 3.0;
StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][7] = StepFetureTime38 / 3.0;
}
if (StepRecordeState[AxisNumberFiltOut + nA / 4][3] <= 3)
if (StepRecordeState[FILTER_AXIS_NUM + nA / 4][3] <= 3)
{
StepRecordeState[AxisNumberFiltOut + nA / 4][0] = StepRecordeState[AxisNumberFiltOut + nA / 4][0] + StepRecordeState[AxisNumberFiltOut + nA / 4][3];
StepRecordeStateTime[AxisNumberFiltOut + nA / 4][0] = StepRecordeStateTime[AxisNumberFiltOut + nA / 4][0] + StepRecordeStateTime[AxisNumberFiltOut + nA / 4][3];
StepRecordeState[FILTER_AXIS_NUM + nA / 4][0] = StepRecordeState[FILTER_AXIS_NUM + nA / 4][0] + StepRecordeState[FILTER_AXIS_NUM + nA / 4][3];
StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][0] = StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][0] + StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][3];
}
else
{
StepRecordeState[AxisNumberFiltOut + nA / 4][0] = StepRecordeState[AxisNumberFiltOut + nA / 4][0] + 3;
StepRecordeStateTime[AxisNumberFiltOut + nA / 4][0] = StepRecordeStateTime[AxisNumberFiltOut + nA / 4][0] + StepFetureTime38;
StepRecordeState[FILTER_AXIS_NUM + nA / 4][0] = StepRecordeState[FILTER_AXIS_NUM + nA / 4][0] + 3;
StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][0] = StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][0] + StepFetureTime38;
}
if (StepRecordeState[AxisNumberFiltOut + nA / 4][3] <= 3)
if (StepRecordeState[FILTER_AXIS_NUM + nA / 4][3] <= 3)
{
StepRecordeState[AxisNumberFiltOut + nA / 4][1] = StepRecordeState[AxisNumberFiltOut + nA / 4][1] + StepRecordeState[AxisNumberFiltOut + nA / 4][3];
StepRecordeState[FILTER_AXIS_NUM + nA / 4][1] = StepRecordeState[FILTER_AXIS_NUM + nA / 4][1] + StepRecordeState[FILTER_AXIS_NUM + nA / 4][3];
}
else if ((StepRecordeStateTime[AxisNumberFiltOut + nA / 4][3] - StepFetureTime38 > StepMaxTime)
&& (StepRecordeState[AxisNumberFiltOut + nA / 4][3] > 11))
else if ((StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][3] - StepFetureTime38 > StepMaxTime)
&& (StepRecordeState[FILTER_AXIS_NUM + nA / 4][3] > 11))
{
StepRecordeState[AxisNumberFiltOut + nA / 4][1] = StepRecordeState[AxisNumberFiltOut + nA / 4][1] + 3;
StepRecordeState[FILTER_AXIS_NUM + nA / 4][1] = StepRecordeState[FILTER_AXIS_NUM + nA / 4][1] + 3;
}
else
{
if (StepRecordeStateTime[AxisNumberFiltOut + nA / 4][4] > 0)
if (StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][4] > 0)
{
nE = StepRecordeStateTime[AxisNumberFiltOut + nA / 4][3] * StepRecordeStateTime[AxisNumberFiltOut + nA / 4][4] / StepRecordeStateTime[AxisNumberFiltOut + nA / 4][5];
nE = StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][3] * StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][4] / StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][5];
}
if ((StepRecordeStateTime[AxisNumberFiltOut + nA / 4][4] > 0) && (nE < StepRecordeState[AxisNumberFiltOut + nA / 4][3]))
if ((StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][4] > 0) && (nE < StepRecordeState[FILTER_AXIS_NUM + nA / 4][3]))
{
if (nE > 4)
{
StepRecordeState[AxisNumberFiltOut + nA / 4][1] = StepRecordeState[AxisNumberFiltOut + nA / 4][1] + nE;
StepRecordeState[FILTER_AXIS_NUM + nA / 4][1] = StepRecordeState[FILTER_AXIS_NUM + nA / 4][1] + nE;
}
else
{
StepRecordeState[AxisNumberFiltOut + nA / 4][1] = StepRecordeState[AxisNumberFiltOut + nA / 4][1] + 3;
StepRecordeState[FILTER_AXIS_NUM + nA / 4][1] = StepRecordeState[FILTER_AXIS_NUM + nA / 4][1] + 3;
}
}
else
{
if (StepRecordeState[AxisNumberFiltOut + nA / 4][3] > 4)
if (StepRecordeState[FILTER_AXIS_NUM + nA / 4][3] > 4)
{
StepRecordeState[AxisNumberFiltOut + nA / 4][1] = StepRecordeState[AxisNumberFiltOut + nA / 4][1] + StepRecordeState[AxisNumberFiltOut + nA / 4][3];
StepRecordeState[FILTER_AXIS_NUM + nA / 4][1] = StepRecordeState[FILTER_AXIS_NUM + nA / 4][1] + StepRecordeState[FILTER_AXIS_NUM + nA / 4][3];
}
else
{
StepRecordeState[AxisNumberFiltOut + nA / 4][1] = StepRecordeState[AxisNumberFiltOut + nA / 4][1] + 3;
StepRecordeState[FILTER_AXIS_NUM + nA / 4][1] = StepRecordeState[FILTER_AXIS_NUM + nA / 4][1] + 3;
}
}
}
StepRecordeStateTime[AxisNumberFiltOut + nA / 4][1] = StepRecordeStateTime[AxisNumberFiltOut + nA / 4][1] + StepRecordeStateTime[AxisNumberFiltOut + nA / 4][3];
StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][1] = StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][1] + StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][3];
}
StepRecordeState[AxisNumberFiltOut + nA / 4][2] = 0;
StepRecordeStateTime[AxisNumberFiltOut + nA / 4][2] = 0;
StepRecordeState[AxisNumberFiltOut + nA / 4][3] = 0;
StepRecordeStateTime[AxisNumberFiltOut + nA / 4][3] = 0;
StepRecordeState[FILTER_AXIS_NUM + nA / 4][2] = 0;
StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][2] = 0;
StepRecordeState[FILTER_AXIS_NUM + nA / 4][3] = 0;
StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][3] = 0;
}
else if ((StepRecordeState[AxisNumberFiltOut + nA / 4][0] > 0) && ((StepRecordeStateTime[AxisNumberFiltOut + nA / 4][2] >= StepMaxTime * 2) || (StepFetureAmp18 < 4 * thred) || (StateDetectLcvar[2] > SampleFrequency)))
else if ((StepRecordeState[FILTER_AXIS_NUM + nA / 4][0] > 0) && ((StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][2] >= StepMaxTime * 2) || (StepFetureAmp18 < 4 * thred) || (StateDetectLcVar[2] > PEDOMETER_FREQ)))
{
nB = AxisNumberStepSaveState - 1;
if (nD > 0)
@ -704,15 +639,15 @@ static void Steps_Rcording(unsigned long long timeStamp)
}
else
{
for (nC = (AxisNumberStepSaveState - 1); nC >= AxisNumber; nC--)
for (nC = (AxisNumberStepSaveState - 1); nC >= AXIS_NUM; nC--)
{
if ((StepRecordeStateTime[nB][0] < StepRecordeStateTime[nC][0]) && (nC != AxisNumberFiltOut))
if ((StepRecordeStateTime[nB][0] < StepRecordeStateTime[nC][0]) && (nC != FILTER_AXIS_NUM))
{
nB = nC;
}
}
}
if ((nB == AxisNumberFiltOut + nA / 4) && (StepRecordeState[nB][0] >= 8))
if ((nB == FILTER_AXIS_NUM + nA / 4) && (StepRecordeState[nB][0] >= 8))
{
if (Steps.walkRealTime > StepRecordeState[nB][1])
{
@ -732,7 +667,7 @@ static void Steps_Rcording(unsigned long long timeStamp)
//#endif
for (nC = 0; nC < AxisNumberStepSaveState; nC++)
{
if ((StepFetureAmp18 < 4 * thred) || (StateDetectLcvar[2] > SampleFrequency))
if ((StepFetureAmp18 < 4 * thred) || (StateDetectLcVar[2] > PEDOMETER_FREQ))
{
StepRecordeState[nC][1] = 0;
StepRecordeStateTime[nC][1] = 0;
@ -773,17 +708,17 @@ static void Steps_Rcording(unsigned long long timeStamp)
}
}
}
StepRecordeState[AxisNumberFiltOut + nA / 4][0] = 0;
StepRecordeStateTime[AxisNumberFiltOut + nA / 4][0] = 0;
StepRecordeState[AxisNumberFiltOut + nA / 4][1] = 0;
StepRecordeStateTime[AxisNumberFiltOut + nA / 4][1] = 0;
StepRecordeState[AxisNumberFiltOut + nA / 4][3] = 0;
StepRecordeStateTime[AxisNumberFiltOut + nA / 4][3] = 0;
StepRecordeStateTime[AxisNumberFiltOut + nA / 4][4] = 0;
StepRecordeStateTime[AxisNumberFiltOut + nA / 4][5] = 0;
StepRecordeStateTime[AxisNumberFiltOut + nA / 4][7] = 0;
StepRecordeStateTime[AxisNumberFiltOut + nA / 4][8] = 0;
timeStampSave[AxisNumberFiltOut + nA / 4][0] = 0;
StepRecordeState[FILTER_AXIS_NUM + nA / 4][0] = 0;
StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][0] = 0;
StepRecordeState[FILTER_AXIS_NUM + nA / 4][1] = 0;
StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][1] = 0;
StepRecordeState[FILTER_AXIS_NUM + nA / 4][3] = 0;
StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][3] = 0;
StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][4] = 0;
StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][5] = 0;
StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][7] = 0;
StepRecordeStateTime[FILTER_AXIS_NUM + nA / 4][8] = 0;
timeStampSave[FILTER_AXIS_NUM + nA / 4][0] = 0;
}
}
@ -802,11 +737,11 @@ static void Steps_Rcording(unsigned long long timeStamp)
if ((StepFetureTime58 >= StepMaxTime)
|| ((nD != 0) && (nD < 0.7l * StepFetureTime18 / 4.0l)))
{
StepRecordeStateTime[nA][8] = SampleFrequency * 8.0 / StepFetureTime18;
StepRecordeStateTime[nA][8] = PEDOMETER_FREQ * 8.0 / StepFetureTime18;
}
else
{
StepRecordeStateTime[nA][8] = SampleFrequency * 4.0 / StepFetureTime18;
StepRecordeStateTime[nA][8] = PEDOMETER_FREQ * 4.0 / StepFetureTime18;
}
timeStampSave[nA][1] = timeStamp;
if (StepRecordeState[nA][0] == 0)
@ -823,7 +758,7 @@ static void Steps_Rcording(unsigned long long timeStamp)
StepRecordeState[nA][1] = StepRecordeState[nA][1] + 4;
}
StepRecordeStateTime[nA][1] = StepRecordeStateTime[nA][1] + StepFetureTime18;
timeStampSave[nA][0] = timeStamp - (unsigned long)(StepFetureTime18 * 1000 / SampleFrequency);
timeStampSave[nA][0] = timeStamp - (unsigned long)(StepFetureTime18 * 1000 / PEDOMETER_FREQ);
}
else
{
@ -951,7 +886,7 @@ static void Steps_Rcording(unsigned long long timeStamp)
StepRecordeState[nA][3] = 0;
StepRecordeStateTime[nA][3] = 0;
}
else if ((StepRecordeState[nA][0] > 0) && ((StepRecordeStateTime[nA][2] >= StepMaxTime * 2) || (StepFetureAmp18 < 4 * thred) || (StateDetectLcvar[2] > SampleFrequency)))
else if ((StepRecordeState[nA][0] > 0) && ((StepRecordeStateTime[nA][2] >= StepMaxTime * 2) || (StepFetureAmp18 < 4 * thred) || (StateDetectLcVar[2] > PEDOMETER_FREQ)))
{
nB = AxisNumberStepSaveState - 1;
if (nD > 0)
@ -966,9 +901,9 @@ static void Steps_Rcording(unsigned long long timeStamp)
}
else
{
for (nC = (AxisNumberStepSaveState - 1); nC >= AxisNumber; nC--)
for (nC = (AxisNumberStepSaveState - 1); nC >= AXIS_NUM; nC--)
{
if ((StepRecordeStateTime[nB][0] < StepRecordeStateTime[nC][0]) && (nC != AxisNumberFiltOut))
if ((StepRecordeStateTime[nB][0] < StepRecordeStateTime[nC][0]) && (nC != FILTER_AXIS_NUM))
{
nB = nC;
}
@ -986,14 +921,10 @@ static void Steps_Rcording(unsigned long long timeStamp)
}
Steps.walkRealTime = 0;
ReSteps.walkSteps = (unsigned long)(Steps.walk);
//#if defined(PLATFORM_PC_WINDOWS) || defined(PLATFORM_PC_LINUX)
// steps_back(ReSteps);
//#elif defined(PLATFORM_ANDROID_QCOM_AP) || defined(PLATFORM_ANDROID_QCOM_ADSP)
// AutoDisplayStep_Event_Handler(ReSteps);
//#endif
for (nC = 0; nC < AxisNumberStepSaveState; nC++)
{
if ((StepFetureAmp18 < 4 * thred) || (StateDetectLcvar[2] > SampleFrequency))
if ((StepFetureAmp18 < 4 * thred) || (StateDetectLcVar[2] > PEDOMETER_FREQ))
{
StepRecordeState[nC][1] = 0;
StepRecordeStateTime[nC][1] = 0;
@ -1204,119 +1135,114 @@ static void State_Detect(unsigned long long timeStamp)
double SumAccYZ = 0;
double AccX = 0;
double AccYZ = 0;
/*double Mean_x = 0, Mean_y = 0, Mean_z = 0;*/
/*double DeDC_x = 0, DeDC_y = 0, DeDC_z = 0, DeDC_xyz = 0;*/
#if defined(PLATFORM_ANDROID_QCOM_SLPI845)
(void)timeStamp;
#endif
if (StateDetectLcvar[0] < StepMinTime)
if (StateDetectLcVar[0] < StepMinTime)
{
StateDetectLcvar[0] = StateDetectLcvar[0] + 1;
if (StateDetectLcvar[0] < 0.5l)
StateDetectLcVar[0] = StateDetectLcVar[0] + 1;
if (StateDetectLcVar[0] < 0.5l)
{
SumAcc = -1;
}
else
{
}else{
SumAcc = SumAcc - 1;
}
}
else
{
SumAcc = 0;
for (nA = 0; nA < (AccelerationNumber - 1); nA++)
for (nA = 0; nA < (ACC_BUFF_NUM - 1); nA++)
{
SumAcc += fabs(stepsFiltAcc[3][nA] - stepsFiltAcc[3][nA + 1]);
SumAccX += fabs(stepsFiltAcc[0][nA] - stepsFiltAcc[0][nA + 1]);
SumAccYZ += fabs(sqrt(stepsFiltAcc[1][nA] * stepsFiltAcc[1][nA] + stepsFiltAcc[2][nA] * stepsFiltAcc[2][nA])
- sqrt(stepsFiltAcc[1][nA + 1] * stepsFiltAcc[1][nA + 1] + stepsFiltAcc[2][nA + 1] * stepsFiltAcc[2][nA + 1]));
SumAcc += fabs(AccBuffer[3][nA] - AccBuffer[3][nA + 1]);
SumAccX += fabs(AccBuffer[0][nA] - AccBuffer[0][nA + 1]);
SumAccYZ += fabs(sqrt(AccBuffer[1][nA] * AccBuffer[1][nA] + AccBuffer[2][nA] * AccBuffer[2][nA])
- sqrt(AccBuffer[1][nA + 1] * AccBuffer[1][nA + 1] + AccBuffer[2][nA + 1] * AccBuffer[2][nA + 1]));
}
SumAcc /= (AccelerationNumber - 1);
SumAccX /= (AccelerationNumber - 1);
SumAccYZ /= (AccelerationNumber - 1);
for (nA = 0; nA < AccelerationNumber; nA++)
{
AccX += fabs(stepsFiltAcc[0][nA]);
}
AccX = AccX / AccelerationNumber;
SumAcc /= (ACC_BUFF_NUM - 1);
SumAccX /= (ACC_BUFF_NUM - 1);
SumAccYZ /= (ACC_BUFF_NUM - 1);
for (nA = 0; nA < AccelerationNumber; nA++)
{
AccYZ += sqrt(stepsFiltAcc[1][nA] * stepsFiltAcc[1][nA] + stepsFiltAcc[2][nA] * stepsFiltAcc[2][nA]);
for (nA = 0; nA < ACC_BUFF_NUM; nA++){
AccX += fabs(AccBuffer[0][nA]);
}
AccYZ /= AccelerationNumber;
AccX = AccX / ACC_BUFF_NUM;
for (nA = 0; nA < ACC_BUFF_NUM; nA++)
{
AccYZ += sqrt(AccBuffer[1][nA] * AccBuffer[1][nA] + AccBuffer[2][nA] * AccBuffer[2][nA]);
}
AccYZ /= ACC_BUFF_NUM;
if (SumAcc > 3 || SumAcc < 0.002l)
{
if (StateDetectLcvar[2] < SampleFrequencyFour)
if (StateDetectLcVar[2] < SampleFrequencyFour)
{
StateDetectLcvar[2] = StateDetectLcvar[2] + StepMinTime;
StateDetectLcVar[2] = StateDetectLcVar[2] + StepMinTime;
}
StateDetectLcvar[3] = 0;
StateDetectLcVar[3] = 0;
}
else
{
if (StateDetectLcvar[3] < SampleFrequencyFour)
if (StateDetectLcVar[3] < SampleFrequencyFour)
{
StateDetectLcvar[3] = StateDetectLcvar[3] + StepMinTime;
StateDetectLcVar[3] = StateDetectLcVar[3] + StepMinTime;
}
StateDetectLcvar[2] = 0;
StateDetectLcVar[2] = 0;
}
if (StateDetectLcvar[2] > SampleFrequencydouble)
if (StateDetectLcVar[2] > SampleFrequencydouble)
{
StateDetectLcvar[4] = 1;
StateDetectLcVar[4] = 1;
}
else if (StateDetectLcvar[2] > SampleFrequencyOPF)
else if (StateDetectLcVar[2] > SampleFrequencyOPF)
{
STEPLIB_MEMSET(StepReFeature, 1, sizeof(StepReFeature));
}
if (StateDetectLcvar[3] > StepMinTime)
if (StateDetectLcVar[3] > StepMinTime)
{
StateDetectLcvar[4] = 0;
StateDetectLcVar[4] = 0;
}
if (((AccX * 1.3l > AccYZ) || (SumAccX * 1.3l > SumAccYZ)) && (SumAcc < 0.8l))
{
if (StateDetectLcvar[1] > 0)
if (StateDetectLcVar[1] > 0)
{
StateDetectLcvar[1] = StateDetectLcvar[1] - 1;
StateDetectLcVar[1] = StateDetectLcVar[1] - 1;
}else{
StateDetectLcvar[1] = 0;
StateDetectLcVar[1] = 0;
}
}
else
{
if ((StateDetectLcvar[1] > 4) || (SumAcc > 0.6l))
if ((StateDetectLcVar[1] > 4) || (SumAcc > 0.6l))
{
StateDetectLcvar[1] = 8;//10
StateDetectLcVar[1] = 8;//10
}
else
{
if ((AccX < AccYZ) && (SumAcc > 0.25l))
{
if (StateDetectLcvar[1] < 8)//10
if (StateDetectLcVar[1] < 8)//10
{
StateDetectLcvar[1] = StateDetectLcvar[1] + 1;
StateDetectLcVar[1] = StateDetectLcVar[1] + 1;
}
}
else
{
StateDetectLcvar[1] = 0;
StateDetectLcVar[1] = 0;
}
}
}
if (StateDetectLcvar[1] > 4){
if (StateDetectLcVar[1] > 4){
stateLcVar[0] = 2;
}else{
stateLcVar[0] = walk;
}
StateDetectLcvar[0] = 0;
StateDetectLcVar[0] = 0;
}
}
void Steps_State_Detect(enumState* state){
void Pedometer_GetState(StepState_t* state){
*state = stateLcVar[0];
}

View File

@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30804.86
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PDR", "project\PDR.vcxproj", "{28D32532-309F-40EA-9E4A-2D162CC434D2}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{28D32532-309F-40EA-9E4A-2D162CC434D2}.Debug|x64.ActiveCfg = Debug|x64
{28D32532-309F-40EA-9E4A-2D162CC434D2}.Debug|x64.Build.0 = Debug|x64
{28D32532-309F-40EA-9E4A-2D162CC434D2}.Debug|x86.ActiveCfg = Debug|Win32
{28D32532-309F-40EA-9E4A-2D162CC434D2}.Debug|x86.Build.0 = Debug|Win32
{28D32532-309F-40EA-9E4A-2D162CC434D2}.Release|x64.ActiveCfg = Release|x64
{28D32532-309F-40EA-9E4A-2D162CC434D2}.Release|x64.Build.0 = Release|x64
{28D32532-309F-40EA-9E4A-2D162CC434D2}.Release|x86.ActiveCfg = Release|Win32
{28D32532-309F-40EA-9E4A-2D162CC434D2}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {B6378B77-5AB0-4A12-ACE8-2B45F292D7EE}
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,48 @@
#ifndef _PDR_AHRS_H_
#define _PDR_AHRS_H_
#ifdef __cplusplus
extern "C" {
#endif
/* Header File Including ------------------------------------------------------------------------ */
#include "pdr_sensor.h"
/* Macro Declaration ---------------------------------------------------------------------------- */
#define AHRS_SAMPLE_FREQ 100 // ARHS算法的传感器采样频率
#define IMU_SAMPLING_FREQUENCY 100
#define AHRS_KP 0.500
#define AHRS_TYPE_GYRO 4
#define AHRS_TYPE_ACCE 1
#define AHRS_TYPE_MAGN 2
#define AHRS_STATUS_RESET_PHASE_0 0x80
#define AHRS_STATUS_RESET_PHASE_1 0x40
#define AHRS_STATUS_RESET (AHRS_STATUS_RESET_PHASE_0|AHRS_STATUS_RESET_PHASE_1)
#define AHRS_STATUS_STABLE 0x20
/* Struct Declaration --------------------------------------------------------------------------- */
/* Function Declaration ------------------------------------------------------------------------- */
void AHRS_Init(void);
void ResetARHS(void);
/**---------------------------------------------------------------------
* Function : fv3Norm
* Description :
* Date : 2021/01/26 yuanlin@vivocom &&
*
*
*---------------------------------------------------------------------**/
void fv3Norm(float* vx, float* vy, float* vz);
int UpdateAHRS(IMU_t* imu);
#ifdef __cplusplus
}
#endif
#endif // for __AHRS_H

View File

@ -0,0 +1,18 @@
#ifndef __PDR_FFT_H__
#define __PDR_FFT_H__
/* Header File Including ------------------------------------------------------------------------ */
#include <stdint.h>
#include <math.h>
#include "Complex.h"
/* Macro Declaration ---------------------------------------------------------------------------- */
#define M_PI 3.14159265358979323846 /* pi */
/* Structure Declaration ------------------------------------------------------------------------ */
/* Function Declaration ------------------------------------------------------------------------- */
extern int FFT_Dft(Complex_t *fft, float *signal, int length);
extern int FFT_Fft(Complex_t *fft, float *signal, int length);
#endif

View File

@ -0,0 +1,52 @@
/******************** (C) COPYRIGHT 2022 Geek************************************
* File Name : Filter.c
* Current Version : V2.0
* Author : logzhan
* Date of Issued : 2022.10.15
* Comments : PDR
********************************************************************************/
/* Header File Including ------------------------------------------------------*/
#ifndef __FILTER_H__
#define __FILTER_H__
/* Macro Declaration ----------------------------------------------------------*/
#define FILTER_MAX_LENGTH 71
/* Structure Declaration ------------------------------------------------------*/
typedef struct Filter_t { // iir or fir filter
int reset; // reset flag
int order; // coefficient array length, not filter order
double H0; // dc signal gain
double b[FILTER_MAX_LENGTH]; // b coefficient
double a[FILTER_MAX_LENGTH]; // a coefficient
double yout[FILTER_MAX_LENGTH]; // yout buffer
double xin[FILTER_MAX_LENGTH]; // xin buffer
} Filter_t;
/* Function Declaration -------------------------------------------------------*/
/**---------------------------------------------------------------------
* Function : FilterReset
* Description :
* Date : 2022/10/15 logzhan
*---------------------------------------------------------------------**/
void FilterReset(Filter_t *f);
/**---------------------------------------------------------------------
* Function : FilterSetCoef
* Description :
* Input : order coefficient array length, not filter order
* *b b coefficient
* *a a coefficient
* H0 dc signal gain
* Date : 2022/10/15 logzhan
*---------------------------------------------------------------------**/
void FilterSetCoef(Filter_t *f, int order, double *b, double *a, double H0);
/**---------------------------------------------------------------------
* Function : FilterFilter
* Description :
* Date : 2022/10/15 logzhan
*---------------------------------------------------------------------**/
double FilterFilter(Filter_t *f, double x);
#endif

View File

@ -0,0 +1,54 @@
/******************** (C) COPYRIGHT 2020 Geek************************************
* File Name : pdr_kalman.h
* Department : Sensor Algorithm Team
* Current Version : V2.0(compare QCOM SAP 5.0)
* Author : logzhan
* Date of Issued : 2020.7.3
* Comments : PDR
********************************************************************************/
#ifndef _PDR_KALMAN_H_
#define _PDR_KALMAN_H_
#ifdef __cplusplus
extern "C" {
#endif
/**----------------------------------------------------------------------
* Function : EKF_Init
* Description :
* Date : 2022/09/19
*---------------------------------------------------------------------**/
void EKF_Init(void);
/**----------------------------------------------------------------------
* Function : EKFStatePredict
* Description : pdr
* Date : 2022/09/19 logzhan
*---------------------------------------------------------------------**/
void EKFStatePredict(EKFPara_t* kf, double step_length, PDR_t* g_pdr, int step);
/**----------------------------------------------------------------------
* Function : EKFCalQRMatrix
* Description :
* scane_type,
* nmea_dataNMEA
* g_pdrPDR
* sys
* kfEKF
* Date : 2022/09/19 logzhan
*---------------------------------------------------------------------**/
void EKFCalQRMatrix(Nmea_t* nmea_data, PDR_t* g_pdr, Classifer_t* sys, EKFPara_t* kf);
/**----------------------------------------------------------------------
* Function : pdr_ekfStateUpdate
* Description : pdr
* Date : 2020/7/22 logzhan
*---------------------------------------------------------------------**/
void EKFStateUpdate(EKFPara_t* kf, GNSS_t* pgnss, Classifer_t* sys, PDR_t* g_pdr,
int scene_type);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,66 @@
/******************** (C) COPYRIGHT 2020 Geek************************************
* File Name : pdr_linearFit.h
* Department : Sensor Algorithm Team
* Current Version : V2.0(compare QCOM SAP 5.0)
* Author :
logzhan
* Date of Issued : 2020.7.4
* Comments : PDR 线
********************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
#ifndef _PDR_LINEAR_FIT_H_
#define _PDR_LINEAR_FIT_H_
/**----------------------------------------------------------------------
* Function : pdr_linearLeastSquaresFitting
* Description : 线 Y = c0 + c1 x
sum| nDataY - (a*nDataX+b)|^2
* Date : 2020/7/4 logzhan
*---------------------------------------------------------------------**/
int linearLeastSquaresFit(const double *nDataX, const double *nDataY,
const int nLength, double *a, double *b);
/**************************************************************************
* Description : 线ax+by+c=0, 线
* Input : x yXY
num,
* Output : para 线, para[0]:a, para[0]:b, para[0]:c
**************************************************************************/
int leastDistanceLinearFit(double x[], double y[], int num, double para[]);
/**----------------------------------------------------------------------
* Function : gsl_fit_linear
* Description : Fit the data (x_i, y_i) to the linear relationship
Y = c0 + c1 x
returning,
c0, c1 -- coefficients
cov00, cov01, cov11 -- variance-covariance matrix of
c0 and c1,
sumsq -- sum of squares of residuals
This fit can be used in the case where the errors for
the data are uknown, but assumed equal for all points.
The resulting variance-covariance matrix estimates the
error in the coefficientsfrom the observed variance of
the points around the best fit line.
* Date :
*---------------------------------------------------------------------**/
static int gslFitLinear(const double* x, const size_t xstride,
const double* y, const size_t ystride,
const size_t n,
double* c0, double* c1,
double* cov_00, double* cov_01, double* cov_11, double* sumsq);
#endif // !_LINEAR_FITTING_H_
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,139 @@
#ifndef __PDR_LOCATION_H__
#define __PDR_LOCATION_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "PDRBase.h"
#define HIST_GPS_NUM 8
#define ACCURACY_THRES 0.6f // 精度阈值
#define YAW_THRES 10.0f // Yaw角范围阈值
/**---------------------------------------------------------------------
* Function : NavSys_Init
* Description : PDR
* Date : 2022/9/16
*---------------------------------------------------------------------**/
void PDR_Init(void);
void PDRInfoInit(void);
/**---------------------------------------------------------------------
* Function : InsLocation
* Description : PDR
* Date : 2022/09/16 logzhan
*---------------------------------------------------------------------**/
int InsLocationUpdate(IMU_t *ss_data, EKFPara_t *kf);
/**----------------------------------------------------------------------
* Function : pdr_noGpsPredict
* Description : gpsGPS10
* Date : 2020/07/08 logzhan
*---------------------------------------------------------------------**/
void NoGnssInfoPredict(EKFPara_t* kf, LctFs_t* result, PDR_t* g_pdr);
/**----------------------------------------------------------------------
* Function : Nmea2Gnss
* Description : nmeagnss
* Date : 2020/07/08 logzhan
*---------------------------------------------------------------------**/
void Nmea2Gnss(Nmea_t* nmea_data, GNSS_t* pgnss);
/**----------------------------------------------------------------------
* Function : pdr_detectFixMode
* Description : PDR,
* GPS
* Date : 2020/07/08 logzhan
* 2020/02/08 logzhan : -1INVAILD_GPS_YAW
*
*---------------------------------------------------------------------**/
int DetectFixMode(GNSS_t* pgnss, EKFPara_t* kf, PDR_t* g_pdr, LctFs_t* result);
/**----------------------------------------------------------------------
* Function : GnssCalHeading
* Description : GPS(0 - 360°)
* Date : 2022/09/16 logzhan
*
*---------------------------------------------------------------------**/
double GnssCalHeading(GNSS_t* pgnss);
/**----------------------------------------------------------------------
* Function : calPdrHeadingOffset
* Description : GPS
* Date : 2020/07/08 logzhan
*---------------------------------------------------------------------**/
void CalPdrHeadingOffset(Nmea_t* nmea_data, PDR_t* p_pdr);
/**---------------------------------------------------------------------
* Function : pdr_resetSysStatus
* Description : PDS
* Date : 2020/2/1 logzhan
*---------------------------------------------------------------------**/
void ResetSystemStatus(EKFPara_t* kf);
/**----------------------------------------------------------------------
* Function : pdr_gnssInsLocation
* Description : PDR GPSINS
* Date : 2021/01/29 logzhan
*---------------------------------------------------------------------**/
int GnssInsFusionLocation(Nmea_t* nmea_data, EKFPara_t* kf, LctFs_t* result);
/**---------------------------------------------------------------------
* Function : pdr_initGnssInfo
* Description : PDS GNSS
* Date : 2020/2/1 logzhan
*---------------------------------------------------------------------**/
void InitGnssInfo(void);
/**----------------------------------------------------------------------
* Function : GnssUpdate
* Description : nmeagnss
* Date : 2020/07/08 logzhan
* 2020/02/09 logzhan : pdr_gpsUpdate
* GPSgnssnmea
*
*---------------------------------------------------------------------**/
void GnssUpdate(GNSS_t* gps, Nmea_t* nmea);
/**----------------------------------------------------------------------
* Function : OutputRawGnssPos
* Description : GPS
* Date : 2022/10/15 logzhan
*---------------------------------------------------------------------**/
void OutputRawGnssPos(GNSS_t* pgnss, LctFs_t* result);
/**----------------------------------------------------------------------
* Function : ResetOutputLoction
* Description : 1
* 2GPSresult
* Date : 2022/09/19 logzhan
*---------------------------------------------------------------------**/
int ResetOutputLoction(GNSS_t* pgnss, PDR_t* g_pdr, EKFPara_t* kf, LctFs_t* result);
/**----------------------------------------------------------------------
* Function : EkfGnssInsLocFusion
* Description : EKFGNSSINS
* Date : 2022/09/21 logzhan
*---------------------------------------------------------------------**/
void EkfGnssInsLocFusion(GNSS_t* pgnss, PDR_t* g_pdr, Classifer_t* sys, double yaw_bias,
EKFPara_t* kf, LctFs_t* res);
/**----------------------------------------------------------------------
* Function : PDRInitialAlignment
* Description : PDR
* Date : 2022/09/19 logzhan
*---------------------------------------------------------------------**/
int GnssInsInitialAlignment(GNSS_t* pgnss, EKFPara_t* kf, PDR_t* g_pdr, LctFs_t* result);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,43 @@
#pragma once
#ifndef _LOCATION_TOOL_H_
#define _LOCATION_TOOL_H_
#include <stddef.h>
#ifndef PI
//#define PI 3.14159265358979323846
#endif // !PI
#ifndef EARTH_RADIUS
#define EARTH_RADIUS 6371008.8
#endif
typedef struct DoublePair {
double x;
double y;
} DoublePair;
typedef DoublePair PlaneCoordinate;
typedef struct LatLng{
double lat;
double lon;
} LatLng_t;
typedef struct DoublePairList{
double *x;
double *y;
size_t length;
} DoublePairList;
typedef struct LocationList{
double *lat;
double *lon;
size_t length;
} LocationList;
LatLng ProjPointOfLatLng(LatLng point, LatLng linePointA, LatLng linePointB);
DoublePair ProjPoint(DoublePair point, DoublePair linePointA, DoublePair linePointB);
//PlaneCoordinate WGS84_XYZ(const LatLng lla);
double CalculateDistance(LatLng pointA, LatLng pointB);
#endif // !_LOCATION_TOOL_H_

View File

@ -0,0 +1,85 @@
/******************** (C) COPYRIGHT 2020 Geek************************************
* File Name : pdr_main.h
* Department : Sensor Algorithm Team
* Current Version : V2.0
* Author :
& yuanlin@vivo.cm
* Date of Issued : 2020.7.18
* Comments : PDR
********************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
#ifndef _PDR_MAIN_H_
#define _PDR_MAIN_H_
#include <string>
using namespace std;
#define PATH_MAX 256
#define TRACK_MAX 100000
typedef struct LatLngd {
double lat;
double lon;
double heading;
double hdop;
double accuracy;
double vel;
double time;
int motionType;
} LatLngd;
typedef struct ResultTracks {
LatLngd gpsTrack[TRACK_MAX];
LatLngd pdrTrack[TRACK_MAX];
int gpsLen;
int pdrLen;
}ResultTracks;
/**----------------------------------------------------------------------
* Function : pdr_writeKml
* Description : pdrgpspdrkml
* path : kml
* name : kml
* postfix
* Date : 2020/11/1 logzhan
*---------------------------------------------------------------------**/
void KmlWrite(string path, string name, string postfix);
/**----------------------------------------------------------------------
* Function : getSimulateFileFp
* Description : 仿
* Date : 2021/01/25 logzhan
*---------------------------------------------------------------------**/
FILE* getSimulateFile(FILE* catalogFp, string path_file, string& fileHead);
/**----------------------------------------------------------------------
* Function : gpsYaw2GoogleYaw
* Description : kml0-360Yaw
* Yaw
* Date : 2021/01/25 logzhan
*---------------------------------------------------------------------**/
double gpsYaw2GoogleYaw(double heading);
/**----------------------------------------------------------------------
* Function : Motion2TypeStr
* Description :
* Date : 2022/9/16 logzhan
*---------------------------------------------------------------------**/
const char* Motion2TypeStr(int type);
/**----------------------------------------------------------------------
* Function : updateResTrack
* Description : GPSPDR
* Date : 2021/01/25 logzhan
*---------------------------------------------------------------------**/
void UpdateResTrack(ResultTracks& resTrack, LctFs_t& lctfs);
#endif
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,70 @@
#ifdef __cplusplus
extern "C" {
#endif
#ifndef _PDR_MATRIX_H_
#define _PDR_MATRIX_H_
#define N 4
/**---------------------------------------------------------------------
* Function : MatrixTrans
* Description :
* Date : 2022/09/14 logzhan
*---------------------------------------------------------------------**/
void MatrixTrans(double a[N][N], double r[N][N]);
/**---------------------------------------------------------------------
* Function : VecMatMultiply
* Description : r = b * a
* Date : 2022/09/14 logzhan
*---------------------------------------------------------------------**/
void VecMatMultiply(double a[N], double b[N][N], double r[N]);
/**---------------------------------------------------------------------
* Function : MatrixMultiply
* Description : r = a * b
* Date : 2022/09/14 logzhan
*---------------------------------------------------------------------**/
void MatrixMultiply(double a[N][N], double b[N][N], double r[N][N]);
/**---------------------------------------------------------------------
* Function : MatrixAdd
* Description : r = a + b, a = a + b
* Date : 2022/09/14 logzhan
*---------------------------------------------------------------------**/
void MatrixAdd(double a[N][N], double b[N][N], double r[N][N]);
/**---------------------------------------------------------------------
* Function : VectorAdd
* Description : r = a + b, a = a + b
* Date : 2022/09/14 logzhan
*---------------------------------------------------------------------**/
void VectorAdd(double a[N], double b[N], double r[N]);
/**---------------------------------------------------------------------
* Function : MatrixSub
* Description : r = a - b, a = a - b
* Date : 2022/09/14 logzhan
*---------------------------------------------------------------------**/
void MatrixSub(double a[N][N], double b[N][N], double r[N][N]);
/**---------------------------------------------------------------------
* Function : VectorSub
* Description : r = a - b, a = a - b
* Date : 2022/09/14 logzhan
*---------------------------------------------------------------------**/
void VectorSub(double a[N], double b[N], double r[N]);
/**---------------------------------------------------------------------
* Function : MatrixInverse
* Description :
* Date : 2022/09/14 logzhan
*---------------------------------------------------------------------**/
void MatrixInverse(double(*a)[N], double(*a_inv)[N]);
#endif
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,232 @@
/******************** (C) COPYRIGHT 2021 Geek************************************
* File Name : pdr_base.h
* Department : Sensor Algorithm Team
* Current Version : V2.0
* Author : yuanlin@vivocom &
*
*
* Date of Issued : 2021.02.01
* Comments : PDR
********************************************************************************/
#ifndef _PDR_BASE_H_
#define _PDR_BASE_H_
/* Header File Including -----------------------------------------------------*/
#include "stdint.h"
#include "pdr_sensor.h"
/* PDR SYS CFG ---------------------------------------------------------------*/
#define PDR_OUTPUT_SMOOTH 0 // 是否开启轨迹平滑
/* Macro Definition ----------------------------------------------------------*/
#define PCA_NUM 200
#define ACCURACY_ERR_MAX 1000 // GPS的accuracy最大值,一般用于初始化用
#define N 4 // 矩阵维数
#define OPEN_SKY 1
#define MAX_NO_GPS_PREDICT 10 // 无GPS信息状态最大位置推算数量
#define UN_UPDATE 0 // 非更新状态
#define DATA_UPDATE 1 // 数据更新
#define ON 1
#define OFF 0
#define PDR_TRUE 1
#define PDR_FALSE 0
#define TYPE_FIX_NONE 0 // PDR修正结果为不输出
#define TYPE_FIX_GPS 2 // PDR修正结果为输出原始GPS
#define TYPE_FIX_PDR 1 // PDR修正结果为PDR融合
// PDR携带方式
#define UNKNOWN 0
#define FORWARD_UP_RIGHT 1 // 臂包右臂头朝上屏朝外or左臂头朝上屏朝内
#define BACKWARD_UP_LEFT 2 // 臂包左臂头朝上屏朝外or右臂头朝上屏朝内
#define BACKWARD_DOWN_RIGHT 3 // 臂包右臂头朝下屏朝外or左臂头朝下屏朝内
#define FORWARD_DOWN_LEFT 4 // 臂包左臂头朝下屏朝外or右臂头朝下屏朝内
#define LEFT_UP_FORWARD 5 // 裤兜:头朝上,屏朝前
#define RIGHT_UP_BACKWARD 6 // 裤兜:头朝上,屏朝后
#define RIGHT_DOWN_FORWARD 7 // 裤兜:头朝下,屏朝前
#define LEFT_DOWN_BACKWARD 8 // 裤兜:头朝下,屏朝后
// PDR相关状态
#define PDR_NO_ERROR 0
#define PDR_OUT_OF_MEMORY 1
#define PDR_MOTION_TYPE_STATIC 0
#define PDR_MOTION_TYPE_IRREGULAR 1
#define PDR_MOTION_TYPE_HANDHELD 2
#define PDR_MOTION_TYPE_SWINGING 3
#define PDR_STATUS_RESET 0x80
#define PDR_STATUS_CACULATING_AXIS_CEOFFICIENT 0x40
#define PDR_STATUS_PCA_STABLE 0x20
#define PDR_STATUS_BIAS_STABLE 0x10
#define PDR_STATUS_STABLE (PDR_STATUS_PCA_STABLE | PDR_STATUS_BIAS_STABLE)
// 地球相关常数
#define WGS84_RE 6378137 // WGS-84椭球体长半轴
#define WGS84_ECCENTR2 6.69437999014e-3 // 第一偏向率的平方e^2(WGS-84)
#define WGS84_OMEGA_E_DOT 7.2921151467e-5 // 地球自转角速度 rad/sec
#define WGS84_GRAVITY 9.7803267714 // 地球平均重力加速度 m/s^2
#define DEG_PER_RADIAN 57.295779513082323 // degrees per radian
#define RADIAN_PER_DEG 0.017453292519943 // radians per degree
#define GPS_SPEED_UNIT 0.5144444 // GPS原始速度转m/s的缩放系数
#define PI 3.1415926
#define DOUBLE_ZERO 1e-10
#define TWO_PI (2.0*PI)
#define R2D(x) (x*57.2957795130823)
#define D2R(x) (x*3.14159265/180.0)
#define USE_BUG_FOR_LOCAL_PARA 1
#define BUF_DMT_1 1
#define BUF_DMT_2 2
#define PRINT_ALGO_RUN_TIME 0
#define PRINT_CLCT 1
#define PATTERN_RECOGNITION_LEN 256 // 缓存256 / SAMPLE_RATE的数量
#define OPEN_AREA 1 // 开阔区域(GPS信号较好)
#define UN_OPEN_AREA 0 // 非开阔区域(GPS信号较弱)
#define DETECTOR_RUN_FREQ 1280 // 用户运动类型检测器检测周期ms
#define DETECTOR_TYPE_STATIC 0 // 用户静止
#define DETECTOR_TYPE_IRREGULAR 1 // 无规律运动
#define DETECTOR_TYPE_HANDHELD 2 // 手持运动
#define DETECTOR_TYPE_SWINGING 3 // 摆手运动
#define ulong unsigned long
#define uchar unsigned char
typedef enum {
IS_INITIAL = 0,
IS_NORMAL = 1,
}pdrStatus;
typedef struct {
double Xk[N]; // 状态变量Xk xk[0]: 北向x xk[1]东向y xk[2]:步长 xk[3] :航向角
double pXk[N]; // 最佳预测变量Xk_predict xk[0]: 北向x xk[1]东向y xk[2]:步长 xk[3] :航向角
double Zk[N];
double pPk[N][N];
double Pk[N][N];
double Phi[N][N];
double hk[N][N];
double Q[N][N]; // 卡尔曼滤波的Q矩阵(过程噪声)
double R[N][N]; // 卡尔曼滤波R矩阵(观测噪声)
double Kk[N][N];
double Lambda;
double pLat;
double pLon;
double initHeading;
}EKFPara_t;
typedef struct{
int fnum;
int deltaStep;
float fsum;
float meanTime;
double lastTime;
}StepPredict;
typedef struct PDR {
uint32_t status; // PDR当前状态
uint32_t MotionType; // 用户运动类型
uint32_t NoGnssCount; // 没有GNSS信息次数
pdrStatus sysStatus; // PDR系统状态
int sceneType; // 场景类型1开阔区域0非开阔区域(信号较弱)
int fusionPdrFlg; // 融合PDR位置标志位, 当flg为0时纯输出GPS
double PllaInit[3]; // 初始plla坐标
double ts; // 时间戳
double x0; // 初始北向坐标
double y0; // 初始东向坐标
// 航向角相关
double heading; // PDR方向角
double lastHeading; // 上一次PDR方向角
double deltaHeading; // 偏航角变化量
double insHeadingOffset; // 惯导方向角偏移
double imuDeltaHeading; // 没间隔一次GPS信号PDR变化的角度用于区分转弯
double GpsHeading; // GPS航向角
double LastGpsHeading; // 上一次GPS航向角
double trackHeading; // GPS轨迹航向角
// 速度相关
double GpsSpeed; // GPS速度
// 步数相关
ulong steps; // 当前步数信息
ulong lastSteps; // 上一次的步数
ulong lastGpsSteps; // 上一次GPS步数
ulong deltaStepsPerGps; // 两次GPS更新之间步数的变化量
float motionFreq; // 运动频率
double gyroTime; // 陀螺仪时间
float axis_ceofficient[3];
float axis_direction[2];
float pca_direction[2];
float pcaAccuracy;
float bias_direction[2];
float biasAccuracy;
float cal_direction[2];
} PDR_t;
typedef struct {
int type;
float accBuffer[PATTERN_RECOGNITION_LEN];
}Classifer_t;
// 用户运动类型分类器
typedef struct DETECTOR {
uint32_t type; // 用户运动类别 0:静止运动 1无规律运动 2手持运动 3摆手运动
uint32_t lastType;
uint64_t tick; // 次数统计,用于调整检测器工作频率
}Detector_t;
/* Function Declaration ------------------------------------------------------*/
/**************************************************************************
* Description :
* Input : stepPredict
timestamp
steps_last
steps
**************************************************************************/
void calStepLastTime(StepPredict *stepPredict, double timestamp, unsigned long steps_last, unsigned long steps);
/**************************************************************************
* Description :
* Input : stepPredict
timestamp
steps_last
gnssVelgps
* Output : int
**************************************************************************/
int PredictStep(StepPredict *stepPredict, double timestamp, unsigned long steps_last, float gnssVel);
/**----------------------------------------------------------------------
* Function : stateRecognition
* Description : 1: 0:
* Date : 2020/7/22 logzhan
*---------------------------------------------------------------------**/
void StateRecognition(float *acc, Classifer_t *sys);
/**----------------------------------------------------------------------
* Function : InsLocationPredict
* Description : PDR
* Date : 2021/02/06 logzhan :
* PDR
*---------------------------------------------------------------------**/
void InsLocationPredict(PDR_t* pdr, StepPredict* stepPredict, IMU_t* imu,
GNSS_t* pgnss, EKFPara_t* kf);
/**************************************************************************
* Description : GPS
* Input : gpsPosGPSECEF
pgnssGPS
* Output : double
**************************************************************************/
double CalGnssTrackHeading(double gpsPos[][3], GNSS_t pgnss);
#endif
#pragma once

View File

@ -0,0 +1,110 @@
#ifdef __cplusplus
extern "C" {
#endif
#ifndef _PARSEDATA_H_
#define _PARSEDATA_H_
#include "pdr_sensor.h"
#define NAEA_LAST_TIME 500
#define IMU_LAST_COUNT 10
#define FLOAT_TO_INT 1000000
/**************************************************************************
* Description : NMEA
* : NMEARMC,GGA,GSA,GSV,
**************************************************************************/
char * strtok_ct(char * s, const char * delim);
/**************************************************************************
* Description :
* Input : pt
ts ms
sstp
* Output : imu_p
**************************************************************************/
void ParseIMU(char* pt, IMU_t *imu_p, double ts, int sstp);
/**************************************************************************
* Description : NMEA
* Input : pt NMEA
ts ms
* Output : ln NMEA
**************************************************************************/
void parseNMEA(char* pt, Nmea_t *ln, double ts);
/**************************************************************************
* Description : GGA
* Input : pt NMEA
ts ms
* Output : ln NMEA
**************************************************************************/
void ParseGGA(char* pt, Nmea_t *ln, double ts);
/**************************************************************************
* Description : RMC
* Input : pt NMEA
ts ms
* Output : ln NMEA
**************************************************************************/
void ParseRMC(char* pt, Nmea_t *ln, double ts);
/**************************************************************************
* Description : GSV
* Input : pt NMEA
ts ms
* Output : ln NMEA
**************************************************************************/
void parseGSV(char* pt, Nmea_t *ln, double ts);
/**************************************************************************
* Description : GSA
* Input : pt NMEA
ts ms
* Output : ln NMEA
**************************************************************************/
void ParseGSA(char* pt, Nmea_t *ln, double ts);
/**----------------------------------------------------------------------
* Function : parseLocAccuracy
* Description : GPSAccuracy
* Date : 2020/7/9 yuanlin@vivo.com &logzhan
*---------------------------------------------------------------------**/
void parseLocAccuracy(char* pt, Nmea_t *ln, double ts);
/**************************************************************************
* Description : NMEA
* Input : ln NMEA
**************************************************************************/
void preprocessNMEA(Nmea_t *ln);
int ParseGnssInsData(char* line, IMU_t* imu_p, Nmea_t* ln);
/**----------------------------------------------------------------------
* Function : HexToDec
* Description :
* Date : 2022-09-15 logzhan
*---------------------------------------------------------------------**/
long HexToDec(char *source);
/**----------------------------------------------------------------------
* Function : pdr_int2Hex
* Description :
* Date : 2020/7/9 yuanlin@vivo.com & logzhan
*---------------------------------------------------------------------**/
char * Int2Hex(int a, char *buffer);
/**----------------------------------------------------------------------
* Function : pdr_getIndexOfSigns
* Description : chsign
* Date : 2020/7/9 yuanlin@vivo.com &logzhan
*---------------------------------------------------------------------**/
int pdr_getIndexOfSigns(char ch);
#endif
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,140 @@
#pragma once
/******************** (C) COPYRIGHT 2023 Geek************************************
* File Name : Pedometer.h
* Department : Sensor Team
* Current Version : V1.0.0
* Author : logzhan
* Date of Issued : 2023.02.24
*******************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
#ifndef _STEPS_ALGORITHM_H_
#define _STEPS_ALGORITHM_H_
#include "pdr_sensor.h"
#define IMU_SAMPLE_FREQ 100 // IMU采样频率100Hz
#define MS2S 1000 // 秒转毫秒单位
#define DOWN_SAMPLE_NUM 4 // 降采样数量
#define ACC_SAMPLE_TIME MS2S / IMU_SAMPLE_FREQ // ACC采样间隔10ms
#define GYRO_SAMPLE_TIME MS2S / IMU_SAMPLE_FREQ // GYR采样间隔10ms
#define SAMPLE_TIME_MIN 9
#define PEDOMETER_FREQ IMU_SAMPLE_FREQ / DOWN_SAMPLE_NUM // 计步器的频率是
#define SampleFrequencyFour 100
#define SampleFrequencydouble 50
#define SampleFrequencyOPF (37.5l)
#define SampleFrequencySix 150
#define AVG_FILTER_BUFF_LEN 5 // 均值滤波器长度默认为5
#define AXIS_NUM 4 // 轴的数量有4个: x、y、z、xyz
#define FILTER_NUM 4 // 滤波器数量4个
#define FILTER_AXIS_NUM AXIS_NUM * FILTER_NUM // 4*4=16, 轴数量4滤波器数量4总共16轴滤波器输出
#define AXIS_ALL 20 // AxisNumberFiltOut + FiltDifNumber
#define ACC_BUFF_NUM 39 // ACC缓存长度39
#define WIN_LENGTH_AVE_DEVI 50 //
#define PI2A (180/3.1415926)
#define STARTSTEPS 8
#define DET_VEHICLE_ACC_BUFF_LEN 200 // Origin acc sampleFrequency is 100 hz
#define WINDOW_LENGTH_MIN2MAX (DET_VEHICLE_ACC_BUFF_LEN/2 - 1) // 25hz , 1 second
#define PLATFORM_PC_WINDOWS
#define STEP_TRUE 1
#define STEP_FALSE 0
#define AXIS_XYZ 3
#if defined PLATFORM_ANDROID_QCOM_ADSP
#define STEPLIB_MEMSET SNS_OS_MEMSET
#if 1
#endif
#elif defined PLATFORM_ANDROID_QCOM_AP || defined PLATFORM_PC_WINDOWS || defined PLATFORM_PC_LINUX || defined PLATFORM_ANDROID_MTK || defined PLATFORM_ANDROID_QCOM_SLPI845
#define STEPLIB_MEMSET memset
#endif
#if defined PLATFORM_ANDROID_MTK
#define ABS_INT abs_value
#else
#define ABS_INT abs
#endif
typedef struct {
unsigned long walkSteps;
}stepsRe;
typedef struct {
double walk;
double walkRealTime;
double nD;
}StepsDefine_t;
typedef enum {
NonSteps = 0,
walk,
run,
}StepState_t;
typedef struct {
unsigned char sign;
StepState_t state;
unsigned long long stateStartTime;
unsigned long long stepsStartTime;
}stateNowDefine;
typedef struct {
StepState_t state;
unsigned long long startTimeStamp;
}StateDef_t;
typedef struct {
int flag;
double ax;
double ay;
double az;
}DownSample_t;
/**---------------------------------------------------------------------
* Function : Pedometer_GetVersion
* Description :
* Date : 2023/02/24
*---------------------------------------------------------------------**/
const char* Pedometer_GetVersion(void);
/**---------------------------------------------------------------------
* Function : initPedometer
* Description : PDR
* Date : 2020/2/20 logzhan
*---------------------------------------------------------------------**/
void Pedometer_Init(void);
/**---------------------------------------------------------------------
* Function : Pedometer_ReInit
* Description :
* Date : 2023/02/24 logzhan
*---------------------------------------------------------------------**/
void Pedometer_ReInit(void);
/**---------------------------------------------------------------------
* Function : PedometerUpdate
* Description : PDR ,
* Date : 2023/02/25 logzhan
*---------------------------------------------------------------------**/
void Pedometer_Update(IMU_t* imu, uint32_t* step);
void Pedometer_GetState(StepState_t* state);
/**---------------------------------------------------------------------
* Function : DetVehicleMode
* Description : PDR ,
* Date : 2023/02/24 logzhan
*---------------------------------------------------------------------**/
void DetVehicleMode(double ax, double ay, double az);
#endif
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,141 @@
#ifndef _PDR_UTIL_H_
#define _PDR_UTIL_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#define TRAJ_POINT_COUNT 1000
#define MIN_POINT_COUNT 15
#define OPT_TRAJ_TIMEOUT 1000
#define FALIED_LINE 0
#define IN_LINE 1
#define CLOSE_START 2
#define CLOSE_END 3
typedef struct LatLng{
double lat;
double lon;
} LatLng_t;
typedef struct TrajSign
{
int count;
double lastTime;
double weight;
double yaw[TRAJ_POINT_COUNT];
double error[TRAJ_POINT_COUNT];
double points[TRAJ_POINT_COUNT][2];
}TrajSign;
/**地球相关参数*******************************************************************/
typedef struct
{
double rmh; /* 子午圈曲率半径 */
double rnh; /* 卯酉圈曲率半径 */
double grav; /* 当地重力加速度 */
double lat; /* 当地纬度rad*/
double wnie[3]; /* 地理系相对惯性系的角速度在导航系分量 */
} EarthData_t;
/**----------------------------------------------------------------------
* Function : mean
* Description : double
* Review :
*
* Date : 2020/7/4 logzhan
*---------------------------------------------------------------------**/
double mean(double *x, int n);
float fmean(float *data, int len);
float stdf(float* data, int len);
double meanAngle(double* angle, int len);
void modAngle(double * angle, double min, double max);
double pow_i(double num, long long n);
double pow_f(double num, double m);
double pow(double x, double y);
void centralization(double *x, double *x_out, int n);
void GetCovMatrix(double *x, double *y, double cov[2][2], int n);
int Jacobi(double a[][2], double p[][2], int n, double eps, int T);
LatLng_t ProjPointOfLatLng(LatLng_t point, LatLng_t linePointA, LatLng_t linePointB);
double CalDistance(LatLng_t pointA, LatLng_t pointB);
void ProjPointOfLatLng_cir(double point1[], double yaw, double point2[], double result[]);
/**----------------------------------------------------------------------
* Function : pdr_invSqrt
* Description : 1/sqrt(x)
* Date : 2020/6/30 logzhan
*---------------------------------------------------------------------**/
float InvSqrt(float x);
/**---------------------------------------------------------------------
* Function : pdr_v3Norm
* Description :
* Date : 2021/01/26 yuanlin@vivocom &&
*
*
*---------------------------------------------------------------------**/
void Vec3Norm(float* vx, float* vy, float* vz);
/**----------------------------------------------------------------------
* Function : pdr_writeCsvStr
* Description : fprintf
* Date : 2020/7/8 logzhan
*---------------------------------------------------------------------**/
void WriteCsvStr(FILE* fp_write, char* str);
/**----------------------------------------------------------------------
* Function : pdr_utc2hms
* Description : UTC
* Date : 2020/7/8 logzhan
*---------------------------------------------------------------------**/
void pdr_utc2hms(double utc, double* h, double* m, double* s);
/**----------------------------------------------------------------------
* Function : qnb2att
* Description :
* Date : 2020/7/4 logzhan
*---------------------------------------------------------------------**/
void Qnb2Att(float* q, double* attitude);
double CalRadianDifferent(double s_dir, double d_dir);
/**----------------------------------------------------------------------
* Function : pdr_earthParameter
* Description :
* Date : 2020/7/8 logzhan
*---------------------------------------------------------------------**/
EarthData_t CalEarthParameter(double oriLat);
/**----------------------------------------------------------------------
* Function : Motion2TypeStr
* Description :
* Date : 2022/9/16 logzhan
*---------------------------------------------------------------------**/
const char* Motion2TypeStr(int type);
int pdr_min(int param_a, int param_b);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,78 @@
#ifndef _PDR_BUFFER_H_
#define _PDR_BUFFER_H_
#ifdef __cplusplus
extern "C" {
#endif
/* Header File Including ------------------------------------------------------------------------ */
/* Macro Declaration ---------------------------------------------------------------------------- */
#define BUFFER_LONG_LENGTH 256
#define BUFFER_SHORT_LENGTH 10
#define BUFFER_TYPE_STACK 0
#define BUFFER_TYPE_QUEUE 1
#define BUFFER_NO_ERROR 0
#define BUFFER_WRONG_PARAMETER 1
#define BUFFER_OUT_OF_MEMORY 2
/* Structure Declaration ------------------------------------------------------------------------ */
#pragma pack (4)
typedef struct BUFFER {
char name[20];
int type;
int length;
int _bottom;
int _top;
int reserved;
double sum;
double mean;
float data[BUFFER_LONG_LENGTH + 1];
}Buffer_t;
typedef struct BUFFER_LONG {
char name[20];
int type;
int length;
int _bottom;
int _top;
int reserved;
double sum;
double mean;
float data[BUFFER_LONG_LENGTH + 1];
} BUFFER_LONG;
typedef struct BUFFER_SHORT {
char name[20];
int type;
int length;
int _bottom;
int _top;
int reserved;
double sum;
double mean;
float data[BUFFER_SHORT_LENGTH + 1];
} BUFFER_SHORT;
#pragma pack ()
/* Global Variable Declaration ------------------------------------------------------------------ */
/* Function Declaration ------------------------------------------------------------------------- */
int BufferInit(Buffer_t *buffer, const char *name, int type, int length);
int BufferClear(Buffer_t *buffer);
int BufferCount(Buffer_t *buffer, int *count);
int BufferGetTop(Buffer_t *buffer, float *value);
int BufferGetBottom(Buffer_t *buffer, float *value);
int BufferPop(Buffer_t *buffer, float *value);
int BufferPush(Buffer_t *buffer, float value);
int BufferGet(Buffer_t *buffer, float *value, int index);
int BufferMean(Buffer_t *buffer, float *mean);
int BufferVar(Buffer_t *buffer, float *var);
int BufferStd(Buffer_t *buffer, float *std);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,15 @@
#ifndef _PDR_GPS_H_
#define _PDR_GPS_H_
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,19 @@
#ifndef __MUNKRES_H
#define __MUNKRES_H
#ifdef __cplusplus
extern "C" {
#endif
/* Macro Definition ----------------------------------------------------------------------------- */
#define MUNKRES_NO_ERROR 0
#define MUNKRES_EXCESSIVE_MATRIX 1
/* Function Declaration ------------------------------------------------------------------------- */
extern int MUNKRES_get_assignment(int *assignment, float* cost, int m, int n);
#ifdef __cplusplus
}
#endif
#endif // for __MUNKRES_H

View File

@ -0,0 +1,151 @@
/******************** (C) COPYRIGHT 2020 Geek************************************
* File Name : pdr_api.h
* Department : Sensor Algorithm Team
* Current Version : V2.0(compare QCOM SAP 5.0)
* Author : logzhan
* Date of Issued : 2021.01.26
* Comments : PDR
********************************************************************************/
#ifndef _PDR_API_H_
#define _PDR_API_H_
#ifdef __cplusplus
extern "C" {
#endif
/* Header File Including -----------------------------------------------------*/
#include <stdio.h>
#include <math.h>
#include <string.h>
#include "pdr_sensor.h"
#include "PDRBase.h"
#include "Utils.h"
/* Macro Definition ----------------------------------------------------------*/
#define IMU_LAST_COUNT 10
typedef struct _PosFusion{
double lat;
double lon;
double gpsLat;
double gpsLon;
double t;
int vaild;
}PosFusion;
/* Function Declaration ------------------------------------------------------*/
/**---------------------------------------------------------------------
* Function : Algorithm_Init
* Description : PDRPDR
*
* Date : 2022/10/15 logzhan
*---------------------------------------------------------------------**/
void Algorithm_Init(void);
/**---------------------------------------------------------------------
* Function : PDRLocationMainLoop
* Description : PDR
*
* Date : 2022/10/16 logzhan
*---------------------------------------------------------------------**/
int PDRLocationMainLoop(IMU_t* ImuData, Nmea_t* NmeaData, LctFs_t* LocFusion);
/**---------------------------------------------------------------------
* Function : pdr_locationMainLoopStr
* Description : PDR
*
* Date : 2020/07/03 logzhan
* 2020/02/02 logzhan :
*---------------------------------------------------------------------**/
int ParseDataAndUpdate(char* line, LctFs_t* result);
/**---------------------------------------------------------------------
* Function : pdr_initRmc
* Description : RMC
* Input : rmc RMC
* Date : 2020/7/3 logzhan
*---------------------------------------------------------------------**/
void RMC_Init(NmeaRMC_t * rmc);
/**---------------------------------------------------------------------
* Function : pdr_initNmeaFlg
* Description : GPSNMEA
* Input : ln NMEA
* Date : 2020/7/3 logzhan
*---------------------------------------------------------------------**/
void NmeaFlag_Init(Nmea_t * ln);
/**---------------------------------------------------------------------
* Function : clearNmeaFlg
* Description : Nmea,init
* Date : 2020/7/4 logzhan
*---------------------------------------------------------------------**/
void ClearNmeaFlg(Nmea_t * ln);
/**---------------------------------------------------------------------
* Function : pdr_saveGnssInfo
* Description : GPS
* Date : 2020/7/3 logzhan
*---------------------------------------------------------------------**/
void SaveGnssInfo(Nmea_t* nmea_data, LctFs_t* result, FILE* fp_gps);
/**----------------------------------------------------------------------
* Function : GetPDRVersion
* Description : pdr
* Date : 2022/10/15 logzhan
*---------------------------------------------------------------------**/
const char* GetPDRVersion(void);
/**----------------------------------------------------------------------
* Function : pdr_closeAlgorithm
* Description : PDR,
* Date : 2020/8/3 logzhan
*---------------------------------------------------------------------**/
void Algorithm_DeInit();
#ifdef _WIN32 // 主要用于支持win32调试使用用于dll接口导出
/**----------------------------------------------------------------------
* Function : LibPDR_Init
* Description : PDR(DLL)
* Date : 2020/8/3 logzhan
*---------------------------------------------------------------------**/
__declspec(dllexport) void LibPDR_Init();
/**----------------------------------------------------------------------
* Function : PDR_StepUpdateGPS
* Description : 仿GPS(DLL)
* Date : 2022/9/16 logzhan
*---------------------------------------------------------------------**/
__declspec(dllexport) PosFusion LibPDR_StepUpdateGPS(int useGpsFlg);
/**----------------------------------------------------------------------
* Function : setSimulatorFileCsvPath
* Description : 仿(DLL)
* Date : 2020/8/3 logzhan
*---------------------------------------------------------------------**/
__declspec(dllexport) void setSimulatorFileCsvPath(char* path);
/**----------------------------------------------------------------------
* Function : LibPDR_DeInit
* Description : pdrdll(DLL)
* Date : 2020/8/3 logzhan
*---------------------------------------------------------------------**/
__declspec(dllexport) void LibPDR_DeInit();
/**----------------------------------------------------------------------
* Function : setRefGpsYaw
* Description : GPS
* Date : 2020/8/3 logzhan
*---------------------------------------------------------------------**/
__declspec(dllexport) void setRefGpsYaw();
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,111 @@
#ifndef __DETECTOR_H
#define __DETECTOR_H
#ifdef __cplusplus
extern "C" {
#endif
/* Header File Including ------------------------------------------------------------------------ */
#include <stdint.h>
#include <stdlib.h>
#include <time.h>
#include "PDRBase.h"
#include "buffer.h"
#include "AHRS.h"
/* Macro Declaration ---------------------------------------------------------------------------- */
#define DETECTOR_NO_ERROR 0
#define DETECTOR_OUT_OF_MEMORY 1
#define MAG_BUF_LEN 256
#define MAG_LEN 6
/* Struct Declaration --------------------------------------------------------------------------- */
typedef void (*DETECTOR_update_callback)(Detector_t *detector);
/* Global Variable Declaration ------------------------------------------------------------------ */
extern BUFFER_SHORT g_acc_frq_buf[3];
extern BUFFER_SHORT g_acc_amp_buf[3];
extern BUFFER_SHORT g_gyr_frq_buf[3];
extern BUFFER_SHORT g_gyr_amp_buf[3];
/* Function Declaration ------------------------------------------------------------------------- */
/**---------------------------------------------------------------------
* Function : GetDetectorObj
* Description : PDR
* Date : 2020/02/16 logzhan
*---------------------------------------------------------------------**/
Detector_t *GetDetectorObj(void);
/**---------------------------------------------------------------------
* Function : Detector_Init
* Description :
* Date : 2022/09/23 logzhan
*---------------------------------------------------------------------**/
Detector_t* Detector_Init(void);
/**---------------------------------------------------------------------
* Function : DetectorReset
* Description : PDR
* Date : 2022/09/23 logzhan
*---------------------------------------------------------------------**/
void DetectorReset(void);
/**---------------------------------------------------------------------
* Function : DetectMotionType
* Description : pdr
* Date : 2020/7/20
*---------------------------------------------------------------------**/
int DetectMotionType(void);
/**---------------------------------------------------------------------
* Function : predict
* Description :
* Date : 2020/7/20 logzhan
*---------------------------------------------------------------------**/
int pdr_detectorPredict(float* feature);
/**----------------------------------------------------------------------
* Function : DetUserStatic
* Description :
* Date : 2022/10/15 logzhan
*---------------------------------------------------------------------**/
int DetUserStatic(PDR_t* g_pdr, GNSS_t* pgnss, unsigned long delSteps);
/**----------------------------------------------------------------------
* Function : detIsCarMode
* Description :
* Input : pgnssGPS
g_pdrPDR
delSteps
time
* Output : int
* Date : 2021/01/28 logzhan
*---------------------------------------------------------------------**/
int DetectCarMode(GNSS_t* pgnss, PDR_t* g_pdr, unsigned long delSteps, int* time);
/**----------------------------------------------------------------------
* Function : detPdrToReset
* Description : PDRPDR
* PDRGPS
* Date : 2021/01/28 logzhan
*---------------------------------------------------------------------**/
int DetectPdrToReset(double pdr_angle, int* gpscnt, unsigned long deltsteps, PDR_t* g_pdr);
/**---------------------------------------------------------------------
* Function : DetectorUpdateIMU
* Description : imu
*
* Date : 2022/09/23
*---------------------------------------------------------------------**/
void DetectorUpdateIMU(IMU_t* imu, PDR_t* pdr);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,314 @@
/******************** (C) COPYRIGHT 2021 Geek************************************
* File Name : pdr_sensor.h
* Department : Sensor Algorithm Team
* Current Version : V2.0
* Author : logzhan
* Date of Issued : 2021.02.01
* Comments : PDR
********************************************************************************/
#ifndef _SENSOR_H_
#define _SENSOR_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
/* Macro Definition ----------------------------------------------------------*/
#define IMU_SENSOR_AXIS 3
#ifdef _WIN32
#define PDR_LOGD printf
#define PDR_LOGE printf
#else
#include <android/log.h>
#define LOG_TAG "Loc_PDR"
#define PDR_LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define PDR_LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
#endif
#define ADD_POINT_NUM 10
#define GGA_STR "GGA"
#define RMC_STR "RMC"
#define GSA_STR "GSA"
#define GSV_STR "GSV"
#define GNGGA_STR "$GNGGA"
#define GPGGA_STR "$GPGGA"
#define GNRMC_STR "$GNRMC"
#define GPRMC_STR "$GPRMC"
#define GNGSA_STR "$GNGSA"
#define GPGSA_STR "$GPGSA"
#define GAGSA_STR "$GAGSA"
#define GLGSA_STR "$GLGSA"
#define GPGSV_STR "$GPGSV"
#define GAGSV_STR "$GAGSV"
#define GLGSV_STR "$GLGSV"
#define NORTH "N"
#define SOUTH "S"
#define EAST "E"
#define WEST "W"
#define ITEM_INVALID (-1)
#define INVAILD_GPS_YAW (-1) // 无效GPS航向角定义
/* Struct Definition ---------------------------------------------------------*/
typedef enum {
SENSOR_MIN,
SENSOR_ACC = 1,
SENSOR_MAG = 2,
SENSOR_GYRO = 4,
SENSOR_LIGHT = 5,
SENSOR_PROXIMITY = 8,
SENSOR_GAME_ROTATION_VECTOR = 15,
SENSOR_LOCATION_STATELLITE = 70,
SENSOR_LOCATION_NETWORK = 71,
SENSOR_LOCATION_FUSION = 72,
SENSOR_LOCATION_NMEA = 73,
SENSOR_LOCATION_NMEA_GNGGA = 74,
SENSOR_LOCATION_NMEA_GPGGA = 75,
SENSOR_LOCATION_NMEA_GNRMC = 76,
SENSOR_LOCATION_NMEA_GPRMC = 77,
SENSOR_LOCATION_NMEA_GNGSA = 78,
SENSOR_LOCATION_NMEA_GPGSA = 79,
SENSOR_LOCATION_NMEA_GPGSV = 80,
SENSOR_LOCATION_NMEA_GLGSV = 81,
SENSOR_LOCATION_NMEA_GAGSV = 82,
SENSOR_LOCATION_NMEA_GLGSA = 83,
SENSOR_LOCATION_NMEA_GAGSA = 84,
SENSOR_MAX,
} sensor;
typedef enum {
POSITIONING_N = 0,
POSITIONING_Y = 1,
}lct_status;
typedef enum {
POSITIONING_MODE_A = 0,
POSITIONING_MODE_M = 1,
}lct_mode;
typedef enum PDR_Mode {
RAW_GPS = 1,
STOP = 2,
WALK_PDR = 3,
WALK_GPS = 4,
CAR = 5
} PDR_Mode;
typedef enum DIR_Mode {
GPS_DATASHEET = 0,
IMU_PCA = 1,
DELTA_LOCATION = 2
} DIR_Mode;
/*for GSA*/
typedef enum {
PSTN_GSA_N = 1,
PSTN_GSA_Y_2D = 2,
PSTN_GSA_Y_3D = 3,
}lct_type;
typedef enum {
LATITUDE_N = 0,
LATITUDE_S = 1,
LONGITUDINAL_E = 2,
LONGITUDINAL_W = 3,
}LL_NSEW;
typedef enum {
MAG_E = 0,
MAG_W = 1,
}mag_heading;
typedef enum {
MODE_A = 0,
MODE_D = 1,
MODE_E = 2,
MODE_N = 3,
}gnrmc_mode;
typedef enum {
invalid = 0,
fix = 1,
dgps_fix = 2,
invalid_pps = 3,
rtk_fix = 4,
rtk_float = 5,
estimating = 6,
}gngga_quality;
typedef struct Sensor {
unsigned char update;
int type;
double time;
float s[IMU_SENSOR_AXIS];
}Sensor_t;
typedef struct imu {
Sensor_t acc;
Sensor_t gyr;
Sensor_t mag;
}IMU_t;
typedef struct NmeaRMC_t {
unsigned char update;
char rmc_check_sum[9];
sensor type;
lct_status status;
LL_NSEW rmc_latitude_ns;
LL_NSEW longitudinal_ew;
mag_heading mag_h;
gnrmc_mode mode;
float speed;
float cog;
float utc_ddmmyy;
float magnetic;
double rmc_utc;
double latitude;
double longitudinal;
double time; //ms
}NmeaRMC_t;
typedef struct NmeaGGA{
unsigned char update;
char gga_check_sum[9];
sensor type;
LL_NSEW gga_latitude_ns;
LL_NSEW longitudinal_ew;
gngga_quality status;
int satellites_nb;
int unit_a;
int unit_h;
int dgps;
float hdop;
float altitude;
float height;
double gga_utc;
double latitude;
double longitudinal;
double time; //ms
}NmeaGGA_t;
typedef struct NmeaGSA {
unsigned char update;
char check_sum[9];
sensor type;
lct_mode mode;
lct_type p_type;
int prnflg;
int prn[12];
float pdop;
float hdop;
float vdop;
double time; //ms
}NmeaGSA_t;
typedef struct satellite_status {
int prn;
int elevation; // elevation >10
int azimuth;
int snr; //snr >25 good
}satellite_status;
typedef struct NmeaGSV {
unsigned char update;
sensor type;
int sentences;
int sentence_number;
int satellites;
int satellite_number;
satellite_status satellites_data[20];
double time; //ms
}NmeaGSV_t;
typedef struct Accuracy{
unsigned char update;
int status; //-1,:Status Unknown; 0: Out of Service; 1: Temporarily Unavailable; 2: Available
float err; // m
double time;
}Accuracy_t;
typedef struct Nmea_t {
unsigned char update;
double minTime;
double maxTime;
NmeaGGA_t gga;
NmeaRMC_t rmc[2]; // 0 - GNRMC, 1 - GPRMC
NmeaGSA_t gsa[3]; // 0 - GPGSA, 1 - GLGSA, 2 - GAGSA
NmeaGSV_t gsv[3]; // 0 - GPGSV, 1 - GLGSV, 2 - GAGSV
Accuracy_t accuracy;
}Nmea_t;
typedef struct lct_fs {
LL_NSEW latitude_ns;
LL_NSEW longitudinal_ew;
double latitude;
double longitudinal;
double gpsLat;
double gpsLon;
double gpsHeading;
double pdrHeading;
double hdop;
double gpsSpeed;
double accuracy;
double time;
double yaw;
double lambda;
double last_lat;
double last_lon;
unsigned long step;
uint8_t motionType;
}LctFs_t;
typedef struct gnss {
LL_NSEW lat_ns;
LL_NSEW lon_ew;
int minElevation;
int satellites_num; // 当前卫星数量
int quality;
float yaw; // GNSS 航向角
float vel; // GNSS 速度
float HDOP; // GNSS 水平精度因子
float error; // 当前GPS的Accuracy
float lastError; // 上一次GPS的Accuracy
int overVelCount; // 速度过快数量统计, 记录速度过快的数量,用于判断手机是否处于车载模式
double timestamps;
double lat;
double lon;
double xNed;
double yNed;
}GNSS_t;
typedef struct IMU {
double time;
float gyr[3];
float acc[3];
float mag[3];
} IMU;
typedef struct AHRS {
uint8_t status;
uint8_t stable; // 当前AHRS算法收敛稳定性
float error;
float q[4]; //
float gravity[3];
float x_axis[3];
float y_axis[3];
float z_axis[3];
float Dt;
float Kp; // mahony kp比例调节参数
float Yaw;
float Pitch;
float Roll;
float insHeading;
}AHRS_t;
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,158 @@
/*********************************************************************************/
/* FILE NAME : scene_recognition.h */
/* AUTHOR : Zhang Jingrui, ID: 11082826, Version: V0.1_Beta, Data:2019-03-28 */
/* DESCRIPTION: This header file conterns the prototype description of the external */
/* interface funtions of the scene recognition module and the definit- */
/* ion of related resources. */
/* HISTORY : (NONE) */
/********************************************************************************/
#ifndef _PDR_SCENE_RECOGNITION_H_
#define _PDR_SCENE_RECOGNITION_H_
/* Header Files Including -----------------------------------------*/
/*=================================================================*/
#include "pdr_sensor.h"
/* Macro Declaration ----------------------------------------------*/
/*=================================================================*/
#define _TIME_BUFFER_SIZE 10 /* Buffer size for the time calculation. */
#define _ACCURACY_BUFFER_SIZE 9 /* Accuracy time-based buffer size. */
#define _GNSS_INDEX_LEN 103 /* Structural array size in _GnssInfo. */
/* Extern Variable Declaration ------------------------------------*/
/*=================================================================*/
//extern int scene_recognition_debug_flag ;
//extern int scene_recognition_log_debug_flag ;
/* Status Declaration ---------------------------------------------*/
/*=================================================================*/
/* Usage: 场景识别模块初始化、重置操作结果状态标志位 */
typedef enum SCENE_INIT_STATE
{
// 场景识别模块初始化相关状态
INIT_SUCCESS = 0,
INIT_NOT_PERFORMED,
INIT_ERROR_MEMORY_OCCUPIED, // 模块资源未提前释放,需先释放资源
INIT_ERROR_MEMORY_INIT_FAILED, // 初始化内存申请失败
INIT_ERROR_REDUNDANCY, // 模块重复初始化,此时初始化无效。若需要重启模块,可以:
// 方法1先关闭模块关闭成功后重新初始化模块。
// 方法2重启模块效果同方法1。
// 场景识别模块重置相关状态(for debug)
INIT_RESET_SUCCESS = 0,
INIT_RESET_FAILED
} SCENE_INIT_STATE;
/* Usage: 场景分类结果 */
typedef enum SCENE_RECOGNITION_RESULT
{
RECOG_UNKNOWN, // 未能确定场景的状态(默认状态)
RECOG_OPEN_AREA, // 场景open-area
RECOG_OTHERS, // 除了上述确定场景外的其他场景
RECOG_ERROR_PARAM_INCRECT, // 输入参数检查错误
RECOG_ERROR_NMEA_INFO_MISS, // 输入参数正确但是内容有误
/* 预研检测结果(不稳定) */
RECOG_MULTIPATH // 检测多径
} SCENE_RECOGNITION_RESULT;
/* Usage: 场景识别模块资源释放操作结果 */
typedef enum SCENE_DESTROY_STATE
{
DESTROY_SUCCESS = 0,
DESTROY_FIALED,
DESTROY_ERROR,
DESTROY_INVALID // 无效释放操作,表示没有对应的初始化或重置操作
} SCENE_DESTROY_STATE;
/* Status Declaration--------------------------------------------*/
/*===============================================================*/
// 描述当前场景识别模块的工作状态
typedef enum _SCENE_MODEL_WORK_STATE
{
MODEL_OFF,
MODEL_ON
} _SCENE_MODEL_WORK_STATE;
/* Usage: Identifier of the quality of the satellites' signal source. */
typedef enum _SIGNAL_QUALITY
{
SIG_UNKNOWN,
GOOD,
BAD
} SIGNAL_QUALITY;
/* Usage: extract and save information from Nmea_t for the module. */
/* This is the interface for the Nmea_t. */
typedef struct _GnssInfo
{
int update; // GNSS更新标志位 1更新 0不更新
double local_timestamp; // 当地时间
float accuracy; // GPS 输出的Accuracy参数Accuracy > 0 当其为负数表示无效
int sat_visible_number; // 当前时间可见卫星数量
float snr_list[_GNSS_INDEX_LEN]; // 当前时间可见卫星的SNR列表
int sat_used_list[_GNSS_INDEX_LEN]; // 当前使用卫星列表
} GnssInfo;
/* Usage: 标记GNSS中的各个卫星系统 */
/* Struct Declaration -------------------------------------------*/
/*===============================================================*/
/* Function Declaration -------------------------------------------*/
/*=================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
/* Function Name: sceneRecognitionInit() */
/* Usage: Initialization module for configuring related resources */
/* and must be executed once first beforing using the scene */
/* recognition module funcition. */
/* Param @ (NONE) */
/* Return @ init_res: Result state of the initialization process. */
SCENE_INIT_STATE SceneRecog_Init(void);
/* Function Name: scene_recognition_reset() */
/* Usage: 初始化模块,配置相关资源,在使用模块前必须首先被执行。 */
/* Param @ (NONE) */
/* Return @ init_res: 重置执行结果。 */
SCENE_INIT_STATE scene_recognition_reset(void);
/**----------------------------------------------------------------------
* Function : sceneRecognitionProc
* Description : GNSS
* 1nmeagnss
* 2) accuracysnrGNSS
* 3)
* Input : PDRnmea
* Return :
* Date : 2020/02/18
*---------------------------------------------------------------------**/
SCENE_RECOGNITION_RESULT sceneRecognitionProc(const Nmea_t* nmea);
/* Function Name: scene_recognition_destroy() */
/* Usage: 场景识别处理结束后的资源释放操作,资源释放后无法继续进行场 */
/* 景识别过程。 */
/* Param @ (NONE) */
/* Return @ destroy_state: 资源释放操作结果。 */
SCENE_DESTROY_STATE scene_recognition_destroy(void);
/**----------------------------------------------------------------------
* Function : isOpenArea
* Description : GNSSGNSS
*
* Return : 0 : 1()
* Author : Zhang Jingrui, Geek ID: 11082826
* Date : 2020/02/18 logzhan
*---------------------------------------------------------------------**/
int isOpenArea(const Nmea_t* nmea);
#ifdef __cplusplus
}
#endif
#endif //__SCENE_RECOGNITION_H__

View File

@ -0,0 +1,207 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\Buffer.c" />
<ClCompile Include="..\src\Complex.cpp" />
<ClCompile Include="..\src\CoordTrans.cpp" />
<ClCompile Include="..\src\Munkres.c" />
<ClCompile Include="..\src\AHRS.c" />
<ClCompile Include="..\src\Interface.c" />
<ClCompile Include="..\src\Detector.c" />
<ClCompile Include="..\src\Fft.c" />
<ClCompile Include="..\src\Filter.c" />
<ClCompile Include="..\src\Kalman.c" />
<ClCompile Include="..\src\LinearFit.c" />
<ClCompile Include="..\src\Location.c" />
<ClCompile Include="..\src\Main.cpp" />
<ClCompile Include="..\src\Matrix.c" />
<ClCompile Include="..\src\ParseData.c" />
<ClCompile Include="..\src\PDRBase.c" />
<ClCompile Include="..\src\Utils.c" />
<ClCompile Include="..\src\Quaternion.cpp" />
<ClCompile Include="..\src\SceneRecognition.c" />
<ClCompile Include="..\src\Pedometer.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\include\buffer.h" />
<ClInclude Include="..\include\Filter.h" />
<ClInclude Include="..\include\LapProcess.h" />
<ClInclude Include="..\include\LocationTool.h" />
<ClInclude Include="..\include\m_munkres.h" />
<ClInclude Include="..\include\ParseData.h" />
<ClInclude Include="..\include\AHRS.h" />
<ClInclude Include="..\include\pdr_api.h" />
<ClInclude Include="..\include\PDRBase.h" />
<ClInclude Include="..\include\pdr_detector.h" />
<ClInclude Include="..\include\Fft.h" />
<ClInclude Include="..\include\Kalman.h" />
<ClInclude Include="..\include\LinearFit.h" />
<ClInclude Include="..\include\Location.h" />
<ClInclude Include="..\include\Main.h" />
<ClInclude Include="..\include\Matrix.h" />
<ClInclude Include="..\include\pdr_sensor.h" />
<ClInclude Include="..\include\pdr_trackSmooth.h" />
<ClInclude Include="..\include\Utils.h" />
<ClInclude Include="..\include\scene_recognition.h" />
<ClInclude Include="..\include\Pedometer.h" />
<ClInclude Include="..\src\Complex.h" />
<ClInclude Include="..\src\CoordTrans.h" />
<ClInclude Include="..\src\Quaternion.h" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{28D32532-309F-40EA-9E4A-2D162CC434D2}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>mp4spliter</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<ProjectName>PDR</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>..\include\;$(IncludePath)</IncludePath>
<ReferencePath>$(ReferencePath)</ReferencePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>..\3rdparty\Json\;..\3rdparty\onnx\;..\3rdparty\opencv\;..\include\;$(IncludePath)</IncludePath>
<ReferencePath>..\3rdparty\Json;$(ReferencePath)</ReferencePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>..\include\;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>..\include\;.\3rdparty\libjson\;..\3rdparty\libcurl\;..\3rdparty\opencv\;$(IncludePath)</IncludePath>
<LibraryPath>..\3rdparty\onnx\lib\;..\3rdparty\opencv\lib\;..\3rdparty\libcurl\bin\;..\3rdparty\libjson\bin\;$(LibraryPath)</LibraryPath>
<ReferencePath>D:\Program Files\OpenSSL-Win64\include;$(ReferencePath)</ReferencePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<BufferSecurityCheck>true</BufferSecurityCheck>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<BufferSecurityCheck>true</BufferSecurityCheck>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,159 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="src">
<UniqueIdentifier>{7c7c488d-9b32-4de4-9ec8-b4bd38c3e7b0}</UniqueIdentifier>
</Filter>
<Filter Include="inc">
<UniqueIdentifier>{a09dc878-ed5c-47e4-bdcc-c3e2c8f05882}</UniqueIdentifier>
</Filter>
<Filter Include="src\Utils">
<UniqueIdentifier>{1d99ec5e-847f-4166-8f79-ddb0473a04dd}</UniqueIdentifier>
</Filter>
<Filter Include="src\Math">
<UniqueIdentifier>{bd2be68d-d6d0-4b04-97d9-2ac99be07afe}</UniqueIdentifier>
</Filter>
<Filter Include="src\Location">
<UniqueIdentifier>{74391251-b6de-45ec-88b1-0ee0171e44da}</UniqueIdentifier>
</Filter>
<Filter Include="src\Ins">
<UniqueIdentifier>{7f1fc113-1a0a-488e-9f77-2b12c7280aed}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\Buffer.c">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\Munkres.c">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\Interface.c">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\Detector.c">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\Fft.c">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\Filter.c">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\Main.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\SceneRecognition.c">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\Utils.c">
<Filter>src\Utils</Filter>
</ClCompile>
<ClCompile Include="..\src\Matrix.c">
<Filter>src\Math</Filter>
</ClCompile>
<ClCompile Include="..\src\Kalman.c">
<Filter>src\Location</Filter>
</ClCompile>
<ClCompile Include="..\src\LinearFit.c">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\Quaternion.cpp">
<Filter>src\Math</Filter>
</ClCompile>
<ClCompile Include="..\src\CoordTrans.cpp">
<Filter>src\Utils</Filter>
</ClCompile>
<ClCompile Include="..\src\Location.c">
<Filter>src\Location</Filter>
</ClCompile>
<ClCompile Include="..\src\ParseData.c">
<Filter>src\Utils</Filter>
</ClCompile>
<ClCompile Include="..\src\AHRS.c">
<Filter>src\Ins</Filter>
</ClCompile>
<ClCompile Include="..\src\Pedometer.c">
<Filter>src\Ins</Filter>
</ClCompile>
<ClCompile Include="..\src\Complex.cpp">
<Filter>src\Math</Filter>
</ClCompile>
<ClCompile Include="..\src\PDRBase.c">
<Filter>src</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\include\buffer.h">
<Filter>inc</Filter>
</ClInclude>
<ClInclude Include="..\include\Filter.h">
<Filter>inc</Filter>
</ClInclude>
<ClInclude Include="..\include\LapProcess.h">
<Filter>inc</Filter>
</ClInclude>
<ClInclude Include="..\include\LocationTool.h">
<Filter>inc</Filter>
</ClInclude>
<ClInclude Include="..\include\m_munkres.h">
<Filter>inc</Filter>
</ClInclude>
<ClInclude Include="..\include\pdr_api.h">
<Filter>inc</Filter>
</ClInclude>
<ClInclude Include="..\include\PDRBase.h">
<Filter>inc</Filter>
</ClInclude>
<ClInclude Include="..\include\pdr_detector.h">
<Filter>inc</Filter>
</ClInclude>
<ClInclude Include="..\include\Fft.h">
<Filter>inc</Filter>
</ClInclude>
<ClInclude Include="..\include\LinearFit.h">
<Filter>inc</Filter>
</ClInclude>
<ClInclude Include="..\include\Main.h">
<Filter>inc</Filter>
</ClInclude>
<ClInclude Include="..\include\pdr_sensor.h">
<Filter>inc</Filter>
</ClInclude>
<ClInclude Include="..\include\pdr_trackSmooth.h">
<Filter>inc</Filter>
</ClInclude>
<ClInclude Include="..\include\scene_recognition.h">
<Filter>inc</Filter>
</ClInclude>
<ClInclude Include="..\include\Utils.h">
<Filter>src\Utils</Filter>
</ClInclude>
<ClInclude Include="..\include\Kalman.h">
<Filter>src\Location</Filter>
</ClInclude>
<ClInclude Include="..\src\Quaternion.h">
<Filter>src\Math</Filter>
</ClInclude>
<ClInclude Include="..\src\CoordTrans.h">
<Filter>src\Utils</Filter>
</ClInclude>
<ClInclude Include="..\include\Matrix.h">
<Filter>src\Math</Filter>
</ClInclude>
<ClInclude Include="..\include\Location.h">
<Filter>src\Location</Filter>
</ClInclude>
<ClInclude Include="..\include\ParseData.h">
<Filter>src\Utils</Filter>
</ClInclude>
<ClInclude Include="..\include\AHRS.h">
<Filter>src\Ins</Filter>
</ClInclude>
<ClInclude Include="..\include\Pedometer.h">
<Filter>src\Ins</Filter>
</ClInclude>
<ClInclude Include="..\src\Complex.h">
<Filter>src\Math</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -0,0 +1,114 @@
/******************** (C) COPYRIGHT 2020 Geek************************************
* File Name : pdr_ahrs.c
* Department : Sensor Algorithm Team
* Current Version : V1.2
* Author : logzhan &
*
*
* Date of Issued : 2020.7.3
* Comments : PDR AHRS 姿
********************************************************************************/
/* Header File Including -----------------------------------------------------*/
#include <math.h>
#include <string.h>
#include "PDRBase.h"
#include "AHRS.h"
#include "pdr_detector.h"
#include "Filter.h"
#include "buffer.h"
#include "Kalman.h"
#include "Utils.h"
#include "Quaternion.h"
/* Macro Definition ----------------------------------------------------------*/
#define FLT_THRES 0.000001f // 浮点数最小阈值
#define ENABLE_MAG 0
/* Global Variable Definition ------------------------------------------------*/
AHRS_t Ahrs;
/**----------------------------------------------------------------------
* Function : MahonyUpdateAHRS
* Description : Mahony姿
* Date : 2020/02/18 logzhan :
* AHRSAHRSerror,
PDR仿10%
*---------------------------------------------------------------------**/
static void MahonyUpdateAHRS(float gx, float gy, float gz, float ax, float ay, float az,
float mx, float my, float mz) {
float* q = Ahrs.q;
// 归一化磁力计和加速度计
Vec3Norm(&ax, &ay, &az);
float wx = 0.0f, wy = 0.0f, wz = 0.0f;
#if ENABLE_MAG
if (!((mx == 0.0f) && (my == 0.0f) && (mz == 0.0f))) {
pdr_v3Norm(&mx, &my, &mz);
// 把磁场从载体系转换到地理坐标系 h = R^-1 * (mx,my,mz)
float hx = 2.0f * (mx * (0.5f - q2 * q2 - q[3] * q[3]) + my * (q[1] * q2 - q[0] * q[3]) + mz * (q[1] * q[3] + q[0] * q2));
float hy = 2.0f * (mx * (q[1] * q2 + q[0] * q[3]) + my * (0.5f - q[1] * q[1] - q[3] * q[3]) + mz * (q2 * q[3] - q[0] * q[1]));
float hz = 2.0f * (mx * (q[1] * q[3] - q[0] * q2) + my * (q2 * q[3] + q[0] * q[1]) + mz * (0.5f - q[1] * q[1] - q2 * q2));
// 理论上bx = 0, by 指向北向因为手机IMU数据使用的是东北天(x,y,z)坐标系
float by = (float)sqrt(hx * hx + hy * hy);
float bz = hz;
wx = by * (q[0] * q[3] + q[1] * q2) + bz * (q[1] * q[3] - q[0] * q2);
wy = by * (0.5f - q[1] * q[1] - q[3] * q[3]) + bz * (q[0] * q[1] + q2 * q[3]);
wz = by * (q2 * q[3] - q[0] * q[1]) + bz * (0.5f - q[1] * q[1] - q2 * q2);
}
#endif
// 把重力转换到地理坐标系 v = R * (0,0,1)
float vx = q[1]*q[3] - q[0]*q[2];
float vy = q[0]*q[1] + q[2]*q[3];
float vz = q[0]*q[0] - 0.5f + q[3]*q[3];
// 计算矢量叉乘误差
float ex = ay*vz - az*vy + my*wz - mz*wy;
float ey = az*vx - ax*vz + mz*wx - mx*wz;
float ez = ax*vy - ay*vx + mx*wy - my*wx;
// Apply proportional feedback
gx += Ahrs.Kp * ex;
gy += Ahrs.Kp * ey;
gz += Ahrs.Kp * ez;
// 龙格库塔法更新四元数
float qa = q[0]; float qb = q[1]; float qc = q[2];
q[0] += (-qb * gx - qc * gy - q[3] * gz) * 0.5f * (Ahrs.Dt);
q[1] += ( qa * gx + qc * gz - q[3] * gy) * 0.5f * (Ahrs.Dt);
q[2] += ( qa * gy - qb * gz + q[3] * gx) * 0.5f * (Ahrs.Dt);
q[3] += ( qa * gz + qb * gy - qc * gx) * 0.5f * (Ahrs.Dt);
// 四元数归一化
QuaternionNorm(&q[0], &q[1], &q[2], &q[3]);
// 四元数转欧拉角
Ahrs.Pitch = asinf(-2.0f * (q[3]*q[1] - q[0]*q[2])) * (180.0f / 3.141592f);
Ahrs.Yaw = atan2f(q[2]*q[1] + q[0]*q[3], 0.5f - q[2]*q[2] - q[3]*q[3]) * (180.0f / 3.141592f);
Ahrs.Roll = atan2f(q[2]*q[3] + q[0]*q[1], 0.5f - q[2]*q[2] - q[1]*q[1]) * (180.0f / 3.141592f);
}
void AHRS_Init(void) {
memset(&Ahrs, 0, sizeof(Ahrs));
Ahrs.Kp = AHRS_KP;
Ahrs.Dt = 1.0f / AHRS_SAMPLE_FREQ;
Ahrs.q[0] = 1.0f;
}
/**----------------------------------------------------------------------
* Function : UpdateAHRS
* Description : AHRS
* Date : 2022/10/18 logzhan
*---------------------------------------------------------------------**/
int UpdateAHRS(IMU_t* imu) {
// logzhan 21/02/06 : 感觉是acc输入精度会高一些
MahonyUpdateAHRS(imu->gyr.s[0], imu->gyr.s[1], imu->gyr.s[2],
imu->acc.s[0], imu->acc.s[1], imu->acc.s[2],
imu->mag.s[0], imu->mag.s[1], imu->mag.s[2]);
return PDR_TRUE;
}

View File

@ -0,0 +1,201 @@
/******************** (C) COPYRIGHT 2022 Geek************************************
* File Name : Buffer.c
* Current Version : V1.2
* Author : logzhan
* Date of Issued : 2022.10.15
* Comments : PDR
*
********************************************************************************/
/* Header File Including ------------------------------------------------------*/
#include <string.h>
#include <math.h>
#include "buffer.h"
/* Macro Declaration ----------------------------------------------------------*/
#define ADD_PTR(ptr, ofs) ((ptr + ofs) % (buffer->length + 1))
#define INC_PTR(ptr) ((ptr + 1) % (buffer->length + 1))
#define DEC_PTR(ptr) ((ptr + buffer->length) % (buffer->length + 1))
/* Function Definition --------------------------------------------------------*/
int BufferInit(Buffer_t *buf, const char *name, int type, int len) {
int i;
if (NULL == buf) {
return BUFFER_WRONG_PARAMETER;
}
memset(buf->data, 0, buf->length * sizeof(*(buf->data)));
for (i = 0; i < 20 - 1 && '\0' != name[i]; ++i) {
buf->name[i] = name[i];
}
buf->name[i] = '\0';
buf->type = type;
buf->length = len;
buf->_bottom = 0;
buf->_top = 0;
buf->mean = 0.0;
buf->sum = 0.0;
return BUFFER_NO_ERROR;
}
int BufferClear(Buffer_t *buffer) {
if (NULL == buffer) {
return BUFFER_WRONG_PARAMETER;
}
memset(buffer->data, 0, buffer->length * sizeof(*(buffer->data)));
buffer->_bottom = 0;
buffer->_top = 0;
buffer->mean = 0.0;
buffer->sum = 0.0;
return BUFFER_NO_ERROR;
}
int BufferCount(Buffer_t *buffer, int *count) {
if (NULL == buffer) {
return BUFFER_WRONG_PARAMETER;
}
*count = (buffer->_top - buffer->_bottom + buffer->length + 1) % (buffer->length + 1);
return BUFFER_NO_ERROR;
}
int BufferGetTop(Buffer_t *buffer, float *value) {
*value = 0;
if (NULL == buffer) {
return BUFFER_WRONG_PARAMETER;
}
if (buffer->_top == buffer->_bottom) {
return BUFFER_OUT_OF_MEMORY;
}
*value = buffer->data[DEC_PTR(buffer->_top)];
return BUFFER_NO_ERROR;
}
int BufferGetBottom(Buffer_t *buffer, float *value) {
if (NULL == buffer) {
return BUFFER_WRONG_PARAMETER;
}
if (buffer->_top == buffer->_bottom) {
return BUFFER_OUT_OF_MEMORY;
}
*value = buffer->data[buffer->_bottom];
return BUFFER_NO_ERROR;
}
int BufferPop(Buffer_t *buffer, float *value) {
if (NULL == buffer) {
return BUFFER_WRONG_PARAMETER;
}
if (buffer->_top == buffer->_bottom) {
return BUFFER_OUT_OF_MEMORY;
}
switch (buffer->type) {
case BUFFER_TYPE_STACK:
buffer->_top = DEC_PTR(buffer->_top);
*value = buffer->data[buffer->_top];
break;
case BUFFER_TYPE_QUEUE:
default:
*value = buffer->data[buffer->_bottom];
buffer->_bottom = INC_PTR(buffer->_bottom);
break;
}
return BUFFER_NO_ERROR;
}
int BufferPush(Buffer_t *buffer, float value) {
if (NULL == buffer) {
return BUFFER_WRONG_PARAMETER; /* BUFFER_WRONG_PARAMETER值为1 */
}
buffer->data[buffer->_top] = value;
buffer->_top = INC_PTR(buffer->_top); /* INC_PTR为加1超过buffer长度就循环加1*/
if (buffer->_top == buffer->_bottom) {
buffer->_bottom = INC_PTR(buffer->_bottom);
return BUFFER_OUT_OF_MEMORY; /* BUFFER_OUT_OF_MEMORY值为2 */
}
else {
return BUFFER_NO_ERROR; /* BUFFER_NO_ERROR值为0 */
}
}
int BufferGet(Buffer_t *buffer, float *value, int index) {
if (NULL == buffer) {
return BUFFER_WRONG_PARAMETER;
}
if (index >= buffer->length) {
return BUFFER_OUT_OF_MEMORY;
}
*value = buffer->data[ADD_PTR(buffer->_bottom, index)];
return BUFFER_NO_ERROR;
}
int BufferMean(Buffer_t *buffer, float *mean) {
int index;
int count;
if (NULL == buffer) {
return BUFFER_WRONG_PARAMETER;
}
*mean = 0;
count = 0;
for (index = buffer->_bottom; index != buffer->_top; index = INC_PTR(index)) {
*mean += buffer->data[index];
++count;
}
if (0 != count) {
*mean /= count;
}
return BUFFER_NO_ERROR;
}
int BufferVar(Buffer_t *buffer, float *var) {
int index;
int count;
float mean;
if (NULL == buffer) {
return BUFFER_WRONG_PARAMETER;
}
mean = 0;
count = 0;
for (index = buffer->_bottom; index != buffer->_top; index = INC_PTR(index)) {
mean += buffer->data[index];
++count;
}
if (0 != count) {
mean /= count;
}
*var = 0;
for (index = buffer->_bottom; index != buffer->_top; index = INC_PTR(index)) {
*var += (buffer->data[index] - mean) * (buffer->data[index] - mean);
}
if (0 != count) {
*var /= count;
}
return BUFFER_NO_ERROR;
}
int BufferStd(Buffer_t *buffer, float *std) {
int ret = BufferVar(buffer, std);
*std = sqrtf(*std);
return ret;
}

View File

@ -0,0 +1,74 @@
/******************** (C) COPYRIGHT 2022 Geek************************************
* File Name : Complex.c
* Current Version : V2.0
* Author : logzhan
* Date of Issued : 2022.10.15
* Comments : PDR
********************************************************************************/
/* Header File Including -----------------------------------------------------*/
#include "math.h"
#include "Complex.h"
/**---------------------------------------------------------------------
* Function : ComplexAbs
* Description :
* Date : 2022/10/15 logzhan
*---------------------------------------------------------------------**/
float ComplexAbs(Complex_t c) {
return sqrtf(c.real * c.real + c.image * c.image);
}
/**---------------------------------------------------------------------
* Function : ComplexAdd
* Description :
* Date : 2022/10/15 logzhan
*---------------------------------------------------------------------**/
Complex_t ComplexAdd(Complex_t a, Complex_t b) {
Complex_t c = { 0 };
c.real = a.real + b.real;
c.image = a.image + b.image;
return c;
}
/**---------------------------------------------------------------------
* Function : ComplexSub
* Description :
* Date : 2022/10/15 logzhan
*---------------------------------------------------------------------**/
Complex_t ComplexSub(Complex_t a, Complex_t b) {
Complex_t c = { 0 };
c.real = a.real - b.real;
c.image = a.image - b.image;
return c;
}
/**---------------------------------------------------------------------
* Function : ComplexMul
* Description :
* Date : 2022/10/15 logzhan
*---------------------------------------------------------------------**/
Complex_t ComplexMul(Complex_t a, Complex_t b) {
Complex_t c;
c.real = a.real * b.real - a.image * b.image;
c.image = a.real * b.image + a.image * b.real;
return c;
}
/**---------------------------------------------------------------------
* Function : ComplexPow
* Description :
* Date : 2022/10/15 logzhan
*---------------------------------------------------------------------**/
Complex_t ComplexPow(Complex_t c, int n) {
Complex_t p = { 1, 0 };
int i;
float real;
for (i = 0; i < n; ++i) {
real = p.real * c.real - p.image * c.image;
p.image = p.real * c.image + p.image * c.real;
p.real = real;
}
return p;
}

View File

@ -0,0 +1,24 @@
#ifndef _PDR_COMPLEX_H_
#define _PDR_COMPLEX_H_
#ifdef __cplusplus
extern "C" {
#endif
typedef struct Complex {
float real;
float image;
} Complex_t;
float ComplexAbs(Complex_t c);
Complex_t ComplexAdd(Complex_t a, Complex_t b);
Complex_t ComplexSub(Complex_t a, Complex_t b);
Complex_t ComplexMul(Complex_t a, Complex_t b);
Complex_t ComplexPow(Complex_t c, int n);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,74 @@
/******************** (C) COPYRIGHT 2022 Geek************************************
* File Name : CoordTrans.cpp
* Current Version : V1.0
* Author : logzhan
* Date of Issued : 2022.09.20
* Comments : PDR
********************************************************************************/
#include <math.h>
#include "CoordTrans.h"
void WGS842ECEF(double* plla, double* ecef) {
double f = 1 / 298.257223563;
double a = 6378136.49;
double b, e, roc;
b = a * (1 - f);
e = sqrt(pow(a, 2) - pow(b, 2)) / a;
roc = a / sqrt(1 - pow(e * sin(plla[0]), 2));
ecef[0] = (roc + plla[2]) * cos(plla[0]) * cos(plla[1]);
ecef[1] = (roc + plla[2]) * cos(plla[0]) * sin(plla[1]);
ecef[2] = (roc * (1 - e * e) + plla[2]) * sin(plla[0]);
}
void ECEF2WGS84(double* ecef, double* plla)
{
double a = 6378137;
double b = 6356752.314245179;
double e, ep, p, th, roc;
e = sqrt(pow(a, 2) - pow(b, 2)) / a;
b = sqrt(pow(a, 2) * (1 - pow(e, 2)));
ep = sqrt((pow(a, 2) - pow(b, 2)) / pow(b, 2));
p = sqrt(ecef[0] * ecef[0] + ecef[1] * ecef[1]);
th = atan2(a * ecef[2], b * p);
plla[1] = atan2(ecef[1], ecef[0]);
plla[0] = atan2((ecef[2] + pow(ep, 2) * b * pow(sin(th), 3)), (p - pow(e, 2) * a * pow(cos(th), 3)));
roc = a / sqrt(1 - pow(e * sin(plla[0]), 2));
plla[2] = p / cos(plla[0]) - roc;
}
void ECEF2NED(double* ecef, double* plla, double* ned)
{
ned[0] = -sin(plla[0]) * cos(plla[1]) * ecef[0] - sin(plla[0]) * sin(plla[1]) * ecef[1] + cos(plla[0]) * ecef[2];
ned[1] = -sin(plla[1]) * ecef[0] + cos(plla[1]) * ecef[1];
ned[2] = -cos(plla[0]) * cos(plla[1]) * ecef[0] - cos(plla[0]) * sin(plla[1]) * ecef[1] - sin(plla[0]) * ecef[2];
}
void NED2ECEF(double* plla, double* ned, double* ecef0, double* ecef)
{
ecef[0] = -sin(plla[0]) * cos(plla[1]) * ned[0] - sin(plla[1]) * ned[1] - cos(plla[0]) * cos(plla[1]) * ned[2] + ecef0[0];
ecef[1] = -sin(plla[0]) * sin(plla[1]) * ned[0] + cos(plla[1]) * ned[1] - cos(plla[0]) * sin(plla[1]) * ned[2] + ecef0[1];
ecef[2] = cos(plla[0]) * ned[0] - sin(plla[0]) * ned[2] + ecef0[2];;
}
void WGS842NED(double* plla, double* ref_lla, double* ned)
{
double ecef[3] = { 0 };
WGS842ECEF(plla, ecef);
ECEF2NED(ecef, ref_lla, ned);
}
void NED2WGS84(double* ref_plla, double* ned, double* plla)
{
double ecef[3] = { 0 };
double ref_ecef[3] = { 0 };
WGS842ECEF(ref_plla, ref_ecef);
NED2ECEF(ref_plla, ned, ref_ecef, ecef);
ECEF2WGS84(ecef, plla);
}

View File

@ -0,0 +1,24 @@
#ifndef _PDR_COORD_SUPPORT_H
#define _PDR_COORD_SUPPORT_H
#ifdef __cplusplus
extern "C" {
#endif
void WGS842ECEF(double* plla, double* ecef);
void ECEF2WGS84(double* ecef, double* plla);
void ECEF2NED(double* ecef, double* plla, double* ned);
void NED2ECEF(double* plla, double* ned, double* ecef0, double* ecef);
void WGS842NED(double* plla, double* ref_lla, double* ned);
void NED2WGS84(double* ref_plla, double* ned, double* plla);
#ifdef __cplusplus
}
#endif
#endif // _PDR_KML_SUPPORT_H

View File

@ -0,0 +1,726 @@
/******************** (C) COPYRIGHT 2020 Geek************************************
* File Name : pdr_detector.c
* Department : Sensor Algorithm Team
* Current Version : V1.2
* Author : ZhangJingrui@vivo.com
* Date of Issued : 2020.7.4
* Comments : PDRPDR
*
********************************************************************************/
/* Header File Including -----------------------------------------------------*/
#include <string.h>
#include <math.h>
#include <stdio.h>
#include "PDRBase.h"
#include "pdr_detector.h"
#include "Filter.h"
#include "buffer.h"
#include "Fft.h"
#include "m_munkres.h"
/* Macro Definition ----------------------------------------------------------*/
#define FLT_BUF_LEN 256
#define FRQ_BUF_LEN 10
#define TMP_BUF_LEN 5
#define FRQ_RAT 0.3f
#define ACCE 0
#define GYRO 1
#define X_AXIS 0
#define Y_AXIS 1
#define Z_AXIS 2
#define ARR_LEN(arr) (sizeof(arr) / sizeof(*arr))
#define GET_MOL(x) (sqrt(x[0] * x[0] + x[1] * x[1] + x[2] * x[2]))
#define INC_PTR(buf, ptr) (((ptr) + 1) % ((buf)->length + 1))
#define DEC_PTR(buf, ptr) (((ptr) + (buf)->length) % ((buf)->length + 1))
#define COST(i, j) cost[(i) + (j) * number]
/* Global Variable Definition ------------------------------------------------*/
static Detector_t pDetector;
static BUFFER_LONG g_mol_buf[2];
static Filter_t g_mol_flt[2];
const double g_mol_flt_b[] = { 4.96135120696701e-05, 0.000496135120696701, 0.00223260804313515, 0.00595362144836041,
0.0104188375346307, 0.0125026050415569, 0.0104188375346307, 0.00595362144836041, 0.00223260804313515,
0.000496135120696701, 4.96135120696701e-05 };
const double g_mol_flt_a[] = { 1, -3.98765436730188, 8.09440659266207, -10.4762753571126, 9.42333716215302, -6.08421408355183,
2.83526165426630, -0.936403462626094, 0.208912324670401, -0.0283358586690797, 0.00176963186900233 };
const double g_mol_flt_h0 = 1;
BUFFER_SHORT g_acc_frq_buf[3];
BUFFER_SHORT g_acc_amp_buf[3];
static BUFFER_SHORT g_acc_tmp_buf[3];
BUFFER_SHORT g_gyr_frq_buf[3];
BUFFER_SHORT g_gyr_amp_buf[3];
static BUFFER_SHORT g_gyr_tmp_buf[3];
static int g_label[5] = { 0 };
/* Function Definition -------------------------------------------------------------------------- */
/**---------------------------------------------------------------------
* Function : GetDetectorObj
* Description : PDR
* Date : 2020/02/16 logzhan
*---------------------------------------------------------------------**/
Detector_t* GetDetectorObj(void) {
return &pDetector;
}
/**---------------------------------------------------------------------
* Function : Detector_Init
* Description :
* Date : 2020/02/16 logzhan & logzhan
*---------------------------------------------------------------------**/
Detector_t* Detector_Init(void) {
DetectorReset();
return &pDetector;
}
/**---------------------------------------------------------------------
* Function : DetectorReset
* Description : PDR
* Date : 2022/09/23 logzhan
*---------------------------------------------------------------------**/
void DetectorReset(void) {
pDetector.tick = 0;
pDetector.lastType = DETECTOR_TYPE_STATIC;
BufferInit((Buffer_t *)&g_mol_buf[ACCE], "acce_mold_filtered", BUFFER_TYPE_QUEUE, FLT_BUF_LEN);
BufferInit((Buffer_t *)&g_mol_buf[GYRO], "gyro_mold_filtered", BUFFER_TYPE_QUEUE, FLT_BUF_LEN);
BufferInit((Buffer_t *)&g_acc_frq_buf[0], "acc_frq_buf_0", BUFFER_TYPE_QUEUE, FRQ_BUF_LEN);
BufferInit((Buffer_t *)&g_acc_frq_buf[1], "acc_frq_buf_1", BUFFER_TYPE_QUEUE, FRQ_BUF_LEN);
BufferInit((Buffer_t *)&g_acc_frq_buf[2], "acc_frq_buf_2", BUFFER_TYPE_QUEUE, FRQ_BUF_LEN);
BufferInit((Buffer_t *)&g_acc_amp_buf[0], "acc_amp_buf_0", BUFFER_TYPE_QUEUE, FRQ_BUF_LEN);
BufferInit((Buffer_t *)&g_acc_amp_buf[1], "acc_amp_buf_1", BUFFER_TYPE_QUEUE, FRQ_BUF_LEN);
BufferInit((Buffer_t *)&g_acc_amp_buf[2], "acc_amp_buf_2", BUFFER_TYPE_QUEUE, FRQ_BUF_LEN);
BufferInit((Buffer_t *)&g_acc_tmp_buf[0], "acc_tmp_buf_0", BUFFER_TYPE_QUEUE, TMP_BUF_LEN);
BufferInit((Buffer_t *)&g_acc_tmp_buf[1], "acc_tmp_buf_1", BUFFER_TYPE_QUEUE, TMP_BUF_LEN);
BufferInit((Buffer_t *)&g_acc_tmp_buf[2], "acc_tmp_buf_2", BUFFER_TYPE_QUEUE, TMP_BUF_LEN);
BufferInit((Buffer_t *)&g_gyr_frq_buf[0], "gyr_frq_buf_0", BUFFER_TYPE_QUEUE, FRQ_BUF_LEN);
BufferInit((Buffer_t *)&g_gyr_frq_buf[1], "gyr_frq_buf_1", BUFFER_TYPE_QUEUE, FRQ_BUF_LEN);
BufferInit((Buffer_t *)&g_gyr_frq_buf[2], "gyr_frq_buf_2", BUFFER_TYPE_QUEUE, FRQ_BUF_LEN);
BufferInit((Buffer_t *)&g_gyr_amp_buf[0], "gyr_amp_buf_0", BUFFER_TYPE_QUEUE, FRQ_BUF_LEN);
BufferInit((Buffer_t *)&g_gyr_amp_buf[1], "gyr_amp_buf_1", BUFFER_TYPE_QUEUE, FRQ_BUF_LEN);
BufferInit((Buffer_t *)&g_gyr_amp_buf[2], "gyr_amp_buf_2", BUFFER_TYPE_QUEUE, FRQ_BUF_LEN);
BufferInit((Buffer_t *)&g_gyr_tmp_buf[0], "gyr_tmp_buf_0", BUFFER_TYPE_QUEUE, TMP_BUF_LEN);
BufferInit((Buffer_t *)&g_gyr_tmp_buf[1], "gyr_tmp_buf_1", BUFFER_TYPE_QUEUE, TMP_BUF_LEN);
BufferInit((Buffer_t *)&g_gyr_tmp_buf[2], "gyr_tmp_buf_2", BUFFER_TYPE_QUEUE, TMP_BUF_LEN);
FilterSetCoef(&g_mol_flt[ACCE], ARR_LEN(g_mol_flt_b), (double *)g_mol_flt_b, (double *)g_mol_flt_a, (double)g_mol_flt_h0);
FilterSetCoef(&g_mol_flt[GYRO], ARR_LEN(g_mol_flt_b), (double *)g_mol_flt_b, (double *)g_mol_flt_a, (double)g_mol_flt_h0);
memset((void *)g_label, 0, sizeof(g_label));
}
/**---------------------------------------------------------------------
* Function : DetectorUpdateIMU
* Description : imu
*
* Date : 2022/09/23
*---------------------------------------------------------------------**/
void DetectorUpdateIMU(IMU_t* imu, PDR_t* pdr) {
BufferPush((Buffer_t *)&g_mol_buf[ACCE], (float)FilterFilter(&g_mol_flt[ACCE], GET_MOL(imu->acc.s)));
BufferPush((Buffer_t *)&g_mol_buf[GYRO], (float)FilterFilter(&g_mol_flt[GYRO], GET_MOL(imu->gyr.s)));
// g_tick_d 实际上是1.28s检测一次,不然检测的频率过高
if ((pDetector.tick % (int)(1.28 * IMU_SAMPLING_FREQUENCY)) == 0) {
// 检测用户的运动类型
int detectResult = DetectMotionType();
if (detectResult == DETECTOR_NO_ERROR && pDetector.lastType != pDetector.type) {
pdr->MotionType = pDetector.type;
pDetector.lastType = pDetector.type;
}
}
++pDetector.tick;
}
/**---------------------------------------------------------------------
* Function : fft_buffer
* Description : accfft
* Date : 2020/7/20 logzhan
*---------------------------------------------------------------------**/
static int fft_buffer(Complex_t *fft, Buffer_t *buffer) {
static float s_signal[1024] = { 0 };
float mean;
int index;
int i;
BufferMean(buffer, &mean);
for (i = 0, index = buffer->_bottom; index != buffer->_top; ++i, index = INC_PTR(buffer, index)) {
s_signal[i] = buffer->data[index] - mean; /*时序上255比0新*/
}
//序号i之后的长度里元素全部置为0
memset(s_signal + i, 0, (ARR_LEN(s_signal) - i) * sizeof(*s_signal));
if (0 == FFT_Fft(fft, s_signal, ARR_LEN(s_signal))) {
return DETECTOR_OUT_OF_MEMORY;
}
return DETECTOR_NO_ERROR;
}
/**----------------------------------------------------------------------
* Function : find_peaks
* Description : numberfrequencyamplitude
* Date : 2020/7/20 logzhan
*---------------------------------------------------------------------**/
static int find_peaks(float *frequency, float *amplitude, int number, Complex_t *fft,
int length, float cut_off_frequency, float min_threshold) {
float amp_2[2];
int min_ind;
int dir;
int n;
int i;
int j;
min_ind = 0;
memset(frequency, 0, number * sizeof(*frequency));
memset(amplitude, 0, number * sizeof(*amplitude));
dir = 1;
n = (int)(cut_off_frequency * length / IMU_SAMPLING_FREQUENCY);
amp_2[1] = fft[0].real * fft[0].real + fft[0].image * fft[0].image;
for (i = 1; i < n; ++i) {
amp_2[0] = amp_2[1];
amp_2[1] = fft[i].real * fft[i].real + fft[i].image * fft[i].image;
if (1 == dir) {
if (amp_2[1] < amp_2[0]) {
if (amp_2[0] > amplitude[min_ind]) {
amplitude[min_ind] = amp_2[0];
frequency[min_ind] = (float)i;
min_ind = 0;
for (j = 1; j < number; ++j) {
if (amplitude[min_ind] > amplitude[j]) {
min_ind = j;
}
}
}
dir = -1;
}
}
else {
if (amp_2[1] > amp_2[0]) {
dir = 1;
}
}
}
for (i = 0; i < number; ++i) {
amplitude[i] = (float)sqrt(amplitude[i]);
if (amplitude[i] < min_threshold) {
frequency[i] = 0;
amplitude[i] = 0;
}
else {
frequency[i] *= (float)IMU_SAMPLING_FREQUENCY / length;
}
}
return DETECTOR_NO_ERROR;
}
static void get_nonzero_weighted_mean(float *mean, BUFFER_SHORT *buffer, int length) {
int weight_sum;
int weight;
int index;
if (buffer->_bottom == buffer->_top) {
*mean = 0;
return;
}
*mean = 0;
weight_sum = 0;
index = buffer->_top;
for (weight = length; weight > 0 && index != buffer->_bottom; --weight) {
index = DEC_PTR(buffer, index);
if (0 != buffer->data[index]) {
*mean += weight * buffer->data[index];
weight_sum += weight;
}
}
if (0 != weight_sum) {
*mean /= weight_sum;
}
}
static void count_zeros(int *count, BUFFER_SHORT *buffer, int length) {
int index;
*count = 0;
for (index = (buffer->_top + buffer->length + 1 - length) % (buffer->length + 1); index != buffer->_top; index = INC_PTR(buffer, index)) {
if (0 == buffer->data[index]) {
++*count;
}
}
}
static void copy_buffer(BUFFER_SHORT *dst, BUFFER_SHORT *src, int length) {
int dst_cnt;
int src_cnt;
int dst_idx;
int src_idx;
BufferCount((Buffer_t *)dst, &dst_cnt);
BufferCount((Buffer_t *)src, &src_cnt);
length = length < dst_cnt ? length : dst_cnt;
length = length < src_cnt ? length : src_cnt;
dst_idx = (dst->_top + dst->length + 1 - length) % (dst->length + 1);
src_idx = (src->_top + src->length + 1 - length) % (src->length + 1);
while (dst_idx != dst->_top) {
dst->data[dst_idx] = src->data[src_idx];
dst_idx = INC_PTR(dst, dst_idx);
src_idx = INC_PTR(src, src_idx);
}
}
static void clear_buffer(BUFFER_SHORT *buffer) {
int index;
index = buffer->_bottom;
while (index != buffer->_top) {
buffer->data[index] = 0;
index = INC_PTR(buffer, index);
}
}
static int track_frequency(BUFFER_SHORT *frequency_buffer, BUFFER_SHORT *amplitude_buffer, BUFFER_SHORT *temp_buffer,
float *frequency, float *amplitude, int number) {
static float mean[3];
static float cost[3 * 3];
static int assignment[3];
float distance;
float prev;
int i;
int j;
int transform_flag;
int count;
/* 0.detect argument */
if (number > ARR_LEN(mean)) {
return DETECTOR_OUT_OF_MEMORY;
}
/* 1.caculate main mean */
for (i = 0; i < number; ++i) {
get_nonzero_weighted_mean(&mean[i], &frequency_buffer[i], TMP_BUF_LEN);
}
/* 2.caculate main cost */
for (i = 0; i < number; ++i) {
for (j = 0; j < number; ++j) {
distance = (float)fabs(mean[i] - frequency[j]);
if (0 == mean[i] || 0 == frequency[j] || distance > FRQ_RAT) {
COST(i, j) = 1e3;
}
else {
COST(i, j) = distance;
}
}
}
/* 3.get main assignment */
MUNKRES_get_assignment(assignment, cost, number, number);
/* 4.push main frequency and main amplitude buffer */
for (i = 0; i < number; ++i) {
if (1e3 == COST(i, assignment[i])) {
BufferPush((Buffer_t *)&frequency_buffer[i], 0);
BufferPush((Buffer_t *)&amplitude_buffer[i], 0);
}
else {
BufferPush((Buffer_t *)&frequency_buffer[i], frequency[assignment[i]]);
BufferPush((Buffer_t *)&amplitude_buffer[i], amplitude[assignment[i]]);
frequency[assignment[i]] = 0;
amplitude[assignment[i]] = 0;
}
}
/* 5.caculate temp mean */
for (i = 0; i < number; ++i) {
get_nonzero_weighted_mean(&mean[i], &temp_buffer[i], TMP_BUF_LEN);
}
/* 6.caculate temp cost */
for (i = 0; i < number; ++i) {
for (j = 0; j < number; ++j) {
if (0 == frequency[j]) {
COST(i, j) = 1e3;
}
else if (0 == mean[i]) {
COST(i, j) = FRQ_RAT;
}
else {
COST(i, j) = (float)fabs(mean[i] - frequency[j]);
}
}
}
/* 7.get main assignment */
MUNKRES_get_assignment(assignment, cost, number, number);
/* 8.push temp buffer */
for (i = 0; i < number; ++i) {
BufferPush((Buffer_t *)&temp_buffer[i], frequency[assignment[i]]);
}
/* 9.caculate temp mean */
for (i = 0; i < number; ++i) {
get_nonzero_weighted_mean(&mean[i], &temp_buffer[i], TMP_BUF_LEN);
}
/* 10.check temp buffer */
transform_flag = 0;
for (i = 0; i < number; ++i) {
prev = temp_buffer[i].data[temp_buffer[i]._bottom];
for (j = temp_buffer[i]._bottom; j != temp_buffer[i]._top; j = INC_PTR(&temp_buffer[i], j)) {
if (0 == temp_buffer[i].data[j] || fabs(temp_buffer[i].data[j] - prev) > FRQ_RAT) {
break;
}
prev = temp_buffer[i].data[j];
}
if (j == temp_buffer[i]._top) {
frequency[i] = mean[i];
transform_flag = 1;
}
else {
frequency[i] = 0;
}
}
if (transform_flag) {
/* 11.caculate main mean */
for (i = 0; i < number; ++i) {
get_nonzero_weighted_mean(&mean[i], &frequency_buffer[i], TMP_BUF_LEN);
}
/* 12.caculate main cost */
for (i = 0; i < number; ++i) {
count_zeros(&count, &frequency_buffer[i], TMP_BUF_LEN);
for (j = 0; j < number; ++j) {
if (0 == frequency[j]) {
COST(i, j) = 1e3;
}
else if (0 == mean[i]) {
COST(i, j) = -5;
}
else if (count >= 3) {
// COST(i, j) = 3 - count;
COST(i, j) = (float)(-5 + fabs(mean[i] - frequency[j]));
}
else {
COST(i, j) = (float)fabs(mean[i] - frequency[j]);
}
}
}
/* 13.get main assignment */
MUNKRES_get_assignment(assignment, cost, number, number);
/* 14.push main frequency and main amplitude buffer */
for (i = 0; i < number; ++i) {
if (0 != frequency[assignment[i]]) {
// Buffer_push(&frequency_buffer[i], frequency[assignment[i]]);
// Buffer_push(&amplitude_buffer[i], 0);
copy_buffer(&frequency_buffer[i], &temp_buffer[assignment[i]], TMP_BUF_LEN);
clear_buffer(&temp_buffer[assignment[i]]);
}
}
}
return DETECTOR_NO_ERROR;
}
static void get_nonzero_mean(float *mean, BUFFER_SHORT *buffer, int length) {
int count;
int index;
count = (buffer->_top - buffer->_bottom + buffer->length + 1) % (buffer->length + 1);
length = count < length ? count : length;
*mean = 0;
count = 0;
for (index = (buffer->_top + buffer->length + 1 - length) % (buffer->length + 1); index != buffer->_top; index = INC_PTR(buffer, index)) {
if (0 != buffer->data[index]) {
*mean += buffer->data[index];
++count;
}
}
if (count >= 0.5 * length) {
*mean /= count;
}
}
static void get_nonzero_std(float *std, BUFFER_SHORT *buffer, int length) {
float mean;
float delta;
int count;
int index;
count = (buffer->_top - buffer->_bottom + buffer->length + 1) % (buffer->length + 1);
length = count < length ? count : length;
mean = 0;
count = 0;
for (index = (buffer->_top + buffer->length + 1 - length) % (buffer->length + 1); index != buffer->_top; index = INC_PTR(buffer, index)) {
if (0 != buffer->data[index]) {
mean += buffer->data[index];
++count;
}
}
if (0 != count) {
mean /= count;
}
*std = 0;
for (index = (buffer->_top + buffer->length + 1 - length) % (buffer->length + 1); index != buffer->_top; index = INC_PTR(buffer, index)) {
if (0 != buffer->data[index]) {
delta = buffer->data[index] - mean;
*std += delta * delta;
}
}
if (count >= 0.5 * length) {
*std = (float)sqrt(*std / count);
}
else {
*std = -1; // default;
}
}
/**---------------------------------------------------------------------
* Function : get_feature
* Description :
* Date : 2020/7/20 logzhan
*---------------------------------------------------------------------**/
static void get_feature(float *feature, int length) {
int i;
int j;
float temp;
BufferMean((Buffer_t *)&g_mol_buf[ACCE], &feature[0]);
BufferStd( (Buffer_t *)&g_mol_buf[ACCE], &feature[1]);
BufferStd( (Buffer_t *)&g_mol_buf[GYRO], &feature[2]);
get_nonzero_std( &feature[3] , &g_acc_frq_buf[0], length); if (feature[3] < 0) feature[3] = 10;
get_nonzero_std( &feature[4] , &g_acc_frq_buf[1], length); if (feature[4] < 0) feature[4] = 10;
get_nonzero_std( &feature[5] , &g_acc_frq_buf[2], length); if (feature[5] < 0) feature[5] = 10;
get_nonzero_mean(&feature[6] , &g_acc_amp_buf[0], length);
get_nonzero_mean(&feature[7] , &g_acc_amp_buf[1], length);
get_nonzero_mean(&feature[8] , &g_acc_amp_buf[2], length);
get_nonzero_std( &feature[9] , &g_gyr_frq_buf[0], length); if (feature[9] < 0) feature[9] = 10;
get_nonzero_std( &feature[10], &g_gyr_frq_buf[1], length); if (feature[10] < 0) feature[10] = 10;
get_nonzero_std( &feature[11], &g_gyr_frq_buf[2], length); if (feature[11] < 0) feature[11] = 10;
get_nonzero_mean(&feature[12], &g_gyr_amp_buf[0], length);
get_nonzero_mean(&feature[13], &g_gyr_amp_buf[1], length);
get_nonzero_mean(&feature[14], &g_gyr_amp_buf[2], length);
/* sort by std - bubble sort */
for (i = 0; i < 2; ++i) {
for (j = 0; j < 2 - i; ++j) {
if (feature[3 + j] > feature[3 + j + 1]) {
temp = feature[3 + j];
feature[3 + j] = feature[3 + j + 1];
feature[3 + j + 1] = temp;
temp = feature[6 + j];
feature[6 + j] = feature[6 + j + 1];
feature[6 + j + 1] = temp;
}
}
}
for (i = 0; i < 2; ++i) {
for (j = 0; j < 2 - i; ++j) {
if (feature[9 + j] > feature[9 + j + 1]) {
temp = feature[9 + j];
feature[9 + j] = feature[9 + j + 1];
feature[9 + j + 1] = temp;
temp = feature[12 + j];
feature[12 + j] = feature[12 + j + 1];
feature[12 + j + 1] = temp;
}
}
}
}
/**---------------------------------------------------------------------
* Function : predict
* Description :
* Date : 2020/7/20 logzhan
*---------------------------------------------------------------------**/
int pdr_detectorPredict(float *feature)
{
if (feature[1] < 0.932921) {
return DETECTOR_TYPE_STATIC;
}else if ((feature[3] < 0.10) + (feature[4] < 0.10) + (feature[5] < 0.10) > 0) {
if (feature[12] < 49.9795) {
if (feature[0] < 10.7220) {
return DETECTOR_TYPE_HANDHELD;
}
else {
return DETECTOR_TYPE_SWINGING;
}
}
else {
if (feature[2] < 0.312002) {
return DETECTOR_TYPE_HANDHELD;
}
else {
return DETECTOR_TYPE_SWINGING;
}
}
}
return DETECTOR_TYPE_IRREGULAR;
}
/**---------------------------------------------------------------------
* Function : debounce
* Description : lengthlabel
* Date : 2020/7/20 logzhan
*---------------------------------------------------------------------**/
static int debounce(int *label, int length) {
int cnt[4];
int def;
int i;
memset(cnt, 0, sizeof(cnt));
for (i = 0; i < length; ++i) {
++cnt[label[i]];
}
def = 0;
for (i = 0; i < ARR_LEN(cnt); ++i) {
if (cnt[i] > length * 3 / 4) {
return i;
}
if (cnt[i] > 0) {
def = i;
}
}
return def;
}
/**---------------------------------------------------------------------
* Function : DetectMotionType
* Description : pdr
* Date : 2022/09/23 logzhan
*---------------------------------------------------------------------**/
int DetectMotionType() {
static Complex_t s_fft[1024] = { {0.0} };
static float s_feature[15] = { 0 };
float frq[3];
float amp[3];
int ret;
int i;
// 分析加速度计
if (DETECTOR_NO_ERROR != (ret = fft_buffer(s_fft, (Buffer_t *)&g_mol_buf[ACCE]))) {
return ret;
}
if (DETECTOR_NO_ERROR != (ret = find_peaks(frq, amp, 3, s_fft, 1024, 5, 0))) {
return ret;
}
if (DETECTOR_NO_ERROR != (ret = track_frequency(g_acc_frq_buf, g_acc_amp_buf, g_acc_tmp_buf, frq, amp, 3))) {
return ret;
}
// 分析陀螺仪
if (DETECTOR_NO_ERROR != (ret = fft_buffer(s_fft, (Buffer_t *)&g_mol_buf[GYRO]))) {
return ret;
}
if (DETECTOR_NO_ERROR != (ret = find_peaks(frq, amp, 3, s_fft, 1024, 5, (DETECTOR_TYPE_SWINGING == pDetector.type ||
DETECTOR_TYPE_HANDHELD == pDetector.type) ? 20.0f : 100.0f))) {
return ret;
}
if (DETECTOR_NO_ERROR != (ret = track_frequency(g_gyr_frq_buf, g_gyr_amp_buf, g_gyr_tmp_buf, frq, amp, 3))) {
return ret;
}
get_feature(s_feature, 5);
pDetector.type = pdr_detectorPredict(s_feature);
/* debounce */
for (i = 0; i < ARR_LEN(g_label) - 1; ++i) {
g_label[i] = g_label[i + 1];
}
g_label[i] = pDetector.type;
pDetector.type = debounce(g_label, ARR_LEN(g_label));
return DETECTOR_NO_ERROR;
}
/**----------------------------------------------------------------------
* Function : DetUserStatic
* Description : ,
*
* Date : 2022/10/15 logzhan
*---------------------------------------------------------------------**/
int DetUserStatic(PDR_t* g_pdr, GNSS_t* pgnss, unsigned long delSteps) {
if (pgnss->vel != -1 && pgnss->vel < 1 && (delSteps == 0 &&
g_pdr->motionFreq == 0.0)) {
return PDR_TRUE;
}
return PDR_FALSE;
}
/**----------------------------------------------------------------------
* Function : DetectCarMode
* Description :
* Input : pgnssGPS
g_pdrPDR
delSteps
time
* Output : int
* Date : 2021/01/28 logzhan
*---------------------------------------------------------------------**/
int DetectCarMode(GNSS_t* gnss, PDR_t* pdr, unsigned long delSteps, int* time)
{
if ((gnss->vel > 10 && delSteps == 0) ||
(delSteps == 0 && pdr->motionFreq == 0.0 && gnss->vel > 3 && gnss->error < 30))
{
(*time)++;
}
else {
*time = 0;
}
if (*time > 5) {
return PDR_TRUE;
}
return PDR_FALSE;
}
/**----------------------------------------------------------------------
* Function : DetectPdrToReset
* Description : PDRPDR
* PDRGPS
* Date : 2022/10/15 logzhan
*---------------------------------------------------------------------**/
int DetectPdrToReset(double pdr_angle, int* gpsCnt, ulong deltsteps, PDR_t* pdr) {
if ((pdr_angle < 0 && deltsteps > 0) || (deltsteps > 0 && (pdr->motionFreq == 0))) {
(*gpsCnt)++;
}
else {
*gpsCnt = 0;
}
return (*gpsCnt > 6);
}

View File

@ -0,0 +1,116 @@
/* Header File Including ------------------------------------------------------------------------ */
#include "Fft.h"
/* Macro Declaration ---------------------------------------------------------------------------- */
#define FFT_MCB_TYPE_OMEGA_AND_POSITION 0x01
#define SWAP(type, a, b) { type t = a; a = b; b = t; }
/* Structure Declaration ------------------------------------------------------------------------ */
typedef struct FFT_MCB {
uint8_t type;
uint32_t parameter[4];
struct FFT_MCB *next;
struct FFT_MCB *prev;
uint8_t buffer[10240];
} FFT_MCB;
/* Global Variable Definition ------------------------------------------------------------------- */
static FFT_MCB gMemery;
/* Function Definition -------------------------------------------------------------------------- */
/**----------------------------------------------------------------------
* Function : FftInit
* Description :
* Date : 2022/10/15 logzhan
*---------------------------------------------------------------------**/
static int FftInit(int length) {
Complex_t *omega;
uint16_t *position;
int bitLength;
int i;
int shift;
int j;
if (length * (sizeof(Complex_t) + sizeof(uint16_t)) > sizeof(gMemery.buffer)) {
return 0;
}
if (FFT_MCB_TYPE_OMEGA_AND_POSITION == gMemery.type && length == (int)gMemery.parameter[0]) {
return length;
}
gMemery.type = FFT_MCB_TYPE_OMEGA_AND_POSITION;
gMemery.parameter[0] = length;
omega = (Complex_t *) gMemery.buffer;
for (i = 0; i < length; ++i) {
omega[i].real = (float)cos(-2 * M_PI * i / length);
omega[i].image = (float)sin(-2 * M_PI * i / length);
}
position = (uint16_t *)(omega + length);
for (bitLength = 0, i = length; (i >> bitLength); ++bitLength);
for (i = 0; i < length; ++i) {
j = 0;
for (shift = 0; shift < bitLength - 1; ++shift) {
if((i >> shift) & 1) {
j |= (1 << (bitLength - shift - 2));
}
}
position[i] = (uint16_t)j;
}
return length;
}
int FFT_Dft(Complex_t *dft, float *signal, int length) {
if (0 == FftInit(length)) return 0;
for (int k = 0; k < length; ++k) {
dft[k].real = 0;
dft[k].image = 0;
for(int i = 0; i < length; ++i) {
int ik = i * k % length;
dft[k].real += signal[i] * ((Complex_t *)gMemery.buffer)[ik].real;
dft[k].image += signal[i] * ((Complex_t *)gMemery.buffer)[ik].image;
}
}
return length;
}
int FFT_Fft(Complex_t *fft, float *signal, int length) {
int i,l,j,m;
uint16_t *position;
Complex_t *omega;
//正常情况下length正常、没溢出就不会进入return0
if (length <= 0 || 0 != (length & (length - 1)) || 0 == FftInit(length)) {
return 0;
}
for (i = 0; i < length; ++i) {
fft[i].real = signal[i];
fft[i].image = 0;
}
position = (uint16_t *)(gMemery.buffer + length * sizeof(Complex_t));
for (i = 0; i < length; ++i) {
if (i < position[i]) {
SWAP(Complex_t, fft[i], fft[position[i]]);
}
}
omega = (Complex_t *)gMemery.buffer;
for (l = 2, m = 1; l <= length; l <<= 1, m <<= 1) {
for (i = 0; i < length; i += l) {
for (j = 0; j < m; ++j) {
Complex_t delta = ComplexMul(omega[length / l * j], fft[i + m + j]);
fft[i + m + j] = ComplexSub(fft[i + j], delta);
fft[i + j] = ComplexAdd(fft[i + j], delta);
}
}
}
return length;
}

View File

@ -0,0 +1,77 @@
/******************** (C) COPYRIGHT 2022 Geek************************************
* File Name : Filter.c
* Current Version : V2.0
* Author : logzhan
* Date of Issued : 2022.10.15
* Comments : PDR
********************************************************************************/
/* Header File Including ------------------------------------------------------*/
#include "stdio.h"
#include "Filter.h"
/* Function Definition --------------------------------------------------------*/
/**---------------------------------------------------------------------
* Function : FilterReset
* Description :
* Date : 2022/10/15 logzhan
*---------------------------------------------------------------------**/
void FilterReset(Filter_t *f) {
f->reset = 1;
}
/**---------------------------------------------------------------------
* Function : FilterSetCoef
* Description :
* Input : order coefficient array length, not filter order
* *b b coefficient
* *a a coefficient
* H0 dc signal gain
* Date : 2022/10/15 logzhan
*---------------------------------------------------------------------**/
void FilterSetCoef(Filter_t *f, int order, double *b, double *a, double H0) {
for (int i = 0; i < order; ++i) {
f->b[i] = b[i];
f->a[i] = a[i];
}
f->order = order;
f->H0 = H0;
f->reset = 1;
}
/**---------------------------------------------------------------------
* Function : FilterFilter
* Description :
* Date : 2022/10/15 logzhan
*---------------------------------------------------------------------**/
double FilterFilter(Filter_t *f, double x) {
if (f->order < 1) {
printf("fileter order is set to incorrect order, pls chk \
your code!\n");
return 0;
}
double y = 0.0;
if (f->reset) {
for (int i = 0; i < f->order; ++i) {
f->yout[i] = f->H0 * x;
f->xin[i] = x;
}
y = f->yout[f->order - 1];
f->reset = 0;
}
// push x and y
for (int i = 0; i < f->order - 1; ++i) {
f->xin[i] = f->xin[i + 1];
f->yout[i] = f->yout[i + 1];
}
f->xin[f->order - 1] = x;
// filter
y = f->b[0] * f->xin[f->order - 1];
for (int i = 1; i < f->order; ++i) {
y += f->b[i] * f->xin[f->order - 1 - i] - f->a[i] * f->yout[f->order - 1 - i];
}
f->yout[f->order - 1] = y;
return y / f->H0;
}

View File

@ -0,0 +1,211 @@
/******************** (C) COPYRIGHT 2022 Geek************************************
* File Name : Interface.c
* Current Version : V2.0
* Author : logzhan
* Date of Issued : 2022.10.15
* Comments : PDR
********************************************************************************/
/* Header File Including -----------------------------------------------------*/
#include <stdio.h>
#include <math.h>
#include <string.h>
#include "pdr_api.h"
#include "PDRBase.h"
#include "Pedometer.h"
#include "Location.h"
#include "parseData.h"
#include "scene_recognition.h"
/* Global Variable Definition ------------------------------------------------*/
const char* Pedometer_Version = "2.0";
Sensor_t SensorDataHist[IMU_LAST_COUNT] = {{0}};
LatLng_t llaLast = { 0 };
Nmea_t Nmea;
IMU_t Imu;
/* Extern Variable Definition ------------------------------------------------*/
extern EKFPara_t EkfPara;
extern AHRS_t Ahrs;
extern GNSS_t pgnss;
/* Function Declaration ------------------------------------------------------*/
/**---------------------------------------------------------------------
* Function : RMC_Init
* Description : RMC
* Date : 2022/09/16 logzhan
*---------------------------------------------------------------------**/
void RMC_Init(NmeaRMC_t * rmc)
{
rmc->type = SENSOR_MIN;
rmc->rmc_utc = ITEM_INVALID;
rmc->status = POSITIONING_N;
rmc->latitude = ITEM_INVALID;
rmc->rmc_latitude_ns = LATITUDE_N;
rmc->longitudinal = ITEM_INVALID;
rmc->longitudinal_ew = LATITUDE_N;
rmc->speed = ITEM_INVALID;
rmc->cog = ITEM_INVALID;
rmc->utc_ddmmyy = ITEM_INVALID;
rmc->magnetic = ITEM_INVALID;
rmc->mag_h = MAG_E;
rmc->mode = MODE_A;
rmc->time = ITEM_INVALID;
rmc->update = UN_UPDATE;
memset(rmc->rmc_check_sum, 0, sizeof(rmc->rmc_check_sum));
}
/**---------------------------------------------------------------------
* Function : NmeaFlag_Init
* Description : GPSNMEA
* Date : 2020/7/3 logzhan
*---------------------------------------------------------------------**/
void NmeaFlag_Init(Nmea_t * ln)
{
ln->gga.update = 0;
for (char i = 0; i < 3; i++) {
ln->gsa[i].update = UN_UPDATE;
ln->gsv[i].update = UN_UPDATE;
}
ln->minTime = 0;
ln->maxTime = 0;
ln->update = UN_UPDATE;
RMC_Init(&ln->rmc[0]);
RMC_Init(&ln->rmc[1]);
ln->accuracy.time = ITEM_INVALID;
ln->accuracy.update = UN_UPDATE;
ln->accuracy.status = ITEM_INVALID;
ln->accuracy.err = ITEM_INVALID;
}
/**---------------------------------------------------------------------
* Function : clearNmeaFlg
* Description : Nmea
* Date : 2020/7/4 logzhan
*---------------------------------------------------------------------**/
void ClearNmeaFlg(Nmea_t * ln){
NmeaFlag_Init(ln);
}
/**---------------------------------------------------------------------
* Function : Algorithm_Init
* Description : PDRPDR
*
* Date : 2022/10/15 logzhan
*---------------------------------------------------------------------**/
void Algorithm_Init(void) {
// 导航相关初始化
PDR_Init();
// 计步器初始化
Pedometer_Init();
// 初始化sensor历史缓存
memset(SensorDataHist, 0, sizeof(SensorDataHist));
memset(&Nmea, 0, sizeof(Nmea));
memset(&Imu, 0, sizeof(Imu));
}
/**---------------------------------------------------------------------
* Function : ParseDataAndUpdate
* Description :
* Date : 2022/10/16 logzhan
*---------------------------------------------------------------------**/
int ParseDataAndUpdate(char* line, LctFs_t* LocFusion)
{
ParseGnssInsData(line, &Imu, &Nmea);
// 给定Imu和Nmea结构体返回融合位置
return PDRLocationMainLoop(&Imu, &Nmea, LocFusion);
}
/**---------------------------------------------------------------------
* Function : PDRLocationMainLoop
* Description : PDR
*
* Date : 2020/07/03 logzhan
* 2020/02/02 logzhan :
*---------------------------------------------------------------------**/
int PDRLocationMainLoop(IMU_t *imu, Nmea_t *nmea, LctFs_t *LocFusion) {
int type = 0;
if (imu->gyr.update) {
// 如果陀螺仪更新则采用惯性传感器计算
InsLocationUpdate(imu,&EkfPara);
imu->gyr.update = UN_UPDATE;
}
// 如果GPS不更新返回
if (!nmea->update)return TYPE_FIX_NONE;
// 写GPS相关LOG信息
SaveGnssInfo(nmea, LocFusion, NULL);
// 有GPS则采用GPS融合定位
int flag = GnssInsFusionLocation(nmea, &EkfPara, LocFusion);
if (flag != TYPE_FIX_NONE) {
// 如果是开车这种直接输出GPS不进行平滑处理
LocFusion->latitude = R2D(LocFusion->latitude);
LocFusion->longitudinal = R2D(LocFusion->longitudinal);
LocFusion->last_lat = LocFusion->latitude;
LocFusion->last_lon = LocFusion->longitudinal;
type = 1;
}else if (LocFusion->last_lat != 0.0 && LocFusion->last_lon != 0.0) {
LocFusion->latitude = LocFusion->last_lat;
LocFusion->longitudinal = LocFusion->last_lon;
type = 1;
}
ClearNmeaFlg(nmea);
return type;
}
/**---------------------------------------------------------------------
* Function : SaveGnssInfo
* Description : GPS
* Date : 2022/10/16 logzhan
*---------------------------------------------------------------------**/
void SaveGnssInfo(Nmea_t* nmea, LctFs_t* result, FILE* fp_gps)
{
NmeaRMC_t rmc = nmea->rmc[1];
// 选取更新时间的rmc
if (nmea->rmc[0].time > nmea->rmc[1].time) {
rmc = nmea->rmc[0];
}
if (rmc.update && (rmc.status == POSITIONING_Y)) {
char str[256];
memset(str, 0, sizeof(str));
float accuracy = -1.0f;
if (fabs(rmc.time - nmea->accuracy.time) < 500){
accuracy = nmea->accuracy.err;
}
sprintf(str, "%f,%.10f,%d,%.10f,%d,%.10f,%f,%f", rmc.time, rmc.latitude,
rmc.rmc_latitude_ns,rmc.longitudinal, rmc.longitudinal_ew, rmc.cog, accuracy,
rmc.speed);
WriteCsvStr(fp_gps, str);
result->gpsLat = rmc.latitude;
result->gpsLon = rmc.longitudinal;
}
}
/**----------------------------------------------------------------------
* Function : GetPDRVersion
* Description : pdr
* Date : 2022/10/15 logzhan
*---------------------------------------------------------------------**/
const char* GetPDRVersion(void){
return Pedometer_Version;
}
/**----------------------------------------------------------------------
* Function : pdr_closeAlgorithm
* Description : PDR,
* Date : 2020/8/3 logzhan
*---------------------------------------------------------------------**/
void Algorithm_DeInit() {
scene_recognition_destroy();
}

View File

@ -0,0 +1,267 @@
/******************** (C) COPYRIGHT 2020 Geek************************************
* File Name : Kalman.c
* Current Version : V2.0
* Author : logzhan
* Date of Issued : 2022.10.15
* Comments : PDR
********************************************************************************/
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <malloc.h>
#include "PDRBase.h"
#include "Kalman.h"
#include "Location.h"
#include "Matrix.h"
#include "Utils.h"
// 扩展卡尔曼向量缓存
static double EkfVecBuf[5][N] = { {0.0} };
// 扩展卡尔曼矩阵缓存
static double EkfMatBuf[7][N][N] = { { {0.0} } };
/**----------------------------------------------------------------------
* Function : KalmanFilter_Init
* Description :
* Date : 2022/09/16 logzhan
*---------------------------------------------------------------------**/
void EKF_Init(void)
{
memset(EkfMatBuf, 0, sizeof(double) * 7 * N * N);
memset(EkfVecBuf, 0, sizeof(double) * 5 * N);
}
/**----------------------------------------------------------------------
* Function : EKFStatePredict
* Description : pdr
* Date : 2022/10/15 logzhan
*---------------------------------------------------------------------**/
void EKFStatePredict(EKFPara_t *ekf, double stepLen, PDR_t* pdr, int step) {
double angle = pdr->deltaHeading + ekf->pXk[3];
if(step == 0){
ekf->pXk[3] = angle;
return;
}
double(*Phi)[N] = (double(*)[N]) & (EkfMatBuf[0][0][0]);
double(*pvec1)[N] = (double(*)[N]) & (EkfMatBuf[1][0][0]);
double(*pvec2)[N] = (double(*)[N]) & (EkfMatBuf[2][0][0]);
memset(EkfMatBuf, 0, sizeof(double) * 7 * N * N);
// xk+1 = xk + step * cos(angle) PDR位置更新方程
// yk+1 = yk + step * sin(angle) PDR位置更新方程
// sk+1 = sk 步长和上一次相同
// ak+1 = ak * (angle / ak) 或 ak+1 = ak
Phi[0][0] = 1; Phi[1][0] = 0; Phi[2][0] = 0; Phi[3][0] = 0;
Phi[0][1] = 0; Phi[1][1] = 1; Phi[2][1] = 0; Phi[3][1] = 0;
Phi[0][2] = cos(angle); Phi[1][2] = sin(angle); Phi[2][2] = 1; Phi[3][2] = 0;
Phi[0][3] = 0; Phi[1][3] = 0; Phi[2][3] = 0; Phi[3][3] = 1;
for (uchar i = 0; i < step; i++) {
// logzhan 21/02/06:
// phi[3][3]是为让kf的预测每次都是最新更新值, 如果phi[3][3]每次都是1可能在惯性
// 导航更新过程中偏航角的预测是固定的实时性没有那么好下面if判断可以在一定程度
// 让预测的值更新,但是效果暂时没有感觉出明显的好
if (fabs(ekf->pXk[3]) > 0.000001 &&
fabs(angle / ekf->pXk[3]) < 3)
{
Phi[3][3] = angle / ekf->pXk[3];
}
// 卡尔曼状态更新方程
// pXk = phi * pXk
VecMatMultiply(ekf->pXk, Phi, ekf->pXk);
// 卡尔曼更新协方差矩阵 : Pk = FPFt + Q
MatrixMultiply(Phi, ekf->pPk, pvec1); // F*P
MatrixTrans(Phi, pvec2); // Ft
MatrixMultiply(pvec1, pvec2, pvec1); // F*P*Ft
MatrixAdd(pvec1, ekf->Q, ekf->pPk); // F*P*Ft + Q
}
}
/**----------------------------------------------------------------------
* Function : EKFStateUpdate
* Description :
* Date : 2020/7/22 logzhan
*---------------------------------------------------------------------**/
void EKFStateUpdate(EKFPara_t *kf, GNSS_t *pgnss, Classifer_t *sys, PDR_t *pdr,
int scene_type) {
double lambda = 0;
// NxN矩阵定义
double(*H)[N] = (double(*)[N])&(EkfMatBuf[0][0][0]);
double(*I)[N] = (double(*)[N])&(EkfMatBuf[1][0][0]);
double(*pvec1)[N] = (double(*)[N])&(EkfMatBuf[2][0][0]);
double(*Ht)[N] = (double(*)[N])&(EkfMatBuf[3][0][0]);
double(*pvec3)[N] = (double(*)[N])&(EkfMatBuf[4][0][0]);
double(*pvec4)[N] = (double(*)[N])&(EkfMatBuf[5][0][0]);
double(*pv3)[N] = (double(*)[N])&(EkfMatBuf[6][0][0]);
memset(EkfMatBuf, 0, sizeof(double) * 7 * N * N);
memset(EkfVecBuf, 0, sizeof(double) * 5 * N);
// Nx1向量定义
double(*pvec5) = &(EkfVecBuf[1][0]);
double(*pvec6) = &(EkfVecBuf[2][0]);
double(*pv1) = &(EkfVecBuf[3][0]);
double(*pv2) = &(EkfVecBuf[4][0]);
// 创建单位矩阵
for (char i = 0; i < 4; i++) {
H[i][i] = 1;
I[i][i] = 1;
}
double* z = &(EkfVecBuf[0][0]);
// 获取观测向量
z[0] = pgnss->xNed; // 北向位置
z[1] = pgnss->yNed; // 东向位置
z[2] = 0.5; // 步长默认0.5
// 这个if条件实际是使用GPS的位置变化量和步数变化量估计步长, 这部分代码还没
// 调好,实际类似于步长不变
//if (pgnss->error > 0 && pgnss->error < 3.8 && pgnss->HDOP <= 0.4 &&
// g_pdr->deltaStepsPerGps != 0 && g_pdr->deltaStepsPerGps < 5) {
// // 利用GPS速度和步频估计步长
// //if (g_pdr->motionFreq > 2.5 && (sys->type == 1)) {
// //
// // //printf("z[2] = %f\n", z[2]);
// //}
// z[2] = pgnss->vel * 0.514 / (g_pdr->deltaStepsPerGps);
//}else {
// z[2] = kf->pXk[2];
//}
z[3] = pgnss->yaw * PI / 180; // 观测的航向角为GPS的航向角
// 计算 K = K = PHt / (R + H*P*H^T)
MatrixTrans(H, Ht); // 计算Ht
MatrixMultiply(H, kf->pPk, pvec1); // 计算HP
MatrixMultiply(pvec1, Ht, pvec3); // pvec3 = H*P*H^T
MatrixAdd(pvec3, kf->R, pvec4); // pvec4 = R + H*P*H^T
MatrixInverse(pvec4, pvec1); // 计算 1 / (R + H*P*H^T)
for (char i = 0; i < N; i++) {
for (uchar j = 0; j < N; j++) {
pv3[i][j] = pvec3[i][j];
}
}
MatrixMultiply(kf->pPk, Ht, pvec3); // 计算PHt
MatrixMultiply(pvec3, pvec1, kf->Kk); // 计算增益K = PHt / (R + H*P*H^T)
VecMatMultiply(kf->pXk, H, pvec5); // pvec5 = Hx'
VectorSub(z, pvec5, pvec6); // pvec6 = Z - Hx'
modAngle(&pvec6[3], -PI, PI);
for (char i = 0; i < N; i++) {
pv1[i] = pvec6[i];
}
VecMatMultiply(pvec6, kf->Kk, pvec5); // pvec5 = K*( z - Hx')
// Get the optimally updated state estimation
VectorAdd(kf->pXk, pvec5, kf->Xk);
// ---- prepare the matrix for updated estimate covariance ------
// pvec1 = K*H
MatrixMultiply(kf->Kk, H, pvec1);
// pvec2 = (I - K*H)
MatrixSub(I, pvec1, Ht);
// pvec3 = (I - K*H)*P
MatrixMultiply(Ht, kf->pPk, pvec3);
// pvec4 = (I- K*H)^T
MatrixTrans(Ht, pvec4);
// pvec1 = (I - K*H)*P*(I- K*H)^T
MatrixMultiply(pvec3, pvec4, pvec1);
// pvec2 = K*R
MatrixMultiply(kf->Kk, kf->R, Ht);
// pvec3 = K^T
MatrixTrans(kf->Kk, pvec3);
// pvec4 = K*R*K^T
MatrixMultiply(Ht, pvec3, pvec4);
// Get the updated estimate covariance: P' = (I - K*H)*P*(I- K*H)^T + K*R*K^T
MatrixAdd(pvec1, pvec4, kf->Pk);
// pv2 = (z - Hx')*( H*P*H^T )
VecMatMultiply(pv1, pv3, pv2);
// inner product the pre-fit residual and the transitioned residual: lamda = (z - Hx')*( H*P*H^T ) .* (z-Hx')
// Calculate the difference between original differenc and the transitioned,
// if the value is close to zero, it shows that there is a big gap in the
// oprimization. Thus, we believe our PDR algorithm
for (char i = 0; i < N; i++) {
lambda += pv2[i] * pv1[i];
}
kf->Lambda = lambda;
kf->pLat = pgnss->lat;
kf->pLon = pgnss->lon;
if (lambda >= 200)return;
for (char i = 0; i < N; i++) {
kf->Xk[i] = kf->pXk[i];
for (int j = 0; j < N; j++) {
kf->Pk[i][j] = kf->pPk[i][j];
}
}
}
/**----------------------------------------------------------------------
* Function : EKFCalQRMatrix
* Description : GPSq
* rGNSSGPS
*
* Date : 2022/09/19 logzhan
*---------------------------------------------------------------------**/
void EKFCalQRMatrix(Nmea_t *nmea, PDR_t *pdr, Classifer_t *sys,
EKFPara_t *kf) {
if (pdr->MotionType != PDR_MOTION_TYPE_HANDHELD &&
pdr->MotionType != PDR_MOTION_TYPE_STATIC) {
kf->Q[0][0] = 25; // PDR预测位置噪声
kf->Q[1][1] = 25; // PDR预测位置噪声
kf->Q[2][2] = 1; // PDR步长噪声
kf->Q[3][3] = 100; // PDR方向噪声
kf->R[0][0] = 50; // GPS观测位置噪声
kf->R[1][1] = 50; // GPS观测位置噪声
kf->R[2][2] = 0.1; // GPS步长噪声
kf->R[3][3] = 50; // GPS方向噪声
return;
}
kf->Q[0][0] = 0.1; // PDR预测位置噪声
kf->Q[1][1] = 0.1; // PDR预测位置噪声
kf->Q[2][2] = 1; // PDR步长噪声
kf->Q[3][3] = 1; // PDR方向噪声
kf->R[0][0] = 100; // GPS预测位置噪声
kf->R[1][1] = 100; // GPS预测位置噪声
kf->R[2][2] = 0.1; // GPS步长噪声
kf->R[3][3] = 1000; // GPS方向噪声
if (nmea->accuracy.err > 0 &&
nmea->accuracy.err < 3.80 &&
nmea->gga.hdop <= 0.4)
{
kf->R[0][0] = 50; // GPS观测位置噪声
kf->R[1][1] = 50; // GPS观测位置噪声
kf->R[2][2] = 0.1; // GPS步长噪声
kf->R[3][3] = 50; // GPS方向噪声
}
if (fabs(R2D((pdr->GpsHeading - pdr->LastGpsHeading))) > 50 ||
pdr->GpsSpeed < 0.7 || pdr->GpsHeading == -1) {
kf->R[3][3] = 10000;
}
}

View File

@ -0,0 +1,149 @@
/******************** (C) COPYRIGHT 2020 Geek************************************
* File Name : pdr_linearFit.c
* Department : Sensor Algorithm Team
* Current Version : V2.0(compare QCOM SAP 5.0)
* Author : logzhan
* Date of Issued : 2020.7.4
* Comments : PDR 线,
********************************************************************************/
/* Header File Including -----------------------------------------------------*/
#include <math.h>
#include <stdlib.h>
#include "LinearFit.h"
#include "Utils.h"
/**----------------------------------------------------------------------
* Function : pdr_linearLeastSquaresFitting
* Description : 线 Y = c0 + c1 x
sum| nDataY - (a*nDataX+b)|^2
* Date : 2020/7/4 logzhan
*---------------------------------------------------------------------**/
int linearLeastSquaresFit(const double *nDataX, const double *nDataY, const int nLength, double *a, double *b)
{
int fittingRes = 0;
if (nDataX == NULL || nDataY == NULL || a == NULL || b == NULL){
fittingRes = -1;
} else if (nLength <= 0){
fittingRes = 1;
} else {
fittingRes = gslFitLinear(nDataX, 1, nDataY, 1, nLength, b, a, NULL, NULL, NULL, NULL);
}
return fittingRes;
}
/**----------------------------------------------------------------------
* Function : gsl_fit_linear
* Description : Fit the data (x_i, y_i) to the linear relationship
Y = c0 + c1 x
returning,
c0, c1 -- coefficients
cov00, cov01, cov11 -- variance-covariance matrix of
c0 and c1,
sumsq -- sum of squares of residuals
This fit can be used in the case where the errors for
the data are uknown, but assumed equal for all points.
The resulting variance-covariance matrix estimates the
error in the coefficientsfrom the observed variance of
the points around the best fit line.
* Date :
*---------------------------------------------------------------------**/
static int gslFitLinear(const double *x, const size_t xstride,
const double *y, const size_t ystride,
const size_t n,
double *c0, double *c1,
double *cov_00, double *cov_01, double *cov_11, double *sumsq)
{
double m_x = 0, m_y = 0, m_dx2 = 0, m_dxdy = 0;
double dx;
double dy;
size_t i;
double s2 = 0, d2 = 0;
double b = 0;
double a = 0;
double d = 0;
for (i = 0; i < n; i++)
{
m_x += (x[i * xstride] - m_x) / (i + 1.0);
m_y += (y[i * ystride] - m_y) / (i + 1.0);
}
for (i = 0; i < n; i++)
{
dx = x[i * xstride] - m_x;
dy = y[i * ystride] - m_y;
m_dx2 += (dx * dx - m_dx2) / (i + 1.0);
m_dxdy += (dx * dy - m_dxdy) / (i + 1.0);
}
/* In terms of y = a + b x */
if (fabs(m_dx2) < 1e-20)return -1;
b = m_dxdy / m_dx2;
a = m_y - m_x * b;
*c0 = a;
*c1 = b;
/* Compute chi^2 = \sum (y_i - (a + b * x_i))^2 */
for (i = 0; i < n; i++)
{
dx = x[i * xstride] - m_x;
dy = y[i * ystride] - m_y;
d = dy - b * dx;
d2 += d * d;
}
s2 = d2 / (n - 2.0); /* chisq per degree of freedom */
/* 为函数增加空指针检查以使函数可以将一下参数设置为空指针 */
if (cov_00 != NULL)
*cov_00 = s2 * (1.0 / n) * (1 + m_x * m_x / m_dx2);
if (cov_11 != NULL)
*cov_11 = s2 * 1.0 / (n * m_dx2);
if (cov_01 != NULL)
*cov_01 = s2 * (-m_x) / (n * m_dx2);
if (sumsq != NULL)
*sumsq = d2;
return 0;
}
/**----------------------------------------------------------------------
* Function : leastDistanceLinearFit
* Description : 线ax+by+c=0, 线
* Input : x yXY
num,
* Output : para 线, para[0]:a, para[0]:b, para[0]:c
*---------------------------------------------------------------------**/
int leastDistanceLinearFit(double x[], double y[], int num, double para[])
{
int i;
double covMatrix[2][2] = { { 0.0 } };
double p[2][2] = { { 0.0 } };
if (num < 2)
return -1;
GetCovMatrix(x, y, covMatrix, num);
Jacobi(covMatrix, p, 2, 1e-10, 1000);
if (covMatrix[0][0] > covMatrix[1][1]) {
para[0] = p[0][1];
para[1] = p[1][1];
}
else {
para[0] = p[0][0];
para[1] = p[1][0];
}
para[2] = 0;
for (i = num - 1; i >= 0; i--) {
para[2] -= (para[0] * x[i] + para[1] * y[i]) / num;
}
return 0;
}

View File

@ -0,0 +1,564 @@
/******************** (C) COPYRIGHT 2020 Geek************************************
* File Name : pdr_location.c
* Current Version : V1.2
* Author : logzhan
* Date of Issued : 2020.7.3
* Comments : PDR
********************************************************************************/
/* Header File Including -----------------------------------------------------*/
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <malloc.h>
#include <errno.h>
#include <stdlib.h>
#include <stdbool.h>
#include "Location.h"
#include "Kalman.h"
#include "Pedometer.h"
#include "AHRS.h"
#include "pdr_detector.h"
#include "Utils.h"
#include "scene_recognition.h"
#include "CoordTrans.h"
/* Global Variable Definition ------------------------------------------------*/
PDR_t pdr; // PDR全局信息
StepPredict stepPredict = { 0 };
Classifer_t sys;
GNSS_t pgnss; // 定位相关信息
EKFPara_t EkfPara;
double GpsPos[HIST_GPS_NUM][3] = {{0}};
static uint32_t g_status;
extern AHRS_t Ahrs;
double refGpsYaw = -1000;
double yaw_bias = -1;
float dir[2] = { 0 };
float bias_dir[2] = { 0 };
/**---------------------------------------------------------------------
* Function : PDRNav_Init
* Description : PDR
* Date : 2022/09/21 logzhan
*---------------------------------------------------------------------**/
void PDR_Init(void) {
memset(&EkfPara, 0, sizeof(EkfPara));
memset(&pgnss, 0, sizeof(pgnss));
memset(GpsPos, 0, sizeof(GpsPos));
memset(&stepPredict, 0, sizeof(stepPredict));
memset(&sys, 0, sizeof(sys));
memset(dir, 0, sizeof(dir));
memset(bias_dir, 0, sizeof(bias_dir));
// GNSS定位初始化
InitGnssInfo();
// 初始化AHRS姿态解算相关
AHRS_Init();
// 检测器初始化
Detector_Init();
// PDR初始化
PDRInfoInit();
//base文件中姿态角计算初始化
EKF_Init();
// 场景识别模块初始化
SceneRecog_Init();
yaw_bias = -1;
}
void PDRInfoInit()
{
memset(&pdr, 0, sizeof(pdr));
pdr.status = PDR_STATUS_RESET;
pdr.axis_ceofficient[0] = 0;
pdr.axis_ceofficient[1] = 1;
pdr.axis_ceofficient[2] = 0;
pdr.bias_direction[0] = 1;
pdr.bias_direction[1] = 0;
pdr.pcaAccuracy = ITEM_INVALID;
pdr.biasAccuracy = ITEM_INVALID;
pdr.sysStatus = IS_INITIAL;
pdr.sceneType = UN_OPEN_AREA;
pdr.fusionPdrFlg = PDR_FALSE;
pdr.trackHeading = ITEM_INVALID;
pdr.motionFreq = 0.1f;
memset(pdr.PllaInit, 0, sizeof(pdr.PllaInit));
}
/**---------------------------------------------------------------------
* Function : InitGnssInfo
* Description : PDS GNSS
* Date : 2020/02/01 logzhan:
*
* 2020/02/08: logzhan initGpsinitGnssInfo
*
*---------------------------------------------------------------------**/
void InitGnssInfo(void) {
pgnss.lastError = ACCURACY_ERR_MAX;
pgnss.overVelCount = 0;
}
/**---------------------------------------------------------------------
* Function : ResetSystemStatus
* Description : PDR
* Date : 2022/09/16 logzhan
*---------------------------------------------------------------------**/
void ResetSystemStatus(EKFPara_t *kf)
{
memset(kf, 0, sizeof(EKFPara_t));
pdr.fusionPdrFlg = PDR_FALSE;
pdr.sysStatus = IS_INITIAL;
pgnss.overVelCount = 0;
}
/**---------------------------------------------------------------------
* Function : InsLocationUpdate
* Description : PDR
* Date : 2022/09/16 logzhan
*---------------------------------------------------------------------**/
int InsLocationUpdate(IMU_t* ImuData, EKFPara_t* Ekf) {
// AHRS姿态更新占2%的运行时间
if (UpdateAHRS(ImuData)) {
// 完成姿态估计后计算PCA 占26%的运行时间
//ComputePCA(&g_ahrs);
}
// 更新用户运动类型检测器IMU信息以及用户运动类型检测, 占21%的运行时间
DetectorUpdateIMU(ImuData, &pdr);
pdr.gyroTime = ImuData->gyr.time;
// 为什么手持类型是0.1的运动频率?
if (pdr.MotionType == DETECTOR_TYPE_HANDHELD)pdr.motionFreq = 0.1f;
// 计步器输入传感器数据占10%的运行时间
Pedometer_Update(ImuData, &pdr.steps);
// ----- Filter Initialization ------- //
if (pdr.sysStatus == IS_INITIAL) {
pdr.ts = ImuData->gyr.time;
pdr.lastSteps = pdr.steps;
stepPredict.lastTime = 0;
stepPredict.fnum = 0;
stepPredict.fsum = 0;
return 0;
}
pdr.ts = ImuData->gyr.time;
if ((0 == ImuData->acc.s[0] && 0 == ImuData->acc.s[1] && 0 == ImuData->acc.s[2]) ||
(0 == ImuData->mag.s[0] && 0 == ImuData->mag.s[1] && 0 == ImuData->mag.s[2])) {
return 0;
}
// 识别当前状态是否平稳这个函数计算量到达整个系统10%的计算量, 以后根据情况进行优化
StateRecognition(ImuData->acc.s, &sys);
//pdr.heading = CalPredHeading(...);
//if (pdr.MotionType == PDR_MOTION_TYPE_HANDHELD)
{
double imuHeading = -Ahrs.Yaw;
if (imuHeading < 0) {
imuHeading += 360;
}
pdr.heading = D2R(imuHeading);
if (fabs(pdr.insHeadingOffset) > 0.000001) {
imuHeading = imuHeading - pdr.insHeadingOffset * (180 / 3.14159265);
pdr.heading = imuHeading / (180 / 3.14159265);
}
pdr.deltaHeading = pdr.heading - pdr.lastHeading;
}
// 角度增量约束(100Hz * 5.5° = 550°/sec)
if (pdr.deltaHeading > D2R(5.5)) {
pdr.deltaHeading = 0.0f;
}
// PDR 惯性位置预测
InsLocationPredict(&pdr, &stepPredict, ImuData, &pgnss, Ekf);
pdr.lastSteps = pdr.steps;
pdr.lastHeading = pdr.heading;
return 0;
}
/**----------------------------------------------------------------------
* Function : GnssInsFusionLocation
* Description : PDR GPSINS
* Date : 2021/01/29 logzhan
*---------------------------------------------------------------------**/
int GnssInsFusionLocation(Nmea_t *nmea, EKFPara_t *kf, LctFs_t *result)
{
Nmea2Gnss(nmea, &pgnss);
// 检查时间差是否满足条件
if (fabs(pgnss.timestamps - pdr.ts) >= 1000)return TYPE_FIX_NONE;
// 根据nmea数据识别场景是否是开阔天空场景
pdr.sceneType = isOpenArea(nmea);
// 根据HDOP、速度、卫星数量等判断gps yaw是否可用
pdr.GpsSpeed = pgnss.vel * GPS_SPEED_UNIT;
pdr.LastGpsHeading = pdr.GpsHeading;
pdr.GpsHeading = GnssCalHeading(&pgnss);
// 如果在win32平台下仿真调试,则添加下面代码
#ifdef _WIN32
result->pdrHeading = kf->pXk[3];
result->gpsHeading = pdr.GpsHeading;
result->hdop = pgnss.HDOP;
result->accuracy = nmea->accuracy.err;
result->gpsSpeed = pdr.GpsSpeed;
result->motionType = pdr.MotionType;
#endif
// 利用Nmea信息修正Ins航向角
CalPdrHeadingOffset(nmea, &pdr);
// 计算两次GPS时间之间步数变化量
pdr.deltaStepsPerGps = pdr.steps - pdr.lastGpsSteps;
pdr.lastGpsSteps = pdr.steps;
int mode = DetectFixMode(&pgnss, kf, &pdr, result);
if (mode != TYPE_FIX_PDR)return mode;
//根据历史GPS拟合输出预估的GPS轨迹航向角
pdr.trackHeading = CalGnssTrackHeading(GpsPos, pgnss);
// 如果系统没有初始化,则先初始化
if (pdr.sysStatus == IS_INITIAL) {
// Gnss系统初始对准
return GnssInsInitialAlignment(&pgnss, kf, &pdr, result);
}
// 如果惯导没有达到输出条件,则不预测轨迹
if (!pdr.fusionPdrFlg)
{
return ResetOutputLoction(&pgnss, &pdr, kf, result);
}
// 根据GPS信息, 计算kf的过程噪声和观测噪声
EKFCalQRMatrix(nmea, &pdr, &sys, kf);
// 运行卡尔曼位置融合
if (pgnss.satellites_num > 4){
// 如果GPS航向角处于无效状态且速度也是无效状态
if (pgnss.yaw == INVAILD_GPS_YAW || pgnss.vel <= 0.0) {
//if(pdr.heading != INVAILD_GPS_YAW){
// pgnss.yaw = (float)(R2D(pdr.heading));
//}else if (pdr.trackHeading != INVAILD_GPS_YAW) {
// pgnss.yaw = (float)(R2D(pdr.trackHeading));
//}
pgnss.yaw = (float)kf->pXk[3];
}
if (pgnss.yaw != INVAILD_GPS_YAW) {
EkfGnssInsLocFusion(&pgnss, &pdr, &sys, yaw_bias, kf, result);
return TYPE_FIX_PDR;
}
}
// 不满足推算条件直接输出原始GPS
if (pgnss.satellites_num > 4 && nmea->accuracy.err > 0 &&
nmea->accuracy.err < 15) {
OutputRawGnssPos(&pgnss, result);
pdr.NoGnssCount = 0;
return TYPE_FIX_GPS;
}
// 如果没有GPS信号那么PDR也会接着推算位置, 但是最多推算10个点
if (pdr.NoGnssCount < MAX_NO_GPS_PREDICT) {
// 无GPS状态位置推算
NoGnssInfoPredict(kf, result, &pdr);
return TYPE_FIX_PDR;
}
pdr.NoGnssCount++;
return 0;
}
/**----------------------------------------------------------------------
* Function : NoGnssInfoPredict
* Description : gpsGPS
* Date : 2022/09/16
*---------------------------------------------------------------------**/
void NoGnssInfoPredict(EKFPara_t* kf, LctFs_t* result, PDR_t* p_pdr)
{
double ned[3] = {0}, lla[3] = {0};
ned[0] = kf->pXk[0] - p_pdr->x0;
ned[1] = kf->pXk[1] - p_pdr->y0;
ned[2] = 0;
NED2WGS84(p_pdr->PllaInit, ned, lla);
result->latitude = lla[0];
result->latitude_ns = pgnss.lat_ns;
result->longitudinal = lla[1];
result->longitudinal_ew = pgnss.lon_ew;
result->time = pgnss.timestamps;
p_pdr->NoGnssCount++;
}
/**----------------------------------------------------------------------
* Function : calPdrHeadingOffset
* Description : GPS
* Date : 2020/07/08 logzhan
*---------------------------------------------------------------------**/
void CalPdrHeadingOffset(Nmea_t* nmea_data, PDR_t* p_pdr) {
//惯导姿态角与GPS行进角度的对准判断GPS信号是否正常以及惯导是否平稳
if (refGpsYaw != -1000)return;
if ((pgnss.satellites_num > 4 && pgnss.HDOP < 2.0 && pgnss.yaw != -1 && pgnss.vel >= 1.0)
&& (nmea_data->accuracy.err > 0 && nmea_data->accuracy.err < 4)
&& (DetUserStatic(&pdr, &pgnss, (p_pdr->steps - p_pdr->lastSteps)) == 0 && pdr.MotionType == 2))
{
/*这里放姿态角与GPS对准part1 start*/
double imuHeading = atan2(2 * (Ahrs.q[0] * Ahrs.q[3] + Ahrs.q[1] * Ahrs.q[2]),
1 - 2 * (Ahrs.q[2] * Ahrs.q[2] + Ahrs.q[3] * Ahrs.q[3]));
if (imuHeading < 0) {
imuHeading += TWO_PI;
}
if (fabs(imuHeading - p_pdr->GpsHeading) < PI / 18)
{
//printf("offset 标定\n");
//p_pdr->insHeadingOffset = imuHeading - p_pdr->gpsHeading;
}
}
}
/**----------------------------------------------------------------------
* Function : DetectFixMode
* Description : PDR,
* GPS
* Date : 2020/07/08 logzhan : -1INVAILD_GPS_YAW
*
*---------------------------------------------------------------------**/
int DetectFixMode(GNSS_t* pgnss, EKFPara_t* kf, PDR_t* pdr, LctFs_t* result) {
// 检测用户是否处于静止状态
if (DetUserStatic(pdr, pgnss, pdr->deltaStepsPerGps)) {
if (pgnss->error > 0 && pgnss->error < 15 &&
pgnss->lastError >= pgnss->error) {
OutputRawGnssPos(pgnss, result);
pgnss->lastError = pgnss->error;
return TYPE_FIX_PDR;
}
// 否则不输出位置
return TYPE_FIX_NONE;
}
// 如果是检测到是开车状态则输出GPS位置
if (DetectCarMode(pgnss, pdr, pdr->deltaStepsPerGps, &pgnss->overVelCount)) {
// 如果检测到车载模式则重置PDR状态需要重新初始化
ResetSystemStatus(kf);
if (pgnss->error >= 0 || (pgnss->satellites_num > 4
&& pgnss->HDOP < 2.0)) {
OutputRawGnssPos(pgnss, result);
return TYPE_FIX_GPS;
}
// 精度过差,不输出位置
return TYPE_FIX_NONE;
}
return TYPE_FIX_PDR;
}
/**----------------------------------------------------------------------
* Function : GnssCalHeading
* Description : GPS(0 - 360°)
* Date : 2022/09/16 logzhan
*
*---------------------------------------------------------------------**/
double GnssCalHeading(GNSS_t* pgnss) {
double gnssHeading = INVAILD_GPS_YAW;
if (pgnss->satellites_num > 4 && pgnss->HDOP < 2.0 && pgnss->vel >= 1.0
&& pgnss->yaw != INVAILD_GPS_YAW && pgnss->error < 50) {
gnssHeading = pgnss->yaw * RADIAN_PER_DEG;
}
return gnssHeading;
}
/**----------------------------------------------------------------------
* Function : pdr_nmea2Gnss
* Description : nmeagnss
* Date : 2020/07/08 logzhan
*---------------------------------------------------------------------**/
void Nmea2Gnss(Nmea_t* nmea_data, GNSS_t* pgnss)
{
NmeaRMC_t rmc = { 0 };
if (nmea_data->rmc[0].time > nmea_data->rmc[1].time) {
rmc = nmea_data->rmc[0];
}else {
rmc = nmea_data->rmc[1];
}
// 更新上一次的Accuracy Error
pgnss->lastError = pgnss->error;
pgnss->lat = rmc.latitude * PI / 180;
pgnss->lat_ns = rmc.rmc_latitude_ns;
pgnss->lon = rmc.longitudinal * PI / 180;
pgnss->lon_ew = rmc.longitudinal_ew;
//pgnss->vel = rmc.speed * GPS_SPEED_UNIT;
pgnss->vel = rmc.speed;
pgnss->HDOP = nmea_data->gsa[0].hdop;
pgnss->yaw = rmc.cog;
pgnss->quality = 0;
pgnss->error = nmea_data->accuracy.err;
pgnss->timestamps = rmc.time;
pgnss->satellites_num = nmea_data->gga.satellites_nb;
}
/**----------------------------------------------------------------------
* Function : OutputRawGnssPos
* Description : GPS
* Date : 2022/10/15 logzhan
*---------------------------------------------------------------------**/
void OutputRawGnssPos(GNSS_t* pgnss, LctFs_t* result) {
result->latitude = pgnss->lat;
result->latitude_ns = pgnss->lat_ns;
result->longitudinal = pgnss->lon;
result->longitudinal_ew = pgnss->lon_ew;
result->time = pgnss->timestamps;
}
/**----------------------------------------------------------------------
* Function : ResetOutputLoction
* Description : 1
* 2GPSresult
* Date : 2022/09/19 logzhan
*---------------------------------------------------------------------**/
int ResetOutputLoction(GNSS_t* pgnss, PDR_t* g_pdr, EKFPara_t* kf, LctFs_t* result) {
double stepLength = 0.7;
double ned[3] = { 0 };
g_pdr->PllaInit[0] = pgnss->lat;
g_pdr->PllaInit[1] = pgnss->lon;
g_pdr->PllaInit[2] = 0;
WGS842NED(g_pdr->PllaInit, g_pdr->PllaInit, ned);
g_pdr->x0 = ned[0];
g_pdr->y0 = ned[1];
kf->pXk[0] = ned[0];
kf->pXk[1] = ned[1];
kf->pXk[2] = stepLength;
// 重置输出GPS时GPS的航向角不一定准
kf->pXk[3] = pgnss->yaw * RADIAN_PER_DEG;
for (uchar i = 0; i < N; i++) {
kf->Xk[i] = kf->pXk[i];
}
// 清除卡尔曼Q矩阵和R矩阵
for (int i = 0; i < N; i++) {
for (int l = 0; l < N; l++) {
kf->Q[i][l] = 0.0;
kf->R[i][l] = 0.0;
}
}
// 输出GPS位置结果
OutputRawGnssPos(pgnss, result);
g_pdr->NoGnssCount = 0;
return PDR_TRUE;
}
/**----------------------------------------------------------------------
* Function : EkfGnssInsLocFusion
* Description : EKFGNSSINS
* Date : 2022/09/21 logzhan
*---------------------------------------------------------------------**/
void EkfGnssInsLocFusion(GNSS_t* pgnss, PDR_t* pdr, Classifer_t* sys, double yaw_bias,
EKFPara_t* kf, LctFs_t* res) {
double plla[3] = { 0 };
double Ned[3] = { 0 };
double yaw_thr = 6;
int scene_type = pdr->sceneType;
plla[0] = pgnss->lat;
plla[1] = pgnss->lon;
plla[2] = 0;
WGS842NED(plla, pdr->PllaInit, Ned);
pgnss->xNed = Ned[0];
pgnss->yNed = Ned[1];
//调整融合策略
EKFStateUpdate(kf, pgnss, sys, pdr, scene_type);
for (uchar i = 0; i < N; i++) {
for (uchar l = 0; l < N; l++) {
kf->pPk[i][l] = kf->Pk[i][l];
}
kf->pXk[i] = kf->Xk[i];
}
Ned[0] = kf->pXk[0] - pdr->x0;
Ned[1] = kf->pXk[1] - pdr->y0;
Ned[2] = 0;
NED2WGS84(pdr->PllaInit, Ned, plla);
res->latitude = plla[0];
res->latitude_ns = pgnss->lat_ns;
res->longitudinal = plla[1];
res->longitudinal_ew = pgnss->lon_ew;
res->time = pgnss->timestamps;
pdr->NoGnssCount = 0;
}
/**----------------------------------------------------------------------
* Function : PDRInitialAlignment
* Description : PDR
* Date : 2022/09/19 logzhan
*---------------------------------------------------------------------**/
int GnssInsInitialAlignment(GNSS_t* pgnss, EKFPara_t* kf, PDR_t* g_pdr, LctFs_t* result)
{
double stepLen = 0.7; // 初始运动步长为0.7m
if (pgnss->satellites_num > 4 && pgnss->HDOP < 2.0 && pgnss->vel >= 1.5 && pgnss->yaw != -1) {
// plla 类似位置坐标的原点(单位是经纬度)
g_pdr->PllaInit[0] = pgnss->lat;
g_pdr->PllaInit[1] = pgnss->lon;
g_pdr->PllaInit[2] = 0;
// plla 转 ned
double ned[3] = { 0 };
WGS842NED(g_pdr->PllaInit, g_pdr->PllaInit, ned);
// 在NED坐标系的计算, 单位是米
g_pdr->x0 = ned[0];
g_pdr->y0 = ned[1];
// 初始化卡尔曼滤波器的观测量
kf->pXk[0] = ned[0]; // 状态量1: 北向x
kf->pXk[1] = ned[1]; // 状态量2东向y
kf->pXk[2] = stepLen; // 状态量3步长
kf->pXk[3] = pgnss->yaw * RADIAN_PER_DEG; // 状态量4航向角
for (uchar i = 0; i < N; i++) {
kf->Xk[i] = kf->pXk[i];
}
kf->initHeading = kf->pXk[3];
for (int i = 0; i < N; i++) {
for (int l = 0; l < N; l++) {
kf->Q[i][l] = 0.0;
kf->R[i][l] = 0.0;
}
}
OutputRawGnssPos(pgnss, result);
g_pdr->sysStatus = IS_NORMAL;
return PDR_TRUE;
}
if (pgnss->satellites_num > 4 && pgnss->HDOP < 2.0 && pgnss->vel > 0 && pgnss->yaw != -1) {
OutputRawGnssPos(pgnss, result);
return PDR_TRUE;
}
return PDR_FALSE;
}

View File

@ -0,0 +1,460 @@
/******************** (C) COPYRIGHT 2020 Geek************************************
* File Name : pdr_main.cpp
* Department : Sensor Algorithm Team
* Current Version : V2.0
* Author : logzhan
* Date of Issued : 2021.1.28
* Comments : PDR PC仿
* Modify : 2021/02/04 logzhan : kmlkml
* hdopheadingaccuracyGoogle Map便
*
* 2021/02/18 logzhan : kml
*
*
*
* 1) GPS0.51444
* GPS
* 2) buffer mean使,
* buffer mean
* 2021/02/10 logzhan:
* 1) SAP5.0
*
* 2) GPS0.51444
*
* 3buffer mean使,
* buffer mean
* 4)*
* GPS
*
*
* 5)*PCAPCA
*
* 6
*
* 7fft
*
* 8)
*
* ()
* 9) PDR
* 线
* 10)
*
*
* 11) PDR
* GPSGPS
* GPS
* 12) kml ---- logzhan finish
*
*
+ () + =>
+ (PCA + ) + =>
+ + => 使
+ + + + => 便
********************************************************************************/
#include <stdio.h>
#include <string>
#include <errno.h>
#include <stdlib.h>
#include "pdr_api.h"
#include "Main.h"
#include "Utils.h"
#include "time.h"
using namespace std;
/* Global Variable Definition ------------------------------------------------*/
ResultTracks resTracks;
FILE* SimFile = NULL;
/* Extern Variable Definition ------------------------------------------------*/
extern "C" PDR pdr;
extern "C" double refGpsYaw;
/**----------------------------------------------------------------------
* Function : main
* Description : pdr仿main
* Date : 2021/01/25 logzhan
*---------------------------------------------------------------------**/
int main(int argc, char* argv[])
{
string logPath = "E:\\SoftwareProject\\GnssIns\\GnssIns-PDR-Private\\1.Software\\PDR 1.06\\Release\\";
string logDate = "shenzhen";
string logLabel = "data\\";
string fileHead;
char line[256] = { 0 };
// 解析命令行, 用于解析参数
for (int i = 0; i < argc; i++) {
string s = argv[i];
if(i == 1)logPath = s;
if(i == 2)logDate = s;
}
clock_t t = clock();
// 获取kml输出路径
string kmlPath = logPath + logDate + "\\output\\";
// 仿真文件夹路径和Catalog.txt路径
string filePath = logPath + logDate + "\\" + logLabel + "\\";
string catalogPath = filePath + "catalog.txt";
FILE* catalogFp = fopen(catalogPath.c_str(), "r");
if (catalogFp == NULL){
printf("open catalog.txt file %s error %s\n", catalogPath.c_str(),
strerror(errno));
system("pause");
return -1;
}
while (!feof(catalogFp))
{
FILE* fileFp = getSimulateFile(catalogFp, filePath, fileHead);
// PDR 仿真流程
Algorithm_Init();
LctFs_t locFusion;
memset(&locFusion,0, sizeof(locFusion));
memset(&resTracks, 0, sizeof(resTracks));
// 解析文本仿真
while (fgets(line, 256, fileFp)){
// 解析文本数据仿真
if (ParseDataAndUpdate(line, &locFusion) != TYPE_FIX_NONE){
// 更新结果轨迹用于最后的kml生成
UpdateResTrack(resTracks, locFusion);
}
}
// 关闭PDR算法释放资源
Algorithm_DeInit();
// 写结果kml
KmlWrite(kmlPath, fileHead, string("_PDR_ZL_2.1c"));
// 关闭文件
fclose(fileFp);
}
// 打印仿真时间信息
printf("PDR simulate spends %f s\n", ((double)(clock() - t) / CLOCKS_PER_SEC));
system("pause");
return 0;
}
/**----------------------------------------------------------------------
* Function : getSimulateFile
* Description : 仿
* catalogFp :
* path_file 仿
* fileHead : C++
* Date : 2021/01/25 logzhan
*---------------------------------------------------------------------**/
FILE* getSimulateFile(FILE* catalogFp, string path_file, string& fileHead) {
char file_name[256] = { 0 };
FILE* fp = NULL;
if (fscanf(catalogFp, "%s\n", file_name) == -1){
printf("get data file name failed\n");
system("pause");
exit(-1);
}
string fileNamePath = path_file + string(file_name);
fp = fopen(fileNamePath.c_str(), "rb");
if (fp == NULL){
printf("open file %s failed error %s\n", fileNamePath.c_str(), strerror(errno));
system("pause");
exit(-1);
}
// 去除文件扩展名.csv
fileHead = file_name;
fileHead = fileHead.substr(0, fileHead.length() - 4);
printf("%s\n", fileNamePath.c_str());
return fp;
}
/**----------------------------------------------------------------------
* Function : gpsYaw2GoogleYaw
* Description : kml0-360Yaw
* Yaw
* Date : 2021/01/25 logzhan
*---------------------------------------------------------------------**/
double gpsYaw2GoogleYaw(double heading) {
double gh = R2D(heading) - 180;
while (gh > 360)gh -= 360;
while (gh < 0)gh += 360;
return gh;
}
/**----------------------------------------------------------------------
* Function : UpdateResTrack
* Description : GPSPDR
* Date : 2022/09/19 logzhan
*---------------------------------------------------------------------**/
void UpdateResTrack(ResultTracks& resTrack, LctFs_t& lctfs)
{
resTrack.pdrTrack[resTrack.pdrLen].lat = lctfs.latitude;
resTrack.pdrTrack[resTrack.pdrLen].lon = lctfs.longitudinal;
resTrack.pdrTrack[resTrack.pdrLen].heading =
gpsYaw2GoogleYaw(lctfs.pdrHeading);
resTrack.pdrTrack[resTrack.pdrLen].hdop = lctfs.hdop;
resTrack.pdrTrack[resTrack.pdrLen].accuracy = lctfs.accuracy;
resTrack.pdrTrack[resTrack.pdrLen].time = lctfs.time;
resTrack.pdrTrack[resTrack.pdrLen].motionType = lctfs.motionType;
resTrack.pdrLen++;
if (lctfs.gpsLat > 0 && lctfs.gpsLon > 0) {
resTrack.gpsTrack[resTrack.gpsLen].lat = lctfs.gpsLat;
resTrack.gpsTrack[resTrack.gpsLen].lon = lctfs.gpsLon;
resTrack.gpsTrack[resTrack.gpsLen].heading =
gpsYaw2GoogleYaw(lctfs.gpsHeading);
resTrack.gpsTrack[resTrack.gpsLen].vel = lctfs.gpsSpeed;
resTrack.gpsTrack[resTrack.gpsLen].hdop = lctfs.hdop;
resTrack.gpsTrack[resTrack.gpsLen].accuracy = lctfs.accuracy;
resTrack.gpsTrack[resTrack.gpsLen].time = lctfs.time;
resTrack.gpsLen++;
}
}
string time2str(double t) {
long time = (long)t;
if (t < 10) {
string str = "0" + std::to_string(time);
return str;
}else {
string str = std::to_string(time);
return str;
}
}
/**----------------------------------------------------------------------
* Function : KmlWrite
* Description : pdrgpspdrkml
* path : kml
* name : kml
* postfix
* Date : 2020/11/1 logzhan
*---------------------------------------------------------------------**/
void KmlWrite(string path, string name, string postfix)
{
string pdrColor = "ff0000ff";
string gpsColor = "ff00ffff";
if (path == "") {
return;
}
string kmlPath = path + name + postfix + ".kml";
string kmlName = name + postfix;
FILE* fid = fopen(kmlPath.c_str(), "w");
fprintf(fid, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
fprintf(fid, "<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n");
fprintf(fid, "\t<Document>\n");
fprintf(fid, "\t\t<name>%s</name>\n", kmlName.c_str());
fprintf(fid, "\t\t<Folder id=\"ID1\">\n");
fprintf(fid, "\t\t<name>GPS Fixs</name>\n");
// 写gps结果
for (int i = 0; i < resTracks.gpsLen; i++) {
fprintf(fid, "\t\t<Placemark>\n");
fprintf(fid, "\t\t\t<Style>\n");
fprintf(fid, "\t\t\t\t<IconStyle>\n");
fprintf(fid, "\t\t\t\t\t<Icon>\n");
fprintf(fid, "\t\t\t\t\t\t<href>%s</href>\n",
"http://maps.google.com/mapfiles/kml/shapes/arrow.png");
fprintf(fid, "\t\t\t\t\t</Icon>\n");
fprintf(fid, "\t\t\t\t\t<scale>%.2f</scale>\n", 0.4);
// 描述轨迹方向信息
fprintf(fid, "\t\t\t\t\t<heading>%.7f</heading>\n", resTracks.gpsTrack[i].heading);
fprintf(fid, "\t\t\t\t\t<color>%s</color>\n", gpsColor.c_str());
fprintf(fid, "\t\t\t\t</IconStyle>\n");
fprintf(fid, "\t\t\t</Style>\n");
// 写入时间信息
double h, m, s;
pdr_utc2hms(resTracks.gpsTrack[i].time, &h, &m, &s);
fprintf(fid, "\t\t\t<TimeStamp>\n");
fprintf(fid, "\t\t\t\t<when>2021-01-22T%s:%s:%s</when>\n", time2str(h).c_str(),
time2str(m).c_str(), time2str(s).c_str());
fprintf(fid, "\t\t\t</TimeStamp>\n");
// 写入描述信息
fprintf(fid, "\t\t\t<description>\n");
fprintf(fid, "\t\t\t\t<![CDATA[\n");
fprintf(fid, "\t\t\t\t<dl>\n");
fprintf(fid, "\t\t\t\t<dd>East : 0.0 (m/s)</dd>\n");
fprintf(fid, "\t\t\t\t<dd>HDOP : %.2f (m/s)</dd>\n",
resTracks.gpsTrack[i].hdop);
fprintf(fid, "\t\t\t\t<dd>accuracy : %.2f (m)</dd>\n",
resTracks.gpsTrack[i].accuracy);
fprintf(fid, "\t\t\t\t<dd>speed : %.2f (m/s)</dd>\n",
resTracks.gpsTrack[i].vel);
fprintf(fid, "\t\t\t\t<dd>Heading : %.2f (degrees) </dd>\n",
resTracks.gpsTrack[i].heading);
fprintf(fid, "\t\t\t\t</dl><hr>]]>\n");
fprintf(fid, "\t\t\t</description>\n");
// 写入坐标信息
fprintf(fid, "\t\t\t<Point>\n");
fprintf(fid, "\t\t\t\t<coordinates>%.10f,%.10f</coordinates>\n",
resTracks.gpsTrack[i].lon,
resTracks.gpsTrack[i].lat);
fprintf(fid, "\t\t\t</Point>\n");
fprintf(fid, "\t\t</Placemark>\n");
}
fprintf(fid, "\t\t</Folder>\n");
fprintf(fid, "\t\t<Folder id=\"ID2\">\n");
fprintf(fid, "\t\t<name>PDR Fixs</name>\n");
// 写pdr结果
for (int i = 0; i < resTracks.pdrLen; i++) {
fprintf(fid, "\t\t<Placemark>\n");
fprintf(fid, "\t\t\t<Style>\n");
fprintf(fid, "\t\t\t\t<IconStyle>\n");
fprintf(fid, "\t\t\t\t\t<Icon>\n");
fprintf(fid, "\t\t\t\t\t\t<href>%s</href>\n",
"http://maps.google.com/mapfiles/kml/shapes/arrow.png");
fprintf(fid, "\t\t\t\t\t</Icon>\n");
fprintf(fid, "\t\t\t\t\t<scale>%.2f</scale>\n", 0.4);
fprintf(fid, "\t\t\t\t\t<heading>%.7f</heading>\n",
resTracks.pdrTrack[i].heading);
fprintf(fid, "\t\t\t\t\t<color>%s</color>\n", pdrColor.c_str());
fprintf(fid, "\t\t\t\t</IconStyle>\n");
fprintf(fid, "\t\t\t</Style>\n");
// 写入时间信息
double h, m, s;
pdr_utc2hms(resTracks.pdrTrack[i].time, &h, &m, &s);
fprintf(fid, "\t\t\t<TimeStamp>\n");
fprintf(fid, "\t\t\t\t<when>2021-01-22T%s:%s:%s</when>\n", time2str(h).c_str(),
time2str(m).c_str(), time2str(s).c_str());
fprintf(fid, "\t\t\t</TimeStamp>\n");
// description
fprintf(fid, "\t\t\t<description>\n");
fprintf(fid, "\t\t\t\t<![CDATA[\n");
fprintf(fid, "\t\t\t\t<dl>\n");
fprintf(fid, "\t\t\t\t<dd>East : 0.0 (m/s)</dd>\n");
fprintf(fid, "\t\t\t\t<dd>HDOP : %.2f (m/s)</dd>\n",
resTracks.pdrTrack[i].hdop);
fprintf(fid, "\t\t\t\t<dd>MOTION TYPE : %s (m/s)</dd>\n",
Motion2TypeStr(resTracks.pdrTrack[i].motionType));
fprintf(fid, "\t\t\t\t<dd>accuracy : %.2f (m/s)</dd>\n",
resTracks.pdrTrack[i].accuracy);
fprintf(fid, "\t\t\t\t<dd>Heading : %.2f (degrees) </dd>\n",
resTracks.pdrTrack[i].heading);
fprintf(fid, "\t\t\t\t</dl><hr>]]>\n");
fprintf(fid, "\t\t\t</description>\n");
fprintf(fid, "\t\t\t<Point>\n");
fprintf(fid, "\t\t\t\t<coordinates>%.10f,%.10f</coordinates>\n",
resTracks.pdrTrack[i].lon,
resTracks.pdrTrack[i].lat);
fprintf(fid, "\t\t\t</Point>\n");
fprintf(fid, "\t\t</Placemark>\n");
}
fprintf(fid, "\t\t</Folder>\n");
fprintf(fid, "\t</Document>\n");
fprintf(fid, "</kml>\n");
fclose(fid);
}
#ifdef _WIN32
/**----------------------------------------------------------------------
* Function : PDR_Init
* Description : PDR(DLL)
* Date : 2022/09/15 logzhan
*---------------------------------------------------------------------**/
void LibPDR_Init() {
Algorithm_Init();
}
/**----------------------------------------------------------------------
* Function : PDR_StepUpdateGPS
* Description : 仿GPS(DLL)
* Date : 2022/9/16 logzhan
*---------------------------------------------------------------------**/
PosFusion LibPDR_StepUpdateGPS(int useGpsFlg)
{
PosFusion fusion;
fusion.vaild = 0;
Nmea_t location_nmea;
Nmea_t* ln = &location_nmea;
imu imu_data;
LctFs_t lct_fusion;
memset(&lct_fusion, 0, sizeof(lct_fusion));
//memset(&location_nmea, 0, sizeof(location_nmea));
memset(&imu_data, 0, sizeof(imu_data));
/*memset(&kf, 0, sizeof(kf));*/
char line[256] = { 0 };
while (fgets(line, 256, SimFile)) {
int flag = ParseDataAndUpdate(line, &lct_fusion);
if (flag) {
fusion.gpsLat = lct_fusion.gpsLat;
fusion.gpsLon = lct_fusion.gpsLon;
}
// 写PDR融合结果
if (flag) {
fusion.lat = lct_fusion.latitude;
fusion.lon = lct_fusion.longitudinal;
fusion.t = lct_fusion.time;
fusion.vaild = 1;
break;
}
}
return fusion;
}
/**----------------------------------------------------------------------
* Function : setSimulatorFileCsvPath
* Description : 仿(DLL)
* Date : 2020/8/3 logzhan
*---------------------------------------------------------------------**/
void setSimulatorFileCsvPath(char* path) {
if (SimFile == NULL) {
SimFile = fopen(path, "rb");
}
else {
fclose(SimFile);
SimFile = NULL;
}
}
/**----------------------------------------------------------------------
* Function : setRefGpsYaw
* Description : GPS
* Date : 2020/8/3 logzhan
*---------------------------------------------------------------------**/
void setRefGpsYaw() {
refGpsYaw = pdr.GpsHeading;
printf("ref Gps Yaw = %f\n", refGpsYaw);
//g_pdr.sysStatus = IS_INITIAL;
//g_pdr.fusionPdrFlg = ON;
}
/**----------------------------------------------------------------------
* Function : closePdrAlgo
* Description : pdrdll(DLL)
* Date : 2020/8/3 logzhan
*---------------------------------------------------------------------**/
void LibPDR_DeInit() {
Algorithm_DeInit();
if (SimFile != NULL) {
fclose(SimFile);
SimFile = NULL;
}
}
#endif

View File

@ -0,0 +1,195 @@
/******************** (C) COPYRIGHT 2022 Geek************************************
* File Name : matrix.c
* Current Version : V2.0
* Author : logzhan
* Date of Issued : 2022.09.14
* Comments : PDR
********************************************************************************/
/* Header File Including -----------------------------------------------------*/
#include "Matrix.h"
/**---------------------------------------------------------------------
* Function : MatrixTrans
* Description :
* Date : 2022/09/14 logzhan
*---------------------------------------------------------------------**/
void MatrixTrans(double a[N][N], double r[N][N]) {
int i, j;
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
r[i][j] = a[j][i];
}
}
}
/**---------------------------------------------------------------------
* Function : VecMatMultiply
* Description : r = b * a
* Date : 2022/09/14 logzhan
*---------------------------------------------------------------------**/
void VecMatMultiply(double a[N], double b[N][N], double r[N]) {
int i, j;
double temp[N] = { 0.0 };
//for (i = 0; i < N; i++) {
// temp[i] = a[i];
//}
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
temp[i] += ((b[i][j] * 100) * (a[j] * 100)) / 10000;
}
}
for (i = 0; i < N; i++) {
r[i] = temp[i];
}
}
/**---------------------------------------------------------------------
* Function : MatrixMultiply
* Description : r = a * b
* Date : 2022/09/14 logzhan
*---------------------------------------------------------------------**/
void MatrixMultiply(double a[N][N], double b[N][N], double r[N][N]) {
int i, j, m;
double temp[N][N] = { { 0.0 } };
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
for (m = 0; m < N; m++) {
//temp[i][j] += a[j][m] * b[m][j];
temp[i][j] += a[i][m] * b[m][j];
}
}
}
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
r[i][j] = temp[i][j];
}
}
}
/**---------------------------------------------------------------------
* Function : MatrixAdd
* Description : r = a + b, a = a + b
* Date : 2022/09/14 logzhan
*---------------------------------------------------------------------**/
void MatrixAdd(double a[N][N], double b[N][N], double r[N][N]) {
int i, j;
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
r[i][j] = a[i][j] + b[i][j];
}
}
}
/**---------------------------------------------------------------------
* Function : VectorAdd
* Description : r = a + b, a = a + b
* Date : 2022/09/14 logzhan
*---------------------------------------------------------------------**/
void VectorAdd(double a[N], double b[N], double r[N]) {
int i;
for (i = 0; i < N; i++) {
r[i] = a[i] + b[i];
}
}
/**---------------------------------------------------------------------
* Function : MatrixSub
* Description : r = a - b, a = a - b
* Date : 2022/09/14 logzhan
*---------------------------------------------------------------------**/
void MatrixSub(double a[N][N], double b[N][N], double r[N][N]) {
int i, j;
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
r[i][j] = a[i][j] - b[i][j];
}
}
}
/**---------------------------------------------------------------------
* Function : VectorSub
* Description : r = a - b, a = a - b
* Date : 2022/09/14 logzhan
*---------------------------------------------------------------------**/
void VectorSub(double a[N], double b[N], double r[N]) {
int i;
for (i = 0; i < N; i++) {
r[i] = a[i] - b[i];
}
}
/**---------------------------------------------------------------------
* Function : MatrixInverse
* Description :
* Date : 2022/09/14 logzhan
*---------------------------------------------------------------------**/
void MatrixInverse(double(*a)[N], double (*a_inv)[N]) {
double l[N][N] = { { 0.0 } };
double u[N][N] = { { 0.0 } };
double l_inv[N][N] = { { 0.0 } };
double u_inv[N][N] = { { 0.0 } };
double temp[N][N] = { { 0.0 } };
int i, j, k;
double s;
for (i = 0; i < N; i++)l[i][i] = 1;
for (i = 0; i < N; i++){
for (j = i; j <N; j++){
s = 0;
for (k = 0; k < i; k++){
s += l[i][k] * u[k][j];
}
u[i][j] = a[i][j] - s;
}
for (j = i + 1; j < N; j++){
s = 0;
for (k = 0; k < i; k++){
s += l[j][k] * u[k][i];
}
l[j][i] = (a[j][i] - s) / u[i][i];
}
}
for (i = 0; i < N; i++)l_inv[i][i] = 1;
for (i = 1; i < N; i++){
for (j = 0; j < i; j++){
s = 0;
for (k = 0; k < i; k++){
s += l[i][k] * l_inv[k][j];
}
l_inv[i][j] = -s;
}
}
for (i = 0; i < N; i++){
u_inv[i][i] = 1 / u[i][i];
}
for (i = 1; i < N; i++)
{
for (j = i - 1; j >= 0; j--)
{
s = 0;
for (k = j + 1; k <= i; k++)
{
s += u[j][k] * u_inv[k][i];
}
u_inv[j][i] = -s / u[j][j];
}
}
for (i = 0; i < N; i++){
for (j = 0; j < N; j++){
for (k = 0; k < N; k++){
temp[i][j] += u_inv[i][k] * l_inv[k][j];
}
}
}
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
a_inv[i][j] = temp[i][j];
}
}
}

View File

@ -0,0 +1,295 @@
/* Header File Including ------------------------------------------------------------------------ */
#include <stdint.h>
#include <string.h>
#include "m_munkres.h"
/* Macro Definition ----------------------------------------------------------------------------- */
#define COST(i, j) cost[(i) + (j) * m]
#define MARK(i, j) mark[(i) + (j) * m]
#define PATH(i, j) path[(i) + (j) * 64]
#define CLR_ALL(flag) (*flag##_cover = 0)
#define SET_FLG(flag, index) (*flag##_cover |= (1 << (index)))
#define CLR_FLG(flag, index) (*flag##_cover &= ~(1 << (index)))
#define TST_FLG(flag, index) (*flag##_cover & (1 << (index)))
/* Global Variable Definition ------------------------------------------------------------------- */
static float g_cost[64];
static int g_mark[64];
static uint8_t g_row_cover;
static uint8_t g_col_cover;
/* Function Declaration ------------------------------------------------------------------------- */
static int step_one(float *cost, int m, int n);
static int step_two(float *cost, int *mark, int m, int n, uint8_t *col_cover);
static int step_three(int *mark, int m, int n, uint8_t *col_cover);
static int step_four(float *cost, int *mark, int m, int n, uint8_t *row_cover, uint8_t *col_cover, int *path_start_i, int *path_start_j);
static int step_five(int *mark, int m, int n, uint8_t *row_cover, uint8_t *col_cover, int path_start_i, int path_start_j);
static int step_six(float *cost, int m, int n, uint8_t *row_cover, uint8_t *col_cover);
/* Function Definition -------------------------------------------------------------------------- */
int MUNKRES_get_assignment(int *assignment, float *cost, int m, int n) {
int i = 0;
int j = 0;
int step;
if (m > 8 || n > 8) {
return MUNKRES_EXCESSIVE_MATRIX;
}
memcpy(g_cost, cost, m * n * sizeof(*g_cost));
memset(g_mark, 0, m * n * sizeof(*g_mark));
g_row_cover = 0;
g_col_cover = 0;
step = 0;
#if PRINT_ALGO_RUN_TIME
time_algo_1 = uTimetick_Get();
#endif
while (7 != step) {
switch (step) {
case 0:
case 1:
step = step_one(g_cost, m, n);
break;
case 2:
step = step_two(g_cost, g_mark, m, n, &g_col_cover);
break;
case 3:
step = step_three(g_mark, m, n, &g_col_cover);
break;
case 4:
step = step_four(g_cost, g_mark, m, n, &g_row_cover, &g_col_cover, &i, &j);
break;
case 5:
step = step_five(g_mark, m, n, &g_row_cover, &g_col_cover, i, j);
break;
case 6:
step = step_six(g_cost, m, n, &g_row_cover, &g_col_cover);
break;
default:
step = 7;
break;
}
}
for (i = 0; i < m; ++i) {
for (j = 0; j < n; ++j) {
if (0 != g_mark[(i) + (j) * m]) {
assignment[i] = j;
break;
}
}
}
return MUNKRES_NO_ERROR;
}
static int step_one(float *cost, int m, int n) {
int i;
int j;
float min;
for (i = 0; i < m; ++i) {
min = COST(i, 0);
for (j = 1; j < n; ++j) {
if (min > COST(i, j)) {
min = COST(i, j);
}
}
for (j = 0; j < n; ++j) {
COST(i, j) -= min;
}
}
return 2;
}
static int step_two(float *cost, int *mark, int m, int n, uint8_t *col_cover) {
int i;
int j;
for (i = 0; i < m; ++i) {
for (j = 0; j < n; ++j) {
if (0 == COST(i, j) && 0 == TST_FLG(col, j)) {
MARK(i, j) = 1;
SET_FLG(col, j);
break;
}
}
}
CLR_ALL(col);
return 3;
}
static int step_three(int *mark, int m, int n, uint8_t *col_cover) {
int i;
int j;
int count;
CLR_ALL(col);
for (i = 0; i < m; ++i) {
for (j = 0; j < n; ++j) {
if (1 == MARK(i, j)) {
SET_FLG(col, j);
}
}
}
count = 0;
for (j = 0; j < n; ++j) {
count += (0 != TST_FLG(col, j) ? 1 : 0);
}
return (count >= m || count >= n) ? 7 : 4;
}
static void find_a_noncovered_zero(int *i, int *j, float *cost, int m, int n, uint8_t *row_cover, uint8_t *col_cover) {
for (*i = 0; *i < m; ++*i) {
if (0 != TST_FLG(row, *i)) {
continue;
}
for (*j = 0; *j < n; ++*j) {
if (0 == COST(*i, *j) && 0 == TST_FLG(col, *j)) {
break;
}
}
if (n != *j) {
break;
}
}
}
static void find_a_star_zero_in_row(int *j, int i, int *mark, int m, int n) {
for (*j = 0; *j < n; ++*j) {
if (1 == MARK(i, *j)) {
break;
}
}
}
static int step_four(float *cost, int *mark, int m, int n, uint8_t *row_cover, uint8_t *col_cover, int *path_start_i, int *path_start_j) {
int i;
int j;
int jj;
while (1) {
find_a_noncovered_zero(&i, &j, cost, m, n, row_cover, col_cover);
if (m == i) {
return 6;
}
else {
MARK(i, j) = 2;
find_a_star_zero_in_row(&jj, i, mark, m, n);
if (m != jj) {
SET_FLG(row, i);
CLR_FLG(col, jj);
j = jj;
}
else {
*path_start_i = i;
*path_start_j = j;
return 5;
}
}
}
}
static void find_a_star_zero_in_col(int *i, int j, int *mark, int m) {
for (*i = 0; *i < m; ++*i) {
if (1 == MARK(*i, j)) {
break;
}
}
}
static void find_a_prime_zero_in_row(int *j, int i, int *mark, int m, int n) {
for (*j = 0; *j < n; ++*j) {
if (2 == MARK(i, *j)) {
break;
}
}
}
static int step_five(int *mark, int m, int n, uint8_t *row_cover, uint8_t *col_cover, int path_start_i, int path_start_j) {
static int path[64 * 2];
int i;
int j;
int k;
k = 0;
PATH(k, 0) = path_start_i;
PATH(k, 1) = path_start_j;
while (1) {
find_a_star_zero_in_col(&i, PATH(k, 1), mark, m);
if (m == i) {
goto STEP_FIVE_EXIT;
}
else {
PATH(k + 1, 0) = i;
PATH(k + 1, 1) = PATH(k, 1);
++k;
find_a_prime_zero_in_row(&j, PATH(k, 0), mark, m, n);
PATH(k + 1, 0) = PATH(k, 0);
PATH(k + 1, 1) = j;
++k;
}
}
STEP_FIVE_EXIT:
/* augment path */
for(; k >= 0; --k) {
MARK(PATH(k, 0), PATH(k, 1)) = (1 == MARK(PATH(k, 0), PATH(k, 1)) ? 0 : 1);
}
/* clear covers */
CLR_ALL(row);
CLR_ALL(col);
/* erease primes */
for (i = 0; i < m; ++i) {
for (j = 0; j < n; ++j) {
if (2 == MARK(i, j)) {
MARK(i, j) = 0;
break;
}
}
}
return 3;
}
static int step_six(float *cost, int m, int n, uint8_t *row_cover, uint8_t *col_cover) {
float min;
int i;
int j;
min = 1e6;
for (i = 0; i < m; ++i) {
for (j = 0; j < n; ++j) {
if (0 == TST_FLG(row, i) && 0 == TST_FLG(col, j)) {
if (min > COST(i, j)) {
min = COST(i, j);
}
}
}
}
for (i = 0; i < m; ++i) {
for (j = 0; j < n; ++j) {
if (0 != TST_FLG(row, i)) {
COST(i, j) += min;
}
if (0 == TST_FLG(col, j)) {
COST(i, j) -= min;
}
}
}
return 4;
}

View File

@ -0,0 +1,265 @@
/******************** (C) COPYRIGHT 2020 Geek************************************
* File Name : PDRBase.c
* Current Version : V2.0
* Author : logzhan
* Date of Issued : 2022.10.15
* Comments : PDR
********************************************************************************/
#include <math.h>
#include "PDRBase.h"
#include "Location.h"
#include "LinearFit.h"
#include "Utils.h"
#include "CoordTrans.h"
#include "Kalman.h"
extern double GpsPos[HIST_GPS_NUM][3];
int PredictStep(StepPredict* stepPredict, double timestamp, unsigned long steps_last, float gnssVel)
{
int step = 0;
float mean_time = 400;
double dis = 0;
if (stepPredict->meanTime > 0)
mean_time = stepPredict->meanTime;
if ((steps_last > 0) && (stepPredict->fnum > 0) && (timestamp - stepPredict->lastTime > mean_time * 3) && (stepPredict->lastTime > 0))
{
stepPredict->fsum = stepPredict->fsum / stepPredict->fnum;
dis = sqrt(pow(GpsPos[HIST_GPS_NUM - 1][0] - GpsPos[HIST_GPS_NUM - 2][0], 2) + pow(GpsPos[HIST_GPS_NUM - 1][1] - GpsPos[HIST_GPS_NUM - 2][1], 2)
+ pow(GpsPos[HIST_GPS_NUM - 1][2] - GpsPos[HIST_GPS_NUM - 2][2], 2));
if (stepPredict->fsum != 0.0 && (gnssVel > 1.0 || (dis > 1.0 && dis < 3.0)))
{
step = (int)((timestamp - stepPredict->lastTime) / mean_time);
stepPredict->deltaStep += step;
}
stepPredict->lastTime = timestamp;
stepPredict->fnum = 0;
stepPredict->fsum = 0;
}
return step;
}
double CalGnssTrackHeading(double gpsPos[][3], GNSS_t pgnss)
{
int i;
double lla[3] = { 0.0 };
double ned1[3] = { 0.0 };
double temp[2][HIST_GPS_NUM] = { { 0.0 } };
double angle[HIST_GPS_NUM - 1] = { 0.0 };
double ned2[3] = { 0.0 };
double maxn = 0;
double maxe = 0;
double minn = 0;
double mine = 0;
double meanx = 0;
double meany = 0;
float error = 0;
float sst = 0;
float r2 = 0;
double range = 0;
double yaw = 0;
double tempYaw = 0;
double diffAngle = 0;
double para[3] = { 0 };
int flg = 0;
lla[0] = pgnss.lat;
lla[1] = pgnss.lon;
for (i = 0; i < HIST_GPS_NUM - 1; i++)
{
gpsPos[i][0] = gpsPos[i + 1][0];
gpsPos[i][1] = gpsPos[i + 1][1];
gpsPos[i][2] = gpsPos[i + 1][2];
}
// 经纬度WGS84转地心地固坐标系ECEF
if ((lla[0] > 0) && (lla[1] > 0)){
WGS842ECEF(lla, gpsPos[HIST_GPS_NUM - 1]);
}else{
gpsPos[HIST_GPS_NUM - 1][0] = 0;
gpsPos[HIST_GPS_NUM - 1][1] = 0;
gpsPos[HIST_GPS_NUM - 1][2] = 0;
return -1;
}
if (pgnss.error > 40){
return -1;
}
for (i = 0; i < HIST_GPS_NUM - 1; i++)
{
if ((fabs(gpsPos[i][0]) < 1e-6) && (fabs(gpsPos[i][1]) < 1e-6) && (fabs(gpsPos[i][2]) < 1e-6))
{
return -1;
}
}
//地心地固坐标系ECEF转东北天坐标系NED
ECEF2NED(gpsPos[HIST_GPS_NUM - 1], lla, ned1);
for (i = HIST_GPS_NUM - 2; i >= 0; i--) {
ECEF2NED(gpsPos[i], lla, ned2);
temp[0][i] = ned1[0] - ned2[0];
temp[1][i] = ned1[1] - ned2[1];
meanx += temp[0][i] / HIST_GPS_NUM;
meany += temp[1][i] / HIST_GPS_NUM;
if (maxn > temp[0][i])
{
maxn = temp[0][i];
}
if (minn < temp[0][i])
{
minn = temp[0][i];
}
if (maxe > temp[1][i])
{
maxe = temp[1][i];
}
if (mine < temp[1][i])
{
mine = temp[1][i];
}
angle[i] = atan2(temp[1][i], temp[0][i]);
if (angle[i] < 0)
angle[i] += TWO_PI;
}
flg = leastDistanceLinearFit(temp[0], temp[1], HIST_GPS_NUM, para);
if (flg < 0)
return -1;
for (i = HIST_GPS_NUM - 1; i >= 0; i--) {
error += (float)(pow(para[0] * temp[0][i] + para[1] * temp[1][i] + para[2], 2) / (pow(para[0], 2) + pow(para[1], 2)));
sst += (float)(pow(meanx - temp[0][i], 2) + pow(meany - temp[1][i], 2));
}
if (sst > 0)
{
r2 = 1 - error / sst;
}
range = sqrt(pow(maxn - minn, 2) + pow(maxe - mine, 2));
//printf("%f,%f,%f\n", r2, error, range);
if (r2 < 0.95 || range < 1.5 || error > 3.0)
return -1;
yaw = atan(-para[0] / para[1]);
modAngle(&yaw, 0, TWO_PI);
tempYaw = meanAngle(angle, HIST_GPS_NUM - 1);
modAngle(&tempYaw, 0, TWO_PI);
diffAngle = tempYaw - yaw;
modAngle(&diffAngle, -PI, PI);
if (fabs(diffAngle) > PI / 2)
yaw += PI;
modAngle(&yaw, 0, TWO_PI);
return yaw;
}
/**----------------------------------------------------------------------
* Function : StateRecognition
* Description : 1: 0:
* Date : 2022/09/19 logzhan
*---------------------------------------------------------------------**/
void StateRecognition(float* acc, Classifer_t* sys) {
}
void calStepLastTime(StepPredict* stepPredict, double timestamp, unsigned long steps_last,
unsigned long steps)
{
float tmpTime = 0;
if (stepPredict->lastTime > 0 && stepPredict->deltaStep == 0 && (steps - steps_last) > 0)
{
tmpTime = (float)((timestamp - stepPredict->lastTime) / (steps - steps_last));
if (tmpTime > 300 && tmpTime < 800)
{
if (stepPredict->meanTime > 0) {
stepPredict->meanTime = stepPredict->meanTime * 0.5f + tmpTime * 0.5f;
}
else {
stepPredict->meanTime = tmpTime;
}
}
}
stepPredict->fnum = 0;
stepPredict->fsum = 0;
stepPredict->lastTime = timestamp;
stepPredict->deltaStep = 0;
}
/**----------------------------------------------------------------------
* Function : InsLocationPredict
* Description : PDR
* Date : 2021/02/06 logzhan :
* PDR
*---------------------------------------------------------------------**/
void InsLocationPredict(PDR_t* pdr, StepPredict* stepPredict, IMU_t* imu,
GNSS_t* pgnss, EKFPara_t* kf) {
int step;
long deltaStep;
double stepLength = 0.7;
stepPredict->fnum++;
stepPredict->fsum += pdr->motionFreq;
ulong steps = pdr->steps;
ulong lastSteps = pdr->lastSteps;
if (steps - lastSteps > 0 && pdr->motionFreq != 0.0) {
deltaStep = steps - lastSteps - stepPredict->deltaStep;
// 应该是防止计步器异常情况,一次计步特别多
if (deltaStep > 5)deltaStep = 5;
if (stepPredict->meanTime > 0)
{
step = (int)((imu->gyr.time - stepPredict->lastTime) / stepPredict->meanTime + 0.5);
if (step > deltaStep && step <= 3)deltaStep = step;
}
if (lastSteps == 0)deltaStep = 0;
if (pdr->heading > 0) {
EKFStatePredict(kf, stepLength, pdr, deltaStep);
pdr->fusionPdrFlg = PDR_TRUE;
}
calStepLastTime(stepPredict, imu->gyr.time, lastSteps, steps);
}
else {
// 有时候计步器可能考虑到稳定性暂时不更新步数因此需要利用GNSS速度预测步数达到
// 惯导更新位置的目的
int PreStep = PredictStep(stepPredict, imu->gyr.time, lastSteps, pgnss->vel);
if (pdr->heading > 0) {
EKFStatePredict(kf, stepLength, pdr, PreStep);
if (PreStep > 0)pdr->fusionPdrFlg = PDR_TRUE;
}
}
// 如果计步器可以保持较高的实时性,就可以采用下面的方法直接计算
//if (pdr->heading > 0) {
// deltaStep = steps - lastSteps;
// EKFStatePredict(kf, stepLength, pdr, deltaStep);
// pdr->fusionPdrFlg = PDR_TRUE;
//}
}

View File

@ -0,0 +1,891 @@
/******************** (C) COPYRIGHT 2020 Geek************************************
* File Name : pdr_parseData.c
* Department : Sensor Algorithm Team
* Current Version : V1.0
* Author :
* Date of Issued : 2021.01.29
* Comments : GNSS
IMUNMEA
IMU : time_ms, type, data_x, data_y, data_z
GPS time_ms, type, utc_time(second unit), $GPXXX,...
time_msmsmsms
type
NMEA$GNMEAutc(s)
********************************************************************************/
/* Header File Including -----------------------------------------------------*/
#include <stdio.h>
#include <math.h>
#include <malloc.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <stdbool.h>
#include "parseData.h"
#include "pdr_sensor.h"
#include "pdr_api.h"
extern Sensor_t SensorDataHist[IMU_LAST_COUNT];
char * strtok_ct(char * s, const char * delim)
{
static char* lasts;
if (s == 0)s = lasts;
if (*s == '\0')return 0;
lasts = s + strcspn(s, delim);
if (*lasts != 0)*lasts++ = 0;
return s;
}
/**----------------------------------------------------------------------
* Function : Int2Hex
* Description :
* Date : 2020/7/9 yuanlin@vivo.com & logzhan
*---------------------------------------------------------------------**/
char* Int2Hex(int a, char *buffer)
{
sprintf(buffer, "%X", a);
return (buffer);
}
/**----------------------------------------------------------------------
* Function : HexToDec
* Description :
* Date : 2022-09-15 logzhan
*---------------------------------------------------------------------**/
long HexToDec(char *source)
{
long sum = 0, t = 1;
int len = (int)strlen(source);
for (int i = len - 1; i >= 0; i--) {
sum += t * pdr_getIndexOfSigns(*(source + i));
t *= 16;
}
return sum;
}
/**----------------------------------------------------------------------
* Function : pdr_getIndexOfSigns
* Description : chsign
* Date : 2020/7/9 yuanlin@vivo.com &logzhan
*---------------------------------------------------------------------**/
int pdr_getIndexOfSigns(char ch)
{
if (ch >= '0' && ch <= '9')return ch - '0';
if (ch >= 'A' && ch <= 'F')return ch - 'A' + 10;
if (ch >= 'a' && ch <= 'f')return ch - 'a' + 10;
return -1;
}
void ParseIMU(char* pt, IMU_t *imu_p, double ts, int sstp)
{
int i = 0;
int j = 0;
Sensor_t data_xyz = { 0 };
Sensor_t outputData = { 0 };
data_xyz.update = 1;
while (pt && 3 > i)
{
if (0 == i)
{
data_xyz.s[0] = (float)atof(pt);
}
else if (1 == i)
{
data_xyz.s[1] = (float)atof(pt);
}
else if (2 == i)
{
data_xyz.s[2] = (float)atof(pt);
}
data_xyz.time = ts;
pt = strtok_ct(NULL, ",");
i++;
}
#if 0
if (SENSOR_ACC == sstp)
{
memcpy(&imu_p->acc, &data_xyz, sizeof(sensor_agm));
}
else if (SENSOR_MAG == sstp)
{
memcpy(&imu_p->mag, &data_xyz, sizeof(sensor_agm));
}
else if (SENSOR_GYRO == sstp)
{
memcpy(&imu_p->gyro, &data_xyz, sizeof(sensor_agm));
}
#else
data_xyz.type = sstp;
//Hist_SensorData第0位为时间上最靠前的数据
if (SensorDataHist[0].time > data_xyz.time)
{
memcpy(&outputData, &data_xyz, sizeof(Sensor_t));
}
else
{
memcpy(&outputData, &SensorDataHist[0], sizeof(Sensor_t));
for (i = IMU_LAST_COUNT - 1; i >= 0; i--)
{
if ((SensorDataHist[i].time <= data_xyz.time))
{
for (j = 1; j <= i ; j++)
{
memcpy(&SensorDataHist[j - 1], &SensorDataHist[j], sizeof(Sensor_t));
}
memcpy(&SensorDataHist[i], &data_xyz, sizeof(Sensor_t));
break;
}
}
}
if (SENSOR_ACC == outputData.type)
{
memcpy(&imu_p->acc, &outputData, sizeof(Sensor_t));
}
else if (SENSOR_MAG == outputData.type)
{
memcpy(&imu_p->mag, &outputData, sizeof(Sensor_t));
}
else if (SENSOR_GYRO == outputData.type)
{
memcpy(&imu_p->gyr, &outputData, sizeof(Sensor_t));
}
#endif
}
void parseNMEA(char* pt, Nmea_t *ln, double ts)
{
long i, result;
long s = 0 ;
char buffer[3] = {'0','0','\0'};
char* line_p = pt + strlen(pt) + 1;
//char sumBuf[3]
if (strchr(line_p, '*') == NULL)
{
return;
}
for (result = line_p[1], i = 2; line_p[i] != '*'; i++){
result ^= line_p[i];
}
buffer[0] = line_p[i + 1];
buffer[1] = line_p[i + 2];
s = HexToDec(buffer);
if (result == s) { //
pt = strtok_ct(NULL, ",");
/*printf("pt nmea l %s %u %u\n", pt,i, strcmp(pt, GNRMC_STR));*/
if (strstr(pt, GGA_STR))
{
ParseGGA(pt, ln, ts);
}
else if (strstr(pt, RMC_STR))
{
ParseRMC(pt, ln, ts);
}
else if (strstr(pt, GSV_STR))
{
parseGSV(pt, ln, ts);
}
else if (strstr(pt, GSA_STR))
{
ParseGSA(pt, ln, ts);
}
//minTime应用程序接收GPS更新的最短时间即只有超过这个时间设定系统才可能通知我们的程序说“GPS"——单位毫秒
if ((ln->minTime < 1000) || (ln->minTime > ts))
{
ln->minTime = ts;
}
if ((ln->maxTime < 1000) || (ln->maxTime < ts))
{
ln->maxTime = ts;
}
}//
else {
printf("unpass %s", line_p);
}
}
void preprocessNMEA(Nmea_t *ln)
{
if (ln->gga.update && (ln->rmc[0].update || ln->rmc[1].update) && (ln->gsa[0].update || ln->gsa[1].update || ln->gsa[2].update)
&& (ln->gsv[0].update || ln->gsv[1].update || ln->gsv[2].update))
{
ln->update = 1;
}
else
{
NmeaFlag_Init(ln);
}
}
void ParseGGA(char* pt, Nmea_t *ln, double ts)
{
if (!strcmp(pt, GNGGA_STR))
{
ln->gga.type = SENSOR_LOCATION_NMEA_GNGGA;
ln->gga.update = 1;
}
else if (!strcmp(pt, GPGGA_STR))
{
ln->gga.type = SENSOR_LOCATION_NMEA_GPGGA;
ln->gga.update = 1;
}
else
{
return;
}
int i = 0;
pt = strtok_ct(NULL, ",");
while (pt && i < 13)
{
if (pt && '\0' == *pt)
{
if (0 == i)
{
ln->gga.gga_utc = ITEM_INVALID;
}
else if (1 == i)
{
ln->gga.latitude = ITEM_INVALID;
}
else if (2 == i)
{
ln->gga.gga_latitude_ns = LATITUDE_N;
}
else if (3 == i)
{
ln->gga.longitudinal = ITEM_INVALID;
}
else if (4 == i)
{
ln->gga.longitudinal_ew = LATITUDE_N;
}
else if (5 == i)
{
ln->gga.status = invalid;
}
else if (6 == i)
{
ln->gga.satellites_nb = ITEM_INVALID;
}
else if (7 == i)
{
ln->gga.hdop = ITEM_INVALID;
}
else if (8 == i)
{
ln->gga.altitude = ITEM_INVALID;
}
else if (9 == i)
{
ln->gga.unit_a = ITEM_INVALID;
}
else if (10 == i)
{
ln->gga.height = ITEM_INVALID;
}
else if (11 == i)
{
ln->gga.unit_h = ITEM_INVALID;
}
else if (12 == i)
{
ln->gga.dgps = ITEM_INVALID;
}
else if (13 == i)
{
ln->gga.gga_check_sum[0] = '\0';
}
}
else
{
if (0 == i)
{
ln->gga.gga_utc = atof(pt);
}
else if (1 == i)
{
ln->gga.latitude = atof(pt);
}
else if (2 == i)
{
if (!strcmp(pt, NORTH))
{
ln->gga.gga_latitude_ns = LATITUDE_N;
}
else if (!strcmp(pt, SOUTH))
{
ln->gga.gga_latitude_ns = LATITUDE_S;
}
}
else if (3 == i)
{
ln->gga.longitudinal = atof(pt);
}
else if (4 == i)
{
if (!strcmp(pt, EAST))
{
ln->gga.longitudinal_ew = LONGITUDINAL_E;
}
else if (!strcmp(pt, WEST))
{
ln->gga.longitudinal_ew = LONGITUDINAL_W;
}
}
else if (5 == i)
{
ln->gga.status = (gngga_quality)atoll(pt);
}
else if (6 == i)
{
ln->gga.satellites_nb = atoi(pt);
}
else if (7 == i)
{
ln->gga.hdop = (float)atof(pt);
}
else if (8 == i)
{
ln->gga.altitude = (float)atof(pt);
}
else if (9 == i)
{
if (!strcmp(pt, "M"))
{
ln->gga.unit_a = 1;
}
}
else if (10 == i)
{
ln->gga.height = (float)atof(pt);
}
else if (11 == i)
{
if (!strcmp(pt, "M"))
{
ln->gga.unit_h = 1;
}
}
}
pt = strtok_ct(NULL, ",");
i++;
/*printf("pt %s %u\n", pt,i);*/
}
ln->gga.time = ts;
}
void ParseRMC(char* pt, Nmea_t *ln, double ts)
{
int i = 0;
double temp = 0;
double rmc_time = 0;
NmeaRMC_t *rmc = NULL;
if (!strcmp(pt, GNRMC_STR))
{
rmc = &ln->rmc[0];
RMC_Init(rmc);
rmc->type = SENSOR_LOCATION_NMEA_GNRMC;
rmc->update = 1;
}
else if (!strcmp(pt, GPRMC_STR))
{
rmc = &ln->rmc[1];
RMC_Init(rmc);
rmc->type = SENSOR_LOCATION_NMEA_GPRMC;
rmc->update = 1;
}
else
{
return;
}
pt = strtok_ct(NULL, ",");
while (pt && 12>i)
{
if (strlen(pt) > 0)
{
if (0 == i)
{
rmc_time = atof(pt);
rmc->rmc_utc = rmc_time;
}
else if (1 == i)
{
if (!strcmp(pt, "V"))
{
rmc->status = POSITIONING_N;
}
else if (!strcmp(pt, "A"))
{
rmc->status = POSITIONING_Y;
}
}
else if (2 == i)
{
temp = atof(pt);
rmc->latitude = (floor(temp / 100) + (temp - floor(temp / 100) * 100) / 60);
}
else if (3 == i)
{
if (!strcmp(pt, NORTH))
{
rmc->rmc_latitude_ns = LATITUDE_N;
}
else if (!strcmp(pt, SOUTH))
{
rmc->rmc_latitude_ns = LATITUDE_S;
}
}
else if (4 == i)
{
temp = atof(pt);
rmc->longitudinal = (floor(temp / 100) + (temp - floor(temp / 100) * 100) / 60);
}
else if (5 == i)
{
if (!strcmp(pt, EAST))
{
rmc->longitudinal_ew = LONGITUDINAL_E;
}
else if (!strcmp(pt, WEST))
{
rmc->longitudinal_ew = LONGITUDINAL_W;
}
}
else if (6 == i)
{
rmc->speed = (float)atof(pt);
}
else if (7 == i)
{
rmc->cog = (float)atof(pt);
}
else if (8 == i)
{
rmc->utc_ddmmyy = (float)atof(pt);
}
else if (9 == i)
{
rmc->magnetic = (float)atof(pt);
}
else if (10 == i)
{
if (!strcmp(pt, EAST))
{
rmc->mag_h = MAG_E;
}
else if (!strcmp(pt, WEST))
{
rmc->mag_h = MAG_W;
}
}
else if (11 == i)
{
if (!strcmp(pt, "A"))
{
rmc->mode = MODE_A;
}
else if (!strcmp(pt, "D"))
{
rmc->mode = MODE_D;
}
else if (!strcmp(pt, "E"))
{
rmc->mode = MODE_E;
}
else if (!strcmp(pt, "N"))
{
rmc->mode = MODE_N;
}
}
else if (12 == i)
{
}
}
pt = strtok_ct(NULL, ",");
i++;
}
rmc->time = ts;
}
void parseGSV(char* pt, Nmea_t *ln, double ts)
{
char *pt_gsv = NULL;
//memset(&ln->gsv, ITEM_INVALID, sizeof(ln->gsv));
int i = 0;
NmeaGSV_t* gsv = NULL;
if (!strcmp(pt, GPGSV_STR))
{
gsv = &ln->gsv[0];
gsv->type = SENSOR_LOCATION_NMEA_GPGSV;
}
else if (!strcmp(pt, GLGSV_STR))
{
gsv = &ln->gsv[1];
gsv->type = SENSOR_LOCATION_NMEA_GLGSV;
}
else if (!strcmp(pt, GAGSV_STR))
{
gsv = &ln->gsv[2];
gsv->type = SENSOR_LOCATION_NMEA_GAGSV;
}
else
{
return;
}
/*printf("gsv %s %d\n", pt, gsv->type);*/
/*printf("nmea rmc %s %u %u\n", pt, !strcmp(pt, GNRMC_STR), rmc->type);*/
pt = strtok_ct(NULL, ",");
while (pt && 3>i)
{
if (0 == i)
{
gsv->sentences = atoi(pt); //total
}
else if (1 == i)
{
gsv->sentence_number = atoi(pt); // Which term of
if (1 == gsv->sentence_number)
{
gsv->satellite_number = 0;
}
}
else if (2 == i)
{
gsv->satellites = atoi(pt); //total
break;
}
pt = strtok_ct(NULL, ",");
i++;
}
pt_gsv = strtok_ct(NULL, "*");
pt = strtok_ct(pt_gsv, ",");
i = 0;
while (pt && 16>i && gsv->satellites > 0)
{
if (pt && '\0' == *pt)
{
if (0 == i % 4)
{
gsv->satellites_data[gsv->satellite_number].prn = ITEM_INVALID;
}
else if (1 == i % 4)
{
gsv->satellites_data[gsv->satellite_number].elevation = ITEM_INVALID;
}
else if (2 == i % 4)
{
gsv->satellites_data[gsv->satellite_number].azimuth = ITEM_INVALID;
}
else if (3 == i % 4)
{
gsv->satellites_data[gsv->satellite_number].snr = ITEM_INVALID;
if (gsv->satellite_number < gsv->satellites) //satellite_number是第几个;satellites是总共的个数
{
gsv->satellite_number++;
if (gsv->satellite_number == gsv->satellites)
{
break;
}
}
}
}
else
{
if (0 == i % 4)
{
gsv->satellites_data[gsv->satellite_number].prn = atoi(pt);
if (gsv->type == SENSOR_LOCATION_NMEA_GPGSV && gsv->satellites_data[gsv->satellite_number].prn > 32)
{
gsv->satellites_data[gsv->satellite_number].prn = (gsv->satellites_data[gsv->satellite_number].prn % 32) + 1;
}
if (gsv->type == SENSOR_LOCATION_NMEA_GLGSV && gsv->satellites_data[gsv->satellite_number].prn < 65 && gsv->satellites_data[gsv->satellite_number].prn > 99)
{
gsv->satellites_data[gsv->satellite_number].prn = (gsv->satellites_data[gsv->satellite_number].prn % 35) + 65;
}
if (gsv->type == SENSOR_LOCATION_NMEA_GAGSV && gsv->satellites_data[gsv->satellite_number].prn > 36)
{
gsv->satellites_data[gsv->satellite_number].prn = (gsv->satellites_data[gsv->satellite_number].prn % 36) + 1;
}
}
else if (1 == i % 4)
{
gsv->satellites_data[gsv->satellite_number].elevation = atoi(pt); //仰角
}
else if (2 == i % 4)
{
gsv->satellites_data[gsv->satellite_number].azimuth = atoi(pt);
}
else if (3 == i % 4)
{
gsv->satellites_data[gsv->satellite_number].snr = atoi(pt);
// printf("2.gsv->satellites_data[gsv->satellite_number]: %d %d %d %d\n", gsv->satellites_data[gsv->satellite_number].prn, gsv->satellites_data[gsv->satellite_number].elevation, gsv->satellites_data[gsv->satellite_number].azimuth, gsv->satellites_data[gsv->satellite_number].snr);
if (gsv->satellite_number<gsv->satellites) //satellite_number是第几个;satellites是总共的个数
{
gsv->satellite_number++;
if (gsv->satellite_number == gsv->satellites)
{
break;
}
}
}
//printf("2.gsv->satellites_data[gsv->satellite_number]: %d %d %d %d\n", gsv->satellites_data[gsv->satellite_number].prn, gsv->satellites_data[gsv->satellite_number].elevation, gsv->satellites_data[gsv->satellite_number].azimuth, gsv->satellites_data[gsv->satellite_number].snr);
}
pt = strtok_ct(NULL, ",");
i++;
}
if (3 == i % 4 && !pt)
{
gsv->satellites_data[gsv->satellite_number].snr = ITEM_INVALID;
if (gsv->satellite_number<gsv->satellites)
{
gsv->satellite_number++;
}
}
if (gsv->satellites == gsv->satellite_number)
{
gsv->update = 1;
//printf_nmea(gsv->type,ln,PrintLOG_file_name);
}
gsv->time = ts;
}
void ParseGSA(char* pt, Nmea_t *ln, double ts)
{
int i = 0;
int idx = -1;
NmeaGSA_t gsa = {0};
if (!strcmp(pt, GNGSA_STR))
{
gsa.type = SENSOR_LOCATION_NMEA_GNGSA;
gsa.update = 1;
}
else if (!strcmp(pt, GPGSA_STR))
{
idx = 0;
gsa.type = SENSOR_LOCATION_NMEA_GPGSA;
gsa.update = 1;
}
else if (!strcmp(pt, GLGSA_STR))
{
idx = 1;
gsa.type = SENSOR_LOCATION_NMEA_GLGSA;
gsa.update = 1;
}
else if (!strcmp(pt, GAGSA_STR))
{
idx = 2;
gsa.type = SENSOR_LOCATION_NMEA_GAGSA;
gsa.update = 1;
}
else
{
return;
}
// printf("gsa %s %d\n", pt, ln->gsa.type);
pt = strtok_ct(NULL, ",");
/*printf("nmea gngsa %s %u\n", pt, i);*/
while (pt && 17>=i)
{
/*printf("%u gsa pt %s\n", i, pt);*/
if (strlen(pt) > 0)
{
if (0 == i)
{
if (!strcmp(pt, "A"))
{
gsa.mode = POSITIONING_MODE_A;
}
else if (!strcmp(pt, "M"))
{
gsa.mode = POSITIONING_MODE_M;
}
}
else if (1 == i)
{
gsa.p_type = (lct_type)atoll(pt);
}
else if (( i >= 2 ) && ( i <= 13 ))
{
gsa.prn[i - 2] = atoi(pt);
if (idx == 0 && gsa.prn[i - 2] > 32)
{
gsa.prn[i - 2] = (gsa.prn[i - 2] % 32)+1;
}
if (idx == 1 && gsa.prn[i - 2] < 65 && gsa.prn[i - 2] > 99)
{
gsa.prn[i - 2] = (gsa.prn[i - 2] % 35) + 65;
}
if (idx == 2 && gsa.prn[i - 2] > 36)
{
gsa.prn[i - 2] = (gsa.prn[i - 2] % 36)+1;
}
if (gsa.prn[i - 2] > 64)
{
gsa.prnflg |= (1 << (gsa.prn[i - 2] - 64));
if (idx < 0)
{
idx = 1;
}
}
else
{
gsa.prnflg |= (1 << gsa.prn[i - 2]);
if (idx < 0)
{
if (ln->gsa[0].update && ln->gsa[1].update)
{
idx = 2;
}
else
{
idx = 0;
}
}
}
}else if (i == 14){
gsa.pdop = (float)atof(pt);
}else if (i == 15){
gsa.hdop = (float)atof(pt);
}else if (i == 16){
gsa.vdop = (float)atof(pt);
}else if (17 == i)
{
if (idx < 0 && pt[0] == '1')
{
idx = 0;
gsa.type = SENSOR_LOCATION_NMEA_GPGSA;
}
else if (idx < 0 && pt[0] == '2')
{
idx = 1;
gsa.type = SENSOR_LOCATION_NMEA_GLGSA;
}
else if (idx < 0 && pt[0] == '3')
{
idx = 2;
gsa.type = SENSOR_LOCATION_NMEA_GAGSA;
}
}
}
pt = strtok_ct(NULL, ",");
i++;
/*printf("pt %s %u\n", pt,i);*/
}
gsa.time = ts;
if (idx >=0 && idx <=2)
{
memcpy(&ln->gsa[idx], &gsa, sizeof(NmeaGSA_t));
}
}
/**----------------------------------------------------------------------
* Function : parseLocAccuracy
* Description : GPSAccuracy
* Date : 2020/7/9 yuanlin@vivo.com &logzhan
*---------------------------------------------------------------------**/
void parseLocAccuracy(char* pt, Nmea_t *ln, double ts)
{
int i = 0;
while (pt && 8>i){
if ((i == 0) && (!strcmp(pt, "Status"))){
pt = strtok_ct(NULL, ",");
ln->accuracy.status = atoi(pt);
return;
}
if (i == 7){
ln->accuracy.update = 1;
ln->accuracy.time = ts;
if ((pt && '\0' == *pt))
{
ln->accuracy.err = -1;
}
else if (ln->accuracy.status == -1 || ln->accuracy.status == 2)
{
ln->accuracy.err = (float)atof(pt);
}
return;
}
pt = strtok_ct(NULL, ",");
i++;
}
}
/**----------------------------------------------------------------------
* Function : ParseLineStr
* Description :
* Date : 2020/7/9 yuanlin@vivo.com &logzhan
*---------------------------------------------------------------------**/
int ParseGnssInsData(char* line, IMU_t* imu_p, Nmea_t* ln)
{
char* pt = NULL;
int i = 0, sstp = -1;
double ts = 0;
pt = strtok_ct(line, ",");
while (pt && i < 2){
if (i == 0)ts = atoll(pt) * 0.000001;
else if (i == 1)sstp = atoi(pt);
pt = strtok_ct(NULL, ",");
i++;
}
switch (sstp)
{
case SENSOR_ACC:
case SENSOR_MAG:
case SENSOR_GYRO:
ParseIMU(pt, imu_p, ts, sstp);
break;
case SENSOR_LOCATION_STATELLITE:
break;
case SENSOR_LOCATION_NETWORK:
break;
case SENSOR_LOCATION_NMEA:
parseNMEA(pt, ln, ts);
if ((ln->maxTime - ln->minTime) > NAEA_LAST_TIME)
{
preprocessNMEA(ln);
}
break;
case SENSOR_LOCATION_FUSION:
parseLocAccuracy(pt, ln, ts);
break;
}
if ((ln->minTime > 0) && (ts - ln->minTime) > NAEA_LAST_TIME) {
preprocessNMEA(ln);
}
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,44 @@
#include "math.h"
#include "Quaternion.h"
const float FLT_THRES = 0.000001f; // 浮点数最小阈值
/**---------------------------------------------------------------------
* Function : QuaternionNorm
* Description :
* Date : 2022/09/21 logzhan
*---------------------------------------------------------------------**/
void QuaternionNorm(float* q0, float* q1, float* q2, float* q3) {
float norm = sqrtf(((*q0) * (*q0) + (*q1) * (*q1) +
(*q2) * (*q2) + (*q3) * (*q3)));
if (norm > FLT_THRES) {
norm = 1 / norm;
(*q0) *= norm; (*q1) *= norm;
(*q2) *= norm; (*q3) *= norm;
}
}
/**---------------------------------------------------------------------
* Function : QuaternConj
* Description :
* Date : 2022/09/21 logzhan
*---------------------------------------------------------------------**/
void QuaternConj(float _q[], float q[]) {
_q[0] = q[0];
_q[1] = -q[1];
_q[2] = -q[2];
_q[3] = -q[3];
}
/**---------------------------------------------------------------------
* Function : QuaternProd
* Description :
* Date : 2022/09/21 logzhan
*---------------------------------------------------------------------**/
void QuaternProd(float qab[], float a[], float b[]) {
qab[0] = a[0] * b[0] - a[1] * b[1] - a[2] * b[2] - a[3] * b[3];
qab[1] = a[0] * b[1] + a[1] * b[0] + a[2] * b[3] - a[3] * b[2];
qab[2] = a[0] * b[2] - a[1] * b[3] + a[2] * b[0] + a[3] * b[1];
qab[3] = a[0] * b[3] + a[1] * b[2] - a[2] * b[1] + a[3] * b[0];
}

View File

@ -0,0 +1,33 @@
#ifndef _PDR_QUATERNION_H_
#define _PDR_QUATERNION_H_
#ifdef __cplusplus
extern "C" {
#endif
/**---------------------------------------------------------------------
* Function : QuaternionNorm
* Description :
* Date : 2022/09/21 logzhan
*---------------------------------------------------------------------**/
void QuaternionNorm(float* q0, float* q1, float* q2, float* q3);
/**---------------------------------------------------------------------
* Function : QuaternConj
* Description :
* Date : 2022/09/21 logzhan
*---------------------------------------------------------------------**/
void QuaternConj(float _q[], float q[]);
/**---------------------------------------------------------------------
* Function : QuaternProd
* Description :
* Date : 2022/09/21 logzhan
*---------------------------------------------------------------------**/
void QuaternProd(float ab[], float a[], float b[]);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,492 @@
/********************************************************************/
/* FILE NAME : scene_recognition.c */
/* AUTHOR : ZhangJingrui, ID: 11082826 */
/* VERSION : V0.85_Beta (Doing) */
/* DESCRIPTION: The definations of functions in scene_recognition.h */
/********************************************************************/
#include "scene_recognition.h"
#include <stdio.h>
#include <math.h> /* fabs() */
#include <stdlib.h> /* malloc(), free() */
/* @Lai Zhilong added below code*/
#if !defined(LOCATION_PLATFORM_QCOM_MODEM) /* The Macro is in "custom.h" */
#include <malloc.h>
/* @Zhang Jingrui: The <malloc.h> header is depercated (and quite Linux specific, */
/* on which it defines non-standard functions like mallinfo(3)). Notice that the */
/* header <stdlib.h> is defined by C89 (and later) standards, but not <malloc.h>. */
#endif
#include <string.h> /* memset() */
#include <float.h> /* FLT_EPSILON */
/* Macro Defination----------------------------------------------*/
/*===============================================================*/
/* Compatible with the value in header file "sensor.h" */
#define _CONSTELLATION_USED_CAPACITY 12 /* Size of array defined as lct_nmea_gsa::prn. */
#define _CONSTELLATION_VISIBLE_CAPACITY 20 /* Size of array defined as lct_nmea_gsv::satellites_data. */
/* Satellite PRN index in _GnssInfo list. */
/* These index are planed with _GNSS_INDEX_LEN. */
/* GP: index in _GnssInfo's list is 0~31, and the PRN index is 1~32 */
#define _GP_INDEX_L 0
#define _GP_INDEX_R 31
#define _GP_INDEX_OFFSET ( _GP_INDEX_L )
#define _GP_SVID_OFFSET 1
/* GA: index in _GnssInfo's list is 32~67, and the PRN index is 1~36 */
#define _GA_INDEX_L 32
#define _GA_INDEX_R 67
#define _GA_INDEX_OFFSET ( _GA_INDEX_L )
#define _GA_SVID_OFFSET 1
/* GL: index in _GnssInfo's list is 68~102, and the PRN index is 65~99 */
#define _GL_INDEX_L 68
#define _GL_INDEX_R 102
#define _GL_INDEX_OFFSET ( _GL_INDEX_L )
#define _GL_SVID_OFFSET 65
/* Global Variable-----------------------------------------------*/
/*===============================================================*/
/* g_gnss_info_buffer: the newnest value is in the 0th sub-stucture. */
static GnssInfo* g_gnss_info_buffer = NULL;
static const int g_gnss_info_buffer_size = _TIME_BUFFER_SIZE;
/* g_gnss_info_buffer_trail: 0 ~ gnss_info_buffer_size */
static int g_gnss_info_buffer_trail = 0;
static _SCENE_MODEL_WORK_STATE g_model_state = MODEL_OFF;
/* static function Declaration-----------------------------------*/
/*===============================================================*/
/* Return @ _is_occupied: 0 -- non resource occupied. */
static int check_resources_occupied(void);
/* Return @ _is_failed: 0 -- process of free res is successful. */
static int free_resources (void);
/* Return @ _is_failed: 0 -- process of allocating res is successful. */
static int alloc_resources (void);
/* Function Name: static _lctnmea_to_gnssinfo() */
/* Usage: Transform from the updated lct_nmea structure to the _GnssInfo structure. */
/* The defination of lct_nmea is in <sensors.h>. */
/* Param @ _dst : The pointer to the target _GnssInfo structure variable.*/
/* Param @ _src_nmea : The pointer to the source lct_nmea structure varible. */
/* Return @ _parse_res_state: The transformation process result.
0--success;
-1--NULL param inputed;
1--lct_nmea _src_nmea is not valiable beacause of the update flag. */
static int lctnmea2Gnssinfo (GnssInfo *, const Nmea_t *);
/* Function name: static _detect_good_signal() */
/* Usage: judge the quality of positioning result between good and bad. */
/* Param @ _src: The pointer to the _GnssInfo structure in the positioning epoch. */
/* The value in the structure should be avaliable. */
/* Return @ _process_res: the quality of positioning result. */
/* _SIGNAL_QUALITY::GOOD -- the signal is good. */
/* _SIGNAL_QUALITY::BAD -- the signal is not good. */
static SIGNAL_QUALITY detGnssSignal (const GnssInfo *);
/* Function name: static _gnss_info_st_cpy() */
/* Usage: Deep copy from one _GnssInfo to another one. */
/* The rule of copy operation: */
/* _dst | _src | Operation behavior */
/* -------------------------------------- */
/* NULL | variable | Nothing done. */
/* NULL | NULL | Nothing done. */
/* val A | NULL | Set the value of A to the initialization value. */
/* val A | val B | Deep copy B to A. */
/* Val A | val A | Nothing done. */
/* Param @ _src: Point to the source _GnssInfo structure. */
/* Param @ _dst: Point to the target _GnssInfo structure . */
/* Return @ (void) */
static void gnss_info_st_cpy (GnssInfo *_dst, const GnssInfo *_src);
/* external function defination ---------------------------------*/
/*===============================================================*/
SCENE_INIT_STATE SceneRecog_Init(void)
{
SCENE_INIT_STATE res = INIT_NOT_PERFORMED;
int _is_occupied = -1;
int is_failed = 0;
/* Check the legality of initialization process. */
if (g_model_state == MODEL_ON)
{
return INIT_ERROR_REDUNDANCY; /* 重复初始化 */
}
/* Initialization of resources */
g_model_state = MODEL_OFF;
_is_occupied = check_resources_occupied();
if (_is_occupied)
{
free_resources();
}
is_failed = alloc_resources();
if (is_failed)
{
res = INIT_ERROR_MEMORY_INIT_FAILED;
}else{
res = INIT_SUCCESS;
g_model_state = MODEL_ON;
}
return res;
}
SCENE_INIT_STATE scene_recognition_reset(void)
{
SCENE_INIT_STATE _process_res = INIT_RESET_FAILED;
int _is_occupied = 0;
int _is_failed = 0;
if (g_model_state == MODEL_OFF)
{
_process_res = INIT_RESET_FAILED;
}
else
{
_is_occupied = check_resources_occupied();
if (_is_occupied)
{
free_resources();
}
g_model_state = MODEL_OFF;
_is_failed = alloc_resources();
if (_is_failed)
{
_process_res = INIT_RESET_FAILED;
g_model_state = MODEL_OFF;
}
else
{
_process_res = INIT_RESET_SUCCESS;
g_model_state = MODEL_ON;
}
}
return _process_res;
}
/**----------------------------------------------------------------------
* Function : sceneRecognitionProc
* Description : GNSS
* 1nmeagnss
* 2) accuracysnrGNSS
* 3)
* Input : PDRnmea
* Return :
* Author : logzhan
* Date : 2020/02/18
*---------------------------------------------------------------------**/
SCENE_RECOGNITION_RESULT sceneRecognitionProc(const Nmea_t *nmea)
{
SCENE_RECOGNITION_RESULT res = RECOG_UNKNOWN;
int transRes = 0;
SIGNAL_QUALITY detRes = SIG_UNKNOWN;
GnssInfo gnssInfo;
// 将nmea转换为gnss
transRes = lctnmea2Gnssinfo(&gnssInfo, nmea);
switch (transRes)
{
case -1:
res = RECOG_ERROR_PARAM_INCRECT;
break;
case 1:
res = RECOG_ERROR_NMEA_INFO_MISS;
break;
case 0:
// GNSS信号检测结果
detRes = detGnssSignal(&gnssInfo);
if (detRes == GOOD)
{ res = RECOG_OPEN_AREA; }
else if (detRes == BAD)
{ res = RECOG_MULTIPATH; }
else /*UNKOWN but is not exist*/
{ res = RECOG_UNKNOWN; }
break;
default:
res = RECOG_UNKNOWN;
}
return res;
}
/**----------------------------------------------------------------------
* Function : isOpenArea
* Description : GNSSGNSS
*
* Return : 0 : 1()
* Author : Zhang Jingrui, Geek ID: 11082826
* Date : 2020/02/18 logzhan
*---------------------------------------------------------------------**/
int isOpenArea(const Nmea_t *nmea)
{
SCENE_RECOGNITION_RESULT type = sceneRecognitionProc(nmea);
// 如果是开阔地则返回1
return (type == RECOG_OPEN_AREA);
}
SCENE_DESTROY_STATE scene_recognition_destroy(void)
{
SCENE_DESTROY_STATE res = DESTROY_INVALID;
if (g_model_state == MODEL_OFF){
res = DESTROY_INVALID;
}else{
// 释放资源
free_resources();
g_model_state = MODEL_OFF;
res = DESTROY_SUCCESS;
}
return res;
}
/* static function defination -----------------------------------*/
/*===============================================================*/
static int check_resources_occupied(void)
{
int res = 0;
if (g_gnss_info_buffer != NULL){
++res;
}
return res;
}
static int free_resources(void)
{
int res = 0;
if (g_gnss_info_buffer != NULL)
{
free(g_gnss_info_buffer);
}
g_gnss_info_buffer = NULL; /* The pointer should be set NULL after free() for memory safety. */
g_gnss_info_buffer_trail = 0; /* 0 because of the memory of g_gnss_info_buffer is NULL now. */
return res;
}
static int alloc_resources(void)
{
int _process_res = 0;
if (g_gnss_info_buffer != NULL)
{
/* Check the buffer's occupied. This branch is generally because of the */
/* functions flow call errors. */
_process_res = -1;
return _process_res;
}
GnssInfo *ptr = (GnssInfo *)malloc(sizeof(GnssInfo) * g_gnss_info_buffer_size);
if (ptr != NULL)
{
g_gnss_info_buffer = ptr;
g_gnss_info_buffer_trail = 0;
_process_res = 0;
}
else
{
/* Failed to apply for memory.*/
_process_res = 1;
}
return _process_res;
}
static int lctnmea2Gnssinfo(GnssInfo *_dst, const Nmea_t * _src_nmea)
{
int _parse_res_state = 0;
/* Temporarily deprecated. */
/* int _gsa_used_prn[3][_CONSTELLATION_USED_CAPACITY] = {0}; */ /* GPGSA, GLGSA, GAGSA */
int _i_first = 0;
int _i_second = 0;
int _offset[6] = { _GP_SVID_OFFSET, _GP_INDEX_OFFSET,
_GL_SVID_OFFSET, _GL_INDEX_OFFSET,
_GA_SVID_OFFSET, _GA_INDEX_OFFSET };
int _index = -1;
/* Detecting the NULL pamrameters inputed. */
if (_src_nmea == NULL || _dst == NULL)
{
_parse_res_state = -1;
}
/* Detecting the _src_nmea if it wasn't updated. */
else if (_src_nmea->update == 0)
{
_parse_res_state = 1;
}
/*****************************************************************/
/* DELETE: abandon this branch for the stability of the program. */
/* Detecting the incorrect accuracy value. */
/*else if ((_src_nmea->accuracy.update == 0) ||
(_src_nmea->accuracy.update == 0) )
{
_parse_res_state = 2;
}*/
/****************************************************************/
/* update the the _GnssInfo. */
else
{
/* initialize the memory space pointed by _dst to all 0. */
gnss_info_st_cpy(_dst, NULL);
/* pick the raw accuracy from lct_nmea::loc_accuracy. Therefore _dst->accuracy
could be equal with ITEM_INVALID. */
_dst->accuracy = _src_nmea->accuracy.err;
/* pick the aviable satellites PRN from GxGSA and match the SNR value in
GxGSV where Gx is the presented to GP, GA or GL. */
for (_i_first = 0 ; _i_first < 3 ; ++ _i_first) /* 0 - GP, 1 - GL, 2 - GA */
{
/* make sure the GxGSA and GxGSV has been update in the epoch */
if (_src_nmea->gsa[_i_first].update == 0 || _src_nmea->gsv[_i_first].update == 0)
{
continue;
}
/* copy all the PRN number in GSA to the _dst pointed _GnssInfo */
for (_i_second = 0 ;
_i_second < _CONSTELLATION_USED_CAPACITY &&
_src_nmea->gsa[_i_first].prn[_i_second] != 0 &&
_src_nmea->gsa[_i_first].prn[_i_second] != ITEM_INVALID ;
++ _i_second)
{
_index = _src_nmea->gsa[_i_first].prn[_i_second]
- _offset[_i_first*2] + _offset[_i_first*2 + 1];
if (_index > 0)
{
_dst->sat_used_list[_index] = 1;
}
}
/* copy all the SNR values in GSV to the _dst pointed _GnssInfo */
for (_i_second = 0 ;
(_i_second < _CONSTELLATION_VISIBLE_CAPACITY) &&
_src_nmea->gsv[_i_first].satellites_data[_i_second].snr != ITEM_INVALID ;
++ _i_second)
{
_index = _src_nmea->gsv[_i_first].satellites_data[_i_second].prn
- _offset[_i_first*2] + _offset[_i_first*2 + 1];
if (_index > 0)
{
_dst->snr_list[_index] = (float)(_src_nmea->gsv[_i_first].satellites_data[_i_second].snr);
}
}
}
_dst->update = 1;
_parse_res_state = 0;
}
return _parse_res_state;
}
/**---------------------------------------------------------------------
* Function : detGnssSignal
* Description : GPS
* 1Accuracy05
* 2Accuracy510使
* GPS
* 3Accuracy10GPS
* Date : 2020/02/18 logzhan
*---------------------------------------------------------------------**/
static SIGNAL_QUALITY detGnssSignal(const GnssInfo* _src)
{
SIGNAL_QUALITY procRes = SIG_UNKNOWN;
int i = 0;
float accuracy = 0;
float snr_large_rate = 0;
int sat_used_num = 0; // 卫星使用数量
/* Simulating a Queue data structure which can be optimazated in the future. */
/* move all the elements to the right one memory and abandon the rightmost one.*/
for (i = 0 ; i < g_gnss_info_buffer_size - 1 ; ++ i)
{
gnss_info_st_cpy((g_gnss_info_buffer + i + 1) , (g_gnss_info_buffer + i) );
}
/* Enqueue where the new element struct is put in the leftmost gpsFusionLocation of the array. */
gnss_info_st_cpy((g_gnss_info_buffer), _src);
if (g_gnss_info_buffer_trail < g_gnss_info_buffer_size)
{
++ g_gnss_info_buffer_trail;
}
/* make sure _src->accuracy is available otherwise the quality of signal is not correct. */
if (fabs(_src->accuracy - ITEM_INVALID) < FLT_EPSILON )
{
procRes = SIG_UNKNOWN;
return procRes;
}
/* features extraction */
for (i = 0 ; i < _GNSS_INDEX_LEN ; ++ i)
{
if (_src->sat_used_list[i] == 1 && _src->snr_list[i] > 20)
{
++ snr_large_rate;
}
}
sat_used_num = _src->sat_visible_number;
accuracy = _src->accuracy;
snr_large_rate = sat_used_num > 0 ? (snr_large_rate / sat_used_num) : 0 ;
/* classification process BEGIN */
if (accuracy > 0 && accuracy < (5 + FLT_EPSILON) )
{ procRes = GOOD; }
else if (accuracy > (10 + FLT_EPSILON) )
{ procRes = BAD; }
else
{
/* 5 <= _accuracy <= 10 */
if (snr_large_rate < 0.878676)
{
if (snr_large_rate < 0.781746)
{ procRes = BAD; }
else
{
if (sat_used_num < 18.5)
{ procRes = BAD; }
else
{ procRes = GOOD; }
}
}else{
if (accuracy > 0 && accuracy < 9.2)
{ procRes = GOOD; }
else
{ procRes = BAD; }
}
}
/* classification process END */
return procRes;
}
static void gnss_info_st_cpy(GnssInfo *_dst, const GnssInfo *_src)
{
if (_dst != NULL && _src == NULL)
{
/* initialize _dst if _src is a empty pointer. */
_dst->update = 0;
_dst->local_timestamp = 0;
_dst->accuracy = 0;
_dst->sat_visible_number = 0;
memset(_dst->snr_list, 0, sizeof(_dst->snr_list) );
memset(_dst->sat_used_list, 0, sizeof(_dst->sat_used_list) );
}
else if (_dst != NULL && _src != NULL && _dst != _src)
{
/* deep copy from _src to _dst if both of them isn't empty and not equal. */
_dst->update = _src->update;
_dst->local_timestamp = _src->local_timestamp;
_dst->accuracy = _src->accuracy;
_dst->sat_visible_number = _src->sat_visible_number;
memcpy(_dst->snr_list, _src->snr_list, sizeof(_src->snr_list) );
memcpy(_dst->sat_used_list, _src->sat_used_list, sizeof(_src->sat_used_list) );
}
else
{
/* _dst and _src are both NULL pointer, then PASS. */
/* _dst is NULL pointer, then PASS. */
/* _dst and _src are both pointer to the same memory, then PASS. */
}
}

View File

@ -0,0 +1,465 @@
/******************** (C) COPYRIGHT 2020 Geek************************************
* File Name : pdr_util.c
* Department : Sensor Algorithm Team
* Current Version : V1.2
* Author : logzhan
* Date of Issued : 2020.7.4
* Comments : PDR
********************************************************************************/
/* Header File Including -----------------------------------------------------*/
#include <stdio.h>
#include <math.h>
#include <float.h>
#include "PDRBase.h"
#include "Utils.h"
#include "CoordTrans.h"
const float FLT_THRES = 0.000001f; // 浮点数最小阈值
/* Function Declaration ------------------------------------------------------*/
/**----------------------------------------------------------------------
* Function : mean
* Description : double
* Review :
*
* Date : 2020/7/4 logzhan
*---------------------------------------------------------------------**/
double mean(double *data, int len) {
int i;
double value = 0;
for (i = 0; i < len; i++) {
value += data[i] / len;
}
return value;
}
/**----------------------------------------------------------------------
* Function : fmean
* Description : float
* Review :
*
* Date : 2020/7/4 logzhan
*---------------------------------------------------------------------**/
float fmean(float *data, int len)
{
float value = 0;
for (int i = 0; i < len; i++){
value += data[i] / len;
}
return value;
}
double meanAngle(double* angle, int len)
{
double baseAngle = angle[0];
double diff = 0.0;
double sum = 0.0;
double value = 0;
if (len <= 0)return 0;
for (int i = 0; i < len; i++)
{
diff = angle[i] - baseAngle;
if (diff > PI)
{
diff = diff - TWO_PI;
}
else if (diff < -PI)
{
diff = diff + TWO_PI;
}
sum += (baseAngle + diff);
}
value = sum / len;
modAngle(&value, 0, TWO_PI);
return value;
}
void modAngle(double * angle, double min, double max)
{
double value = *angle;
double range = max - min;
while (value > max)value = value - range;
while (value < min)value = value + range;
*angle = value;
}
float stdf(float* data, int len)
{
int i;
float meanValue = fmean(data, len);
float value = 0;
for (i = 0; i < len; i++)
{
value += (data[i] - meanValue) * (data[i] - meanValue) / len;
}
return (float)sqrt(value);
}
/**----------------------------------------------------------------------
* Function : pdr_invSqrt
* Description : 1/sqrt(x)
* Date : 2020/6/30 logzhan
*---------------------------------------------------------------------**/
float InvSqrt(float x) {
float xHalf = 0.5f * x;
int i = *(int *)&x;
i = 0x5f3759df - (i >> 1);
x = *(float *)&i;
x = x * (1.5f - xHalf * x * x);
return x;
}
/**---------------------------------------------------------------------
* Function : Vec3Norm
* Description :
* Date : 2022/11/1 logzhan
*---------------------------------------------------------------------**/
void Vec3Norm(float* vx, float* vy, float* vz)
{
float norm = sqrtf(((*vx) * (*vx) + (*vy) * (*vy) +
(*vz) * (*vz)));
// 防止出现模为0的情况
if (norm > FLT_THRES) {
norm = 1 / norm;
(*vx) *= norm; (*vy) *= norm; (*vz) *= norm;
}
}
/**----------------------------------------------------------------------
* Function : Motion2TypeStr
* Description :
* Date : 2022/9/16 logzhan
*---------------------------------------------------------------------**/
const char* Motion2TypeStr(int type)
{
if (type == PDR_MOTION_TYPE_STATIC) {
return "STATIC";
}
else if (type == PDR_MOTION_TYPE_IRREGULAR) {
return "IRREGULAR";
}
else if (type == PDR_MOTION_TYPE_HANDHELD) {
return "HANDLED";
}
else if (type == PDR_MOTION_TYPE_SWINGING) {
return "SWINGING";
}
return "UNKOWN";
}
/**----------------------------------------------------------------------
* Function : qnb2att
* Description :
* Date : 2020/7/4 logzhan
*---------------------------------------------------------------------**/
void Qnb2Att(float* q, double* attitude)
{
double q11 = q[0] * q[0]; double q13 = q[0] * q[2];
double q12 = q[0] * q[1]; double q14 = q[0] * q[3];
double q22 = q[1] * q[1]; double q24 = q[1] * q[3];
double q23 = q[1] * q[2]; double q33 = q[2] * q[2];
double q34 = q[2] * q[3]; double q44 = q[3] * q[3];
if (fabs(q34 + q12) <= 0.5) {
attitude[0] = asin(2 * (q34 + q12));
}
attitude[1] = atan2(-2 * (q24 - q13), q11 - q22 - q33 + q44);
attitude[2] = atan2(-2 * (q23 - q14), q11 - q22 + q33 - q44);
}
void GetCovMatrix(double *x, double *y, double cov[2][2], int n) {
int i;
double sum_x = 0, sum_y = 0, sum_xy = 0;
double m_x = 0, m_y = 0;
m_x = mean(x, n);
m_y = mean(y, n);
for (i = 0; i < n; i++) {
sum_xy += (x[i] - m_x)*(y[i] - m_y);
sum_x += (x[i] - m_x)*(x[i] - m_x);
sum_y += (y[i] - m_y)*(y[i] - m_y);
}
cov[0][0] = sum_x / n;
cov[0][1] = sum_xy / n;
cov[1][0] = sum_xy / n;
cov[1][1] = sum_y / n;
}
int Jacobi(double a[][2], double p[][2], int n, double eps, int T)
{
int i, j, k;
double max = a[0][1];
int row = 0;
int col = 0;
int ite_num = 0;
double theta = 0;
double aii = 0;
double ajj = 0;
double aij = 0;
double sin_theta = 0;
double cos_theta = 0;
double sin_2theta = 0;
double cos_2theta = 0;
double arowk = 0;
double acolk = 0;
double pki = 0;
double pkj = 0;
for (i = 0; i < n; i++)
p[i][i] = 1;
while (1)
{
max = fabs(a[0][1]);
row = 0;
col = 1;
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
if (i != j && fabs(a[i][j])>max)
{
max = fabs(a[i][j]);
row = i;
col = j;
}
if (max < eps)
{
//printf("max : %lf \n", max);
//printf("t : %lf \n", ite_num);
return 1;
}
if (ite_num>T)
{
//printf("max : %lf \n", max);
//printf("t : %lf \n", ite_num);
return 0;
}
if (a[row][row] == a[col][col])
theta = PI / 4;
else
theta = 0.5*atan(2 * a[row][col] / (a[row][row] - a[col][col]));
aii = a[row][row];
ajj = a[col][col];
aij = a[row][col];
sin_theta = sin(theta);
cos_theta = cos(theta);
sin_2theta = sin(2 * theta);
cos_2theta = cos(2 * theta);
a[row][row] = aii * cos_theta*cos_theta + ajj * sin_theta*sin_theta + aij * sin_2theta;
a[col][col] = aii * sin_theta*sin_theta + ajj * cos_theta*cos_theta - aij * sin_2theta;
a[row][col] = 0.5*(ajj - aii)*sin_2theta + aij * cos_2theta;
a[col][row] = a[row][col];
for (k = 0; k < n; k++)
{
if (k != row && k != col)
{
arowk = a[row][k];
acolk = a[col][k];
a[row][k] = arowk * cos_theta + acolk * sin_theta;
a[k][row] = a[row][k];
a[col][k] = acolk * cos_theta - arowk * sin_theta;
a[k][col] = a[col][k];
}
}
if (ite_num == 0)
{
p[row][row] = cos_theta;
p[row][col] = -sin_theta;
p[col][row] = sin_theta;
p[col][col] = cos_theta;
}
else
{
for (k = 0; k < n; k++)
{
pki = p[k][row];
pkj = p[k][col];
p[k][row] = pki * cos_theta + pkj * sin_theta;
p[k][col] = pkj * cos_theta - pki * sin_theta;
}
}
ite_num++;
}
}
static int isRealLat(double lat){ return (lat < 90) && (lat > -90); }
static int isRealLon(double lon){ return (lon < 180) && (lon > -180); }
/*
function: 线
param @ pointA : A
param @ pointB : B
return @ dis : AB0AB
*/
double CalDistance(LatLng_t pointA, LatLng_t pointB)
{
double dis = -1;
double lla1[3] = { 0 };
double lla2[3] = { 0 };
double ned1[3] = { 0 };
double ned2[3] = { 0 };
double diff_ned[3] = { 0 };
lla1[0] = pointA.lat * RADIAN_PER_DEG;
lla1[1] = pointA.lon * RADIAN_PER_DEG;
lla2[0] = pointB.lat * RADIAN_PER_DEG;
lla2[1] = pointB.lon * RADIAN_PER_DEG;
if (isRealLat(pointA.lat) && isRealLon(pointA.lon)
&& isRealLat(pointB.lat) && isRealLon(pointB.lon))
{
WGS842NED(lla1, lla1, ned1);
WGS842NED(lla2, lla1, ned2);
diff_ned[0] = ned1[0] - ned2[0];
diff_ned[1] = ned1[1] - ned2[1];
diff_ned[2] = ned1[2] - ned2[2];
dis = sqrt(pow(diff_ned[0], 2) + pow(diff_ned[1], 2) + pow(diff_ned[2], 2));
}
return dis;
}
LatLng_t ProjPointOfLatLng(LatLng_t point, LatLng_t linePointA, LatLng_t linePointB)
{
/* local variables declaration */
double gradxB_P; /* linePointB 向 point 的 x 梯度 */
double gradxB_A; /* linePointA 向 linePointB 的 x 梯度 */
double gradyB_A; /* linePointA 向 linePointB 的 y 梯度 */
double normPow; /* linePointA 向 linePointB 梯度的平方和 */
double scalarMultip; /* gradxB_A * gradyB_A 的标量乘法 */
LatLng_t resProjPoint; /* 结果点坐标 */
/* block process */
gradxB_A = linePointA.lat - linePointB.lat;
gradyB_A = linePointA.lon - linePointB.lon;
if ((fabs(gradxB_A) < DBL_EPSILON) && (fabs(gradyB_A) < DBL_EPSILON))
{
/* 当linePointA 和linePointB是同一点时返回的point坐标 */
resProjPoint.lat = point.lat;
resProjPoint.lon = point.lon;
}
else
{
gradxB_P = point.lat - linePointB.lat;
normPow = pow(gradxB_A, 2) + pow(gradyB_A, 2);
resProjPoint.lon = (double)(
(gradxB_P * gradxB_A * gradyB_A + point.lon * pow(gradyB_A, 2) + linePointB.lon * pow(gradxB_A, 2)) / normPow);
if ((fabs(gradxB_A) < DBL_EPSILON) || (fabs(gradyB_A) < DBL_EPSILON))
{
/* 当linePointA 和 linePointB 所在直线与 x轴或y轴平行时做规避*/
scalarMultip = (fabs(gradxB_A) < DBL_EPSILON) ? gradyB_A : gradxB_A;
}
else
{
scalarMultip = gradxB_A * gradyB_A;
}
resProjPoint.lat = (double)(
(gradxB_A * linePointB.lat * gradyB_A + gradxB_A * gradxB_A * (resProjPoint.lon - linePointB.lon)) / scalarMultip);
if (fabs(gradxB_A) < DBL_EPSILON)
{
resProjPoint.lat = linePointA.lat;
}
if (fabs(gradyB_A) < DBL_EPSILON)
{
resProjPoint.lon = point.lon;
}
}
return resProjPoint;
}
/**----------------------------------------------------------------------
* Function : CalEarthParameter
* Description :
* Date : 2020/7/8 logzhan
*---------------------------------------------------------------------**/
EarthData_t CalEarthParameter(double lat)
{
double temp_value = 0;
EarthData_t earthData = { 0 };
if (fabs(lat) >= PI / 2)lat = 0.0f;
temp_value = sqrt(1 - WGS84_ECCENTR2 * (sin(lat)*sin(lat)));
earthData.lat = lat;
earthData.rmh = WGS84_RE * (1 - WGS84_ECCENTR2) / (temp_value*temp_value*temp_value);
earthData.rnh = WGS84_RE * cos(lat) / temp_value;
return earthData;
}
/**----------------------------------------------------------------------
* Function : pdr_CalRadianDifferent
* Description :
* Date : 2020/7/8 logzhan
*---------------------------------------------------------------------**/
double CalRadianDifferent(double s_dir, double d_dir)
{
double dirDiff = d_dir - s_dir;
if (fabs(dirDiff) < PI)return dirDiff;
return dirDiff > 0 ? dirDiff - 2 * PI : dirDiff + 2 * PI;
}
void ProjPointOfLatLng_cir(double point1[], double yaw, double point2[], double result[])
{
if (fabs(fabs(yaw) - PI / 2) < DOUBLE_ZERO)
{
result[0] = point1[0];
result[1] = point2[1];
return;
}
EarthData_t earthData = CalEarthParameter(point1[0]);
double k = -tan(yaw);
double lonDiff = (point2[1] - point1[1]) * earthData.rnh;
double latDiff = (point2[0] - point1[0]) * earthData.rmh;
double x = (k*latDiff + k * k * lonDiff) / (1 + k * k);
double y = (latDiff + k * lonDiff) / (1 + k * k);
result[1] = point1[1] + x / earthData.rnh;
result[0] = point1[0] + y / earthData.rmh;
}
/**----------------------------------------------------------------------
* Function : pdr_WriteCsvStr
* Description : fprintf
* Date : 2020/7/8 logzhan
*---------------------------------------------------------------------**/
void WriteCsvStr(FILE* fp_write, char* str)
{
if (NULL == fp_write)return;
fprintf(fp_write, "%s\n", str);
}
int pdr_min(int a, int b){
return (a > b ? b : a);
}
/**----------------------------------------------------------------------
* Function : pdr_utc2hms
* Description : UTC
* Date : 2020/7/8 logzhan
*---------------------------------------------------------------------**/
void pdr_utc2hms(double utc, double* h, double* m, double* s) {
long lutc = (long)(utc / 1000);
lutc = lutc % (3600 * 24);
*h = floor((double)(lutc / (3600)));
*m = floor((lutc - (*h) * 3600) / 60);
*s = lutc - (*h) * 3600 - (*m) * 60;
}

View File

@ -0,0 +1,7 @@
/* Header File Including ------------------------------------------------------------------------ */
#include <stdint.h>
#include <math.h>
#include <string.h>
#include "imu.h"
#include "ahrs.h"
#include "detector.h"

View File

@ -0,0 +1,7 @@
/* Header File Including ------------------------------------------------------------------------ */
#include <string.h>
#include <math.h>
#include "m_gps.h"
#include "pdr_util.h"
#include "pdr.h"