I’m programming some angle preset buttons for more efficient driving using an ADXRS450 gyro. I’m having one issue with my code. Here’s a real world example:

If the robot is currently sitting at 0°, and I set the set point to -45°, the robot will turn 45° counterclockwise, great! However, if during match play the robot has rotated twice, the gyro now reads 720°. If I set the set point to -45°, the robot will make two full revolutions counterclockwise plus the 45 degrees. Obviously very inefficient. What Java code can I use to limit the range of the gyroscope to between -180° and 180° and make any higher/lower numbers rollover?

Thanks in advance!

You actually have two problems, though you haven’t noticed the second yet.

For the problem you’ve noticed (that of clamping the range of the gyro), I suggest you take look at the modulo operator. With a bit of thinking, you should be able to figure out how to use it to clamp the range from 0° to 360°, and from there it should be obvious how to shift it to -180° to 180°.

The second problem, which you will likely notice soon after fixing the first, is that if you are currently at -179° and you give your robot a setpoint of 181°, your robot will turn the long way 'round to get there. This is because of topology: a standard PID controller is usually programmed assuming that the process variable lies in a simple interval, but heading lies on a circle (which is an interval with the ends connected to each other). Thankfully, the WPILib PIDController class has a method to deal with just this problem.

Awesome, thanks so much for the information!

I have figured out how to apply and convert the values.

Thanks for pointing out that second problem. Conveniently I am already using WPILib’s PID class so this problem can be easily remedied.

Thanks again!

Rather than the modulo operator, I would suggest using:

java.lang.Math.IEEEremainder(double f1, double f2)

for this purpose.

Steve

I don’t wish to derail this thread, but why do you suggest that? Does the compiled code result in more efficient handling of the data by the processor?

It behaves differently, and can (sort of) save you a bit of code.

If you want to use modulo to clamp heading values to a range from -180 to 180 and also preserve what the gyro reports as a heading of 0, you need to do something like:

```
(gyro.get()+180)%360-180
```

However, simply calling

```
Math.IEEEremainder(gyro.get(), 360)
```

does the same thing.

Yes, that is the reason. I have seen people struggle for hours getting the modulo operator working for the boundary conditions while IEEEremainder just works.

Steve