@@ -19,6 +19,7 @@ void Sensor::update() {
1919 /* * get current angular velocity (rad/s) */ 
2020float  Sensor::getVelocity () {
2121    //  calculate sample time
22+     //  if timestamps were unsigned, we could get rid of this section, unsigned overflow handles it correctly
2223    float  Ts = (angle_prev_ts - vel_angle_prev_ts)*1e-6f ;
2324    if  (Ts < 0 .0f ) {    //  handle micros() overflow - we need to reset vel_angle_prev_ts
2425        vel_angle_prev = angle_prev;
@@ -28,10 +29,28 @@ float Sensor::getVelocity() {
2829    }
2930    if  (Ts < min_elapsed_time) return  velocity; //  don't update velocity if deltaT is too small
3031
31-     velocity = ( (float )(full_rotations - vel_full_rotations)*_2PI + (angle_prev - vel_angle_prev) ) / Ts;
32-     vel_angle_prev = angle_prev;
33-     vel_full_rotations = full_rotations;
34-     vel_angle_prev_ts = angle_prev_ts;
32+     float  current_angle = 0 .0f ;
33+     float  prev_angle = 0 .0f ;
34+     //  Avoid floating point precision loss for large full_rotations
35+     //  this is likely optional
36+     if  (full_rotations == vel_full_rotations) {
37+         current_angle = angle_prev;
38+         prev_angle = vel_angle_prev;
39+     } else  {
40+         current_angle = (float ) full_rotations * _2PI + angle_prev;
41+         prev_angle = (float ) vel_full_rotations * _2PI + vel_angle_prev;
42+     }
43+     const  float  delta_angle = current_angle - prev_angle;
44+ 
45+     //  floating point equality checks are bad, so instead we check that the angle change is very small
46+     if  (fabsf (delta_angle) > 1e-8f ) {
47+         velocity = delta_angle / Ts;
48+ 
49+         vel_angle_prev = angle_prev;
50+         vel_full_rotations = full_rotations;
51+         vel_angle_prev_ts = angle_prev_ts;
52+     }
53+     
3554    return  velocity;
3655}
3756
0 commit comments