Gyro sensor accuracy

For my writing robot (WriterBot) project, I decided to try to use the gyro sensor to improve the accuracy of the robot's writing. Individual letters were more accurately drawn, but when the robot drew a string of several letters, the line of text started to curve down in a pronounced way. I decided to do some tests to see how accurate and reliable my gyro sensor is. Furthermore, I wanted to know whether any inaccuracies are systematic and predictable, in which they could be compensated for within the code.

So I spent an hour twisting the robot and gyro sensor back and forth on a 'lazy Susan' platform, recording the real angles used (180° and 360°) and the angles reported by the gyro sensor, as shown in port view on the brick. I was careful to ensure that the sensor was still when the robot was started up, so that the reading did not wander - this was confirmed by a steady reading in port view when the robot was still. I took about 40 measurements in total. Here are my observations in some detail:

When rotating the sensor clockwise thorough 360° fairly quickly (in about 5s), I almost always got measured angle changes of between 351° and 355°, with an average of about 353°. This means the sensor was significantly underestimating the clockwise rotation, by about 2%. The sensor ALWAYS underestimated the clockwise turn angle. 

When rotating the sensor clockwise thorough 360° fairly slowly (in about 10s), I got less consistent, more inaccurate readings, between 326° and 353° with an average reading for the angle change of about 345°: highly inaccurate. 

When rotating the sensor counter-clockwise thorough 360° fairly quickly, I almost always got measured angle changes of between 359° and 363°, with an average of about 361°. This means the sensor was usually fairly accurate in measuring counter-clockwise rotation. 

When rotating the sensor counter-clockwise thorough 360° fairly slowly, I got less consistent, more inaccurate readings, between 335° and 375° with an average reading for the angle change of about 360°: highly variable. 

I also tried doing a jerky 360° rotation in both directions and got my worst result of all: 405° for a counter-clockwise rotation of 360°!

When I rotated the sensor through 180° instead of 360° I got the same pattern of results as above, with the sensor underestimating clockwise rotations by about 2.5%, on average, but giving better results when measuring counter-clockwise rotations.

I also tried varying the proximity of the sensor to the brick, doing some trials with the sensor attached directly to the side of the brick, and others with the sensor several cm away from the brick (attached to  the end of a long Lego beam which was itself attached to the brick). Based on my observations, the position of the sensor was not important - the sensor did not seem to suffer from any interference fro the brick's electronics even when close. 

One last observation: even though I made sure that the sensor reading was not wandering before the trials, I noticed that the reading would sometimes start wandering during my experimentation. In one case, after a slow 360° rotation, the sensor began wandering by -0.5 degrees per second which would have introduced high inaccuracies to subsequent readings had I not re-initialised the sensor.

Then I did a second set of experiments, running this program:

'GYRO SENSOR TEST

'Attach motors to ports B and C

'Attach gyro sensor to port 2

Sensor.SetMode(2,0)  'measure angle

Sensor.Wait(2)  '(Should not be necessary)

startangle=Sensor.ReadRawValue(2, 0)

speed=20 'must be positive

For n=1 To 10

  Motor.StartSync("BC",speed,-speed)

  While Sensor.ReadRawValue(2, 0)-startangle < 360

  EndWhile

  

  Motor.StartSync("BC",-speed,speed)

  While Sensor.ReadRawValue(2, 0)-startangle > 0

  EndWhile

EndFor

Motor.Stop("BC", "True")

Since the gyro sensor cannot be reset to zero degrees by code, this program first records the initial angle as startangle so that angles can be found relative to the starting position as new angle - startangle. This program makes the robot rotate clockwise until the sensor detects that the robot has rotated at least 360° relative to the starting angle, then it rotates the robot back again until the angle has returned to (or gone beyond) the starting position. This cycle is repeated 10 times. After the 10 cycles, the robot would have returned to its initial position if the gyro sensor was working perfectly. I ran this program about 20 times, using different values (5, 10, 20, 30) for the speed. Almost every time, the final position was significantly clockwise relative to the starting position. In the first set of runs, the results were rather consistent for each speed:

So we make the same observation as before, that the errors are larger when the robot is rotating slowly. this is counter-intuitive - you would normally expect that if the robot is allowed to move slowly then there will be fewer problems of inertia and therefore hight accuracy. This video may give a clue as to what is going on. Builderdude35 explains that the gyro sensor measures angular velocity (rate of turn) rather than turn angle - the turn angle is obtained by a calculation based on the angular velocity and the time. The angular velocity measurement is rounded to the nearest degree per second. This means that if a wheel is turning at, say, 14.52 degrees per second then the sensor will round this to 14 degrees per second, introducing a small (4%) rounding error. If the wheel is turning at 1.452 degrees per second then the sensor will round this to 1 degree per second, introducing a huge (45%) rounding error. So we learn that the gyro can probably measure turns more accurately if they are made quickly.

Then I tried turning the robot off and on and running the program again, and was disappointed to see that the sensor's behaviour had changed. For example, using speed=20, I was now getting a consistent final error of 25° instead of 100°. So this means if you want to try to compensate for the errors of the gyro sensor, you will have to run a test like the one above each time the sensor is powered on. Once the test has been performed and the corresponding adjustment has been made to the main program it should be valid until the sensor is next powered down, I think.

I did also note however that sometimes (about 1 trial in 10) the first (clockwise) rotation of the robot was very much short of the 360° that it should have turned. For example, sometimes the robot only turned 270° instead of 360° in that very first clockwise rotation. So there really are a lot of inconsistencies in the way the sensor behaves. 

Conclusion

My carefully-initialized gyro sensor usually measures counter-clockwise rotation fairly accurately, but usually underestimates clockwise rotations significantly. My first set of experiments seemed to indicate that the sensor underestimated clockwise rotations by about 2.5%. This may not sound like much, but these errors will accumulate, so for example if my sensor is twisted back and forth through 360° ten times then the error will be about 2.5% x 360° x 10 = 45°, which is really significant. I also noticed that errors were large for slow or jerky rotations, and smaller for faster, smoother rotations ('faster' meaning a full rotation in about 5 seconds). My second set of tests (with the program above) indicate that the errors also vary between one session and the next (a 'session' meaning a period for which the sensor is continuously powered up).

It's possible that my observations apply only to my gyro sensor, but it's also possible that they apply to all EV3 gyro sensors - if you need high accuracy from your sensor then you should do your own tests...

Based on my tests, I concluded that there was a systematic component in the errors made by the sensor, which I attempted to compensate for in my WriterBot code by making regular adjustments to take into account that the angle measured by the sensor would gradually deviate more and more in the negative (counter-clockwise) direction, compared to the true rotation angle. This code workaround was helpful, but may only be valid for the duration of one session. If the sensor is powered down and then restarted then it will be necessary to seek a new adjustment factor (by trial and error or using the above program) to compensate for the sensor's bias.