-
-
Notifications
You must be signed in to change notification settings - Fork 115
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Mixer smoothing (Motor Output Mixer) (Thrust Linearization) #398
Conversation
…oving the harsh motorMix constraining. Also introduced thrust linearization and 'AirMode 2.0'
src/main/flight/mixer.c
Outdated
|
||
// Predictive AirMode actually predicts the need of greater authority based on stick movements | ||
float calculatePredictiveAirModeAuthorityMultiplier() { | ||
float maxStickMovement = MAX(stickMovement[ROLL], MAX(stickMovement[PITCH], stickMovement[YAW])); // [0, 1], the max r/p/y stick movement |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using stick input with only pt1 filter will make the motor outputs more jerky?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This value is the filtered rc command. So we add an additional pt1 filter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is also smoothed/filtered stick data
See: https://github.com/emuflight/EmuFlight/blob/master/src/main/fc/fc_rc.c
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If im not mistaken the filtered RC command you are referring to is what is being used here. Maybe im wrong though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes you are right. You are getting it from rcCommandf, which is already filtered before being converted to the floats. Is extra filtering really needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The extra filtering gives us two advantages. It delays it slightly and keeps the effect going once we have stopped moving our sticks for a bit of time.
Hi guys, I updated both graphs updating plots order and labeling (I think that "authority" explains better the concept than "torque %", but I leaved it in the axis legend). Also I updated the graphs of the AirMode OFF because in the current implementation we don't have a selectable authority value for the middle throttle, so it scales between the values for zero throttle and full throttle. Maybe it can be useful to introduce a configurable third value for an authority value, e.g. 30% throttle -> 100% authority. |
I wanna stress out the Motor Mixer 2.0 only changes the behavior of motors not directly interested in the main/principal quad's movement. These are the same graphs of above where the two opposite motors don't have a constant respective output difference, but is the motorMixRange itself. AirMode OFF: AirMode ON: |
this pr what is shown in https://www.youtube.com/watch?v=A_rQs3Uqkq0 ? |
Ok I finally managed to do some mixer checks. I did not fly yet. But your mixer strategy to keep the thrust equal seems fine. It gives the full authority, but the throttle offset is selected better. Just like shown in your graphs.
I do think you are trying to change too much in this single PR. In order to really flight test this linear mixer behavior it may be better to get rid of all other stuff, that you introduced in this PR. Perhaps just keep the authorityZeroThrottle and authorityFullThrottle to configure for now? |
have to agree with @borisbstyle here in terms of this being too much for one pr. |
I agree too, basically I should leave the applyMixerClipAdjustment() and the thrust linearization (it is needed by the 2.0 thing, it's something I really care about and it integrates well and simplifies the battery compensation logic) and leave out the @Quick-Flash part for the moment (predictive AirMode and axis lock). I didn't understand "Basically in here I was getting exact same behaviour". |
@tylercorleone i would like to do |
Well I wrote a small piece of simulation software, where I can play with different scenarios from stick inputs, gyro data and also test separate mixer scenarios. I am not sure why? Maybe I did something wrong and it also got late, but I will double check. I used (1.0 factor) for zero and full throttle authority for my tests and I didn't enable predictive airmode. I think for naming convention it might be good to first flight test it and see how it feels :D. Than perhaps relate it to some "feeling". I would expect and hope it gives more organic feeling on sharper stick inputs, but that is just how I think it might be. |
Yeah that is what users want to see. Enable something and fly :D or make it default if it's good. Then eventually additional stuff can be implemented later on as enhancements. |
@borisbstyle yes, the "lazy" mode works exactly as the normal mode if you look only at the motors with the highest offset, like I wrote in a comment above (identical graphs). The difference is that not all the motors will receive the same amount of offset because ABS(motorMix[i]) is not equal to motorMixDelta for all the motors. There is a discussion on Discord, from the first tests it seems that it behaves as it did on my quad. Less nervous, more predictable, no bounces when on the ground, no "vacuum effect" when you get hit the wall etc. |
Ok. That makes sense. I said it was simple test. I was only testing single axis. |
src/main/flight/mixer.c
Outdated
@@ -623,6 +648,14 @@ static void calculateThrottleAndCurrentMotorEndpoints(timeUs_t currentTimeUs) { | |||
#define CRASH_FLIP_DEADBAND 20 | |||
#define CRASH_FLIP_STICK_MINF 0.15f | |||
|
|||
static float mapThrustToMotorOutput(float thrust) | |||
{ | |||
float vbatCompFactor = currentControlRateProfile->vbat_comp_type != VBAT_COMP_TYPE_OFF ? calculateBatteryCompensationFactor() : 1.0f; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO: move this calculation out
After more testing, I'm really unsure of the usefulness of predictive airmode. Axis lock (or whatever we want to call it) does however seem useful. |
Yes, with the lazy mixer maybe we don't need Predictive AirMode. I didn't tried the axis lock, but I think the suggestion of Borisbstyle was just to make the PR smaller and easier to test. |
…e (there was a division by 100 too much)
src/main/flight/mixer.c
Outdated
@@ -623,6 +635,12 @@ static void calculateThrottleAndCurrentMotorEndpoints(timeUs_t currentTimeUs) { | |||
#define CRASH_FLIP_DEADBAND 20 | |||
#define CRASH_FLIP_STICK_MINF 0.15f | |||
|
|||
static float mapThrustToMotorOutput(float thrust, float vbatCompFactor) | |||
{ | |||
float linearizedThrust = vbatCompFactor * ((1.0f - thrust_linearization_level) * thrust + thrust_linearization_level * SIGN(thrust) * vbatCompFactor * sqrtf(ABS(thrust))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if the sign management is necessary. I did it because of the 3D mode, but actually I don't know if here we can have a negative thrust value. If not the formula could be cleaned up.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah i didn't notice this, but your completely correct. Thrust should never be able to have a negative sign.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you Quick 🙂
…that with boht linear_throttle ON and OFF the transition is the same
done |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
its time, defaults for thrust linear may still need to be played with though
* feat(mixer_smoothing): smoothing out the motor output calculation removing the harsh motorMix constraining. Also introduced thrust linearization and 'AirMode 2.0' * feat: QuickFlash's predictive AirMode, porting from another impl (emuflight#3) * min/max fix, thanks to borisbstyle * predictiveAirMode activation logic refactor * applyAirMode become applyMixerClipAdjustment * refactoring and simplification * rolling back some useless changes * cleared out thrust linearization formula and fixed the linear throttle (there was a division by 100 too much) * removed unnecessary sign management * removed unnecessary change * fix * fixes, removed throttle linearization for the moment * moved PID scaling * removed DEBUG_WRONG_PIDSUM_SIGN * thrust linearization formula changed (actual matematical inverse) and reintroduced thruttle linearization * removed duplicated code * mixer_impl * mixing yaw separately * fixes and temporarily put mixerImpl on OSD * mix & roll/pitch mix rate * norm fix * wip * fixes * final, maybe... * cleanup * unlinear throttle fix * removing avg controller's caused thrust/motor * backup * two pass mixer. Version 1.0.0 * two level thrust linearization * code cleaning * TL from idle level and TPA disabled when TL is enabled * fix SPA and motorOutputIdleLevel * changed desmos link for TL graphs * fix: applying AirMode level (so AirMode OFF) given throttleMotor, so that with boht linear_throttle ON and OFF the transition is the same * removed mixer impl from OSD and another code cleaning * mixerInitProfile called into pidInitConfig * rewording * fix: fixed thrust-linearization disabling. Code cleaning * 65 default value for linear_thrust_low_output * little code simplification * 3d mode fix and cleanup Co-authored-by: nerdCopter <56646290+nerdCopter@users.noreply.github.com> Co-authored-by: Quick-Flash <46289813+Quick-Flash@users.noreply.github.com>
@tylercorleone , almost certain this PR broke 3D-mode. Can you investigate? References |
This PR brings different changes to the way the controller's output (roll, pitch and yaw) is mixed with throttle to obtain a motor output.
The needs of roll and pitch can interfere with yaw's needs, controller's output interferes with throttle demands etc.
Here are proposed two alternatives to the LEGACY mixer, SMOOTH and 2PASS.
Both SMOOTH and 2PASS can use an option called "laziness" that enables a smarter "clipping prevention" strategy, that is called lazy because it adds only the minimum required amount of offset to remain in the [0, 1] for each "motor group" (that is a group of opposite motors that can actually work in conjunction in order to obtain a certain amount of roll/pitch) instead of applying the biggest needed amount. In this way we avoid to add/increase the total thrust when not needed, obtaining a better "throttle authority".
The scope of the SMOOTH mixer is just to avoid the harsh clipping strategy that the legacy mixer uses to keep the sum of the controller's output (roll + pitch + yaw) and throttle in the [0, 1] range.
These graphs show the total thrust and the torque applied by two opposite motors with a respective output difference of 0.2 varying throttle and motorMixRange (maximum controller's output range).
AirMode OFF
1 - LEGACY
2 - SMOOTH - laziness OFF
3 - SMOOTH - laziness ON
AirMode ON
1 - LEGACY
2 - SMOOTH - laziness OFF
3 - SMOOTH - laziness ON
Laziness assumes that the torque obtained given a difference of X between two motors is independent from the offset they are working to. That is, it requires thrust linearization (TL).
This PR brings a TL formula that speculates that the thrust/RPM strategy can be expressed as the composition of a quadratic and a linear curve and uses its mathematical inverse to compensate for that non-linearity.
Here a tool to play with to calculate the correct parameters to use for low and high RPM compensation (0.65 and 0.3 is a good midpoint): https://www.desmos.com/calculator/zal1gyqrcn
In this example you first have to match the thrust response curve of your quad (there are a couple already provided taken from www.miniquadtestbench.com), and then find the correct values to make it linear.
The two pass mixer (2PASS) handles yaw output and roll/pitch output differently. The first needs RPM linearity, hence motorOutput linearity, although it's not exactly a linear relationship, as you can see from other Mini Quad Bench graphs, while the seconds need thrust linearity.
This is the motorOutput at different throttle levels, when roll+pitch sum has the same magnitude of yaw (50/50):
yaw output is linear, roll+pitch output is linear too (what you see here is motor output, so motor and props will make it linear)
Here the roll+pitch/yaw rate is 90/10:
same roll and pitch authority while preserving a little more throttle authority
Here the roll+pitch/yaw rate is 10/90:
again yaw linearity while also preserving throttle authority
Here is the comparison between LECACY and 2PASS with laziness ON, that is the preferred combination so far (50/50 roll+pitch/yaw rate):
Keep in mind that the 0 axis represent the separation between different motors.