default m_period for PIDController???

Hi All,
Our team (3018 Nordic Storm) has created a PIDSubsytem class and instantiated 4 of them and given them a SpeedController implementation


class NordicSpeedController extends PIDSubsytem implements SpeedController{


In this way we can instantiate 4 separate PID Subsystems by passing a Talon and an encoder to each and then in the class we implement the set() entry from the SpeedController interface to call setSetpoint() and set up the returnPIDInput to scale the rate of the encoder such that 1.0 generates a rate that is our maximum. This can also be accomplished by the call to setDistancePerPulse() though.

Then we pass these 4 NordicSpeedControllers to RobotDrive and we of course get far better results on our mecanum drive than using a standard SpeedController (Talon) with just PWM setting without feedback.

As we were tuning the PID, we discovered that it was very sluggish. Upon further investigation, we discovered that in we have:

public static final double kDefaultPeriod = .05;

private double m_period = kDefaultPeriod;

From what I could tell, these are in seconds so we only revisit the pid 20 times a second by default??? I don’t have last year’s wpilib on my system but I seem to recall teleopPeriodic was called 50 times a second and that PID’s defaulted to 100 times a second (0.01 period).

We changed our period to .005 (by passing in p,i,d,f,period constructor via super()) and things got much better, so I think we followed the breadcrumbs properly to resolve our issue.

So my question for the forum is-- did we get off in the weeds and misunderstand something? I tried searching CD for various keywords to find a discussion of the above but failed miserably-- that’s not to say there are no threads,but I could not find any. I find it hard to believe others have not run across this. If we are not in the weeds-- I wanted to raise the visibility of this because a 50ms period is going to make PIDs not work well at all from our experience.

In looking at how PIDController schedules its period, it seems that an overall scheduler schedules all tasks and that the minimum resolution is 1ms. I discovered this at home after our practice so I will be having our team try 1ms instead of 5ms the next time we meet (unfortunately only 3 times a week :eek: ). Running 4 pids at 5ms period barely put the roboRio load over 20% so that was pretty cool!

We had planned to use the CAN Talon to marshal the PID for each motor in a largely similar way (to minimize effort of rio), but we didn’t have the SRX when our pracitce chassis was complete. We have the Talon’s now, but we still haven’t wired them up yet, and I’m wondering if there will be much of a benefit.

Thoughts anyone? Anyone have similar insights to share? I think adding a Speed Controller interface to a PID Subsystem is a nifty way to use RobotDrive along with encoders which otherwise isn’t terribly simple, so I wanted to throw that out there for teams to consider as well.

I’m pretty sure that increasing the PID frequency does not actually improve the performance much. In the WPILib implementation, multiplying the PID frequency by a certain amount effectively multiplies the the I and D terms by the same value. This is because the PIDController does not normalize for elapsed time internally. I think that might be what actually caused your wheels to perform better.

There is also the possibility that I am totally wrong about this, so feel free to correct me if you know more about it.

I just read the calculate() function in the latest wpilib. I could have sworn some 4 years ago when I first read this code that they used m_period in the calculation for the I and D components. But I don’t see anything in the current implementation to account for that. So I think I get your first point.

But I don’t quite follow your full thought. You start saying increasing PID frequency does not improve the performance, but the wheels perform better becuase we increased the frequency and that caused the I/D to calculate differently.

For me it is just common sense that the more frequently you sample the sensor, the more frequently you can compensate for the changes and thus achieve better performance.

My understanding is that The I value should be multiplied by the integral of the error function over time. Normally one draws a bunch of rectangles under the curve and sums the length/width product of each of these to approximate an integral. PIDController seems to assume the period is going to be perfect each time (so hopefully we don’t revisit at 50ms and then 70ms later and the 30ms after that) and assumes the width of each rectangle is 1.0 and thus has done a sort of internal normalization of a 50ms rectangle width to 1.0 width. I think this means that a faster frequency will require a smaller I for equivalent behavior.

If I run a 50ms period and take 3 successive errors of 0.3, 0.2, 0.1 over 150ms, m_totalError is then 0.6 and if I have I=0.01, then the I component of output would be .006 and the P component would be identical.

But if I run a 5ms sample we would have acquired 30 successive errors of 0.3, 0.29,0.28,0.27,0.26,0.25…0.1 over the same 150ms and our m_totalError would be 4.2 so to achieve the same I component of .006 we would need an i of .0014, not .01.

I think you might be suggesting that we kept the same PID values before and after changing the frequency and the above effect is what improved performance (we effectively used a much larger I had we not changed I). Is that what you meant? In our case however, we did not arrive at same I for best performance iirc. Not sure though.

But I still tend to conclude that with faster frequency we can more accurately calculate an estimate of delta-error and the integral of the error function (significantly better I believe) and find better performance through the better accuracy of those values.

Last year was the same as this year. telopPeriodic is 50hz and PIDController is 20hz.