重构代码,删除冗余版本

PDRHistoryBranch
詹力 2024-12-06 21:30:26 +08:00
parent f77aeb5ab8
commit 318dad3572
549 changed files with 2699 additions and 62409 deletions

View File

@ -1,43 +0,0 @@
#ifndef __FILTER_H__
#define __FILTER_H__
/* Macro Declaration ---------------------------------------------------------------------------- */
#define FILTER_COEF_MAX_LENGTH 71
#define FILTER_FIR_COEF_MAX_LENGTH 71
/* Structure Declaration ------------------------------------------------------------------------ */
typedef struct FILTER { // iir or fir filter
int reset; // reset flag
int order; // coefficient array length, not filter order
double H0; // dc signal gain
double b[FILTER_COEF_MAX_LENGTH]; // b coefficient
double a[FILTER_COEF_MAX_LENGTH]; // a coefficient
double yout[FILTER_COEF_MAX_LENGTH]; // yout buffer
double xin[FILTER_COEF_MAX_LENGTH]; // xin buffer
} FILTER;
typedef struct FILTER_FIR { // fir filter
int reset; // reset flag
int order; // coefficient array length, not filter order
double H0; // dc signal gain
double b[FILTER_FIR_COEF_MAX_LENGTH]; // b coefficient
double xin[FILTER_FIR_COEF_MAX_LENGTH]; // xin buffer
} FILTER_FIR;
typedef struct DELAYER { // delayer
int reset;
int delay; // delay point number
double xin[FILTER_FIR_COEF_MAX_LENGTH]; // xin buffer
} DELAYER;
/* Function Declaration ------------------------------------------------------------------------- */
extern void FILTER_reset(FILTER *f);
extern void FILTER_FIR_reset(FILTER_FIR *f);
extern void FILTER_setCoef(FILTER *f, int order, double *b, double *a, double H0);
extern void FILTER_FIR_setCoef(FILTER_FIR *f, int order, double *b, double H0);
extern double FILTER_filter(FILTER *f, double x);
extern double FILTER_FIR_filter(FILTER_FIR *f, double x);
extern void DELAY_reset(DELAYER *d);
extern void DELAY_setCoef(DELAYER *d, int delay);
extern double DELAY_delay(DELAYER *d, double x);
#endif

View File

@ -1,43 +0,0 @@
#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;
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

@ -1,77 +0,0 @@
#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;
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 Buffer_initialize(BUFFER *buffer, const char *name, int type, int length);
int Buffer_clear(BUFFER *buffer);
int Buffer_count(BUFFER *buffer, int *count);
int Buffer_top(BUFFER *buffer, float *value);
int Buffer_bottom(BUFFER *buffer, float *value);
int Buffer_pop(BUFFER *buffer, float *value);
int buffer_push(BUFFER *buffer, float value);
int Buffer_get(BUFFER *buffer, float *value, int index);
int Buffer_mean(BUFFER *buffer, float *mean);
int Buffer_var(BUFFER *buffer, float *var);
int Buffer_std(BUFFER *buffer, float *std);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,110 +0,0 @@
#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 *imu_p, double ts, int sstp);
/**************************************************************************
* Description : NMEA
* Input : pt NMEA
ts ms
* Output : ln NMEA
**************************************************************************/
void parseNMEA(char* pt, lct_nmea *ln, double ts);
/**************************************************************************
* Description : GGA
* Input : pt NMEA
ts ms
* Output : ln NMEA
**************************************************************************/
void ParseGGA(char* pt, lct_nmea *ln, double ts);
/**************************************************************************
* Description : RMC
* Input : pt NMEA
ts ms
* Output : ln NMEA
**************************************************************************/
void ParseRMC(char* pt, lct_nmea *ln, double ts);
/**************************************************************************
* Description : GSV
* Input : pt NMEA
ts ms
* Output : ln NMEA
**************************************************************************/
void parseGSV(char* pt, lct_nmea *ln, double ts);
/**************************************************************************
* Description : GSA
* Input : pt NMEA
ts ms
* Output : ln NMEA
**************************************************************************/
void ParseGSA(char* pt, lct_nmea *ln, double ts);
/**----------------------------------------------------------------------
* Function : parseLocAccuracy
* Description : GPSAccuracy
* Date : 2020/7/9 yuanlin@vivo.com &logzhan
*---------------------------------------------------------------------**/
void parseLocAccuracy(char* pt, lct_nmea *ln, double ts);
/**************************************************************************
* Description : NMEA
* Input : ln NMEA
**************************************************************************/
void preprocessNMEA(lct_nmea *ln);
int pdr_parseLineStr(char* line, imu* imu_p, lct_nmea* 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

@ -1,48 +0,0 @@
#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 pdr_initAhrs(void);
void pdr_ahrsReset(void);
/**---------------------------------------------------------------------
* Function : fv3Norm
* Description :
* Date : 2021/01/26 yuanlin@vivocom &&
*
*
*---------------------------------------------------------------------**/
void fv3Norm(float* vx, float* vy, float* vz);
int pdr_imuUpdateAhrs(imu* imu);
#ifdef __cplusplus
}
#endif
#endif // for __AHRS_H

View File

@ -1,157 +0,0 @@
/******************** (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 "pdr_base.h"
#include "pdr_util.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 : pdr_algorithmInit
* Description : PDRPDR
*
* Date : 2020/7/3 logzhan
*---------------------------------------------------------------------**/
void Algorithm_Init(void);
/**---------------------------------------------------------------------
* Function : pdr_locationMainLoop
* Description : PDR
*
* Input : ss_data
nmea_data, NMEA
result
* Output : int,
* Date : 2020/7/3 logzhan
*---------------------------------------------------------------------**/
int pdr_locationMainLoop(imu *ss_data, lct_nmea *nmea_data, lct_fs *result,
FILE *fp_gps);
/**---------------------------------------------------------------------
* Function : pdr_locationMainLoopStr
* Description : PDR
*
* Date : 2020/07/03 logzhan
* 2020/02/02 logzhan :
*---------------------------------------------------------------------**/
int pdr_locationMainLoopStr(char* line, lct_fs* result);
/**---------------------------------------------------------------------
* Function : pdr_initRmc
* Description : RMC
* Input : rmc RMC
* Date : 2020/7/3 logzhan
*---------------------------------------------------------------------**/
void RMC_Init(lct_nmea_rmc * rmc);
/**---------------------------------------------------------------------
* Function : pdr_initNmeaFlg
* Description : GPSNMEA
* Input : ln NMEA
* Date : 2020/7/3 logzhan
*---------------------------------------------------------------------**/
void NmeaFlag_Init(lct_nmea * ln);
/**---------------------------------------------------------------------
* Function : clearNmeaFlg
* Description : Nmea,init
* Date : 2020/7/4 logzhan
*---------------------------------------------------------------------**/
void clearNmeaFlg(lct_nmea * ln);
/**---------------------------------------------------------------------
* Function : pdr_saveGnssInfo
* Description : GPS
* Date : 2020/7/3 logzhan
*---------------------------------------------------------------------**/
void pdr_saveGnssInfo(lct_nmea* nmea_data, lct_fs* result, FILE* fp_gps);
/**----------------------------------------------------------------------
* Function : pdr_libVersion
* Description : pdr
* Date : 2020/8/3 logzhan
*---------------------------------------------------------------------**/
const char* pdr_libVersion(void);
/**----------------------------------------------------------------------
* Function : pdr_closeAlgorithm
* Description : PDR,
* Date : 2020/8/3 logzhan
*---------------------------------------------------------------------**/
void pdr_closeAlgorithm();
#ifdef _WIN32 // 主要用于支持win32调试使用用于dll接口导出
/**----------------------------------------------------------------------
* Function : LibPDR_Init
* Description : PDR(DLL)
* Date : 2020/8/3 logzhan
*---------------------------------------------------------------------**/
__declspec(dllexport) void LibPDR_Init();
/**----------------------------------------------------------------------
* Function : pdrSumulatorUpdateGpsStep
* Description : 仿GPS(DLL)
* Date : 2020/8/3 logzhan
*---------------------------------------------------------------------**/
__declspec(dllexport) PosFusion pdrSumulatorUpdateGpsStep(int useGpsFlg);
/**----------------------------------------------------------------------
* Function : setSimulatorFileCsvPath
* Description : 仿(DLL)
* Date : 2020/8/3 logzhan
*---------------------------------------------------------------------**/
__declspec(dllexport) void setSimulatorFileCsvPath(char* path);
/**----------------------------------------------------------------------
* Function : closePdrAlgo
* Description : pdrdll(DLL)
* Date : 2020/8/3 logzhan
*---------------------------------------------------------------------**/
__declspec(dllexport) void closePdrAlgo();
/**----------------------------------------------------------------------
* Function : setRefGpsYaw
* Description : GPS
* Date : 2020/8/3 logzhan
*---------------------------------------------------------------------**/
__declspec(dllexport) void setRefGpsYaw();
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,345 +0,0 @@
/******************** (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 p_xk[N]; // 最佳预测变量Xk_predict xk[0]: 北向x xk[1]东向y xk[2]:步长 xk[3] :航向角
double zk[N];
double p_pk[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;
}KfPara;
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 noGpsCount; // 没有GPS次数
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 pca_accuracy;
float bias_direction[2];
float bias_accuracy;
float cal_direction[2];
} PDR;
typedef struct {
int type;
float accBuffer[PATTERN_RECOGNITION_LEN];
}classifer;
// 用户运动类型分类器
typedef struct DETECTOR {
uint32_t type; // 用户运动类别 0:静止运动 1无规律运动 2手持运动 3摆手运动
uint32_t lastType;
uint64_t tick; // 次数统计,用于调整检测器工作频率
} DETECTOR;
DETECTOR *pdr_getDetector(void);
/* Function Declaration ------------------------------------------------------*/
PDR* pdr_initBase(void);
/**----------------------------------------------------------------------
* Function : pdr_resetData
* Description : PDR
* Date : 2020/7/21
*
*---------------------------------------------------------------------**/
void pdr_resetData(void);
/**----------------------------------------------------------------------
* Function : pdr_computePCA
* Description : RESET_PHASE_1\STABLEPCA
* Date : 2020/7/21 logzhan
*---------------------------------------------------------------------**/
void pdr_computePCA(AHRS* ahrs);
/**---------------------------------------------------------------------
* Function : detectorUpdate
* Description : g_pdr.status
* Date : 2020/7/20 logzhan
*---------------------------------------------------------------------**/
void detectorUpdate(DETECTOR* detector);
void gpsUpdateCb(gnss* gps);
/**************************************************************************
* 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 *sys);
/**************************************************************************
* Description : GPSGPSPDR
* Input : g_pdrPDR
sys
gps_yawGPS
G_yawGPS
ss_data
* Output : double
**************************************************************************/
double calPredAngle(PDR *g_pdr, classifer *sys, double gps_yaw, double G_yaw, imu *ss_data);
/**************************************************************************
* Description : GPSGPSPDR
* Input : g_pdrPDR
steps
steps_last
stepPredict
pdr_angle
scene_typeGPS
ss_data
pgnssGPS
kfEKF
pdr, PDR
**************************************************************************/
void pdr_insPredict(PDR *g_pdr, StepPredict *stepPredict,imu *ss_data,
gnss *pgnss, KfPara *kf);
/**----------------------------------------------------------------------
* Function : pdr_detStatic
* Description :
* Date : 2021/01/28 logzhan
*---------------------------------------------------------------------**/
int pdr_detStatic(PDR *g_pdr, gnss *pgnss, unsigned long delSteps);
/**----------------------------------------------------------------------
* Function : pdr_outputGpsPos
* Description : GPS
* Date : 2020/07/08 logzhan
*---------------------------------------------------------------------**/
void pdr_outputGpsPos(gnss *pgnss, lct_fs *result);
/**----------------------------------------------------------------------
* Function : resetOutputResult
* Description : 1
* 2GPSresult
* pgnssGPS
* plla_initNED
* x_inity_initNEDne
* kf EKF
* Date : 2020/07/08 logzhan
*---------------------------------------------------------------------**/
int resetOutputResult(gnss *pgnss, PDR* g_pdr, KfPara *kf, lct_fs *result);
/**----------------------------------------------------------------------
* Function : detIsCarMode
* Description :
* Input : pgnssGPS
g_pdrPDR
delSteps
time
* Output : int
* Date : 2021/01/28 logzhan
*---------------------------------------------------------------------**/
int detIsCarMode(gnss *pgnss, PDR *g_pdr, unsigned long delSteps, int *time);
/**----------------------------------------------------------------------
* Function : detPdrToReset
* Description : PDRPDR
* PDRGPS
* Date : 2021/01/28 logzhan
*---------------------------------------------------------------------**/
int detPdrToReset(double pdr_angle, int *gpscnt, unsigned long deltsteps, PDR *g_pdr);
/**************************************************************************
* Description : EKF
* Input : pgnssGPS
plla_initNED
kf EKF
x_inity_initNEDne
sys_status
* Output : int
result
**************************************************************************/
int pdr_initProc(gnss *pgnss, KfPara *kf, PDR* g_pdr, lct_fs *result);
/**************************************************************************
* Description : EKFQR
* Input : scane_type,
nmea_dataNMEA
g_pdrPDR
sys
kfEKF
**************************************************************************/
/**************************************************************************
* Description : GPS
* Input : gpsPosGPSECEF
pgnssGPS
* Output : double
**************************************************************************/
double calGnssTrackHeading(double gpsPos[][3], gnss pgnss);
#endif
#pragma once

View File

@ -1,85 +0,0 @@
#ifndef __DETECTOR_H
#define __DETECTOR_H
#ifdef __cplusplus
extern "C" {
#endif
/* Header File Including ------------------------------------------------------------------------ */
#include <stdint.h>
#include <stdlib.h>
#include <time.h>
#include "pdr_base.h"
#include "buffer.h"
#include "pdr_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 *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 : pdr_getDetector
* Description : PDR
* Date : 2020/02/16 logzhan &
*
*---------------------------------------------------------------------**/
DETECTOR *pdr_getDetector(void);
/**---------------------------------------------------------------------
* Function : pdr_initDetector
* Description :
* Date : 2020/02/16 logzhan & logzhan
*---------------------------------------------------------------------**/
DETECTOR* pdr_initDetector(void);
/**---------------------------------------------------------------------
* Function : pdr_resetDetector
* Description : PDR
* Date : 2020/02/16 logzhan & logzhan
*---------------------------------------------------------------------**/
void pdr_resetDetector(void);
/**---------------------------------------------------------------------
* Function : pdr_motionTypeDetect
* Description : pdr
* Date : 2020/7/20
*
*---------------------------------------------------------------------**/
int pdr_motionTypeDetect(void);
/**---------------------------------------------------------------------
* Function : predict
* Description :
* Date : 2020/7/20 logzhan
*---------------------------------------------------------------------**/
int pdr_detectorPredict(float* feature);
void mag_calibration(IMU *imu);
void mag_m_trans(float a[MAG_BUF_LEN][3], float r[3][MAG_BUF_LEN]);
void mag_min(float a[MAG_BUF_LEN], float *mag_min);
void mag_max(float a[MAG_BUF_LEN], float *mag_max);
void mag_rand(float r[6]);
void updateDetectorImu(imu* imu);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,63 +0,0 @@
/******************** (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 : pdr_initKalman
* Description :
* Date : 2020/8/27
*
*---------------------------------------------------------------------**/
void pdr_initKalman(void);
/**----------------------------------------------------------------------
* Function : pdr_ekfStatePredict
* Description : pdr
* Date : 2020/7/22 logzhan
*---------------------------------------------------------------------**/
void pdr_ekfStatePredict(KfPara* kf, double step_length, PDR* g_pdr, int step);
/**----------------------------------------------------------------------
* Function : getQRValue
* Description :
* scane_type,
* nmea_dataNMEA
* g_pdrPDR
* sys
* kfEKF
* Date : 2020/07/09 logzhan
*---------------------------------------------------------------------**/
void calEkfQRMatrix(lct_nmea* nmea_data, PDR* g_pdr, classifer* sys, KfPara* kf);
/**----------------------------------------------------------------------
* Function : pdr_ekfStateUpdate
* Description : pdr
* Date : 2020/7/22 logzhan
*---------------------------------------------------------------------**/
void pdr_ekfStateUpdate(KfPara* kf, gnss* pgnss, classifer* sys, PDR* g_pdr,
int scene_type);
/**----------------------------------------------------------------------
* Function : pdr_gnssInsLocFusion
* Description : PDRGNSSINS
* Date : 2020/07/09 logzhan
*---------------------------------------------------------------------**/
void pdr_gnssInsLocFusion(gnss* pgnss, PDR* g_pdr, classifer* sys, double yaw_bias,
KfPara* kf, lct_fs* res);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,99 +0,0 @@
#ifndef __PDR_LOCATION_H__
#define __PDR_LOCATION_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "pdr_base.h"
#define HIST_GPS_NUM 8
#define ACCURACY_THRES 0.6f // 精度阈值
#define YAW_THRES 10.0f // Yaw角范围阈值
/**---------------------------------------------------------------------
* Function : pdr_navSysInit
* Description : PDR
* Date : 2020/2/1
*
*
*
*
*
*
*---------------------------------------------------------------------**/
void NavSys_Init(void);
int pdr_insLocation(imu *ss_data, KfPara *kf);
/**----------------------------------------------------------------------
* Function : pdr_noGpsPredict
* Description : gpsGPS10
* Date : 2020/07/08 logzhan
*---------------------------------------------------------------------**/
void pdr_noGpsPredict(KfPara* kf, lct_fs* result, PDR* g_pdr);
/**----------------------------------------------------------------------
* Function : pdr_nmea2Gnss
* Description : nmeagnss
* Date : 2020/07/08 logzhan
*---------------------------------------------------------------------**/
void pdr_nmea2Gnss(lct_nmea* nmea_data, gnss* pgnss);
/**----------------------------------------------------------------------
* Function : pdr_detectFixMode
* Description : PDR,
* GPS
* Date : 2020/07/08 logzhan
* 2020/02/08 logzhan : -1INVAILD_GPS_YAW
*
*---------------------------------------------------------------------**/
int pdr_detectFixMode(gnss* pgnss, KfPara* kf, PDR* g_pdr, lct_fs* result);
/**----------------------------------------------------------------------
* Function : pdr_getGpsHeading
* Description : GPS
* Date : 2020/07/08 logzhan
*---------------------------------------------------------------------**/
double pdr_getGpsHeading(gnss* pgnss);
/**----------------------------------------------------------------------
* Function : calPdrHeadingOffset
* Description : GPS
* Date : 2020/07/08 logzhan
*---------------------------------------------------------------------**/
void calPdrHeadingOffset(lct_nmea* nmea_data, PDR* p_pdr);
/**---------------------------------------------------------------------
* Function : pdr_resetSysStatus
* Description : PDS
* Date : 2020/2/1 logzhan
*---------------------------------------------------------------------**/
void pdr_resetSysStatus(KfPara* kf);
/**----------------------------------------------------------------------
* Function : pdr_gnssInsLocation
* Description : PDR GPSINS
* Date : 2021/01/29 logzhan
*---------------------------------------------------------------------**/
int pdr_gnssInsLocation(lct_nmea* nmea_data, KfPara* kf, lct_fs* result);
/**---------------------------------------------------------------------
* Function : pdr_initGnssInfo
* Description : PDS GNSS
* Date : 2020/2/1 logzhan
*---------------------------------------------------------------------**/
void pdr_initGnssInfo(void);
void pdr_gnssUpdate(gnss* gps, lct_nmea* nmea);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,85 +0,0 @@
/******************** (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 : motionType2Str
* Description :
* Date : 2020/8/3 logzhan
*---------------------------------------------------------------------**/
const char* motionType2Str(int type);
/**----------------------------------------------------------------------
* Function : updateResTrack
* Description : GPSPDR
* Date : 2021/01/25 logzhan
*---------------------------------------------------------------------**/
void updateResTrack(ResultTracks& resTrack, lct_fs& lctfs);
#endif
#ifdef __cplusplus
}
#endif

View File

@ -1,70 +0,0 @@
#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

@ -1,314 +0,0 @@
/******************** (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_agm {
unsigned char update;
int type;
double time; //ms
float s[IMU_SENSOR_AXIS];
}sensor_agm;
typedef struct imu {
sensor_agm acc;
sensor_agm gyr;
sensor_agm mag;
}imu;
typedef struct lct_nmea_rmc {
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
}lct_nmea_rmc;
typedef struct lct_nmea_gga {
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
}lct_nmea_gga;
typedef struct lct_nmea_gsa {
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
}
lct_nmea_gsa;
typedef struct satellite_status {
int prn;
int elevation; // elevation >10
int azimuth;
int snr; //snr >25 good
}satellite_status;
typedef struct lct_nmea_gsv {
unsigned char update;
sensor type;
int sentences;
int sentence_number;
int satellites;
int satellite_number;
satellite_status satellites_data[20];
double time; //ms
}lct_nmea_gsv;
typedef struct loc_accuracy{
unsigned char update;
int status; //-1,:Status Unknown; 0: Out of Service; 1: Temporarily Unavailable; 2: Available
float err; // m
double time;
}loc_accuracy;
typedef struct lct_nmea {
unsigned char update;
double minTime;
double maxTime;
lct_nmea_gga gga;
lct_nmea_rmc rmc[2]; // 0 - GNRMC, 1 - GPRMC
lct_nmea_gsa gsa[3]; // 0 - GPGSA, 1 - GLGSA, 2 - GAGSA
lct_nmea_gsv gsv[3]; // 0 - GPGSV, 1 - GLGSV, 2 - GAGSV
loc_accuracy accuracy;
}lct_nmea;
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;
}lct_fs;
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;
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 qnb[4];
float gravity[3];
float x_axis[3];
float y_axis[3];
float z_axis[3];
float kp; // mahony kp比例调节参数
float yaw;
float pitch;
float roll;
float insHeading;
} AHRS;
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,158 +0,0 @@
#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;
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 vivopow(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);
void QuaternConj(float _q[], float q[]);
void quaternProd(float ab[], float a[], float b[]);
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);
LatLng ProjPointOfLatLng(LatLng point, LatLng linePointA, LatLng linePointB);
double calDistance(LatLng pointA, LatLng 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 pdr_v3Norm(float* vx, float* vy, float* vz);
/**---------------------------------------------------------------------
* Function : quatNorm
* Description :
* Date : 2021/01/26 yuanlin@vivocom && logzhan
* 2021/01/27 logzhan :
* 0
*---------------------------------------------------------------------**/
void QuatNorm(float* q0, float* q1, float* q2, float* q3);
/**----------------------------------------------------------------------
* Function : pdr_writeCsvStr
* Description : fprintf
* Date : 2020/7/8 logzhan
*---------------------------------------------------------------------**/
void pdr_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);
int pdr_min(int param_a, int param_b);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,164 +0,0 @@
/*********************************************************************************/
/* 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 lct_nmea for the module. */
/* This is the interface for the lct_nmea. */
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 initSceneRecognition(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 lct_nmea* 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 lct_nmea* nmea);
#ifdef __cplusplus
}
#endif
#endif //__SCENE_RECOGNITION_H__

View File

@ -1,177 +0,0 @@
#pragma once
/******************** (C) COPYRIGHT 2017 Geek************************************
* File Name : Steps_Algorithm.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
*******************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
#ifndef _STEPS_ALGORITHM_H_
#define _STEPS_ALGORITHM_H_
#include "pdr_sensor.h"
#define ACC_SAMPLE_RATE_100HZ
//#define ACC_SAMPLE_RATE_25HZ
#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 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 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
#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;
}stepsDfine;
typedef enum {
nonSteps = 0,
walk,
}enumState;
typedef struct {
unsigned char sign;
enumState state;
unsigned long long stateStartTime;
unsigned long long stepsStartTime;
}stateNowDfine;
typedef struct {
enumState state;
unsigned long long startTimeStamp;
}stateDfine;
typedef struct {
int flag;
double ax;
double ay;
double az;
}downSample;
/**---------------------------------------------------------------------
* Function : getPedometerLibVersion
* Description :
* Date : 2020/2/20
*---------------------------------------------------------------------**/
const char* getPedometerLibVersion(void);
/**---------------------------------------------------------------------
* Function : initPedometer
* Description : PDR
* Date : 2020/2/20 logzhan
*---------------------------------------------------------------------**/
void Pedometer_Init(void);
/**---------------------------------------------------------------------
* Function : reinitPedometer
* Description : PDR
* Date : 2020/2/20 logzhan
*---------------------------------------------------------------------**/
void reinitPedometer(void);
/**---------------------------------------------------------------------
* Function : updatePedometer
* Description : PDR ,
* Date : 2020/2/1 logzhan
*---------------------------------------------------------------------**/
void updatePedometer(imu* ss_data, unsigned long* step);
void Steps_State_Detect(enumState* state);
/**---------------------------------------------------------------------
* Function : detVehicleMode
* Description : PDR ,
* Date : 2020/2/1 logzhan
*---------------------------------------------------------------------**/
void detVehicleMode(double ax, double ay, double az);
#endif
#ifdef __cplusplus
}
#endif

View File

@ -1,202 +0,0 @@
<?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\LapProcess.c" />
<ClCompile Include="..\src\m_munkres.c" />
<ClCompile Include="..\src\pdr_ahrs.c" />
<ClCompile Include="..\src\pdr_api.c" />
<ClCompile Include="..\src\pdr_base.c" />
<ClCompile Include="..\src\pdr_detector.c" />
<ClCompile Include="..\src\pdr_fft.c" />
<ClCompile Include="..\src\pdr_filter.c" />
<ClCompile Include="..\src\pdr_kalman.c" />
<ClCompile Include="..\src\pdr_linearFit.c" />
<ClCompile Include="..\src\pdr_location.c" />
<ClCompile Include="..\src\pdr_main.cpp" />
<ClCompile Include="..\src\pdr_matrix.c" />
<ClCompile Include="..\src\pdr_parseData.c" />
<ClCompile Include="..\src\pdr_trackSmooth.c" />
<ClCompile Include="..\src\pdr_util.c" />
<ClCompile Include="..\src\scene_recognition.c" />
<ClCompile Include="..\src\steps.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\pdr_ahrs.h" />
<ClInclude Include="..\include\pdr_api.h" />
<ClInclude Include="..\include\pdr_base.h" />
<ClInclude Include="..\include\pdr_detector.h" />
<ClInclude Include="..\include\pdr_fft.h" />
<ClInclude Include="..\include\pdr_kalman.h" />
<ClInclude Include="..\include\pdr_linearFit.h" />
<ClInclude Include="..\include\pdr_location.h" />
<ClInclude Include="..\include\pdr_main.h" />
<ClInclude Include="..\include\pdr_matrix.h" />
<ClInclude Include="..\include\pdr_sensor.h" />
<ClInclude Include="..\include\pdr_trackSmooth.h" />
<ClInclude Include="..\include\pdr_util.h" />
<ClInclude Include="..\include\scene_recognition.h" />
<ClInclude Include="..\include\steps.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>
</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>Use</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(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

@ -1,144 +0,0 @@
<?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>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\buffer.c">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\LapProcess.c">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\m_munkres.c">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\pdr_ahrs.c">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\pdr_api.c">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\pdr_base.c">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\pdr_detector.c">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\pdr_fft.c">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\pdr_filter.c">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\pdr_linearFit.c">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\pdr_location.c">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\pdr_main.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\pdr_parseData.c">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\pdr_trackSmooth.c">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\scene_recognition.c">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\steps.c">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\pdr_util.c">
<Filter>src\Utils</Filter>
</ClCompile>
<ClCompile Include="..\src\pdr_matrix.c">
<Filter>src\Math</Filter>
</ClCompile>
<ClCompile Include="..\src\pdr_kalman.c">
<Filter>src\Location</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\parseData.h">
<Filter>inc</Filter>
</ClInclude>
<ClInclude Include="..\include\pdr_ahrs.h">
<Filter>inc</Filter>
</ClInclude>
<ClInclude Include="..\include\pdr_api.h">
<Filter>inc</Filter>
</ClInclude>
<ClInclude Include="..\include\pdr_base.h">
<Filter>inc</Filter>
</ClInclude>
<ClInclude Include="..\include\pdr_detector.h">
<Filter>inc</Filter>
</ClInclude>
<ClInclude Include="..\include\pdr_fft.h">
<Filter>inc</Filter>
</ClInclude>
<ClInclude Include="..\include\pdr_kalman.h">
<Filter>inc</Filter>
</ClInclude>
<ClInclude Include="..\include\pdr_linearFit.h">
<Filter>inc</Filter>
</ClInclude>
<ClInclude Include="..\include\pdr_location.h">
<Filter>inc</Filter>
</ClInclude>
<ClInclude Include="..\include\pdr_main.h">
<Filter>inc</Filter>
</ClInclude>
<ClInclude Include="..\include\pdr_matrix.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\pdr_util.h">
<Filter>inc</Filter>
</ClInclude>
<ClInclude Include="..\include\scene_recognition.h">
<Filter>inc</Filter>
</ClInclude>
<ClInclude Include="..\include\steps.h">
<Filter>inc</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -1,343 +0,0 @@
/* Header File Including ------------------------------------------------------------------------ */#include <stdint.h>
#include <string.h>
#include "m_munkres.h"
//#include "loc_vivo_pdr.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);
#ifdef __MATLAB_DBG
void display_cost_matrix_and_cover(float *cost, int m, int n, uint8_t row_cover, uint8_t col_cover);
void display_mark_matrix_and_cover(int *mark, int m, int n, uint8_t row_cover, uint8_t col_cover);
#endif
/* Function Definition -------------------------------------------------------------------------- */
int MUNKRES_get_assignment(int *assignment, float *cost, int m, int n) {
int i = 0;
int j = 0;
int step;
#if PRINT_ALGO_RUN_TIME
uint64 time_algo_1 = 0l;
uint64 time_algo_2 = 0l;
uint64 time_algo_3 = 0l;
uint64 time_algo_4 = 0l;
#endif
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) {
#ifdef __MATLAB_DBG
mexPrintf("step %d:\n", step);
#endif
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);
#if PRINT_ALGO_RUN_TIME
time_algo_3 = uTimetick_Get();
time_algo_3 = (time_algo_3-time_algo_1);
#if defined(LOCATION_PLATFORM_QCOM_MODEM)
Geek_PDR_LOGH_NMEA("step_4 run time ms %d",(int)time_algo_3,0,0,0);
#endif
#endif
break;
case 5:
step = step_five(g_mark, m, n, &g_row_cover, &g_col_cover, i, j);
#if PRINT_ALGO_RUN_TIME
time_algo_4 = uTimetick_Get();
time_algo_4 = (time_algo_4-time_algo_1);
#if defined(LOCATION_PLATFORM_QCOM_MODEM)
Geek_PDR_LOGH_NMEA("step_5 run time ms %d",(int)time_algo_4,0,0,0);
#endif
#endif
break;
case 6:
step = step_six(g_cost, m, n, &g_row_cover, &g_col_cover);
break;
default:
step = 7;
break;
}
#ifdef __MATLAB_DBG
mexPrintf(" cost:\n", step);
display_cost_matrix_and_cover(g_cost, m, n, g_row_cover, g_col_cover);
mexPrintf(" mark:\n", step);
display_mark_matrix_and_cover(g_mark, m, n, g_row_cover, g_col_cover);
#endif
}
#if PRINT_ALGO_RUN_TIME
time_algo_2 = uTimetick_Get();
#endif
#if PRINT_ALGO_RUN_TIME
time_algo_2 = (time_algo_2-time_algo_1);
// time_algo_3 = (time_algo_3-time_algo_2);
#if defined(LOCATION_PLATFORM_QCOM_MODEM)
Geek_PDR_LOGH_NMEA("munkres run time ms %d",(int)time_algo_2,0,0,0);
#endif
// Geek_PDR_LOGH_NMEA("pdr2 run time ms %d %d",(int)time_algo_5,time_algo_6,0,0);
#endif
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

@ -1,422 +0,0 @@
/******************** (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 "pdr_base.h"
#include "pdr_ahrs.h"
#include "pdr_detector.h"
#include "Filter.h"
#include "buffer.h"
#include "pdr_kalman.h"
#include "pdr_util.h"
/* Macro Definition ----------------------------------------------------------*/
#define AHRS_BUF_LEN 256
#define FLT_THRES 0.000001f // 浮点数最小阈值
//计算模值
#define GET_MOL(v) sqrt((v)[0] * (v)[0] + (v)[1] * (v)[1] + (v)[2] * (v)[2])
//获取数组长度
#define ARR_LEN(arr) (sizeof(arr) / sizeof(*arr))
#define SET_BIT(msk) (g_ahrs.status |= AHRS_STATUS_##msk)
#define CLR_BIT(msk) (g_ahrs.status &= ~AHRS_STATUS_##msk)
#define TST_BIT(msk) (g_ahrs.status & AHRS_STATUS_##msk)
#define INC_PTR(buf, ptr) (((ptr) + 1) % ((buf).length + 1))
#define GRV_BUF_NME(i) "grav_buf_##i"
#define GYR_BUF_NME(i) "gyro_buf_##i"
#define MAG_BUF_NME(i) "magn_buf_##i"
/* Global Variable Definition ------------------------------------------------*/
/* Macro Definition ----------------------------------------------------------*/
/* Global Variable Definition ------------------------------------------------*/
static IMU g_imu;
AHRS g_ahrs;
static uint64_t g_ticker;
static BUFFER_LONG g_erro_buf;
static BUFFER_LONG g_grav_buf[3];
static BUFFER_LONG g_gyro_buf[3];
static BUFFER_LONG g_magn_buf[3];
static float dt = 1.0f / AHRS_SAMPLE_FREQ; // sample interval in second
static float Kp = 0; // 2 * proportional gain (Kp)
static float q0 = 1.0f, q1 = 0.0f, q2 = 0.0f, q3 = 0.0f; // 初始四元数
static const float g_x_axis[] = {1, 0, 0};
static const float g_y_axis[] = {0, 1, 0};
static const float g_z_axis[] = {0, 0, 1};
/**----------------------------------------------------------------------
* Function : mahonyUpdateAHRS
* Description : mahony姿
* Date : 2020/8/3 logzhan
* 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) {
// 归一化磁力计和加速度计
pdr_v3Norm(&ax, &ay, &az);
float wx = 0.0f, wy = 0.0f, wz = 0.0f;
//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 - q3 * q3) + my * (q1 * q2 - q0 * q3) + mz * (q1 * q3 + q0 * q2));
// float hy = 2.0f * (mx * (q1 * q2 + q0 * q3) + my * (0.5f - q1 * q1 - q3 * q3) + mz * (q2 * q3 - q0 * q1));
// float hz = 2.0f * (mx * (q1 * q3 - q0 * q2) + my * (q2 * q3 + q0 * q1) + mz * (0.5f - q1 * q1 - q2 * q2));
// // 理论上bx = 0, by 指向北向因为手机IMU数据使用的是东北天(x,y,z)坐标系
// float by = (float)sqrt(hx * hx + hy * hy);
// float bz = hz;
// wx = by * (q0 * q3 + q1 * q2) + bz * (q1 * q3 - q0 * q2);
// wy = by * (0.5f - q1 * q1 - q3 * q3) + bz * (q0 * q1 + q2 * q3);
// wz = by * (q2 * q3 - q0 * q1) + bz * (0.5f - q1 * q1 - q2 * q2);
//}
// 把重力转换到地理坐标系 v = R * (0,0,1)
float vx = q1*q3 - q0*q2;
float vy = q0*q1 + q2*q3;
float vz = q0*q0 - 0.5f + q3*q3;
// 计算矢量叉乘误差
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 += Kp * ex;
gy += Kp * ey;
gz += Kp * ez;
// 这两个函数占了大量的时间
if (g_ahrs.stable == PDR_FALSE) {
buffer_push((BUFFER*)&g_erro_buf, (float)(2 * sqrt(ex * ex + ey * ey + ez * ez)));
Buffer_mean((BUFFER*)&g_erro_buf, &g_ahrs.error);
}
// 龙格库塔法更新四元数
float qa = q0; float qb = q1; float qc = q2;
q0 += (-qb * gx - qc * gy - q3 * gz) * 0.5f * (dt);
q1 += ( qa * gx + qc * gz - q3 * gy) * 0.5f * (dt);
q2 += ( qa * gy - qb * gz + q3 * gx) * 0.5f * (dt);
q3 += ( qa * gz + qb * gy - qc * gx) * 0.5f * (dt);
// 四元数归一化
QuatNorm(&q0, &q1, &q2, &q3);
// 四元数转欧拉角
g_ahrs.pitch = (float)asin(-2.0f * (q3*q1 - q0*q2)) * (180.0f / 3.141592f);
g_ahrs.yaw = (float)atan2(q2*q1 + q0*q3, 0.5f - q2*q2 - q3*q3) * (180.0f / 3.141592f);
g_ahrs.roll = (float)atan2(q2*q3 + q0*q1, 0.5f - q2*q2 - q1*q1) * (180.0f / 3.141592f);
}
/**---------------------------------------------------------------------
* Function : AHRS_sensorFrame2EarthFrame
* Description :
* Date : 2020/7/20 logzhan
*---------------------------------------------------------------------**/
void AHRS_sensorFrame2EarthFrame(float e[], float s[]) {
float quaVec[4];
float quaTmp[4];
float quaCnj[4];
quaVec[0] = 0;
quaVec[1] = s[0];
quaVec[2] = s[1];
quaVec[3] = s[2];
quaternProd(quaTmp, g_ahrs.qnb, quaVec);
QuaternConj(quaCnj, g_ahrs.qnb);
quaternProd(quaVec, quaTmp, quaCnj);
e[0] = quaVec[1];
e[1] = quaVec[2];
e[2] = quaVec[3];
}
void pdr_initAhrs(void) {
int i;
g_ahrs.stable = PDR_FALSE;
Buffer_initialize((BUFFER *)&g_erro_buf, "erro_buf", BUFFER_TYPE_QUEUE, AHRS_BUF_LEN);
for (i = 0; i < 3; ++i) {
Buffer_initialize((BUFFER *)&g_grav_buf[i], GRV_BUF_NME(i), BUFFER_TYPE_QUEUE, AHRS_BUF_LEN);
Buffer_initialize((BUFFER *)&g_gyro_buf[i], GYR_BUF_NME(i), BUFFER_TYPE_QUEUE, AHRS_BUF_LEN);
Buffer_initialize((BUFFER *)&g_magn_buf[i], MAG_BUF_NME(i), BUFFER_TYPE_QUEUE, AHRS_BUF_LEN);
}
pdr_ahrsReset();
}
void pdr_ahrsReset(void) {
Buffer_clear((BUFFER *)&g_erro_buf);
for (uchar i = 0; i < 3; ++i) {
Buffer_clear((BUFFER *)&g_grav_buf[i]);
Buffer_clear((BUFFER *)&g_gyro_buf[i]);
Buffer_clear((BUFFER *)&g_magn_buf[i]);
}
g_ticker = 0;
q0 = 1.0f;
q1 = 0.0f;
q2 = 0.0f;
q3 = 0.0f;
memset(&g_ahrs, 0, sizeof(g_ahrs));
g_ahrs.status = (uint8_t)AHRS_STATUS_RESET_PHASE_0;
g_ahrs.error = -1;
g_ahrs.qnb[0] = 1.0f;
g_ahrs.qnb[1] = 0.0f;
g_ahrs.qnb[2] = 0.0f;
g_ahrs.qnb[3] = 0.0f;
g_ahrs.gravity[0] = 0.0f;
g_ahrs.gravity[1] = 0.0f;
g_ahrs.gravity[2] = 9.8f;
g_ahrs.x_axis[0] = 1.0f;
g_ahrs.x_axis[1] = 0.0f;
g_ahrs.x_axis[2] = 0.0f;
g_ahrs.y_axis[0] = 0.0f;
g_ahrs.y_axis[1] = 1.0f;
g_ahrs.y_axis[2] = 0.0f;
g_ahrs.z_axis[0] = 0.0f;
g_ahrs.z_axis[1] = 0.0f;
g_ahrs.z_axis[2] = 1.0f;
}
/**---------------------------------------------------------------------
* Function : estimate_sensor_vector
* Description : q姿grav
* input : float eVec[], float gyro[]
* output : float sVec[]
* Date : 2020/7/20 logzhan
*---------------------------------------------------------------------**/
static void estimate_sensor_vector(float sVec[], float eVec[], float gyro[]) {
float q[4];
float gx, gy, gz;
float qa, qb, qc;
float recipNorm;
float quaVec[4];
float quaTmp[4];
float quaCnj[4];
/* estimate */
gx = gyro[0] * (0.5f * (dt));
gy = gyro[1] * (0.5f * (dt));
gz = gyro[2] * (0.5f * (dt));
qa = q0;
qb = q1;
qc = q2;
q[0] = q0 + (-qb * gx - qc * gy - q3 * gz);
q[1] = q1 + (qa * gx + qc * gz - q3 * gy);
q[2] = q2 + (qa * gy - qb * gz + q3 * gx);
q[3] = q3 + (qa * gz + qb * gy - qc * gx);
recipNorm = InvSqrt(q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]);
q[0] *= recipNorm;
q[1] *= recipNorm;
q[2] *= recipNorm;
q[3] *= recipNorm;
/* project */
QuaternConj(q, q);
quaVec[0] = 0;
quaVec[1] = eVec[0];
quaVec[2] = eVec[1];
quaVec[3] = eVec[2];
quaternProd(quaTmp, q, quaVec);
QuaternConj(quaCnj, q);
quaternProd(quaVec, quaTmp, quaCnj);
sVec[0] = quaVec[1];
sVec[1] = quaVec[2];
sVec[2] = quaVec[3];
}
/**----------------------------------------------------------------------
* Function : pdr_imuUpdateAhrs
* Description : 1AHRS
* 2Error
* 3PCA
* Date : 2020/6/30 logzhan
*---------------------------------------------------------------------**/
int pdr_imuUpdateAhrs(imu* imu) {
float gyro[3], acce[3], magn[3], grav[3], mean[2];
int index;
int count;
int i;
for (uchar i = 0; i < 3; ++i) {
gyro[i] = imu->gyr.s[i];
acce[i] = imu->acc.s[i];
magn[i] = imu->mag.s[i];
}
//g_ahrs.status(初始状态0x80) 按位与 AHRS_STATUS_RESET_PHASE_0(0x80)
if (g_ahrs.status & AHRS_STATUS_RESET_PHASE_0) {
// ARHS BUF 中存储了256个sensor的缓存
if (g_ticker <= AHRS_BUF_LEN) {
for (i = 0; i < 3; ++i) {
buffer_push((BUFFER *)&g_grav_buf[i], acce[i]);
buffer_push((BUFFER *)&g_gyro_buf[i], gyro[i]);
buffer_push((BUFFER *)&g_magn_buf[i], magn[i]);
}
}
// 只有缓存满的时候才计算
if (g_ticker >= AHRS_BUF_LEN) {
//int index;
index = (g_magn_buf[0]._top + AHRS_BUF_LEN + 1 - AHRS_BUF_LEN / 2) % (g_magn_buf[0].length + 1);
for (i = 0; i < 3; ++i) {
Buffer_mean((BUFFER *)&g_grav_buf[i], &grav[i]);
magn[i] = g_magn_buf[i].data[index];
g_grav_buf[i]._top = g_grav_buf[i]._bottom;
}
Kp = (float)(2 * 2);
/* 这里循环运行1000次,收敛,趋于正确姿态 */
for (i = 0; i < 1000; ++i) {
mahonyUpdateAHRS(0, 0, 0, grav[0], grav[1], grav[2], magn[0], magn[1], magn[2]);
}
AHRS_sensorFrame2EarthFrame(g_ahrs.gravity, grav);
Kp = (float)(2 * 2);
for (index = INC_PTR(g_gyro_buf[0], index); index != g_gyro_buf[0]._top; index = INC_PTR(g_gyro_buf[0], index)) {
for (i = 0; i < 3; ++i) {
buffer_push((BUFFER *)&g_grav_buf[i], g_ahrs.gravity[i]);
Buffer_mean((BUFFER *)&g_grav_buf[i], &grav[i]);
gyro[i] = g_gyro_buf[i].data[index];
acce[i] = g_grav_buf[i].data[index];
magn[i] = g_magn_buf[i].data[index];
}
estimate_sensor_vector(grav, grav, gyro);
// AHRS 更新
mahonyUpdateAHRS(gyro[0], gyro[1], gyro[2], grav[0], grav[1], grav[2], magn[0],
magn[1], magn[2]);
AHRS_sensorFrame2EarthFrame(g_ahrs.gravity, acce);
}
g_ahrs.qnb[0] = q0;
g_ahrs.qnb[1] = q1;
g_ahrs.qnb[2] = q2;
g_ahrs.qnb[3] = q3;
CLR_BIT(RESET_PHASE_0); /*#define CLR_BIT(msk) (g_ahrs.status &= ~AHRS_STATUS_##msk)清零g_ahrs.status*/
SET_BIT(RESET_PHASE_1); /*#define SET_BIT(msk) (g_ahrs.status |= AHRS_STATUS_##msk)赋值g_ahrs.status与phase1相同*/
}
++g_ticker;
//return;
//g_ahrs.status(0x80) 按位与 AHRS_STATUS_RESET_PHASE_1(0x40)
}else if (g_ahrs.status & AHRS_STATUS_RESET_PHASE_1) {
//PDR_LOGD("阶段1");
// 应该是判断是否进入PCA的条件
if (g_ahrs.error < 0.3) {
Buffer_count((BUFFER *)&g_erro_buf, &count);
memset((void *)mean, 0, sizeof(mean));
for (index = g_erro_buf._bottom, i = 0; index != g_erro_buf._top; index = INC_PTR(g_erro_buf, index), ++i) {
int c = count >> 1;
if (i < c ) {
mean[0] += g_erro_buf.data[index];
}
else {
mean[1] += g_erro_buf.data[index];
}
}
int a = count >> 1;
int b = count - (count >> 1);
mean[0] /= a;
mean[1] /= b;
if (fabs(mean[0] - mean[1]) < 0.025) {
Kp = (float)(2 * AHRS_KP);
// 这个标志位决定是否进入PCA方向估计
CLR_BIT(RESET_PHASE_1);
SET_BIT(STABLE);
g_ahrs.stable = PDR_TRUE;
}
}
for (i = 0; i < 3; ++i) {
buffer_push((BUFFER *)&g_grav_buf[i], g_ahrs.gravity[i]);
Buffer_mean((BUFFER *)&g_grav_buf[i], &grav[i]);
}
estimate_sensor_vector(grav, grav, gyro);
mahonyUpdateAHRS(gyro[0], gyro[1], gyro[2],
grav[0], grav[1], grav[2],
magn[0], magn[1], magn[2]);
g_ahrs.qnb[0] = q0;
g_ahrs.qnb[1] = q1;
g_ahrs.qnb[2] = q2;
g_ahrs.qnb[3] = q3;
AHRS_sensorFrame2EarthFrame(g_ahrs.gravity, acce);
AHRS_sensorFrame2EarthFrame(g_ahrs.x_axis, (float*)g_x_axis);
AHRS_sensorFrame2EarthFrame(g_ahrs.y_axis, (float*)g_y_axis);
AHRS_sensorFrame2EarthFrame(g_ahrs.z_axis, (float*)g_z_axis);
pdr_computePCA(&g_ahrs);
++g_ticker;
}
else {
// Buffer_mean的计算时间太长了10ms更新来算计算256个数的平均
// 计算量实在太大
//for (i = 0; i < 3; ++i) {
// Buffer_push((BUFFER *)&g_grav_buf[i], g_ahrs.gravity[i]);
// Buffer_mean((BUFFER *)&g_grav_buf[i], &grav[i]);
//}
//estimate_sensor_vector(grav, grav, gyro);
// logzhan 21/02/06 : 感觉是acc输入精度会高一些
mahonyUpdateAHRS(gyro[0], gyro[1], gyro[2],
acce[0], acce[1], acce[2],
magn[0], magn[1], magn[2]);
g_ahrs.qnb[0] = q0;
g_ahrs.qnb[1] = q1;
g_ahrs.qnb[2] = q2;
g_ahrs.qnb[3] = q3;
// 把载体系的加速度转换为地理坐标系,
AHRS_sensorFrame2EarthFrame(g_ahrs.gravity, acce);
// 这部分代码都是可以简化以增加运算速度的,暂时不清楚作用
AHRS_sensorFrame2EarthFrame(g_ahrs.x_axis, (float*)g_x_axis);
AHRS_sensorFrame2EarthFrame(g_ahrs.y_axis, (float*)g_y_axis);
AHRS_sensorFrame2EarthFrame(g_ahrs.z_axis, (float*)g_z_axis);
++g_ticker;
return PDR_TRUE;
}
return PDR_FALSE;
}
/**---------------------------------------------------------------------
* Function : fv3Norm
* Description :
* Date : 2021/01/26 logzhan
*---------------------------------------------------------------------**/
void fv3Norm(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;
}
}

View File

@ -1,256 +0,0 @@
/******************** (C) COPYRIGHT 2020 Geek************************************
* File Name : pdr_api.c
* Department : Sensor Algorithm Team
* Current Version : V2.0
* Author :
*
* Date of Issued : 2020.7.3
* Comments : PDR
********************************************************************************/
/* Header File Including -----------------------------------------------------*/
#include <stdio.h>
#include <math.h>
#include <string.h>
#include "pdr_api.h"
#include "pdr_base.h"
#include "steps.h"
#include "pdr_location.h"
#include "parseData.h"
#include "scene_recognition.h"
#include "pdr_trackSmooth.h"
#include "LapProcess.h"
/* Global Variable Definition ------------------------------------------------*/
const char* pdrVersion = "1.0";
size_t slideWindowSize = 5;
sensor_agm SensorDataHist[IMU_LAST_COUNT] = {{0}};
LatLng lla_last = { 0 };
lct_nmea ln;
imu imuData;
/* Extern Variable Definition ------------------------------------------------*/
extern KfPara g_kfPara;
extern AHRS g_ahrs;
extern gnss pgnss;
/* Function Declaration ------------------------------------------------------*/
/**---------------------------------------------------------------------
* Function : pdr_initRmc
* Description : RMC
* Date : 2020/7/3 logzhan
*---------------------------------------------------------------------**/
void RMC_Init(lct_nmea_rmc * 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 : pdr_initNmeaFlg
* Description : GPSNMEA
* Date : 2020/7/3 logzhan
*---------------------------------------------------------------------**/
void NmeaFlag_Init(lct_nmea * 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(lct_nmea * ln){
NmeaFlag_Init(ln);
}
/**---------------------------------------------------------------------
* Function : Algorithm_Init
* Description : PDRPDR
*
* Date : 2020/7/3 logzhan
*---------------------------------------------------------------------**/
void Algorithm_Init(void) {
// 导航相关初始化
NavSys_Init();
// 计步器初始化
Pedometer_Init();
// 设置轨迹平滑滑动窗口大小
TrackSmoothSetWinSize(slideWindowSize);
// 跑圈优化初始化
lapInit();
// 初始化sensor历史缓存
memset(SensorDataHist, 0, sizeof(SensorDataHist));
memset(&ln, 0, sizeof(ln));
memset(&imuData, 0, sizeof(imuData));
}
/**---------------------------------------------------------------------
* Function : pdr_locationMainLoopStr
* Description : PDR
*
* Date : 2020/07/03 logzhan
* 2020/02/02 logzhan :
*---------------------------------------------------------------------**/
int pdr_locationMainLoopStr(char* line, lct_fs* result) {
pdr_parseLineStr(line, &imuData, &ln);
return pdr_locationMainLoop(&imuData, &ln, result, NULL);
}
/**---------------------------------------------------------------------
* Function : pdr_locationMainLoop
* Description : PDR
*
* Date : 2020/07/03 logzhan
* 2020/02/02 logzhan :
*---------------------------------------------------------------------**/
int pdr_locationMainLoop(imu *ss_data, lct_nmea *nmea_data, lct_fs *result, FILE *fp_gps) {
int type = 0;
if (ss_data->gyr.update) {
// 如果陀螺仪更新则采用惯性传感器计算
pdr_insLocation(ss_data,&g_kfPara);
ss_data->gyr.update = UN_UPDATE;
}
// 如果GPS不更新返回
if (!nmea_data->update)return TYPE_FIX_NONE;
// 保存GPS相关信息
pdr_saveGnssInfo(nmea_data, result, fp_gps);
// 有GPS则采用GPS融合定位
int flag = pdr_gnssInsLocation(nmea_data, &g_kfPara, result);
if (flag != TYPE_FIX_NONE) {
// 如果是开车这种直接输出GPS不进行平滑处理
if (flag == TYPE_FIX_GPS) {
result->latitude = R2D(result->latitude);
result->longitudinal = R2D(result->longitudinal);
lapProcess(pgnss, result);
} else {
LatLng lla = { 0 };
lla.lat = R2D(result->latitude);
lla.lon = R2D(result->longitudinal);
if (result->last_lat != 0.0 && result->last_lon != 0.0 &&
calDistance(lla, lla_last) > 10) {
TrackSmoothSetWinSize(slideWindowSize);
}
result->latitude = R2D(result->latitude);
result->longitudinal = R2D(result->longitudinal);
lapProcess(pgnss, result);
result->latitude = (result->latitude) * RADIAN_PER_DEG;
result->longitudinal = (result->longitudinal) * RADIAN_PER_DEG;
#if PDR_OUTPUT_SMOOTH
double outLat = 0, outLon = 0;
// 输出轨迹平滑
pdr_trackSmooth(R2D(result->latitude), R2D(result->longitudinal) ,
&outLat, &outLon);
result->latitude = outLat;
result->longitudinal = outLon;
#else
result->latitude = R2D(result->latitude);
result->longitudinal = R2D(result->longitudinal);
#endif
result->last_lat = result->latitude;
result->last_lon = result->longitudinal;
lla_last.lat = lla.lat;
lla_last.lon = lla.lon;
}
type = 1;
}else if (result->last_lat != 0.0 && result->last_lon != 0.0) {
result->latitude = result->last_lat;
result->longitudinal = result->last_lon;
type = 1;
lapProcess(pgnss, result);
}
clearNmeaFlg(nmea_data);
return type;
}
/**---------------------------------------------------------------------
* Function : pdr_saveGnssInfo
* Description : GPS
* Date : 2020/7/3 logzhan
*---------------------------------------------------------------------**/
void pdr_saveGnssInfo(lct_nmea* nmea_data, lct_fs* result, FILE* fp_gps)
{
lct_nmea_rmc rmc = nmea_data->rmc[1];
// 选取更新时间的rmc
if (nmea_data->rmc[0].time > nmea_data->rmc[1].time) {
rmc = nmea_data->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_data->accuracy.time) < 500){
accuracy = nmea_data->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);
pdr_WriteCsvStr(fp_gps, str);
result->gpsLat = rmc.latitude;
result->gpsLon = rmc.longitudinal;
}
}
/**----------------------------------------------------------------------
* Function : pdr_libVersion
* Description : pdr
* Date : 2020/8/3 logzhan
*---------------------------------------------------------------------**/
const char* pdr_libVersion(void){
return pdrVersion;
}
/**----------------------------------------------------------------------
* Function : pdr_closeAlgorithm
* Description : PDR,
* Date : 2020/8/3 logzhan
*---------------------------------------------------------------------**/
void pdr_closeAlgorithm() {
freeTrackSmooth();
scene_recognition_destroy();
}

View File

@ -1,745 +0,0 @@
/******************** (C) COPYRIGHT 2020 Geek************************************
* File Name : pdr_base.c
* Department : Sensor Algorithm Team
* Current Version : V1.2
* Author : logzhan
* Date of Issued : 2021.02.02
* Comments : PDR
********************************************************************************/
/* Header File Including -----------------------------------------------------*/
#include <string.h>
#include <math.h>
#include "pdr_location.h"
#include "pdr_kalman.h"
#include "pdr_util.h"
#include "pdr_ahrs.h"
#include "pdr_detector.h"
#include "buffer.h"
#include "Filter.h"
#include "pdr_base.h"
#include "pdr_fft.h"
/* Macro Definition ----------------------------------------------------------*/
#define DOWNSAMPLING_RATE 4
#define BUF_LEN 256
#define ARR_LEN(arr) (sizeof(arr) / sizeof(*arr))
#define INC_PTR(buf, ptr) (((ptr) + 1) % ((buf)->length + 1))
#define GET_MOL(v) ((float)sqrt((v)[0] * (v)[0] + (v)[1] * (v)[1]))
#define P_SET_BIT(msk) (g_pdr.status |= PDR_STATUS_##msk)
#define P_CLR_BIT(msk) (g_pdr.status &= ~PDR_STATUS_##msk)
#define P_TST_BIT(msk) (g_pdr.status & PDR_STATUS_##msk)
/* Global Variable Definition ------------------------------------------------*/
PDR g_pdr;
static DETECTOR *g_detector;
static uint64_t g_tick_p;
static uint32_t g_motion_type;
static uint32_t g_axis_ceof_counter;
static BUFFER_LONG g_axis[9];
static BUFFER_LONG g_grav[2];
static BUFFER_LONG g_erro;
static BUFFER_LONG g_posi[4];
static int angle_count;
static double p_angle[3][BUF_LEN];
double angle_mean[3] = { 0 };
static FILTER g_grv_flt[2];
#if defined(__MATLAB_DBG)
static int g_debug[2];
static float axis_mean[9];
#endif
const double g_grv_flt_b[] = { 4.62344870721942e-10, 4.62344870721942e-09, 2.08055191824874e-08, 5.54813844866331e-08,
9.70924228516079e-08, 1.16510907421929e-07, 9.70924228516079e-08, 5.54813844866331e-08,
2.08055191824874e-08, 4.62344870721942e-09, 4.62344870721942e-10 };
const double g_grv_flt_a[] = { 1, -8.39368255078839, 31.8158646581919, -71.7026569821430, 106.381617694638,
-108.553825650279, 77.1444606240244, -37.6960546719428, 12.1197601392885,
-2.31493776310228, 0.199454975553812 };
const double g_grv_flt_h0 = 1;
PDR* pdr_initBase() {
g_detector = pdr_getDetector();
Buffer_initialize((BUFFER *)&g_axis[0], "x_axis_0", BUFFER_TYPE_QUEUE, BUF_LEN);
Buffer_initialize((BUFFER *)&g_axis[1], "x_axis_1", BUFFER_TYPE_QUEUE, BUF_LEN);
Buffer_initialize((BUFFER *)&g_axis[2], "x_axis_2", BUFFER_TYPE_QUEUE, BUF_LEN);
Buffer_initialize((BUFFER *)&g_axis[3], "y_axis_0", BUFFER_TYPE_QUEUE, BUF_LEN);
Buffer_initialize((BUFFER *)&g_axis[4], "y_axis_1", BUFFER_TYPE_QUEUE, BUF_LEN);
Buffer_initialize((BUFFER *)&g_axis[5], "y_axis_2", BUFFER_TYPE_QUEUE, BUF_LEN);
Buffer_initialize((BUFFER *)&g_axis[6], "z_axis_0", BUFFER_TYPE_QUEUE, BUF_LEN);
Buffer_initialize((BUFFER *)&g_axis[7], "z_axis_1", BUFFER_TYPE_QUEUE, BUF_LEN);
Buffer_initialize((BUFFER *)&g_axis[8], "z_axis_2", BUFFER_TYPE_QUEUE, BUF_LEN);
Buffer_initialize((BUFFER *)&g_grav[0], "grav_0", BUFFER_TYPE_QUEUE, BUF_LEN);
Buffer_initialize((BUFFER *)&g_grav[1], "grav_1", BUFFER_TYPE_QUEUE, BUF_LEN);
Buffer_initialize((BUFFER *)&g_erro, "erro", BUFFER_TYPE_QUEUE, 5 * IMU_SAMPLING_FREQUENCY / DOWNSAMPLING_RATE);
Buffer_initialize((BUFFER *)&g_posi[0], "posi_0", BUFFER_TYPE_QUEUE, 60);
Buffer_initialize((BUFFER *)&g_posi[1], "posi_1", BUFFER_TYPE_QUEUE, 60);
Buffer_initialize((BUFFER *)&g_posi[2], "posi_2", BUFFER_TYPE_QUEUE, 60);
Buffer_initialize((BUFFER *)&g_posi[3], "posi_3", BUFFER_TYPE_QUEUE, 60);
FILTER_setCoef(&g_grv_flt[0], ARR_LEN(g_grv_flt_b), (double *)g_grv_flt_b, (double *)g_grv_flt_a, (double)g_grv_flt_h0);
FILTER_setCoef(&g_grv_flt[1], ARR_LEN(g_grv_flt_b), (double *)g_grv_flt_b, (double *)g_grv_flt_a, (double)g_grv_flt_h0);
pdr_resetData();
return &g_pdr;
}
/**----------------------------------------------------------------------
* Function : pdr_resetData
* Description : PDR
* Date : 2020/7/21 logzhan
*---------------------------------------------------------------------**/
void pdr_resetData(void) {
memset(&g_pdr, 0, sizeof(g_pdr));
g_pdr.status = PDR_STATUS_RESET;
g_pdr.axis_ceofficient[0] = 0;
g_pdr.axis_ceofficient[1] = 1;
g_pdr.axis_ceofficient[2] = 0;
g_pdr.bias_direction[0] = 1;
g_pdr.bias_direction[1] = 0;
g_pdr.pca_accuracy = -1;
g_pdr.bias_accuracy = -1;
// 初始坐标初始化为0
g_pdr.x0 = 0;
g_pdr.y0 = 0;
// 初始步数为0
g_pdr.steps = 0;
g_pdr.lastSteps = 0;
g_pdr.lastGpsSteps = 0;
g_pdr.deltaStepsPerGps = 0;
g_pdr.heading = 0.0;
g_pdr.lastHeading = 0.0;
g_pdr.deltaHeading = 0.0;
g_pdr.ts = 0.0;
g_pdr.sysStatus = IS_INITIAL;
g_pdr.noGpsCount = 0;
g_pdr.sceneType = UN_OPEN_AREA;
g_pdr.fusionPdrFlg = PDR_FALSE;
g_pdr.gpsHeading = 0;
g_pdr.trackHeading = ITEM_INVALID;
g_pdr.motionFreq = 0.1f;
g_pdr.insHeadingOffset = 0.0f;
g_pdr.gyroTime = 0.0;
memset(g_pdr.pllaInit, 0, sizeof(g_pdr.pllaInit));
g_tick_p = 0;
g_motion_type = g_detector->type;
g_axis_ceof_counter = 0;
Buffer_clear((BUFFER *)&g_axis[0]);
Buffer_clear((BUFFER *)&g_axis[1]);
Buffer_clear((BUFFER *)&g_axis[2]);
Buffer_clear((BUFFER *)&g_axis[3]);
Buffer_clear((BUFFER *)&g_axis[4]);
Buffer_clear((BUFFER *)&g_axis[5]);
Buffer_clear((BUFFER *)&g_axis[6]);
Buffer_clear((BUFFER *)&g_axis[7]);
Buffer_clear((BUFFER *)&g_axis[8]);
Buffer_clear((BUFFER *)&g_grav[0]);
Buffer_clear((BUFFER *)&g_grav[1]);
Buffer_clear((BUFFER *)&g_erro);
Buffer_clear((BUFFER *)&g_posi[0]);
Buffer_clear((BUFFER *)&g_posi[1]);
Buffer_clear((BUFFER *)&g_posi[2]);
Buffer_clear((BUFFER *)&g_posi[3]);
FILTER_reset(&g_grv_flt[0]);
FILTER_reset(&g_grv_flt[1]);
angle_count = 0;
memset(&p_angle, 0, sizeof(p_angle));
memset(&angle_mean, 0, sizeof(angle_mean));
}
static float get_main_frequency(BUFFER_SHORT *frequency, BUFFER_SHORT *amplitude, int number) {
float amp[3] = { {0.0f} };
float frq;
int count;
int index;
int i;
if (number > 3) {
return 0;
}
for (i = 0; i < number; ++i) {
amp[i] = 0;
count = 0;
for (index = amplitude[i]._bottom; index != amplitude[i]._top; index = INC_PTR(&amplitude[i], index)) {
if (0 != amplitude[i].data[index]) {
amp[i] += amplitude[i].data[index];
++count;
}
}
if (0 != count) {
amp[i] /= count;
}
}
i = amp[0] > amp[1] ? 0 : 1;
i = amp[i] > amp[2] ? i : 2;
frq = 0;
count = 0;
for (index = frequency[i]._bottom; index != frequency[i]._top; index = INC_PTR(&frequency[i], index)) {
if (0 != frequency[i].data[index]) {
frq += frequency[i].data[index];
++count;
}
}
if (0 != count) {
frq /= count;
}
return frq;
}
static int get_optimal_length_by_frequency(BUFFER_LONG *buffer, float frequency) {
int temp;
if (0 != frequency) {
temp = (int)((int)(buffer->length / (IMU_SAMPLING_FREQUENCY / frequency)) * (IMU_SAMPLING_FREQUENCY / frequency));
return 0 == temp ? buffer->length : temp;
}
else {
return buffer->length;
}
}
static void get_buffer_mean(float *mean, BUFFER_LONG *buffer, int length) {
int count;
int index;
int i;
count = (buffer->_top - buffer->_bottom + buffer->length + 1) % (buffer->length + 1);
length = count < length ? count : length;
count = 0;
memset(mean, 0, 3 * sizeof(*mean));
for (index = (buffer->_top + buffer->length + 1 - length) % (buffer->length + 1); index != buffer->_top; index = INC_PTR(buffer, index)) {
for (i = 0; i < 3; ++i) {
mean[i] += buffer[i].data[index];
}
++count;
}
mean[0] /= count;
mean[1] /= -count;
mean[2] /= -count;
}
static void get_pca_direction(float *direction, BUFFER_LONG *buffer, int length) {
float buff_mean[2];
float varX;
float varY;
float varXY;
float lambda;
int count;
int index;
int i;
count = (buffer->_top - buffer->_bottom + buffer->length + 1) % (buffer->length + 1);
length = count < length ? count : length;
memset(buff_mean, 0, sizeof(buff_mean));
for (index = (buffer[0]._top + buffer[0].length + 1 - length) % (buffer[0].length + 1); index != buffer[0]._top; index = INC_PTR(&buffer[0], index)) {
for (i = 0; i < 2; ++i) {
buff_mean[i] += buffer[i].data[index];
}
}
buff_mean[0] /= length;
buff_mean[1] /= length;
varX = 0;
varY = 0;
varXY = 0;
for (index = (buffer[0]._top + buffer[0].length + 1 - length) % (buffer[0].length + 1); index != buffer[0]._top; index = INC_PTR(&buffer[0], index)) {
float deltaX = buffer[0].data[index] - buff_mean[0];
float deltaY = buffer[1].data[index] - buff_mean[1];
varX += deltaX * deltaX;
varY += deltaY * deltaY;
varXY += deltaX * deltaY;
}
lambda = ((varX + varY) + (float)sqrt((varX - varY) * (varX - varY) + 4 * varXY * varXY)) * 0.5f;
if (0 != varXY) {
direction[0] = (lambda - varY) / varXY;
direction[1] = InvSqrt(direction[0] * direction[0] + 1);
direction[0] *= direction[1];
direction[1] = -direction[1];
}
else {
direction[0] = 0;
direction[1] = 0;
}
}
static void caculate_determinant(float *determinant, float A[][3], int row, int col) {
int k = 0;
float temp[4];
for (uchar i = 0; i < 3; ++i) {
if (row == i) continue;
for (uchar j = 0; j < 3; ++j) {
if (col == j) continue;
temp[k++] = A[i][j];
}
}
*determinant = temp[0] * temp[3] - temp[1] * temp[2];
}
static void caculate_adjoint_matrix(float A_star[][3], float A[][3]) {
int i;
int j;
for (i = 0; i < 3; ++i) {
for (j = 0; j < 3; ++j) {
caculate_determinant(&A_star[i][j], A, j, i);
if ((i + j) % 2) {
A_star[i][j] = -A_star[i][j];
}
}
}
}
static void get_ceof_by_pca(float *ceof, float *axis_mean, float *pca_direction) {
float A[3][3];
float A_star[3][3];
float x[3];
float axs_dir[2];
float mold;
int dir;
int i;
int j;
/* caculate adjoint matrix */
for (i = 0; i < 3; ++i) {
for (j = 0; j < 3; ++j) {
A[i][j] = axis_mean[j * 3 + i];
}
}
caculate_adjoint_matrix(A_star, A);
/* caculate x vector (Ax = b) */
for (i = 0; i < 3; ++i) {
x[i] = A_star[i][0] * pca_direction[0] + A_star[i][1] * pca_direction[1];
}
mold = (float)sqrt(x[0] * x[0] + x[1] * x[1] + x[2] * x[2]);
if (0 == mold) {
goto GET_CEOF_BY_PCA_ARITHMETIC_ERROR;
}
for (i = 0; i < 3; ++i) {
x[i] /= mold;
}
for (i = 0; i < 2; ++i) {
axs_dir[i] = A[i][0] * ceof[0] + A[i][1] * ceof[1] + A[i][2] * ceof[2];
}
dir = (axs_dir[0] * pca_direction[0] + axs_dir[1] * pca_direction[1] < 0) ? -1 : 1;
for (i = 0; i < 3; ++i) {
ceof[i] = dir * x[i];
}
return;
GET_CEOF_BY_PCA_ARITHMETIC_ERROR:
ceof[0] = 0;
ceof[1] = 1;
ceof[2] = 0;
}
static void correct_axis_ceofficient(float ratio) {
float axis_mean[9];
float pca_direction[2];
float axis_ceofficient[3];
float mold;
int length;
int i;
length = get_optimal_length_by_frequency(g_axis, g_pdr.motionFreq);
get_buffer_mean(&axis_mean[0], &g_axis[0], length);
get_buffer_mean(&axis_mean[3], &g_axis[3], length);
get_buffer_mean(&axis_mean[6], &g_axis[6], length);
get_pca_direction(pca_direction, g_grav, length);
memcpy((void *)axis_ceofficient, (void *)g_pdr.axis_ceofficient, sizeof(g_pdr.axis_ceofficient));
get_ceof_by_pca(axis_ceofficient, axis_mean, pca_direction);
for (i = 0; i < 3; ++i) {
g_pdr.axis_ceofficient[i] = (1 - ratio) * g_pdr.axis_ceofficient[i] + ratio * axis_ceofficient[i];
}
mold = (float)sqrt(g_pdr.axis_ceofficient[0] * g_pdr.axis_ceofficient[0] + g_pdr.axis_ceofficient[1] * g_pdr.axis_ceofficient[1] + g_pdr.axis_ceofficient[2] * g_pdr.axis_ceofficient[2]);
for (i = 0; i < 3; ++i) {
g_pdr.axis_ceofficient[i] /= mold;
}
}
/**----------------------------------------------------------------------
* Function : pdr_computePCA
* Description : RESET_PHASE_1\STABLEPCA
* Date : 2020/7/21 logzhan
*---------------------------------------------------------------------**/
void pdr_computePCA(AHRS *ahrs) {
float axis_mean[9];
float freq;
float mold;
int length;
int i;
double attitude[3];
double angle_sum[3] = { 0 };
int angle_len;
//RESET_1时只加ticker之后直接返回
/* filter bad data */
if (AHRS_STATUS_RESET & ahrs->status) {
++g_tick_p;
return;
}
/* caculate axis ceofficient */
/*PDR_STATUS_CACULATING_AXIS_CEOFFICIENT 0x40*/
if (P_TST_BIT(CACULATING_AXIS_CEOFFICIENT) && \
(g_grav[0]._top - g_grav[0]._bottom + g_grav[0].length + 1) % (g_grav[0].length + 1) > (BUF_LEN >> 1)) {
correct_axis_ceofficient(0.50f);
P_CLR_BIT(CACULATING_AXIS_CEOFFICIENT);
P_SET_BIT(PCA_STABLE);
g_erro._bottom = 0;
for (g_erro._top = 0; g_erro._top < g_erro.length && g_erro._top < 2 * IMU_SAMPLING_FREQUENCY / DOWNSAMPLING_RATE; ++g_erro._top) {
g_erro.data[g_erro._top] = (g_erro._top % 2) ? +0.4f : -0.4f;
}
Buffer_clear((BUFFER *)&g_posi[0]);
Buffer_clear((BUFFER *)&g_posi[1]);
Buffer_clear((BUFFER *)&g_posi[2]);
Buffer_clear((BUFFER *)&g_posi[3]);
g_pdr.bias_direction[0] = 1;
g_pdr.bias_direction[1] = 0;
g_pdr.bias_accuracy = -1;
//++flag;
//}
}
/* correct axis ceofficient */
if ((g_pdr.status & PDR_STATUS_PCA_STABLE) && 0 == (g_tick_p % (2 * IMU_SAMPLING_FREQUENCY))) {
correct_axis_ceofficient(0.10f);
}
/* downsample */
if (0 != (g_tick_p % DOWNSAMPLING_RATE)) {
++g_tick_p;
return;
}
/* push data */
for (i = 0; i < 3; ++i) {
buffer_push((BUFFER *)&g_axis[0 + i], ahrs->x_axis[i]);
buffer_push((BUFFER *)&g_axis[3 + i], ahrs->y_axis[i]);
buffer_push((BUFFER *)&g_axis[6 + i], ahrs->z_axis[i]);
}
for (i = 0; i < 2; ++i) {
//Buffer_push((BUFFER *)&g_grav[i], (float)FILTER_filter(&g_grv_flt[i], ahrs->gravity[i]));
buffer_push((BUFFER *)&g_grav[i], ahrs->gravity[i]);
}
/* motion frequency */
freq = get_main_frequency(g_acc_frq_buf, g_acc_amp_buf, 3);
if (3.5 >= freq && freq > 1.5) {
g_pdr.motionFreq = freq;
}
else if (1.5 >= freq && freq > 0.75){
g_pdr.motionFreq = 2 * freq;
}
/* axis direction */
length = get_optimal_length_by_frequency(g_axis, g_pdr.motionFreq);
get_buffer_mean(&axis_mean[0], &g_axis[0], length);
get_buffer_mean(&axis_mean[3], &g_axis[3], length);
get_buffer_mean(&axis_mean[6], &g_axis[6], length);
memset(g_pdr.axis_direction, 0, sizeof(g_pdr.axis_direction));
for (i = 0; i < 2; ++i) {
g_pdr.axis_direction[i] = g_pdr.axis_ceofficient[0] * axis_mean[0 + i] + g_pdr.axis_ceofficient[1] * axis_mean[3 + i] + g_pdr.axis_ceofficient[2] * axis_mean[6 + i];
}
mold = (float)GET_MOL(g_pdr.axis_direction);
if (0 != mold) {
g_pdr.axis_direction[0] /= mold;
g_pdr.axis_direction[1] /= mold;
}
/* pca direction */
get_pca_direction(g_pdr.pca_direction, g_grav, length);
if (g_pdr.pca_direction[0] * g_pdr.axis_direction[0] + g_pdr.pca_direction[1] * g_pdr.axis_direction[1] < 0) {
g_pdr.pca_direction[0] = -g_pdr.pca_direction[0];
g_pdr.pca_direction[1] = -g_pdr.pca_direction[1];
}
/* direction accuracy */
/*代码疑问1g_erro为什么由下式确定什么含义*/
buffer_push((BUFFER *)&g_erro, (float)fabs(g_pdr.axis_direction[0] * g_pdr.pca_direction[1] - g_pdr.axis_direction[1] * g_pdr.pca_direction[0]));
if (!P_TST_BIT(CACULATING_AXIS_CEOFFICIENT)) {
float accuracy;
Buffer_std((BUFFER *)&g_erro, &accuracy);
if (DETECTOR_TYPE_HANDHELD == g_pdr.motionType) {
if (!P_TST_BIT(STABLE) && !P_TST_BIT(CACULATING_AXIS_CEOFFICIENT) && 0.15 >= accuracy) {
P_SET_BIT(CACULATING_AXIS_CEOFFICIENT);
}
else if (g_pdr.pca_accuracy < 0.30 && 0.30 <= accuracy) {
P_CLR_BIT(CACULATING_AXIS_CEOFFICIENT);
P_CLR_BIT(STABLE);
}
}
g_pdr.pca_accuracy = accuracy;
}
else {
g_pdr.pca_accuracy = -1;
}
/* calibrated direction */
g_pdr.cal_direction[0] = g_pdr.pca_direction[0] * g_pdr.bias_direction[0] + g_pdr.pca_direction[1] * g_pdr.bias_direction[1];
g_pdr.cal_direction[1] = g_pdr.pca_direction[1] * g_pdr.bias_direction[0] - g_pdr.pca_direction[0] * g_pdr.bias_direction[1];
//PDR_LOGD("%f %f\n", g_pdr.cal_direction[0],g_pdr.cal_direction[1]);
if (DETECTOR_TYPE_STATIC == g_detector->type || DETECTOR_TYPE_IRREGULAR == g_detector->type) {
g_pdr.motionFreq = 0;
}
Qnb2Att(ahrs->qnb,attitude);
if (angle_count < BUF_LEN - 1)
{
p_angle[0][angle_count] = attitude[0];
p_angle[1][angle_count] = attitude[1];
p_angle[2][angle_count] = attitude[2];
angle_count++;
}
else{
for (int i = 0; i < BUF_LEN - 1; i++)
{
p_angle[0][i] = p_angle[0][i + 1];
p_angle[1][i] = p_angle[1][i + 1];
p_angle[2][i] = p_angle[2][i + 1];
}
p_angle[0][BUF_LEN - 1] = attitude[0];
p_angle[1][BUF_LEN - 1] = attitude[1];
p_angle[2][BUF_LEN - 1] = attitude[2];
angle_len = (length <= BUF_LEN) ? length : BUF_LEN;
for (int j = BUF_LEN - 1; j >(BUF_LEN - 1 - angle_len); j--)
{
angle_sum[0] = angle_sum[0] + p_angle[0][j];
angle_sum[1] = angle_sum[1] + p_angle[1][j];
angle_sum[2] = angle_sum[2] + p_angle[2][j];
}
angle_mean[0] = angle_sum[0] / angle_len;
angle_mean[1] = angle_sum[1] / angle_len;
angle_mean[2] = angle_sum[2] / angle_len;
}
++g_tick_p;
}
/**----------------------------------------------------------------------
* Function : pdr_outputGpsPos
* Description : PDRGPS
* Date : 2020/07/08 logzhan
*---------------------------------------------------------------------**/
void pdr_outputGpsPos(gnss* pgnss, lct_fs* 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 : pdr_detStatic
* Description : ,
*
* Date : 2021/01/28 logzhan
*---------------------------------------------------------------------**/
int pdr_detStatic(PDR* g_pdr, gnss* 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 : detIsCarMode
* Description :
* Input : pgnssGPS
g_pdrPDR
delSteps
time
* Output : int
* Date : 2021/01/28 logzhan
*---------------------------------------------------------------------**/
int detIsCarMode(gnss* pgnss, PDR* g_pdr, unsigned long delSteps, int* time) {
if ((pgnss->vel > 10 && delSteps == 0) ||
(delSteps == 0 && g_pdr->motionFreq == 0.0 && pgnss->vel > 3 && pgnss->error < 30))
{
(*time)++;
}else {
*time = 0;
}
if (*time > 5) {
return PDR_TRUE;
}
return PDR_FALSE;
}
/**----------------------------------------------------------------------
* Function : detPdrToReset
* Description : PDRPDR
* PDRGPS
* Date : 2021/01/28 logzhan
*---------------------------------------------------------------------**/
int detPdrToReset(double pdr_angle, int* gpscnt, ulong deltsteps, PDR* g_pdr) {
if ((pdr_angle < 0 && deltsteps > 0) || (deltsteps > 0 && (g_pdr->motionFreq == 0))) {
(*gpscnt)++;
}else {
*gpscnt = 0;
}
return (*gpscnt > 6);
}
/**---------------------------------------------------------------------
* Function : detectorUpdate
* Description : g_pdr.status
* Date : 2020/7/20 logzhan
*---------------------------------------------------------------------**/
void detectorUpdate(DETECTOR *detector) {
// 设置PDR的运动类型
g_pdr.motionType = detector->type;
if (DETECTOR_TYPE_SWINGING == g_pdr.motionType && DETECTOR_TYPE_SWINGING != g_motion_type) {
if (!P_TST_BIT(STABLE)) {
P_SET_BIT(CACULATING_AXIS_CEOFFICIENT);
P_CLR_BIT(STABLE);
}
}
else if ((DETECTOR_TYPE_STATIC == g_pdr.motionType || DETECTOR_TYPE_IRREGULAR == g_pdr.motionType) &&
(DETECTOR_TYPE_HANDHELD == g_motion_type || DETECTOR_TYPE_SWINGING == g_motion_type)) {
P_CLR_BIT(CACULATING_AXIS_CEOFFICIENT);
P_CLR_BIT(STABLE);
}
g_motion_type = g_pdr.motionType;
}
/**---------------------------------------------------------------------
* Function : gpsUpdateCb
* Description : gpsPCAGPS
* PCA
* Date : 2020/02/16 logzhan
*---------------------------------------------------------------------**/
void gpsUpdateCb(gnss* gps)
{
float temp;
float meanA[2];
float meanY[2];
float ctc; // ctc[0][0], ctc[1][1]
float cty[2];
float a[2];
float mold;
float dx;
float dy;
int count;
int index;
/* filter bad point */
double vel_thr;
double error_thr;
if (g_pdr.sceneType) {
vel_thr = 2.5;
error_thr = 6;
}
else {
vel_thr = 1.0;
error_thr = 15;
}
if (fabs(gps->timestamps - g_pdr.gyroTime) > 1000
|| gps->vel < vel_thr \
|| gps->error > error_thr \
|| (DETECTOR_TYPE_SWINGING != g_detector->type && DETECTOR_TYPE_HANDHELD != g_detector->type) \
|| -1 == g_pdr.pca_accuracy \
|| gps->yaw < 0) {
return;
}
/* caculate position */
Buffer_top((BUFFER *)&g_posi[0], &temp);
buffer_push((BUFFER *)&g_posi[0], temp + (float)cos(gps->yaw / 180 * M_PI));
Buffer_top((BUFFER *)&g_posi[1], &temp);
buffer_push((BUFFER *)&g_posi[1], temp + (float)sin(gps->yaw / 180 * M_PI));
Buffer_top((BUFFER *)&g_posi[2], &temp);
buffer_push((BUFFER *)&g_posi[2], temp + g_pdr.pca_direction[0]);
Buffer_top((BUFFER *)&g_posi[3], &temp);
buffer_push((BUFFER *)&g_posi[3], temp + g_pdr.pca_direction[1]);
if ((g_posi[0]._top - g_posi[0]._bottom + g_posi[0].length + 1) % (g_posi[0].length + 1) >= 5) {
count = 0;
meanA[0] = 0;
meanA[1] = 0;
meanY[0] = 0;
meanY[1] = 0;
for (index = g_posi[0]._bottom; index != g_posi[0]._top; index = INC_PTR(&g_posi[0], index)) {
meanA[0] += g_posi[0].data[index];
meanA[1] += g_posi[1].data[index];
meanY[0] += g_posi[2].data[index];
meanY[1] += g_posi[3].data[index];
++count;
}
meanA[0] /= count;
meanA[1] /= count;
meanY[0] /= count;
meanY[1] /= count;
for (index = g_posi[0]._bottom; index != g_posi[0]._top; index = INC_PTR(&g_posi[0], index)) {
g_posi[0].data[index] -= meanA[0];
g_posi[1].data[index] -= meanA[1];
g_posi[2].data[index] -= meanY[0];
g_posi[3].data[index] -= meanY[1];
}
ctc = 0;
cty[0] = 0;
cty[1] = 0;
for (index = g_posi[0]._bottom; index != g_posi[0]._top; index = INC_PTR(&g_posi[0], index)) {
ctc += g_posi[0].data[index] * g_posi[0].data[index] + g_posi[1].data[index] * g_posi[1].data[index];
cty[0] += g_posi[0].data[index] * g_posi[2].data[index] + g_posi[1].data[index] * g_posi[3].data[index];
cty[1] += -g_posi[1].data[index] * g_posi[2].data[index] + g_posi[0].data[index] * g_posi[3].data[index];
}
if (0 != ctc) {
/* (c^Tc)^{-1}c^Ty */
a[0] = cty[0] / ctc;
a[1] = cty[1] / ctc;
}
else {
goto GPS_UPDATE_ARITHMETIC_ERROR;
}
if (0 == (mold = (float)GET_MOL(a))) {
goto GPS_UPDATE_ARITHMETIC_ERROR;
}
g_pdr.bias_direction[0] = a[0] / mold;
g_pdr.bias_direction[1] = a[1] / mold;
g_pdr.bias_accuracy = 0;
for (index = g_posi[0]._bottom; index != g_posi[0]._top; index = INC_PTR(&g_posi[0], index)) {
dx = g_posi[2].data[index] - a[0] * g_posi[0].data[index] + a[1] * g_posi[1].data[index];
dy = g_posi[3].data[index] - a[1] * g_posi[0].data[index] - a[0] * g_posi[1].data[index];
g_pdr.bias_accuracy += dx * dx + dy * dy;
}
g_pdr.bias_accuracy = (float)sqrt(g_pdr.bias_accuracy / count);
P_SET_BIT(BIAS_STABLE);
return;
}
GPS_UPDATE_ARITHMETIC_ERROR:
g_pdr.bias_direction[0] = 1;
g_pdr.bias_direction[1] = 0;
g_pdr.bias_accuracy = -1;
P_CLR_BIT(BIAS_STABLE);
}

View File

@ -1,875 +0,0 @@
/******************** (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 "pdr_base.h"
#include "pdr_detector.h"
#include "Filter.h"
#include "buffer.h"
#include "pdr_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]
#define CALIBRATE_ON 1
#define CALIBRATE_OFF 0
extern int debugCount;
static float ellipsoidPoint[3];
static float ellipsoidScale[3];
/* Global Variable Definition ------------------------------------------------*/
static DETECTOR g_detector;
static BUFFER_LONG g_mol_buf[2];
static FILTER 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 float mag_buff[MAG_BUF_LEN][3];
static int mag_count;
static unsigned char mag_calibrate;
//static double mag_time;
static int g_label[5] = { 0 };
/* Function Definition -------------------------------------------------------------------------- */
/**---------------------------------------------------------------------
* Function : pdr_getDetector
* Description : PDR
* Date : 2020/02/16 logzhan &
*
*
*---------------------------------------------------------------------**/
DETECTOR* pdr_getDetector(void) {
return &g_detector;
}
/**---------------------------------------------------------------------
* Function : pdr_initDetector
* Description :
* Date : 2020/02/16 logzhan & logzhan
*---------------------------------------------------------------------**/
DETECTOR* pdr_initDetector(void) {
pdr_resetDetector();
return &g_detector;
}
/**---------------------------------------------------------------------
* Function : pdr_resetDetector
* Description : PDR
* Date : 2020/02/16 logzhan & logzhan
*---------------------------------------------------------------------**/
void pdr_resetDetector(void) {
g_detector.tick = 0;
g_detector.lastType = DETECTOR_TYPE_STATIC;
Buffer_initialize((BUFFER *)&g_mol_buf[ACCE], "acce_mold_filtered", BUFFER_TYPE_QUEUE, FLT_BUF_LEN);
Buffer_initialize((BUFFER *)&g_mol_buf[GYRO], "gyro_mold_filtered", BUFFER_TYPE_QUEUE, FLT_BUF_LEN);
Buffer_initialize((BUFFER *)&g_acc_frq_buf[0], "acc_frq_buf_0", BUFFER_TYPE_QUEUE, FRQ_BUF_LEN);
Buffer_initialize((BUFFER *)&g_acc_frq_buf[1], "acc_frq_buf_1", BUFFER_TYPE_QUEUE, FRQ_BUF_LEN);
Buffer_initialize((BUFFER *)&g_acc_frq_buf[2], "acc_frq_buf_2", BUFFER_TYPE_QUEUE, FRQ_BUF_LEN);
Buffer_initialize((BUFFER *)&g_acc_amp_buf[0], "acc_amp_buf_0", BUFFER_TYPE_QUEUE, FRQ_BUF_LEN);
Buffer_initialize((BUFFER *)&g_acc_amp_buf[1], "acc_amp_buf_1", BUFFER_TYPE_QUEUE, FRQ_BUF_LEN);
Buffer_initialize((BUFFER *)&g_acc_amp_buf[2], "acc_amp_buf_2", BUFFER_TYPE_QUEUE, FRQ_BUF_LEN);
Buffer_initialize((BUFFER *)&g_acc_tmp_buf[0], "acc_tmp_buf_0", BUFFER_TYPE_QUEUE, TMP_BUF_LEN);
Buffer_initialize((BUFFER *)&g_acc_tmp_buf[1], "acc_tmp_buf_1", BUFFER_TYPE_QUEUE, TMP_BUF_LEN);
Buffer_initialize((BUFFER *)&g_acc_tmp_buf[2], "acc_tmp_buf_2", BUFFER_TYPE_QUEUE, TMP_BUF_LEN);
Buffer_initialize((BUFFER *)&g_gyr_frq_buf[0], "gyr_frq_buf_0", BUFFER_TYPE_QUEUE, FRQ_BUF_LEN);
Buffer_initialize((BUFFER *)&g_gyr_frq_buf[1], "gyr_frq_buf_1", BUFFER_TYPE_QUEUE, FRQ_BUF_LEN);
Buffer_initialize((BUFFER *)&g_gyr_frq_buf[2], "gyr_frq_buf_2", BUFFER_TYPE_QUEUE, FRQ_BUF_LEN);
Buffer_initialize((BUFFER *)&g_gyr_amp_buf[0], "gyr_amp_buf_0", BUFFER_TYPE_QUEUE, FRQ_BUF_LEN);
Buffer_initialize((BUFFER *)&g_gyr_amp_buf[1], "gyr_amp_buf_1", BUFFER_TYPE_QUEUE, FRQ_BUF_LEN);
Buffer_initialize((BUFFER *)&g_gyr_amp_buf[2], "gyr_amp_buf_2", BUFFER_TYPE_QUEUE, FRQ_BUF_LEN);
Buffer_initialize((BUFFER *)&g_gyr_tmp_buf[0], "gyr_tmp_buf_0", BUFFER_TYPE_QUEUE, TMP_BUF_LEN);
Buffer_initialize((BUFFER *)&g_gyr_tmp_buf[1], "gyr_tmp_buf_1", BUFFER_TYPE_QUEUE, TMP_BUF_LEN);
Buffer_initialize((BUFFER *)&g_gyr_tmp_buf[2], "gyr_tmp_buf_2", BUFFER_TYPE_QUEUE, TMP_BUF_LEN);
FILTER_setCoef(&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);
FILTER_setCoef(&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(*mag_buff,0,sizeof(mag_buff));
mag_count = 0;
mag_calibrate = CALIBRATE_OFF;
ellipsoidPoint[0] = 0;
ellipsoidPoint[1] = 0;
ellipsoidPoint[2] = 0;
ellipsoidScale[0] = 1;
ellipsoidScale[1] = 1;
ellipsoidScale[2] = 1;
memset((void *)g_label, 0, sizeof(g_label));
}
/**---------------------------------------------------------------------
* Function : updateDetectorImu
* Description : imu
*
* Date : 2020/09/02
*
*---------------------------------------------------------------------**/
void updateDetectorImu(imu* imu) {
buffer_push((BUFFER *)&g_mol_buf[ACCE], (float)FILTER_filter(&g_mol_flt[ACCE], GET_MOL(imu->acc.s)));
buffer_push((BUFFER *)&g_mol_buf[GYRO], (float)FILTER_filter(&g_mol_flt[GYRO], GET_MOL(imu->gyr.s)));
// g_tick_d 实际上是1.28s检测一次,不然检测的频率过高
if ((g_detector.tick % (int)(1.28 * IMU_SAMPLING_FREQUENCY)) == 0) {
// 检测用户的运动类型
int detectResult = pdr_motionTypeDetect();
//mag_calibration(imu);
if (detectResult == DETECTOR_NO_ERROR && g_detector.lastType != g_detector.type) {
detectorUpdate(&g_detector);
g_detector.lastType = g_detector.type;
}
}
++g_detector.tick;
}
/**---------------------------------------------------------------------
* Function : mag_calibration
* Description :
* Date : 2020/09/02 logzhan
*---------------------------------------------------------------------**/
void mag_calibration(IMU *imu)
{
if (DETECTOR_TYPE_SWINGING == g_detector.type && CALIBRATE_OFF == mag_calibrate)
{
mag_buff[mag_count][0] = imu->mag[0];
mag_buff[mag_count][1] = imu->mag[1];
mag_buff[mag_count][2] = imu->mag[2];
mag_count++;
}
else{
mag_count = 0;
}
if (MAG_BUF_LEN == mag_count && CALIBRATE_OFF == mag_calibrate)
{
/*处理代码(模拟退火)start*/
float xmin = 0.0f;
float ymin = 0.0f;
float zmin = 0.0f;
float xmax = 0.0f;
float ymax = 0.0f;
float zmax = 0.0f;
float err_ori = 0.0;
float r[6] = { 0 };
float mag_buff_T[3][MAG_BUF_LEN] = { { 0 } };
mag_m_trans(mag_buff, mag_buff_T);
mag_min(mag_buff_T[0], &xmin);
mag_min(mag_buff_T[1], &ymin);
mag_min(mag_buff_T[2], &zmin);
mag_max(mag_buff_T[0], &xmax);
mag_max(mag_buff_T[1], &ymax);
mag_max(mag_buff_T[2], &zmax);
float xc = 0.5f*(xmax + xmin);
float yc = 0.5f*(ymax + ymin);
float zc = 0.5f*(zmax + zmin);
float a = 0.5f* (float)fabs(xmax - xmin);
float b = 0.5f* (float)fabs(ymax - ymin);
float c = 0.5f* (float)fabs(zmax - zmin);
for (int i = 0; i < MAG_BUF_LEN; i++)
{
err_ori = err_ori + (float)fabs((mag_buff[i][0] - xc)*(mag_buff[i][0] - xc) / a / a + \
(mag_buff[i][1] - yc)*(mag_buff[i][1] - yc) / b / b + \
(mag_buff[i][2] - zc)*(mag_buff[i][2] - zc) / c / c - 1);
}
float xclast = xc;
float yclast = yc;
float zclast = zc;
float alast = a;
float blast = b;
float clast = c;
float err_last = err_ori;
float xcnew = 0;
float ycnew = 0;
float zcnew = 0;
float anew = 0;
float bnew = 0;
float cnew = 0;
float err_new = 0;
for (int i = 0; i < 1000; i++)
{
mag_rand(r);
xcnew = xclast + r[0] - 0.5f;
ycnew = yclast + r[1] - 0.5f;
zcnew = zclast + r[2] - 0.5f;
anew = (float)fabs(alast + r[3] - 0.5);
bnew = (float)fabs(blast + r[4] - 0.5);
cnew = (float)fabs(clast + r[5] - 0.5);
err_new = 0;
for (int j = 0; j < MAG_BUF_LEN; j++)
{
err_new = err_new + (float)fabs((mag_buff[j][0] - xcnew)*(mag_buff[j][0] - xcnew) / anew / anew + \
(mag_buff[j][1] - ycnew)*(mag_buff[j][1] - ycnew) / bnew / bnew + \
(mag_buff[j][2] - zcnew)*(mag_buff[j][2] - zcnew) / cnew / cnew - 1);
}
if (err_new < err_ori){
xclast = xcnew;
yclast = ycnew;
zclast = zcnew;
alast = anew;
blast = bnew;
clast = cnew;
err_last = err_new;
}
}
float err_0 = 0.0;
for (int j = 0; j < MAG_BUF_LEN; j++)
{
err_0 = err_0 + (float)fabs((mag_buff[j][0])*(mag_buff[j][0]) + (mag_buff[j][1])*(mag_buff[j][1]) + (mag_buff[j][2])*(mag_buff[j][2]) - 1);
}
/*处理代码(模拟退火)end*/
if (err_0 > err_last)
{
ellipsoidPoint[0] = xclast;
ellipsoidPoint[1] = yclast;
ellipsoidPoint[2] = zclast;
ellipsoidScale[0] = alast;
ellipsoidScale[1] = blast;
ellipsoidScale[2] = clast;
mag_calibrate = CALIBRATE_ON;
}
else
{
ellipsoidPoint[0] = 0;
ellipsoidPoint[1] = 0;
ellipsoidPoint[2] = 0;
ellipsoidScale[0] = 1;
ellipsoidScale[1] = 1;
ellipsoidScale[2] = 1;
}
mag_count = 0;
memset(*mag_buff, 0, sizeof(mag_buff));
}
ellipsoidPoint[0] = 0;
ellipsoidPoint[1] = 0;
ellipsoidPoint[2] = 0;
ellipsoidScale[0] = 1;
ellipsoidScale[1] = 1;
ellipsoidScale[2] = 1;
imu->mag[0] = (imu->mag[0] - ellipsoidPoint[0]) * ellipsoidScale[0];
imu->mag[1] = (imu->mag[1] - ellipsoidPoint[1]) * ellipsoidScale[1];
imu->mag[2] = (imu->mag[2] - ellipsoidPoint[2]) * ellipsoidScale[2];
}
/**---------------------------------------------------------------------
* Function : mag_rand
* Description : 0-1
* Date : 2020/09/02 logzhan
*---------------------------------------------------------------------**/
void mag_rand(float r[6]){
float temp[6] = { 0.0 };
srand((unsigned)time(NULL)); //读取系统时间,产生一个种子数值
for (int i = 0; i < 6; i++)
{
temp[i] = rand() / (RAND_MAX + 1.0f);
}
for (int i = 0; i < 6; i++)
{
r[i] = temp[i];
}
}
/**---------------------------------------------------------------------
* Function : mag_min
* Description :
* Date : 2020/09/02 logzhan
*---------------------------------------------------------------------**/
void mag_min(float a[MAG_BUF_LEN],float *mag_min){
float temp;
temp = a[0];
for (int i = 1; i < MAG_BUF_LEN; i++)
{
if (a[i] < temp)
temp = a[i];
}
*mag_min = temp;
}
/**---------------------------------------------------------------------
* Function : mag_max
* Description :
* Date : 2020/09/02 logzhan
*---------------------------------------------------------------------**/
void mag_max(float a[MAG_BUF_LEN], float *mag_max){
float temp;
temp = a[0];
for (int i = 1; i < MAG_BUF_LEN; i++)
{
if (a[i] > temp)
temp = a[i];
}
*mag_max = temp;
}
/**---------------------------------------------------------------------
* Function : mag_m_trans
* Description :
* Date : 2020/09/02 logzhan
*---------------------------------------------------------------------**/
void mag_m_trans(float a[MAG_BUF_LEN][3], float r[3][MAG_BUF_LEN]) {
int i, j;
for (i = 0; i < 3; i++) {
for (j = 0; j < MAG_BUF_LEN; j++) {
r[i][j] = a[j][i];
}
}
}
/**---------------------------------------------------------------------
* Function : fft_buffer
* Description : accfft
* Date : 2020/7/20 logzhan
*---------------------------------------------------------------------**/
static int fft_buffer(myComplex *fft, BUFFER *buffer) {
static float s_signal[1024] = { 0 };
float mean;
int index;
int i;
Buffer_mean(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, myComplex *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;
Buffer_count((BUFFER *)dst, &dst_cnt);
Buffer_count((BUFFER *)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])) {
buffer_push((BUFFER *)&frequency_buffer[i], 0);
buffer_push((BUFFER *)&amplitude_buffer[i], 0);
}
else {
buffer_push((BUFFER *)&frequency_buffer[i], frequency[assignment[i]]);
buffer_push((BUFFER *)&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) {
buffer_push((BUFFER *)&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;
Buffer_mean((BUFFER *)&g_mol_buf[ACCE], &feature[0]);
Buffer_std( (BUFFER *)&g_mol_buf[ACCE], &feature[1]);
Buffer_std( (BUFFER *)&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 : pdr_motionTypeDetect
* Description : pdr
* Date : 2020/7/20 logzhan
*---------------------------------------------------------------------**/
int pdr_motionTypeDetect() {
static myComplex 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 *)&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 *)&g_mol_buf[GYRO]))) {
return ret;
}
if (DETECTOR_NO_ERROR != (ret = find_peaks(frq, amp, 3, s_fft, 1024, 5, (DETECTOR_TYPE_SWINGING == g_detector.type ||
DETECTOR_TYPE_HANDHELD == g_detector.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);
g_detector.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] = g_detector.type;
g_detector.type = debounce(g_label, ARR_LEN(g_label));
return DETECTOR_NO_ERROR;
}

View File

@ -1,180 +0,0 @@
/*****************************************************************
*Module Name: filter
*Module Date: 2018.10.24
*Module Auth: chelimin11070377
*****************************************************************/
/* Header File Including ------------------------------------------------------------------------ */
#include "stdio.h"
#include "Filter.h"
/* Function Definition -------------------------------------------------------------------------- */
/*****************************************************************
*Description: reset filter
*Input : *f filter
*Output: none
*Return: none
*****************************************************************/
void FILTER_reset(FILTER *f) {
f->reset = 1;
}
/*****************************************************************
*Description: reset fir filter
*Input : *f fir filter
*Output: none
*Return: none
*****************************************************************/
void FILTER_FIR_reset(FILTER_FIR *f) {
f->reset = 1;
}
/*****************************************************************
*Description: set filter coefficient
*Input : order coefficient array length, not filter order
* *b b coefficient
* *a a coefficient
* H0 dc signal gain
*Output: *f filter
*Return: none
*****************************************************************/
void FILTER_setCoef(FILTER *f, int order, double *b, double *a, double H0) {
int i;
for (i = 0; i < order; ++i) {
f->b[i] = b[i];
f->a[i] = a[i];
}
f->order = order;
f->H0 = H0;
f->reset = 1;
}
/*****************************************************************
*Description: set fir filter coefficient
*Input : order coefficient array length, not filter order
* *b b coefficient
* *a a coefficient
* H0 dc signal gain
*Output: *f fir filter
*Return: none
*****************************************************************/
void FILTER_FIR_setCoef(FILTER_FIR *f, int order, double *b, double H0) {
int i;
for (i = 0; i < order; ++i) {
f->b[i] = b[i];
}
f->order = order;
f->H0 = H0;
f->reset = 1;
}
/*****************************************************************
*Description: filter x signal
*Input : *f filter
* x signal
*Output: none
*Return: filter result
*****************************************************************/
double FILTER_filter(FILTER *f, double x) {
int i;
double y;
if (f->order < 1) {
printf("fileter order is set to incorrect order, pls chk \
your code!\n");
return 0;
}
if (f->reset) {
for (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 (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 (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;
}
/*****************************************************************
*Description: filter x signal
*Input : *f fir filter
* x signal
*Output: none
*Return: filter result
*****************************************************************/
double FILTER_FIR_filter(FILTER_FIR *f, double x) {
int i;
double y;
if (f->order < 1) {
printf("fileter order is set to incorrect order, pls chk \
your code!\n");
return 0;
}
if (f->reset) {
for (i = 0; i < f->order; ++i) {
f->xin[i] = x;
}
f->reset = 0;
}
// push x
for (i = 0; i < f->order - 1; ++i) {
f->xin[i] = f->xin[i + 1];
}
f->xin[f->order - 1] = x;
// filter
y = f->b[0] * f->xin[f->order - 1];
for (i = 1; i < f->order; ++i) {
y += f->b[i] * f->xin[f->order - 1 - i];
}
return y / f->H0;
}
void DELAY_reset(DELAYER *d) {
d->reset = 1;
}
void DELAY_setCoef(DELAYER *d, int delay) {
d->delay = delay;
d->reset = 1;
}
double DELAY_delay(DELAYER *d, double x) {
double yout = d->xin[0];
int i;
if (d->reset) {
for (i = 0; i < d->delay; ++i) {
d->xin[i] = x;
}
yout = x;
d->reset = 0;
}
else {
for (i = 0; i < d->delay - 1; ++i) {
d->xin[i] = d->xin[i + 1];
}
d->xin[d->delay - 1] = x;
}
return yout;
}

View File

@ -1,890 +0,0 @@
/******************** (C) COPYRIGHT 2020 Geek************************************
* File Name : pdr_kalman.c
* Current Version : V2.0(compare QCOM SAP 5.0)
* Author : logzhan
* Date of Issued : 2020.7.3
* Comments : PDR
********************************************************************************/
#include <stdio.h>
#include <string.h>
#include <math.h>
#if !defined(LOCATION_PLATFORM_QCOM_MODEM)
#include <malloc.h>
#endif
#include "pdr_base.h"
#include "pdr_kalman.h"
#include "pdr_location.h"
#include "pdr_matrix.h"
#include "pdr_util.h"
#include "pdr_linearFit.h"
#if USE_BUG_FOR_LOCAL_PARA
static double Ekf_Upd_buf_2d[5][N] = { {0.0} };
static double Ekf_Upd_buf_3d[7][N][N] = { { {0.0} } };
#endif
extern double GpsPos[HIST_GPS_NUM][3];
extern int debugCount;
extern double angle_mean[3];
static int hold_type;
static double b_timestamp;
static double b_last_time;
static double attitude_yaw;
static DETECTOR *g_detector;
static int hold_type;
static double BUL_duration;
static double FUR_duration;
/**----------------------------------------------------------------------
* Function : pdr_initKalman
* Description :
* Date : 2020/8/27 logzhan
*---------------------------------------------------------------------**/
void pdr_initKalman(void)
{
b_timestamp = -1;
b_last_time = -1;
BUL_duration = -1;
FUR_duration = -1;
attitude_yaw = -1;
hold_type = 0;
}
int clear_buf(double *buf_p, int dmt)
{
int bufLen = 0;
double *buf_pdr = (double *)buf_p;
if (NULL == buf_p)return -1;
if (!(2 == dmt || 1 == dmt)){
return -1;
}
else if (2 == dmt)bufLen = N * N;
else if (1 == dmt)bufLen = N;
for (int i = 0; i < bufLen; i++){
buf_pdr[i] = 0.0f;
}
return 0;
}
/**----------------------------------------------------------------------
* Function : pdr_ekfStatePredict
* Description : pdr
* Date : 2020/7/22 logzhan
*---------------------------------------------------------------------**/
void pdr_ekfStatePredict(KfPara *kf, double stepLen, PDR* g_pdr, int step) {
double (*phi)[N] = (double(*)[N])&(Ekf_Upd_buf_3d[0][0][0]);
double (*pvec1)[N] = (double(*)[N])&(Ekf_Upd_buf_3d[1][0][0]);
double (*pvec2)[N] = (double(*)[N])&(Ekf_Upd_buf_3d[2][0][0]);
clear_buf((double *)phi, BUF_DMT_1);
clear_buf((double *)pvec1, BUF_DMT_1);
clear_buf((double *)pvec2, BUF_DMT_1);
double deltaHeading = g_pdr->heading - g_pdr->lastHeading;
double angle = g_pdr->heading;
//printf("deltaHeading = %f\n", R2D(deltaHeading));
//if (fabs(deltaHeading) < D2R(10) && g_pdr->lastHeading != 0.0f) {
// angle = deltaHeading + kf->p_xk[3];
//}else {
// angle = g_pdr->heading;
//}
if (g_pdr->motionType != PDR_MOTION_TYPE_HANDHELD) {
deltaHeading = 0;
}
angle = deltaHeading + kf->p_xk[3];
if (fabs(deltaHeading) > 5.5) {
//printf("%f %f\n", R2D(g_pdr->heading), R2D(g_pdr->lastHeading));
//printf("d heading = %f\n", R2D(deltaHeading));
if (deltaHeading < 0) {
deltaHeading = deltaHeading + D2R(360);
}else {
deltaHeading = deltaHeading - D2R(360);
}
deltaHeading = 0;
angle = deltaHeading + kf->p_xk[3];
}
if(step == 0){
kf->p_xk[3] = angle;
}
// 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(kf->p_xk[3]) > 0.000001 &&
fabs(angle / kf->p_xk[3]) < 3)
{
phi[3][3] = angle / kf->p_xk[3];
}
// 卡尔曼状态更新方程
// p_xk = phi * p_xk
VecMatMultiply(kf->p_xk, phi, kf->p_xk);
// 卡尔曼更新协方差矩阵 : Pk = FPFt + Q
MatrixMultiply(phi, kf->p_pk, pvec1); // F*P
MatrixTrans(phi, pvec2); // Ft
MatrixMultiply(pvec1, pvec2, pvec1); // F*P*Ft
MatrixAdd(pvec1, kf->q, kf->p_pk); // F*P*Ft + Q
}
}
/**----------------------------------------------------------------------
* Function : pdr_ekfStateUpdate
* Description : pdr
* Date : 2020/7/22 logzhan
*---------------------------------------------------------------------**/
void pdr_ekfStateUpdate(KfPara *kf, gnss *pgnss, classifer *sys, PDR *g_pdr,
int scene_type) {
int j;
double(*H)[N] = (double(*)[N])&(Ekf_Upd_buf_3d[0][0][0]);
double *z = &(Ekf_Upd_buf_2d[0][0]);
double(*I)[N] = (double(*)[N])&(Ekf_Upd_buf_3d[1][0][0]);
double(*pvec1)[N] = (double(*)[N])&(Ekf_Upd_buf_3d[2][0][0]);
double(*Ht)[N] = (double(*)[N])&(Ekf_Upd_buf_3d[3][0][0]);
double(*pvec3)[N] = (double(*)[N])&(Ekf_Upd_buf_3d[4][0][0]);
double(*pvec4)[N] = (double(*)[N])&(Ekf_Upd_buf_3d[5][0][0]);
double(*pvec5) = &(Ekf_Upd_buf_2d[1][0]);
double(*pvec6) = &(Ekf_Upd_buf_2d[2][0]);
double lambda = 0;
double(*pv1) = &(Ekf_Upd_buf_2d[3][0]);
double(*pv2) = &(Ekf_Upd_buf_2d[4][0]);
double(*pv3)[N] = (double(*)[N])&(Ekf_Upd_buf_3d[6][0][0]);
clear_buf((double *)z, BUF_DMT_1);
clear_buf((double *)pvec5, BUF_DMT_1);
clear_buf((double *)pvec6, BUF_DMT_1);
clear_buf((double *)pv1, BUF_DMT_1);
clear_buf((double *)pv2, BUF_DMT_1);
clear_buf((double *)H, BUF_DMT_2);
clear_buf((double *)I, BUF_DMT_2);
clear_buf((double *)pvec1, BUF_DMT_2);
clear_buf((double *)Ht, BUF_DMT_2);
clear_buf((double *)pvec3, BUF_DMT_2);
clear_buf((double *)pvec4, BUF_DMT_2);
clear_buf((double *)pv3, BUF_DMT_2);
for (char i = 0; i < 4; i++) {
H[i][i] = 1;
I[i][i] = 1;
}
// 获取观测向量
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->p_xk[2];
//}
z[3] = pgnss->yaw * PI / 180; // 观测的航向角为GPS的航向角
// 计算 K = K = PHt / (R + H*P*H^T)
MatrixTrans(H, Ht); // 计算Ht
MatrixMultiply(H, kf->p_pk, 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->p_pk, Ht, pvec3); // 计算PHt
MatrixMultiply(pvec3, pvec1, kf->Kk); // 计算增益K = PHt / (R + H*P*H^T)
VecMatMultiply(kf->p_xk, 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->p_xk, 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->p_pk, 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->p_xk[i];
for (j = 0; j < N; j++) {
kf->pk[i][j] = kf->p_pk[i][j];
}
}
}
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;
}
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;
}
/**----------------------------------------------------------------------
* Function : stateRecognition
* Description : 1: 0:
* Date : 2020/7/22 logzhan
*---------------------------------------------------------------------**/
void stateRecognition(float *acc, classifer *sys) {
int i,j,k;
float accNorm = 0;
float sum = 0, max_min = 0, max = -1, min = 999;
float mean = 0, std = 0;
// 先计算当前加速度的模
accNorm = (float)sqrt(vivopow(acc[0], 2) + vivopow(acc[1], 2) + vivopow(acc[2], 2));
// 缓存更新
for (i = 0; i < PATTERN_RECOGNITION_LEN - 1; i++) {
sys->accBuffer[i] = sys->accBuffer[i + 1];
}
sys->accBuffer[PATTERN_RECOGNITION_LEN - 1] = accNorm;
// 计算最大最小值和sum
for (j = 0; j < PATTERN_RECOGNITION_LEN - 1; j++) {
sum += sys->accBuffer[j];
if (sys->accBuffer[j] > max) {
max = sys->accBuffer[j];
}
if (sys->accBuffer[j] < min) {
min = sys->accBuffer[j];
}
}
// 计算均值
mean = sum / PATTERN_RECOGNITION_LEN;
// 计算方差
for (k = 0; k < PATTERN_RECOGNITION_LEN - 1; k++) {
std += (sys->accBuffer[k] - mean) * (sys->accBuffer[k] - mean) / PATTERN_RECOGNITION_LEN;
}
std = (float)sqrt(std);
// 计算最大最小差值
max_min = max - min;
if (std > 5 && max_min > 25) {
sys->type = 1;
}
else {
sys->type = 0;
}
}
/**----------------------------------------------------------------------
* Function : calPredAngle
* Description : pdr->cal_directiongps_yawangle
* Date : 2020/7/22 logzhan
*---------------------------------------------------------------------**/
double calPredAngle(PDR *g_pdr, classifer *sys, double gpsYaw, double trackYaw, imu *ss_data) {
int attitude_flag = PDR_FALSE;
g_detector = pdr_getDetector();
/*姿态角YAW辅助计算start*/
if (DETECTOR_TYPE_HANDHELD == g_detector->type)
{
b_timestamp = ss_data->gyr.time;
if (!(angle_mean[0] == 0 && angle_mean[1] == 0 && angle_mean[2] == 0))
{
if (b_last_time > 0 && b_timestamp - b_last_time >= 5000 && gpsYaw != 0.0 && gpsYaw != -1 && trackYaw != -1)
{
/* 将姿态yaw角调整到0到2*PI */
/*左臂包,头朝上,屏朝外 or 右臂包,头朝上,屏朝内*/
if (ss_data->acc.s[1] > 9 && (fabs(angle_mean[2] + 6.15 - gpsYaw) < PI / 18 && fabs(angle_mean[2] + 6.15 - trackYaw) < PI / 18))
{
FUR_duration = -1;
if (BUL_duration < 0)
{
BUL_duration = ss_data->gyr.time;
}
if (BUL_duration >= 0 && (b_timestamp - BUL_duration) >= 1500)
{
attitude_yaw = angle_mean[2] + 6.15 + PI;
attitude_flag = PDR_TRUE;
hold_type = BACKWARD_UP_LEFT;
}
}
/*右臂包,头朝上,屏朝外 or 左臂包,头朝上,屏朝内*/
if (ss_data->acc.s[1] > 9 && (fabs(angle_mean[2] + 7.10 - gpsYaw) < PI / 18 && fabs(angle_mean[2] + 7.10 - trackYaw) < PI / 18))
{
BUL_duration = -1;
if (FUR_duration < 0)
{
FUR_duration = ss_data->gyr.time;
}
if (FUR_duration >= 0 && (b_timestamp - FUR_duration) >= 1500)
{
attitude_yaw = angle_mean[2] + 7.10;
attitude_flag = PDR_TRUE;
hold_type = FORWARD_UP_RIGHT;
}
}
}
if (-1 == b_last_time)
{
b_last_time = b_timestamp;
}
}
}
else{
b_last_time = -1;
FUR_duration = -1;
BUL_duration = -1;
}
/*姿态角YAW辅助计算end*/
double angle = -1;
double ahrsYaw = atan2(g_pdr->cal_direction[1], g_pdr->cal_direction[0]);
//printf("PCA Yaw = %f\n", ahrsYaw * (180 / 3.1415926));
if (ahrsYaw < 0) {
ahrsYaw += TWO_PI;
}
// 评估PCA计算方向角的准确性
if ((g_pdr->bias_accuracy > 0 && g_pdr->bias_accuracy < 0.9) && (g_pdr->pca_accuracy > 0 && g_pdr->pca_accuracy < 0.25)) {
angle = ahrsYaw;
//printf("PCA准确性满足条件, angle = ahrsYaw %f\n", ahrsYaw * (180 / 3.1415926));
}
if (gpsYaw != 0.0 && gpsYaw != -1 ) //&& scene_type
{
// Status -- Explosion
if (fabs(ss_data->acc.s[0]) > 70 || fabs(ss_data->acc.s[1]) > 70 || fabs(ss_data->acc.s[2]) > 70 || fabs(ss_data->gyr.s[0]) > 30 || fabs(ss_data->gyr.s[1]) > 30 || fabs(ss_data->gyr.s[2]) > 30) {
angle = gpsYaw;
//printf("Explosion, angle = gpsYaw = %f\n", gps_yaw * (180 / 3.1415926));
}
// Status -- Running
if (g_pdr->motionFreq > 2.7 || (g_pdr->motionType != 3 && g_pdr->motionType != 2) || (sys->type == 1)) { //&& g_pdr->motion_type != 2
angle = gpsYaw;
//printf("Running, angle = gpsYaw = %f\n", gps_yaw * (180 / 3.1415926));
}
}
if (trackYaw != -1 && ((g_pdr->bias_accuracy < 0 || g_pdr->bias_accuracy > 0.05) || (g_pdr->pca_accuracy < 0 || g_pdr->pca_accuracy > 0.05))) {
angle = trackYaw;//gps_yaw: obtained from the datasheet; G_yaw : calculated from the route
if (attitude_flag == PDR_TRUE)
{
angle = attitude_yaw;
}
}
if (angle < 0)
{
if (g_pdr->bias_accuracy > 0 && g_pdr->pca_accuracy > 0 && (g_pdr->bias_accuracy < 1.5 && g_pdr->pca_accuracy < 0.5))//g_pdr->bias_accuracy < 6
{
angle = ahrsYaw;
}
else if (attitude_flag == PDR_TRUE)
{
angle = attitude_yaw;
}
else if (gpsYaw != 0.0 && gpsYaw != -1)
{
angle = gpsYaw;
}
else //if (lastYaw > 0)
{
angle = -1; //lastYaw;
}
}
return angle;
}
double calGnssTrackHeading(double gpsPos[][3], gnss 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];
}
if ((lla[0] > 0) && (lla[1] > 0))
{
//经纬度WGS84转地心地固坐标系ECEF
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)(vivopow(para[0] * temp[0][i] + para[1] * temp[1][i] + para[2], 2) / (vivopow(para[0], 2) + vivopow(para[1], 2)));
sst += (float)(vivopow(meanx - temp[0][i], 2) + vivopow(meany - temp[1][i], 2));
}
if (sst > 0)
{
r2 = 1 - error / sst;
}
range = sqrt(vivopow(maxn - minn, 2) + vivopow(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 : pdr_insPredict
* Description : PDR,
* Date : 2020/07/08 logzhan
* 2021/02/06 logzhan :
* PDR
*---------------------------------------------------------------------**/
void pdr_insPredict(PDR *g_pdr, StepPredict *stepPredict, imu *ss_data,
gnss *pgnss, KfPara *kf) {
int step;
long deltaStep;
double stepLength = 0.7;
stepPredict->fnum++;
stepPredict->fsum += g_pdr->motionFreq;
ulong steps = g_pdr->steps;
ulong lastSteps = g_pdr->lastSteps;
if (steps - lastSteps > 0 && g_pdr->motionFreq != 0.0) {
deltaStep = steps - lastSteps - stepPredict->deltaStep;
// 应该是防止计步器异常情况,一次计步特别多
if (deltaStep > 5)deltaStep = 5;
if (stepPredict->meanTime > 0)
{
step = (int)((ss_data->gyr.time - stepPredict->lastTime) / stepPredict->meanTime + 0.5);
if (step > deltaStep && step <= 3)deltaStep = step;
}
if (lastSteps == 0)deltaStep = 0;
if (g_pdr->heading > 0) {
pdr_ekfStatePredict(kf, stepLength, g_pdr, deltaStep);
g_pdr->fusionPdrFlg = PDR_TRUE;
}
calStepLastTime(stepPredict, ss_data->gyr.time, lastSteps, steps);
}else{
// 有时候计步器可能考虑到稳定性暂时不更新步数因此需要利用GNSS速度预测步数达到
// 惯导更新位置的目的
int preStep = predictStep(stepPredict, ss_data->gyr.time, lastSteps, pgnss->vel);
if (g_pdr->heading > 0){
pdr_ekfStatePredict(kf, stepLength, g_pdr, preStep);
if(preStep > 0)g_pdr->fusionPdrFlg = PDR_TRUE;
}
}
}
/**----------------------------------------------------------------------
* Function : resetOutputResult
* Description : 1
* 2GPSresult
* Date : 2020/07/08 logzhan
*---------------------------------------------------------------------**/
int resetOutputResult(gnss *pgnss, PDR* g_pdr, KfPara *kf, lct_fs *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->p_xk[0] = ned[0];
kf->p_xk[1] = ned[1];
kf->p_xk[2] = stepLength;
// 重置输出GPS时GPS的航向角不一定准
kf->p_xk[3] = pgnss->yaw*RADIAN_PER_DEG;
for (uchar i = 0; i < N; i++) {
kf->xk[i] = kf->p_xk[i];
}
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;
}
}
//printf("重置PDR滤波器输出GPS位置\n");
// 输出GPS位置结果
pdr_outputGpsPos(pgnss, result);
g_pdr->noGpsCount = 0;
return PDR_TRUE;
}
int pdr_initProc(gnss *pgnss, KfPara *kf, PDR* g_pdr,lct_fs *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->p_xk[0] = ned[0]; // 状态量1: 北向x
kf->p_xk[1] = ned[1]; // 状态量2东向y
kf->p_xk[2] = stepLen; // 状态量3步长
kf->p_xk[3] = pgnss->yaw * RADIAN_PER_DEG; // 状态量4航向角
for (uchar i = 0; i < N; i++) {
kf->xk[i] = kf->p_xk[i];
}
kf->initHeading = kf->p_xk[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;
}
}
pdr_outputGpsPos(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) {
pdr_outputGpsPos(pgnss, result);
return PDR_TRUE;
}
return PDR_FALSE;
}
/**----------------------------------------------------------------------
* Function : calEkfQRMatrix
* Description : GPSq
* rGNSSGPS
*
* Date : 2020/07/09 logzhan
*---------------------------------------------------------------------**/
void calEkfQRMatrix(lct_nmea *nmea, PDR *g_pdr, classifer *sys,
KfPara *kf) {
if (g_pdr->motionType != PDR_MOTION_TYPE_HANDHELD &&
g_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((g_pdr->gpsHeading - g_pdr->lastGpsHeading))) > 50 ||
g_pdr->gpsSpeed < 0.7 || g_pdr->gpsHeading == -1) {
kf->r[3][3] = 10000;
}
}
/**----------------------------------------------------------------------
* Function : pdr_gnssInsLocFusion
* Description : PDRGNSSINS
* Date : 2020/07/09 logzhan
*---------------------------------------------------------------------**/
void pdr_gnssInsLocFusion(gnss *pgnss, PDR *g_pdr, classifer *sys, double yaw_bias,
KfPara *kf, lct_fs *res) {
double plla[3] = { 0 };
double ned[3] = { 0 };
double yaw_thr = 6;
int scene_type = g_pdr->sceneType;
plla[0] = pgnss->lat;
plla[1] = pgnss->lon;
plla[2] = 0;
wgs842Ned(plla, g_pdr->pllaInit, ned);
pgnss->xNed = ned[0];
pgnss->yNed = ned[1];
//调整融合策略
pdr_ekfStateUpdate(kf, pgnss, sys, g_pdr, scene_type);
for (uchar i = 0; i < N; i++) {
for (uchar l = 0; l < N; l++) {
kf->p_pk[i][l] = kf->pk[i][l];
}
kf->p_xk[i] = kf->xk[i];
}
ned[0] = kf -> p_xk[0] - g_pdr->x0;
ned[1] = kf -> p_xk[1] - g_pdr->y0;
ned[2] = 0;
ned2Wgs84(g_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;
g_pdr->noGpsCount = 0;
}

View File

@ -1,149 +0,0 @@
/******************** (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 "pdr_linearFit.h"
#include "pdr_util.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

@ -1,402 +0,0 @@
/******************** (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 "pdr_location.h"
#include "pdr_kalman.h"
#include "steps.h"
#include "pdr_ahrs.h"
#include "pdr_detector.h"
#include "pdr_util.h"
#include "scene_recognition.h"
/* Global Variable Definition ------------------------------------------------*/
PDR* pdr; // PDR全局信息
StepPredict stepPredict = { 0 };
classifer sys;
gnss pgnss; // 定位相关信息
KfPara g_kfPara;
double GpsPos[HIST_GPS_NUM][3] = {{0}};
static uint32_t g_status;
extern AHRS g_ahrs;
double refGpsYaw = -1000;
double yaw_bias = -1;
float dir[2] = { 0 };
float bias_dir[2] = { 0 };
/**---------------------------------------------------------------------
* Function : pdr_navSysInit
* Description : PDR
* Date : 2020/2/1 logzhan
*---------------------------------------------------------------------**/
void NavSys_Init(void) {
memset(&g_kfPara, 0, sizeof(g_kfPara));
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定位初始化
pdr_initGnssInfo();
// 初始化AHRS姿态解算相关
pdr_initAhrs();
// 检测器初始化
pdr_initDetector();
// PDR初始化
pdr = pdr_initBase();
//base文件中姿态角计算初始化
pdr_initKalman();
// 场景识别模块初始化
initSceneRecognition();
yaw_bias = -1;
}
/**---------------------------------------------------------------------
* Function : pdr_initGnssInfo
* Description : PDS GNSS
* Date : 2020/02/01 logzhan:
*
* 2020/02/08: logzhan initGpsinitGnssInfo
*
*---------------------------------------------------------------------**/
void pdr_initGnssInfo(void) {
pgnss.lastError = ACCURACY_ERR_MAX;
pgnss.overVelCount = 0;
}
/**---------------------------------------------------------------------
* Function : pdr_resetSysStatus
* Description : PDR
* Date : 2020/2/1 logzhan
*---------------------------------------------------------------------**/
void pdr_resetSysStatus(KfPara *kf)
{
memset(kf, 0, sizeof(KfPara));
pdr->fusionPdrFlg = PDR_FALSE;
pdr->sysStatus = IS_INITIAL;
pgnss.overVelCount = 0;
}
/**---------------------------------------------------------------------
* Function : pdr_insLocation
* Description : PDR
* Date : 2020/2/1 logzhan
*---------------------------------------------------------------------**/
int pdr_insLocation(imu* ss_data, KfPara* kf) {
// AHRS姿态更新占2%的运行时间
if (pdr_imuUpdateAhrs(ss_data)) {
// 完成姿态估计后计算PCA 占26%的运行时间
pdr_computePCA(&g_ahrs);
}
// 更新用户运动类型检测器IMU信息以及用户运动类型检测, 占21%的运行时间
updateDetectorImu(ss_data);
pdr->gyroTime = ss_data->gyr.time;
// 为什么手持类型是0.1的运动频率?
if (pdr->motionType == DETECTOR_TYPE_HANDHELD)pdr->motionFreq = 0.1f;
// 计步器输入传感器数据占10%的运行时间
updatePedometer(ss_data, &pdr->steps);
// ----- Filter Initialization ------- //
if (pdr->sysStatus == IS_INITIAL) {
pdr->ts = ss_data->gyr.time;
pdr->lastSteps = pdr->steps;
stepPredict.lastTime = 0;
stepPredict.fnum = 0;
stepPredict.fsum = 0;
return 0;
}
pdr->ts = ss_data->gyr.time;
if ((0 == ss_data->acc.s[0] && 0 == ss_data->acc.s[1] && 0 == ss_data->acc.s[2]) ||
(0 == ss_data->mag.s[0] && 0 == ss_data->mag.s[1] && 0 == ss_data->mag.s[2])) {
return 0;
}
// 识别当前状态是否平稳这个函数计算量到达整个系统10%的计算量, 以后根据情况进行优化
// stateRecognition(ss_data->acc.s, &sys);
pdr->heading = calPredAngle(pdr, &sys, pdr->gpsHeading, pdr->trackHeading, ss_data);
if (yaw_bias != -1) {
if (pdr->pca_accuracy > 0 && pdr->pca_accuracy < 0.1 && pdr->motionType == 3 &&
(pdr->bias_accuracy > 1.5 || pdr->bias_accuracy == -1 || pgnss.error > 30)
&& (fabs(yaw_bias - 2 * PI) < YAW_THRES * PI / 180 || fabs(yaw_bias - PI) < YAW_THRES * PI / 180 ||
fabs(yaw_bias) < YAW_THRES * PI / 180)) {
dir[0] = pdr->pca_direction[0] * bias_dir[0] + pdr->pca_direction[1] * bias_dir[1];
dir[1] = pdr->pca_direction[1] * bias_dir[0] - pdr->pca_direction[0] * bias_dir[1];
pdr->heading = atan2(dir[1], dir[0]);
if (pdr->heading < 0) {
pdr->heading += TWO_PI;
}
}
}
double imuYaw = - g_ahrs.yaw;
if (imuYaw < 0) {
imuYaw += 360;
}
pdr->heading = imuYaw / (180 / 3.14159265);
if (fabs(pdr->insHeadingOffset) > 0.000001) {
imuYaw = imuYaw - pdr->insHeadingOffset * (180 / 3.14159265);
pdr->heading = imuYaw / (180 / 3.14159265);
}
// PDR 惯性位置预测
pdr_insPredict(pdr, &stepPredict, ss_data, &pgnss, kf);
pdr->lastSteps = pdr->steps;
pdr->lastHeading = pdr->heading;
return 0;
}
/**----------------------------------------------------------------------
* Function : pdr_gnssInsLocation
* Description : PDR GPSINS
* Date : 2021/01/29 logzhan
*---------------------------------------------------------------------**/
int pdr_gnssInsLocation(lct_nmea *nmea_data, KfPara *kf, lct_fs *result)
{
// GPS数据更新
pdr_gnssUpdate(&pgnss, nmea_data);
// 检查时间差是否满足条件
if (fabs(pgnss.timestamps - pdr->ts) >= 1000)return TYPE_FIX_NONE;
// 根据nmea数据识别场景是否是开阔天空场景
pdr->sceneType = isOpenArea(nmea_data);
// 根据HDOP、速度、卫星数量等判断gps yaw是否可用
pdr->gpsSpeed = pgnss.vel * GPS_SPEED_UNIT;
pdr->lastGpsHeading = pdr->gpsHeading;
pdr->gpsHeading = pdr_getGpsHeading(&pgnss);
// 如果在win32平台下仿真调试,则添加下面代码
#ifdef _WIN32
result->pdrHeading = kf->p_xk[3];
result->gpsHeading = pdr->gpsHeading;
result->hdop = pgnss.HDOP;
result->accuracy = nmea_data->accuracy.err;
result->gpsSpeed = pdr->gpsSpeed;
result->motionType = pdr->motionType;
// printf("utc time = %f\n", nmea_data->gga.gga_utc);
#endif
calPdrHeadingOffset(nmea_data, pdr);
// 计算两次GPS时间之间步数变化量
pdr->deltaStepsPerGps = pdr->steps - pdr->lastGpsSteps;
pdr->lastGpsSteps = pdr->steps;
int mode = pdr_detectFixMode(&pgnss, kf, pdr, result);
if (mode != TYPE_FIX_PDR)return mode;
//根据历史GPS拟合输出预估的GPS轨迹航向角
pdr->trackHeading = calGnssTrackHeading(GpsPos, pgnss);
// 如果系统没有初始化,则先初始化
if (pdr->sysStatus == IS_INITIAL) {
return pdr_initProc(&pgnss, kf, pdr, result);
}
// 如果惯导没有达到输出条件,则不预测轨迹
if (!pdr->fusionPdrFlg)return resetOutputResult(&pgnss, pdr, kf, result);
// 根据GPS信息, 计算kf的过程噪声和观测噪声
calEkfQRMatrix(nmea_data, 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->p_xk[3];
}
if (pgnss.yaw != INVAILD_GPS_YAW) {
pdr_gnssInsLocFusion(&pgnss, pdr, &sys, yaw_bias, kf, result);
return TYPE_FIX_PDR;
}
}
// 不满足推算条件直接输出原始GPS
if (pgnss.satellites_num > 4 && nmea_data->accuracy.err > 0 &&
nmea_data->accuracy.err < 15) {
pdr_outputGpsPos(&pgnss, result);
pdr->noGpsCount = 0;
return TYPE_FIX_GPS;
}
// 如果没有GPS信号那么PDR也会接着推算位置, 但是最多推算10个点
if (pdr->noGpsCount < MAX_NO_GPS_PREDICT) {
// 无GPS状态位置推算
pdr_noGpsPredict(kf, result, pdr);
return TYPE_FIX_PDR;
}
pdr->noGpsCount++;
return 0;
}
/**----------------------------------------------------------------------
* Function : pdr_noGpsPredict
* Description : gpsGPS10
* Date : 2020/07/08
*
*---------------------------------------------------------------------**/
void pdr_noGpsPredict(KfPara* kf, lct_fs* result, PDR* p_pdr)
{
double ned[3] = {0}, lla[3] = {0};
ned[0] = kf->p_xk[0] - p_pdr->x0;
ned[1] = kf->p_xk[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->noGpsCount++;
}
/**----------------------------------------------------------------------
* Function : calPdrHeadingOffset
* Description : GPS
* Date : 2020/07/08 logzhan
*---------------------------------------------------------------------**/
void calPdrHeadingOffset(lct_nmea* nmea_data, PDR* 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)
&& (pdr_detStatic(pdr, &pgnss, (p_pdr->steps - p_pdr->lastSteps)) == 0 && pdr->motionType == 2))
{
/*这里放姿态角与GPS对准part1 start*/
double imuHeading = atan2(2 * (g_ahrs.qnb[0] * g_ahrs.qnb[3] + g_ahrs.qnb[1] * g_ahrs.qnb[2]),
1 - 2 * (g_ahrs.qnb[2] * g_ahrs.qnb[2] + g_ahrs.qnb[3] * g_ahrs.qnb[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 : pdr_detectFixMode
* Description : PDR,
* GPS
* Date : 2020/07/08 logzhan
* 2020/02/08 logzhan : -1INVAILD_GPS_YAW
*
*---------------------------------------------------------------------**/
int pdr_detectFixMode(gnss* pgnss, KfPara* kf, PDR* g_pdr, lct_fs* result) {
// 检测用户是否处于静止状态
if (pdr_detStatic(pdr, pgnss, g_pdr->deltaStepsPerGps)) {
if (pgnss->error > 0 && pgnss->error < 15 &&
pgnss->lastError >= pgnss->error) {
pdr_outputGpsPos(pgnss, result);
pgnss->lastError = pgnss->error;
return TYPE_FIX_PDR;
}
// 否则不输出位置
return TYPE_FIX_NONE;
}
// 如果是检测到是开车状态则输出GPS位置
if (detIsCarMode(pgnss, pdr, pdr->deltaStepsPerGps, &pgnss->overVelCount)) {
// 如果检测到车载模式则重置PDR状态需要重新初始化
pdr_resetSysStatus(kf);
if (pgnss->error >= 0 || (pgnss->satellites_num > 4
&& pgnss->HDOP < 2.0)) {
pdr_outputGpsPos(pgnss, result);
return TYPE_FIX_GPS;
}
// 精度过差,不输出位置
return TYPE_FIX_NONE;
}
return TYPE_FIX_PDR;
}
/**----------------------------------------------------------------------
* Function : pdr_getGpsHeading
* Description : GPS(0 - 360°)
* Date : 2020/07/08 logzhan
* 2020/02/08 logzhan : -1INVAILD_GPS_YAW
*
*---------------------------------------------------------------------**/
double pdr_getGpsHeading(gnss* pgnss) {
double gpsYaw = INVAILD_GPS_YAW;
if (pgnss->satellites_num > 4 && pgnss->HDOP < 2.0 && pgnss->vel >= 1.0
&& pgnss->yaw != INVAILD_GPS_YAW && pgnss->error < 50) {
gpsYaw = pgnss->yaw * RADIAN_PER_DEG;
}
return gpsYaw;
}
/**----------------------------------------------------------------------
* Function : pdr_nmea2Gnss
* Description : nmeagnss
* Date : 2020/07/08 logzhan
*---------------------------------------------------------------------**/
void pdr_nmea2Gnss(lct_nmea* nmea_data, gnss* pgnss)
{
lct_nmea_rmc 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 : pdr_gnssUpdate
* Description : nmeagnss
* Date : 2020/07/08 logzhan
* 2020/02/09 logzhan : pdr_gpsUpdate
* GPSgnssnmea
*
*---------------------------------------------------------------------**/
void pdr_gnssUpdate(gnss* gps, lct_nmea* nmea) {
// nmea数据转gnss数据结构
pdr_nmea2Gnss(nmea, &pgnss);
// GPS回调更新暂时不清楚函数功能
gpsUpdateCb(gps);
}

View File

@ -1,483 +0,0 @@
/******************** (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) SAP5.0
* 22
* 2021/02/09 logzhan PDRbug
* 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 "pdr_main.h"
#include "time.h"
using namespace std;
/* Global Variable Definition ------------------------------------------------*/
ResultTracks resTracks;
FILE* fpSimulatorFile = NULL;
/* Extern Variable Definition ------------------------------------------------*/
extern "C" PDR g_pdr;
extern "C" double refGpsYaw;
/**----------------------------------------------------------------------
* Function : main
* Description : pdr仿main
* Date : 2021/01/25 logzhan
*---------------------------------------------------------------------**/
int main(int argc, char* argv[])
{
string logPath = "E:\\Software Project\\GnssIns-PDR-Private\\1.Software\\Debug\\";
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();
lct_fs lct_fusion;
memset(&lct_fusion,0, sizeof(lct_fusion));
memset(&resTracks, 0, sizeof(resTracks));
// 解析文本仿真
while (fgets(line, 256, fileFp)){
// 解析文本数据仿真
if (pdr_locationMainLoopStr(line, &lct_fusion) != TYPE_FIX_NONE){
// 更新结果轨迹用于最后的kml生成
updateResTrack(resTracks, lct_fusion);
}
}
// 关闭PDR算法释放资源
pdr_closeAlgorithm();
// 写结果kml
KmlWrite(kmlPath, fileHead, string("_PDR_ZL_2.0b"));
// 关闭文件
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 : 2021/01/25 logzhan
*---------------------------------------------------------------------**/
void updateResTrack(ResultTracks& resTrack, lct_fs& 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",
motionType2Str(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);
}
/**----------------------------------------------------------------------
* Function : motionType2Str
* Description :
* Date : 2020/8/3 logzhan
*---------------------------------------------------------------------**/
const char* motionType2Str(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";
}
#ifdef _WIN32
/**----------------------------------------------------------------------
* Function : PDR_Init
* Description : PDR(DLL)
* Date : 2022/09/15 logzhan
*---------------------------------------------------------------------**/
void LibPDR_Init() {
Algorithm_Init();
}
/**----------------------------------------------------------------------
* Function : pdrSumulatorUpdateGpsStep
* Description : 仿GPS(DLL)
* Date : 2020/8/3 logzhan
*---------------------------------------------------------------------**/
PosFusion pdrSumulatorUpdateGpsStep(int useGpsFlg)
{
PosFusion fusion;
fusion.vaild = 0;
lct_nmea location_nmea;
lct_nmea* ln = &location_nmea;
imu imu_data;
lct_fs 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, fpSimulatorFile)) {
int flag = pdr_locationMainLoopStr(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 (fpSimulatorFile == NULL) {
fpSimulatorFile = fopen(path, "rb");
}
else {
fclose(fpSimulatorFile);
fpSimulatorFile = NULL;
}
}
/**----------------------------------------------------------------------
* Function : setRefGpsYaw
* Description : GPS
* Date : 2020/8/3 logzhan
*---------------------------------------------------------------------**/
void setRefGpsYaw() {
refGpsYaw = g_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 closePdrAlgo() {
pdr_closeAlgorithm();
if (fpSimulatorFile != NULL) {
fclose(fpSimulatorFile);
fpSimulatorFile = NULL;
}
}
#endif

View File

@ -1,195 +0,0 @@
/******************** (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 "pdr_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

@ -1,886 +0,0 @@
/******************** (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_agm 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 *imu_p, double ts, int sstp)
{
int i = 0;
int j = 0;
sensor_agm data_xyz = { 0 };
sensor_agm 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_agm));
}
else
{
memcpy(&outputData, &SensorDataHist[0], sizeof(sensor_agm));
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_agm));
}
memcpy(&SensorDataHist[i], &data_xyz, sizeof(sensor_agm));
break;
}
}
}
if (SENSOR_ACC == outputData.type)
{
memcpy(&imu_p->acc, &outputData, sizeof(sensor_agm));
}
else if (SENSOR_MAG == outputData.type)
{
memcpy(&imu_p->mag, &outputData, sizeof(sensor_agm));
}
else if (SENSOR_GYRO == outputData.type)
{
memcpy(&imu_p->gyr, &outputData, sizeof(sensor_agm));
}
#endif
}
void parseNMEA(char* pt, lct_nmea *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(lct_nmea *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, lct_nmea *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, lct_nmea *ln, double ts)
{
int i = 0;
double temp = 0;
double rmc_time = 0;
lct_nmea_rmc *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, lct_nmea *ln, double ts)
{
char *pt_gsv = NULL;
//memset(&ln->gsv, ITEM_INVALID, sizeof(ln->gsv));
int i = 0;
lct_nmea_gsv* 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, lct_nmea *ln, double ts)
{
int i = 0;
int ind = -1;
lct_nmea_gsa gsa = {0};
if (!strcmp(pt, GNGSA_STR))
{
gsa.type = SENSOR_LOCATION_NMEA_GNGSA;
gsa.update = 1;
}
else if (!strcmp(pt, GPGSA_STR))
{
ind = 0;
gsa.type = SENSOR_LOCATION_NMEA_GPGSA;
gsa.update = 1;
}
else if (!strcmp(pt, GLGSA_STR))
{
ind = 1;
gsa.type = SENSOR_LOCATION_NMEA_GLGSA;
gsa.update = 1;
}
else if (!strcmp(pt, GAGSA_STR))
{
ind = 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 (ind == 0 && gsa.prn[i - 2] > 32)
{
gsa.prn[i - 2] = (gsa.prn[i - 2] % 32)+1;
}
if (ind == 1 && gsa.prn[i - 2] < 65 && gsa.prn[i - 2] > 99)
{
gsa.prn[i - 2] = (gsa.prn[i - 2] % 35) + 65;
}
if (ind == 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 (ind < 0)
{
ind = 1;
}
}
else
{
gsa.prnflg |= (1 << gsa.prn[i - 2]);
if (ind < 0)
{
if (ln->gsa[0].update && ln->gsa[1].update)
{
ind = 2;
}
else
{
ind = 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 (ind < 0 && pt[0] == '1')
{
ind = 0;
gsa.type = SENSOR_LOCATION_NMEA_GPGSA;
}
else if (ind < 0 && pt[0] == '2')
{
ind = 1;
gsa.type = SENSOR_LOCATION_NMEA_GLGSA;
}
else if (ind < 0 && pt[0] == '3')
{
ind = 2;
gsa.type = SENSOR_LOCATION_NMEA_GAGSA;
}
}
}
pt = strtok_ct(NULL, ",");
i++;
/*printf("pt %s %u\n", pt,i);*/
}
gsa.time = ts;
if (ind >=0 && ind <=2)
{
memcpy(&ln->gsa[ind], &gsa, sizeof(lct_nmea_gsa));
}
}
/**----------------------------------------------------------------------
* Function : parseLocAccuracy
* Description : GPSAccuracy
* Date : 2020/7/9 yuanlin@vivo.com &logzhan
*---------------------------------------------------------------------**/
void parseLocAccuracy(char* pt, lct_nmea *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++;
}
}
int pdr_parseLineStr(char* line, imu* imu_p, lct_nmea* 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;
}

View File

@ -1,602 +0,0 @@
/******************** (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 "pdr_base.h"
#include "pdr_util.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 : pdr_v3Norm
* Description :
* Date : 2021/01/26 yuanlin@vivocom &&
*
*---------------------------------------------------------------------**/
void pdr_v3Norm(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 : quatNorm
* Description :
* Date : 2021/01/26 yuanlin@vivocom && logzhan
* 2021/01/27 logzhan :
* 0
*---------------------------------------------------------------------**/
void QuatNorm(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;
}
}
double pow_i(double num, long long n)
{
double powint = 1;
long long i;
for (i = 1; i <= n; i++)
{
powint *= num;
}
return powint;
}
double pow_f(double num, double m)
{
int i, j;
double powf = 0, x, tmpm = 1;
x = num - 1;
for (i = 1; tmpm>1e-12 || tmpm<-1e-12; i++)
{
for (j = 1, tmpm = 1; j <= i; j++)
{
tmpm *= (m - j + 1)*x / j;
}
powf += tmpm;
}
return powf + 1;
}
// https://blog.csdn.net/xiaoxiongli/article/details/2134626
double vivopow(double num, double m)
{
if (num == 0 && m != 0)
{
return 0;
}
else if (num == 0 && m == 0)
{
return 1;
}
else if (num < 0 && (m != (long long)m))
{
return (num - num) / (num - num);
}
if (num > 2)
{
num = 1 / num;
m = -m;
}
if (m < 0)
{
return 1 / vivopow(num, -m);
}
if (m == (long long)m)
{
return pow_i(num, (long long)m);
}
else
{
return pow_f(num, m - (long long)m) * pow_i(num, (long long)m);
}
}
/**----------------------------------------------------------------------
* 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 QuaternConj(float _q[], float q[]) {
_q[0] = q[0];
_q[1] = -q[1];
_q[2] = -q[2];
_q[3] = -q[3];
}
void quaternProd(float ab[], float a[], float b[]) {
ab[0] = a[0] * b[0] - a[1] * b[1] - a[2] * b[2] - a[3] * b[3];
ab[1] = a[0] * b[1] + a[1] * b[0] + a[2] * b[3] - a[3] * b[2];
ab[2] = a[0] * b[2] - a[1] * b[3] + a[2] * b[0] + a[3] * b[1];
ab[3] = a[0] * b[3] + a[1] * b[2] - a[2] * b[1] + a[3] * b[0];
}
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(vivopow(a, 2) - vivopow(b, 2)) / a;
roc = a / sqrt(1 - vivopow(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(vivopow(a, 2) - vivopow(b, 2)) / a;
b = sqrt(vivopow(a, 2)*(1 - vivopow(e, 2)));
ep = sqrt((vivopow(a, 2) - vivopow(b, 2)) / vivopow(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] + vivopow(ep, 2)*b*vivopow(sin(th), 3)), (p - vivopow(e, 2)*a*vivopow(cos(th), 3)));
roc = a / sqrt(1 - vivopow(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);
}
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 pointA, LatLng 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 ProjPointOfLatLng(LatLng point, LatLng linePointA, LatLng 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 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 = vivopow(gradxB_A, 2) + vivopow(gradyB_A, 2);
resProjPoint.lon = (double)(
(gradxB_P * gradxB_A * gradyB_A + point.lon * vivopow(gradyB_A, 2) + linePointB.lon * vivopow(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 pdr_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

@ -1,496 +0,0 @@
/********************************************************************/
/* 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 lct_nmea *);
/* 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 initSceneRecognition(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 lct_nmea *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 lct_nmea *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 lct_nmea * _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. */
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1 +0,0 @@
.DS_store

View File

@ -1,95 +0,0 @@
Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator and
subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for the
purpose of contributing to a commons of creative, cultural and scientific works
("Commons") that the public can reliably and without fear of later claims of
infringement build upon, modify, incorporate in other works, reuse and
redistribute as freely as possible in any form whatsoever and for any purposes,
including without limitation commercial purposes. These owners may contribute to
the Commons to promote the ideal of a free culture and the further production of
creative, cultural and scientific works, or to gain reputation or greater
distribution for their Work in part through the use and efforts of others.
For these and/or other purposes and motivations, and without any expectation of
additional consideration or compensation, the person associating CC0 with a Work
(the "Affirmer"), to the extent that he or she is an owner of Copyright and
Related Rights in the Work, voluntarily elects to apply CC0 to the Work and
publicly distribute the Work under its terms, with knowledge of his or her
Copyright and Related Rights in the Work and the meaning and intended legal
effect of CC0 on those rights.
1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and Related
Rights"). Copyright and Related Rights include, but are not limited to, the
following:
the right to reproduce, adapt, distribute, perform, display, communicate, and
translate a Work; moral rights retained by the original author(s) and/or
performer(s); publicity and privacy rights pertaining to a person's image or
likeness depicted in a Work; rights protecting against unfair competition in
regards to a Work, subject to the limitations in paragraph 4(a), below; rights
protecting the extraction, dissemination, use and reuse of data in a Work;
database rights (such as those arising under Directive 96/9/EC of the European
Parliament and of the Council of 11 March 1996 on the legal protection of
databases, and under any national implementation thereof, including any amended
or successor version of such directive); and other similar, equivalent or
corresponding rights throughout the world based on applicable law or treaty, and
any national implementations thereof. 2. Waiver. To the greatest extent
permitted by, but not in contravention of, applicable law, Affirmer hereby
overtly, fully, permanently, irrevocably and unconditionally waives, abandons,
and surrenders all of Affirmer's Copyright and Related Rights and associated
claims and causes of action, whether now known or unknown (including existing as
well as future claims and causes of action), in the Work (i) in all territories
worldwide, (ii) for the maximum duration provided by applicable law or treaty
(including future time extensions), (iii) in any current or future medium and
for any number of copies, and (iv) for any purpose whatsoever, including without
limitation commercial, advertising or promotional purposes (the "Waiver").
Affirmer makes the Waiver for the benefit of each member of the public at large
and to the detriment of Affirmer's heirs and successors, fully intending that
such Waiver shall not be subject to revocation, rescission, cancellation,
termination, or any other legal or equitable action to disrupt the quiet
enjoyment of the Work by the public as contemplated by Affirmer's express
Statement of Purpose.
3. Public License Fallback. Should any part of the Waiver for any reason be
judged legally invalid or ineffective under applicable law, then the Waiver
shall be preserved to the maximum extent permitted taking into account
Affirmer's express Statement of Purpose. In addition, to the extent the Waiver
is so judged Affirmer hereby grants to each affected person a royalty-free, non
transferable, non sublicensable, non exclusive, irrevocable and unconditional
license to exercise Affirmer's Copyright and Related Rights in the Work (i) in
all territories worldwide, (ii) for the maximum duration provided by applicable
law or treaty (including future time extensions), (iii) in any current or future
medium and for any number of copies, and (iv) for any purpose whatsoever,
including without limitation commercial, advertising or promotional purposes
(the "License"). The License shall be deemed effective as of the date CC0 was
applied by Affirmer to the Work. Should any part of the License for any reason
be judged legally invalid or ineffective under applicable law, such partial
invalidity or ineffectiveness shall not invalidate the remainder of the License,
and in such case Affirmer hereby affirms that he or she will not (i) exercise
any of his or her remaining Copyright and Related Rights in the Work or (ii)
assert any associated claims and causes of action with respect to the Work, in
either case contrary to Affirmer's express Statement of Purpose.
4. Limitations and Disclaimers.
No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document. Affirmer offers
the Work as-is and makes no representations or warranties of any kind concerning
the Work, express, implied, statutory or otherwise, including without limitation
warranties of title, merchantability, fitness for a particular purpose, non
infringement, or the absence of latent or other defects, accuracy, or the
present or absence of errors, whether or not discoverable, all to the greatest
extent permissible under applicable law. Affirmer disclaims responsibility for
clearing rights of other persons that may apply to the Work or any use thereof,
including without limitation any person's Copyright and Related Rights in the
Work. Further, Affirmer disclaims responsibility for obtaining any necessary
consents, permissions or other rights required for any use of the Work. Affirmer
understands and acknowledges that Creative Commons is not a party to this
document and has no duty or obligation with respect to this CC0 or use of the
Work.

View File

@ -1,244 +0,0 @@
# NMEAParser
An Arduino library to parse NMEA sentences.
NMEA is a communication standard in the marine equipment industry: GPS, anemometers,... The NMEAParser library allows you to analyze NMEA sentences and associate handlers to each of those that need to be recognized. The library provides the means to associate a handler to each identifier and also provides functions to retrieve the arguments of the sentence in different data formats: character, integer, float, character string.
## Changelog
* ```1.1``` : Added joker in type. Remove binaries from ```extra```
* ```1.0``` : Initial release
## Memory footprint
On an Arduino Uno, an instance of a NMEAParser requires 97 bytes with only one handler. 8 bytes per additional handler are required.
## Using NMEAParser
As usual, the library should be included at the beginning of the sketch.
```C++
#include <NMEAParser.h>
```
Then, you must instantiate a parser as follows:
```C++
NMEAParser<4> parser;
```
The ```4``` is the maximum number of handlers desired, ```parser``` is the name of the object that will allow the analysis of NMEA sentences. you can of course use the name you want.
In ```setup``` you configure your parser as you wish using the following functions.
### ```void addHandler(<type>, <handler>)```
where ```<type>``` is a character string and the type of sentence to recongnize, and ```<handler>``` the function to call when a sentence is recognize. ```<type>``` can be a string stored un RAM or a string stored in flash : ```F("ASTRI")```. If ```<type>``` has more than 5 characters, it is trucated.
For example, suppose you want to recognize the following sounder sentences which give the water depth below keel (DBK) and below surface (DBS):
```
$SDDBK,...
```
and
```
$SDDBS,...
```
You will install two handlers as follows (assuming your parsing object is named ```parser```):
```C++
parser.addHandler("SDDBK", handleDepthBelowKeel);
parser.addHanlder("SDDBS", handleDepthBelowSurface);
```
```handleDepthBelowKeel``` and ```handleDepthBelowSurface``` are functions that will be called when sentences are recognized.
With version 1.1, ```<type>``` may include hyphens. An hyphens matches any character. For instance if you want the handler to match all sentences coming from the sounder, you would write:
```C++
parser.addHandler("SD---", handleSounder);
```
```handleSounder``` function would be called for any sentence with the type beginning with SD.
### ```void setDefaultHandler(<handler>)```
When a sentence is succefully parsed but none of the handler correspond to it, ```<handler>``` is called. It is a function corresponding to a ```void f(void)``` prototype. By default, no function is called.
### ```void setErrorHandler(<handler>)```
When a sentence is malformed : too long, wrong characters, etc, ```<handler>``` is called. It is a function corresponding to a ```void f(void)``` prototype. By default, no function is called.
### ```void setHandleCRC(<doCRC>)```
Specifies whether the CRC is checked or not. By default, the CRC is checked. If you do not want CRC verification, pass ```false``` to ```setHandleCRC```.
---
In the handlers, you will get the arguments of the sentence, the sentence type or the error if any by using the following functions:
### ```bool getArg(<argnum>, <argval>)```
is used to get the arguments of the sentence. ```<argnum>``` is the number of the argument, starting at 0 for the argument that follows the identifier. ```<argval``` is a variable where the argument value will be stored if successful. ```getArg``` returns a boolean which is true if successfull, false if not.
Continuing with the example, [both sentences have the same 6 arguments](https://gpsd.gitlab.io/gpsd/NMEA.html#_dbk_depth_below_keel)
* Argument 0 is a float number giving the depth in feet.
* Argument 1 is a ```f``` for feet.
* Argument 2 is a float number giving the depth in meters.
* Argument 3 is a ```M``` for Meters.
* Argument 4 is a float number giving the depth in fathoms.
* At last Argument 5 is a ```F``` for Fathoms.
Suppose you are interested by the depths in meters and you have two float variables to store theses data:
```C++
float depthBelowKeel;
float depthBelowSurface;
```
You would implement ```handleDepthBelowKeel``` and ```handleDepthBelowSurface``` as follow:
```C++
void handleDepthBelowKeel(void)
{
float depth;
if (parser.getArg(2, depth))
{
depthBelowKeel = depth;
}
}
void handleDepthBelowSurface(void)
{
float depth;
if (parser.getArg(2, depth))
{
depthBelowSurface = depth;
}
}
```
### ```bool getType(<type>) / bool getType(<num>, <charType>)```
3 versions of ```getType``` exist. The first one puts the type of the sentence in ```<type>``` which is a ```char *```. The second one does the same but ```<type>``` is a ```String```. Return ```true``` if a type has been parsed, ```false``` otherwise. The third one puts a character of the type at position ```<num>```
### ```uint8_t argCount()```
Return the number of arguments.
### ```NMEA::ErrorCode error()```
Return the error. The returned code can be:
* ```NMEA::NO_ERROR```: no error;
* ```NMEA::UNEXPECTED_CHAR```: a char which is not expected in the sentence has been encountered;
* ```NMEA::BUFFER_FULL```: the sentence is too long to fit in the buffer;
* ```NMEA::TYPE_TOO_LONG```: the sentence type has more than 5 characters;
* ```NMEA::CRC_ERROR```: the CRC is wrong;
* ```NMEA::INTERNAL_ERROR```: the internal state of the parser is wrong, should not happen by the way.
### Feeding characters to the parser
Characters are fed to the parser in ```loop```, assuming we get the characters from ```Serial```, the following way:
```C++
while (Serial.available()) {
parser << Serial.read();
}
```
This can also be done in ```serialEvent```. ```while``` could be replaced by ```if```.
## A complete example
Let's say you want to turn the Arduino's LED on and off. We define a NMEA sentence taking a single argument: 1 to turn on the LED and 0 to turn it off. The sentence can therefore be:
```
$ARLED,1*43
```
to turn the LED on and
```
$ARLED,0*42
```
to turn the LED off. We define a single handler to retrieve the argument and control the LED accordingly:
```C++
void ledHandler()
{
Serial.print("Got ARLED with ");
Serial.print(parser.argCount());
Serial.println(" arguments");
int ledState;
if (parser.getArg(0,ledState)) {
digitalWrite(LED_BUILTIN, ledState == 0 ? LOW : HIGH);
}
}
```
We define 2 other handlers for anything else than ```ARLED``` and for errors
```C++
void errorHandler()
{
Serial.print("*** Error : ");
Serial.println(parser.error());
}
void unknownCommand()
{
Serial.print("*** Unkown command : ");
char buf[6];
parser.getType(buf);
Serial.println(buf);
}
```
In ```setup```, the handlers are installed:
```C++
void setup() {
Serial.begin(115200);
parser.setErrorHandler(errorHandler);
parser.addHandler("ARLED", ledHandler);
parser.setDefaultHandler(unknownCommand);
pinMode(LED_BUILTIN, OUTPUT);
}
```
At last in loop, we feed the parser with the chars coming from ```Serial```.
```C++
void loop() {
if (Serial.available()) {
parser << Serial.read();
}
}
```
---
# Extra software
Additional software can be found in the ```extra``` directory.
## NMEA sentences generator
The ```gen``` subdirectory contains ```nmeagen```, a NMEA sentence generator program. This program generates well formed sentences with good or bad CRC. It can be used to test the parser. To build ```nmeagen```, run the ```build.sh``` script. ```nmeagen``` takes 1 or 2 arguments. The first argument is the number of sentences to generate. The second optional one is the number of sentences with bad CRC.
## Test program
The ```test``` subdirectory contains a test program that compile on Linux or Mac OS X. It takes sentences from the standard input, parse them and print out the type, the arguments and if an error occured.
---
# Additional links
* [NMEA CRC calculator](https://nmeachecksum.eqth.net)
* [NMEA 0183 on Wikipedia](https://fr.wikipedia.org/wiki/NMEA_0183)
* [NMEA revealed](https://gpsd.gitlab.io/gpsd/NMEA.html)
That's all folks !

View File

@ -1,60 +0,0 @@
/*
* NMEAParser library.
*
* A NMEA example to switch ON or OFF the built in LED
*
* Sentences to send are :
*
* $ARLED,1*43
*
* to switch the LED on and
*
* $ARLED,0*42
*
* to switch the LED off
*
* Set the serial monitor end of line to <cr><lf>
*/
#include <NMEAParser.h>
/* A parser with only one handler */
NMEAParser<1> parser;
void errorHandler()
{
Serial.print("*** Error : ");
Serial.println(parser.error());
}
void unknownCommand()
{
Serial.print("*** Unkown command : ");
char buf[6];
parser.getType(buf);
Serial.println(buf);
}
void ledHandler()
{
Serial.print("Got ARLED with ");
Serial.print(parser.argCount());
Serial.println(" arguments");
int ledState;
if (parser.getArg(0,ledState)) {
digitalWrite(LED_BUILTIN, ledState == 0 ? LOW : HIGH);
}
}
void setup() {
Serial.begin(115200);
parser.setErrorHandler(errorHandler);
parser.addHandler("ARLED", ledHandler);
parser.setDefaultHandler(unknownCommand);
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
if (Serial.available()) {
parser << Serial.read();
}
}

View File

@ -1,67 +0,0 @@
/*
* NMEAParser library.
*
* A NMEA example to switch ON or OFF the built in LED but with the use
* of wild char in the type
*
* Sentences to send are :
*
* $ARLE1*2B
*
* to switch the LED on and
*
* $ARLE0*2A
*
* to switch the LED off
*
* Set the serial monitor end of line to <cr><lf>
*/
#include <NMEAParser.h>
/* A parser with only one handler */
NMEAParser<1> parser;
void errorHandler()
{
Serial.print("*** Error : ");
Serial.println(parser.error());
}
void unknownCommand()
{
Serial.print("*** Unkown command : ");
char buf[6];
parser.getType(buf);
Serial.println(buf);
}
void ledHandler()
{
Serial.print("Got ARLEx with ");
Serial.print(parser.argCount());
Serial.println(" arguments");
char wantedLedState;
if (parser.getType(4, wantedLedState)) { // get the 4th character ot the type
if (wantedLedState == '0' || wantedLedState == '1') {
digitalWrite(LED_BUILTIN, wantedLedState == '0' ? LOW : HIGH);
}
else {
Serial.println("x should be 0 or 1");
}
}
}
void setup() {
Serial.begin(115200);
parser.setErrorHandler(errorHandler);
parser.addHandler("ARLE-", ledHandler);
parser.setDefaultHandler(unknownCommand);
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
if (Serial.available()) {
parser << Serial.read();
}
}

View File

@ -1,77 +0,0 @@
/*
* NMEAParser library.
*
* Parsing example.
*
* 2 handlers are added and 2 sentences are parsed
*/
#include <NMEAParser.h>
/* A parser is declared with 2 handlers at most */
NMEAParser<2> parser;
const char firstSentence[] = "$DBAXK*54\r\n";
const char secondSentence[] = "$EJCHQ,03,O,UUEIE,S,953.11,S,4.172,ASBUX,J*54\r\n";
void errorHandler()
{
Serial.print("*** Error : ");
Serial.println(parser.error());
}
void firstHandler()
{
Serial.print("Got DBAXK with ");
Serial.print(parser.argCount());
Serial.println(" arguments");
}
void secondHandler()
{
Serial.print("Got $EJCHQ with ");
Serial.print(parser.argCount());
Serial.println(" arguments");
int arg0;
char arg1;
char arg2[10];
char arg3;
float arg4;
char arg5;
float arg6;
String arg7;
char arg8;
if (parser.getArg(0,arg0)) Serial.println(arg0);
if (parser.getArg(1,arg1)) Serial.println(arg1);
if (parser.getArg(2,arg2)) Serial.println(arg2);
if (parser.getArg(3,arg3)) Serial.println(arg3);
if (parser.getArg(4,arg4)) Serial.println(arg4);
if (parser.getArg(5,arg5)) Serial.println(arg5);
if (parser.getArg(6,arg6)) Serial.println(arg6);
if (parser.getArg(7,arg7)) Serial.println(arg7);
if (parser.getArg(8,arg8)) Serial.println(arg8);
}
void setup()
{
Serial.begin(115200);
parser.setErrorHandler(errorHandler);
parser.addHandler("DBAXK", firstHandler);
parser.addHandler("EJCHQ", secondHandler);
Serial.print("Parsing : ");
Serial.print(firstSentence);
for (uint8_t i = 0; i < strlen(firstSentence); i++) {
parser << firstSentence[i];
}
Serial.print("Parsing : ");
Serial.print(secondSentence);
for (uint8_t i = 0; i < strlen(secondSentence); i++) {
parser << secondSentence[i];
}
}
void loop()
{
}

View File

@ -1,101 +0,0 @@
#include <stdio.h>
#include <inttypes.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <time.h>
char intToHex(uint8_t v)
{
if (v < 10) return '0' + v;
else if (v < 16) return 'A' + v - 10;
else return '-';
}
void generateSentence(bool goodCRC)
{
uint8_t crc = 0;
putchar('$');
/* generate the id */
for (int i = 0; i < 5; i++) {
char letter = 'A' + random() % 26;
putchar(letter);
crc ^= letter;
}
int numberOfArgs = random() % 10;
for (int i = 0; i < numberOfArgs; i++) {
putchar(',');
crc ^= ',';
int kind = random() % 5;
switch (kind) {
case 0: /* integer */
for (int j = 0; j < random() % 5 + 1; j++) {
char digit = '0' + random() % 10;
putchar(digit);
crc ^= digit;
}
break;
case 1: /* char */
if (1) {
char letter = 'A' + random() % 26;
putchar(letter);
crc ^= letter;
}
break;
case 2: /* string */
for (int i = 0; i < 5; i++) {
char letter = 'A' + random() % 26;
putchar(letter);
crc ^= letter;
}
break;
case 3: /* float */
for (int j = 0; j < random() % 5 + 1; j++) {
char digit = '0' + random() % 10;
putchar(digit);
crc ^= digit;
}
putchar('.');
crc ^= '.';
for (int j = 0; j < random() % 5 + 1; j++) {
char digit = '0' + random() % 10;
putchar(digit);
crc ^= digit;
}
case 4: /* nothing */
break;
}
}
if (! goodCRC) crc = ~crc;
putchar('*');
putchar(intToHex(crc >> 4));
putchar(intToHex(crc & 0x0F));
putchar('\r');
putchar('\n');
}
int main(int argc, char *argv[])
{
if (argc < 2 || argc > 3) {
printf("Usage: nmeagen <n> [<c>] where <n> is the number of sentences\n"
" and <c> the number of sentences with a wrong CRC\n");
exit(1);
}
else {
int numberOfSentences = strtol(argv[1], NULL, 0);
int numberOfWrongCRCSentences = 0;
if (argc == 3) {
numberOfWrongCRCSentences = strtol(argv[2], NULL, 0);
}
/* Init a the random seed with the epoch */
srandom(time(NULL));
for (int i = 0; i < numberOfSentences; i++) {
generateSentence(true);
}
for (int i = 0; i < numberOfWrongCRCSentences; i++) {
generateSentence(false);
}
}
}

View File

@ -1,3 +0,0 @@
#!/bin/bash
gcc -o nmeagen NMEASentencesGenerator.c

View File

@ -1,30 +0,0 @@
$FRMIO,G,33,081,I,Q,Q,J,48*2E
$APYOG,LDCXT,JSCIE,KUJAU,64,EJMVQ,F,P,AJQLD*12
$SUHEG,GAGCE,G,Q*31
$KIEHA,E,W,R,SXGMG,64,40,WCIEC,2253,THWNT*6E
$WPHGT,FRYBV,5689,C*68
$YDXHC,A,J*45
$GUIAZ,CWIMW*2B
$SOEOE,ZBKFY,HKTHJ,536,504,946,0,705,BIDPI,ACEOK*4B
$TEHJW,NNHPF,4,34,DFSFJ,8638,F,B*59
$LKGPI,XTUUO*36
$ZCHFN,769,0202,12*4E
$DQTMV,Y,712,0*2B
$MQPEM,H,95,E,M,U,92,N,340,D*47
$APUXX,RKPFP,MUQOA,VOCGB,39,6,D,V,U*78
$MBLXP,22573,3,AVNFF*3C
$LCBXF,V,21,AKCLF,YIASR,PHIUS,VPRJM*11
$OFXPI,2,B,14,A*7C
$IUKFO,D,MSETP,99,GYBDX*05
$UDSFE,QHPNK,D,N,R*55
$EDULQ,ISGJX,FDXLJ,O,H,M,B,ROZIU,C*4A
$FUONE,P,Y*5E
$VLVIU*50
$WTBCG,14,819,ATHAO,V,MSUHV,NSCLD*76
$WJZLK,3,Q,31*0C
$MRFGM,NCVPP,NZCBL,F,U,C,672,LPFAS*56
$UFOJW,V,AIUHA,BFBKN*2C
$OHOSS,HOIBI,8695,031,B,CVSMD,154,DEUCB*79
$MYHGK,ZKTDK,YFJBI,OLBOI,74,KPASB,XBCSE,Q,U*00
$ZIENW*4F
$ONAYP,N,27,A*6F

View File

@ -1,3 +0,0 @@
#!/bin/bash
c++ -o testNMEA testNMEA.cpp

View File

@ -1,63 +0,0 @@
#include "../../src/NMEAParser.h"
#include <string.h>
NMEAParser<4> commandNMEA;
int errorCount = 0;
void error()
{
printf("=================================================\n");
int err = commandNMEA.error();
printf("*** ERROR %d ",err);
switch (err) {
case NMEA::UNEXPECTED_CHAR:
printf("(UNEXPECTED CHAR)\n");
break;
case NMEA::BUFFER_FULL:
printf("(BUFFER FULL)\n");
break;
case NMEA::CRC_ERROR:
printf("(CRC ERROR)\n");
break;
case NMEA::INTERNAL_ERROR:
printf("(INTERNAL ERROR)\n");
break;
default:
printf("(?)\n");
break;
}
commandNMEA.printBuffer();
printf("=================================================\n");
errorCount++;
}
void defaultHandler()
{
printf("------------\n");
char buf[82];
if (commandNMEA.getType(buf)) {
printf("%s\n", buf);
for (int i = 0; i < commandNMEA.argCount(); i++) {
if (commandNMEA.getArg(i, buf)) {
printf(" %s\n", buf);
}
}
}
}
int main()
{
printf("Debut du test\n");
commandNMEA.setErrorHandler(error);
commandNMEA.setDefaultHandler(defaultHandler);
int count = 0;
int v;
while ((v = getchar()) != EOF) {
commandNMEA << v;
if (v == '\n') count++;
}
printf("*** Processed %d NMEA sentences\n", count);
printf("*** Got %d error(s)\n", errorCount);
}

View File

@ -1,32 +0,0 @@
#######################################
# Syntax Coloring Map For NMEAParser
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
NMEAParser KEYWORD1
NMEA KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
addHandler KEYWORD2
setErrorHandler KEYWORD2
setDefaultHandler KEYWORD2
argCount KEYWORD2
getArg KEYWORD2
getType KEYWORD2
error KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################
NO_ERROR LITERAL1
UNEXPECTED_CHAR LITERAL1
BUFFER_FULL LITERAL1
CRC_ERROR LITERAL1
INTERNAL_ERROR LITERAL1

View File

@ -1,9 +0,0 @@
name=NMEAParser
version=1.1
author=Glinnes Hulden
maintainer=Glinnes Hulden
sentence=A simple Arduino library to parse NMEA sentences.
paragraph=A simple Arduino library to parse NMEA sentences.
category=Communication
url=https://github.com/Glinnes/NMEAParser
architectures=*

View File

@ -1,657 +0,0 @@
/*
* NMEA parser library for Arduino
*
* Simple and compact NMEA parser designed for Arduino
*
* Author : Glinnes Hulden
*
* This work is distributed under license CC0.
* Check https://creativecommons.org/publicdomain/zero/1.0/deed.en
*
* No Copyright
*
* The person who associated a work with this deed has dedicated the work
* to the public domain by waiving all of his or her rights to the work
* worldwide under copyright law, including all related and neighboring rights,
* to the extent allowed by law.
*
* You can copy, modify, distribute and perform the work, even for commercial
* purposes, all without asking permission. See Other Information below.
*
* Other Information
*
* In no way are the patent or trademark rights of any person affected by CC0,
* nor are the rights that other persons may have in the work or in how the
* work is used, such as publicity or privacy rights.
* Unless expressly stated otherwise, the person who associated a work with
* this deed makes no warranties about the work, and disclaims liability for
* all uses of the work, to the fullest extent permitted by applicable law.
* When using or citing the work, you should not imply endorsement by the
* author or the affirmer.
*/
#ifndef __NMEAParser_h__
#define __NMEAParser_h__
#ifdef __amd64__
/* To use on my development platform */
#include <stddef.h>
#include <stdint.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#else
#include <Arduino.h>
#endif
namespace NMEA {
/*
* Error codes
*/
typedef enum {
NO_ERROR,
UNEXPECTED_CHAR,
BUFFER_FULL,
TYPE_TOO_LONG,
CRC_ERROR,
INTERNAL_ERROR
} ErrorCode;
}
/*
* The library consists of a single template: NMEAParser.
*/
template <size_t S> class NMEAParser {
private:
typedef void (*NMEAErrorHandler)(void);
typedef void (*NMEAHandler)(void);
typedef struct { char mToken[6]; NMEAHandler mHandler; } NMEAHandlerEntry;
typedef enum { INIT, SENT, ARG, CRCH, CRCL, CRLFCR, CRLFLF } State;
public:
/*
* maximum sentence size is 82 including the starting '$' and the <cr><lf>
* at the end. Since '$', the '*', the 2 characters CRC and the <cr><lf>
* are not bufferized, 82 - 6 + 1 = 77 chars are enough.
* is enough.
*/
static const uint8_t kSentenceMaxSize = 77;
private:
/*
* buffer to store the NMEA sentence excluding starting '$', the ','
* separator, the '*', the CRC and the <cr><lf>. The tail of the buffer
* is used to store the index of the arguments.
*/
char mBuffer[kSentenceMaxSize];
/*
* Current index to store a char of the sentence
*/
uint8_t mIndex;
/*
* Current index to store the index of an argument
*/
uint8_t mArgIndex;
/*
* A handler to notify a malformed sentence
*/
NMEAErrorHandler mErrorHandler;
/*
* A handler for well formed but unrecognized sentences
*/
NMEAHandler mDefaultHandler;
/*
* An array of NMEA handler : pointers to functions to call when a sentence
* is recognized
*/
NMEAHandlerEntry mHandlers[S];
/*
* The current number of mHandlers
*/
uint8_t mHandlerCount;
/*
* Parsing automaton variable
*/
State mState;
/*
* mError
*/
NMEA::ErrorCode mError;
/*
* True if CRC is handled, false otherwise. Defaults to true
*/
bool mHandleCRC;
/*
* Variables used to computed and parse the CRC
*/
uint8_t mComputedCRC;
uint8_t mGotCRC;
/*
* NMEAParserStringify is used internally to temporarely replace a char
* in the buffer by a '\0' so that libc string functions may be used.
* Instantiating a NMEAParserStringify object in a pair of {} defines
* a section in which the 'stringification' is done : the constructor
* does that according to the arguments and se destructor restore the buffer.
*/
class NMEAParserStringify {
uint8_t mPos;
char mTmp;
NMEAParser<S> *mParent;
public:
NMEAParserStringify(NMEAParser<S> *inParent, uint8_t inPos) :
mPos(inPos),
mParent(inParent)
{
mTmp = mParent->mBuffer[mPos];
mParent->mBuffer[mPos] = '\0';
}
~NMEAParserStringify()
{
mParent->mBuffer[mPos] = mTmp;
}
};
/*
* Call the error handler if defined
*/
void callErrorHandler(void)
{
if (mErrorHandler != NULL) {
mErrorHandler();
}
}
/*
* Reset the parser
*/
void reset() {
mState = INIT;
mIndex = 0;
mArgIndex = kSentenceMaxSize;
mError = NMEA::NO_ERROR;
}
/*
* Called when the parser encounter a char that should not be there
*/
void unexpectedChar()
{
mError = NMEA::UNEXPECTED_CHAR;
callErrorHandler();
reset();
}
/*
* Called when the buffer is full because of a malformed sentence
*/
void bufferFull()
{
mError = NMEA::BUFFER_FULL;
callErrorHandler();
reset();
}
/*
* Called when the type of the sentence is longer than 5 characters
*/
void typeTooLong()
{
mError = NMEA::TYPE_TOO_LONG;
callErrorHandler();
reset();
}
/*
* Called when the CRC is wrong
*/
void crcError()
{
mError = NMEA::CRC_ERROR;
callErrorHandler();
reset();
}
/*
* Called when the state of the parser is not ok
*/
void internalError()
{
mError = NMEA::INTERNAL_ERROR;
callErrorHandler();
reset();
}
/*
* retuns true is there is at least one byte left in the buffer
*/
bool spaceAvail()
{
return (mIndex < mArgIndex);
}
/*
* convert a one hex digit char into an int. Used for the CRC
*/
static int8_t hexToNum(const char inChar)
{
if (isdigit(inChar)) return inChar - '0';
else if (isupper(inChar) && inChar <= 'F') return inChar - 'A' + 10;
else if (islower(inChar) && inChar <= 'f') return inChar - 'a' + 10;
else return -1;
}
static bool strnwcmp(const char *s1, const char *s2, uint8_t len)
{
while (len-- > 0) {
if (*s1 != *s2 && *s1 != '-' && *s2 != '-') return false;
s1++;
s2++;
}
return true;
}
/*
* return the slot number for a handler. -1 if not found
*/
int8_t getHandler(const char *inToken)
{
/* Look for the token */
for (uint8_t i = 0; i < mHandlerCount; i++) {
if (strnwcmp(mHandlers[i].mToken, inToken, 5)) {
return i;
}
}
return -1;
}
/*
* When all the sentence has been parsed, process it by calling the handler
*/
void processSentence()
{
/* Look for the token */
uint8_t endPos = startArgPos(0);
int8_t slot;
{
NMEAParserStringify stfy(this, endPos);
slot = getHandler(mBuffer);
}
if (slot != -1) {
mHandlers[slot].mHandler();
}
else {
if (mDefaultHandler != NULL) {
mDefaultHandler();
}
}
}
/*
* Return true if inArgNum corresponds to an actual argument
*/
bool validArgNum(uint8_t inArgNum)
{
return inArgNum < (kSentenceMaxSize - mArgIndex);
}
/*
* Return the start index of the inArgNum th argument
*/
uint8_t startArgPos(uint8_t inArgNum)
{
return mBuffer[kSentenceMaxSize - 1 - inArgNum];
}
/*
* Return the end index of the inArgNum th argument
*/
uint8_t endArgPos(uint8_t inArgNum)
{
return mBuffer[kSentenceMaxSize - 2 - inArgNum];
}
public:
/*
* Constructor initialize the parser.
*/
NMEAParser() :
mErrorHandler(NULL),
mDefaultHandler(NULL),
mHandlerCount(0),
mError(NMEA::NO_ERROR),
mHandleCRC(true),
mComputedCRC(0),
mGotCRC(0)
{
reset();
}
/*
* Add a sentence handler
*/
void addHandler(const char *inToken, NMEAHandler inHandler)
{
if (mHandlerCount < S) {
if (getHandler(inToken) == -1) {
strncpy(mHandlers[mHandlerCount].mToken, inToken, 5);
mHandlers[mHandlerCount].mToken[5] = '\0';
mHandlers[mHandlerCount].mHandler = inHandler;
mHandlerCount++;
}
}
}
#ifdef __AVR__
/*
* Add a sentence handler. Version with a token stored in flash.
*/
void addHandler(const __FlashStringHelper *ifsh, NMEAHandler inHandler)
{
char buf[6];
PGM_P p = reinterpret_cast<PGM_P>(ifsh);
for (uint8_t i = 0; i < 6; i++) {
char c = pgm_read_byte(p++);
buf[i] = c;
if (c == '\0') break;
}
addHandler(buf, inHandler);
}
#endif
/*
* Set the error handler which is called when a sentence is malformed
*/
void setErrorHandler(NMEAErrorHandler inHandler)
{
mErrorHandler = inHandler;
}
/*
* Set the default handler which is called when a sentence is well formed
* but has no handler associated to
*/
void setDefaultHandler(NMEAHandler inHandler)
{
mDefaultHandler = inHandler;
}
/*
* Give a character to the parser
*/
void operator<<(char inChar)
{
int8_t tmp;
switch (mState) {
/* Waiting for the starting $ character */
case INIT:
mError = NMEA::NO_ERROR;
if (inChar == '$') {
mComputedCRC = 0;
mState = SENT;
}
else unexpectedChar();
break;
case SENT:
if (isalnum(inChar)) {
if (spaceAvail()) {
if (mIndex < 5) {
mBuffer[mIndex++] = inChar;
mComputedCRC ^= inChar;
}
else {
typeTooLong();
}
}
else bufferFull();
}
else {
switch(inChar) {
case ',' :
mComputedCRC ^= inChar;
mBuffer[--mArgIndex] = mIndex;
mState = ARG;
break;
case '*' :
mGotCRC = 0;
mBuffer[--mArgIndex] = mIndex;
mState = CRCH;
break;
default :
unexpectedChar();
break;
}
}
break;
case ARG:
if (spaceAvail()) {
switch(inChar) {
case ',' :
mComputedCRC ^= inChar;
mBuffer[--mArgIndex] = mIndex;
break;
case '*' :
mGotCRC = 0;
mBuffer[--mArgIndex] = mIndex;
mState = CRCH;
break;
default :
mComputedCRC ^= inChar;
mBuffer[mIndex++] = inChar;
break;
}
}
else bufferFull();
break;
case CRCH:
tmp = hexToNum(inChar);
if (tmp != -1) {
mGotCRC |= (uint8_t)tmp << 4;
mState = CRCL;
}
else unexpectedChar();
break;
case CRCL:
tmp = hexToNum(inChar);
if (tmp != -1) {
mGotCRC |= (uint8_t)tmp;
mState = CRLFCR;
}
else unexpectedChar();
break;
case CRLFCR:
if (inChar == '\r') {
mState = CRLFLF;
}
else unexpectedChar();
break;
case CRLFLF:
if (inChar == '\n') {
if (mHandleCRC && (mGotCRC != mComputedCRC)) {
crcError();
}
else {
processSentence();
}
reset();
}
else unexpectedChar();
break;
default:
internalError();
break;
}
}
/*
* Returns the number of arguments discovered in a well formed sentence.
*/
uint8_t argCount()
{
return kSentenceMaxSize - mArgIndex - 1;
}
/*
* Returns one of the arguments. Different versions according to data type.
*/
bool getArg(uint8_t num, char &arg)
{
if (validArgNum(num)) {
uint8_t startPos = startArgPos(num);
uint8_t endPos = endArgPos(num);
arg = mBuffer[startPos];
return (endPos - startPos) == 1;
}
else return false;
}
bool getArg(uint8_t num, char *arg)
{
if (validArgNum(num)) {
uint8_t startPos = startArgPos(num);
uint8_t endPos = endArgPos(num);
{
NMEAParserStringify stfy(this, endPos);
strcpy(arg, &mBuffer[startPos]);
}
return true;
}
else return false;
}
#ifdef ARDUINO
bool getArg(uint8_t num, String &arg)
{
if (validArgNum(num)) {
uint8_t startPos = startArgPos(num);
uint8_t endPos = endArgPos(num);
{
NMEAParserStringify stfy(this, endPos);
arg = &mBuffer[startPos];
}
return true;
}
else return false;
}
#endif
bool getArg(uint8_t num, int &arg)
{
if (validArgNum(num)) {
uint8_t startPos = startArgPos(num);
uint8_t endPos = endArgPos(num);
{
NMEAParserStringify stfy(this, endPos);
arg = atoi(&mBuffer[startPos]);
}
return true;
}
else return false;
}
bool getArg(uint8_t num, float &arg)
{
if (validArgNum(num)) {
uint8_t startPos = startArgPos(num);
uint8_t endPos = endArgPos(num);
{
NMEAParserStringify stfy(this, endPos);
arg = atof(&mBuffer[startPos]);
}
return true;
}
else return false;
}
/*
* Returns the type of sentence.
*/
bool getType(char *arg)
{
if (mIndex > 0) {
uint8_t endPos = startArgPos(0);
{
NMEAParserStringify stfy(this, endPos);
strncpy(arg, mBuffer, 5);
arg[5] = '\0';
}
return true;
}
else return false;
}
#ifdef ARDUINO
bool getType(String &arg)
{
if (mIndex > 0) {
uint8_t endPos = startArgPos(0);
{
NMEAParserStringify stfy(this, endPos);
arg = mBuffer;
}
return true;
}
else return false;
}
#endif
bool getType(uint8_t inIndex, char &outTypeChar)
{
if (mIndex > 0) {
uint8_t endPos = startArgPos(0);
if (inIndex < endPos) {
outTypeChar = mBuffer[inIndex];
return true;
}
else return false;
}
else return false;
}
NMEA::ErrorCode error() {
return mError;
}
void setHandleCRC(bool inHandleCRC)
{
mHandleCRC = inHandleCRC;
}
#ifdef __amd64__
void printBuffer()
{
{
NMEAParserStringify stfy(this, startArgPos(0));
printf("%s\n", mBuffer);
}
for (uint8_t i = 0; i < argCount(); i++) {
uint8_t startPos = startArgPos(i);
uint8_t endPos = endArgPos(i);
{
NMEAParserStringify stfy(this, endPos);
printf("%s\n", &mBuffer[startPos]);
}
}
}
#endif
};
#endif

View File

@ -1,17 +0,0 @@
# Auto detect text files and perform LF normalization
* text=auto
# Custom for Visual Studio
*.cs diff=csharp
# Standard to msysgit
*.doc diff=astextplain
*.DOC diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot diff=astextplain
*.DOT diff=astextplain
*.pdf diff=astextplain
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain

View File

@ -1,3 +0,0 @@
# These are supported funding model platforms
custom: ['paypal.me/tilz0R']

View File

@ -1,385 +0,0 @@
#Build Keil files
*.rar
*.o
*.d
*.crf
*.htm
*.dep
*.map
*.bak
*.axf
*.lnp
*.lst
*.ini
*.scvd
*.iex
*.sct
*.MajerleT
*.tjuln
*.tilen
*.dbgconf
*.uvguix
*.uvoptx
*.__i
*.i
!docs/*.txt
RTE/
# IAR Settings
**/settings/*.crun
**/settings/*.dbgdt
**/settings/*.cspy
**/settings/*.cspy.*
**/settings/*.xcl
**/settings/*.dni
**/settings/*.wsdt
**/settings/*.wspos
# IAR Debug Exe
**/Exe/*.sim
# IAR Debug Obj
**/Obj/*.pbd
**/Obj/*.pbd.*
**/Obj/*.pbi
**/Obj/*.pbi.*
*.TMP
/docs_src/x_Doxyfile.doxy
.DS_Store
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
_build/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
**/Properties/launchSettings.json
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
*.out
*.sim
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# TypeScript v1 declaration files
typings/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
*.sln.iml
# CodeRush
.cr/
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
log_file.txt
.metadata/
.mxproject
.settings/
project.ioc
mx.scratch
*.tilen majerle
*.exe

View File

@ -1,5 +0,0 @@
" tree-specific vimrc to comply with project coding style
" see https://github.com/MaJerle/c-code-style
if &ft == "c" || &ft == "cpp"
setlocal shiftwidth=4 tabstop=4 softtabstop=4 expandtab autoindent cc=80 foldmethod=indent
endif

View File

@ -1,39 +0,0 @@
################################################################################
# Lightweight GPS (lwgps) CMake support
################################################################################
# The lwgps library can be configured with a lwgps_opts.h file.
# If such a file is used, the user should set the LWGPS_CONFIG_PATH path variable where
# the configuration file is located so that is is included properly.
#
# Other than that, only two steps are necessary to compile and link against LWGPS:
# 1. Use add_subdirectory to add the lwgps folder
# 2. Link against lwgps with target_link_libraries
################################################################################
cmake_minimum_required(VERSION 3.13)
set(LIB_LWGPS_NAME lwgps)
add_library(${LIB_LWGPS_NAME})
add_subdirectory(${LIB_LWGPS_NAME})
add_subdirectory(examples)
# The project CMakeLists can set a LWGPS_CONFIG_PATH path including the lwgps_opts.h file
# and add it.
if(NOT LWGPS_CONFIG_PATH)
message(STATUS "Lightweight GPS configuration path not set.")
endif()
# Extract the absolute path of the provided configuration path
if(IS_ABSOLUTE ${LWGPS_CONFIG_PATH})
set(LWGPS_CONFIG_PATH_ABSOLUTE ${LWGPS_CONFIG_PATH})
else()
get_filename_component(LWGPS_CONFIG_PATH_ABSOLUTE
${LWGPS_CONFIG_PATH} REALPATH BASE_DIR ${CMAKE_SOURCE_DIR}
)
endif()
target_include_directories(${LIB_LWGPS_NAME} PRIVATE
${LWGPS_CONFIG_PATH_ABSOLUTE}
)

View File

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2020 Tilen MAJERLE
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,40 +0,0 @@
# Lightweight GPS NMEA parser
Platform independent GPS NMEA parser for embedded systems.
<h3>Read first: <a href="http://docs.majerle.eu/projects/lwgps/">Documentation</a></h3>
## Features
* Written in ANSI C99
* Platform independent, easy to use
* Built-in support for 4 GPS statements
* ``GPGGA`` or ``GNGGA``: GPS fix data
* ``GPGSA`` or ``GNGSA``: GPS active satellites and dillusion of position
* ``GPGSV`` or ``GNGSV``: List of satellites in view zone
* ``GPRMC`` or ``GNRMC``: Recommended minimum specific GPS/Transit data
* Optional ``float`` or ``double`` floating point units
* Low-level layer is separated from application layer, thus allows you to add custom communication with GPS device
* Works with operating systems
* Works with different communication interfaces
* User friendly MIT license
## Contribute
Fresh contributions are always welcome. Simple instructions to proceed::
1. Fork Github repository
2. Respect [C style & coding rules](https://github.com/MaJerle/c-code-style) used by the library
3. Create a pull request to develop branch with new features or bug fixes
Alternatively you may:
1. Report a bug
2. Ask for a feature request
## Test
To build the code and run basic tests on your host::
cd examples
make test

View File

@ -1,31 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.28803.452
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lwgps_dev", "lwgps_dev.vcxproj", "{C7C465FB-17B3-4226-BBD5-E79C1B3796C6}"
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
{C7C465FB-17B3-4226-BBD5-E79C1B3796C6}.Debug|x64.ActiveCfg = Debug|Win32
{C7C465FB-17B3-4226-BBD5-E79C1B3796C6}.Debug|x64.Build.0 = Debug|Win32
{C7C465FB-17B3-4226-BBD5-E79C1B3796C6}.Debug|x86.ActiveCfg = Debug|Win32
{C7C465FB-17B3-4226-BBD5-E79C1B3796C6}.Debug|x86.Build.0 = Debug|Win32
{C7C465FB-17B3-4226-BBD5-E79C1B3796C6}.Release|x64.ActiveCfg = Release|x64
{C7C465FB-17B3-4226-BBD5-E79C1B3796C6}.Release|x64.Build.0 = Release|x64
{C7C465FB-17B3-4226-BBD5-E79C1B3796C6}.Release|x86.ActiveCfg = Release|Win32
{C7C465FB-17B3-4226-BBD5-E79C1B3796C6}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C58E98E3-45C5-48F1-A7AF-BCFEC103DD09}
EndGlobalSection
EndGlobal

View File

@ -1,149 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.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="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{C7C465FB-17B3-4226-BBD5-E79C1B3796C6}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>LwGPS</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</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)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<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|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="Shared">
</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 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 Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<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|x64'">
<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>.;..\..\lwgps\src\include;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\examples\test_code.c" />
<ClCompile Include="..\..\lwgps\src\lwgps\lwgps.c" />
<ClCompile Include="main.c" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -1,23 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Source Files\LwGPS">
<UniqueIdentifier>{d2afbed4-545f-40e7-bf68-d835c5948bcc}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\lwgps\src\lwgps\lwgps.c">
<Filter>Source Files\LwGPS</Filter>
</ClCompile>
<ClCompile Include="main.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\examples\test_code.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -1,44 +0,0 @@
/**
* \file lwgps_opts_template.h
* \brief LwGPS configuration file
*/
/*
* Copyright (c) 2020 Tilen MAJERLE
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
* AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* This file is part of LwGPS - Lightweight GPS NMEA parser library.
*
* Author: Tilen MAJERLE <tilen@majerle.eu>
* Version: $2.1.0$
*/
#ifndef LWGPS_HDR_OPTS_H
#define LWGPS_HDR_OPTS_H
/* Rename this file to "lwgps_opts.h" for your application */
/*
* Open "include/lwgps/lwgps_opt.h" and
* copy & replace here settings you want to change values
*/
#endif /* LWGPS_HDR_OPTS_H */

View File

@ -1,32 +0,0 @@
/*
* This example uses direct processing function,
* to process dummy NMEA data from GPS receiver
*/
#include <string.h>
#include <stdio.h>
#include <math.h>
#include "lwgps/lwgps.h"
/* External function */
extern void run_tests();
int
main() {
lwgps_float_t distance, bearing;
run_tests();
/* Calculate distance and bearing */
lwgps_distance_bearing(40.6, -73.7, 48.3, 11.7, &distance, &bearing);
printf("Distance: %lf meters\r\n", (double)distance);
printf("Bearing: %lf degrees\r\n", (double)bearing);
lwgps_distance_bearing(48.3, 11.7, 40.6, -73.7, &distance, &bearing);
printf("Distance: %lf meters\r\n", (double)distance);
printf("Bearing: %lf degrees\r\n", (double)bearing);
return 0;
}
/* JFK: 40.642569, -73.783790 */
/* Munich: 48.353962, 11.775114 */

View File

@ -1,20 +0,0 @@
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = .
BUILDDIR = _build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

View File

@ -1,6 +0,0 @@
.. _api_lwgps:
LwGPS
=====
.. doxygengroup:: LWGPS

View File

@ -1,12 +0,0 @@
.. _api_lwgps_opt:
Configuration
=============
This is the default configuration of the middleware.
When any of the settings shall be modified, it shall be done in dedicated application config ``lwgps_opts.h`` file.
.. note::
Check :ref:`getting_started` to create configuration file.
.. doxygengroup:: LWGPS_OPT

View File

@ -1,13 +0,0 @@
.. _api_reference:
API reference
=============
List of all the modules:
.. toctree::
:maxdepth: 2
:glob:
*

View File

@ -1,129 +0,0 @@
# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
# -- Path setup --------------------------------------------------------------
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
# import os
# import sys
# sys.path.insert(0, os.path.abspath('.'))
from sphinx.builders.html import StandaloneHTMLBuilder
import subprocess, os
# Run doxygen first
# read_the_docs_build = os.environ.get('READTHEDOCS', None) == 'True'
# if read_the_docs_build:
subprocess.call('doxygen doxyfile.doxy', shell=True)
# -- Project information -----------------------------------------------------
project = 'LwGPS'
copyright = '2020, Tilen MAJERLE'
author = 'Tilen MAJERLE'
# The full version, including alpha/beta/rc tags
version = 'v2.1.0'
# Try to get branch at which this is running
# and try to determine which version to display in sphinx
git_branch = ''
res = os.popen('git branch').read().strip()
for line in res.split("\n"):
if line[0] == '*':
git_branch = line[1:].strip()
# Decision for display version
try:
if git_branch.index('develop') >= 0:
version = "latest-develop"
except Exception:
print("Exception for index check")
# For debugging purpose
print("GIT BRANCH: " + git_branch)
print("VERSION: " + version)
# -- General configuration ---------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.intersphinx',
'sphinx.ext.autosectionlabel',
'sphinx.ext.todo',
'sphinx.ext.coverage',
'sphinx.ext.mathjax',
'sphinx.ext.ifconfig',
'sphinx.ext.viewcode',
'sphinx_sitemap',
'breathe',
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['templates']
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
highlight_language = 'c'
# -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'sphinx_rtd_theme'
html_theme_options = {
'canonical_url': '',
'analytics_id': '', # Provided by Google in your dashboard
'display_version': True,
'prev_next_buttons_location': 'bottom',
'style_external_links': False,
'logo_only': False,
# Toc options
'collapse_navigation': True,
'sticky_navigation': True,
'navigation_depth': 4,
'includehidden': True,
'titles_only': False
}
html_logo = 'static/images/logo.svg'
github_url = 'https://github.com/MaJerle/lwgps'
html_baseurl = 'https://docs.majerle.eu/projects/lwgps/'
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['static']
html_css_files = [
'css/common.css',
'css/custom.css',
]
html_js_files = [
'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css'
]
master_doc = 'index'
#
# Breathe configuration
#
#
#
breathe_projects = {
"lwgps": "_build/xml/"
}
breathe_default_project = "lwgps"
breathe_default_members = ('members', 'undoc-members')

File diff suppressed because it is too large Load Diff

View File

@ -1,47 +0,0 @@
.. _examples:
Examples and demos
==================
There are several basic examples provided with the library.
Parse block of data
^^^^^^^^^^^^^^^^^^^
In this example, block of data is prepared as big string array and sent to processing function in single shot.
Application can then check if GPS signal has been detected as valid and use other data accordingly.
.. literalinclude:: ../../examples/example.c
:language: c
:linenos:
:caption: Minimum example code
Parse received data from interrupt/DMA
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Second example is a typical use case with interrupts on embedded systems.
For each received character, application uses ``ringbuff`` as intermediate buffer.
Data are later processed outside interrupt context.
.. note::
For the sake of this example, application *implements* interrupts as function call in *while loop*.
.. literalinclude:: ../../examples/example_buff.c
:language: c
:linenos:
:caption: Example of buffer
Distance and bearing
^^^^^^^^^^^^^^^^^^^^
Library provides calculation of distance and bearing between ``2`` coordinates on earth.
This is useful if used with autonomnous devices to understand in which direction
device has to move to reach end point while knowing start coordinate.
.. literalinclude:: ../../examples/example_dist_bear.c
:language: c
:linenos:
:caption: Distance and bearing calculation
.. toctree::
:maxdepth: 2

View File

@ -1,100 +0,0 @@
.. _getting_started:
Getting started
===============
.. _download_library:
Download library
^^^^^^^^^^^^^^^^
Library is primarly hosted on `Github <https://github.com/MaJerle/lwgps>`_.
* Download latest release from `releases area <https://github.com/MaJerle/lwgps/releases>`_ on Github
* Clone `develop` branch for latest development
Download from releases
**********************
All releases are available on Github `releases area <https://github.com/MaJerle/lwgps/releases>`_.
Clone from Github
*****************
First-time clone
""""""""""""""""
* Download and install ``git`` if not already
* Open console and navigate to path in the system to clone repository to. Use command ``cd your_path``
* Clone repository with one of available ``3`` options
* Run ``git clone --recurse-submodules https://github.com/MaJerle/lwgps`` command to clone entire repository, including submodules
* Run ``git clone --recurse-submodules --branch develop https://github.com/MaJerle/lwgps`` to clone `development` branch, including submodules
* Run ``git clone --recurse-submodules --branch master https://github.com/MaJerle/lwgps`` to clone `latest stable` branch, including submodules
* Navigate to ``examples`` directory and run favourite example
Update cloned to latest version
"""""""""""""""""""""""""""""""
* Open console and navigate to path in the system where your resources repository is. Use command ``cd your_path``
* Run ``git pull origin master --recurse-submodules`` command to pull latest changes and to fetch latest changes from submodules
* Run ``git submodule foreach git pull origin master`` to update & merge all submodules
.. note::
This is preferred option to use when you want to evaluate library and run prepared examples.
Repository consists of multiple submodules which can be automatically downloaded when cloning and pulling changes from root repository.
Add library to project - Generic
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
At this point it is assumed that you have successfully download library, either cloned it or from releases page.
* Copy ``lwgps`` folder to your project
* Add ``lwgps/src/include`` folder to `include path` of your toolchain
* Add source files from ``lwgps/src/`` folder to toolchain build
* Copy ``lwgps/src/include/lwgps/lwgps_opts_template.h`` to project folder and rename it to ``lwgps_opts.h``
* Build the project
Add library to project - CMake
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Including the library with CMake is very easy.
* Add the ``lwgps`` folder with ``add_subdirectory``
* Copy ``lwgps/src/include/lwgps/lwgps_opts_template.h`` to the project folder and rename it
to ``lwgps_opts.h``
* Set the ``LWGPS_CONFIG_PATH`` path variable containing the ``lwgps_opts.h`` file
in the project ``CMakeLists.txt``
* Link your project against the ``lwgps`` library with ``target_link_libraries``
* The include directory should be set automatically by CMake
Configuration file
^^^^^^^^^^^^^^^^^^
Library comes with template config file, which can be modified according to needs.
This file shall be named ``lwgps_opts.h`` and its default template looks like the one below.
.. note::
Default configuration template file location: ``lwgps/src/include/lwgps/lwgps_opts_template.h``.
File must be renamed to ``lwgps_opts.h`` first and then copied to the project directory (or simply renamed in-place) where compiler
include paths have access to it by using ``#include "lwgps_opts.h"``.
.. tip::
Check :ref:`api_lwgps_opt` section for possible configuration settings
.. literalinclude:: ../../lwgps/src/include/lwgps/lwgps_opts_template.h
:language: c
:linenos:
:caption: Template options file
Minimal example code
^^^^^^^^^^^^^^^^^^^^
Run below example to test and verify library
.. literalinclude:: ../../examples/example.c
:language: c
:linenos:
:caption: Test verification code

View File

@ -1,71 +0,0 @@
LwGPS |version| documentation
=============================
Welcome to the documentation for version |version|.
LwGPS is lightweight, platform independent library to parse NMEA statements from GPS receivers. It is highly optimized for embedded systems.
.. image:: static/images/logo.svg
:align: center
.. rst-class:: center
.. rst-class:: index_links
:ref:`download_library` :ref:`getting_started` `Open Github <https://github.com/MaJerle/lwgps>`_ `Donate <https://paypal.me/tilz0R>`_
Features
^^^^^^^^
* Written in ANSI C99
* Platform independent, easy to use
* Built-in support for 4 GPS statements
* ``GPGGA`` or ``GNGGA``: GPS fix data
* ``GPGSA`` or ``GNGSA``: GPS active satellites and dillusion of position
* ``GPGSV`` or ``GNGSV``: List of satellites in view zone
* ``GPRMC`` or ``GNRMC``: Recommended minimum specific GPS/Transit data
* Optional ``float`` or ``double`` floating point units
* Low-level layer is separated from application layer, thus allows you to add custom communication with GPS device
* Works with operating systems
* Works with different communication interfaces
* User friendly MIT license
Requirements
^^^^^^^^^^^^
* C compiler
* Driver for receiving data from GPS receiver
* Few *kB* of non-volatile memory
Contribute
^^^^^^^^^^
Fresh contributions are always welcome. Simple instructions to proceed:
#. Fork Github repository
#. Respect `C style & coding rules <https://github.com/MaJerle/c-code-style>`_ used by the library
#. Create a pull request to ``develop`` branch with new features or bug fixes
Alternatively you may:
#. Report a bug
#. Ask for a feature request
License
^^^^^^^
.. literalinclude:: ../LICENSE
Table of contents
^^^^^^^^^^^^^^^^^
.. toctree::
:maxdepth: 2
self
get-started/index
user-manual/index
api-reference/index
examples/index

View File

@ -1,35 +0,0 @@
@ECHO OFF
pushd %~dp0
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=.
set BUILDDIR=_build
if "%1" == "" goto help
%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.http://sphinx-doc.org/
exit /b 1
)
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
goto end
:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
:end
popd

View File

@ -1,8 +0,0 @@
breathe>=4.9.1
colorama
docutils>=0.14
sphinx>=2.0.1
sphinx_rtd_theme
sphinx-tabs
sphinxcontrib-svg2pdfconverter
sphinx-sitemap

View File

@ -1,64 +0,0 @@
/* Center aligned text */
.center {
text-align: center;
}
/* Paragraph with main links on index page */
.index-links {
text-align: center;
margin-top: 10px;
}
.index-links a {
display: inline-block;
border: 1px solid #0E4263;
padding: 5px 20px;
margin: 2px 5px;
background: #2980B9;
border-radius: 4px;
color: #FFFFFF;
}
.index-links a:hover, .index-links a:active {
background: #0E4263;
}
/* Table header p w/0 margin */
.index-links a table thead th {
vertical-align: middle;
}
table thead th p {
margin: 0;
}
.table-nowrap td {
white-space: normal !important;
}
/* Breathe output changes */
.breathe-sectiondef.container {
background: #f9f9f9;
padding: 10px;
margin-bottom: 10px;
border: 1px solid #efefef;
}
.breathe-sectiondef.container .breathe-sectiondef-title {
background: #2980b9;
color: #FFFFFF;
padding: 4px;
margin: -10px -10px 0 -10px;
}
.breathe-sectiondef.container .function,
.breathe-sectiondef.container .member,
.breathe-sectiondef.container .class,
.breathe-sectiondef.container .type {
border-bottom: 1px solid #efefef;
}
.breathe-sectiondef.container .function:last-child,
.breathe-sectiondef.container .member:last-child,
.breathe-sectiondef.container .class:last-child,
.breathe-sectiondef.container .type:last-child {
border-bottom: none;
margin-bottom: 0;
}
/*# sourceMappingURL=common.css.map */

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 30 KiB

View File

@ -1 +0,0 @@
<mxfile modified="2019-03-17T18:59:38.494Z" host="www.draw.io" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/7.8.7 Chrome/58.0.3029.110 Electron/1.7.5 Safari/537.36" version="10.4.9" etag="K-7s2_uXvQkXh2xx6gpu" type="device"><diagram id="7c61e978-b8e5-555b-ca9a-a1ec85429089" name="Page-1">7Ztfb5swFMU/TR4n2RgIPC5d1z5s0rR06rMDJlgBHDlOk+zTz4BpSM2kaupyq6vmITXXf8C/wwPn0MzYTX2803xbfle5qGYByY8z9mUWBDQkzP5pK6e+ktB5X1hrmbtB58JS/hauSFx1L3OxuxholKqM3F4WM9U0IjMXNa61OlwOK1R1edYtXwuvsMx45VcfZW5KV6Vxeu64F3JdulMngdvfimebtVb7xp1vFrCi+/TdNR/WchvdlTxXh1GJ3c7YjVbK9K36eCOqlu2ArZ/39S+9z9etRWNeMyHoJzzxau+2vnxwV2ZOA41uP6KdQWZscSilEcstz9reg9Xf1kpTV/aI2mbFV6JaPGO4UZXStqtRjR2/KFRjnNw0cMfDEMuKMWI/tu7vw23tSWgjjqOS29edULUw+mSHuF4W9TPcLRikDvnhLChzpXIkZehq3N1C6+eFzxhtw5Gcpso8qiuChGoMRzX0qVIkVFM4qrFPNUBClQZwWOc+VoYFawSHNfGxhliwJnBYUx9rhASrvV3BsA6Ps2OuMRauISBX6nOdY+E6B+Q6YQd+IOHKCCBX3xDgsVkJgeM6YQmwGK2QAnKNfK5YrFYYAnJFbLbCOSBXxG4rIoBcEdutiAFyRey3ohiO65CqY/RbUQrIFbHfigNAroj9VhwBcvX91uJkhK2oxn79+vzTui9SiafutWU3gKykGfrpp0epxXlEXNlrW6y0ba3b1oOsZbNuz7frkbTblvVWacMtr8BeH7l/tF+Gb0Q7JOPdcqpoxxl/QSSSv3jjxtiU4v9Lct8Kfkh+ffd/Xc19m7osrSKtDLIW7xN6IatqVM8jkeShre+MVhsx6kmsh4njN5LpFS/Dhzx3rFLyFir5phdN+JVAPjxMmF4s4VcC+fAwYXqxhF8JYFg79ZIRS/iVAoa1w7oYw68UMKxlE6YXS/iVAoa1zDe9aMIvSgDTWjbxb4dY0i9KAONaNvGaEUv8RQlgXssmDByW/IsSwMCW+Z7rIw25vh28ahrCfD/4TXUq9WFIK8pOtS0iGyO03m87wa0IJJdFIbqNt5rtNoO0K9HrLI4i2xurx7tU7mWkwkVSZFORSpwlYlW8Ub79CitFwwmt/yFTsYfnn4R0faPf3bDbPw==</diagram></mxfile>

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 8.8 KiB

View File

@ -1 +0,0 @@
<mxfile modified="2019-03-17T18:28:51.770Z" host="www.draw.io" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/7.8.7 Chrome/58.0.3029.110 Electron/1.7.5 Safari/537.36" etag="Lw4IH-C7q6o9UbXhWxg1" version="10.4.9" type="device"><diagram id="oLfy0yLwNNLmw2rXhwVB" name="Page-1">7VpNc9owEP01HMnYkmXsYyBpy6Fpm5CU9tIRtjCaGIsRopD++sq2DJZlkuCYkHaSQ0a7+rL2vd2VNunAwXzzkePF7DMLSdwBVrjpwIsOAD2/J3+niodcgaCfKyJOw1xl7xQ39A9R45RyRUOy1MYJxmJBF7oyYElCAqHpMOdsrQ+bsljfdIEjYihuAhyb2u80FDOltV1/1/GJ0GimtvaAOu8cF4OtXLGc4ZCtSyp42YEDzpjIW/PNgMSp6Qqz5PM+7OndfhgniXjOhC+Mrn6Ovv2KRugD/0a7v4bTUVet8hvHK3Xgz4Nbqfhy3QFuLNftT7hsRWnr9qbfSfdw8Xwhxay3uxWzIbL/9vx6pA4sHgorrmdUkJsFDlJ5LXkix87EPJaSLZt4ucixm9INkZ/bn9I4HrCY8Ww6nHoBCQKpXwrO7kmpZ+IhB1nZzlVrFEcjXJBNSaWs85GwORH8QQ4pei2FlGIq8JS8LgFfjJmVMN8qsSJbtF17h4dsKEgOgMcz4DFMS5LwPOW5lBKWEN2wZEPFuNT+IdvWmfStJibOewovAI8ZfclWPCBP846EmveZ0JRMj2osX+g4ibGgv3WfrUND7fCVUfnFO+Q9pCEPLaQvkZ9HzSr7WGWhrbPvW0hgHhFhLJSRY3vs5nyxTX82CMPZKglTL7tIQX3CM0/iiNKhdEe0TUcEj7ChdTcsNmvuh4n8jHHmfKgQfzQ28QGOmPPtGYx5I55YdSDgVzBt6onAfV1PBH5LoVsxpgjejQiTzr7YqOmZ8KCEA6hUYchzgvxpqWT7Zz3kucByPd9FyAY6ISxwBm0LOo68sqXDvHaIZnvgVYkGzdh0NxiYtzeDfTIYC51y+wm0j3I4plEidYEkC5Gd/TTIU3l7PlcdcxqG6Ya1eUbPRC0kDtvX87jdMxNHHePAsRIHfEY+fjQKHDU5vNWY7zWM+Q56YqFjuyJ4R/tgtCFq6a796mjDljK8/jjrvT/Oqo8zHWcHtnQlNJh3bMIggzB29/vw+tJM1heXd8NBjd4g2KGFlRhPSNzHwX2UJd+CSYqcp3ntuRU/tsyk7dbQy20haUcArybjcLwZXlm3V5zeB5NJ97+FycCkBrm9MEHnjcHkvsNUA5NTzYqnhqn3wixpJrbHiimZsHvqZlLx1m2Kh/HwbVJnyYP/yS5dfktXbGhXK6VHu3TVsumlBfF/gU2nIgnstUWS6kLIP/NKP/6rUualhbhTUmZXIUnXVoYinEqbEJ4mKppEnXL55O2y68nHeeNX/knZVfMXl9FYyl+HVwbNzIpb+/WzF10ebKRHd1DU00oUcZBJkTbqZ/XWNSsq1/+NdaFzNOtKcfePBTnVd/+cAS//Ag==</diagram></mxfile>

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 11 KiB

View File

@ -1 +0,0 @@
<mxfile modified="2019-03-17T18:24:31.030Z" host="www.draw.io" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/7.8.7 Chrome/58.0.3029.110 Electron/1.7.5 Safari/537.36" version="10.4.9" etag="GRhl1qzylYBum7KQYHDi" type="device"><diagram id="85174833-9250-f023-2320-fd733ea284ef" name="Page-1">7Vxdd6I6FP01PraLBMLHY9V2pg8zd1Y7HWceKUTNGgQH01Hvr78BgkKigsiHt8WXkgMEOHvvk5ND6EAdLTafQns5/xK42BtAxd0M1PEAQqApKvsTWbaJxQRGYpiFxOUH7Q3P5F+cGBE3vhEXr3LH0SDwKFnmjU7g+9ihOZsdhsE6f9g08PIXXdozLBmeHduTrRPi0jl/CKTs7Z8xmc3TKwOF73m1nd+zMHjz+fUGUJ3Gv2T3wk774sev5rYbrDMm9X6gjsIgoMnWYjPCXuTa1GvJeQ9H9u7uO8Q+LXOCNRk++KOvD5//jP3J2Jj88TXnBqT9/LW9N5w+SHy7dJu6CPvuXeRp1vIDnxmHc7rwWAuwTbwh9CfbVm4Rb/2KWmx7SjxvFHhBGPeiTk0HOw6zr2gY/MaZPa8m0pDCzx5v+OlxY8sbyTkpQMx3w+QusSuhu/cH2HmZkRcHC0zDLTtkvYc5RXmeQTi1hdizKfmb797mbJvtuttd4VtA2IWhwoUBLU5wLgtgqvkuVsFb6GB+Vha3oo4QyndE7XCGqdQR28g89t4U0+IMiiBdYsiX0Qsz/PM0gLrHvDZ8DdnWLNp6eWbAMAfq9mLJmvHem10zPoTtf7l7+i6xbD0nFD8vbSdqr1msyfPMXi0T+U/JBruV6MWfA4cUb84lDT9BwAIanCwZTu0CRJZUO+MhAuUQOxseoyYBg6x8byGq5OLqOmU3HAuikIldCRqYSh57S9BhaUGr6HRHTQvaLGZMPK5FMoujb4E0O1Ei1MT4KksRnmBD7ULUlXc+kpZRqNnpkIu0WwOZOlR009IRAjDPEAPeqkBRNc2E8WFmRf0icUCGrepXl1O2H6ORPBZL7GNio3nKHSfQMcrZHpn5zOYwbmC2cxiJmLB0+o7vWBDXjS54MGjkw0oTUUCTo4B+gHGwsSigNTIcG/1wLA7HRh55TYS0rJxVkO9I1dodjnUkMQbcTB6f7mVFj+9/PI4O2CWGnZtLe/Yr9oa7CW1KJc7OTsZ3VciSwIFU+5Cy9caULc+DepyY7sC14VQivT0ZgeWgyVwRbjOpWdT8lcboqLFPteJWmmtVBaRMeE6iUmFc6So8q7owyRHz7tLh2RKmXYbQUdPh2foAdOqKJZpWE0ukjqB1a2Z+VqucMeQM/ftP1v72+FXijpyUX1mKDZAgQBNJAT71fisptgEl7z69G+/u0p6uvGvJ3j0v3rU5S+ms0qAJqInl3dK1BKEjKS1qOFJZao/22WhXr/yibiu/1qXFiQ+BtjDxrK5tsc7ftrblwkKPdnEArkvbYkdNoy2XJ06h7Xj2akWcDwi4iJNZ19AtdtQ04HW9+E1fESWV5vTd0+G3R1dWggaKcU1cqj5UFJGyYS4Bpc8MSsAt1rQq54FGt3kgUPrUoALcVYtTkrrFjhqH+7zcoIf7MnUX8aZxuEtkBjQktj87WufKYO+SEDuUBFFtjLkgQqJGPtT69l8F5dYAAeU4OS4qngFw6XLaD6G0oqlS5cCqtqy0dIVRD/cpuIWFk9WzZHEFZssFFQD6aun5cFcfR8XF1m1nyaCfFJWA26hrDixOilpXdz8pqqDuymO3qO6W66UA9AXTcoiLQFUumIrUabvIBfqKKXNCt0v0rbpGiyJWNk6mEssM38ck27y6SXaJJXn/gw+YBL92/gETSK/WJ0DnDIe1JUBtFy/gpbNZGbz3t0JVQqm2FaptV4VhP5stsWy96GOgql8V1Qc3a+7/aURy+P4fc6j3/wE=</diagram></mxfile>

View File

@ -1 +0,0 @@
<mxfile host="Electron" modified="2020-12-05T00:17:49.072Z" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/12.3.2 Chrome/78.0.3904.113 Electron/7.1.2 Safari/537.36" etag="J3RPSOEyywhlMJWRwdgH" version="12.3.2" type="device" pages="1"><diagram id="Wsjaadh77UIxB9X1bxos" name="Page-1">jZJNb8MgDIZ/TY6VkpB067Vd10nrqkk59IyCG1AhRJSMdL9+ZDH5UDVpJ/BjY+B9HZGd6g6GNvxDM5BRGrMuIi9RmibxU+aXntwHssnzAVRGMCyaQCG+IZxE2goGt0Wh1Vpa0SxhqesaSrtg1BjtlmUXLZe3NrSCB1CUVD7Ss2CWD/Q5jyf+BqLi4eYkxoyioRjBjVOm3QyRfUR2Rms77FS3A9mLF3QZzr3+kR0fZqC2/zlwWrEMNsodT6rdZpv3izwnK+zyRWWLHz66w2eBL7b3IIPRbc2g75REZOu4sFA0tOyzzhvvGbdKYvpmjb6Ocq09uejaorekj0ctYh88fiS8CoyFbobwYwfQCqy5+xLMkgynCqcsDbGbPEvWaASf+RV8pDgm1dh6UtJvUMwQTqb95majT/Y/</diagram></mxfile>

View File

@ -1,3 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="166px" height="56px" viewBox="-0.5 -0.5 166 56" content="&lt;mxfile host=&quot;Electron&quot; modified=&quot;2020-12-05T00:17:54.452Z&quot; agent=&quot;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/12.3.2 Chrome/78.0.3904.113 Electron/7.1.2 Safari/537.36&quot; etag=&quot;QrTFHCUJlsVW3_ulGR16&quot; version=&quot;12.3.2&quot; type=&quot;device&quot; pages=&quot;1&quot;&gt;&lt;diagram id=&quot;Wsjaadh77UIxB9X1bxos&quot; name=&quot;Page-1&quot;&gt;jZJNb8MgDIZ/TY6VkpB067Vd10nrqkk59IyCG1AhRJSMdL9+ZDH5UDVpJ/BjY+B9HZGd6g6GNvxDM5BRGrMuIi9RmibxU+aXntwHssnzAVRGMCyaQCG+IZxE2goGt0Wh1Vpa0SxhqesaSrtg1BjtlmUXLZe3NrSCB1CUVD7Ss2CWD/Q5jyf+BqLi4eYkxoyioRjBjVOm3QyRfUR2Rms77FS3A9mLF3QZzr3+kR0fZqC2/zlwWrEMNsodT6rdZpv3izwnK+zyRWWLHz66w2eBL7b3IIPRbc2g75REZOu4sFA0tOyzzhvvGbdKYvpmjb6Ocq09uejaorekj0ctYh88fiS8CoyFbobwYwfQCqy5+xLMkgynCqcsDbGbPEvWaASf+RV8pDgm1dh6UtJvUMwQTqb95majT/Y/&lt;/diagram&gt;&lt;/mxfile&gt;"><defs/><g><rect x="3" y="3" width="160" height="50" rx="7.5" ry="7.5" fill="#ffffff" stroke="#000000" stroke-width="6" pointer-events="all"/><g transform="translate(21.5,6.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="122" height="41" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 36px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 123px; white-space: nowrap; overflow-wrap: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;white-space:normal;">LwGPS</div></div></foreignObject><text x="61" y="39" fill="#000000" text-anchor="middle" font-size="36px" font-family="Helvetica">LwGPS</text></switch></g></g></svg>

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

View File

@ -1,15 +0,0 @@
.. _float_double:
Float/double precision
======================
With configuration of ``GSM_CFG_DOUBLE``, it is possible to enable ``double`` floating point precision.
All floating point variables are then configured in *double precision*.
When configuration is set to ``0``, floating point variables are configured in *single precision* format.
.. note::
Single precision uses less memory in application. As a drawback, application may be a subject of data loss at latter digits.
.. toctree::
:maxdepth: 2

View File

@ -1,38 +0,0 @@
.. _how_it_works:
How it works
============
LwGPS parses raw data formatted as NMEA 0183 statements from GPS receivers. It supports up to ``4`` different statements:
* ``GPGGA`` or ``GNGGA``: GPS fix data
* ``GPGSA`` or ``GNGSA``: GPS active satellites and dillusion of position
* ``GPGSV`` or ``GNGSV``: List of satellites in view zone
* ``GPRMC`` or ``GNRMC``: Recommended minimum specific GPS/Transit data
.. tip::
By changing different configuration options, it is possible to disable some statements.
Check :ref:`api_lwgps_opt` for more information.
Application must assure to properly receive data from GPS receiver.
Usually GPS receivers communicate with host embedded system with UART protocol and output directly formatted NMEA 0183 statements.
.. note::
Application must take care of properly receive data from GPS.
Application must use :cpp:func:`lwgps_process` function for data processing. Function will:
* Detect statement type, such as *GPGGA* or *GPGSV*
* Parse all the terms of specific statement
* Check valid CRC after each statement
Programmer's model is as following:
* Application receives data from GPS receiver
* Application sends data to :cpp:func:`lwgps_process` function
* Application uses processed data to display altitude, latitude, longitude, and other parameters
Check :ref:`examples` for typical example
.. toctree::
:maxdepth: 2

View File

@ -1,12 +0,0 @@
.. _um:
User manual
===========
.. toctree::
:maxdepth: 2
how-it-works
float-double
thread-safety
tests

View File

@ -1,14 +0,0 @@
.. _tests:
Tests during development
========================
During the development, test check is performed to validate raw NMEA input data vs expected result.
.. literalinclude:: ../../examples/test_code.c
:language: c
:linenos:
:caption: Test code for development
.. toctree::
:maxdepth: 2

View File

@ -1,16 +0,0 @@
.. _thread_safety:
Thread safety
=============
Library tends to be as simple as possible.
No specific features have been implemented for thread safety.
When library is using multi-thread environment and if multi threads tend to access to shared resources,
user must resolve it with care, using mutual exclusion.
.. tip::
When single thread is dedicated for GPS processing, no special mutual exclusion is necessary.
.. toctree::
:maxdepth: 2

View File

@ -1,40 +0,0 @@
# gps-nmea-parser examples and tests Makefile
# (c) 2020 Sirio, Balmelli Analog & Digital
TARGETS := \
example.exe \
example_stat.exe \
test_code.exe \
test_time.exe
.PHONY: all clean test
all: $(TARGETS)
clean:
@rm -fv $(TARGETS)
test: $(TARGETS)
@for tgt in $(TARGETS); do \
echo "\n--- $$tgt ---"; \
./$$tgt; \
done
CFLAGS += -Wall \
-DDEBUG=1 \
-I../lwgps/src/include \
-I./
example.exe: example.c
example_stat.exe: CFLAGS += -DLWGPS_CFG_STATUS=1
example_stat.exe: example_stat.c
test_code.exe: ../lwgps/src/lwgps/lwgps.c test_code.c ../dev/VisualStudio/main.c
test_time.exe: CFLAGS += \
-DLWGPS_CFG_STATEMENT_PUBX=1 \
-DLWGPS_CFG_STATEMENT_PUBX_TIME=1
test_time.exe: ../lwgps/src/lwgps/lwgps.c test_time.c ../dev/VisualStudio/main.c
$(TARGETS) : ../lwgps/src/lwgps/lwgps.c
$(CC) -o $@ $(CFLAGS) $^

View File

@ -1,47 +0,0 @@
/**
* This example uses direct processing function
* to process dummy NMEA data from GPS receiver
*/
#include <string.h>
#include <stdio.h>
#include "lwgps/lwgps.h"
/* GPS handle */
lwgps_t hgps;
/**
* \brief Dummy data from GPS receiver
*/
const char
gps_rx_data[] = ""
"$GPRMC,183729,A,3907.356,N,12102.482,W,000.0,360.0,080301,015.5,E*6F\r\n"
"$GPRMB,A,,,,,,,,,,,,V*71\r\n"
"$GPGGA,183730,3907.356,N,12102.482,W,1,05,1.6,646.4,M,-24.1,M,,*75\r\n"
"$GPGSA,A,3,02,,,07,,09,24,26,,,,,1.6,1.6,1.0*3D\r\n"
"$GPGSV,2,1,08,02,43,088,38,04,42,145,00,05,11,291,00,07,60,043,35*71\r\n"
"$GPGSV,2,2,08,08,02,145,00,09,46,303,47,24,16,178,32,26,18,231,43*77\r\n"
"$PGRME,22.0,M,52.9,M,51.0,M*14\r\n"
"$GPGLL,3907.360,N,12102.481,W,183730,A*33\r\n"
"$PGRMZ,2062,f,3*2D\r\n"
"$PGRMM,WGS84*06\r\n"
"$GPBOD,,T,,M,,*47\r\n"
"$GPRTE,1,1,c,0*07\r\n"
"$GPRMC,183731,A,3907.482,N,12102.436,W,000.0,360.0,080301,015.5,E*67\r\n"
"$GPRMB,A,,,,,,,,,,,,V*71\r\n";
int
main() {
/* Init GPS */
lwgps_init(&hgps);
/* Process all input data */
lwgps_process(&hgps, gps_rx_data, strlen(gps_rx_data));
/* Print messages */
printf("Valid status: %d\r\n", hgps.is_valid);
printf("Latitude: %f degrees\r\n", hgps.latitude);
printf("Longitude: %f degrees\r\n", hgps.longitude);
printf("Altitude: %f meters\r\n", hgps.altitude);
return 0;
}

View File

@ -1,81 +0,0 @@
#include "lwgps/lwgps.h"
#include "lwrb/lwrb.h"
#include <string.h>
/* GPS handle */
lwgps_t hgps;
/* GPS buffer */
lwrb_t hgps_buff;
uint8_t hgps_buff_data[12];
/**
* \brief Dummy data from GPS receiver
* \note This data are used to fake UART receive event on microcontroller
*/
const char
gps_rx_data[] = ""
"$GPRMC,183729,A,3907.356,N,12102.482,W,000.0,360.0,080301,015.5,E*6F\r\n"
"$GPRMB,A,,,,,,,,,,,,V*71\r\n"
"$GPGGA,183730,3907.356,N,12102.482,W,1,05,1.6,646.4,M,-24.1,M,,*75\r\n"
"$GPGSA,A,3,02,,,07,,09,24,26,,,,,1.6,1.6,1.0*3D\r\n"
"$GPGSV,2,1,08,02,43,088,38,04,42,145,00,05,11,291,00,07,60,043,35*71\r\n"
"$GPGSV,2,2,08,08,02,145,00,09,46,303,47,24,16,178,32,26,18,231,43*77\r\n"
"$PGRME,22.0,M,52.9,M,51.0,M*14\r\n"
"$GPGLL,3907.360,N,12102.481,W,183730,A*33\r\n"
"$PGRMZ,2062,f,3*2D\r\n"
"$PGRMM,WGS84*06\r\n"
"$GPBOD,,T,,M,,*47\r\n"
"$GPRTE,1,1,c,0*07\r\n"
"$GPRMC,183731,A,3907.482,N,12102.436,W,000.0,360.0,080301,015.5,E*67\r\n"
"$GPRMB,A,,,,,,,,,,,,V*71\r\n";
static size_t write_ptr;
static void uart_irqhandler(void);
int
main() {
uint8_t rx;
/* Init GPS */
lwgps_init(&hgps);
/* Create buffer for received data */
lwrb_init(&hgps_buff, hgps_buff_data, sizeof(hgps_buff_data));
while (1) {
/* Add new character to buffer */
/* Fake UART interrupt handler on host microcontroller */
uart_irqhandler();
/* Process all input data */
/* Read from buffer byte-by-byte and call processing function */
if (lwrb_get_full(&hgps_buff)) { /* Check if anything in buffer now */
while (lwrb_read(&hgps_buff, &rx, 1) == 1) {
lwgps_process(&hgps, &rx, 1); /* Process byte-by-byte */
}
} else {
/* Print all data after successful processing */
printf("Latitude: %f degrees\r\n", hgps.latitude);
printf("Longitude: %f degrees\r\n", hgps.longitude);
printf("Altitude: %f meters\r\n", hgps.altitude);
break;
}
}
return 0;
}
/**
* \brief Interrupt handler routing for UART received character
* \note This is not real MCU, it is software method, called from main
*/
static void
uart_irqhandler(void) {
/* Make interrupt handler as fast as possible */
/* Only write to received buffer and process later */
if (write_ptr < strlen(gps_rx_data)) {
/* Write to buffer only */
lwrb_write(&hgps_buff, &gps_rx_data[write_ptr], 1);
++write_ptr;
}
}

View File

@ -1,24 +0,0 @@
#include "lwgps/lwgps.h"
/* Distance and bearing results */
lwgps_float_t dist, bear;
/* New York coordinates */
lwgps_float_t lat1 = 40.685721;
lwgps_float_t lon1 = -73.820465;
/* Munich coordinates */
lwgps_float_t lat2 = 48.150906;
lwgps_float_t lon2 = 11.554176;
/* Go from New York to Munich */
/* Calculate distance and bearing related to north */
lwgps_distance_bearing(lat1, lon1, lat2, lon2, &dist, &bear);
printf("Distance: %f meters\r\n", (float)dist);
printf("Initial bearing: %f degrees\r\n", (float)bear);
/* Go from Munich to New York */
/* Calculate distance and bearing related to north */
lwgps_distance_bearing(lat2, lon2, lat1, lon1, &dist, &bear);
printf("Distance: %f meters\r\n", (float)dist);
printf("Initial bearing: %f degrees\r\n", (float)bear);

View File

@ -1,77 +0,0 @@
/**
* This example tests the callback functionality of lwgps_process()
* when the LWGPS_CFG_STATUS flag is set.
*/
#include <string.h>
#include <stdio.h>
#include "lwgps/lwgps.h"
#if !LWGPS_CFG_STATUS
#error "this test must be compiled with -DLWGPS_CFG_STATUS=1"
#endif /* !LWGPS_CFG_STATUS */
/* GPS handle */
lwgps_t hgps;
/**
* \brief Dummy data from GPS receiver
*/
const char
gps_rx_data[] = ""
"$GPRMC,183729,A,3907.356,N,12102.482,W,000.0,360.0,080301,015.5,E*6F\r\n"
"$GPRMB,A,,,,,,,,,,,,V*71\r\n"
"$GPGGA,183730,3907.356,N,12102.482,W,1,05,1.6,646.4,M,-24.1,M,,*75\r\n"
"$GPGSA,A,3,02,,,07,,09,24,26,,,,,1.6,1.6,1.0*3D\r\n"
"$GPGSV,2,1,08,02,43,088,38,04,42,145,00,05,11,291,00,07,60,043,35*71\r\n"
"$GPGSV,2,2,08,08,02,145,00,09,46,303,47,24,16,178,32,26,18,231,43*77\r\n"
"$PGRME,22.0,M,52.9,M,51.0,M*14\r\n"
"$GPGLL,3907.360,N,12102.481,W,183730,A*33\r\n"
"$PGRMZ,2062,f,3*2D\r\n"
"$PGRMM,WGS84*06\r\n"
"$GPBOD,,T,,M,,*47\r\n"
"$GPRTE,1,1,c,0*07\r\n"
"$GPRMC,183731,A,3907.482,N,12102.436,W,000.0,360.0,080301,015.5,E*67\r\n"
"$GPRMB,A,,,,,,,,,,,,V*71\r\n";
const lwgps_statement_t expected[] = {
STAT_RMC,
STAT_UNKNOWN,
STAT_GGA,
STAT_GSA,
STAT_GSV,
STAT_GSV,
STAT_UNKNOWN,
STAT_UNKNOWN,
STAT_UNKNOWN,
STAT_CHECKSUM_FAIL,
STAT_UNKNOWN,
STAT_UNKNOWN,
STAT_RMC,
STAT_UNKNOWN
};
static int err_cnt;
void
callback(lwgps_statement_t res) {
static int i;
if (res != expected[i]) {
printf("failed i %d, expected res %d but received %d\n",
i, expected[i], res);
++err_cnt;
}
++i;
}
int
main() {
/* Init GPS */
lwgps_init(&hgps);
/* Process all input data */
lwgps_process(&hgps, gps_rx_data, strlen(gps_rx_data), callback);
return err_cnt;
}

View File

@ -1,71 +0,0 @@
/*
* This example uses direct processing function,
* to process dummy NMEA data from GPS receiver
*/
#include <string.h>
#include <stdio.h>
#include "lwgps/lwgps.h"
#include "test_common.h"
/* GPS handle */
lwgps_t hgps;
/**
* \brief Dummy data from GPS receiver
*/
const char
gps_rx_data[] = ""
"$GPRMC,183729,A,3907.356,N,12102.482,W,000.0,360.0,080301,015.5,E*6F\r\n"
"$GPGGA,183730,3907.356,N,12102.482,W,1,05,1.6,646.4,M,-24.1,M,,*75\r\n"
"$GPGSA,A,3,02,,,07,,09,24,26,,,,,1.6,1.6,1.0*3D\r\n"
"$GPGSV,2,1,08,02,43,088,38,04,42,145,00,05,11,291,00,07,60,043,35*71\r\n"
"$GPGSV,2,2,08,08,02,145,00,09,46,303,47,24,16,178,32,26,18,231,43*77\r\n"
"";
/**
* \brief Run the test of raw input data
*/
void
run_tests() {
lwgps_init(&hgps); /* Init GPS */
/* Process all input data */
lwgps_process(&hgps, gps_rx_data, strlen(gps_rx_data));
/* Run the test */
RUN_TEST(!INT_IS_EQUAL(hgps.is_valid, 0));
RUN_TEST(INT_IS_EQUAL(hgps.fix, 1));
RUN_TEST(INT_IS_EQUAL(hgps.fix_mode, 3));
RUN_TEST(FLT_IS_EQUAL(hgps.latitude, 39.1226000000));
RUN_TEST(FLT_IS_EQUAL(hgps.longitude, -121.0413666666));
RUN_TEST(FLT_IS_EQUAL(hgps.altitude, 646.4000000000));
RUN_TEST(FLT_IS_EQUAL(hgps.course, 360.0000000000));
RUN_TEST(INT_IS_EQUAL(hgps.dop_p, 1.6000000000));
RUN_TEST(INT_IS_EQUAL(hgps.dop_h, 1.6000000000));
RUN_TEST(INT_IS_EQUAL(hgps.dop_v, 1.0000000000));
RUN_TEST(FLT_IS_EQUAL(hgps.speed, 0.0000000000));
RUN_TEST(FLT_IS_EQUAL(hgps.geo_sep, -24.100000000));
RUN_TEST(FLT_IS_EQUAL(hgps.variation, 15.500000000));
RUN_TEST(INT_IS_EQUAL(hgps.sats_in_view, 8));
RUN_TEST(INT_IS_EQUAL(hgps.sats_in_use, 5));
RUN_TEST(INT_IS_EQUAL(hgps.satellites_ids[0], 2));
RUN_TEST(INT_IS_EQUAL(hgps.satellites_ids[1], 0));
RUN_TEST(INT_IS_EQUAL(hgps.satellites_ids[2], 0));
RUN_TEST(INT_IS_EQUAL(hgps.satellites_ids[3], 7));
RUN_TEST(INT_IS_EQUAL(hgps.satellites_ids[4], 0));
RUN_TEST(INT_IS_EQUAL(hgps.satellites_ids[5], 9));
RUN_TEST(INT_IS_EQUAL(hgps.satellites_ids[6], 24));
RUN_TEST(INT_IS_EQUAL(hgps.satellites_ids[7], 26));
RUN_TEST(INT_IS_EQUAL(hgps.satellites_ids[8], 0));
RUN_TEST(INT_IS_EQUAL(hgps.satellites_ids[9], 0));
RUN_TEST(INT_IS_EQUAL(hgps.satellites_ids[10], 0));
RUN_TEST(INT_IS_EQUAL(hgps.satellites_ids[11], 0));
RUN_TEST(INT_IS_EQUAL(hgps.date, 8));
RUN_TEST(INT_IS_EQUAL(hgps.month, 3));
RUN_TEST(INT_IS_EQUAL(hgps.year, 1));
RUN_TEST(INT_IS_EQUAL(hgps.hours, 18));
RUN_TEST(INT_IS_EQUAL(hgps.minutes, 37));
RUN_TEST(INT_IS_EQUAL(hgps.seconds, 30));
}

View File

@ -1,18 +0,0 @@
#ifndef TEST_COMMON_HDR_H
#define TEST_COMMON_HDR_H
#include <math.h>
#include <stdlib.h>
#define RUN_TEST(x) do { \
if ((x)) { \
printf("Test passed on line %u with condition " # x "\r\n", (unsigned)__LINE__); \
} else { \
printf("Test FAILED on line %u with condition " # x "\r\n", (unsigned)__LINE__ ); \
exit(1); \
} \
} while (0)
#define FLT_IS_EQUAL(x, y) (fabs((double)(x) - (double)(y)) < 0.00001)
#define INT_IS_EQUAL(x, y) ((int)((x) == (y)))
#endif /* TEST_COMMON_HDR_H */

View File

@ -1,69 +0,0 @@
/*
* This example uses direct processing function,
* to process dummy PUBX TIME packets from GPS receiver
*/
#include <string.h>
#include <stdio.h>
#include "lwgps/lwgps.h"
#include "test_common.h"
#if !LWGPS_CFG_STATEMENT_PUBX_TIME
#error "this test must be compiled with -DLWGPS_CFG_STATEMENT_PUBX_TIME=1"
#endif /* !LWGPS_CFG_STATEMENT_PUBX_TIME */
/* GPS handle */
lwgps_t hgps;
/**
* \brief Dummy data from GPS receiver
*/
const char
gps_rx_data_A[] = ""
"$PUBX,04*37\r\n"
"$PUBX,04,073731.00,091202,113851.00,1196,15D,1930035,-2660.664,43*71\r\n"
"";
const char
gps_rx_data_B[] = ""
"$PUBX,04,200714.00,230320,158834.00,2098,18,536057,257.043,16*12\r\b"
"";
/**
* \brief Run the test of raw input data
*/
void
run_tests() {
lwgps_init(&hgps);
/* Process and test block A */
lwgps_process(&hgps, gps_rx_data_A, strlen(gps_rx_data_A));
RUN_TEST(INT_IS_EQUAL(hgps.hours, 7));
RUN_TEST(INT_IS_EQUAL(hgps.minutes, 37));
RUN_TEST(INT_IS_EQUAL(hgps.seconds, 31));
RUN_TEST(INT_IS_EQUAL(hgps.date, 9));
RUN_TEST(INT_IS_EQUAL(hgps.month, 12));
RUN_TEST(INT_IS_EQUAL(hgps.year, 2));
RUN_TEST(FLT_IS_EQUAL(hgps.utc_tow, 113851.00));
RUN_TEST(INT_IS_EQUAL(hgps.utc_wk, 1196));
RUN_TEST(INT_IS_EQUAL(hgps.leap_sec, 15));
RUN_TEST(INT_IS_EQUAL(hgps.clk_bias, 1930035));
RUN_TEST(FLT_IS_EQUAL(hgps.clk_drift, -2660.664));
RUN_TEST(INT_IS_EQUAL(hgps.tp_gran, 43));
/* Process and test block B */
lwgps_process(&hgps, gps_rx_data_B, strlen(gps_rx_data_B));
RUN_TEST(INT_IS_EQUAL(hgps.hours, 20));
RUN_TEST(INT_IS_EQUAL(hgps.minutes, 7));
RUN_TEST(INT_IS_EQUAL(hgps.seconds, 14));
RUN_TEST(INT_IS_EQUAL(hgps.date, 23));
RUN_TEST(INT_IS_EQUAL(hgps.month, 3));
RUN_TEST(INT_IS_EQUAL(hgps.year, 20));
RUN_TEST(FLT_IS_EQUAL(hgps.utc_tow, 158834.00));
RUN_TEST(INT_IS_EQUAL(hgps.utc_wk, 2098));
RUN_TEST(INT_IS_EQUAL(hgps.leap_sec, 18));
RUN_TEST(INT_IS_EQUAL(hgps.clk_bias, 536057));
RUN_TEST(FLT_IS_EQUAL(hgps.clk_drift, 257.043));
RUN_TEST(INT_IS_EQUAL(hgps.tp_gran, 16));
}

View File

@ -1 +0,0 @@
add_subdirectory(src)

View File

@ -1,3 +0,0 @@
add_subdirectory(include)
add_subdirectory(lwgps)

View File

@ -1,7 +0,0 @@
target_include_directories(${LIB_LWGPS_NAME} INTERFACE
${CMAKE_CURRENT_SOURCE_DIR}
)
target_include_directories(${LIB_LWGPS_NAME} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
)

View File

@ -1,3 +0,0 @@
target_sources(${LIB_LWGPS_NAME} PRIVATE
lwgps.c
)

Some files were not shown because too many files have changed in this diff Show More