Altitude hold agorithm
Altitude hold agorithm
Folks,
There is something about algorithm of altitude hold that does not make much sense to me. When stick is "neutral", it seems to be proper - the P term (and I term) responds to altitude error as intended. The D term cleverly implements damping using mostly inertial input. That is actually a great solution because baro signal is quite noisy and slow. Anyways, all is well, that is if baro signal is good enough and PID values are properly chosen. The actual altitude holding should work well (and it does for me).
However, consider what happens when stick calls for altitude change. The althold variable is adjusted gradually, rate of change is dependent on stick deflection. The altitude error appears after althold changed enough, causing P term to increase and, eventually, increases throttle output, etc. The response is unnecessarily sluggish, because the P term becomes significant only after althold is changed substantially. Forget about actual altitude (estimated altitude) being ever close to designated altitude (althold); there must be a substantial error for copter to change altitude. If it rise/descents long enough, the I-term will build up, which not particularly desirable either. And, D-term is actually makes response even more sluggish because it will actually counteract initial vertical acceleration.
Now, consider what happens when stick is returned to neutral. Because the at no time during ascent the estimated altitude was close to target altitude, the stick returning to neutral causes abrupt jump in target altitude ( it is forced to estimated altitude by AltHold = alt.EstAlt;). The accumulated I-term is still present (version 2.3), and the D-term is again making completely nuisance of itself by making copter to rise, the P-term builds-up in opposite direction in response, and we have an unprovoked bounce.
Nothing that I described constitutes a major problem. But, it can be easily prevented by making some simple changes to algorithm. After all, why be intentionally inferior to various Naza's and other black boxes? Here is what I propose:
Change D-term to use intended rate of ascent as input. If stick is neutral, the intended rate of ascent is exactly zero and the algorithm is exactly the same as it is right now. But if stick calls for altitude change, the stick signal (delta from neutral, actually) is exactly proportional to intended vertical velocity and that should dictate D-term. All the elements are already present in the code, including vertical velocity determination by integrating acc signal. If it is implemented correctly (and PID values are proper) the sluggish response and bouncing should be gone.
All comments including criticism are welcome.
There is something about algorithm of altitude hold that does not make much sense to me. When stick is "neutral", it seems to be proper - the P term (and I term) responds to altitude error as intended. The D term cleverly implements damping using mostly inertial input. That is actually a great solution because baro signal is quite noisy and slow. Anyways, all is well, that is if baro signal is good enough and PID values are properly chosen. The actual altitude holding should work well (and it does for me).
However, consider what happens when stick calls for altitude change. The althold variable is adjusted gradually, rate of change is dependent on stick deflection. The altitude error appears after althold changed enough, causing P term to increase and, eventually, increases throttle output, etc. The response is unnecessarily sluggish, because the P term becomes significant only after althold is changed substantially. Forget about actual altitude (estimated altitude) being ever close to designated altitude (althold); there must be a substantial error for copter to change altitude. If it rise/descents long enough, the I-term will build up, which not particularly desirable either. And, D-term is actually makes response even more sluggish because it will actually counteract initial vertical acceleration.
Now, consider what happens when stick is returned to neutral. Because the at no time during ascent the estimated altitude was close to target altitude, the stick returning to neutral causes abrupt jump in target altitude ( it is forced to estimated altitude by AltHold = alt.EstAlt;). The accumulated I-term is still present (version 2.3), and the D-term is again making completely nuisance of itself by making copter to rise, the P-term builds-up in opposite direction in response, and we have an unprovoked bounce.
Nothing that I described constitutes a major problem. But, it can be easily prevented by making some simple changes to algorithm. After all, why be intentionally inferior to various Naza's and other black boxes? Here is what I propose:
Change D-term to use intended rate of ascent as input. If stick is neutral, the intended rate of ascent is exactly zero and the algorithm is exactly the same as it is right now. But if stick calls for altitude change, the stick signal (delta from neutral, actually) is exactly proportional to intended vertical velocity and that should dictate D-term. All the elements are already present in the code, including vertical velocity determination by integrating acc signal. If it is implemented correctly (and PID values are proper) the sluggish response and bouncing should be gone.
All comments including criticism are welcome.
Re: Altitude hold agorithm
Vario-based altitude hold fucking sucks.
my 2c
my 2c
Re: Altitude hold agorithm
imho the way to go is a cascaded pid controller like the one I implemented in Baseflight: https://github.com/multiwii/baseflight/ ... imu.c#L395 feel free to do your own implementation on multiwii. Every every flight control software with working althold uses a similar approach.
Here is an example of it working with default pids: https://www.youtube.com/watch?v=A0XaMP3PCFU (not my copter)
Here is an example of it working with default pids: https://www.youtube.com/watch?v=A0XaMP3PCFU (not my copter)
Re: Altitude hold agorithm
crazyal wrote:imho the way to go is a cascaded pid controller like the one I implemented in Baseflight: https://github.com/multiwii/baseflight/ ... imu.c#L395 feel free to do your own implementation on multiwii. Every every flight control software with working althold uses a similar approach.
Here is an example of it working with default pids: https://www.youtube.com/watch?v=A0XaMP3PCFU (not my copter)
Hmm, briefly looking through the referenced code, it seems that it suffers from exactly the same flaws as stock Multiwii - unnecessarily sluggish response to stick input in althold mode. I say that because the D-term completely ignores the stick input. Or have I missed some sneaky coding?

The linked video only shows no-stick-input altitude hold. It does it well, but so does stock Multiwii with good baro and proper PID values. Personally, I get similar-to-that-video altitude holding performance with MW2.2 on Crius AIO clone board. The issue is not that. The issue is what happens when you move stick up/down in althold mode. Re-read my initial post for more detailed description.
Re: Altitude hold agorithm
As the controller controls the velocity, the stick response should definetly be better and it makes tuning easy(I never got the pids on the old althold 100% right. With the new approach it was a matter of minutes). Also it definetly behaves better when there are disturbances such as wind etc.
The rate of change mainly depends on how fast a certain throttle input changes the set altitude and on the altiude controller gain.
I guess it could be improved by adding a D-term(to have less overshoot) for the altitude controller so you can have a faster response. I still have to test this.
The rate of change mainly depends on how fast a certain throttle input changes the set altitude and on the altiude controller gain.
I guess it could be improved by adding a D-term(to have less overshoot) for the altitude controller so you can have a faster response. I still have to test this.
Re: Altitude hold agorithm
Or this - my copter: GPS Pos Hold+ACC+MAG - baseflight FW https://www.youtube.com/watch?v=GkNA_nCsTM4
Re: Altitude hold agorithm
happul3 wrote: it seems that it suffers from exactly the same flaws as stock Multiwii - unnecessarily sluggish response to stick input in althold mode. I say that because the D-term completely ignores the stick input. Or have I missed some sneaky coding?![]()
Vario-based altitude hold [censored] is not implemented in baseflight. because it is [censored] viewed as an unnecessary feature ....
source : viewtopic.php?f=8&t=4992&p=49860#p49800
-
- Posts: 244
- Joined: Sat Mar 23, 2013 12:34 am
- Location: Australia
Re: Altitude hold agorithm
Sounds like innovation. Desist!
Re: Altitude hold agorithm
Pardon my potential ignorance about the jargon, but what do you mean by "vario-based" altitude hold?
To me, (sadly former) hang glider pilot, vario means an instrument measuring vertical velocity. The actual measurement is of course not of velocity itself, but of barometric altitude, followed by differentiation. The barometric altitude measurement is the same as in a typical flight controller. Stock multiwii does differentiation of the measured baro altitude to include into D-term of PID. Is that what you mean by "vario-based altitude hold"? In other words, is your problem with D-term? Or are you using "vario" unconventionally broadly to mean the barometric altitude measurement and your problem is with barometric sensor and P-term also?
Putting terminology aside, the point I was making seems to be lost. The flaw I found has nothing to do with barometric sensor. The flaw is there regardless of whether one uses inertial (ACC) or barometric data to implement althold. Either way, the algoritm is <sensored> up. And the fix does takes literally less than a single line of code and, on paper, does not seem to have any drawbacks whatsoever. I am going to test it at the first opportunity I get and share the results.
Cheers
To me, (sadly former) hang glider pilot, vario means an instrument measuring vertical velocity. The actual measurement is of course not of velocity itself, but of barometric altitude, followed by differentiation. The barometric altitude measurement is the same as in a typical flight controller. Stock multiwii does differentiation of the measured baro altitude to include into D-term of PID. Is that what you mean by "vario-based altitude hold"? In other words, is your problem with D-term? Or are you using "vario" unconventionally broadly to mean the barometric altitude measurement and your problem is with barometric sensor and P-term also?
Putting terminology aside, the point I was making seems to be lost. The flaw I found has nothing to do with barometric sensor. The flaw is there regardless of whether one uses inertial (ACC) or barometric data to implement althold. Either way, the algoritm is <sensored> up. And the fix does takes literally less than a single line of code and, on paper, does not seem to have any drawbacks whatsoever. I am going to test it at the first opportunity I get and share the results.
Cheers
Re: Altitude hold agorithm
The problem is with implementation.
Alt hold where "hover" is on "center stick" and moving it up or down controls rate of climb/descent. This is fail.
Alt hold where "hover" is on "center stick" and moving it up or down controls rate of climb/descent. This is fail.
Re: Altitude hold agorithm
timecop wrote:The problem is with implementation.
Alt hold where "hover" is on "center stick" and moving it up or down controls rate of climb/descent. This is fail.
Ok, so you do not like the basic premise of alt hold. You are certainly entitled to dislike whatever you like (pun intended). I'd be certainly curious to hear what you think is a viable alternative for doing altitude control. Please describe what would you like throttle stick to control in altitude hold mode.
HOWEVER, that has little to do with the subject I brought up. To put it simply, I was pointing out the alt hold algorithm has specific flaw and proposing how to fix it, cleanly and completely. I do not agree with you that the algorithm is a "fail". It works for me as it is, it should work even better once I add the intended fix. Hence, at the moment, I have no interest in changing basic idea of altitude hold control by moving throttle stick up or down to control rate of climb/descent
Altitude hold agorithm
Can you show a code diff with your fix so people can try it out?
Re: Altitude hold agorithm
koenkooi wrote:Can you show a code diff with your fix so people can try it out?
Good idea, it will make easier to analyze and test if it works.
Re: Altitude hold agorithm
Don't use this myself, but curious what the normal implementation is here also.
"hoverband" around neutral - maybe +/- 25% stick and then change desired target altitude outside ? Proportional to stick deviation?
"hoverband" around neutral - maybe +/- 25% stick and then change desired target altitude outside ? Proportional to stick deviation?
timecop wrote:The problem is with implementation.
Alt hold where "hover" is on "center stick" and moving it up or down controls rate of climb/descent. This is fail.
Re: Altitude hold agorithm
I was not able to test "the fix" yet, but I suppose there is nothing wrong with sharing something untested if there is interest. Please go ahead and check it out, carefully, that is.
in MW2.3, IMU.cpp replace
BaroPID -= constrain(conf.pid[PIDALT].D8 * alt.vario >>4, -150, 150);
with
BaroPID -= constrain(conf.pid[PIDALT].D8 * (alt.vario - (rcCommand[THROTTLE]-initialThrottleHold)/2 )>>4, -150, 150);
That's all there is to it in its simplest form. With this change, althold will behave exactly the same as before when stick is "neutral", but when stick calls for altitude change, the D-term should provide faster initial response.
It is probably a good idea to make a little more extensive changes to utilize stick deadband. Something along this lines:
in multiwii.cpp
static int16_t dterm_temp = 0;
dterm_temp=0;
if (abs(rcCommand[THROTTLE]-initialThrottleHold)>ALT_HOLD_THROTTLE_NEUTRAL_ZONE) {
// Slowly increase/decrease AltHold proportional to stick movement ( +100 throttle gives ~ +50 cm in 1 second with cycle time about 3-4ms)
AltHoldCorr+= dterm_temp = rcCommand[THROTTLE] - initialThrottleHold;
in IMU.cpp
BaroPID -= constrain(conf.pid[PIDALT].D8 * (alt.vario - dterm_temp/2 )>>4, -150, 150);
in MW2.3, IMU.cpp replace
BaroPID -= constrain(conf.pid[PIDALT].D8 * alt.vario >>4, -150, 150);
with
BaroPID -= constrain(conf.pid[PIDALT].D8 * (alt.vario - (rcCommand[THROTTLE]-initialThrottleHold)/2 )>>4, -150, 150);
That's all there is to it in its simplest form. With this change, althold will behave exactly the same as before when stick is "neutral", but when stick calls for altitude change, the D-term should provide faster initial response.
It is probably a good idea to make a little more extensive changes to utilize stick deadband. Something along this lines:
in multiwii.cpp
static int16_t dterm_temp = 0;
dterm_temp=0;
if (abs(rcCommand[THROTTLE]-initialThrottleHold)>ALT_HOLD_THROTTLE_NEUTRAL_ZONE) {
// Slowly increase/decrease AltHold proportional to stick movement ( +100 throttle gives ~ +50 cm in 1 second with cycle time about 3-4ms)
AltHoldCorr+= dterm_temp = rcCommand[THROTTLE] - initialThrottleHold;
in IMU.cpp
BaroPID -= constrain(conf.pid[PIDALT].D8 * (alt.vario - dterm_temp/2 )>>4, -150, 150);
Re: Altitude hold agorithm
As branch: https://github.com/koenkooi/multiwii-fi ... e-hold-pid
As patch: https://github.com/koenkooi/multiwii-fi ... ef56.patch
I haven't tried to compile it yet, so it might not work as expected.
As patch: https://github.com/koenkooi/multiwii-fi ... ef56.patch
I haven't tried to compile it yet, so it might not work as expected.
Re: Altitude hold agorithm
And it doesn't compile because rcCommand isn't visible from inside the PID loop scope. I suspect the second version will have a similar problem with dterm_temp.
Re: Altitude hold agorithm
koenkooi wrote:And it doesn't compile because rcCommand isn't visible from inside the PID loop scope. I suspect the second version will have a similar problem with dterm_temp.
As I mentioned, I have not tested the code, so it is no big surprise that it does not compile. But it is easy enough to make it compile. It is actually not rcCommand that is not visible, it is initialThrottleHold. So few more changes are needed:
in multiwii.h add line
extern int16_t initialThrottleHold;
in multiwii.cpp move line
int16_t initialThrottleHold;
outside of loop (for example, right after int16_t errorAltitudeI = 0;)
Re: Altitude hold agorithm
Finally, I got to test the proposed change in altitude hold code. The logic behind the fix seemed flawless, but I was half-expecting that there is something I missed and the test would reveal that.
Well, imaging my joy when the improved code worked exactly as intended on the first try. It produced clear and obvious improvement in responsiveness of altitude change. As you can see from attached pictures, the lag between the time when the stick input is given and the time quad actually starts going up is reduced dramatically, from 2-3 sec -very sluggish response - to basically 0. Note that in my case, the stick input is 4X larger than it would be if you were to use stock 2.2 or 2.3 (2000 instead of 500 or 512: if(abs(AltHoldCorr) > 2000) { AltHold += AltHoldCorr/2000; AltHoldCorr %= 2000; and the fix is scaled respectively, divide-by-8 instead of divide-by-2: (rcCommand[THROTTLE]-initialThrottleHold)/8 ).
I played with my quad a bit, making it go up and down fast and slow, while moving and while hovering. I did not see any ill effects.
Some cautionary notes: I do want to stress that in order for this improvement to be effective, you need to have already well-tuned PID of altitude hold. If your multicopter does not hold altitude well with no stick input in altitude hold mode, my fix is not going to help with that. And if what you consider tuned PID has negligible or zero D value, my fix will have negligible effect too. Finally, note that I fly heavily modified MW 2.2 version. It has some useful additions such as dynamic PID adjustments by AUX channels, motor/prop balancing with real-time computation of vib frequencies and amplitudes, GPS-homing failsafe etc. Transferring all those goodies to 2.3 is something I just can't bring myself to do. So, the bottom line is I have tested the subject matter fix on modified 2.2 only. I do not think it will work any differently on stock 2.3, but I can't guarantee that.
Well, imaging my joy when the improved code worked exactly as intended on the first try. It produced clear and obvious improvement in responsiveness of altitude change. As you can see from attached pictures, the lag between the time when the stick input is given and the time quad actually starts going up is reduced dramatically, from 2-3 sec -very sluggish response - to basically 0. Note that in my case, the stick input is 4X larger than it would be if you were to use stock 2.2 or 2.3 (2000 instead of 500 or 512: if(abs(AltHoldCorr) > 2000) { AltHold += AltHoldCorr/2000; AltHoldCorr %= 2000; and the fix is scaled respectively, divide-by-8 instead of divide-by-2: (rcCommand[THROTTLE]-initialThrottleHold)/8 ).
I played with my quad a bit, making it go up and down fast and slow, while moving and while hovering. I did not see any ill effects.
Some cautionary notes: I do want to stress that in order for this improvement to be effective, you need to have already well-tuned PID of altitude hold. If your multicopter does not hold altitude well with no stick input in altitude hold mode, my fix is not going to help with that. And if what you consider tuned PID has negligible or zero D value, my fix will have negligible effect too. Finally, note that I fly heavily modified MW 2.2 version. It has some useful additions such as dynamic PID adjustments by AUX channels, motor/prop balancing with real-time computation of vib frequencies and amplitudes, GPS-homing failsafe etc. Transferring all those goodies to 2.3 is something I just can't bring myself to do. So, the bottom line is I have tested the subject matter fix on modified 2.2 only. I do not think it will work any differently on stock 2.3, but I can't guarantee that.
Re: Altitude hold agorithm
Hi,
Good to know that your tests were successful. I hope Alex is looking at this thread and apply the solution in the development branch. Anybody else had the opportunity to test this code change?
Regards,
Luis Sismeiro
Good to know that your tests were successful. I hope Alex is looking at this thread and apply the solution in the development branch. Anybody else had the opportunity to test this code change?
Regards,
Luis Sismeiro
Re: Altitude hold agorithm
happul3 wrote:Finally, I got to test the proposed change in altitude hold code. The logic behind the fix seemed flawless, but I was half-expecting that there is something I missed and the test would reveal that.
Well, imaging my joy when the improved code worked exactly as intended on the first try. It produced clear and obvious improvement in responsiveness of altitude change. As you can see from attached pictures, the lag between the time when the stick input is given and the time quad actually starts going up is reduced dramatically, from 2-3 sec -very sluggish response - to basically 0. Note that in my case, the stick input is 4X larger than it would be if you were to use stock 2.2 or 2.3 (2000 instead of 500 or 512: if(abs(AltHoldCorr) > 2000) { AltHold += AltHoldCorr/2000; AltHoldCorr %= 2000; and the fix is scaled respectively, divide-by-8 instead of divide-by-2: (rcCommand[THROTTLE]-initialThrottleHold)/8 ).
I played with my quad a bit, making it go up and down fast and slow, while moving and while hovering. I did not see any ill effects.
Some cautionary notes: I do want to stress that in order for this improvement to be effective, you need to have already well-tuned PID of altitude hold. If your multicopter does not hold altitude well with no stick input in altitude hold mode, my fix is not going to help with that. And if what you consider tuned PID has negligible or zero D value, my fix will have negligible effect too. Finally, note that I fly heavily modified MW 2.2 version. It has some useful additions such as dynamic PID adjustments by AUX channels, motor/prop balancing with real-time computation of vib frequencies and amplitudes, GPS-homing failsafe etc. Transferring all those goodies to 2.3 is something I just can't bring myself to do. So, the bottom line is I have tested the subject matter fix on modified 2.2 only. I do not think it will work any differently on stock 2.3, but I can't guarantee that.
looks good, you could improve the response with ignoring the d-term for a few baro measurement cycles.
set the counter for example to 10 when you detect a different altitude hold settings.
when the counter is active, aka > 0, then ignore the d-term in the pid calculations.
Re: Altitude hold agorithm
timecop wrote:Vario-based altitude hold fucking sucks.
my 2c
using python i would suggest to use the keyword self.
http://stackoverflow.com/questions/2709821/python-self-explained
you could write self.fuck
Re: Altitude hold agorithm
brm wrote:
looks good, you could improve the response with ignoring the d-term for a few baro measurement cycles.
set the counter for example to 10 when you detect a different altitude hold settings.
when the counter is active, aka > 0, then ignore the d-term in the pid calculations.
Thanks. I agree, the response would indeed improve by ignoring d-term like you suggest. However, the improvement would not be much because the stock version is lagging primarily due to (1) baro signal being inherently slow (averaging and LPF contributes to that) and (2) it takes time to build-up significant change in target altitude to increase p-term. The d-term just compounds the problem in stock version.
Also, note that the solution I've proposed is not only more effective in improving response, it is also much simpler - it is less than one line of code (ignoring the change to make variable visible).
-
- Posts: 1630
- Joined: Wed Jan 19, 2011 9:07 pm
Re: Altitude hold agorithm
sismeiro wrote:Hi,
Good to know that your tests were successful. I hope Alex is looking at this thread and apply the solution in the development branch. Anybody else had the opportunity to test this code change?
Hi,
Don't worry I'm still here and read almost all the posts

If validated by 2 or 3 users, for sure I will add it.
I like the simplicity of the approach
Re: Altitude hold agorithm
brm wrote:timecop wrote:Vario-based altitude hold fucking sucks.
my 2c
using python i would suggest to use the keyword self.
http://stackoverflow.com/questions/2709821/python-self-explained
you could write self.fuck
I dislike python as much as I dislike vario althold, so I'm not sure what you're getting at here.
- Crashpilot1000
- Posts: 631
- Joined: Tue Apr 03, 2012 7:38 pm
Re: Altitude hold agorithm
Thank you very much happul3 for wrapping your head around that subject!
Concerning the "I" part you can diminish it (with a lower limit like 50%) according to the highterror during "vario" hightchange. I currently just do it during Autostartsequence to get quicker off the ground but tried it for normal highchange operation seems a little better. Note: I wouldn't turn down the "I" on reducing hight ("negative vario"). Concerning *somehow* "snappiness" of logging in the new targethight after a vario hight change you will have to project the stopping point (that includes the baro + filtering lag) just try it - you will see thats very nice.
Cheers Rob
Concerning the "I" part you can diminish it (with a lower limit like 50%) according to the highterror during "vario" hightchange. I currently just do it during Autostartsequence to get quicker off the ground but tried it for normal highchange operation seems a little better. Note: I wouldn't turn down the "I" on reducing hight ("negative vario"). Concerning *somehow* "snappiness" of logging in the new targethight after a vario hight change you will have to project the stopping point (that includes the baro + filtering lag) just try it - you will see thats very nice.
Cheers Rob
Re: Altitude hold agorithm
Crashpilot1000 wrote:Thank you very much happul3 for wrapping your head around that subject!
Concerning the "I" part you can diminish it (with a lower limit like 50%) according to the highterror during "vario" hightchange. I currently just do it during Autostartsequence to get quicker off the ground but tried it for normal highchange operation seems a little better. Note: I wouldn't turn down the "I" on reducing hight ("negative vario"). Concerning *somehow* "snappiness" of logging in the new targethight after a vario hight change you will have to project the stopping point (that includes the baro + filtering lag) just try it - you will see thats very nice.
Cheers Rob
Rob, can you please explain what do you mean by "Autostartsequence"? Also, it is not clear to me why you are bringing up the I-term. Its main purpose is to compensate for the slowest changes, for example, battery discharge. If you are relying on it for the relatively fast events such as altitude change it might be helpful to retune althold PID values.
Perhaps it would be useful to share althold performance records. Not knowing how it supposed to perform when done correctly may result in frustration and, possibly, even giving up on a useful feature. I have a proposal directed at everyone interested: Unless you have nice and steady althold performance (something like the gentleman who mentioned baseflight showed in his video) post time log of P-term, I-term, D-term, baro altitude, and rcData[THROTTLE] of multicopter when it is in althold mode. You can acquire the logs with wingui, assuming you have bluetooth hardware on your multicopter. Use 20 Hz sampling - should be fast enough for the task. The p-,i-,d-terms are not directly available I think, but it is completely trivial to modify the code to copy them into debug[0]-debug[2], which are visible and capturable in wingui. If you have a problem with changing code see below three modified lines to make it happen.
I'll post some of representative logs for reference when I get to my "multwii" computer at home. You can compare with what you get or just post yours and ask for suggestions on how to improve PID values from everyone reading this thread.
replace three respective line in 2.3 code with the ones below
BaroPID = debug[0] = constrain((conf.pid[PIDALT].P8 * error16 >>7), -150, +150);
BaroPID += debug[1] = errorAltitudeI>>9; //I in range +/-60
BaroPID += debug[2] = -constrain(conf.pid[PIDALT].D8 * alt.vario >>4, -150, 150);
Re: Altitude hold agorithm
As promised, examples of althold pid values effects. Hopefully the attached images will help someone
- Crashpilot1000
- Posts: 631
- Joined: Tue Apr 03, 2012 7:38 pm
Re: Altitude hold agorithm
Hi happul3!
Sorry for my mistake. I am so much into the terminology of my own stuff that I mixed it up. In my former post the "I" should have been a "D". I use the gui delivered "D" term just for anglecorrection so it is a PD controller. I omitted the errorintegration over time "I" because I found that it just adds a parameter to tune with too limited real life effect (edit: I've seen more swinging trouble with a real "I"). But no reason not to revisit that subject again..
Concerning Autostart there was much fiddeling around involved because you want to get fast of the ground and then climb to the target hight with not too much overshoot. I ended up with an Autostart in 3 stages:
1: Initialization: Do checks if Autostart is allowed and possible (not possible: like copter is already flying). Zero out current Altitude and initialize the targethight. User may has defined a no-fly-throttle if so use that otherwise assume standbythrottle + 5% pwmrange. (Note: no-fly-throttle is round about the throttle where the copter gets light but barely doesn't fly, it is used for some failsafe / generated in flight hoverthrottle plausibility checks and abused here to shorten the time on the ground)
2: Lift off: Now use a virtual targethight (not related to the real targethight) and increase it rapidly (configureable) to make the copter lift off. It is something like a "rubberband". Detecting the liftoff in the rubberbandphase actually happens by checking the variometer and that wasn't easy I ended up with 2 checks on stronger filtered vario values: If vario exceeds 50cm/s or the std. deviation of vario exceeds 10.
3: Proceed to targethight: Once the lift off is assumed I do a short "Althold". This resets the rubberband proceeding and prevents becoming a rocket. The targethight is approached with a predefined speed that will diminish when reaching the targethight by a factor of 3 though leaving headroom for a necessary minimal climbrate. It will also work without decelleration on approaching the targethight but overshoot and that doesn't look nice...
When the targethight is reached/surpassed althold is engaged with the currenty measured hight (not the targethight, but they are of course roughly the same).
- EDIT: So basically the algo does what you would do yourself when starting a copter - give a good amount of thrust to get off the ground and then reduce the thrust once in the air and climb to a desired hight.
- Hardwarenote: Sonar can help but is not needed (the same goes for Autolanding). Tested with MS5611 and BMP085 Baro (with pimped driver).
Limits of this procedure:
- It will work reliably with 2m targethight and beyond that. 1m targethight is also possible but you may end up then with something like 50cm or the correct 1m. Therefor indoor usage is not so recommended for reliable operation unless you have high ceilings.
During the testing I had some datamonitoring but you wouldn't want to see that ... a usb cable in the copter center and manually lifting off monitoring the alt/vario parameters. Meanwhile I have a Blutooth usb dongle but attached to a different project. Sorry, but I will not be able to provide you with your requested data right now.
Cheers Rob
BTW: I love vario althold steering, maybe I should try python as well..
Sorry for my mistake. I am so much into the terminology of my own stuff that I mixed it up. In my former post the "I" should have been a "D". I use the gui delivered "D" term just for anglecorrection so it is a PD controller. I omitted the errorintegration over time "I" because I found that it just adds a parameter to tune with too limited real life effect (edit: I've seen more swinging trouble with a real "I"). But no reason not to revisit that subject again..
Concerning Autostart there was much fiddeling around involved because you want to get fast of the ground and then climb to the target hight with not too much overshoot. I ended up with an Autostart in 3 stages:
1: Initialization: Do checks if Autostart is allowed and possible (not possible: like copter is already flying). Zero out current Altitude and initialize the targethight. User may has defined a no-fly-throttle if so use that otherwise assume standbythrottle + 5% pwmrange. (Note: no-fly-throttle is round about the throttle where the copter gets light but barely doesn't fly, it is used for some failsafe / generated in flight hoverthrottle plausibility checks and abused here to shorten the time on the ground)
2: Lift off: Now use a virtual targethight (not related to the real targethight) and increase it rapidly (configureable) to make the copter lift off. It is something like a "rubberband". Detecting the liftoff in the rubberbandphase actually happens by checking the variometer and that wasn't easy I ended up with 2 checks on stronger filtered vario values: If vario exceeds 50cm/s or the std. deviation of vario exceeds 10.
3: Proceed to targethight: Once the lift off is assumed I do a short "Althold". This resets the rubberband proceeding and prevents becoming a rocket. The targethight is approached with a predefined speed that will diminish when reaching the targethight by a factor of 3 though leaving headroom for a necessary minimal climbrate. It will also work without decelleration on approaching the targethight but overshoot and that doesn't look nice...
When the targethight is reached/surpassed althold is engaged with the currenty measured hight (not the targethight, but they are of course roughly the same).
- EDIT: So basically the algo does what you would do yourself when starting a copter - give a good amount of thrust to get off the ground and then reduce the thrust once in the air and climb to a desired hight.
- Hardwarenote: Sonar can help but is not needed (the same goes for Autolanding). Tested with MS5611 and BMP085 Baro (with pimped driver).
Limits of this procedure:
- It will work reliably with 2m targethight and beyond that. 1m targethight is also possible but you may end up then with something like 50cm or the correct 1m. Therefor indoor usage is not so recommended for reliable operation unless you have high ceilings.
During the testing I had some datamonitoring but you wouldn't want to see that ... a usb cable in the copter center and manually lifting off monitoring the alt/vario parameters. Meanwhile I have a Blutooth usb dongle but attached to a different project. Sorry, but I will not be able to provide you with your requested data right now.
Cheers Rob
BTW: I love vario althold steering, maybe I should try python as well..
Re: Altitude hold agorithm
Crashpilot1000 wrote:Hi happul3!
Sorry for my mistake. I am so much into the terminology of my own stuff that I mixed it up. In my former post the "I" should have been a "D". I use the gui delivered "D" term just for anglecorrection so it is a PD controller. I omitted the errorintegration over time "I" because I found that it just adds a parameter to tune with too limited real life effect (edit: I've seen more swinging trouble with a real "I"). But no reason not to revisit that subject again..
Concerning Autostart there was much fiddeling around involved because you want to get fast of the ground and then climb to the target hight with not too much overshoot. I ended up with an Autostart in 3 stages:
1: Initialization: Do checks if Autostart is allowed and possible (not possible: like copter is already flying). Zero out current Altitude and initialize the targethight. User may has defined a no-fly-throttle if so use that otherwise assume standbythrottle + 5% pwmrange. (Note: no-fly-throttle is round about the throttle where the copter gets light but barely doesn't fly, it is used for some failsafe / generated in flight hoverthrottle plausibility checks and abused here to shorten the time on the ground)
2: Lift off: Now use a virtual targethight (not related to the real targethight) and increase it rapidly (configureable) to make the copter lift off. It is something like a "rubberband". Detecting the liftoff in the rubberbandphase actually happens by checking the variometer and that wasn't easy I ended up with 2 checks on stronger filtered vario values: If vario exceeds 50cm/s or the std. deviation of vario exceeds 10.
3: Proceed to targethight: Once the lift off is assumed I do a short "Althold". This resets the rubberband proceeding and prevents becoming a rocket. The targethight is approached with a predefined speed that will diminish when reaching the targethight by a factor of 3 though leaving headroom for a necessary minimal climbrate. It will also work without decelleration on approaching the targethight but overshoot and that doesn't look nice...
When the targethight is reached/surpassed althold is engaged with the currenty measured hight (not the targethight, but they are of course roughly the same).
- EDIT: So basically the algo does what you would do yourself when starting a copter - give a good amount of thrust to get off the ground and then reduce the thrust once in the air and climb to a desired hight.
- Hardwarenote: Sonar can help but is not needed (the same goes for Autolanding). Tested with MS5611 and BMP085 Baro (with pimped driver).
Limits of this procedure:
- It will work reliably with 2m targethight and beyond that. 1m targethight is also possible but you may end up then with something like 50cm or the correct 1m. Therefor indoor usage is not so recommended for reliable operation unless you have high ceilings.
During the testing I had some datamonitoring but you wouldn't want to see that ... a usb cable in the copter center and manually lifting off monitoring the alt/vario parameters. Meanwhile I have a Blutooth usb dongle but attached to a different project. Sorry, but I will not be able to provide you with your requested data right now.
Cheers Rob
BTW: I love vario althold steering, maybe I should try python as well..
Thanks for the details, Rob. I am curious: have you released your autostart code for pubic testing/use? I am actually thinking of implementing something along these lines, but if it is already done there is no need to re-invent the bicycle. I am a bit concerned though with what you wrote - it sounds like you are relying on baro signal to detect and control ascent. I think that such approach would be undesirably sensitive to multicopter configuration because props may create a lot of pressure gradient when close on the ground or flying in what's called ground effect. Using accelerometer to control take-off seem like a more general and robust approach. What do you think?
- Crashpilot1000
- Posts: 631
- Joined: Tue Apr 03, 2012 7:38 pm
Re: Altitude hold agorithm
Hi, happul3 !
Well I consider those things as *done* and solidly working - that doesn't mean there is no room for improvement or different ideas / approaches to that subject. The altitude and vario values are already fusioned with acc values and with sonar values, if available. The groundeffect baromisreadings are a real problem and greatly affected by motor to motor distance and propsize, or simply the aircussion the baro sits in and measures a pile of errors. After my post I rechecked my code and actually found a logical error (std dev and vario>50 check) that is fixed now - but it worked well even with that error, so probably it is possible to strip down the check to work without std. dev. but I will leave it that way for now.
I know you didn't ask for it, but the groundeffect - aircushion is most pain during autolanding because it will lead to bunnyhopping. Without mounting the baro above the groundeffect, I fiddeled around and found a way to reduce/eliminate that. Before Autolanding the copter will hover 2sec and gather a fresh hoverthrottle. The maximal throttle during descent and landing is basically limited to that throttle but that will make the copter come down more or less as a rock because the copter needs to give more thrust during descent to brake than the hoverthrottle - so the solution was to define a percentage of wich the hoverthrottle can be exceeded to brake enough but to block hopping on the ground (high pressure = low alt = regulation wants to throttle up to compensate an obviously (eye of the observer) false hightdrop) my copters are happy with a 5% margin (cfg.al_debounce = 0-20%). Sonar ground detection is also implemented and can help but there are some catches with those devices.
On faster descents in althold and stopping it by putting the throttlestick in the middle again the copter will want to brake with full throttle. I've seen yaw movements in those situations because the highthrottle handling in the mixer can be improved - alternatively the althold controller could be reduced to not use the full throttle range - that's a matter of taste I think. I left my althold controller at full authority because the mixer should be able to handle that - that's why there are also changes in the mixer part.
My repo that is basically a zipfiledump is here https://github.com/Crashpilot1000?tab=repositories. I know it's a mess and it doesn't contain the latest changes in mixer and althold. I will PM you my email so I can give you the actual zip, it is not uploaded because the GPS part is undergoing some changes and will not work in its current state. I am no programmer but the althold stuff is as clean as I could do it.
Looking forward to your project!
Cheers Rob
Well I consider those things as *done* and solidly working - that doesn't mean there is no room for improvement or different ideas / approaches to that subject. The altitude and vario values are already fusioned with acc values and with sonar values, if available. The groundeffect baromisreadings are a real problem and greatly affected by motor to motor distance and propsize, or simply the aircussion the baro sits in and measures a pile of errors. After my post I rechecked my code and actually found a logical error (std dev and vario>50 check) that is fixed now - but it worked well even with that error, so probably it is possible to strip down the check to work without std. dev. but I will leave it that way for now.
I know you didn't ask for it, but the groundeffect - aircushion is most pain during autolanding because it will lead to bunnyhopping. Without mounting the baro above the groundeffect, I fiddeled around and found a way to reduce/eliminate that. Before Autolanding the copter will hover 2sec and gather a fresh hoverthrottle. The maximal throttle during descent and landing is basically limited to that throttle but that will make the copter come down more or less as a rock because the copter needs to give more thrust during descent to brake than the hoverthrottle - so the solution was to define a percentage of wich the hoverthrottle can be exceeded to brake enough but to block hopping on the ground (high pressure = low alt = regulation wants to throttle up to compensate an obviously (eye of the observer) false hightdrop) my copters are happy with a 5% margin (cfg.al_debounce = 0-20%). Sonar ground detection is also implemented and can help but there are some catches with those devices.
On faster descents in althold and stopping it by putting the throttlestick in the middle again the copter will want to brake with full throttle. I've seen yaw movements in those situations because the highthrottle handling in the mixer can be improved - alternatively the althold controller could be reduced to not use the full throttle range - that's a matter of taste I think. I left my althold controller at full authority because the mixer should be able to handle that - that's why there are also changes in the mixer part.
My repo that is basically a zipfiledump is here https://github.com/Crashpilot1000?tab=repositories. I know it's a mess and it doesn't contain the latest changes in mixer and althold. I will PM you my email so I can give you the actual zip, it is not uploaded because the GPS part is undergoing some changes and will not work in its current state. I am no programmer but the althold stuff is as clean as I could do it.
Looking forward to your project!
Cheers Rob