Need for two sets of PID gains for Elevator

Hello Everyone,
As many teams, my team used an elevator for moving the cubes up and down. In Programming subteam, we used a PID controller for the elevator, and we had two sets of gains for it: One for going up, and one for going down (as you can see here. The reason was that while the elevator was going down, gravity “helped” it and did the opposite when it was going up.
However, I am wondering now whether it was necessary: The PID controller says what the speed of the elevator needs to be, and that calculation seems to take gravity in the calculation (the motor will just give more power if it sees the elevator needs to accelerate more). Am I correct? Is one set enough?


What you’re describing is called gain scheduling, and can be useful to make tuning easier when your system experiences appreciably different loading conditions (and you have a means of accurately determining which loading condition your in).

With the feature set and substantially higher operating frequency the Talon SRXs offer (Assuming you’re using these) it’s a lot less common than when teams were operating in ~50Hz loop on rio.

The reason for having two sets of coefficients is, as you said, to provide more force when accelerating up to counteract gravity. Since our lift wasn’t counterbalanced, with no power applied the lift would always go to the bottom.

Think about it like this. Let’s say we use a single set of coefficients with a kP of .03 (random number) and no I or D. The lift is currently at 50cm and we want it to go to 70 cm. The error is 20cm, so the motor power will be 60%. If we were at 50cm and we wanted it to go to 30cm, the error would be -20cm so the motor power would be -60%. The motor would apply the same power going both up and down, but the up direction has gravity fighting against it and the down direction has gravity going with it, so they will accelerate differently.

Using different coefficients was a hack to fix that problem. Since we used a smaller kP going down than up, the motor power going down was smaller than going up for the same error. The coefficients were tuned so that the difference in motor power between going from top to bottom and bottom to top was about equal to the difference in gravity forces, so the elevator appeared to have the same speed/acceleration in both directions.

The “proper” way to do this, however, would have been to use a constant (aka arbitrary) feedforward term. So long as the lift wasn’t in intake mode (i.e. all the way at the bottom resting on the base), the PID loop should have a small positive constant added to it that approximately balances the gravity force. It would add slightly to the (absolute value of the) motor power when going against gravity and subtract from it when going with gravity. That way, the P, I, and D parts of the controller don’t have to take into account the direction it’s travelling.

edit: And as Adam said, since we used an SRX for the lift, we can put the single set of coefficients with the arbitrary feedforward into the internal PID loop and let it run itself at a much faster update rate.

edit 2: Or, just tell the mechanical team to get their act together and add a constant force spring to balance gravity. Then let the PID only needs to accelerate and decelerate the lift, not balance gravity.

We added a constant amount equal to the amount of power we needed to hold the carriage in place during all of our PID loops. Talon SRXs support this using the ArbitraryFeedforward option, and WPIlib PID libraries let you just write a constant adder into your output commands. This effectively compensated for PID differences going up and down.

Gain scheduling is useful for when the PID controller’s assumption of a linear system results in unacceptably degraded performance throughout the envelope of operating conditions you care about. You can schedule new gains to “re-linearize” the controller around different operating points, thus subdividing the envelope and escaping the need for “one size fits all” gain tuning.

As others have noted, a constant offset due to gravity is better dealt with through a feedforward term that “cancels” the nonlinearity from the dynamics.

However, you still might find value in gain scheduling: for example, 254 used different feedforward gravity/acceleration compensation gains depending on whether we sensed we were holding a cube.

As another sample point, with perhaps broader perspective:

Our elevator started as bang-bang control this year. We used different up/down speeds to help keep results consistent, and eventually added a “slow down when descending and close to goal” chunk of logic to prevent overshoot due to gravity. Next step was gonna be a full PID, but we thought we could get around having to do tuning (and I think we did end up accomplishing that at least to some extent).

But yes. The problem is fundamentally asymmetrical, depending on whether you’re working with or against gravity. There may be a set of gains which works always, but if you take that approach gravity becomes this constant disturbance to the system.

I’m not exactly sure how the math works out, but I’m pretty sure with a known constant disturbance not accounted for, you’ll never get optimal controller behavior.

The solution to get closer to optimal? Inject info about gravity into the system. Assuming your robot never tips, this happens to be trivial in the case of an elevator.

Could you please explain that? I could not really understand what you meant.

Suppose your elevator didn’t go up and down but went side to side. Then gravity doesn’t have an effect, and tuning with PID is 1 set of parameters.

Use that same set of parameters, and then add a bias to counter-act gravity.

So if you tuned your elevator on the side, the motor output range might be -.6, .6]
Then, turn the elevator up and add +.2 so the new output range is -.4,.8].


The wording I chose was a purposefully vague description of the elevator-motor-motorController-roboRIO-human group of parts as simply a “system”.

At the end of the day, your goal is to design the mechanical parts, electrical parts, and software to accomplish certan things. In this case, get a cube to a certan height. The “optimal solution” to this is just the best-case result of design criteria that specify this system must act quickly, accurately, safely, simply, etc.

For the software side, you’ve chosen a PID algorithm for the controller. We chose a modified bang-bang algorithm. Both perform the same task, but in different ways. Either could be the “optimal solution”, but only if they fit the design criteria.

In my statement, “injecting info about gravity” simply means designing some part of your system to incorporate the fact that it will have to fight gravity in one direction, and will work with it in the other. It doesn’t matter exactly what your elevator looks like, what motors you used, what control algortihm you picked - the presence of gravity remains. One possible mechanical answer is to use a counterweight or spring. One possible software answer is to add some constant offset to your PID feedforward term. Both should accomplish the same goal when properly designed.

“Trivial to do” will likely be relative per team, but the software answer is pretty straightforward I think. Adding the constant term or gain scheduling is the impelmentation answer.

The key is that totally ignoring the effect of gravity on the system may simplify your work, but also will create a system that has a varying disturbance on it over time. Feedback can help correct for this, but why rely on feedback when you know in advance the distrubance will be present?

Note 254 hit on this a bit - the presence of a cube is an additional disturbance which changes the design criteria for what’s the “optimal solution”. Most folks would just design a software controller that’s “good enough” to account for it. You could also do better installing a sensor to tell you when the cube’s there or not, and doing additional gain scheduling. Again, you’re injecting info about the forces acting on robot into the system in an effort to correct for them.

Could you please explain how a spring can be implemented in this system? Could you give an example?

Constant force springs are coils of metal that, when you pull on them, pull back with a constant force (unlike normal springs, whose force increases with displacement). Attach one end to the top of the elevator and the other to the gripper, and pick a spring that exerts the same amount of force as the gripper weighs. The PID loop then only has to deal with accelerating the lift, not countering the force from gravity.

There are a number of good examples of robots that use constant force springs on CD.

We didn’t have one in the original design, but adding a constant force spring was a great addition later in build season. Evened out the PID and took a lot of stress off the motors trying to hold it in position. Later added a modified bike brake to help with that, too. Picture

We used this spring.

We went a bit overkill last year on 449, and gain-scheduled our feedforward, Kv, and Ka for with/without cube, number of stages engaged (0 or 1), and forward/reverse (the friction changes direction, even if the gravity remains the same). We also motion-profiled the movement, which is not hard to implement with current tools and has quite a large payoff.

While we had some major problems with our robot this year, smooth elevator operation was not one of them - it was possibly the nicest-behaved mechanism our team has ever built, this despite having quite a large amount of internal friction in the belt system.

When it comes to PID stuff, I believe the Talon has multiple PID slots. In your elevator example you can tune for up, put those values in #1 slot and tune for down and put them in #2 slot. Which set of values to use is commanded by the ROBRIO. We used this option for the velocity control on the drives, one set of values for medium to high speed, another set for low to super low speed.

Disclaimer: Not a software dude, just repeating what I’ve heard them say. Might be worth checking into.

Our elevator didn’t need it. We used linear springs.