PID Loop Question

So, I’ve worked with PID Loops before, although I’ve never got them working well. I’m wondering a few things:

  1. What’s the best tuning method? It’s especially difficult to tune when you are tuning your drive wheels with encoders to go a specific speed.

  2. As far as I know, if I tune free running wheels, the PID values won’t work when the wheels are on the ground. Is this true? I have a calculus background, which supports this idea, but I want to confirm with you guys.

  3. Is it worth using PID loops on drive wheels?

Thanks!

I’ve never tried closed-loop control of wheel speed. My use of PID for drive motors has always been position control for autonomous driving (and once for “hold position” mode when commanded by the driver). For tuning it, I set up a way to force the robot to drive a specified distance forward or backward on command, then tweaked the P and D parameters until it was repeatable within a tolerable error.

The “inertial load” on the wheels will change drastically when you put the robot down or pick it up off the floor. This will greatly change the D parameter for good tuning, and it is likely to have a significant effect on P as well, making the I parameter very important to compensate for small steady-state position errors. But for speed control instead of position control, you probably don’t need to care about I.

@Alan
I’ve heard twice before that for closed loop wheel speed control, PD is sufficient. What makes the “D” term more valuable than the “I” term in this case?

For the sake of this discussion, I’m going to assume that your sensor input to the PID loop is velocity, and your output is either PWM or voltage.

Are you sure about that? If you want to go at, say 1 m/s, with just a P (or PD) controller, that will take a signal to the motor controller. That signal will only be produced by a PD controller if there is an error, which means you aren’t driving at the correct speed. This isn’t caused by friction, which is the reason why you added the I term in a position loop.

For velocity control, you really only need P and I. P will act like the D term would in a standard PID position loop. I will act like the P term would in a standard PID position loop.

Quite the contrary! In order to achieve perfect tracking in steady state in speed control, it is imperative that integral control is used - when considering position control, there’s no need for it, except if deadzone compensation is of interest.

This is explained by the internal model principle: the unstable modes of the reference signal must be included in the loop in order to achieve perfect tracking; a step change’s Laplace transform is 1/s (an unstable pole at the origin), so we must include this pole in the loop. A position control system already has a pole at the origin (because position is speed integrated over time), so there’s no need for integral control. That isn’t true for a speed control system, which is why we must add integral control to cancel the unstable mode of the reference signal. If you were using a sine source as the reference things would be different, of course.

More info than you’d ever like to know (in a seminal academical paper, though): http://www.sciencedirect.com/science?_ob=ArticleURL&_udi=B6V21-47X16C0-6&_user=10&_coverDate=09%2F30%2F1976&_rdoc=1&_fmt=high&_orig=search&_origin=search&_sort=d&_docanchor=&view=c&_searchStrId=1619581714&_rerunOrigin=google&_acct=C000050221&_version=1&_urlVersion=0&_userid=10&md5=7d3b669bae8b1ce73682ba6fa686705e&searchtype=a

I apologize for giving bad advice. I have always used PD control for motor speed when experimenting, but I failed to describe the important step of post-integrating the PID output. When I’ve played with it, I have used the output of the PID controller as a delta, to increase or decrease the motor control. If I were to use it as an absolute motor power command, which I suppose most people would do as a matter of course, it would definitely need the I parameter!

Alan, now you’ve got me curious.

I know there are tons of methods for position tracking, but what method do you use? E.g. what sensors, what algorithms (if you don’t mind sharing :)) and other such things… because from my experience, accelerometers aren’t capable of accurate position tracking, but who knows, I’m hoping someone proves me VERY wrong.

Also, is there a benefit to a speed control PID? I mean, going straight, yes, but wouldn’t directional control be easier with a gyro and joystick position?

Basically I’m asking for what all of you use PID loops for, because it’s nice to know what’s worth the effort in tuning.

Tim Wescott wrote a excellent piece for Embedded Systems Programming back in October 2000 entitled PID without a PhD giving a really detailed but easily approachable explanation of how PID control works as well as tuning a PID controller.

Tuning a system while it is not under load will result in a very poorly tuned system. While it will account for the plant (motor and gears and whatnot) it will not account for the robot’s inertia or the friction in the drive.

Have you ever commanded your robot to go straight forward only to have it veer off to one side or another over time? PID can help. Having closed loop control on your robot’s wheels will try to make sure all of your wheels are spinning at the rate you commanded (and by extension make sure your robot is doing what you told it to do) and will compensate to provide some disturbance rejection. The feedback can also be used to then calculate the current position and orientation of a robot when dead-reckoning.

Thats actually a pretty cool learning experience!

If I am understanding you correctly, you were essentially integrating the output of a PD controller, which would effectively give you a PI controller?

Integrated once, P becomes I, D becomes P, so PD = IP = PI?

I’m wondering if there are any useful side effects to this method… I’ll ponder it more when I’m not on drugs (lousy cold!)

Yep, that’s apparently what’s going on. It explains why I’ve been improperly suggesting PD control where pretty much everyone else uses PI.

I’m wondering if there are any useful side effects to this method… I’ll ponder it more when I’m not on drugs (lousy cold!)

I toyed with closed-loop speed control back in the IFI controller days, when debugging wasn’t quite as easy as probing LabVIEW wires or opening a front panel window. I was using a servo as an analog indicator to show me what the PID computation was producing as its output, and I wanted a consistent zero point.

Is it safe to assume that 4 wheels on a mecanum base will need the same PID values for speed control?

If your weight is fairly evenly distributed, yes. If not, it will probably still work, but you can do a little better by tuning one loop for the heavier side, and one loop for the lighter side.

If there is a theoretical basis for this belief would you share it please?

**

I’ll take a crack at answering my own question.

If the center of mass is not equidistant from all four wheels, then during conditions of acceleration the wheel(s) to which the CoM is closest will see a greater effective inertia. If there is no (or minimal) acceleration, the only effect would be an increase in rolling resistance which may or may not be significant depending on the flooring material and the wheels.

**

The only thing I can see that would be different is that the integral capping method would be easier to understand and maybe handle some situations a bit differently. I think it might give a slightly better response at full power.

With standard PID, I’ve always set the limit on I such that I is only in the range from ± u_max / K_i. I justify this as keeping the I term from trying to apply more power than is available.

With Alan’s method, you can easily just limit the integrator at the output of the PD controller to be ± u_max.

From block diagram manipulation of Alan’s form to the other form, it looks like the equivalent capping of the integrator in the I part of the PI controller (assuming the integrator is before the Ki gain) is to keep it within the range, (u_max - Kd * error)/Ki, (-u_max - Kd * error)/Ki].

I got there by writing out the block diagram with the integrator directly after the sum block at the output of the PID controller (adding the terms together), writing down the conditions that cap the integrator, and then splitting the integrator and moving it before the sum block. I made sure to rewrite the conditions such that the two integrators would still have the same effective cap as the original integrator. The integrator and differentiator in the Kd part of Alan’s form cancel, giving the range above.

Sounds like a nice explanation. In addition, if you are at the traction limit, the wheels with more normal force on them will be able to contribute more to the acceleration of the robot, and should have a more aggressive controller to do that.

The topic of doing speed control via PID has come up several times in recent weeks. I have referred people to this thread: http://www.chiefdelphi.com/forums/showthread.php?t=62888&highlight=PID

To quote myself:

A couple things to keep in mind here:

The standard POSITION PID loop might look something like this:

output = Kpe_pos + Kie_pos_sum + Kd*e_pos_delta;

Where output is the output.
e_pos is the error in position = desired_pos - actual_pos
e_pos_sum is the sum of the position errors = e_pos_sum + e_pos
e_pos_delta is the derivative of the error = e_pos - e_pos_last

This loop, if well tuned, should provide pretty good position control. But what about VELOCITY? Speed is the first derivative of position - so we could differentiate the position loop with respect to time to obtain a velocity controller.

I will use the D() operator to represent taking the time derivative.

D(output) = KpD(e_pos) + KiD(e_pos_sum) + Kd*D(e_pos_delta);

So far so good. What’s the derivative of the output? Well, that’s the change in output over time, so D(output) = output - output_last.

Whats the derivative of e_pos? Remember that e_pos itself is (desired_pos - actual_pos). It’s derivative would simply replace “pos” with “vel”.

e_vel = D(e_pos) = desired_vel - actual_vel.
e_vel_sum = D(e_pos_sum) = e_vel_sum + e_vel.
e_vel_delta = D(e_pos_delta) = e_vel - e_vel_last.

Putting it all together, you get:

output - output_last = Kpe_vel + Kie_vel_sum + Kd*e_vel_delta;

Let’s rearrange…

output = output_last + Kpe_vel + Kie_vel_sum + Kd*e_vel_delta;

or…

output += Kpe_vel + Kie_vel_sum + Kd*e_vel_delta;
(assuming output is global or static and persists between loop iterations)

The key is the “+=” in the final equation. E.g. your PID loop output should be the DELTA to the motor PWM. If you use the output directly, you essentially only took the time derivative of one side of the (well understood) position PID equation. You can still tune it to work, but Kp, Ki, and Kd no longer represent what you thought they did.

In simpler terms, position PID uses motor PWM (~= speed, the time derivative of position) as the quantity being output. Thus, velocity PID uses motor acceleration (the time derivative, or DELTA in motor PWM) as the quantity being output.

So how would one go about tuning a speed-based PID? I mean, the thing is on the ground and moving, and if you have multiple PID loops going, each one will affect the others, right? It just seems like it would be a huge pain to tune. Someone have a method they wouldn’t mind sharing?

And there lies one problem with the application of PID control… Unless you have developed a mathematical model of the whole system, an analytical/simulation solution is fairly hard to come by.

Now, to specifically answer your question I’d probably do something like the following. Note that I haven’t done this specifically for multiple loops so take it all with a grain of salt. I’m sure someone here has more experience in this regards as most of my experience with successful loops has come with a fully modeled system. Most importantly you are going to want telemetry data on the system’s response as you are tuning. Without this you’ll be taking a stab in the dark saying “I think that was better…”.

  1. Assuming multiple control loops, tune them using the same constants throughout. Unless the system each controller is controlling is vastly different, this should get you pretty close.

  2. Once you’ve gotten pretty close with each controller, analyze your telemetry data and tune from that making only ONE change at a time and proceeding to test and analyze. Rinse and repeat as needed.

For example, lets say you have two control loops, one for the speed of the left drive wheels and one for the right drive wheels. You’ve tuned them using the same constants, however your telemetry (and probably physical observations) indicate that your right drive wheels speed up slightly slower than the left leading to the robot veering to the left before the right wheels catch up and straighten out. In this situation I would probably increase Kp slightly to improve the rise time.

Again, this is all in theory and assumes an understanding of manually tuning of a PID controller. If I remember correctly back in 2005 my team used a control loops on the speed of our drive wheels. We only used one controller for both however and achieved acceptable results. The robot was fairly equally balanced though so your mileage may vary. I’d definitely suggest trying to tune them the same first and then if that doesn’t work, go for individual tuning of the loops.

How I tuned the gain of our drivetrain, on a practice bot (to get the code right):

  1. Run the robot in each direction to determine the maximum forward/reverse speed of the slower side (since that limits the forward/reverse speed)
  2. Setup LabVIEW to graph the Sensor, Setpoint, Delta, and Output (basically just open the VI that shows the graph, and open the constants VI as well)
  3. Set the gain to a known in-range number (in my case, that was 0.01)
  4. Jack up the gain until the graphs show a reasonable rise time and minimum overshoot.
  5. Decide if I need to write a gain scheduler (and I decided to, so I did write a linear gain scheduler)
  6. Tune the gains again (go back to 4) for each end of the spectrum, and check that the performance is good in all zones
  7. See how the extreme and precise response is, and decide what to do about those. I found that with an I only, the robot backs up slightly when stopping (integral windup), so I wrote some code to handle sign mismatches between setpoint and sensor differently.
  8. Drive it again and tune, repeat until perfect.

On the chassis I tested (34 lbs chassis w/ everything but 1 front bumper and the battery, + 50lbs in weights) with 6" kit wheels and a 1-speed, I was fine with 1 set of constants. I assume I will need to tune High and Low separately, but that comes when the robot is done.