Our climber consists of 2 ThriftyBot elevators and two homemade fixed-length rotating arms. Each is controlled by a Neo and SparkMax. We’re using the Smart Motion profile and for the most part things are going well. We need to retract the elevator all the way down in order to rotate the arms to get their hooks over the bar. Then we extend the elevators, thus lowering the robot so it’s hanging from the arms. The elevator has a fixed stop where the inner tube hits a mounting bolt at the bottom.
Our problem is that the Smart Motion profile overshoots the requested position setPoint. We have tried varying the max acceleration and max velocity and we have also tried varying the P & I values in the velocity PID. We don’t have enough play in the elevator to characterize the velocity PID loop.
I found the setPoint value for the lowest elevator position by going down in small increments. But if I try to go to that point from when the elevator is fully extended, I get the overshoot.
Any suggestions on how to tune this?
Note that we are currently just trying to tune this with the robot sitting on the ground, so the elevator is not bearing any weight. I suspect things will be different while hanging, but I wanted to get a feel for tuning before hanging the robot. Is there a chance that we won’t get the overshoot under load? (The good news is that if I overshoot while extending the arm, the winch will just overrotate and wind up a little rope and then go back to the right spot so my arm will end up at the highest point.)
There are a couple things you should probably take note of:
You can’t tune feedback control loops in an unloaded environment and expect them to work in a loaded environment. What’s more, unloaded mechanisms have much smaller time constants than loaded mechanisms, so they’re generally harder to control (the faster the mechanism moves, the faster your loop frequency and measurements have to be).
IIRC, SmartMotion follows profiles by cascading to the SparkMax’s internal velocity controller. However, the SparkMax has a hardcoded filter on that it applies to its NEO velocity measurements that adds a sensor delay of about 110ms. This has huge effects on the performance of the feedback controller. For reference, here are optimal feedback gains for a drivetrain with and without this delay - note the factor of 50 difference:
If you use position control on the SparkMax along with a trapezoidal profile on the RIO, you should not have any trouble.
As for getting gains, you can obtain good estimates of kG, kV, and kA from ReCalc, and use these to find optimal PID gains in SysId’s theoretical mode (nab the latest version off of github to gain access to this feature).
I realize that I will have to re-tune for a hanging robot. I was just trying to make sure I understood the system before doing that. (I hope that doesn’t sound snarky. It isn’t meant to.)
We really haven’t dug into all the motion profiling capabilities that are available. I found the SparkMax Smart Motion and it sounded like it would do what we want. But if there is a delay in the loop, I can see where the overshoot could come from. So if I understand correctly, you are suggesting that we use an edu.wpi.first.math.trajectory.TrapezoidProfile and the SparkMax internal PID in kPosition mode? That would follow the example from Trapezoidal Motion Profiles in WPILib — FIRST Robotics Competition documentation?
And since I have a rotating arm and an elevator, I could use the ArmFeedForward and ElevatorFeedForward in place of the SimpleMotorFeedForward shown in the example. That sounds pretty cool. Now to see if I can get my (almost) all rookie programming team to understand this and implement it.