I'm a heli guy. However I'm not very satisfied with Vbar. There's certain part that definitely can be improved but they don't. Plus they are selling it way too expensive. I have a lot of used CC3Ds in my toolbox (from a previous quad project). I want to start a flybarless improvement for LibrePilot.
I'm currently a graduate student in computer science, embedded systems more specifically. I do all kinds of programming, but not the GUI part. I'll start improve it without changing the GUI and hope someone could help on that part. Anyway, the LibrePilot has a very good framework to start with.
The goal will be, to improve the LibrePilot on CC3D, make it a flybarless unit comparable to commercial products (let set bar here, VBAR). "Comparable" I mean in performance, User-friendliness will not be my goal, unfortunately.
I name it OBar for OpenBar, now. It's hosted in github
https://github.com/gongtao0607/LibrePilotThe following will be organized as:
- 0. VBar parameters
- 1. VBar algorithm identification
- 2. VBar stick expo identification and mapping to Librepilot
- 3. Some implementation trash talk
0. VBar parameters1. VBar algorithm identification1.1 Tail algorithmAfter several weeks experiment, I came up with this diagram to show the tail algorithm.
Stick Input first goes to a yaw rate scaler(which set by the yaw rate). Then a Low Pass Filter, whose time constant is decided by "acceleration" parameter.
The filtered stick input then compare with gyro and feed to PI Controller. The PI Controller has P gain and I gain which sets separately, plus a gain scaler. The scaler has two sources: one is by an unknown fuzzy logic which has a gain range of 1.0 to 2.0; another is an input edge detector has a configurable gain between 1.0 to 2.0, only applies to the stick movement edge. On the other side, the stick input has a feedforward adds directly to the output. The gain is between 0-1 and can enable self-adjustment
Parameters:assume the stick_input is [-1,1]:
Output = feedback + feedforward;
feedforward = control_loop/128 * yaw_rate/100 * stick_input;
feedback = pid_apply( stick_input * yaw_rate/100 * 500 - gyro );
P = gyro_gain/75 * P_gain/80 * 0.002;
I = gyro_gain/75 * I_gain/60 * 0.036;
Stop gain scaler = 1+stop_gain/100;
Explain:100 in yaw_rate = 500 degree per second
30 in control_loop = 30/128 feedforward gain
75/80 P gain = 0.002 P gain
75/60 I gain = 0.036 I gain
50% Expo = 6 or 7 expo
20 Stop gain = 120% PI scaler during a stop (or acceleration)
All these parameters are all linear mapping (except the expo).
Remember the fuzzy logic can scale every gains up between 1.0x to 2.0x1.2 Cyclic Algorithm:Some new findings: the cyclic controller gain is related to stick input (like the virtual flybar fast flip algorithm) and also the current gyro reading.
Basically, larger stick = lower gain, faster movement = lower I gain and higher P gain. The relationship haven't be clearly found out. The major difficulty here is that the controller is not a pure PID controller. There's some conditioning in the controller and I am trying to figure out.
Some part of following might be wrong. The control diagram:
Parametersassume the stick_input is [-1,1]:
Output = feedback + feedforward;
feedforward = stick_input*control_loop/60
feedback = pid_apply( stick_input*agility/120*150 - gyro )
P = gyro_gain/120 * 0.0008;
I = 180;
ExplainFeedforward gain: 60 in control_loop = 1.0 gain.
Agility scale: 120 in VBar Agility = 150 dps in LibrePilot (Yes this is very small, because feedforward gain is very large and here we only feed back very little portion of stick)
PI controller parameter:
P gain: seems from the gyro gain, but range is very small, like 0-8 maps to 0 to 120 in vbar
I gain: constant ~ 180
The style slider is a time delay (damping) at the PI controller output. I don't care that much so I just ignored it. It should give you the most "robotic" feel.
Paddle simulation: I haven't find any different behaviors yet.
2. VBar stick expo identification and mapping to LibrepilotFortunately VBar cyclic expo and tail expo has the same algorithm. (I can't disable the integral on cyclic makes the analysis rather difficult)
On Vbar tail, one can set to rate mode and see the servo-stick response and analyze the expo:
The LibrePilot has a quite strange expo algorithm. I think the reason is the fastexp is not accurate. Here I list down the LibrePilot expo values, dumped from a running CC3D:
Expo% | 25% | 50% | 75% |
0 | 25 | 50 | 75 |
1 | 25 | 50 | 75 |
2 | 23 | 48 | 73 |
3 | 21 | 46 | 72 |
4 | 19 | 45 | 70 |
5 | 18 | 43 | 68 |
6 | 16 | 41 | 67 |
7 | 14 | 40 | 65 |
8 | 12 | 38 | 64 |
9 | 12 | 36 | 62 |
10 | 11 | 34 | 60 |
The values are very different from a true EXP(), which makes me believe the expo value
will be different for REVO or other targets
The VBar 50% expo is like 5% to 8%. I'll use 6.
The VBar 15% expo is like 1-2%. I'll use 2.
Some implementation trash talkThe functions currently missing in the LibrePilot I identified now are:
- Stick input setpoint weighting, self-learning (corresponding to the optimizer function in Vbar)
- Feedforwards: collective to tail, collective to elevator (precompensations in Vbar)
- Stop gain (or accel gain) (pitch pump, flight style, tail stop gain)
- Speed governor, with feedforwards (expert governor)
- Auto trim
This will be a long run. So the plan is important. The study part:
- Literature study. Understand the current flybarless algorithm(s)
- Blackbox analyze the VBar stabilizer algorithm, and clone to CC3D
- Blackbox analyze the stick response algorithm
- Combined analysis(Hopefully they aren't too complected)
The implementation part:
- Tune a baseline flyable helicopter (I have a TRex 450 DFC to do this), using original LibrePilot
- Cyclic and Tail (3-axis) algorithm implement
- Governor function implement, that requires some code structure change
- Add collective to stabilization axis, that requires a lot changes. I'm not sure by now if I am able to do that.
The algorithm
For a flybarless unit, the tail system (yaw) must be a rate PID, the Head Holding is just the I gain. However for cyclic, currently I identified two complete different algorithms.
1. like normal rate PID, need to tune PID numbers. Rate tracks the stick input.
2. like the one in the source code "virtual flybar". The gyro works like a weight stabilizer. Output = Stick_input + Stabilizer_correction*(1-Stick_input) //pseudo.
I'll try to do a blackbox analysis on the Vbar first to see what is used, and I will stick to that algorithm.
By a blackbox analysis I mean put it on a platform that can have controlled rotation by a program, and record the output.
The baseline helicopter
I mounted a CC3D Atom on my Align TRex 450 DFC. The mix and the radio have been setup correctly. I'm using a futaba 8fg + aftermarket sbus receiver. Currently working on tuning the PID numbers.
The problem now is my 450 wobbles horribly in ANY PID numbers (I tried turned down the P to 5). I've already had 3 crashes by the wobble, and changed all servos. I'm will try to figure out with the help of a pwm recorder (my BlackboxCC3D recorder).
Video uploaded:
I removed the main blades and did a bench test. Seem a lot vibration from the gyro. I think I need to tune the gyro filter.
It turns out the actual problem is on the accelerometer. Under some vibration the accelerometer start to read everything completely wrong. I thought it is saturation but 16g scale still doesn't help. I tried just disable the accelerometer in attitude calculation, by reducing the Accel P and I (since we only run rate mode, plus the Vbar also only has gyroscope).
After removing the accelerometer fusion, the heli is now totally controllable. And I did a flip today! (no video).
I know I should tune those PID numbers now, but before that, I want to analyze a Vbar PID numbers.
My setup is like this:
- VbarSensor and 2 of CC3Ds are stick together. The Vbar output is the reference. One CC3D is the PID under tune. The other CC3D has my customized firmware (BlackboxCC3D). It records the gyro movements and the pwm signals.
- A servo whose arm is glued to the VbarSensor and 2 CC3Ds, so that the servo can drive the who thing in one axis.
- A arduino UNO to output 2 PWM signals. One to drive the servo, another as a receiver input to that axis, to both Vbar and the CC3D-under-tune
I used arduino the generate some standard pulse signal in order to help me analyze the algorithm used in Vbar
A video showing my bench blackbox analysis:
CH1 is the platform servo signal (Y is the same movement recorded by a gyro)
CH2 is the stick input (same axis)
CH3 is the CC3D, PID need to be tuned
CH4 is the VBar response
Vbar default settings at aileron stabilizer has a equivalent PID = [0, 0.0275, 0]Next step is to figure out the stick input to servo relationship
The CC3D response (the smooth one) to the stick is understandable. The response is the integral of the stick. However Vbar's is strange. I guess the model Vbar is using is:
output = (weight1)gyro_integral + (weight2)stick_input (Incorrect)
I'm still working it out. It seems a non-continues algorithm (if-else included).
Snapshot included, CH1 is external movement, CH2 is stick input, CH4 is Vbar output
I also believed the expo disturbed me. Tonight I'm going to disable the expo to test again.
Just learned this process is called system identification, and matlab has such automatic function provided. I'll try look into details.
I think I almost there for mimicking vbar's algorithm. Look at the bench test result: identical! CH3 is CC3D, CH4 is Vbar for reference
Pseudo algorithm
PID.iAccumulator * = decay_alpha
output = SetpointWeight * command + PIDApply( (1-SetpointWeight) * command, gyro )
decay_alpha is expf(-fakeDt/VbarTau), flybar_tau from my measurement is 2.5 (2.5 second time constant)
SetpointWeight is 0.45
(All default Vbar setting with all precompensation and expo removed)
The elevator:
has a equivalent PID = [0.005, 0.0275, 0]Sorry I made a mistake. The P=0.005 is way to high for a stable elevator, causing W-O-D.
I set to 0 and everything is just fine. The screencapture still shows the 0.005 one.
Very interesting finding. The small fluctuation from Vbar output, actually is not the P portion (I made mistake on this). But I don't know where its from for now. I'll leave it.
The gyro low pass filter on vbar has an approximate
Tau = 0.01 (LibrePilot fakeDt algorithm)
Next step I'll do the tail, which could be more difficult.
The vbar tail:
has a equivalent PID = [0.0045, 0.07, 0] (In vbar: Gain=75, P Gain=80, I Gain=60)
The description at vbar software is very very confusing. It says 100 yaw rate = 1 pirouette per sec, which is ABSOLUTELY NOT TRUE.
From my measurements, 100 yaw rate approximately equal to
1000 degree per sec, and yes, vbar has a high expo setup. Half stick in vbar has a rate of ~360. So will be
approximate 30% expo in LPMaiden test flight here!
GyroTau = 0.01
Cyclic PID = [0, 0.0275, 0], rate = 360, flybar_tau = 2.5, Setpoint_weight = 45
Tail PID = [0, 0.0275, 0], rate = 360, Setpoint_weight = 20
Second test flight.
Tail Tau fixed (I used 0 to disable decay, but didn't check, caused me to lose I completely).
Collective to Tail feedforward added.
I did some basic maneuvers: flips, inverted, tic-toc, half-piro-flip.
Watch me!The tail need more tune. I found one helpful article here:
https://www.rcgroups.com/forums/showthread.php?1538273-The-Heli-Gyro-as-a-Controller-Theory-and-ExperimentI implemented a low pass prefilter at the tail input, and I did a field test flight today. Here's the link.
Tail is much better now. I also tried the built-in pirouette compensation. It's AWESOME!! Now I don't need to do that inside OBar!
The motor is not enough powerful, the Headspeed dropped a lot at full pitch(+-12.5). I'll reduce it to (+-10.5) (stock value for this heli) and test.
I have another 450L dominator which has more powerful setup. After I fine tune everything I'll work on that one.
Detailed vbar tail parameters blackbox(identification):
- Acceleration
- Stop gain
- Low pass filter (parameter not changeable)
Please find them circled out in the recording:
After carefully thinking about the tail. I believe the vbar tail filter dsp is missed a bit, although solid.
Instead of doing Acceleration damping, stop gain overshooting, and low pass filter. I think we need to look back why these are needed. The reason is actually simple:
1. Gyro without I gain (rate gyro) is great, just no tail lock
2. Gyro with I gain has tail lock, but not good at acceleration and stop
The reason a HH gyro is not good at those, according to my understanding, is that the servo is slower than the setpoint input (user command) to PID. And such error quickly accumulate by I.
To avoid the issue. I am proposing a different filter algorithm. Basically we know there's limitation at the actuator, so we cap the command input.
1. Limited rate (the speed of the servo).
2. Limited acceleration (by the load on the tail).
3. No limited deceleration. (the servo should slow down immediately).
I will try my algorithm out later.
I need to ask my friends about this DSP stuff since I have no background at this. Meanwhile I'm working on change the architecture to incorporate the RPM input signal.
The idea was to alter the function of servo 6 output to be an input port,
and reuse some of the pwm functions to also read the pwm periodReusing servo 6 is cool, but use as pwm input might not be good. The pwm input channels are tightly coded into receiver. I think I need to make a separate module.
I tried to place it in the sensor module. Then I realized the CC3D doesn't even have sensor module enabled. This is awkward. I also try create a separate RPM module. However I think I'm not able to put another Task in CC3D. I might do some dirty coding and hope someone will replace it correctly.
The governor has another slight issue about the execution rate. The original thrust control runs a same rate as inner-loop which is 500hz. However when using a rpm sensor, each signal edge is way slower than 500Hz and most of the computing is wasted. Also a low pass filter need to incorporate with rpm signal. Because of the nature of the RPM signal, which is a set of pulse signal (is not a periodically sampled data), this can be difficult to achieve nicely.
About the stick response and expo settings. The LibrePilot has a weird fastexp algorithm I believe. I made a little expo cheat sheet sampled from the actual LibrePilot CC3D output:
Expo% 25 50 75
0 25 50 75
1 25 50 75
2 23 48 73
3 21 46 72
4 19 45 70
5 18 43 68
6 16 41 67
7 14 40 65
8 12 38 64
9 12 36 62
10 11 34 60
The Vbar 50% Expo at tail reads out: 16,37,68. Which is around 5%-8% in LibrePilot CC3D Expo
The result might be different from Revo because only CC3D uses fastexp()I think I'm pretty successful for the prototype.
Other minor improvements:
1. Cyclic Ring
2. End-of-initialization servo twitch
3. Pitch curve fix (x-axis should start from -1, instead of 0)
Finishing:
1. Parameters (UAVO) cleanup
2. UAVO for state monitoring
3. Document for Heli (Almost done)
4. Document for OBar Module
5. Sample config and easy start instruction
6. Parameter range check
To be continued...