EvoPid is an auto-tuning PID controller from ETK. It uses evolutionary algorithms to search for optimal PID gains.
There are a number of ways to tune a PID controller. PID gains can be calculated using hard rules and previously gathered data. Methods that use this approach include the Zigler Nichols method and relay-based tuning. These methods specify a process – a means to an end – without guaranteeing that the result is optimal for a given situation. An alternative approach to PID tuning is to specify how an optimally tuned system should respond, then search for gains that work best. Essentially, this is ‘hand tuning’ only automated.
EvoPid uses an evolutionary algorithm to search for optimal PID gains.
EAs (Evolutionary algorithms) are a searching heuristic – a short cut that gives ‘close enough is good enough’ results. EAs maintain a population of different possible solutions called genomes. In this context, a genome consists of PID gains Kp, Ki and Kd. Each genome is given a fitness rating which represents how close its performance is to ideal. Once the entire population has been rated, survival of the fittest takes place. The best performing genomes are combined randomly to create a whole new population. Every now and again, there will be a mutation (a gain is changed randomly). Eventually, the entire population will become close to ideal.
Basic PID Rating
EAs must rate each genome. It’s absolutely essential that genomes are rated so that better performing gains are given good ratings. If the rating algorithm can’t spot a good PID controller (i.e. gives random ratings to identical genomes), the EA will never settle on optimal values.
A naive way to assess the performance of a PID controller is to measure the average amount of setpoint-measurement error over a period of time. Both over tuned and under tuned systems will usually have more error for a given time period than an optimally tuned system. The BasicPIDRater has a function called set_minimum_samples that specifies the minimum number of samples to record before calculating the average error. In practice, this approach alone performs poorly. A system that has reached a stable point of equilibrium can be poorly tuned without displaying any symptoms. The system must be perturbed for it’s performance to be assessed.
There are two ways to perturb the system. One is by changing the set point. The other is by disrupting the system externally ( poking it ). Set point changes are easy to measure, but external disruptions *should* not be. If there is a predictable external disruption, it should be accounted for by some other means such as feed-forward. EvoPid assumes disruptions are random and short lived, so they are ignored. That means the only practical means of detecting a disturbance is by checking for a change of setpoint. The BasicPIDRater has a set_min_setpoint_delta function that specifies the minimum amount of set point change that must occur before the genome is rated.
At this point, the basic PID rater must require both a minimum number of samples, plus a minimum amount of set point change to occur before it will calculate average error. The final score is equal to the average error. I have experimented with this form of PID rating and found that it actually tends to over tune controllers. This is because fast, high frequency oscillations produce less total error than an equivalently under tuned system. I worked around this particular issue by detecting if the measurement was oscillating, and if so it would multiply the error by a two. This made the rating algorithm favour a very slightly under-tuned system, and gave more stable results.
The random nature of genetic mutations means the chance of a mutation being beneficial is also random. In real biology, bad mutations will often mean defective offspring won’t live very long. In EA lingo, these are termed fatal mutations. In a PID control system, a bad PID setting could be disastrous. The PID pid rater should be able to detect very bad performance and rapidly remove the faulty genome. The basic PID rater has a function called set_max_error. When the average of the last 10 samples crosses the max error threshold, the genome is terminated early. This can help speed up evolution by rapidly removing very bad genomes and can also help prevent bad genomes from causing real damage.
Let’s discuss a hypothetical evolutionary problem. We’ve got a population of humanoid creatures called ‘ewoks’. The ewoks have arms and hands but no thumbs. If they had thumbs they could throw spears more easily and increase their change of survival. The ewoks unknowing live next to an abandoned nuclear power station. They tend to REALLY mutate. A lot of baby mutant ewoks don’t survive long after birth due to the drastic nature of their changes. The ones that do survive have extra arms, two heads and so on. None of these mutations provide the advantage that a simple thumb could! It’s not to say they couldn’t mutate into having thumbs, just the range of possible mutations so large that it greatly reduces the chance of a small but beneficial mutation. As time goes on and the radiation from the power station dies down, the severity of the ewoks mutations decreases. The survival rate of baby ewoks increases and their mutations become less pronounced. Mutants are now more likely to develop extra fingers rather than extra arms or heads. One of these mutants finds he can use his extra digit to throw spears very well, which impresses the ladies and causes his beneficial mutation to merge into the gene pool.
EvoPid has three settings that influence the evolutionary algorithm. These are
- Maximum mutation level. This is how strong the radiation from the old reactor is.
- Minimum mutation level. This is ‘background radiation’ – the lowest allowable mutation level
- Mutation chance. This is the chance of a mutation actually occurring each re-population.
The maximum mutation level sets the largest possible change that a mutation can make during re-population. A large value can increase the rate at which EvoPid finds good gains. It will also make the system more unpredictable and increase the chance of a fatal mutation. If this setting is too low, the EA can take an excessively long time to find optimal PID gains. A good rule of thumb is: make the max mutation level equal the range of possible P gains. Let’s say you expect the P gain to be between 20 and 80. Set the max mutation level to 60.
Every time EvoPid repopulates, the maximum mutation level is multiplied by 0.99. This causes the mutation rate to reduce every generation (emulating the decay of radiation from the reactor). By progressively making smaller mutations, EvoPid is able to hone in on optimal PID settings more precisely. The mutation level will never be reduced below the minimum mutation level.
A minimum mutation level is necessary only if the PID controller is in an ever-changing environment (such as the ewoks, who now have to slowly adapt to global warming).
The mutation chance is the change of a mutation actually occurring each time genomes are recombined to create a new population. Typically, this would be about 0.15 ( 15% chance) for EvoPid. Making the mutation chance too high will degrade the EA by turning it into a random search. Set this too low and evolution will take longer than necessary.