Help with making robot turn 180 degrees in auton

So basically, I’m just getting started with using gyroscopes (NavX) and PID systems for some more advanced features. I have this command callled turncommand that is set to run during autonomous which, in theory, should make the robot turn 180 degrees. However, when it is actually run the robot DOES stop at 180 but the momentum carries it to about 257 degrees. Now, when I tried to adjust the kP value on my PID controller to anything below 0.4 it would just keep spinning in place forever. If anyone has any ideas on any possible fixes or anything I could try then that would be greatly appreciated. I have provided a picture that singles out the code but if you wish to view to full thing here is the code: GitHub - rambots/Robot-2022: Robot code for FIRST 2022 Rapid React

Is your driveRrain.getAngle() returning degrees or radians? Does that unit match what unit you’re passing into the command?

Can you log the angle to network tables/SmartDashboard/Shuffleboard and confirm its turning in the direction you would expect?

Also, when you say it turns endlessly with a kP < 0.4, is it moving steadily at a constant speed? Or is it accelerating? Decelerating? Oscillating? Maybe graph the motor output values to confirm.

Basically, can you graph the controller and confirm you’re actually approaching the setpoint and not endlessly diverging?

drivetrain.getangle() returns degrees

I have logged the angle to shuffle board and yes, when auton is enabled it starts moving towards 180 degrees (positive, not negative)

Im pretty sdure it is moving at a constant speed which should be 80% of the motors speed. Once I have acess to the robot again i will graph the output values to confirm but Im almost certain that its constant

A few things:

  1. You need to set the PID controller to be continuous. The angle measurement from the navX will continue to increase/decrease past 360/0. The navX angle is also positive clockwise while you are probably driving your motors to turn counter-clockwise, which is probably why it spins in place indefinitely. I’m not exactly sure why a higher P value ‘works’ in this case, so I’m going to think it’s a random fluke.

  2. Let’s think about the PID math for a bit. Let’s say you are at 0 degrees and you want to go to 180 degrees and you are using a P value of 0.4. On the first iteration, the output will calculate 0.4*(180-0)=72. This 72 is then clamped down to 0.8 and becomes your motor output.

Let’s also think about the math in reverse. At what delta angle will you need to have before this slows down? With the same numbers, this ends at +/-2 degrees, which means you will be pushing 80% motor power to your motors until you are within +/-2 degrees to your target before you even start slowing down.

Given these two cases, you should consider lowering your P value to a much lower value first and then increase it as you confirm that this works.

  1. Do you mean to turn to an absolute angle with this command or do you want it to turn to an angle relative to your current heading? For example, lets say your robot is facing 90 degrees and you command it to 90 degrees. As the code is written, the robot will not move from this position as it thinks it is on target.
1 Like

So for number 1, would adding a line of code that says “controller.enableContinuousInput(0, 360);” be sufficient? I also dont understand why a higher P value is preferred, what I learnt was that usually a lower P value should give you more accurate actions.

As for 3, I do not mean this to turn to an absolute angle, I would want it to turn 180 based on its current heading. In other words, to turn about face.

  1. Most examples of this have the range at (-180, 180). I think (0, 360) should work fine, but I’ve never tried it before.
  2. A higher P value is generally preferred because if it is too low, it will take time before you reach your target. But if it is too high, then it becomes hard to control and you will overshoot and oscilate before you reach your target. You can compensate for this by adding I and D values, but for a turn in place command, you can generally get fast enough results with just a P value. Since it seems like you are fairly unfamiliar with this, I would just stick to using a well-tuned P value.
  3. If you want the target to be relative to your current position, just set your setpoint to your current angle + your target angle.

This is a good use case for trapedoid profiled PID. It is C++, but here’s code to do this – it shouldn’t be hard to do this in Java. Also, you might want to have your drive motors set to brake mode, if you have not already done this.

(0, 360) did in fact end up working fine, after enabling continious output during the first test the robot actually did a perfect 180. However, after running multiple tests i realized that it was a 50/50 thing. Sometimes it did a smooth 180, othertimes it oscillated 2-3 times before reaching the goal. While I understand that further tuning the kP and kD values can eliminate this, how come sometimes it runs perfectly and sometimes it doesnt all with the same kP value?

I’ll definitely look more into the trapedoid profiled PID’s, as a matter of fact I should run through all of WPIlibs documentation on PIDs one more time. And yes all of the motors are in brake mode, if anything i might have to tweak the ramp rate a bit.

1 Like

What P value are you currently using? You can also try calling controller.reset() in the initialize() portion of the Command.

The only other thing that may cause this is if your navX is giving a bad reading. When the robot is still, does the angle value increase over time?

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.