Velocity Limiting PID

We have a PID controller based on a ten-turn potentiometer. However, one of my mentors told me to try to limit the max velocity, so the robot won’t flip over when accelerating upwards.

Is there a way to limit the max velocity of the PID controller (not the output range, but degrees per second). Thanks,

Peter Chacko

One thing to consider: regardless of how it’s implemented, preventing too much velocity ultimately will come down to limiting the control effort in some way.

Is limiting the output range of the control effort undesirable in your setup?

Tackling the same problem you’ve got. What language are you running? How familiar are you with said language?

What Im doing is creating a class, lets call it “EnhancedElbowMotor” and implementing PIDOutput. in EnhancedElbowMotor, there should be an override for pidWrite. then you do your logic from there.

Oh, Im using Java, so if your using labveiw, i dunno how to help. (I think this is somewhat applicable for C++, but im a newbie to C++)

Sorry for the late response, been really busy. First, I am using java. Actually, I have implemented PIDOutput for the arm. This is the code for it:


package org.usfirst.frc.team3997.robot.pid;

import org.usfirst.frc.team3997.robot.hardware.RobotModel;

import edu.wpi.first.wpilibj.PIDOutput;

public class ArmPIDOutput implements PIDOutput{
	
	RobotModel robot;
	
	public ArmPIDOutput(RobotModel robot) {
		this.robot = robot;
	}

	@Override
	public void pidWrite(double output) {
		robot.moveArm(output);
	}

}

And the reason for limiting velocity, is we might need full power to overcome inertia in the beginning, but not as much when the arm is higher up. (Sorry for the bad explanation) :wink:

Page 92 of the Talon SRX software reference manual has example code that does this.

You should look a bit more closely at the PIDController class.

I’m trying to limit the velocity of the arm(degrees/second), not the motor output (-1 to 1)

It is not clear how you think doing this would work. If you had direct control over the process variable such that a hard limit could be trivially imposed, there would be no need for a PID Controller.

If you are running a velocity PID, you can easily limit the setpoint. This does not guarantee that the process variable (velocity) won’t exceed the setpoint during operation, but if the loop is well-tuned it should not do so by much.

If you are running a position PID, you have no direct velocity feedback and so have no way to accomplish this in the position loop itself. You can, of course, cascade the output of your position loop to a velocity loop, and then do what is described above.

That’s still a bit confusing. What is causing the “inertia” to be less when the arm is higher up ? Is the arm articulated ?

Perhaps you meant that the PID tuning works when the arm is lower, but not when the arm is higher, because of gravity. If that’s what you meant, have you explored some kind of gain scheduling ?

So, when the arm is down and I want to move it up, I have to work against gravity and inertia. Quote from my mentor after I asked why I needed something other than output range :

Because as the arm changes angle, those power outputs will mean drastically different speeds.

The problem is that your system is not linear- how the motor outputs correspond to your measured system changes based on the current measurement (value of the process variable.)

One path to the solution you are looking for is making your system linear. This is achieved by using a feed-forward term- adding something to your output that reverses the effect of different positions of the arm. For a single-jointed arm affected by gravity, this will be in the form of A * cos theta, where theta is the angle above the horizontal, and A is some constant that such that this feedforward term counteracts gravity (physically, it’s the opposite of the torque that gravity exerts on the arm, expressed as a voltage applied to a motor.)

Linearizing your system will make motor output speed correspond more directly to speed of your system, and may make it so that you don’t need to do this in the first place!

Your mentor is correct, but in the above quote from your mentor, there is no mention of “inertia”.

So, when the arm is down and I want to move it up, I have to work against gravity and inertia.

Why do you think the “inertia” changes with different arm angles? Is your arm articulated ?

Perhaps what you meant was that the required torque changes, depending on arm angle. Torque and inertia are two entirely different things.

You may be able to solve this problem with gain scheduling, or feedforward (see Nick’s post), or both.

Thanks, sorry for my ignorance of physics

One way to avoid the problem of gravity affecting arm speed is to gear your arm to be gravity-negligible. Using 10% or less of a motor’s stall current to move the arm will ensure there is no significant velocity change as the arm changes angle.

No problem! We’re all here to both teach and learn!

As you’ve probably seen though, you have walked into a somewhat non-trivial physics & control-theory problem - I wouldn’t expect this one to get solved with “just a bit of code” which happens to work first shot on the robot.

Just so we don’t leave you hanging, do the principles expressed here make sense? Particularly the notes about linearization via feed-forward, direct control over process variable, and the cascaded control loop make sense? It’s ok to say “No”, these are topics not usually taught till well into an undergraduate engineering curriculum. (Though, I believe, they are not so complex as to be beyond the grasp of a FRC student).

To execute this properly, it will be important to understand the theoretical concepts & behavior first. We might be able to work with you some here if you wish to drive understanding. It would also be super helpful if the mentor you are working with was familiar with this thread and the control theory involved.

I’m still not exactly sure what Feed forward is, or a process variable, but I vaguely grasp using the position pid to influence velocity pid. I don’t know how to implement any of them though :frowning:

Thanks again for your help

“process variable” is simply a technical term for your feedback signal.

So if you are using a pot to measure arm angle, then “arm angle” is your process variable.

Feed forward is an additional tuning parameter. PID has three tuning parameters Proportional, Integral, Derivative. You can add feed forward as a 4th tuning parameter and it’s called PIDF.

[strike]Give me a few minutes and I’ll draw a sketch.[/strike]

EDIT:

I see you are using Java, so maybe a sketch is not the right way to help.

If you are presently using just a simple P controller (proportional only), then what you are doing is this:

output = Kp*(setpoint-process_variable)

You can add a feed forward term to that like so:

output = Kp*(setpoint-process_variable) + F(setpoint)

F() is a function which you can determine experimentally. Run your arm open-loop to determine how much throttle is required to hold the arm statically various positions along its travel. Then fit a curve to those test points. That’s your F() function.

Have you considered using a Motion Profile? An MP system might be your best bet. As Ether and a few others mentioned, you’re going to have a pretty difficult time limiting the velocity of a PID Loop, but if you use a Motion Profile, you can, by definition, control the speed and acceleration of the system at any given time. The TalonSRX has a pretty well documented system in place for it. You might want to look into that if your current route isn’t working for you. We are using it to control our Drivetrain during autonomous this year and are having a pretty good time with it. I recommend taking a look into it. You can a Motion Profile Generator to create the paths, and CTRE’s sample code to follow the paths using your Talons.
Generator Link
Sample Code Link

Well, we are way behind schedule (we haven’t even mounted the sensor much less tested pid, comp is in 4 days :frowning:) so I’m not even sure it will be a problem. And I don’t know how to follow a path not used for driving, (using sparks).

This my help. If I’m understanding right - I am presuming this system is provided a changing setpoint over time? A trivial, non-SRX implementation may simply be to only allow the setpoint input to the PID to change by a certain amount per loop (ie, if you want to limit to 100 deg/sec, and you are running at 20ms/loop, then don’t let the PID input change by more than 10*0.02 = 2 deg/loop).

This is the same ramping strategy many people use for limiting current draw on a drivetrain.

What this will not solve: If the force required to move the arm changes due to angle (because gravity, as you have indicated), the system is still non-linear. You may or may not be able to get a set of PID gains which work well for all angles.

OP, for your understanding, “Path” here is used in a more general sense than you are thinking probably. For drivetrain, a “path” is defined by a set of 3-element data points: (time, X position, Y position). The same term could be applied to your arm, except the “path” is a set of 2-element data points: (time, arm angle). The reduction of a degree of flexibility helps reduce the “creativity” needed when creating a smooth transition between defined points.