123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869 |
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <math.h>
- #include <stdint.h>
- #include "footPDR.h"
- #include "ekfPDR.h"
- #include "ukfPDR.h"
- #define ZUPT_threshold 0.81
- #define SIGMA 0.01
- #define SIGMA_V 0.01
- #define PI 3.14159265f
- #define RUN 1
- #define STAND 0
- extern void sen_step_to_host(uint8_t, uint16_t);
- //当地的重力加速度
- float g = 9.8179995f;
- float dt = 0.01f;
- float P[81], acc_n[3];
- float Temporary_array1[9], Temporary_array2[9];
- float K[27], P_prev[81], delta_x[9];
- float C[9], C_prev[9];
- float vel_n[3], pos_n[3];
- float last_pos_n[3];
- float pos_offset[3];
- int frame_index = 0;
- int stand_num = 0;
- float gyr_norm_window[10];
- float gyr_extreme[6];
- float gyr_mean[3];
- float num_peak;
- float acc_mean[3];
- float gyrBias[3];
- float last_gyr[3];
- float last_acc[3];
- float last_vel_n[3];
- float accSum;
- float accSize;
- int press_data[10];
- int ZUPT_STATUS;
- int press_index;
- int time_zupt;
- //last_stage:0 为 走路状态;
- //last_stage:1 为 静止状态
- int last_stage;
- uint8_t step_count;
- uint16_t step_distance;
- int step_time = 0;
- //UKF参数
- int UKF_L = 4;
- float UKF_alpha = 0.01f;
- float UKF_beta = 2.0f;
- float UKF_kappa = 0.0f;
- float gamma;
- float wm[9];
- float wc[9];
- float UKF_Q[4];
- float UKF_P[4][4];
- int UKF_iter;
- float mag_prev[3];
- float deltaC[9];
- float UKF_C[9];
- float UKF_roll;
- float UKF_pitch;
- float UKF_yaw;
- float EKF_roll;
- float EKF_pitch;
- float EKF_yaw;
- int canUKF = 0;
- int stand_zupt_count = 0;
- //重置磁航向,计算双脚的磁航向,以确定身体的正朝向
- float magSum_xyz[3];
- float accSum_xyz[3];
- float calHeading(float mag[3], float acc[3])
- {
- float hSqrt;
- float eSqrt;
-
- float h[3]; //东向
-
- h[0] = mag[1] * acc[2] - mag[2] * acc[1];
- h[1] = mag[2] * acc[0] - mag[0] * acc[2];
- h[2] = mag[0] * acc[1] - mag[1] * acc[0];
-
- hSqrt = 1/sqrt(h[0] * h[0] + h[1] * h[1] + h[2] * h[2]);
-
- for(int i = 0; i < 3; i++)
- {
- h[i] *= hSqrt;
- }
-
- float e[3]; //北向
-
- e[0] = acc[1] * h[2] - acc[2] * h[1];
- e[1] = acc[2] * h[0] - acc[0] * h[2];
- e[2] = acc[0] * h[1] - acc[1] * h[0];
-
- eSqrt = 1/sqrt(e[0] * e[0] + e[1] * e[1] + e[2] * e[2]);
-
- for(int i = 0; i < 3; i++)
- {
- e[i] *= eSqrt;
- }
- return atan2(-h[1], e[1]);
-
- }
-
- void resetAttbyMag(float *C, float acc[3], float mag[3])
- {
- float pitch = asin(-acc[0]);
- float roll = atan2(acc[1], acc[2]);
-
- float pitch_sin = sin(pitch);
- float pitch_cos = cos(pitch);
- float roll_sin = sin(roll);
- float roll_cos = cos(roll);
-
- float mag_heading;
- C[0] = pitch_cos;
- C[1] = pitch_sin * roll_sin;
- C[2] = pitch_sin * roll_cos;
- C[3] = 0.0;
- C[4] = roll_cos;
- C[5] = -roll_sin;
-
- mag_heading = atan2(C[4] * mag[1] + C[5] * mag[2], C[0] * mag[0] + C[1] * mag[1] + C[2] * mag[2]);
-
- float yaw_sin = sin(mag_heading);
-
- float yaw_cos = cos(mag_heading);
-
- C[0] = pitch_cos * yaw_cos;
- C[1] = pitch_sin * roll_sin * yaw_cos - roll_cos * yaw_sin;
- C[2] = pitch_sin * roll_cos * yaw_cos + roll_sin * yaw_sin;
- C[3] = pitch_cos * yaw_sin;
- C[4] = pitch_sin * roll_sin * yaw_sin + roll_cos * yaw_cos;
- C[5] = pitch_sin * roll_cos * yaw_sin - roll_sin * yaw_cos;
-
- C[6] = acc[0];
- C[7] = acc[1];
- C[8] = acc[2];
-
- }
- void cal_step_data(void)
- {
- static int step_count_sum = 0;
- step_count = 1;
- step_count_sum += step_count;
- float step_length = sqrt((last_pos_n[0] - pos_n[0])*(last_pos_n[0] - pos_n[0]) + (last_pos_n[1] - pos_n[1])*(last_pos_n[1] - pos_n[1]));
- if (step_length > 5.0f)
- {
- step_length = 1.2f;
- }
- step_distance = (uint16_t)(step_length * 100.0f);
- //sen_step_to_host(step_count, step_distance);
- }
- uint8_t get_step_count(void)
- {
- return step_count;
- }
- uint16_t get_step_length(void)
- {
- return step_distance;
- }
- void Initialize(float *gyr, float *acc)
- {
- frame_index = 1;
- stand_num = 0;
- accSize = 1.0f;
- accSum = 0.0f;
- ZUPT_STATUS = 0;
- memset(last_pos_n, 0, 3 * sizeof(float));
- memset(pos_offset, 0, 3 * sizeof(float));
- memset(gyr_norm_window, 0, 10 * sizeof(float));
- memset(P, 0, 81 * sizeof(float));
- memset(acc_n, 0, 3 * sizeof(float));
- memset(vel_n, 0, 3 * sizeof(float));
- memset(pos_n, 0, 3 * sizeof(float));
- memset(Temporary_array1, 0, 9 * sizeof(float));
- memset(Temporary_array2, 0, 9 * sizeof(float));
- memset(K, 0, 27 * sizeof(float));
- memset(P_prev, 0, 81 * sizeof(float));
- memset(delta_x, 0, 9 * sizeof(float));
- memset(C, 0, 9 * sizeof(float));
- memset(Temporary_array1, 0, 9 * sizeof(float));
- memset(Temporary_array2, 0, 9 * sizeof(float));
- memset(press_data, 0, 10 * sizeof(int));
- init_attitude_matrix(C, acc, g);
- memcpy(C_prev, C, 9 * sizeof(float));
- }
- void attitude_matrix_update(float *C, float *Temporary_array1, float *Temporary_array2, float *gyr, float dt)
- {
- Temporary_array1[0] = 2.0f;
- Temporary_array1[1] = dt * gyr[2];
- Temporary_array1[2] = -dt * gyr[1];
- Temporary_array1[3] = -dt * gyr[2];
- Temporary_array1[4] = 2.0f;
- Temporary_array1[5] = dt * gyr[0];
- Temporary_array1[6] = dt * gyr[1];
- Temporary_array1[7] = -dt * gyr[0];
- Temporary_array1[8] = 2.0f;
- invert3x3(Temporary_array1, Temporary_array2);
- memset(Temporary_array1, 0, 9 * sizeof(float));
- Temporary_array1[0] = 2 * C[0] + C[1] * dt * gyr[2] - C[2] * dt * gyr[1];
- Temporary_array1[1] = 2 * C[1] - C[0] * dt * gyr[2] + C[2] * dt * gyr[0];
- Temporary_array1[2] = 2 * C[2] + C[0] * dt * gyr[1] - C[1] * dt * gyr[0];
- Temporary_array1[3] = 2 * C[3] + C[4] * dt * gyr[2] - C[5] * dt * gyr[1];
- Temporary_array1[4] = 2 * C[4] - C[3] * dt * gyr[2] + C[5] * dt * gyr[0];
- Temporary_array1[5] = 2 * C[5] + C[3] * dt * gyr[1] - C[4] * dt * gyr[0];
- Temporary_array1[6] = 2 * C[6] + C[7] * dt * gyr[2] - C[8] * dt * gyr[1];
- Temporary_array1[7] = 2 * C[7] - C[6] * dt * gyr[2] + C[8] * dt * gyr[0];
- Temporary_array1[8] = 2 * C[8] + C[6] * dt * gyr[1] - C[7] * dt * gyr[0];
- multiply3x3(Temporary_array1, Temporary_array2, C);
- }
- float max_window_val(float *window, int window_size)
- {
- float val = window[0];
- for (int i = 0; i < window_size; i++)
- {
- if (window[i] > val)
- val = window[i];
- }
- return val;
- }
- int max_window_int(int *window, int window_size)
- {
- int val = window[0];
- for (int i = 0; i < window_size; i++)
- {
- if (window[i] > val)
- val = window[i];
- }
- return val;
- }
- float min_window_val(float *window, int window_size)
- {
- float val = window[0];
- for (int i = 0; i < window_size; i++)
- {
- if (window[i] < val)
- val = window[i];
- }
- return val;
- }
- int min_window_int(int *window, int window_size)
- {
- int val = window[0];
- for (int i = 0; i < window_size; i++)
- {
- if (window[i] < val)
- val = window[i];
- }
- return val;
- }
- //press_tren 函数功能:提供走路过程中上升沿,下降沿
- //1 为上升 2 为 下降 0为不需要得状态
- int press_trend(int index, int *window, int window_size)
- {
- int i;
- int max_val = window[(index - 1) % window_size];
- int max_index = index;
- int min_val = max_val;
- int min_index = max_index;
- for (i = 1; i < window_size + 1; i++)
- {
- if (max_val < window[(index - i) % window_size])
- {
- max_index = index - i + 1;
- max_val = window[(index - i) % window_size];
- }
- if (min_val > window[(index - i) % window_size])
- {
- min_index = index - i + 1;
- min_val = window[(index - i) % window_size];
- }
- }
- if (max_index > min_index && max_val > min_val + 50000)
- {
- return 1;
- }
- if (max_index < min_index && max_val > min_val + 50000)
- {
- return 2;
- }
- return 0;
- }
- void dcm2angle(float *dcm, float *roll, float *pitch, float *yaw)
- {
- *yaw = atan2(dcm[3], dcm[0]);
- *pitch = asin(-dcm[6]);
- *roll = atan2(dcm[7], dcm[8]);
- }
- void quat2angleTest(float qin[4], float *roll, float *pitch, float *yaw)
- {
- //float r11 = qin[0] * qin[0] + qin[1] * qin[1] - qin[2] * qin[2] - qin[3] * qin[3];
- float r11 = 2.0f * (qin[1] * qin[2] + qin[0] * qin[3]);
- //float r21 = 2.0f * (qin[1] * qin[2] - qin[0] * qin[3]);
- float r12 = qin[0] * qin[0] + qin[1] * qin[1] - qin[2] * qin[2] - qin[3] * qin[3];
- float r21 = -2.0f * (qin[1] * qin[3] - qin[0] * qin[2]);
- float r31 = 2.0f * (qin[2] * qin[3] + qin[0] * qin[1]);
- float r32 = qin[0] * qin[0] - qin[1] * qin[1] - qin[2] * qin[2] + qin[3] * qin[3];
- if (r21 < -0.999999999f)
- r21 = -1.0f;
- else if (r21 > 0.999999999f)
- r21 = 1.0f;
- *roll = atan2(r11, r12);
-
- *pitch = asin(r21);
-
- *yaw = atan2(r31, r32);
- }
- void dcm2angleTest(float C[9], short att[3])
- {
- float yaw, pitch, roll;
-
- pitch = asin(-C[6]);
-
- if(C[6] > 0.999999f || C[6] < -0.999999f)
- {
- //当俯仰角为90度的时候,则假设翻滚角为0度
- yaw = atan2(-C[1], C[4]);
-
- roll = 0.0f;
- }
- else
- {
- yaw = atan2(C[3], C[0]);
-
- roll = atan2(C[7], C[8]);
- }
-
- att[0] = (short)(yaw * 10000.f); //yaw
- att[1] = (short)(pitch * 10000.f); //pitch
- att[2] = (short)(roll * 10000.f); //roll
- }
- void quat2dcm(float *qin, float *dcm)
- {
- float qin_norm = 1 / sqrt(qin[0] * qin[0] + qin[1] * qin[1] + qin[2] * qin[2] + qin[3] * qin[3]);
-
- for (int i = 0; i < 4; i++)
- qin[i] *= qin_norm;
- dcm[0] = qin[0] * qin[0] + qin[1] * qin[1] - qin[2] * qin[2] - qin[3] * qin[3];
- dcm[1] = 2.0f * (qin[1] * qin[2] + qin[0] * qin[3]);
- dcm[2] = 2.0f * (qin[1] * qin[3] - qin[0] * qin[2]);
- dcm[3] = 2.0f * (qin[1] * qin[2] - qin[0] * qin[3]);
- dcm[4] = qin[0] * qin[0] - qin[1] * qin[1] + qin[2] * qin[2] - qin[3] * qin[3];
- dcm[5] = 2.0f * (qin[2] * qin[3] + qin[0] * qin[1]);
- dcm[6] = 2.0f * (qin[1] * qin[3] + qin[0] * qin[2]);
- dcm[7] = 2.0f * (qin[2] * qin[3] - qin[0] * qin[1]);
- dcm[8] = qin[0] * qin[0] - qin[1] * qin[1] - qin[2] * qin[2] + qin[3] * qin[3];
- }
- void multiply3x3T(float *a, float *b, float* dst)
- {
- dst[0] = a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
- dst[1] = a[0] * b[3] + a[1] * b[4] + a[2] * b[5];
- dst[2] = a[0] * b[6] + a[1] * b[7] + a[2] * b[8];
- dst[3] = a[3] * b[0] + a[4] * b[1] + a[5] * b[2];
- dst[4] = a[3] * b[3] + a[4] * b[4] + a[5] * b[5];
- dst[5] = a[3] * b[6] + a[4] * b[7] + a[5] * b[8];
- dst[6] = a[6] * b[0] + a[7] * b[1] + a[8] * b[2];
- dst[7] = a[6] * b[3] + a[7] * b[4] + a[8] * b[5];
- dst[8] = a[6] * b[6] + a[7] * b[7] + a[8] * b[8];
- }
- void deltaAttMatrix(float C_prev[9], float C_now[9], float deltaC[9])
- {
- //detaC = C_prev'* C;
- deltaC[0] = C_now[0] * C_prev[0] + C_now[3] * C_prev[3] + C_now[6] * C_prev[6];
- deltaC[1] = C_now[1] * C_prev[0] + C_now[4] * C_prev[3] + C_now[7] * C_prev[6];
- deltaC[2] = C_now[2] * C_prev[0] + C_now[5] * C_prev[3] + C_now[8] * C_prev[6];
- deltaC[3] = C_now[0] * C_prev[1] + C_now[3] * C_prev[4] + C_now[6] * C_prev[7];
- deltaC[4] = C_now[1] * C_prev[1] + C_now[4] * C_prev[4] + C_now[7] * C_prev[7];
- deltaC[5] = C_now[2] * C_prev[1] + C_now[5] * C_prev[4] + C_now[8] * C_prev[7];
- deltaC[6] = C_now[0] * C_prev[2] + C_now[3] * C_prev[5] + C_now[6] * C_prev[8];
- deltaC[7] = C_now[1] * C_prev[2] + C_now[4] * C_prev[5] + C_now[7] * C_prev[8];
- deltaC[8] = C_now[2] * C_prev[2] + C_now[5] * C_prev[5] + C_now[8] * C_prev[8];
- }
- void resetUKF(float *UKF_Q, float UKF_P[4][4], float *mag_prev, float *mag, float *UKF_C, float *C)
- {
- memset(UKF_Q, 0, 4 * sizeof(float));
- UKF_Q[0] = 1.0f;
- memcpy(mag_prev, mag, 3 * sizeof(float));
- memcpy(UKF_C, C, 9 * sizeof(float));
- for (int i = 0; i < 4; i++)
- for (int j = 0; j < 4; j++)
- {
- UKF_P[i][j] = 0.0f;
- }
- for (int i = 0; i < 4; i++)
- {
- UKF_P[i][i] = 0.0000001f;
- }
- }
- //利用陀螺仪的双极端盘判断是否在稳定的范围
- int isStandCon(float gyr_extreme[6])
- {
- if(gyr_extreme[1] - gyr_extreme[0] < 0.008f && gyr_extreme[3] - gyr_extreme[2] < 0.008f && gyr_extreme[5] - gyr_extreme[4] < 0.008f)
- {
- return 1;
- }
-
- return 0;
- }
- unsigned char footPDR(int num, float *gyr, float *acc, float *mag ,int press, int16_t* pos_res, int16_t* att, int16_t* zupt)
- {
- unsigned char movement_e = 0;
- for (int i = 0; i < 3; i++)
- {
- accSum_xyz[i] += acc[i];
- magSum_xyz[i] += mag[i];
-
- gyr[i] *= (PI / 180);
- acc[i] *= g;
- }
-
- if (num_peak == 0)
- {
- for (int i = 0; i < 3; i++)
- {
- gyr_extreme[2 * i] = gyr[i];
- gyr_extreme[2 * i + 1] = gyr[i];
- }
- }
- for (int i = 0; i < 3; i++)
- {
- if (gyr[i] < gyr_extreme[2 * i])
- {
- gyr_extreme[2 * i] = gyr[i];
- }
- if (gyr[i] > gyr_extreme[2 * i + 1])
- {
- gyr_extreme[2 * i + 1] = gyr[i];
- }
- }
- accSum += sqrt(acc[0] * acc[0] + acc[1] * acc[1] + acc[2] * acc[2]);
- for (int i = 0; i < 3; i++)
- {
- gyr_mean[i] += gyr[i];
- }
- num_peak++;
- //在线估计陀螺仪的零偏, 6050的零偏偏大
- if (num_peak == 500)
- {
- if (isStandCon(gyr_extreme))
- {
- float accSqrt = 1/sqrt(accSum_xyz[0] * accSum_xyz[0] + accSum_xyz[1] * accSum_xyz[1] + accSum_xyz[2] * accSum_xyz[2]);
- float magSqrt = 1/sqrt(magSum_xyz[0] * magSum_xyz[0] + magSum_xyz[1] * magSum_xyz[1] + magSum_xyz[2] * magSum_xyz[2]);
-
- for(int i = 0; i < 3; i++)
- {
- gyrBias[i] = gyr_mean[i] * 0.002f;
- accSum_xyz[i] *= accSqrt;
- magSum_xyz[i] *= magSqrt;
- }
-
- resetAttbyMag(C, accSum_xyz, magSum_xyz);
- resetUKF(UKF_Q, UKF_P, mag_prev, magSum_xyz, UKF_C, C);
- memset(P, 0, 81 * sizeof(float));
-
- canUKF = 1;
-
- gpio_mt_run(50);
- }
-
- num_peak = 0;
- accSum = 0.0f;
- memset(gyr_mean, 0, 3 * sizeof(float));
- memset(accSum_xyz, 0, 3 * sizeof(float));
- memset(magSum_xyz, 0, 3 * sizeof(float));
- }
- gyr[0] -= gyrBias[0];
- gyr[1] -= gyrBias[1];
- gyr[2] -= gyrBias[2];
- float gyr_norm_xyz = sqrt(gyr[0] * gyr[0] + gyr[1] * gyr[1] + gyr[2] * gyr[2]);
- //需要一个滑动窗口来判断脚步是否在地上
- frame_index++;
- //下面为惯导解算
- if (num == 1 || frame_index < 0)
- {
- Initialize(gyr, acc);
- UKF_para(UKF_L, UKF_alpha, UKF_beta, UKF_kappa, &gamma, wm, wc);
- return movement_e;
- }
- //惯导解算: 姿态矩阵更新
- attitude_matrix_update(C, Temporary_array1, Temporary_array2, gyr, dt);
- //惯导解算: 将IMU坐标系的加速度转换到“导航坐标系”下
- multiply3x1(C, acc, acc_n);
- //惯导解算: 更新IMU速度
- vel_n[0] = vel_n[0] + acc_n[0] * dt;
- vel_n[1] = vel_n[1] + acc_n[1] * dt;
- vel_n[2] = vel_n[2] + (acc_n[2] - g) * dt;
- //惯导解算: 更新IMU位置
- pos_n[0] = pos_n[0] + vel_n[0] * dt;
- pos_n[1] = pos_n[1] + vel_n[1] * dt;
- pos_n[2] = pos_n[2] + vel_n[2] * dt;
-
- //ekf步骤: 状态协方差矩阵预测更新
- //P = F*P*F' + Q;
- State_covariance_matrix_update(P, acc_n, dt);
- int window_index = (frame_index - 1) % 10;
- float gyr_norm_xz = sqrt(gyr[0] * gyr[0] + gyr[1] * gyr[1] + gyr[2] * gyr[2]);
- gyr_norm_window[window_index] = gyr_norm_xz;
- press_data[window_index] = press;
- //当press_trend函数返回是1,判断为踩地上
- // 返回2 的时候,判断为离地
- // 返回0 的时候,需要保持状态
- int press_trend_val = press_trend(frame_index, press_data, 10);
- if (press_trend_val == 1)
- {
- ZUPT_STATUS = 1;
- }
- else if (press_trend_val == 2)
- {
- ZUPT_STATUS = 2;
- }
- //RUN_ZUPT mean detect on floor when running
- int RUN_ZUPT = 0;
- if ((frame_index > 10 && ZUPT_STATUS == 1))
- RUN_ZUPT = 1;
- //STAND_ZUPT mean detect on floor when no any moving
- int STAND_ZUPT = 0;
- if ((frame_index > 15 && gyr_norm_window[window_index] < 0.35f && fabs(min_window_val(gyr_norm_window, 10) - max_window_val(gyr_norm_window, 10)) < 0.1f))
- STAND_ZUPT = 1;
-
- //zupt
- if ((STAND_ZUPT || RUN_ZUPT))
- {
- //计算一步的距离及步数+1
- //做一个计算时间时间,防止非正常走路的情况出来
- if (last_stage == 2 && frame_index - step_time > 30)
- {
- cal_step_data();
- step_time = frame_index;
- }
- stand_num = stand_num + 1;
-
- time_zupt++;
- //ekf步骤: 计算卡尔曼滤波增益
- //K = P*H'/(H*P*H' + R);
- Kalfman_gain(P, Temporary_array1, Temporary_array2, K);
- //ekf步骤: 观测误差更新
- //delta_x = K * [vel_n(:,i);];
- multiply9x3(K, vel_n, delta_x);
- //ekf步骤: 状态协方差矩阵观测更新
- State_covariance_matrix_corr(P, P_prev, K);
- //这里先从设置 delta_x(3) = atan2(C(2,1),C(1,1));
- //意味着每一步的参考方向是IMU X轴方向
- // delta_x[2] = atan2(C[3], C[0]);
- // theta = -1.7801 + atan2(C[3], C[0]);
- // theta = 0.0f;
- //delta_x[2] = 0.0f;
- //修正姿态矩阵
- Att_matrix_corr(C, C_prev, Temporary_array1, Temporary_array2, delta_x);
- //修正位置
- pos_n_corr(pos_n, delta_x);
- //修正速度
- vel_n_corr(vel_n, delta_x);
- last_pos_n[0] = pos_n[0];
- last_pos_n[1] = pos_n[1];
- last_pos_n[2] = pos_n[2];
- last_stage = 1;
- *zupt = 1;
- }
- else
- {
- stand_num = 0;
- *zupt = 0;
- }
- //融合磁力计数据
- //
-
- float mag_norm = sqrt(mag[0] * mag[0] + mag[1] * mag[1] + mag[2] * mag[2]);
-
- if(STAND_ZUPT)
- {
- stand_zupt_count ++;
- }
- else
- {
- stand_zupt_count = 0;
- }
-
- if(stand_zupt_count == 100 &&(mag_norm < 1.2f && mag_norm > 0.8f))
- {
- mag[0] /= mag_norm;
- mag[1] /= mag_norm;
- mag[2] /= mag_norm;
-
- resetUKF(UKF_Q, UKF_P, mag_prev, mag, UKF_C, C);
- memset(P, 0, 81 * sizeof(float));
-
- stand_zupt_count = 0;
- }
- if (canUKF && (mag_norm < 1.2f && mag_norm > 0.8f))
- {
- mag[0] /= mag_norm;
- mag[1] /= mag_norm;
- mag[2] /= mag_norm;
- float magEst[3];
- deltaAttMatrix(UKF_C, C, deltaC);
- multiply3x1(deltaC, mag, magEst);
- UKF_quat(UKF_Q, UKF_P, gyr, mag_prev, magEst, gamma, wm, wc, UKF_L, dt);
- //dcm=C_tmp * quat2dcm(X') * C_tmp' ;
- float dcm[9];
- quat2dcm(UKF_Q, dcm);
- multiply3x3(UKF_C, dcm, deltaC);
- multiply3x3T(deltaC, UKF_C, dcm);
- dcm2angle(dcm, &EKF_roll, &EKF_pitch, &EKF_yaw);
- //float ukf_norm = 1 / sqrt(UKF_Q[0] * UKF_Q[0] + UKF_Q[1] * UKF_Q[1] + UKF_Q[2] * UKF_Q[2] + UKF_Q[3] * UKF_Q[3]);
- //UKF_Q[0] *= ukf_norm;
- //UKF_Q[1] *= ukf_norm;
- //UKF_Q[2] *= ukf_norm;
- //UKF_Q[3] *= ukf_norm;
- //quat2angle(UKF_Q, UKF_yaw, UKF_pitch, UKF_roll);
-
- Kalfman_gain_angle(P, Temporary_array1, Temporary_array2, K);
- State_covariance_matrix_corr_angle(P, P_prev, K);
- float angleErr[3];
- angleErr[0] = 0.1f*( EKF_roll);
- angleErr[1] = 0.1f*( EKF_pitch);
- angleErr[2] = 0.1f*( EKF_yaw);
- multiply9x3(K, angleErr, delta_x);
- Att_matrix_corr(C, C_prev, Temporary_array1, Temporary_array2, delta_x);
- //修正位置
- pos_n_corr(pos_n, delta_x);
- //修正速度
- vel_n_corr(vel_n, delta_x);
-
- }
-
- //状态协方差矩阵保持正交性,以防出现退化
- State_covariance_matrix_orthogonalization(P);
- memcpy(last_vel_n, vel_n, 3 * sizeof(float));
- pos_offset[0] = pos_n[0] - last_pos_n[0];
- pos_offset[1] = pos_n[1] - last_pos_n[1];
- pos_offset[2] = pos_n[2] - last_pos_n[2];
-
- dcm2angleTest(C, att); //航向角,俯仰角, 翻滚角(z y x)
- // att[0] = (short)(atan2(C[3], C[0]) * 10000.f); //yaw
- // att[1] = (short)(asin(-C[6]) * 10000.f); //pitch
- // att[2] = (short)(atan2(C[7], C[8]) * 10000.f); //roll
- // att[0] = (short)(1 ); //yaw
- // att[1] = (short)(2 ); //pitch
- // att[2] = (short)(3 ); //roll
- pos_res[0] = (short) (pos_offset[0] * 100.0f);
- pos_res[1] = (short) (pos_offset[1] * 100.0f);
- pos_res[2] = (short) (pos_offset[2] * 100.0f);
- if ((pos_res[0] * pos_res[0] + pos_res[1] * pos_res[1] + pos_res[2] * pos_res[2]) > 10)
- {
- last_stage = 2;
- }
- return movement_e;
- }
|