Good day,

I am currently working on a project using Complementary filter for Sensor fusion and PID algorithm for motor control. I viewed a lot of videos in youtube as well as consulted various blogs and papers with what to expect with setting the P gain to high or too low.

P Gain too low

easy over correction and easy to turn by hand

P Gain too high

oscillates rapidly

I have a sample video of what I think a high P gain (3 in my case) looks like. Do this look like the P gain is too high? https://youtu.be/8rBqkcmVS1k

From the video:

I noticed that the quad sometimes corrects its orientation immediately after turning few degrees (4-5 deg). However, it does not do so in a consitent manner.

It also overcorrects.

The reason behind my doubt is because the quadcopter doesn't react immediately to changes. I checked the complementary filter. It updates (fast) the filtered angle reading from sudden angular acceleration from the gyro as well as updates the long term filtered angle changes from the accelerometer (albeit slowly). If I am right, is the the P gain is responsible for compensating the "delay"?

The formula I used in the complementary filter is the following:

float alpha = 0.98;
float pitchAngleCF=(alpha)*pitchAngleCF+gyroAngleVelocityArray.Pitch*deltaTime)+(1-alpha)*(accelAngleArray.Pitch);

Here is a video for a P gain of 1: https://youtu.be/rSBrwULKun4

Your help would be very appreciated :)

  • $\begingroup$ I had removed the video as since the dT used is wrong the PID controller is not working properly at all $\endgroup$ Feb 25, 2016 at 15:12

1 Answer 1



I've edited out most of the content I had previously written because your code does work (except for the mis-matched parenthesis), but it threw me off because this is not really a complimentary filter. You have a hodge-podge here that is confusing to look at initially.

First you have a lag filter on the accelerometer output:

alpha = 0.98;
filteredAccelerometer = alpha*filteredAccelerometer + (1-alpha)*rawAccelerometer;

Then, instead of doing proper numeric integration on the gyro, which would look something like:

gyroAngle = gyroAngle + gyroAngleVelocityArray.Pitch*deltaTime;

You instead are substituting in the filtered accelerometer measurement as the "accumulated" angle:

gyroAngle = filteredAccelerometer + gyroAngleVelocityArray.Pitch*deltaTime;

and you are calling all of this a "complimentary filter", such that:

pitchAngleCF = alpha*pitchAngleCF + (1-alpha)*angleAccelArray.Pitch + gyroAngleVelocityArray.Pitch*deltaTime;

However, this isn't really a complimentary filter because there's "option" or "setting" to blend the gyro and accelerometer outputs. I would suggest converting both sensors to a common unit (degres, for instance), then using the complimentary filter to combine the two measurements, then filter that if you find that anything needs filtering.

So, following your schema:

accelVelocityArray.Pitch = accelVelocityArray.Pitch + accelAccelArray.Pitch*deltaTime;
accelAngleArray.Pitch = accelAngleArray.Pitch + accelVelocityArray.Pitch*deltaTime;

gyroAngleArray.Pitch = gryoVelocityArray.Pitch*deltaTime;

alpha = 0.95;
pitchCF = alpha*gyroAngleArray.Pitch + (1-alpha)*accelAngleArray.Pitch;

THIS is the output of a complimentary filter. Now if you find that your craft is not responsive enough you can increase alpha (take more of the reading from the gyro), or if you find that there is too much drift you can decrease alpha (take more of the reading from the accelerometer). If you find that the reading is too noisy, then you can put this through a lag filter:

beta = 0.9;
filteredPitch = beta*pitchCF + (1-beta)*filteredPitch;

NOW you adjust beta to determine how smooth you want the combined pitch reading to be.

I hope this clarifies things for you.

Now, regarding your actual question, I don't think it's possible to give a quality answer with the (lack of) data you have provided.

It is true that, for a real system with inertia, if you set the proportional gain too high the system will oscillate. However, it is not clear if you are only using a proportional gain (if you have kI and kD set to zero). Also, because the craft is tethered and you are holding it, it's not clear if the craft is responding to its own controller or if it's responding to the external forces (you and the tether).

I'm also not sure how stable your control loop timing is and/or how you are determining what deltaTime should be. If you're interested in manual tuning of a PID controller, first be sure that you are processing your sensor output correctly (see my above comments regarding sensor fusion and filtering), then give the Ziegler-Nichols tuning method a try:

  1. Set kP, kI, and kD to zero.
  2. Increase kP until the system achieves consistent oscillations.
  3. Record kP (as the "ultimate" gain, kU), and the oscillation period.
  4. Set kP, kI, and kD to values based on the ultimate gain and oscillation period.
  • $\begingroup$ Oh I am sorry about the mismatched parenthesis, I mean this float pitchAngleCF=(alpha)*(pitchAngleCF+gyroAngleVelocityArray.Pitch*deltaTime)+(1-alpha)*(accelAngleArray.Pitch); My source was Shane Colton's white paper on the Balance Filter: b94be14129454da9cf7f056f5f8b89a9b17da0be.googledrive.com/host/… $\endgroup$ Dec 13, 2015 at 11:52
  • 1
    $\begingroup$ I found my error, I was using the wrong DT now it works like a charm :) Thank you $\endgroup$ Jan 7, 2016 at 8:33
  • $\begingroup$ I just revisited this, I saw the same filter implementation (the lag filter on the post) on a tutorial on filtering accelerometer data in Matlab. They called this the exponential moving average filter. This solved my problem with the vibrations on the quadcopter $\endgroup$ Feb 25, 2016 at 15:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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