Elevator is Spasing while extending

Hello, our team has an elevator(arm) for the game this year which has a potentiometer which we are using to bring it to setpoints. We use the standard wpilib PID(p = .34 I = 0, D = 0.03) to extend it to predetermined setpoints. 80 percent of the time, our arm moves well, with no jittering or rough extension. However, often times, our arm starts spasing and jittering while trying to go to its setpoint. (It still gets to the setpoint, but it’s very slow, and looks painful). I added the extension command in this post. Does anyone have any ideas why this phenomenon is happening once in a while. I don’t believe it’s battery because it happens even with a full battery. Also I think I could tune D higher but I’m not sure if that will fix the problem.

You can see it happening at time 0:41(team 2791)

It’s very hard to tell if this is a mechanical problem (something sticking and loading then unloading) or a controls one. A mechanical problem might look like a controls problem. If you graphed the output command to the motor, and it’s a smooth value, then it’s likely mechanical. If you graph the output and it’s a very noisy value, you might have noise on your potentiometer line.

Thanks, I’ll definetly try displaying the graphs

Do you have any logic to hold your elevator position? When we had logic like that, it was causing our elevator to spasm the same way. If not, another thing could be gear slip since you’re using a position PID. My team uses trapezoidal motion profiles for the elevator motion and it’s made it a lot smoother and accurate than it used to be when we used position PIDs.

First, if you are controlling position using just the potentiometer you will have a harder time holding a set point as all of the system “slop” will add to being unable to hit your setpoint. Think all of the gear lash in your gear reductions, chain stretch, cable stretch, constant force springs, or rope stretch. Think if you elevator misses the target, everything in the system has to reverse and you can end up in a bad feedback loop where you are bouncing back and forth past your setpoint because the controller keeps ramping command to swap back and forth between all the system backlash. If you have an encoder on your motor (using a neo, falcon, or venom) it might be better to use this to control to setpoints and using your absolute encoder (potentiometer) to help zero the system/ provide verifications that you moved to a set point.

I would consider adding some I gain (making it non zero) to your system tuning as that helps the system settle around your setpoint, however having a more robust mechanical system and more solid sensor strategy is always a better 1st move.

We don’t have anything to hold the position. For a trapezoid motion profile, do you mean instantiating the pid controller as (new ProfiledPidController(kp, ki, kd, Constraints(MaxV, MaxA). I thinking trying trapezoid might be worthwhile, but I never quite understood what those constraints did, because I never knew where they were getting those velocities and accelerations from.

Yeah I meant a ProfiledPIDController exactly like you said. It’s worth a try. Really ended up helping our elevator motion a ton!

Do u know what those constraints are actually? Like how is the profile setting velocity and acceleration when I haven’t given it the encoders of my motor

I believe the constraints are in the same unit of velocity that your PID will be outputting . Those should be fed into a feed forward calculator expecting the same units to determine voltage.

So your PIDController normally calculates a position your encoders should be at at time t according to the PID Constants kP, kI, kD. Based on that, you can get a position versus time graph for your PIDController. With a position-time graph, you can get a velocity-time curve. The Trapezoidal motion profile constraints apply constraints to that velocity-time graph.

For actually working with it, you can look at this command in our code base for driving the robot to a certain pose (completely plagiarized from 7028, all credit to them, awesome codebase): 2023-ChargedUp-177/DriveToPoseCommand.java at post-waterbury · BobcatRobotics/2023-ChargedUp-177 · GitHub

The constraints are in the encoder position unit per second. You could either use a feedforward calculator like @Bmongar suggests, or you could set whatever motor is controlling your elevator to position mode so you can just use .calculate as your output to send to your motor. I recommend using position mode on your motors.

Here is the WPILib Docs on ProfiledPIDControllers: Combining Motion Profiling and PID Control with ProfiledPIDController — FIRST Robotics Competition documentation

If you’re using Falcon 500’s or some other CTRE motor, take a look at MotionMagic control. REV motors, then try checking out SmartMotion (I believe that’s the one but I’m not familiar with REV, don’t quote me). It does the same thing a ProfiledPIDController does for you, but runs it for you in the motor class.


In addition to what Arnav wrote above, check if your elevator is being current limited. If your current limit is too low you may see the jittering, but I’m unsure why you would see it randomly.

The PIDController class makes the assumption that the time steps are fixed (default 0.02 seconds). The execute() might be irregularly executing sometimes due to garbage collection or other processes. Check for the loop overrun messages. CAN bus overload can also effect timing.

Logging the input and output of the PID contriller should be informative. I’d print everything - getpositionError(), getVelocityError(), setpoint, getExtendPot(), output, time.

1 Like

Hi again, we found the problem to be a code problem. Our manual extension code seemed to interfere with our pid extension, since it uses joystick axis values. When the joystick wasn’t pressed, I think it was trying to stop extension during a pid loop, causing the arm to freak out. Since then, we fixed that manual extension code to not interfere and also switched to a Profiled PID controller, and haven’t had any issues since.