iNavFlight / inav

INAV: Navigation-enabled flight control software
https://inavflight.github.io
GNU General Public License v3.0
3.06k stars 1.45k forks source link

Discussion - Acro flight performance enhancements #218

Closed theArchLadder closed 7 years ago

theArchLadder commented 8 years ago

I just tried betaflight, wow! Very impressive, so locked in compared to fp-pid. It felt like i became a twice as good pilot!

Could we get this performance in inav? Why having to compromise between nav and acro performance! :stuck_out_tongue_winking_eye: The default looptime on betaflight is 500 and even i could notice a difference when switching to 1000 like i have on inav. 500 made it feel a little bit more sharp. Would it be possible to get inav to run at 500 on F3 targets?

But the most important difference is that the attitude was so locked in! Perhaps i'm a terrible tuner but no matter what i do i can't get the attitude to be locked in on fp-pid, and to high I-gains starts to ruin the performance... Is there to much anti-windup or what is going on here? Attitude on betaflight was very locked in even on 1000 looptime. Fp-pid changes the attitude all the time without me telling it to, that makes acro flying very hard.

As usual i'm more than happy to make my custom builds and flight test them, just give me some ideas on what to try! What else could we borrow from betaflight to improve acro flight?

DzikuVx commented 8 years ago

If you want to have much better performance for acro:

theArchLadder commented 8 years ago

@DzikuVx Thanks! :smile: I will do a test flight tomorrow!

My biggest problem is the changing attitude though. For example when i go fast from side-to-side using only roll, pitch and yaw will change attitude, but this does not really happen in betaflight. It would be interesting to hear what you, or @digitalentity think the reason is for the unstable attitude and what can be done about it...?

It would also be helpful if i could convert the defaults of betaflight mwrewrite into fp-pid, does anyone know how that can be calculated?

DzikuVx commented 8 years ago

For attitude.... More I? I have around 60 on roll and 90 on pitch.

DzikuVx commented 8 years ago

42hz for gyro is noise proof but barely flyable. 98 is compromise. 188 is afair what betaflight uses. And what are your P?

theArchLadder commented 8 years ago

gyro_lpf = 98HZ set p_roll = 35 set i_roll = 80 set d_roll = 80

My P was 50 when my quad was 150g heavier. AUW now is 500g, with 6 inch props and 4s battery. I did try I at 100 but i started getting bounce-back and it just didn't feel right.

I plan to try cleanflight tomorrow to see how that feels...

digitalentity commented 8 years ago

Lower looptimes tend to tolerate vibrations better. You might want to adjust your filtering settings on D and gyro.

Blackbox logs will help debug. Possibly too low P and too high D, hard to guess.

We can't have looptime faster than 1000 at the moment - requires changes to scheduler code and decoupling of gyro, accelerometer reads, PID controller and motor updates.

Will work in that direction after configuration refactoring PR is merged.

digitalentity commented 8 years ago

Can you post compete dump here?

theArchLadder commented 8 years ago

This blackbox log should be decent, i was flying fast side-to-side using only roll, that's when i had the issues with the attitude wandering about. https://www.dropbox.com/s/4yog9m5wd8mht51/blackbox_log_2016-05-17_163714_pedestrian-limit-test?dl=0

Dump: https://www.dropbox.com/s/bk9fovvj8n7gd6t/2016-05-16_x3_theladder?dl=0

Is it possible to convert between fp-pids and the pids of mwrewrite or luxfloat? That way i can compare with the same pid-tuning.

theArchLadder commented 8 years ago

I just tried cleanflight 12.0, and it also felt very good, the main difference is that the attitude doesn't drift. When doing quick roll manuvers, pitch and yaw stays the same. When doing yaw pirouttes, pitch/roll stays the same, this is not my experince with inav...

I need to try inav again now and see how big the difference really is, and do some more tuning, but something feels wrong here, cleanflight with default settings should not be better than inav for acro, right?

Ralf-W commented 8 years ago

@theArchLadder Just some observations in your BB log. At the end of a roll command - roll (and pitch) stick are centered - we see the roll gyro and the rolling copter overshooting several times with reducing amplitude. Some gain is too high. Before the roll you made the copter climb with throttle. Then throttle is reduced to get a roll with low hight loss. However, throttle gets so low, that two motors are more or less stopping during the roll. Looking at the 4 motor graphs, the rpm are not controlled symetrically. Two curves have a sharp Peak. The lower ones get cut in a plateau and cannot be reduced as far as the other two are incresed. roll_1 Although there is no rc command, pitch and yaw come alive due to the asymmetrical rpm changes of the 4 motors. roll_2

In a roll with high throttle setting, two motor rpm are maxed out. This results in an oscillation in the pitch and even in the yaw directions (yellow gyro curve is yaw, turquise gyro curve is pitch). roll_high_throttle

theArchLadder commented 8 years ago

@Ralf-W Thanks! Do you have any idea what's wrong with my pids? To me it looks like i-gain might be to high but i'm not that good at pid tuning

My blackbox denom is way to high in that log, problem is though, if i have it at 1-2 my black box fills up super quick... I guess i can do som super short flights and look at the blackbox.

Ralf-W commented 8 years ago

@theArchLadder I updated my comment. Please have a second look at it.

I am still no expert in tuning, but I would start reducing the I-gain, too. And even the D-gain can be set to Zero, just to make analysis easier.

theArchLadder commented 8 years ago

@Ralf-W Oh wow, thank you very much for that detailed analysis!

I think i figured out how to change the pid scaling to match betaflight. I will try betaflight defaults and see what happens...

theArchLadder commented 8 years ago

Hmm, tried some more betaflight and this time tuned only p so that it barely had any oscillations, default p=45 and i ended up with p=20, and it actually seemed to fly well so perhaps i have been using way to high pids... I guess it makes sense since my quad is lighter than the average fpv racer, and has 6 inch props.

Still not sure why both cleanflight and betaflight seems to hold attitude better than inav during agressive acro flying, when i use stock pids on all of them...

EDIT: Did some tuning with inav, feels different from betaflight while tuning, oscillations are slower and i find it harder to tune to fly well. Time to play with some lowpass filters i guess

EDIT2: Used these settings gyro_lpf = 188HZ gyro_soft_lpf_hz = 100 dterm_lpf_hz = 100 I did not notice any improvement. On betaflight i use 50 for both gyro_soft and dterm, i guess betaflight does not use the gyro hardware filter anymore...

EDIT3: same 1000 looptime was used on all tests. I wish inav still had luxfloat so i could compare...

theArchLadder commented 8 years ago

Ugh, it's a nightmare debugging this. Both cleanflight and betaflight flies good on defaults, but inav is unstable just looking at the quad during a hover, and has problem keeping attitude etc... And i have not manage to tune it to behave good

It would really help to have the same pid scaling. Both luxfloat and mwrewrite has the same scaling in both betaflight and cleanflight, so it would be helpful if inav used the same scaling.

I tried to use this: https://github.com/cleanflight/cleanflight/blob/52612ebb3a9ae4668a021a51c75de1c726977e1a/src/main/flight/pid_luxfloat.c#L70 In inav, and ended up replacing these:

#define FP_PID_RATE_P_MULTIPLIER  31.219513f    // inav 40.0f    // betaflight - 40.0
#define FP_PID_RATE_I_MULTIPLIER  4.092004f     // inav 10.0f    // betaflight - 10.0
#define FP_PID_RATE_D_MULTIPLIER  1890.629883f  // inav 4000.0f  // betaflight - 1000.0

Those betaflight comments are already in inav, but i think those are from before betaflight changed luxfloat scaling to match mwrewrite. I tried these scalings with cleanflight default pids, but i got lots of oscillations that i did not have in cleanflight, so perhaps i did something wrong. I think i need @digitalentity to help me get this scaling right...

Oh, i also tried to completely disable anti-windup but that didn't improve things, nothing wrong with those it seems, good :+1:

oleost commented 8 years ago

@theArchLadder Try this: https://docs.google.com/spreadsheets/d/1mX0a6yytARsZiaU6sCGKvpwXSBYjTjTwVJZiJmktKqg/edit?usp=sharing

This is atleast what DigitalEntity told me to convert from old luxfloat to new FP PID

EDIT: Use values from CLI

oleost commented 8 years ago

@theArchLadder And remember use values from CLI.

theArchLadder commented 8 years ago

@oleost Thanks... Are those luxfloat values the old defaults? In that case this seems obsolete, fp-pid p-gain of 200 is very high compared to default 30...

oleost commented 8 years ago

No, those are my PIDs that I had on my fixed wing. So yes, they are very high and unusable on MR

oleost commented 8 years ago

@theArchLadder So you got it to fly better?

Still looks like people are having more issues with iNav and default values than with cleanflight and betaflight.

DzikuVx commented 8 years ago

I took some paper, a pen and did some calculations today. I will share my thoughts later in a spearate ticket, but looks like it is as issue of not only default PIDs but also scaling (how response scales to PID)

theArchLadder commented 8 years ago

Awesome that we have the same pid scaling as betaflight/cleanflight now! I have been flying betaflight and switched over to inav just now with the same pids, and my first impression is that it does not feel as locked in.

Settings used:

@digitalentity @DzikuVx Does inav use the same gyro software filter as betaflight? AFAIK betaflight turns off the hardware gyro filter, but this does not seem possible in inav, could we bring that over?

digitalentity commented 8 years ago

@theArchLadder can you post your dump from betaflight?

theArchLadder commented 8 years ago

@digitalentity I didn't save that, but almost everything was on defaults, except gyro_lowpass=75. Is there anything specific you want to know?

I did some more flying and it behaved better when i increased pitch/roll d-gain to 35, i have used 18-25 on betaflight. Perhaps inav need higher d-gain because of this? https://github.com/iNavFlight/inav/blob/master/src/main/flight/pid.c#L274

DzikuVx commented 8 years ago

There is a very specific reason why Betaflight can be so good in terms of Acro: type of aircraft it is targeted to run on: 250 or smaller with a very rigid frame using 5" or smaller props. Weighting usually between 500 and 700g. And thanks to that:

With bigger machines it's not so easy. For example, my 600mm on 12" props quad hovers at about 4500RPM. Noise it then around 75Hz. Cutoff of 75Hz would make it unflyable: all the motor noise would go straight into gyro. Even for 10" props cutoff 75Hz is too high.

INAV is not targeted at any kind of aircraft. Everyone expects his machine would fly great at default values. Pretty impossible. We can make it flyable for everyone. But not flying good for everyone.

There is only one solution I see: presets in configurator. I've already put so thinking into it, and this is how I see it: new configurator tab when pilot can choose propeller size and type: racer, photo platform, whatever. Maybe also weight, frame size... but probably only propeller size would be really enough. Preset would set gyro, LPF cutoffs, maybe something else too. Of maybe even some PID changes.

I think I will start working on this somewhere after my vacation.

martinbudden commented 8 years ago

@theArchLadder , have you also adjusted your rates? Your rates will have an effect on the feel and they are scaled differently in iNav and betaflight, see https://github.com/iNavFlight/inav/wiki/Rate-conversion-for-INAV-1.2

@DzikuVx , I think having presets in the configurator would be excellent. Openpilot/Librepilot has something similar (at least I assume it does - as part of the setup wizard it asks you to choose a frame type and I presume that is used to set PIDs, filters etc - I haven't actually looked at the code though). And Openpilot flies very well "out of the box" - ie with no tuning.

DzikuVx commented 8 years ago

@martinbudden Exactly, OpenPilot was source of my idea. I also not sure what was set in those, but PIDs and rates for sure.

theArchLadder commented 8 years ago

@DzikuVx I'm okay with having to tune filters and pids on inav, but so far i have not been able to come close to default betaflight. Inav feels sloppy and lose while betaflight feels locked in.

The main difference between bf and inav afaik is that bf can turn off the hardware gyro filter, as long as the software filters are the same in bf and inav (are they?)

@martinbudden Yes, i use 540deg/s for now, feels about right to me

martinbudden commented 8 years ago

@theArchLadder , software filtering of DTerm is different in iNav and bf. iNav uses a filter to differentiate and filter at the same time.

theArchLadder commented 8 years ago

Wow, @DzikuVx was not lying, filters make a huge difference. I did an experiment like this: i-gain and d-gain at zero and looptime at 1000, then do a gentle hover and increase p-gain until i got constant oscillations

Betaflight

p-gain software gyro lpf hardware gyro lpf
8.7 100 off
8.4 75 off
6.7 100 188hz
6.6 75 188hz

inav

p-gain software gyro lpf hardware gyro lpf
5.8 75 188hz
4.4 75 42hz

As you can see, turning off the hardware lpf allows much higher p-gain, i get why betaflight has it turned off by default now. I guess i should test different software lpf values without hardware lpf and see how that performs

DzikuVx commented 8 years ago

With lpf problem is that it is also platform dependent. If you have a lot of noise, you need lower cutoff to increase atenuation. If you have super super smooth motors and props, you can increase cutoff. Disabling hardware lpf means, in theory, you should lower software cutoff to compendate for missing 3dB. But lpf is not libear. Plus of having only one lpf is lower delay.

Ah, are you sure gyro_lpf 256 is not in deed the same as OFF?

theArchLadder commented 8 years ago

Did some more tests on betaflight:

p-gain software gyro lpf hardware gyro lpf
6.4 50 off
4.1 25 off
10.5 200 off

the results with low p-gain has slow and big oscillations, while high p-gain gives small and fast oscillations. Seems like a good way to test how much delay there is in the system.

I have not compared how effective soft vs hard is at removing noise, but i know that only soft seems to be effective on betaflight. 188hz hardware lpf sounds to high to be useful but it still seems to add lots of delay. The betaflight guys seems to know what they are doing and it seems like they came to the conclusion that using only software lpf is better.

@DzikuVx not sure if 256hz does it, IIRC i was unable to arm with that last time i tried, i guess i have to reflash inav and try it.

theArchLadder commented 8 years ago

@DzikuVx Something seems wrong with 256hz option, after i set it the inav configurator just says "waiting for data" no matter what tab i'm in, even after restarting both configurator and FC...

Oh, i just figured it out, i have to change set gyro_sync_denom=8 to get 1000 looptime, i guess the gyro starts to run in 8khz mode.

theArchLadder commented 8 years ago

Yay it worked! Thanks @DzikuVx !

Those settings gives constant oscillations at around 8.5 p-gain, just like betaflight, nice! Feels like we just got the P-term to behave as good/responsive as betaflight, i guess the next thing to check is D-term and see if there is any more delay there compared to betaflight, i don't think i will have time for that today though.

Inav uses a fancy "5-point noise-robust differentiators without time delay": https://github.com/iNavFlight/inav/blob/master/src/main/flight/pid.c#L274 Perhaps this will allow a higher dterm_lpf_hz so we can reduce delay without getting more noise. Or perhaps that "without time delay" is a lie and we would be better of without it :stuck_out_tongue_winking_eye:

EDIT: Looks like we reduced the gyro delay so i guess that should also help with d-term...

DzikuVx commented 8 years ago

Ha, this is a very nice think we learned here. INAV will never do looptimes as low as Betaflight because of higher computational requiements, but I see no reason not to be quite close

theArchLadder commented 8 years ago

Did some more test flights just now, i ended up with these settings: gyro_lpf = 256HZ gyro_sync_denom=8 gyro_soft_lpf_hz = 75 dterm_lpf_hz = 50 p_roll = 45 i_roll = 30 d_roll = 30 roll_rate = 72

There is still a bit of noise when looking in the bblog, the "5-point noise-robust differentiators without time delay" does not seem to make any big difference as far as i can tell. But i think the noise is on an acceptable level.

But wow, now it actually starts to fly well! One good sign of this is that my quad used to be very unstable and wobble a lot during -200cm/s descents, but now it looks really stable! Awesome! I can sort of hear the motors working hard to fight the turbulent propwash but the quad still looks stable, big improvement, YAY! :smiley:

digitalentity commented 8 years ago

@theArchLadder gyro_lpf = 256HZ is actually no LPF on MPU end, so this is OFF setting.

Ok, so this issue is basically a matter of properly setting parameters for miniquads. Thanks for figuring this out!

theArchLadder commented 8 years ago

Not sure if this is only for miniquads though, great acro gives great angle performance, and that should help with navigation stuff, surly bigger copters also want a wobble-free descent for example. Perhaps turning off the hardware lpf (also using 8khz mode) and using a lower software lpf hz will reduce delay but still be effective at reducing noise, and therefore increase performance...?

Betaflight also seems to do some clever stuff with i-term, i think that's worth investigating too.

DzikuVx commented 8 years ago

I took my 250 for a spin with

gyro_lpf = 256HZ
gyro_sync_denom=12
gyro_soft_lpf_hz = 75
dterm_lpf_hz = 50

and I must say, that was pretty impressive. Maybe not super awesome because of one motor slightly off balance, but pretty impressive. Specially prop-wash situations improved greatly. Also rolls seems to be much more dynamic now.

martinbudden commented 8 years ago

@DzikuVx , @digitalentity , I think as well as @DzikuVx idea for the configurator setting default values, I think we should revisit the default values in iNav. In particular I favour less hardware filtering, and compensating with different soft filters.

@DzikuVx , it will also be interesting to hear any results you have with your larger quads when you get back from holiday.

(My largest quad is a 250, but I'm looking at building a 350 with camera and gimbal soon...)

DzikuVx commented 8 years ago

@martinbudden from my latest experiments I think that only software LPF might be a good idea also for big machines. Before one of my motors started to introduce much noise I was using gyro_lpf=188HZ and gyro_soft_lpf_hz=50. I will try to confirm that as soon as I replace faulty motor

digitalentity commented 8 years ago

As a matter of fact on a 450-sized machine without Damped Light support on the ESCs I was only able to get a flyable tune with gyro_lpf=98HZ or 42HZ. Anything higher made D-term crazy no matter how low I was setting gyro_soft_lpf_hz.

I guess heavy internal filtering with gyro_lpf introduces a lot of delay which makes closed-loop control worse on all machines, however on bigger machines high-frequency vibrations might make things even worse.

The trick is that MPU is sampling gyro internally at 8kHz and thus is able to do very effective LPF filtering. If we would be sampling gyro at 8kHz as well, we could always be running with imternal LPF disabled.

As a matter of fact I'm thinking about modifying gyro driver to read gyro at highest possible rate (1kHz or 8kHz depending on gyro_lpf setting) and downsample it to looptime if required. Current gyro_sync_denom setting is dropping unused samples, I intend to average them to suppress noise.

digitalentity commented 8 years ago

For example:

gyro_sync=256HZ
gyro_sync_denom=16

will yield 500Hz looptime and will use only 1 sample out of 16 (the rest 15 would be silently dropped). If we modify the code to record all 16 samples and average them out we will significantly suppress influence of high-frequency noise and will reduce effect of aliasing (current approach will alias everything above 250Hz, proposed approach will be immune to aliasing up to 4kHz vibrations).

digitalentity commented 8 years ago

I guess it's time to look into making INAV better suited for tiny acro machines - it flies good enough on bigger ones :smiley:

martinbudden commented 8 years ago

@digitalentity, as you point out, setting gyro_sync_denom to a value of other than one results in gyro samples being dropped rather than used.

Before I got diverted by the F4 port I was working on this issue. However, rather than change the gyro driver, I think the correct approach is to make changes to the PID controller.

My ideas were actually prompted by the way you have structured the iNav PID. As stated in your code, it is divided into 4 steps:

// Step 1: Calculate gyro rates
// Step 2: Read target
// Step 3: Run control for ANGLE_MODE, HORIZON_MODE, and HEADING_LOCK
// Step 4: Run gyro-driven control

However, all 4 steps are called sequentially from within the main pidController function.

My code, which I've provisionally implemented in a new PID (which I've called "Mars") at https://github.com/martinbudden/cleanflight/blob/pid_mars/src/main/flight/pid_mars.c instead spits the PID into 3:

  1. pidMarsUpdateGyroRate - called every time there is a gyroUpdate, regardless of gyro_sync_denom
  2. pidMarsUpdateDesiredRate - called whenever there is new RC input (ie the pilot has changed the desired rate)
  3. pidMarsCalculate - called whenever a calculation is required - ie just before the motors are updated

This means each part of the pid calculation is only performed when it is required and so pidMarsUpdateGyroRate can be called at a high frequency.

pidMarsUpdateGyroRate does three things:

  1. updates a filter using the latest gyro rate. Currently I'm using a FIR filter, which I think gives better results than simply averaging the gyro value
  2. updates ITerm (ie adds the gyro rate and does some anti-windup calculations)
  3. optionally applies some DTerm filtering

The advantages of this approach are

  1. No gyro update values are dropped
  2. Specific filtering actions can be taken for P, I and D terms, rather than having generic filtering or averaging in the gyro driver.
  3. Since calculations are only peformed when required, overall overhead of PID is reduced
  4. taskMainPidLoopChecker in mw.c can be simplified (although in my code it is more complicated, since I support both the old PIDs and the new).

I sort of regard this as the logical conclusion of the restructuring work you did for the iNav PID and think it will result in much improved performance, although I have only done very limited testing.

theArchLadder commented 8 years ago

At what rate can the gyro be read when connected with i2c?

digitalentity commented 8 years ago

@theArchLadder If we would have a proper DMA-based I2C driver, we can reach 3-4kHz gyro rate even with I2C bus at 400kHz. Problem is that currect I2C driver is blocking meaning that going over 1-2kHz would be problematic already.

digitalentity commented 8 years ago

@martinbudden I'd separate gyro completely from PID loop. Read gyro as fast as possible, filter it and provide value to PID loop only when necessary. Make gyro and PID loop run at different rate (possibly even asynchronous).

gurkenfolie commented 8 years ago

tried my 250 with this settings gyro_lpf = 256HZ gyro_sync_denom=12 gyro_soft_lpf_hz = 75 dterm_lpf_hz = 50 F1, looptime 2000

the quad flies way better, rolls are very smooth, poshold behaviour is better, plus i was able to go up with P up to 16 without oscillations (felt so, i will have a look at the blackbox log).

DzikuVx commented 8 years ago

@digitalentity @martinbudden Idea of separating gyro readouts and PID loop sounds very promising to me.