diff options
| author | Keith Packard <keithp@keithp.com> | 2013-10-27 23:37:55 -0700 | 
|---|---|---|
| committer | Keith Packard <keithp@keithp.com> | 2013-10-27 23:37:55 -0700 | 
| commit | 4bebade9e9004bad81df1a423687f3e3f356f1c2 (patch) | |
| tree | 794d47bec593f260f5ee69508672d2eb85a78a8c /src/core/ao_sample.c | |
| parent | 06b0c1b768a7d3eae57e66bc9aea25db49f9ea8a (diff) | |
altos: Correct incremental rotation computation
Trying to compute the combined rotation by taking the x/y/z rotations
as a vector is a good approximation, but not accurate enough for our
application given the large angles we sometimes see.
Instead, use a correct-but-expensive function with a pile of
transcendental function calls. The STM32L seems to be fast enough at least...
Signed-off-by: Keith Packard <keithp@keithp.com>
Diffstat (limited to 'src/core/ao_sample.c')
| -rw-r--r-- | src/core/ao_sample.c | 37 | 
1 files changed, 7 insertions, 30 deletions
diff --git a/src/core/ao_sample.c b/src/core/ao_sample.c index fc8f8680..adf8399d 100644 --- a/src/core/ao_sample.c +++ b/src/core/ao_sample.c @@ -164,47 +164,24 @@ ao_sample_preflight_set(void)  }  #if HAS_GYRO + +#define TIME_DIV	200.0f +  static void  ao_sample_rotate(void)  {  #ifdef AO_FLIGHT_TEST -	float	dt = (ao_sample_tick - ao_sample_prev_tick) / 100.0; +	float	dt = (ao_sample_tick - ao_sample_prev_tick) / TIME_DIV;  #else -	static const float dt = 1/100.0; +	static const float dt = 1/TIME_DIV;  #endif  	float	x = ao_mpu6000_gyro((float) ((ao_sample_pitch << 9) - ao_ground_pitch) / 512.0f) * dt;  	float	y = ao_mpu6000_gyro((float) ((ao_sample_yaw << 9) - ao_ground_yaw) / 512.0f) * dt;  	float	z = ao_mpu6000_gyro((float) ((ao_sample_roll << 9) - ao_ground_roll) / 512.0f) * dt;  	struct ao_quaternion	rot; -	struct ao_quaternion	point; - -	/* The amount of rotation is just the length of the vector. Now, -	 * here's the trick -- assume that the rotation amount is small. In this case, -	 * sin(x) ≃ x, so we can just make this the sin. -	 */ - -	n_2 = x*x + y*y + z*z; -	n = sqrtf(n_2); -	s = n / 2; -	if (s > 1) -		s = 1; -	c = sqrtf(1 - s*s); - -	/* Make unit vector */ -	if (n > 0) { -		x /= n; -		y /= n; -		z /= n; -	} - -	/* Now compute the unified rotation quaternion */ - -	ao_quaternion_init_rotation(&rot, -				    x, y, z, -				    s, c); -	/* Integrate with the previous rotation amount */ -	ao_quaternion_multiply(&ao_rotation, &ao_rotation, &rot); +	ao_quaternion_init_half_euler(&rot, x, y, z); +	ao_quaternion_multiply(&ao_rotation, &rot, &ao_rotation);  	/* And normalize to make sure it remains a unit vector */  	ao_quaternion_normalize(&ao_rotation, &ao_rotation);  | 
