Skip to content

Issues related to formula in Plane::update_load_factor #24320

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

Open
abaghiyan opened this issue Jul 15, 2023 · 4 comments
Open

Issues related to formula in Plane::update_load_factor #24320

abaghiyan opened this issue Jul 15, 2023 · 4 comments

Comments

@abaghiyan
Copy link
Contributor

Bug report

Issue details

In method Plane::update_load_factor to estimate aerodynamic load factor the following formula is used aerodynamic_load_factor = 1.0f / safe_sqrt(cosf(radians(demanded_roll)));. In general when there the pitch and roll exist the formula for the aerodynamic load factor should be as follows: aerodynamic_load_factor = cosf(radians(_ahrs.pitch))/cosf(radians(demanded_roll)), which in case of turns (in horizontal plane) becomes aerodynamic_load_factor = 1.0f/cosf(radians(demanded_roll)). Why square root is used in the existing code. If proposed formulas are accepted shouldn't the code int32_t roll_limit = degrees(acosf(sq(1.0f / max_load_factor)))*100; also be changed accordingly (without square and taking into account pitch).

Version
4.3.7

Platform
Plane

Airframe type
Plane airframes

Hardware type
Pixhawk

@IamPete1
Copy link
Member

I think all our maths give the correct results, just that were just doing the sqrt in the wrong spot?

I think we would accept a PR to fix it, remove the sqrt from the load factor and the square from the roll limit cal. We would also need to add a sqrt here in that case:

_TASmin *= _load_factor;

Is that something you could do?

Once that is corrected we could think about including the pitch. That will reduce the load factor, so we might be better to ignore to stay on the conservative side.

@abaghiyan
Copy link
Contributor Author

I think all our maths give the correct results, just that were just doing the sqrt in the wrong spot?

I think we would accept a PR to fix it, remove the sqrt from the load factor and the square from the roll limit cal. We would also need to add a sqrt here in that case:

_TASmin *= _load_factor;

Is that something you could do?

Once that is corrected we could think about including the pitch. That will reduce the load factor, so we might be better to ignore to stay on the conservative side.

Dear @IamPete1, thank you for the quick response, I think I can do the changes and create a PR to fix the issue (will leave the pitch part for future).

abaghiyan added a commit to improvisllc/ardupilot that referenced this issue Aug 1, 2023
abaghiyan added a commit to improvisllc/ardupilot that referenced this issue Aug 1, 2023
@abaghiyan
Copy link
Contributor Author

abaghiyan commented Aug 2, 2023

Dear Peter Hall (@IamPete1) the connection between minimum airspeed and load factor can be obtained through equation:
liftForce = 0.5 * liftCoeff * rho * v_min * v_min * area = gravityForce //(in case of loadFactor = 1)
v_min = sqrt(2*gravityForce/(liftCoeff * rho * area))
For cases when loadfactor ≠ 1 we have the following formula:
liftForce = 0.5 * liftCoeff * rho * v_minwithloadFacor * v_minwithloadFacor * area = loadFactor * gravityForce , so
v_minwithloadFacor = sqrt(2 * loadFactor * gravityForce/(liftCoeff * rho * area)) = sqrt(loadFactor) * v_min which should be in ardupilot/libraries/AP_TECS/AP_TECS.cpp.
To connect load factor to speed ratio between smoothed airspeed v_smooth and minimum airspeed v_min the last formula can be used for v_smooth:
v_smooth = sqrt(loadFactor) * v_min, from which
loadFactor = square(v_smooth/v_min), so formula in Plane::update_load_factor should be changed to:
float max_load_factor = sq(smoothed_airspeed / MAX(aparm.airspeed_min, 1));

So if you approve the above I'll add new commit to PR #24469 to fix the above formula. As from tests I see that test-sitl-plane failed (AT-0153.2: Exception caught: roll-over: Failed to hold set attitude)

abaghiyan added a commit to improvisllc/ardupilot that referenced this issue Aug 4, 2023
abaghiyan added a commit to improvisllc/ardupilot that referenced this issue Aug 4, 2023
@abaghiyan
Copy link
Contributor Author

abaghiyan commented Aug 5, 2023

Added all fixes in PR #24509 . All tests passed.

abaghiyan added a commit to improvisllc/ardupilot that referenced this issue Aug 14, 2023
In general when there the pitch and roll exist the formula for the aerodynamic load factor should be as follows:
aerodynamic_load_factor = cosf(radians(_ahrs.pitch))/cosf(radians(demanded_roll));
which in case of turns (in the horizontal plane) becomes
aerodynamic_load_factor = 1.0f/cosf(radians(demanded_roll));
formulas can be obtained from equations of balanced spiral:
liftForce * cos(roll) = gravityForce * cos(pitch);
liftForce * sin(roll) = gravityForce * lateralAcceleration / gravityAcceleration; // as mass = gravityForce/gravityAcceleration
see issue ArduPilot#24320 [ArduPilot#24320].
To connect loadFactor to airspeed we can use formula of balancing between lift force and gravity force:
liftForce = loadFactor * gravityForce; on the other hand lift force can be expressed as
liftForce = 0.5 * lifCoefficient * airDensity * sq(airspeed) * referenceArea; minimum airseepd is at loadFactor = 1
and lift force only balances the gravit force, so gravity force (which is same as lift force at minimum airspeed) with minimum airspeed can be expressed as
gravityForce = 0.5 * lifCoefficient * airDensity * sq(airspeed_min) * referenceArea; substituting gravit force in previous formula gives us
0.5 * lifCoefficient * airDensity * sq(airspeed) * referenceArea = loadFactor * 0.5 * lifCoefficient * airDensity * sq(airspeed_min) * referenceArea;
from where we get:
loadFactor = sq(airspeed / airspeed_min);
These changes also require changes in ardupilot/libraries/AP_TECS/AP_TECS.cpp
Line 418 (according to the comments by Peter Hall): _TASmin *= _load_factor; should be changed to _TASmin *= safe_sqrt(_load_factor);
abaghiyan added a commit to improvisllc/ardupilot that referenced this issue Aug 14, 2023
abaghiyan added a commit to improvisllc/ardupilot that referenced this issue Aug 14, 2023
abaghiyan added a commit to improvisllc/ardupilot that referenced this issue Aug 14, 2023
In general when there the pitch and roll exist the formula for the aerodynamic load factor should be as follows:
aerodynamic_load_factor = cosf(radians(_ahrs.pitch))/cosf(radians(demanded_roll));
which in case of turns (in the horizontal plane) becomes
aerodynamic_load_factor = 1.0f/cosf(radians(demanded_roll));
formulas can be obtained from equations of balanced spiral:
liftForce * cos(roll) = gravityForce * cos(pitch);
liftForce * sin(roll) = gravityForce * lateralAcceleration / gravityAcceleration; // as mass = gravityForce/gravityAcceleration
see issue ArduPilot#24320 [ArduPilot#24320].
To connect loadFactor to airspeed we can use formula of balancing between lift force and gravity force:
liftForce = loadFactor * gravityForce; on the other hand lift force can be expressed as
liftForce = 0.5 * lifCoefficient * airDensity * sq(airspeed) * referenceArea; minimum airseepd is at loadFactor = 1
and lift force only balances the gravit force, so gravity force (which is same as lift force at minimum airspeed) with minimum airspeed can be expressed as
gravityForce = 0.5 * lifCoefficient * airDensity * sq(airspeed_min) * referenceArea; substituting gravit force in previous formula gives us
0.5 * lifCoefficient * airDensity * sq(airspeed) * referenceArea = loadFactor * 0.5 * lifCoefficient * airDensity * sq(airspeed_min) * referenceArea;
from where we get:
loadFactor = sq(airspeed / airspeed_min);
These changes also require changes in ardupilot/libraries/AP_TECS/AP_TECS.cpp
Line 418 (according to the comments by Peter Hall): _TASmin *= _load_factor; should be changed to _TASmin *= safe_sqrt(_load_factor);
abaghiyan added a commit to improvisllc/ardupilot that referenced this issue Aug 22, 2023
abaghiyan added a commit to improvisllc/ardupilot that referenced this issue Aug 22, 2023
abaghiyan added a commit to improvisllc/ardupilot that referenced this issue Aug 22, 2023
In general when there the pitch and roll exist the formula for the aerodynamic load factor should be as follows:
aerodynamic_load_factor = cosf(radians(_ahrs.pitch))/cosf(radians(demanded_roll));
which in case of turns (in the horizontal plane) becomes
aerodynamic_load_factor = 1.0f/cosf(radians(demanded_roll));
formulas can be obtained from equations of balanced spiral:
liftForce * cos(roll) = gravityForce * cos(pitch);
liftForce * sin(roll) = gravityForce * lateralAcceleration / gravityAcceleration; // as mass = gravityForce/gravityAcceleration
see issue ArduPilot#24320 [ArduPilot#24320].
To connect loadFactor to airspeed we can use formula of balancing between lift force and gravity force:
liftForce = loadFactor * gravityForce; on the other hand lift force can be expressed as
liftForce = 0.5 * lifCoefficient * airDensity * sq(airspeed) * referenceArea; minimum airseepd is at loadFactor = 1
and lift force only balances the gravit force, so gravity force (which is same as lift force at minimum airspeed) with minimum airspeed can be expressed as
gravityForce = 0.5 * lifCoefficient * airDensity * sq(airspeed_min) * referenceArea; substituting gravit force in previous formula gives us
0.5 * lifCoefficient * airDensity * sq(airspeed) * referenceArea = loadFactor * 0.5 * lifCoefficient * airDensity * sq(airspeed_min) * referenceArea;
from where we get:
loadFactor = sq(airspeed / airspeed_min);
These changes also require changes in ardupilot/libraries/AP_TECS/AP_TECS.cpp
Line 418 (according to the comments by Peter Hall): _TASmin *= _load_factor; should be changed to _TASmin *= safe_sqrt(_load_factor);
IamPete1 pushed a commit to IamPete1/ardupilot that referenced this issue Jan 17, 2025
In general when there the pitch and roll exist the formula for the aerodynamic load factor should be as follows:
aerodynamic_load_factor = cosf(radians(_ahrs.pitch))/cosf(radians(demanded_roll));
which in case of turns (in the horizontal plane) becomes
aerodynamic_load_factor = 1.0f/cosf(radians(demanded_roll));
formulas can be obtained from equations of balanced spiral:
liftForce * cos(roll) = gravityForce * cos(pitch);
liftForce * sin(roll) = gravityForce * lateralAcceleration / gravityAcceleration; // as mass = gravityForce/gravityAcceleration
see issue ArduPilot#24320 [ArduPilot#24320].
To connect loadFactor to airspeed we can use formula of balancing between lift force and gravity force:
liftForce = loadFactor * gravityForce; on the other hand lift force can be expressed as
liftForce = 0.5 * lifCoefficient * airDensity * sq(airspeed) * referenceArea; minimum airseepd is at loadFactor = 1
and lift force only balances the gravit force, so gravity force (which is same as lift force at minimum airspeed) with minimum airspeed can be expressed as
gravityForce = 0.5 * lifCoefficient * airDensity * sq(airspeed_min) * referenceArea; substituting gravit force in previous formula gives us
0.5 * lifCoefficient * airDensity * sq(airspeed) * referenceArea = loadFactor * 0.5 * lifCoefficient * airDensity * sq(airspeed_min) * referenceArea;
from where we get:
loadFactor = sq(airspeed / airspeed_min);
These changes also require changes in ardupilot/libraries/AP_TECS/AP_TECS.cpp
Line 418 (according to the comments by Peter Hall): _TASmin *= _load_factor; should be changed to _TASmin *= safe_sqrt(_load_factor);

See details here: ArduPilot#24320
peterbarker pushed a commit to peterbarker/ardupilot that referenced this issue Jan 20, 2025
In general when there the pitch and roll exist the formula for the aerodynamic load factor should be as follows:
aerodynamic_load_factor = cosf(radians(_ahrs.pitch))/cosf(radians(demanded_roll));
which in case of turns (in the horizontal plane) becomes
aerodynamic_load_factor = 1.0f/cosf(radians(demanded_roll));
formulas can be obtained from equations of balanced spiral:
liftForce * cos(roll) = gravityForce * cos(pitch);
liftForce * sin(roll) = gravityForce * lateralAcceleration / gravityAcceleration; // as mass = gravityForce/gravityAcceleration
see issue ArduPilot#24320 [ArduPilot#24320].
To connect loadFactor to airspeed we can use formula of balancing between lift force and gravity force:
liftForce = loadFactor * gravityForce; on the other hand lift force can be expressed as
liftForce = 0.5 * lifCoefficient * airDensity * sq(airspeed) * referenceArea; minimum airseepd is at loadFactor = 1
and lift force only balances the gravit force, so gravity force (which is same as lift force at minimum airspeed) with minimum airspeed can be expressed as
gravityForce = 0.5 * lifCoefficient * airDensity * sq(airspeed_min) * referenceArea; substituting gravit force in previous formula gives us
0.5 * lifCoefficient * airDensity * sq(airspeed) * referenceArea = loadFactor * 0.5 * lifCoefficient * airDensity * sq(airspeed_min) * referenceArea;
from where we get:
loadFactor = sq(airspeed / airspeed_min);
These changes also require changes in ardupilot/libraries/AP_TECS/AP_TECS.cpp
Line 418 (according to the comments by Peter Hall): _TASmin *= _load_factor; should be changed to _TASmin *= safe_sqrt(_load_factor);

See details here: ArduPilot#24320
rubenp02 pushed a commit to Ventor-Innovations/ardupilot that referenced this issue Jan 27, 2025
In general when there the pitch and roll exist the formula for the aerodynamic load factor should be as follows:
aerodynamic_load_factor = cosf(radians(_ahrs.pitch))/cosf(radians(demanded_roll));
which in case of turns (in the horizontal plane) becomes
aerodynamic_load_factor = 1.0f/cosf(radians(demanded_roll));
formulas can be obtained from equations of balanced spiral:
liftForce * cos(roll) = gravityForce * cos(pitch);
liftForce * sin(roll) = gravityForce * lateralAcceleration / gravityAcceleration; // as mass = gravityForce/gravityAcceleration
see issue ArduPilot#24320 [ArduPilot#24320].
To connect loadFactor to airspeed we can use formula of balancing between lift force and gravity force:
liftForce = loadFactor * gravityForce; on the other hand lift force can be expressed as
liftForce = 0.5 * lifCoefficient * airDensity * sq(airspeed) * referenceArea; minimum airseepd is at loadFactor = 1
and lift force only balances the gravit force, so gravity force (which is same as lift force at minimum airspeed) with minimum airspeed can be expressed as
gravityForce = 0.5 * lifCoefficient * airDensity * sq(airspeed_min) * referenceArea; substituting gravit force in previous formula gives us
0.5 * lifCoefficient * airDensity * sq(airspeed) * referenceArea = loadFactor * 0.5 * lifCoefficient * airDensity * sq(airspeed_min) * referenceArea;
from where we get:
loadFactor = sq(airspeed / airspeed_min);
These changes also require changes in ardupilot/libraries/AP_TECS/AP_TECS.cpp
Line 418 (according to the comments by Peter Hall): _TASmin *= _load_factor; should be changed to _TASmin *= safe_sqrt(_load_factor);

See details here: ArduPilot#24320
tridge pushed a commit that referenced this issue Feb 17, 2025
In general when there the pitch and roll exist the formula for the aerodynamic load factor should be as follows:
aerodynamic_load_factor = cosf(radians(_ahrs.pitch))/cosf(radians(demanded_roll));
which in case of turns (in the horizontal plane) becomes
aerodynamic_load_factor = 1.0f/cosf(radians(demanded_roll));
formulas can be obtained from equations of balanced spiral:
liftForce * cos(roll) = gravityForce * cos(pitch);
liftForce * sin(roll) = gravityForce * lateralAcceleration / gravityAcceleration; // as mass = gravityForce/gravityAcceleration
see issue #24320 [#24320].
To connect loadFactor to airspeed we can use formula of balancing between lift force and gravity force:
liftForce = loadFactor * gravityForce; on the other hand lift force can be expressed as
liftForce = 0.5 * lifCoefficient * airDensity * sq(airspeed) * referenceArea; minimum airseepd is at loadFactor = 1
and lift force only balances the gravit force, so gravity force (which is same as lift force at minimum airspeed) with minimum airspeed can be expressed as
gravityForce = 0.5 * lifCoefficient * airDensity * sq(airspeed_min) * referenceArea; substituting gravit force in previous formula gives us
0.5 * lifCoefficient * airDensity * sq(airspeed) * referenceArea = loadFactor * 0.5 * lifCoefficient * airDensity * sq(airspeed_min) * referenceArea;
from where we get:
loadFactor = sq(airspeed / airspeed_min);
These changes also require changes in ardupilot/libraries/AP_TECS/AP_TECS.cpp
Line 418 (according to the comments by Peter Hall): _TASmin *= _load_factor; should be changed to _TASmin *= safe_sqrt(_load_factor);

See details here: #24320
tizianofiorenzani pushed a commit to tizianofiorenzani/ardupilot that referenced this issue Feb 28, 2025
In general when there the pitch and roll exist the formula for the aerodynamic load factor should be as follows:
aerodynamic_load_factor = cosf(radians(_ahrs.pitch))/cosf(radians(demanded_roll));
which in case of turns (in the horizontal plane) becomes
aerodynamic_load_factor = 1.0f/cosf(radians(demanded_roll));
formulas can be obtained from equations of balanced spiral:
liftForce * cos(roll) = gravityForce * cos(pitch);
liftForce * sin(roll) = gravityForce * lateralAcceleration / gravityAcceleration; // as mass = gravityForce/gravityAcceleration
see issue ArduPilot#24320 [ArduPilot#24320].
To connect loadFactor to airspeed we can use formula of balancing between lift force and gravity force:
liftForce = loadFactor * gravityForce; on the other hand lift force can be expressed as
liftForce = 0.5 * lifCoefficient * airDensity * sq(airspeed) * referenceArea; minimum airseepd is at loadFactor = 1
and lift force only balances the gravit force, so gravity force (which is same as lift force at minimum airspeed) with minimum airspeed can be expressed as
gravityForce = 0.5 * lifCoefficient * airDensity * sq(airspeed_min) * referenceArea; substituting gravit force in previous formula gives us
0.5 * lifCoefficient * airDensity * sq(airspeed) * referenceArea = loadFactor * 0.5 * lifCoefficient * airDensity * sq(airspeed_min) * referenceArea;
from where we get:
loadFactor = sq(airspeed / airspeed_min);
These changes also require changes in ardupilot/libraries/AP_TECS/AP_TECS.cpp
Line 418 (according to the comments by Peter Hall): _TASmin *= _load_factor; should be changed to _TASmin *= safe_sqrt(_load_factor);

See details here: ArduPilot#24320
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants