void ahrs_fusion_ag(AxesRaw_TypeDef_Float *acc, AxesRaw_TypeDef_Float *gyro, AHRS_State_TypeDef *ahrs)
{//변수 생성
float axf,ayf,azf,gxf,gyf,gzf;//가속도 3축, 자이로 3축
float norm;//vector norm을 구하기위한 변수
float vx, vy, vz;
float ex, ey, ez;
float q0q0, q0q1, q0q2, /*q0q3,*/ q1q1, /*q1q2,*/ q1q3, q2q2, q2q3, q3q3;
//quaternion 연산을 위한 변수
float halfT;// dt/2
if(gTHR<MIN_THR)//throtle 명령이 최소치(MIN_THR) 보다 작을 경우
{//적분 이득을 올리는 듯 하다. 이건 제어 성능차원에서 넣은듯 싶다.
//자세 제어기 이득은 아니지만 결국엔 자세제어기 입력에 영향을 주게된다.
//확실치는 않지만 지면효과에 의한 외란을 줄이기 위함이라 생각된다
ahrs_kp = AHRS_KP_BIG;
}
else
{
ahrs_kp = AHRS_KP_NORM;
}
//3축 가속도 센서 정보를 저장
axf = acc->AXIS_X;
ayf = acc->AXIS_Y;
azf = acc->AXIS_Z;
// mdps convert to rad/s
gxf = ((float)gyro->AXIS_X) * ((float)COE_MDPS_TO_RADPS);
gyf = ((float)gyro->AXIS_Y) * ((float)COE_MDPS_TO_RADPS);
gzf = ((float)gyro->AXIS_Z) * ((float)COE_MDPS_TO_RADPS);
// auxiliary variables to reduce number of repeated operations
q0q0 = q0*q0;
q0q1 = q0*q1;
q0q2 = q0*q2;
//q0q3 = q0*q3;
q1q1 = q1*q1;
//q1q2 = q1*q2;
q1q3 = q1*q3;
q2q2 = q2*q2;
q2q3 = q2*q3;
q3q3 = q3*q3;
// normalise the accelerometer measurement
norm = invSqrt(axf*axf+ayf*ayf+azf*azf);
// 1/sqrt(...) 연산 bit 연산으로 빠르게 하드웨어친화적 계산
axf = axf * norm;//vector nomalization routine
ayf = ayf * norm;//vector nomalization routine
azf = azf * norm;//vector nomalization routine
// estimated direction of gravity and flux (v and w)
// 지금 자세 쿼터니언을 이용하여 중력 방향의 벡터를 계산하는 것 참고문헌[1]의 식(19) 참고!
// 참고식에서 x, y 가 바뀌어 보이는 이유는 센서 축을 맞추기 위한 것
vx = 2*(q1q3 - q0q2);
vy = 2*(q0q1 + q2q3);
vz = q0q0 - q1q1 - q2q2 + q3q3;
// 구한 가속도 벡터 axf, ayf, azf와 중력 벡터사이의 오차를 구하는 부분
// 외적 연산 ->
// | ex ey ez |
// | ax ay az |
// | vx vy vz | ad-bc 해서 해보면 됩니다. 만약 중력방향과 가속도 벡터가 일치하면
// 올바르게 hovering하고 있는 거니까 error인 ex, ey, ez 가 0이 되겠지요
ex = (ayf*vz - azf*vy);
ey = (azf*vx - axf*vz);
ez = (axf*vy - ayf*vx);
// 이 다음 부터는 가속도 벡터와 중력방향 사이의 오차를 적분하고
// integral error scaled integral gain
exInt = exInt + ex*AHRS_KI*SENSOR_SAMPLING_TIME;
eyInt = eyInt + ey*AHRS_KI*SENSOR_SAMPLING_TIME;
ezInt = ezInt + ez*AHRS_KI*SENSOR_SAMPLING_TIME;
// 이를 자이로 측정치와 같이 하여 적분한다.
// adjusted gyroscope measurements
gxf = gxf + ahrs_kp*ex + exInt;
gyf = gyf + ahrs_kp*ey + eyInt;
gzf = gzf + ahrs_kp*ez + ezInt;
//왜 이렇게 작성한지는 모르겠지만 아마도 이런 방식은 자세제어의 반응성을 더 빠르
//게 할 수 있다는 생각이 든다.
//앞의 식은 quaternion kinematics equation (discrete) 을 코드로 작성한 것이다.
//밑에 식에 대한 설명 추가
// integrate quaternion rate and normalise
halfT = 0.5f*SENSOR_SAMPLING_TIME;
q0 = q0 + (-q1*gxf - q2*gyf - q3*gzf)*halfT;
q1 = q1 + ( q0*gxf + q2*gzf - q3*gyf)*halfT;
q2 = q2 + ( q0*gyf - q1*gzf + q3*gxf)*halfT;
q3 = q3 + ( q0*gzf + q1*gyf - q2*gxf)*halfT;
// normalise quaternion : 맞아요 quaternion의 특성을 만족시키기위해 nomalization
norm = invSqrt(q0q0 + q1q1 + q2q2 + q3q3);
q0 *= norm;
q1 *= norm;
q2 *= norm;
q3 *= norm;
// 자세 추정?은 아니고 계산 결과를 ahrs 구조체에 저장!
ahrs->q.q0 = q0;
ahrs->q.q1 = q1;
ahrs->q.q2 = q2;
ahrs->q.q3 = q3;
// q0, q1, q2, q3 변수는 전역 변수로 설정되어 있기 때문에 계속 이 루틴을
// 반복하며 계속 자세가 누적되며 갱신된다!
}
Comments
Post a Comment