I am trying to use a PID controller to stop a quadcopter at a specific location while travelling horizontally, however currently it overshoots/undershoots depending on the max velocity. I have tried manually tuning the P,I and D gains with limited success. Essentially the velocity needs to go from maxSpeed to 0 at the very end of the flight path.

It uses the DJI SDK so the inputs to the quadcopter are very simplistic, the pitch input to the quadcopter is in m/s and I recalculate the distance(m) to the target on each iteration.

I run a loop that executes every 0.1 of a second. Some pseudo code:

kP = 0.25
kI = 0.50
kD = 90
timeStep = 0.1
maxSpeed = 10

currentError = initialDistanceToLocation - currentDistanceToLocation
derivativeError = (currentError - previousError) / timeStep
previousError = currentError
output = kP * currentError + kI * integralError + kD * derivativeError
integralError = integralError + currentError * timeStep

if >= maxSpeed {
    output = maxSpeed
} else if output <= 0 {
    output = 0
return output

Is there a way to reliably tune this PID controller to this system that will work for different max velocities, or is it too simplistic and there are other factors I need to consider?


If you want to work with higher velocities, you need to look into velocity controller as well. You can also try incorporating velocity control into your control system. It enables smooth stopping to point which can alleviate your problem. But a generic PID controller with just position control should not overshoot too much if tuned correctly and the maximum velocities aren't too high.


I don't know to which extent your pseudo-code can be taken as representative of your real code, but I can see the following concerns with it.

Derivative term

In practical applications, the derivative term computed as a one-step finite difference as below is completely useless:

derivativeError = (currentError - previousError) / timeStep

There is a large number of reasons for that, mainly related to the fact that physical signals just like the measured distance from the target are heavily affected by the noise, which in turn has high-frequency components that get amplified by this operation degrading inevitably the PID performance and causing instability.

Thereby, you should instead resort to more sophisticated techniques such as velocity observers (e.g. the Kalman state estimator) or robust filtering (e.g. Savitzky–Golay filtering), or even better sensors that are apt to measure the velocity natively (they are rare and quite expensive devices though).

Don't panic/worry, just drop the derivative term lightheartedly. Remember that 90% of the worldwide PID controllers are simply PI 😉

Integral term

This is the most problematic part. You cannot threshold the controller output within [0, maxSpeed] without telling the PID what is going on. It won't simply work out. By doing this, in fact, you will elicit unwanted oscillations that are right what you have been observing.

To let the controller be aware of actuation bounds, you shall rely on a standard anti-windup diagram.

This is a well-known procedure in literature. You can find it out in the bible of PID controllers (par. 3.5), plus you could read up this interesting MATLAB resource.

Essentially, you need to integrate also the difference between the thresholded output and the sheer output (see the illustration below).

integralError += (currentError + thresOutput - sheerOutput) * timeStep

Integral Anti-windup

Final remarks

Once you'll have fiddled with all the points above, you'll certainly have more chances to reduce the over/undershoots. That being said, a pure velocity controller turns to be a kind of simplistic approach. Therefore, to be even more effective and accurate, you should be eventually playing with the dynamical model of the quadcopter.

Hope it helps out.


The posted sourcecode measures the current system state and then the control action is determined. Even if the calculation is done 10 times per second it is based on a single measurement in the now. The desired behavior to stop the quadcopter smoothly and avoid overshooting is a multi-stage problem. Multi state means, that more than a single decision and measurement are required. In the simplest case, the source code has to be extended with a second input value, so that the equation takes t and t-1 as input.

From an implementation perspective the architecture has a lot of common with using a recurrent neural network and a pid controller together. This helps to improve the quality of the control actions.

  • $\begingroup$ The solution used values from t-1 as input. the derivative term is calculated as the difference between the current error and the previous error. The previous error is coming from t-1. The advice to use recurrent neural networks is interesting, but it is not sufficiently explained, how such a network can be used, what are its inputs and outputs and how to obtain a dataset to train it. $\endgroup$ – 50k4 Nov 2 '20 at 16:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.