"Closing the loop" in teleop drive

Hello all,
We have had much success with our robot and our programming this year, except for the fact that our driver has to manually correct the robot because it is hard coded to accept raw input from joysticks. In order to drive straight in teleop, he has to constantly change how much hes tilting the sticks which can become difficult. We have a PID implemented for our auton, and we were wondering if there is a similar technique we can implement for teleop as well?

1 Like

Buy a NavX, run a control loop on the angular error that feeds to a speed differential between the two sides of the drive.

For our mecanum drivetrain, we just had a PID that kept a gyro heading. So after you rotated the robot, our code would wait just half a second and then “lock” onto that angle to keep it straight using a PID. It worked really well and wasn’t that hard to implement.

Try “split arcade drive”. Instead of having each joystick map to each side of the drivebase, have the left joystick’s Y axis map to the Y-position (forward back movement) of the robot, and have the right joystick’s X axis map to the Z-axis rotation of the robot. Our drivers found this very useful for fast, long, straight cycles over standard tank drive. It’s also easier to implement than a gyro, although it is most definitely useful.

Yes. There is.

What I am guessing you are doing is setting motor speeds based on joystick input. This is especially common for tank drive. Joystick position 0.5 = motor input 0.5. Right?

Instead, think of your joysticks as setpoints for a PID loop. They are telling the robot what direction to go, now it’s up to the robot’s program to actually choose the motor inputs that will take you there.

To do that, you have to have equations that translate desired direction, speed, and rotation into motor inputs. For a holonomic drive, the WPI libraries already do that. I’ve never used their libraries for tank drive, so I don’t know if they have the same sort of thing there. However, tank drive is pretty easy, if for no other reason than it is an extremely common example from textbooks and lecture notes, so it’s all over the web. Just google “differential drive”, or possibly “differential drive kinematics”.

For differential drive robots, the answer is that the forward speed of the robot is proportional to (mL+mR)/2, and the rotation rate of the robot is proportional to (mR-mL)/2, where mL and mR are the motor inputs. Given a desired motion, you can calculate the mL and mR to give the correct motor inputs.

For last year’s robot, I found that I could drive best with a single, twisting, joystick. The forward and back position was my translation rate setting, and the twist was my rotation rate setting. If my y position (forward and back) on my joystick was y, and my z position (twist) was z then I had (mL+mR)/2=y, (mR-mL)/2=z. y and z come from the joystick, so I have two equations and two unknowns. Solve those and that gives my motor inputs. However, my students preferred two joysticks for tank drive, so I just used the inputs and calculated the desired value based on the inputs, and then went backwards to pick the motor rates. I could have just used the joysticks directly, except for reasons I am about to explain.

Doing the math doesn’t actually solve your problem, though, because motors are slightly different, so if you set the values of the left and right motor the same, you won’t drive perfectly straight. It will pull toward the weaker motor. To correct that problem, I used a gyroscope. The PID loop used my current heading as a direction setpoint, and if the driver was not deliberately turning, based on his joystick inputs, the gyroscope was used to inject small rotations to correct the drive.

Finally, there are the joysticks themselves. I used a deadband to assume that if they are not turning at least a certain amount, the driver probably doesn’t want to turn anyway, so I set the desired rotation to zero. This was especially important in two - stick drive with tank drive, because it’s almost impossible for a driver to keep two joysticks positioned accurately. It’s all well and good for drivers who want only two speeds, full and stop, but if there is any subtlety to the driving at all, it got really hard.

If you aren’t using tank drive, the same general principles apply, but you need to have a model of how your robot responds to desired headings, i.e. you need to know your robot kinematics. Wheel encoders can be used to improve on or replace gyroscopes.

Obviously, the above is not mathematically rigorous. If no one responds with a link to a really good presentation on the subject, I’ll try to expand. The very simple summary is that yes, you can “close the loop”. Just think of your joystick input as a set point instead of a direct command, and figure out how to apply feedback control to your system to achieve the setpoint.

Yes this is exactly how we function currently.

This makes a lot of sense and shouldn’t be extensively difficult to implement, thanks for the quick response.

We’ve done this, and it’s not too hard to implement, but it’s not super easy to tune, because it’s about the feel of the robot for the driver. You can also have problems with the interplay of the forward loop and the turning loop, for example if you have full forward and full turning, one of these could saturate the other, depending how you tuned the two loops. This isn’t to discourage you from trying it or doing it, just things to be thinking about while you’re doing it.

Are you sure you need the closed loop?

I agree that drivetrain closed loops are useful in a lot of cases, especially when needing to drive straight or at a certain angle relative to the field in teleop. And of course it’s really really useful in auton. But usually I consider curvy driving to be a mechanical problem first and foremost. If your speed controllers are properly calibrated, then the source of the problem could be something like old/bad CIMs, unworn gearboxes, extra friction on one side, et cetera. But these problems can be fixed.

67’s 2010 robot had open loop control on the drivetrain. I’m sure many world champion robots since then have also been open loop most of the time. This could be an indication that while closed loop control on the drivetrain can give your team an advantage if done correctly, it’s not absolutely essential in order to have success.

We’re on an open loop right now and our driver complains that when driving straightaways in matches transferring gears he is having a hard time going straight, i.e. one side is always a bit faster than the other side which causes him to go off course and sometimes have an unwanted crash.

I guess we’re looking for a solution that allows us to maintain an open loop (for maximum driver input) but also adjust accordingly for driving straight. I had an idea for this which would be to take the input, use the gyro to calculate error change and make an adjustment to the input based off that gyro change; however, with this solution I fear an issue arising when the driver tries to turn suddenly.

There’s an easy solution for the sudden turn problem. We went back to open loop as soon as the driver selected a turn. We only used the gyro for keeping a straight line. When the driver finished a turn, the current angle was the new angle setpoint.

You could get some extra precision using it everywhere, but it’s much, much, more difficult.

And if you do go to that method, setting the setpoint when the driver stops the turn, there’s a well documented “kick” problem, where the robot jerks a bit at the end of a turn. I read about it in 2014, the first time I used gyro-corrected steering. The problem is a momentum problem. The driver brings the joystick(s) back to neutral to go in a straight line, which sets the setpoint to its current angle, but the robot is still rotating, so it goes past the setpoint, and the PID yanks it back to the setpoint. The solution is to not set the setpoint until the joysticks are calling for straight line motion, and the robot’s rotation rate is small. Drivers can still deal with setting the right angle, and they can drive straight at the newly chosen angle.

We had the “jerk-back” problem as well, but there’s not really much need to wait until the driver is driving straight again, you just need to have a low angular velocity like you mentioned and also have a short (1/10th of a second) delay after being below that angular threshold before you set the gyro setpoint because the gyro “lags” behind reality a bit.

We split our controls: one joystick for forward/backward movement and the other for turning. This significantly improved every single driver candidate’s ability to navigate our tryout courses, especially on the “go fast on this straightaway” part. Every single one improved, even the die-hard “tank drive” kids.

We had ‘drive straight’ enabled in high gear based upon a NavX feedback loop. It didn’t help keep things straight, to be honest. We disabled it before our first competition. It probably helped that we tuned out most of the mechanical inconsistencies in the drive train gearboxes before final assembly, so the robot almost naturally drives straight. Almost.

We are open-loop tank-drive and have found it useful to add a “Drive Trim” control to the Custom tab of the dashboard. It is a Horizontal Pointer Slide that sets the value for a multiplier to be applied to one of the joysticks. So, if the robot drifts right and we adjust the trim 5% to the left, the left joystick value gets multiplied by 0.95, before it is written to the motor.