PID Controller Tuning & Flight Settings - heliflight3d/heliflight GitHub Wiki
P, I, D, and F
The Proportional (P), Integral (I), Derivative (D), and Feedforward (F) terms are the heart of a PID controller. The PID terms form the "feedback" portion of the controller, and the F term forms the "feedforward" portion of the controller. The feedback terms operate on information from the gyro about what has happened in the past, while the feedforward terms use inputs from the pilot to provide servo and motor output commands based on predictions about what will happen to the helicopter in the future.
Noise in the gyro traces caused by vibrations from the helicopter can wreak havoc on the feedback portion of the PID controller. This noise will cause fast oscillations in the servo outputs as the PID terms cannot differentiate the noise in the gyro from the real information about the rotation rate of the helicopter. These oscillations will then be detected by the PID controller and cause additional control responses. Thus if your helicopter is "noisy" due to imbalanced blades, bad bearings, chipped gears, or other problems, then you will have to reduce your PID gains dramatically in order to prevent catastrophic oscillations in the control system. Reducing gains will cause very poor performance of the helicopter to both control inputs and disturbances like wind and flight dynamics. Low gains can even cause control oscillations as the pilot will feel "out of sync" with the helicopter and may be providing inputs that appear heavily delayed. It is best to first fix the noise problems by fixing the mechanical issues and/or tuning the noise filters in Heliflight.
The Feedforward terms are not really affected by gyro noise as they do not rely on gyro information for their function. Instead, the Feedforward terms look at the Setpoint command from the radio control and apply a gain to that setpoint in order to determine what the required control output should be. For the roll and pitch axis of a helicopter, this feedforward is a constant term that is applied during the entire time that a rotation is requested on one of those two axis. Constant application of tail thrust is not required to maintain a yaw rate, so the Yaw axis feedforward is instead based on the rate of change of the Yaw axis setpoint, and not on the current value of the Yaw axis setpoint.
These are example P/I/D/F gains from a helicopter running Heliflight. Try reducing the P & D terms by 25% on the first test flight, although so little experimentation has been done that it's hard to say if that's really a good starting point for most helicopters or not…
set p_pitch = 140
set i_pitch = 40
set d_pitch = 70
set f_pitch = 125
set p_roll = 100
set i_roll = 50
set d_roll = 30
set f_roll = 150
set p_yaw = 150
set i_yaw = 40
set d_yaw = 10
set f_yaw = 5
Pidsum_Limit & Iterm_Limit
Each term in the PID Controller is summed together to produce the output on each axis (roll, pitch, and yaw). Pidsum_limit
limits the maximum value of the sum of all of the terms for an axis in the PID controller. This is important because it is usually not ideal for the PID controller to attempt to provide more control action than the system can accept. This can cause error to accumulate in the integral terms which will cause unwanted overshoot later on when the error begins to be reduced.
The Servo Setup & Servo Mixing document has you scale the Roll and Pitch axis servos to an assumed pidsum_limit of 500. So let's set the roll and pitch axis to 500 using pidsum_limit. The yaw axis has it's own pidsum_limit.
set pidsum_limit = 500
- If you cannot get your desired cyclic pitch setting while setting up the helicopter when you already have your smix rates at maximum (the highest rate value can only be 100), then you might need to increase the
pidsum_limit
beyond 500.
set pidsum_limit_yaw = 1000
- It is a good idea to ensure that
pidsum_limit_yaw
is high enough that the tail servo can use it's full travel. Observe the min/max limits for the Yaw (tail) servo configuration. Subtract each from the center value of the servo and see which one is farther from the center. Take the larger value and divide it by the "Rate" percentage that is configured for the Yaw channel smix (servo #5). Divide this value by 0.7 and the result will be the smallest that you should set yourpidsum_limit_yaw
. - As an example, the minimum pidsum_limit_yaw for the settings below that would allow for full tail deflection would be: (855-732)/(0.33*0.7) = 532
- servo 5 610 855 732 100 -1
- smix 8 5 2 -33 0 0 100 0
set iterm_limit = 400
- iterm_limit simply limits the maximum error that can accumulate in the integral term. Too small of iterm_limit could affect the heading hold ability of Heliflight, especially on the Yaw axis. Too large of iterm_limit could lead to large overshoots when the requested rotation rate can't be achieved by the helicopter for whatever reason (mechanical control limits, gains too low, etc).
Error accumulation at pidsum_limit
Integral error and Absolute Control error is not allowed to accumulate on an axis if the pidsum_limit
for that axis has been reached. This means that the "heading hold" feature on that axis is no longer accumulating error and the helicopter will not reach the exact angle inferred by the stick deflection integrated over time. On the other hand, the helicopter rotation will stop exactly when a stick is returned to center.
This really only becomes a concern when the commanded rotation rate on an axis (setpoint) is higher than the helicopter can physically achieve. As an example, if your roll rate is set to 480 deg/s, but your helicopter is only capable of achieving 360 deg/s, then the PID controller will likely hit the pidsum_limit value as it drives the servos to the maximum cyclic pitch deflection you have configured. If the error continued to accumulate on the roll axis during this time, then when you returned the stick to center the helicopter would continue rolling until the accumulated error was offset back to zero. This process could sometimes take a half a second or more after the stick returned to center and was very unnerving for the pilot! Preventing the error accumulation on an axis when it is at the pidsum_limit solves this overshoto problem.
In other maneuvers like a very fast funnel, the commanded rate on an axis might be really small when the pidsum is high. In this case, even through the yaw stick may only be commanding a low rate like 20 deg/s, the Yaw pidsum will be very high as a lot of tail thrust is necessary to hold the position of the tail against the wind coming from the side of the helicopter and the torque from the main motor. If not enough tail authority is available then the pidsum_limit
will be reached at the tail will only return partially to the correct orientation after it weathervanes into the direction of flight. It was found through experimentation that this is preferable to having the tail swing around wildly for half a second or more after the tail initially let loose.
There is no setting to change for this functionality. It is enabled by default in the code.
Absolute Control
Absolute Control is a feature from Betaflight that tracks stick movements and gyro response and accumulates the angle error over time between the setpoint and the gyro rate. In this way it is similar to an Integral term. However, while the Integral term applies a gain to this error and sums that in the output, Absolute Control feeds the error back into the setpoint of the PID controller. This means that all of the PID+F terms are applied to the Absolute Control output, including the Feedforward term.
Absolute Control provides for rotation of the error among the axis of the helicopter as it rotates in space, which helps provide the correct inputs while the helicopter pirouettes. This is similar to pirouette compensation in some ways.
When Absolute Control is applied, the Integral term of the PID controller is reduced on each axis in proportion to the AC gain. For low Integral gain settings, this can mean that there is no Integral term contribution to the PID controller.
More information on Absolute Control can be found by reading through various Betaflight documentation on this feature.
set abs_control_gain = 7
- This is the gain applied to the accumulated absolute control error on each axis. The error is multiplied by the gain, and that becomes the new Setpoint offset for that axis. This Setpoint offset is then added to the Setpoint of the PID controller.
set abs_control_limit = 120
- This is the limit of the total amount of setpoint offset that absolute control is allowed to add to the Setpoint of the PID controller for each axis.
set abs_control_error_limit = 45
- This is the limit for the amount of accumulated angle error on each axis. The accumulated error is multiplied by the AC gain to determine the setpoint offset, so the abs_control_error_limit and abs_control_limit have some overlap in functionality. The difference is that one limits the amount of setpoint change directly, and the other limits the amount of "wind-up" or accumulated error that can occur over time. This accumulated error will need to be offset by error in the opposite direction in order for the total error to return to zero. Setting the error_limit too large could result in long control overshoots on an axis for certain situations.
set abs_control_cutoff = 11
- This is the cutoff frequency of the high-pass filter used to evaluate setpoint changes and limit error accumulation during fast setpoint changes (typically fast stick movements or enabling rescue mode).
I-Term Relax
Absolute Control must be used with I-Term relax. Not much experimentation has been done with the I-Term Relax settings. Mostly they will affect stick feel. Only recommended on the Roll & Pitch axis? (TBD)
set iterm_relax = RP
set iterm_relax_type = SETPOINT
set iterm_relax_cutoff = 12
I-term Rotation
This feature is the closest thing in Betaflight to true "pirouette compensation" found in other FBL controllers, however the Betaflight implementation is not ideal for helicopters. I-term error really only needs to be rotated on the roll and pitch axes, and only the error not related to CG and tail thrust should be rotated. A calibration flight mode and additional modifications will be needed to I-term rotation before it is appropriate for helicopter use. For now, Absolute Control works well enough for pirouette compensation effect.
set iterm_rotation = OFF
Collective and Cyclic Feedforward
Changing the collective or cyclic pitch during flight changes the load on the main motor of the helicopter. Higher pitch values result in higher load, and thus higher torque supplied from the motor. This torque going into the main shaft of the helicopter will result in the frame of the helicopter rotating in the opposite direction. The change in torque must be offset by the tail rotor thrust. The PID controller's feedback terms (P, I and D) can accomplish this after a slight delay, but this delay will show up as a "kick" of the tail if a governor is being used for the main motor. Since the flight controller has full knowledge of the amount of change in collective and cyclic pitch, we can instead use Collective and Cyclic Feedforward terms to offset the change in torque before the motor even has time to begin adding or removing the torque.
The amount of torque supplied by the motor will change based on whether a governor is actively managing the RPM or not. If no governor is used with a flat throttle curve, then the torque change will still exist but will not be as dramatic. With a governor in use the torque change can be very high depending on how aggressive the governor is tuned.
While tuning the Collective and Cyclic Feedforward terms, it is helpful to watch the direction that the tail is kicking out before increasing or decreasing the terms. If the tail is kicking out with the torque from the main motor, then the feedforward terms need to be increased in order to provide additional counter-thrust from the tail. If the tail is kicking out against the torque of the main motor, then the feedforward gains are too high for the amount of torque being added by the main motor. It is also good to observe when these changes happen. Do they happen immediately? Does the tail kick offset occur during the entire length of a collective punch-out? The change in the terms that accumulate error on the Yaw axis (Integral and Absolute Control) can be observed in the log files to see if the Feedforward gains have been set appropriately. Ideally, the Feedforward gains would be set so that no change in the accumulated error is seen in the logs during changes in pitch.
Note that very similar settings are available for the main motor governor in order to provide predictive torque to the main motor. Increasing gains on the main motor governor may require increasing the Yaw collective and cyclic feedforward gains as well.
set yaw_collective_ff_gain = 150
- The collective_ff_gain term applies a gain to the absolute value of the collective channel input. More collective pitch (positive or negative) will lead to more feedforward in the Yaw axis, which will result in more tail thrust. Zero collective pitch (center stick) will result in no feedforward contribution from this term. The effects of this term are immediately obvious when doing collective pitch pumps.
set collective_ff_impulse_freq = 100
- The impulse_freq term sets the cutoff frequency of the high-pass filter used to separate out fast collective stick movements from a slow-moving on non-moving collective stick. The idea is that more torque compensation is needed for fast impulse changes in collective pitch (when the collective stick is moving very quickly).
set yaw_collective_ff_impulse_gain = 100
- The collective_ff_impulse_gain term applies a gain to the output of the collective feedforward impulse high-pass filter. The faster the collective stick moves, the higher the output of the filter will be, and that output will be multiplied by this gain to provide additional thrust to the tail motor.
set yaw_cyclic_ff_gain = 100
- The cyclic_ff_gain term looks at the output of the PID controller and provides a feedforward gain on the amount of total cyclic pitch combined from the roll and the pitch axes.
set yaw_base_thrust = 0
- The yaw_base_thrust term provides a base value of thrust that is necessary to offset the main motor torque when the blades are at zero pitch. It is not really necessary to use this term as ultimately the base thrust offset will just end up in the Integral term of the Yaw axis. This feedforward term has been implemented in order to provide enhanced support for motor-driven tails.
Elevator Filter
Larger helicopters (360mm blades and larger) tend to have some overshoot and "bounce" on the elevator axis. This is commonly referred to as "elevator bounce", and is likely due to the extended length of the tail boom giving some inertia to the helicopter for forward & back pitching. It is usually only observed when quickly stopping an elevator movement in a hover. Other mechanical issues can cause bouncing on stops, such as a loose linkage or servo arm, sloppy servo potentiometer, etc. Mechanical issues should be checked before attempting to addressing the elevator bounce using software tricks.
The elevator filter in Heliflight simply slows down the response of the Feedforward term on the elevator (pitch) axis when it returns to zero. It does this by creating a "window" around the setpoint of 0 deg/s and determining how long it has been since the commanded rate was outside of the window. If it has been longer than the elevator_window_time setting, then the elevator filter will slow down the return of the elevator feedforward to it's new setpoint within the window. This "slowing down" is accomplished by replacing the direct feedforward term with a low-pass filtered version of the feedforward term once inside the window if the time conditions are met.
Small helicopters like the OMP M2 do not seem to need much (if any) elevator filtering.
set elevator_filter_gain = 100
- Set elevator_filter_gain = 0 to disable the elevator filter code
- The filter gain is the multiplier for the elevator filter feedforward offset
- This value is divided by 100 in the code, so start with a setting of 100 and work up from there.
- Filter gain automatically scales with the elevator (pitch) axis feedforward gain
set elevator_filter_window_time = 100
- Time is milliseconds to apply elevator filter after entering the filter window
- Recommend 100 ms
set elevator_filter_window_size = 30
- Size of the filter window in deg/s, centered around 0 deg/s pitch rate
- Recommend 30 deg/s
set elevator_filter_hz = 5
- Cutoff frequency for the PT1 filter applied to the elevator setpoint
- Lower setting should give less bounce, but will slow the elevator stop response. Find a balance!
- Lower settings will require longer elevator_filter_window_times to be effective, and vice-versa.
- Recommend 5 Hz
Betaflight features and settings that still exist in Heliflight, but are not used
Do not enable or use these features:
- Anti-gravity
… More to be completed …