#include "detect_step_by_acc.h" static int ACC_WINDOW_SIZE=20; static int16_t acc_y_buff[20]; static int16_t acc_z_buff[20]; static int16_t acc_x_buff[20]; static int32_t acc_xyz_buff[20]; //static int acc_y_wait; //static int acc_z_wait; //static int acc_x_wait; static int acc_y_status = 1; static int acc_z_status = 1; static int acc_x_status = 1; //static int last_zupt; static int last_acc_x_status; static int last_acc_y_status; static int last_acc_z_status; static int x_raised; static int y_raised; static int z_raised; static int x_hollow; static int y_hollow; static int z_hollow; static int zero_x_wait; static int zero_y_wait; static int zero_z_wait; //static int can_detect_zupt = 1; //static int stop_out_zupt = 0; //static int acc_diff_wait_count = 0; static int last_time_stamp = 0; //static int PDR_step_count = 0; static int16_t max_z_unzero = 2048; static int16_t min_z_unzero = 2048; void detect_raised_hollow(int16_t *acc, int length, int16_t max_val_thresh, int16_t min_val_thresh, int16_t distance, int *raised, int *hollow) { //本函数用来检测加速度曲线的凹凸标志 //1、遍历加速度窗口的最大值及最小值 int start_index = ACC_WINDOW_SIZE - length; if(start_index < 0) { return; } int16_t max_val = acc[ACC_WINDOW_SIZE - length / 2]; int16_t min_val = acc[ACC_WINDOW_SIZE - length / 2]; for(int i = ACC_WINDOW_SIZE - length / 2; i < ACC_WINDOW_SIZE; i++) { if(max_val < acc[i]) { max_val = acc[i]; } if(min_val > acc[i]) { min_val = acc[i]; } } //检测到平稳信号,需要重新检测凹凸性 if(max_val - min_val < 410) //0.2*2048 { *raised = 0; *hollow = 0; return; } for(int i = 0; i < ACC_WINDOW_SIZE - length / 2; i++) { if(max_val < acc[i]) { max_val = acc[i]; } if(min_val > acc[i]) { min_val = acc[i]; } } //检测凹凸性 if(max_val - acc[0] > distance && max_val - acc[ACC_WINDOW_SIZE-1] > distance && *raised == 0 && max_val > max_val_thresh) { *raised = 1; } if(acc[0] - min_val > distance && acc[ACC_WINDOW_SIZE - 1] - min_val > distance && *hollow == 0 && min_val < min_val_thresh) { *hollow = 1; } } //求取拐点 int detect_turn_line(int16_t *acc, int length, int tag) { int start_index = ACC_WINDOW_SIZE - length; int16_t min_val = acc[start_index]; int min_index = start_index; int16_t max_val = acc[start_index]; int max_index = start_index; for(int i = 8; i < ACC_WINDOW_SIZE; i ++) { if(min_val > acc[i]) { min_val = acc[i]; min_index = i; } if(max_val < acc[i]) { max_val = acc[i]; max_index = i; } } int16_t min_val_5 = acc[ACC_WINDOW_SIZE - 5]; int16_t max_val_5 = acc[ACC_WINDOW_SIZE - 5]; for(int i = ACC_WINDOW_SIZE - 5; i < ACC_WINDOW_SIZE; i++ ) { if(min_val_5 > acc[i]) { min_val_5 = acc[i]; } if(max_val_5 < acc[i]) { max_val_5 = acc[i]; } } if(max_val - min_val > 1024 && max_val_5 - min_val_5 < 410) { if(tag == 1) { if(max_index < min_index) { return 1; } else { return 0; } } return 1; } return 0; } //求取平稳信号 int station_signal(int16_t *acc, int length) { int start_index = ACC_WINDOW_SIZE - length; int16_t max_val = acc[start_index]; int16_t min_val = acc[start_index]; for(int i = start_index; i < ACC_WINDOW_SIZE; i++) { if(max_val < acc[i]) { max_val = acc[i]; } if(min_val > acc[i]) { min_val = acc[i]; } } if(max_val - min_val < 307) { return 1; } return 0; } //剧烈信号探测拐点 int severe_turn_point_z(int16_t *acc, int length) { int16_t max_val = acc[0]; int16_t min_val = acc[0]; int16_t min_temp = acc[0]; int16_t max_distance = max_val - min_val; for(int i = 1 ; i < ACC_WINDOW_SIZE; i++) { int16_t distance_tmp = acc[i-1] - acc[i]; if(i > 1 && distance_tmp < (acc[i-2] - acc[i])) distance_tmp = (acc[i-2] - acc[i]); if(i > 2 && distance_tmp < (acc[i-3] - acc[i])) distance_tmp = (acc[i-3] - acc[i]); if(i > 3 && distance_tmp < (acc[i-4] - acc[i])) distance_tmp = (acc[i-4] - acc[i]); if(i > 4 && distance_tmp < (acc[i-5] - acc[i])) distance_tmp = (acc[i-5] - acc[i]); if(max_distance < distance_tmp) { max_distance = distance_tmp; } if(min_temp > acc[i]) { min_temp = acc[i]; } } max_val = acc[ACC_WINDOW_SIZE-5]; min_val = acc[ACC_WINDOW_SIZE-5]; for(int i = ACC_WINDOW_SIZE - 5; i< ACC_WINDOW_SIZE; i++) { if(max_val < acc[i]) { max_val = acc[i]; } if(min_val > acc[i]) { min_val = acc[i]; } } int16_t min_distance = max_val - min_val; if(max_distance > 3072 && min_distance < 614 && min_temp > 1024) { return 1; } return 0; } int severe_turn_point(int16_t *acc, int length) { int16_t max_val = acc[0]; int16_t min_val = acc[0]; int16_t max_distance = max_val - min_val; for(int i = 1 ; i < ACC_WINDOW_SIZE; i++) { int16_t distance_tmp = acc[i] - acc[i-1]; if(i > 1 && distance_tmp < fabsf(acc[i] - acc[i-2])) distance_tmp = fabsf(acc[i] - acc[i-2]); if(i > 2 && distance_tmp < fabsf(acc[i] - acc[i-3])) distance_tmp = fabsf(acc[i] - acc[i-3]); if(i > 3 && distance_tmp < fabsf(acc[i] - acc[i-4])) distance_tmp = fabsf(acc[i] - acc[i-4]); if(i > 4 && distance_tmp < fabsf(acc[i] - acc[i-5])) distance_tmp = fabsf(acc[i] - acc[i-5]); if(max_distance < distance_tmp) { max_distance = distance_tmp; } } max_val = acc[ACC_WINDOW_SIZE-5]; min_val = acc[ACC_WINDOW_SIZE-5]; for(int i = ACC_WINDOW_SIZE - 5; i< ACC_WINDOW_SIZE; i++) { if(max_val < acc[i]) { max_val = acc[i]; } if(min_val > acc[i]) { min_val = acc[i]; } } int16_t min_distance = max_val - min_val; if(max_distance > 2662 && min_distance < 615) { return 1; } return 0; } int32_t var_acc(int16_t *acc, int length) { if(length < 10) { return 0; } int32_t mean_x = 0; int32_t sum_x = 0; for(int i = length - 10; i < length; i++) { sum_x += acc[i]; } mean_x = sum_x / 10; sum_x = 0; for(int i = length - 10; i < length; i++) { sum_x += ((acc[i]- mean_x) * (acc[i]- mean_x)); } return sum_x / 10 ; } //寻找窗口的最小值 int16_t min_window(int16_t *acc, int length) { int start_index = ACC_WINDOW_SIZE - length; int16_t min_val = acc[start_index]; for(int i = 0; i < ACC_WINDOW_SIZE; i++) { if(acc[i] < min_val) { min_val = acc[i]; } } return min_val; } //寻找窗口的最大值 int16_t max_window(int16_t *acc, int length) { int start_index = ACC_WINDOW_SIZE - length; int16_t max_val = acc[start_index]; for(int i = 0; i < ACC_WINDOW_SIZE; i++) { if(acc[i] > max_val) { max_val = acc[i]; } } return max_val; } //三轴稳定判断 int station_window_xyz(int32_t *acc) { int32_t max_val = acc[0]; int32_t min_val = acc[0]; for(int i = 0; i < ACC_WINDOW_SIZE; i++) { if(acc[i] > max_val) { max_val = acc[i]; } if(acc[i] < min_val) { min_val = acc[i]; } } if(max_val - min_val < 419430) { return 1; } return 0; } void detect_step_by_acc(int16_t *acc) { //缓存加速度的滑动窗口 static uint32_t time_stamp; memcpy(acc_x_buff, acc_x_buff + 1, (ACC_WINDOW_SIZE - 1) * sizeof(int16_t)); acc_x_buff[(ACC_WINDOW_SIZE - 1)] = acc[0]; memcpy(acc_y_buff, acc_y_buff + 1, (ACC_WINDOW_SIZE - 1) * sizeof(int16_t)); acc_y_buff[(ACC_WINDOW_SIZE - 1)] = acc[1]; memcpy(acc_z_buff, acc_z_buff + 1, (ACC_WINDOW_SIZE - 1) * sizeof(int16_t)); acc_z_buff[(ACC_WINDOW_SIZE - 1)] = acc[2]; memcpy(acc_xyz_buff, acc_xyz_buff + 1, (ACC_WINDOW_SIZE - 1) * sizeof(int32_t)); acc_xyz_buff[(ACC_WINDOW_SIZE - 1)] = acc[0] * acc[0] + acc[1] * acc[1] + acc[2] * acc[2]; //检测拐点 //detect_raised_hollow(float *acc, int length, float max_val_thresh, float min_val_thresh, float distance, int *raised, int *hollow) detect_raised_hollow(acc_x_buff, ACC_WINDOW_SIZE, 1434, -1434, 1024, &x_raised, &x_hollow); detect_raised_hollow(acc_y_buff, ACC_WINDOW_SIZE, 1434, -1434, 1024, &y_raised, &y_hollow); detect_raised_hollow(acc_z_buff, ACC_WINDOW_SIZE, 2458, 1638, 820, &z_raised, &z_hollow); if(x_raised == 1 && x_hollow == 1 && zero_x_wait == 0) { zero_x_wait = 30; } if(y_raised == 1 && y_hollow == 1 && zero_y_wait == 0) { zero_y_wait = 30; } if(z_raised == 1 && z_hollow == 1 && zero_z_wait == 0) { zero_z_wait = 30; } acc_x_status = 0; acc_y_status = 0; acc_z_status = 0; if((zero_x_wait > 0 || acc_x_status == 1) && detect_turn_line(acc_x_buff, 10, 0)) { acc_x_status = 1; } if((zero_y_wait > 0 || acc_y_status == 1) && detect_turn_line(acc_y_buff, 10, 0)) { acc_y_status = 1; } if((zero_z_wait > 0 || acc_z_status == 1) && detect_turn_line(acc_z_buff, 10, 1)) { acc_z_status = 1; } //剧烈信号探测拐点 if(severe_turn_point(acc_x_buff, ACC_WINDOW_SIZE)) { acc_x_status = 1; } if(severe_turn_point(acc_y_buff, ACC_WINDOW_SIZE)) { acc_y_status = 1; } if(severe_turn_point_z(acc_z_buff, ACC_WINDOW_SIZE)) { acc_z_status = 1; } //标志垫着脚跑的变量 int special_zupt = 0; if(var_acc(acc_z_buff, ACC_WINDOW_SIZE) > 2097152 && max_window(acc_z_buff, 10) > 2048 && acc[2] > 1434) { acc_x_status = 1; acc_y_status = 1; acc_z_status = 3; special_zupt = 1; } //当上次信号大于0的时候, 判断下滑曲线 if(last_acc_x_status && station_signal(acc_x_buff, 5)) { acc_x_status = 2; } if(last_acc_y_status && station_signal(acc_y_buff, 5)) { acc_y_status = 2; } if(last_acc_z_status && station_signal(acc_z_buff, 5)) { acc_z_status = 2; } if((acc_x_status || acc_y_status) && abs(acc[2] - 2048) < 410 && station_signal(acc_z_buff, 10)) { acc_z_status = 2; } if(acc_z_status == 0 && last_acc_z_status == 3 && max_window(acc_z_buff, 10) - acc[2] > 2048 && acc[2] > 1434 && acc[2] < 3072) { acc_z_status = 3; } //因为会有断开的现象,所以大概估计到200ms内出现平缓信号,视为在地上 if(time_stamp - last_time_stamp < 20) { //if(max_window(acc_xyz_buff, 10) - min_window(acc_xyz_buff, 10) < 205) if(station_window_xyz(acc_xyz_buff)) { acc_x_status = 1; acc_y_status = 1; acc_z_status = 1; } } //利用奇异值来去掉误判信号 if(special_zupt == 0 && (acc[2] < 1638 || abs(acc[0]) > 1024 || abs(acc[1]) > 1024)) { acc_x_status = 0; acc_y_status = 0; acc_z_status = 0; } //凹凸信号都检测信号,需要延时等待 if(zero_x_wait > 0) { zero_x_wait --; if(zero_x_wait == 0) { x_raised = 0; x_hollow = 0; } } if(zero_y_wait > 0) { zero_y_wait --; if(zero_y_wait == 0) { y_raised = 0; y_hollow = 0; } } if(zero_z_wait > 0) { zero_z_wait --; if(zero_z_wait == 0) { z_raised = 0; z_hollow = 0; } } last_acc_x_status = acc_x_status; last_acc_y_status = acc_y_status; last_acc_z_status = acc_z_status; if(time_stamp - last_time_stamp < 15) { if(acc[2] > max_z_unzero) { max_z_unzero = acc[2]; } if(acc[2] < min_z_unzero) { min_z_unzero = acc[2]; } } else { max_z_unzero = 2048; min_z_unzero = 2048; } //记录zupt if( (acc_z_status > 0 || (acc_x_status > 0 && acc_y_status > 0)) ) { // *zupt = 1; if(time_stamp - last_time_stamp > 15) { //PDR_step_count ++; mFlash.mStep.stepCur[0]++; } else if(min_z_unzero < 0 && max_z_unzero > 4096 && time_stamp - last_time_stamp > 5) { mFlash.mStep.stepCur[0]++; max_z_unzero = 2048; min_z_unzero = 2048; } // DEBUG_LOG("bushu:%d\n",mRAMStep_t->stepCur[0]); last_time_stamp = time_stamp; } // else // { // *zupt = 0; // } // *x_zero = 0; // *y_zero = 0; // *z_zero = acc_z_status; time_stamp ++; }