/* dcm.c */ #ifdef WE_HAVE_SQRT #include #endif #include "matrix.h" #include "dcm.h" #include "uart.h" /* Implementation of the DCM IMU concept as described by Premerlani * and Bizard */ float dcm[3*3] = {1, 0, 0, 0, 1, 0, 0, 0, 1}; float delta_t = 0.01; void dcm_update(float omega_x, float omega_y, float omega_z) { float tx = delta_t * omega_x; float ty = delta_t * omega_y; float tz = delta_t * omega_z; float update_matrix[3*3] = { 0, -tz, ty, tz, 0, -tx, -ty, tx, 0}; float temp_matrix[3*3]; matrix_multiply(temp_matrix, dcm, update_matrix, 3, 3, 3); matrix_add(dcm, dcm, temp_matrix, 3, 3); dcm_normalise(); } void dcm_normalise(void) { float error; float tmp[6]; int i; /* dot product of first two rows */ error = dcm[0]*dcm[3] + dcm[1]*dcm[4] + dcm[2]*dcm[5]; /* printf("error is %f\n", error); */ tmp[0] = dcm[3]; tmp[1] = dcm[4]; tmp[2] = dcm[5]; tmp[3] = dcm[0]; tmp[4] = dcm[1]; tmp[5] = dcm[2]; for (i = 0; i < 6; i++) dcm[i] = dcm[i] - (tmp[i] * (0.5f * error)); /* third row = cross product of first two rows */ dcm[6] = dcm[1]*dcm[5] - dcm[2]*dcm[4]; dcm[7] = dcm[2]*dcm[3] - dcm[0]*dcm[5]; dcm[8] = dcm[0]*dcm[4] - dcm[1]*dcm[3]; if (!(dcm_renormalise(dcm+0) && dcm_renormalise(dcm+3) && dcm_renormalise(dcm+6))) { /* Shit. I've been shot. */ dcm[0] = dcm[4] = dcm[8] = 1.0f; dcm[1] = dcm[2] = dcm[3] = 0.0f; dcm[5] = dcm[6] = dcm[7] = 0.0f; } } bool dcm_renormalise(float *v) { float f = v[0] * v[0] + v[1] * v[1] + v[2] * v[2]; /* printf("f is %f\n", f); */ if (f < 1.5625f && f > 0.64f) { f = 0.5 * (3 - f); #ifdef WE_HAVE_SQRT } else if (f < 100.0f && f > 0.01f) { f = 1.0 / sqrt(f); /* XXX log this event? */ #endif } else { putstr("problem\r\n"); return FALSE; } v[0] = v[0] * f; v[1] = v[1] * f; v[2] = v[2] * f; return TRUE; } void dcm_dump(void) { putstr("dcm: "); putint_s((int)(dcm[0] * 100000.0f)); putstr(", "); putint_s((int)(dcm[1] * 100000.0f)); putstr(", "); putint_s((int)(dcm[2] * 100000.0f)); putstr("\r\n "); putint_s((int)(dcm[3] * 100000.0f)); putstr(", "); putint_s((int)(dcm[4] * 100000.0f)); putstr(", "); putint_s((int)(dcm[5] * 100000.0f)); putstr("\r\n "); putint_s((int)(dcm[6] * 100000.0f)); putstr(", "); putint_s((int)(dcm[7] * 100000.0f)); putstr(", "); putint_s((int)(dcm[8] * 100000.0f)); putstr("\r\n"); } void puthexfloat(float f) { union { float f; unsigned int i; } u; u.f = f; puthex(u.i); } void dcm_send_packet(void) { putstr("D:("); puthexfloat(dcm[0]); putstr(","); puthexfloat(dcm[1]); putstr(","); puthexfloat(dcm[2]); putstr(","); puthexfloat(dcm[3]); putstr(","); puthexfloat(dcm[4]); putstr(","); puthexfloat(dcm[5]); putstr(","); puthexfloat(dcm[6]); putstr(","); puthexfloat(dcm[7]); putstr(","); puthexfloat(dcm[8]); putstr(")\r\n"); }