已知三轴加速度数据,利用低通滤波,华东窗口以及波峰波谷的检测实现对步数的计步,C语言来写
时间: 2023-07-14 17:14:02 浏览: 172
利用三轴加速度传感器的计步测算法
以下是一个基于三轴加速度数据的计步算法示例,使用了低通滤波、华东窗口和波峰波谷检测。请注意,这是一个简单的示例,实际应用中可能需要根据具体情况进行调整和优化。
```c
#include <stdio.h>
#include <math.h>
#define SAMPLE_RATE 50 // 采样率,单位 Hz
#define WINDOW_SIZE 20 // 窗口大小,单位采样点
#define THRESHOLD_FACTOR 0.25 // 波峰波谷阈值系数
#define MIN_STEP_INTERVAL 300 // 最小步间隔,单位毫秒
// 低通滤波器
typedef struct {
double a1, a2, b0, b1, b2;
double x1, x2, y1, y2;
} LowPassFilter;
void initLowPassFilter(LowPassFilter* filter, double cutoffFreq) {
double omega = 2.0 * M_PI * cutoffFreq / SAMPLE_RATE;
double alpha = sin(omega) / (2.0 * 0.707);
double beta = sqrt(2.0) * alpha;
double a0 = 1.0 + beta + alpha * alpha;
filter->a1 = (2.0 * (alpha * alpha - 1.0)) / a0;
filter->a2 = (1.0 - beta + alpha * alpha) / a0;
filter->b0 = (alpha * alpha) / a0;
filter->b1 = (2.0 * alpha * alpha) / a0;
filter->b2 = (alpha * alpha) / a0;
filter->x1 = 0.0;
filter->x2 = 0.0;
filter->y1 = 0.0;
filter->y2 = 0.0;
}
double lowPassFilter(LowPassFilter* filter, double x) {
double y = filter->b0 * x + filter->b1 * filter->x1 + filter->b2 * filter->x2
- filter->a1 * filter->y1 - filter->a2 * filter->y2;
filter->x2 = filter->x1;
filter->x1 = x;
filter->y2 = filter->y1;
filter->y1 = y;
return y;
}
// 华东窗口
typedef struct {
double* buffer;
int size;
int head;
double sum;
} MovingWindow;
void initMovingWindow(MovingWindow* window, int size) {
window->buffer = (double*) malloc(size * sizeof(double));
window->size = size;
window->head = 0;
window->sum = 0.0;
}
void destroyMovingWindow(MovingWindow* window) {
free(window->buffer);
}
void addToMovingWindow(MovingWindow* window, double x) {
window->sum += x;
window->sum -= window->buffer[window->head];
window->buffer[window->head] = x;
window->head = (window->head + 1) % window->size;
}
double getMovingWindowAvg(MovingWindow* window) {
return window->sum / window->size;
}
// 波峰波谷检测状态
typedef enum {
STATE_IDLE,
STATE_RISING,
STATE_FALLING
} PeakDetectionState;
// 波峰波谷检测
typedef struct {
PeakDetectionState state;
double threshold;
double lastValue;
double lastPeak;
double lastValley;
} PeakDetector;
void initPeakDetector(PeakDetector* detector, double threshold) {
detector->state = STATE_IDLE;
detector->threshold = threshold;
detector->lastValue = 0.0;
detector->lastPeak = 0.0;
detector->lastValley = 0.0;
}
int updatePeakDetector(PeakDetector* detector, double value, double* peak, double* valley) {
switch (detector->state) {
case STATE_IDLE:
if (value > detector->lastValue + detector->threshold) {
detector->state = STATE_RISING;
detector->lastPeak = value;
*peak = value;
return 1;
} else if (value < detector->lastValue - detector->threshold) {
detector->state = STATE_FALLING;
detector->lastValley = value;
*valley = value;
return 1;
}
break;
case STATE_RISING:
if (value < detector->lastPeak) {
detector->state = STATE_FALLING;
detector->lastValley = value;
*valley = value;
return 1;
}
break;
case STATE_FALLING:
if (value > detector->lastValley) {
detector->state = STATE_RISING;
detector->lastPeak = value;
*peak = value;
return 1;
}
break;
}
detector->lastValue = value;
return 0;
}
// 计步器
typedef struct {
LowPassFilter filter;
MovingWindow window;
PeakDetector peakDetector;
int stepCount;
int lastStepTime;
} StepCounter;
void initStepCounter(StepCounter* counter) {
initLowPassFilter(&counter->filter, 5.0);
initMovingWindow(&counter->window, WINDOW_SIZE);
initPeakDetector(&counter->peakDetector, THRESHOLD_FACTOR * getMovingWindowAvg(&counter->window));
counter->stepCount = 0;
counter->lastStepTime = 0;
}
void destroyStepCounter(StepCounter* counter) {
destroyMovingWindow(&counter->window);
}
int updateStepCounter(StepCounter* counter, double x, double y, double z) {
double norm = sqrt(x * x + y * y + z * z);
double filtered = lowPassFilter(&counter->filter, norm);
addToMovingWindow(&counter->window, filtered);
double avg = getMovingWindowAvg(&counter->window);
double peak = 0.0, valley = 0.0;
if (updatePeakDetector(&counter->peakDetector, filtered - avg, &peak, &valley)) {
int interval = SAMPLE_RATE * (peak - valley) / norm;
if (interval > MIN_STEP_INTERVAL && counter->lastStepTime + interval < SAMPLE_RATE * 2) {
counter->stepCount++;
counter->lastStepTime += interval;
return 1;
}
}
return 0;
}
int main() {
// 假设有一组加速度数据 ax, ay, az,每秒50个样本
double ax[1000], ay[1000], az[1000];
// 初始化计步器
StepCounter counter;
initStepCounter(&counter);
// 处理加速度数据
for (int i = 0; i < 1000; i++) {
int step = updateStepCounter(&counter, ax[i], ay[i], az[i]);
if (step) {
printf("Step %d detected\n", counter.stepCount);
}
}
// 销毁计步器
destroyStepCounter(&counter);
return 0;
}
```
阅读全文