I am a first year mentor with a mostly rookie team, so I have steered my team toward trying to use the internal PID control in RobotC rather than trying to write it themselves. So far, it is going reasonably well (once we abandoned the default settings), and I expect with further tuning of the constants, it will get fairly good performance. The automatic debug mode that is available makes it very nice for tuning and is also helpful as a teaching tool (showing error, i and d in real-time among other things).
The challenge I have is the lack of documentation available to describe the internal routine. Is there a detailed description available anywhere? I am particularly interested in sampling/calculation rates, task priority, etc. Also, is there a way to use/reference any if the internal variables used and shown in the debugger? I was hoping to use the error (< a predetermined margin) to decide if a ball is ready to be loaded.
The only description I have seen is here in the forum was helpful, but still pretty thin. It did imply that it was an integer based calculation rather than floating point to optimize processor performance, so that gives me hope that performance was a key design consideration.
Overall, it has been dramatically easier for the team to get operational, but the black-box nature of it, and the lack of accessibility makes me worry about debugging it’s performance as the software gets more complex with more subsystems of the robot being enabled with corresponding software tasks.
We do not disclose the exact algorithm used. The primary reason the internal PID was developed was to help teachers in a classroom setting with trying to make a robot drive in a straight line. With the base clawbot, there were often situations where build issues and differences between motors would cause the robot to veer off to the left or right. The PID was designed to help eliminate this issue when driving from point to point.
mtrPid_Deadband] //Deadband for motor when under PID control.
mtrPid_ErrorD] //The last derivative error (read only)
mtrPid_ErrorI] //The current value of the integrated error (read only)
mtrPid_ErrorP] //The last PID calculated error (read only)
mtrPid_kD] //The value of the derivative constant, Kd.
mtrPid_kI] //The value of the integral constant, Ki.
mtrPid_kP] //The value of the proportional constant, Kp.
mtrPid_Period] //The PID loop execution period in mS.
You can see all of these values in the ROBOTC motor debug window (probably need to be in expert or super_user menu mode).
The “error” we use in the calculation is not exactly an error in velocity (we do not calculate velocity in rpm or anything like that), it’s an error between the number of encoder ticks measured and the number of encoder ticks we expect in a given period (which is another way of looking at velocity). In the thread linked above, you will see we have a maximum encoder counts/second value (default is 1000). If we command the motor to run with the maximum control value, then that means we are expecting 1000 encoder ticks/second, or in a 50mS period 50 ticks. When running at constant speed we effectively move a target position 50 counts further on each time around the loop. In reality it is more complicated than that, we have maximum slew rates for the motor that allow for acceleration and deceleration. We also compensate for actual time that encoders were read in a similar way to what I described in this thread. https://vexforum.com/t/velocity-calculation-traps/32267/1
Using integer math is common on MCUs without hardware support for floating point math, however, we do many internal calculations using float variables. I wouldn’t worry about performance, the cortex is plenty fast enough.
It’s designed for beginner/intermediate use. For something like flywheel control, there’s a good chance that knowledge of the specific system being controlled with allow code to be developed that will have better performance than what is obviously a generalized solution.