GeekIMU/4.Software/GeekIMUDriver 1.0/Src/SensorImpl.cpp

638 lines
17 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include "windows.h"
#include "SensorImpl.h"
#include "stdio.h"
#include "quaternion.h"
#include "math.h"
#include "UsbHid_CAPI.h"
#include "MyCls.h"
extern "C" FILE* fpdata;
Quaternion GlobalQ;
BOOL GlobalQ_Updating;
float LocX,LocY,LocZ;
float Yaw,Pitch,Roll;
extern FILE* Getfpdata();
extern int global_calibration_flag;
extern int global_Show;
UINT8 global_key[4] = { 0 };
float gxc=0, gyc=0, gzc=0;
int gyro_cali_count = 0;
#define GYRO_CALIBRATION_SAMPLE_NUMBER 3000
float gx0=0, gy0=0, gz0=0;
BOOL GlobalMag_Updating = false;
Vector3 GlobalMag = {0};
static bool HmdStandByState;
void MagFilter(float *mx,float *my,float *mz,float sita);
void GyroComputeDrift(float *gx, float *gy, float *gz);
void LowPassFilterYaw(float *z, float alpha);
bool IsHmdIntoStandBy(float *Pitch, float *Roll, float dTime);
void UnpackSensor(const UCHAR* buffer, long* x, long* y, long* z)
{
struct {INT32 x:21;} s;
*x = s.x = (buffer[0] << 13) | (buffer[1] << 5) | ((buffer[2] & 0xF8) >> 3);
*y = s.x = ((buffer[2] & 0x07) << 18) | (buffer[3] << 10) | (buffer[4] << 2) |
((buffer[5] & 0xC0) >> 6);
*z = s.x = ((buffer[5] & 0x3F) << 15) | (buffer[6] << 7) | (buffer[7] >> 1);
}
Vector3 DM_GetMag()
{
Vector3 v = { 0 };
static Vector3 VLast = { 0 };
if (!GlobalMag_Updating)
{
VLast = GlobalMag;
}
v = VLast;
return v;
}
void GetControllerSensor(unsigned char usb_input_buffer[])
{
static UINT8 updatecnt = 0;
INT16 MagX,MagY,MagZ;
INT16 MagX1, MagY1, MagZ1;
long GX,GY,GZ;
long AX,AY,AZ;
UINT NowTime;
float ax, ay, az, gx, gy, gz, mx, my, mz, mx1, my1, mz1;;
static float mxlast=0,mylast=0,mzlast=0;
static int Dtime = 0;
static UINT LastTime = 0;
float q0,q1,q2,q3;
NowTime = *(UINT16* )(usb_input_buffer+2);
if(LastTime != 0)
{
if(NowTime >= LastTime)
{
Dtime = NowTime - LastTime;
LastTime = NowTime;
}else
{
Dtime = (65535 - LastTime) + NowTime;
//printf("NowTime = %d LastTime = %d Dtime = %d\n",NowTime,LastTime,Dtime);
LastTime = NowTime;
}
}else
{
Dtime = 1;
LastTime = NowTime;
}
if (global_Show==5)
{
//clrscr();
back2zero();
printf("Hex<EFBFBD><EFBFBD><EFBFBD><EFBFBD>\n\n");
for (int i = 0; i < 64; i++)
{
if ((i%16)==0)
{
printf("\n");
}
//if (global_debug)
printf("%2x ", usb_input_buffer[i]);
}
printf("\n");
}
//if(Dtime>3)printf("NowTime = %d LastTime = %d Dtime = %d\n",NowTime,LastTime,Dtime);
// MagX1 = *(INT16 *)(usb_input_buffer + 46);
// MagY1 = *(INT16 *)(usb_input_buffer + 48);
// MagZ1 = *(INT16 *)(usb_input_buffer + 50);
MagX = *(INT16 *)(usb_input_buffer + 56);
MagY = *(INT16 *)(usb_input_buffer + 58);
MagZ = *(INT16 *)(usb_input_buffer + 60);
UnpackSensor(usb_input_buffer+8, &AX,&AY,&AZ);
UnpackSensor(usb_input_buffer+16, &GX,&GY,&GZ);
ax = (float)0.0001*AX;
ay = (float)0.0001*AY;
az = (float)0.0001*AZ;
gx = (float)0.0001*GX;
gy = (float)0.0001*GY;
gz = (float)0.0001*GZ;
float x = 16.4 * 180 / 3.14159265358979323846F;
if (global_Show == 1)
{
printf("gx = %f,gy = %f gz =%f\n", gx*x, gy*x, gz*x);
}
GyroComputeDrift(&gx, &gy, &gz);
if (global_calibration_flag == 1)
{
if (gyro_cali_count > GYRO_CALIBRATION_SAMPLE_NUMBER)
{
gyro_cali_count = 0;
gxc = gyc = gzc = 0;
}
gyro_cali_count++;
gxc += gx*x;
gyc += gy*x;
gzc += gz*x;
if (gyro_cali_count == GYRO_CALIBRATION_SAMPLE_NUMBER)
{
gx0 = gxc / gyro_cali_count;
gy0 = gyc / gyro_cali_count;
gz0 = gzc / gyro_cali_count;
gyro_cali_count++;
global_calibration_flag = 0;
printf("%f %f %f\n", gx0, gy0, gz0);
}
}
// q0 = *(float *)(usb_input_buffer+24);
// q1 = *(float *)(usb_input_buffer+28);
// q2 = *(float *)(usb_input_buffer+32);
// q3 = *(float *)(usb_input_buffer+36);
// q0 = *(float *)(usb_input_buffer + 32);
// q1 = *(float *)(usb_input_buffer + 36);
// q2 = *(float *)(usb_input_buffer + 40);
// q3 = *(float *)(usb_input_buffer + 44);
global_key[0] = usb_input_buffer[24];
//global_key[0] = usb_input_buffer[25];
//global_key[0] = usb_input_buffer[26];
global_key[3] = usb_input_buffer[27];
// GlobalQ_Updating = TRUE;
// GlobalQ.w = q0;
// GlobalQ.x = q2;
// GlobalQ.y = q3;
// GlobalQ.z = q1;
// GlobalQ_Updating = FALSE;
// Pitch = asin(-2.0f*(q3*q1 - q0*q2))* (180.0f / 3.141592f); /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD>ŷ<EFBFBD><C5B7><EFBFBD>ǵ<EFBFBD>ת<EFBFBD><D7AA> */
// Yaw = atan2(q2*q1 + q0*q3, 0.5f - q2*q2 - q3*q3)* (180.0f / 3.141592f);
// Roll = atan2(q2*q3 + q0*q1, 0.5f - q2*q2 - q1*q1)* (180.0f / 3.141592f);
//
// if (global_Show == 4)
// printf("Yaw = %f,Pitch = %f Roll =%f\n", Yaw, Pitch, Roll);
mx = (float)MagX / 16;
my = (float)MagY / 16;
mz = (float)MagZ / 16;
if (global_calibration_flag==3)
{
GlobalMag_Updating = true;
mx = (float)MagX;
my = (float)MagY;
mz = (float)MagZ;
// mx1 = (float)MagX1;
// my1 = (float)MagY1;
// mz1 = (float)MagZ1;
GlobalMag.x = (float)MagX;
GlobalMag.y = (float)MagY;
GlobalMag.z = (float)MagZ;
GlobalMag_Updating = false;
}
// mx = (float)MagX;
// my = (float)MagY;
// mz = (float)MagZ;
//Pitch = asin(-2.0f*(q3*q1-q0*q2))* (180.0f /3.141592f); /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD>ŷ<EFBFBD><C5B7><EFBFBD>ǵ<EFBFBD>ת<EFBFBD><D7AA> */
//Yaw = atan2(q2*q1 + q0*q3,0.5f - q2*q2 - q3*q3)* (180.0f /3.141592f);
//Roll = atan2(q2*q3 + q0*q1,0.5f - q2*q2 - q1*q1)* (180.0f /3.141592f);
//
//printf("Yaw = %f,Pitch = %f Roll =%f\n",Yaw,Pitch,Roll);
if(mxlast == 0&&mylast == 0&&mylast == 0)
{
mxlast = mx;
mylast = my;
mzlast = mz;
MagFilter(&mx, &my, &mz, 0.95f);
for (int i = 0; i < 200; i++)
AHRSupdate(0, 0, 0, az, ax, ay, mz, mx, my, 1, Dtime * 400);
}
else
{
updatecnt++;
if (updatecnt > 10)
updatecnt = 0;
if (mx == mxlast&&my == my&&mz == mzlast && updatecnt < 10)
{
AHRSupdate(gz,gx,gy,az,ax,ay,mz,mx,my,1,Dtime);
//printf("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD><C8AB>ͬ...\n");
}
else
{
mxlast = mx;
mylast = my;
mzlast = mz;
// if (global_Show == 3)
// printf("mx = %f my= %f mz= %f\n", mx, my, mz);
// if (global_calibration_flag == 3)
// {
//
// if (Getfpdata() != NULL)
// {
// fprintf(Getfpdata(), "%f %f %f\n", mx, my, mz);
// Sleep(5);
// }
// }
MagFilter(&mx,&my,&mz,0.95f);
// printf("mx = %f my= %f mz= %f\n", mx, my, mz);
// if (Getfpdata()!=NULL)
// {
// fprintf(Getfpdata(), "%f %f %f\n", mx, my, mz);
// }
AHRSupdate(gz,gx,gy,az,ax,ay,mz,mx,my,1,Dtime);
}
}
//printf("mx = %f my= %f mz= %f\n",mx,my,mz);
}
/**********************************************************************************************************
* Function Name : AHRSupdate
* <20><><EFBFBD><EFBFBD> : <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٶȼơ<C8BC><C6A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǡ<EFBFBD><C7A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƶ<EFBFBD>ֵ
* <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ٶȼơ<C8BC><C6A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǡ<EFBFBD><C7A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ںϵõ<CFB5><C3B5><EFBFBD>ŷ<EFBFBD><C5B7><EFBFBD><EFBFBD>
1<><31><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E3B7A8><EFBFBD>ڱ<EFBFBD>׼<EFBFBD>ѿ<EFBFBD><D1BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD><CFB5>z<EFBFBD><EFBFBD>ϣ<EFBFBD>x<EFBFBD><EFBFBD>ˣ<EFBFBD>y<EFBFBD><EFBFBD><E1B3AF>
2<><32><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ķ<EFBFBD><C4B7><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><E4BBBB><EFBFBD>͸<EFBFBD><CDB8><EFBFBD><E3B7A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><CDAC>
* <20>޸<EFBFBD> <20><>2016/11/5 : <20><><EFBFBD>ݴ<EFBFBD><DDB4><EFBFBD><EFBFBD>Ʋ<EFBFBD><C6B2><EFBFBD><EFBFBD>ʱȽϵ͵<CFB5><CDB5>ص㣬<D8B5><E3A3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>2<EFBFBD><32>ģʽ<C4A3><CABD>1<EFBFBD><31><EFBFBD>ںϴ<DABA><CFB4><EFBFBD><EFBFBD><EFBFBD> 2<><32><EFBFBD><EFBFBD><EFBFBD>ںϴ<DABA><CFB4><EFBFBD><EFBFBD><EFBFBD>
2016/11/6 <20><><EFBFBD>Ľ<EFBFBD><C4BD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E3B7A8>ԭ<EFBFBD><D4AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E1B5BC><EFBFBD>ۼ<EFBFBD><DBBC><EFBFBD><EFBFBD>
2016/11/9 : <20><EFBFBD>˱<EFBFBD><CBB1><EFBFBD><E3B7A8><EFBFBD>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E1A3AC>д<EFBFBD><D0B4><EFBFBD><EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD>ŷ<EFBFBD><C5B7><EFBFBD>DZ任<C7B1>Ĵ<EFBFBD><C4B4>
***********************************************************************************************************/
float q0 = 1, q1 = 0, q2 = 0, q3 = 0;
float exInt = 0, eyInt = 0, ezInt = 0; /*<2A><><EFBFBD>Ż<EFBFBD><C5BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
#define Kp 2.5f /*<2A><><EFBFBD>ٶȼƺʹ<C6BA><CDB4><EFBFBD><EFBFBD>ƶ<EFBFBD><C6B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǵı<C7B5><C4B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
#define Ki 0.005f /*<2A><><EFBFBD>ٶȼƺʹ<C6BA><CDB4><EFBFBD><EFBFBD>ƶ<EFBFBD><C6B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǵĻ<C7B5><C4BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
#define Kd 0.0f
static int AHRS_Init = 0;
void ResetAHRS(){ AHRS_Init = 0; q0 = 1; q1 = 0; q2 = 0; q3 = 0; }
void AHRSupdate(float gx, float gy, float gz, float ax, float ay, float az, float mx, float my, float mz, char useMag, int Dtime)
{
/*ԭ<><EFBFBD>Ķ<EFBFBD><C4B6><EFBFBD>*/
float norm, halfT;
float hx, hy, hz, bz, by;
float vx, vy, vz, wx, wy, wz;
float ex, ey, ez;
float qw, qx, qy, qz;
float AccelAjust, MagAjust;
/*<2A><><EFBFBD><EFBFBD>֮<EFBFBD><D6AE><EFBFBD>ij<EFBFBD><C4B3><EFBFBD>ʹ<EFBFBD>ã<EFBFBD><C3A3><EFBFBD><EFBFBD>ټ<EFBFBD><D9BC><EFBFBD>ʱ<EFBFBD><CAB1>*/
float q0q0 = q0*q0; float q0q1 = q0*q1;
float q0q2 = q0*q2; float q0q3 = q0*q3;
float q1q1 = q1*q1; float q1q2 = q1*q2;
float q1q3 = q1*q3; float q2q2 = q2*q2;
float q2q3 = q2*q3; float q3q3 = q3*q3;
if (AHRS_Init > 200)
{
halfT = 0.0005f*Dtime; /*<2A>õ<EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD>̬<EFBFBD><CCAC><EFBFBD>µ<EFBFBD><C2B5><EFBFBD><EFBFBD>ڵ<EFBFBD>һ<EFBFBD><D2BB>t = (1/SampleFrq) * 0.5 */
}
else
{
if (useMag == 1)
{
halfT = 0.1;
gx = gy = gz = 0;
AHRS_Init++;
}
else
{
return;
}
}
norm = invSqrt(ax*ax + ay*ay + az*az); /*<2A>Ѽ<EFBFBD><D1BC>ٶȼ<D9B6><C8BC><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><D7AA>Ϊ<EFBFBD><CEAA>λ<EFBFBD><CEBB><EFBFBD><EFBFBD>*/
if ((1.0f / norm) > 1.6 || (1.0f / norm) < 0.4){
AccelAjust = 0;
MagAjust = 1.2f;
}
else{
AccelAjust = 1.0f;
MagAjust = 1.0f;
}
// printf("<22><><EFBFBD>ٶȹ<D9B6><C8B9><EFBFBD>...\n");
// getchar();
ax = ax * norm;
ay = ay * norm;
az = az * norm; /*<2A>Ѵ<EFBFBD><D1B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><D7AA>Ϊ<EFBFBD><CEAA>λ<EFBFBD><CEBB><EFBFBD><EFBFBD> */
norm = invSqrt(mx*mx + my*my + mz*mz);
mx = mx * norm;
my = my * norm;
mz = mz * norm;
hx = 2.0f*(mx*(0.5f - q2q2 - q3q3) + my*(q1q2 - q0q3) + mz*(q1q3 + q0q2)); /*<2A><>(mx,my,mz)ת<><D7AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD><CFB5>(hx,hy,hz),<2C><><EFBFBD><EFBFBD>H = Q^-1 * M */
hy = 2.0f*(mx*(q1q2 + q0q3) + my*(0.5f - q1q1 - q3q3) + mz*(q2q3 - q0q1));
hz = 2.0f*(mx*(q1q3 - q0q2) + my*(q2q3 + q0q1) + mz*(0.5f - q1q1 - q2q2));
/*<2A>Ƶ<EFBFBD><C6B5><EFBFBD>ֵΪ(bx,by,0),<2C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Dz<EFBFBD><C7B2><EFBFBD>עhx<68><78><EFBFBD><EFBFBD>ֵ */
// bx = sqrtf((hx*hx) + (hy*hy)); /*ʹ<><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
by = sqrtf((hx*hx) + (hy*hy));
bz = hz;
/*v<><76><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰѵ<C7B0><D1B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD>ļ<EFBFBD><C4BC>ٶ<EFBFBD>(0,0,1g)ת<><D7AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD>ļ<EFBFBD> */
vx = 2.0f*(q1q3 - q0q2); /*<2A>ٶȼ<D9B6>(ax,ay,az),<2C><>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>R*(0,0,1),RΪ<52><CEAA>ת<EFBFBD><D7AA><EFBFBD>󣬴˾<F3A3ACB4><CBBE><EFBFBD><EFBFBD><EFBFBD> */
vy = 2 * (q0q1 + q2q3); /*<2A><><EFBFBD><EFBFBD>Ԫ<EFBFBD><D4AA>ת<EFBFBD><D7AA><EFBFBD>õ<EFBFBD> */
vz = q0q0 - q1q1 - q2q2 + q3q3;
wx = 2.0f*(by*(q1q2 + q0q3) + bz*(q1q3 - q0q2)); /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>H<EFBFBD><48>B<EFBFBD>ӵ<EFBFBD><D3B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵת<CFB5><D7AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD><CFB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>W = Q * B */
wy = 2.0f*(by*(0.5f - q1q1 - q3q3) + bz*(q0q1 + q2q3)); /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊbx = 0 */
wz = 2.0f*(by*(q2q3 - q0q1) + bz*(0.5f - q1q1 - q2q2));
/*<2A><><EFBFBD><EFBFBD>ʹ<EFBFBD>ô<EFBFBD><C3B4><EFBFBD><EFBFBD>ƣ<EFBFBD><C6A3><EFBFBD><EFBFBD>ںϴ<DABA><CFB4><EFBFBD><EFBFBD><EFBFBD>*/
if (useMag != 0)
{ /*<2A>õ<EFBFBD>ǰ<EFBFBD><C7B0>̬<EFBFBD><CCAC><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC>ٶȵ<D9B6><C8B5><EFBFBD>̬<EFBFBD><CCAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ˣ<EFBFBD><CBA3>˻<EFBFBD>ԽС˵<D0A1><CBB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Խ<EFBFBD><D4BD>ͬ*/
ex = AccelAjust*(ay*vz - az*vy) + MagAjust*(my*wz - mz*wy);
ey = AccelAjust*(az*vx - ax*vz) + MagAjust*(mz*wx - mx*wz);
ez = AccelAjust*(ax*vy - ay*vx) + MagAjust*(mx*wy - my*wx);
}
else
{
ex = AccelAjust*(ay*vz - az*vy);
ey = AccelAjust*(az*vx - ax*vz); /*<2A><>Ϊ<EFBFBD><CEAA><EFBFBD>ٶȼ<D9B6>û<EFBFBD><C3BB>У׼<D0A3><D7BC>ez<65><7A><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
ez = AccelAjust*(ax*vy - ay*vx);
ez = 0;
}
if (ex != 0.0f && ey != 0.0f && ez != 0.0f)
{
/*<2A><><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD>PID<49><44><EFBFBD>ڵķ<DAB5>ʽ<EFBFBD><CABD><EFBFBD>Խ<EFBFBD><D4BD>ٶ<EFBFBD><D9B6><EFBFBD><EFBFBD><EFBFBD>,Ki <20>ǻ<EFBFBD><C7BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Kp<4B><70>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
exInt = exInt + ex*Ki * halfT; /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD><D0BB><EFBFBD> */
eyInt = eyInt + ey*Ki * halfT;
ezInt = ezInt + ez*Ki * halfT;
gx = gx + Kp*(1 + Kd*fabsf(ex))*ex + exInt; /*ʹ<>ñ<EFBFBD><C3B1><EFBFBD><EFBFBD>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD>ۺ϶<DBBA><CFB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǽ<EFBFBD><C7BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><DAB4>ڻ<EFBFBD><DABB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Բ<EFBFBD><D4B2><EFBFBD>ȷ<EFBFBD><C8B7><EFBFBD><EFBFBD> */
gy = gy + Kp*(1 + Kd*fabsf(ey))*ey + eyInt; /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD><D8B5><EFBFBD>λ<EFBFBD><CEBB> */
gz = gz + Kp*(1 + Kd*fabsf(ez))*ez + ezInt;
}
qw = (-q1*gx - q2*gy - q3*gz)*halfT; /*<2A><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD><EFBFBD>и<EFBFBD><D0B8><EFBFBD>*/
qx = (q0*gx + q2*gz - q3*gy)*halfT;
qy = (q0*gy - q1*gz + q3*gx)*halfT;
qz = (q0*gz + q1*gy - q2*gx)*halfT;
q0 = q0 + qw;
q1 = q1 + qx;
q2 = q2 + qy;
q3 = q3 + qz;
//QuaternionFilter(&q1,&q2,&q3,0.98f);
//LowPassFilterYaw(&q3,0.98);
norm = invSqrt(q0*q0 + q1*q1 + q2*q2 + q3*q3); /*<2A><><EFBFBD><EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD><EFBFBD>й淶<D0B9><E6B7B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD><D4AA>ģΪ1*/
q0 = q0 * norm; //w
q1 = q1 * norm; //x
q2 = q2 * norm; //y
q3 = q3 * norm; //z
/*<2A><>ԭ<EFBFBD><EFBFBD><E4BBBB>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD><D2B5><EFBFBD><EFBFBD><EFBFBD><E2A3AC><EFBFBD>ձ<EFBFBD>׼<EFBFBD><D7BC>ѧ<EFBFBD><D1A7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
// Pitch = asin(-2.0f*(q3*q1 - q0*q2))* (180.0f / 3.141592f); /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD>ŷ<EFBFBD><C5B7><EFBFBD>ǵ<EFBFBD>ת<EFBFBD><D7AA> */
// Yaw = atan2(q2*q1 + q0*q3, 0.5f - q2*q2 - q3*q3)* (180.0f / 3.141592f);
// Roll = atan2(q2*q3 + q0*q1, 0.5f - q2*q2 - q1*q1)* (180.0f / 3.141592f);
// /*<2A><>ԭ<EFBFBD><EFBFBD><E4BBBB>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD><D2B5><EFBFBD><EFBFBD><EFBFBD><E2A3AC><EFBFBD>ձ<EFBFBD>׼y<D7BC><79>x<EFBFBD><78>z<EFBFBD><7A>*/
// Pitch = asin(-2.0f*(q2*q3 - q0*q1))* (180.0f / 3.141592f); /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD>ŷ<EFBFBD><C5B7><EFBFBD>ǵ<EFBFBD>ת<EFBFBD><D7AA> */
// Yaw = atan2(q1*q3 + q0*q2, 0.5f - q1*q1 - q2*q2)* (180.0f / 3.141592f);
// Roll = atan2(q1*q2 + q0*q3, 0.5f - q1*q1 - q3*q3)* (180.0f / 3.141592f);
/*<2A><>ԭ<EFBFBD><EFBFBD><E4BBBB>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD><D2B5><EFBFBD><EFBFBD><EFBFBD><E2A3AC><EFBFBD>ձ<EFBFBD>׼y<D7BC><79>z<EFBFBD><7A>xǰ*/
Pitch = asin(-2.0f*(q2*q1 - q0*q3))* (180.0f / 3.141592f); /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD>ŷ<EFBFBD><C5B7><EFBFBD>ǵ<EFBFBD>ת<EFBFBD><D7AA> */
Yaw = atan2(q3*q1 + q0*q2, 0.5f - q3*q3 - q2*q2)* (180.0f / 3.141592f);
Roll = atan2(q3*q2 + q0*q1, 0.5f - q3*q3 - q1*q1)* (180.0f / 3.141592f);
LowPassFilterYaw(&Yaw, 0.9f);
// if (global_Show == 4)
// printf("Yaw = %f,Pitch = %f Roll =%f\n", Yaw, Pitch, Roll);
if (AHRS_Init > 200)
{
GlobalQ_Updating = TRUE;
GlobalQ.w = q0;
GlobalQ.x = q2;
GlobalQ.y = q3;
GlobalQ.z = q1;
GlobalQ_Updating = FALSE;
}
IsHmdIntoStandBy(&Pitch, &Roll, 1.0f);
}
void MagFilter(float *mx, float *my, float *mz, float sita)
{
static float xlast = 0, ylast = 0, zlast = 0;
if (xlast == 0 && ylast == 0 && ylast == 0)
{
xlast = *mx;
ylast = *my;
zlast = *mz;
}
else
{
xlast = sita*xlast + (1 - sita)*(*mx);
ylast = sita*ylast + (1 - sita)*(*my);
zlast = sita*zlast + (1 - sita)*(*mz);
}
}
/*******************************************************************************
* Function Name : invSqrt
* Description : <20><><EFBFBD>ټ<EFBFBD><D9BC><EFBFBD> 1/Sqrt(x)<29><>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>3<EFBFBD><33><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>0x5f3759df
* <20><><EFBFBD><EFBFBD> : x
* <20><><EFBFBD><EFBFBD> <20><>1/sqrt(x)
*******************************************************************************/
float invSqrt(float x)
{
float halfx = 0.5f * x;
float y = x;
long i = *(long*)&y;
i = 0x5f3759df - (i >> 1);
y = *(float*)&i;
y = y * (1.5f - (halfx * y * y));
return y;
}
void GyroComputeDrift(float *gx, float *gy, float *gz)
{
static float GxOffect = 0.0f, GyOffect = 0.0f, GzOffect = 0.0f;
static float GxOffectTmp = 0.0f, GyOffectTmp = 0.0f, GzOffectTmp = 0.0f;
static float GxTmp = 0.0f, GyTmp = 0.0f, GzTmp = 0.0f;
static int count = 0;
*gx = *gx - GxOffect;
*gy = *gy - GyOffect;
*gz = *gz - GzOffect;
if (HmdStandByState == true){
GxTmp = GxTmp + *gx;
GyTmp = GyTmp + *gy;
GzTmp = GzTmp + *gz;
count++;
if (count == 3000){
//printf("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У׼<D0A3><D7BC><EFBFBD><EFBFBD>\n");
GxOffectTmp = GxTmp / count;
GyOffectTmp = GyTmp / count;
GzOffectTmp = GzTmp / count;
GxOffect = GxOffect + GxOffectTmp;
GyOffect = GyOffect + GyOffectTmp;
GzOffect = GzOffect + GzOffectTmp;
GxTmp = 0.0f;
GyTmp = 0.0f;
GzTmp = 0.0f;
count = 0;
}
}
else{
count = 0;
GxTmp = 0.0f;
GyTmp = 0.0f;
GzTmp = 0.0f;
}
}
void LowPassFilterYaw(float *z, float alpha)
{
static float lastz = 0;
if (lastz == 0)
{
lastz = *z;
}
else
{
*z = alpha*lastz + (1 - alpha)*(*z);
lastz = *z;
}
}
bool IsHmdIntoStandBy(float *Pitch, float *Roll, float dTime)
{
static float LastPitch = 0.0f, LastRoll = 0.0f;
static float LastGyroX = 0.0f, LastGyroY = 0.0f;
static int count = 0;
float GyroX = 0.0f, GyroY = 0.0f, alpha = 0.98f;
/* <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>̬<EFBFBD><CCAC><EFBFBD><EFBFBD> */
if (LastPitch == 0.0f&&LastRoll == 0.0f){
LastPitch = *Pitch;
LastRoll = *Roll;
}
/*<2A><>Pitch<63><68>Roll΢<6C>֣<EFBFBD><D6A3><EFBFBD>Gx<47><78>Gy */
GyroX = fabsf(*Roll - LastRoll) / dTime;
GyroY = fabsf(*Pitch - LastPitch) / dTime;
/*<2A><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>̬<EFBFBD><CCAC><EFBFBD><EFBFBD>*/
if (LastGyroX == 0.0f&&LastGyroY == 0.0f){
LastGyroX = GyroX;
LastGyroY = GyroY;
}
/*<2A><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˲<EFBFBD><CBB2><EFBFBD><EFBFBD><EFBFBD>żȻ<C5BC><C8BB><EFBFBD><EFBFBD>*/
GyroX = alpha*LastGyroX + (1 - alpha)*GyroX;
GyroY = alpha*LastGyroY + (1 - alpha)*GyroY;
if (GyroX < 0.0015f&&GyroY < 0.0015f){
count++;
if (count == 3000){
count = 0;
HmdStandByState = true;
//printf("ͷ<>Խ<EFBFBD><D4BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>\n");
}
}
else{
count = 0;
HmdStandByState = false;
}
/* <20><><EFBFBD>¾<EFBFBD>̬<EFBFBD><CCAC><EFBFBD><EFBFBD> */
LastRoll = *Roll;
LastPitch = *Pitch;
LastGyroX = GyroX;
LastGyroY = GyroY;
return HmdStandByState;
}
float DM_GetYaw(void)
{
return Yaw;
}
float DM_GetPitch(void)
{
return Pitch;
}
float DM_GetRoll(void)
{
return Roll;
}
Quaternion CQ_DM = { 1, 0, 0, 0 };
bool DM_Corrected = false;
Quaternion CorrectQuaterinonYaw(Quaternion q)
{
Quaternion qcorr;
qcorr.w = q.w; qcorr.x = 0.0f;
qcorr.y = q.y; qcorr.z = 0.0f;
qcorr = QuaternionInversion(qcorr);
float mod = QuaternionMod(qcorr);
qcorr.w = qcorr.w / mod;
qcorr.x = qcorr.x / mod;
qcorr.y = qcorr.y / mod;
qcorr.z = qcorr.z / mod;
return qcorr;
}
int DM_Correct(void)
{
Quaternion q = { GlobalQ.w, 0, GlobalQ.y, 0 };
CQ_DM = CorrectQuaterinonYaw(q);
DM_Corrected = true;
return DM_Corrected ? 1 : 0;
}
Quaternion DM_GetPoseQuat(void)
{
static Quaternion QLast = { 1.0f, 0.0f, 0.0f, 0.0f };
if (!GlobalQ_Updating)
{
QLast.w = GlobalQ.w;
QLast.x = GlobalQ.x;
QLast.y = GlobalQ.y;
QLast.z = GlobalQ.z;
}
if (DM_Corrected)
{
return QuaternionMulti(QLast, CQ_DM);
}
else
return QLast;
}