Skip to content
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

Advanced Ballistics - Drag model revamp & Spin drift correction #5566

Merged
merged 16 commits into from
Oct 6, 2017

Conversation

ulteq
Copy link
Contributor

@ulteq ulteq commented Sep 28, 2017

Many thanks to @dedmen, @brainslush and @Laid3acK for the extensive help.

- Moved away from using the drag tables from the GNU exterior ballistics library
- The drag functions are now based off this data from JBM Ballistics: http://www.jbmballistics.com/ballistics/downloads/text/
- The differences are minor, but some players might still appreciate the additional authenticity
@ulteq ulteq added the kind/enhancement Release Notes: **IMPROVED:** label Sep 28, 2017
@ulteq ulteq added this to the 3.11.0 milestone Sep 28, 2017
jonpas
jonpas previously approved these changes Sep 28, 2017
Copy link
Member

@jonpas jonpas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I trust what you are doing.

@@ -29,7 +29,8 @@ private _distance = 0;
while {_velocity > _thresholdVelocity} do {
private _bc = GVAR(targetSolutionInput) select 14;
private _dragModel = GVAR(targetSolutionInput) select 15;
private _drag = parseNumber(("ace_advanced_ballistics" callExtension format["retard:%1:%2:%3", _dragModel, _bc, _velocity]));
private _temperature = GVAR(targetSolutionInput) select 5;
private _drag = parseNumber(("ace_advanced_ballistics" callExtension format["retard:%1:%2:%3:%4", _dragModel, _bc, _velocity, _temperature]));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whitespace after parseNumber and format.

@@ -118,7 +118,7 @@ while {_TOF < 15 && (_bulletPos select 1) < _targetRange} do {
_trueSpeed = vectorMagnitude _trueVelocity;

if (missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]) then {
private _drag = parseNumber(("ace_advanced_ballistics" callExtension format["retard:%1:%2:%3", _dragModel, _bc, _trueSpeed]));
private _drag = parseNumber(("ace_advanced_ballistics" callExtension format["retard:%1:%2:%3:%4", _dragModel, _bc, _trueSpeed, _temperature]));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same.

@@ -103,7 +103,7 @@ while {_TOF < 6 && (_bulletPos select 1) < _targetRange} do {
_trueSpeed = vectorMagnitude _trueVelocity;

if (_useABConfig) then {
private _drag = parseNumber(("ace_advanced_ballistics" callExtension format["retard:%1:%2:%3", _dragModel, _bc, _trueSpeed]));
private _drag = parseNumber(("ace_advanced_ballistics" callExtension format["retard:%1:%2:%3:%4", _dragModel, _bc, _trueSpeed, _temperature]));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same.

@ulteq
Copy link
Contributor Author

ulteq commented Sep 28, 2017

@Neviothr, can we fix those style issues later, in a different pull request?

I trust what you are doing.

@jonpas, please do not merge it yet.

…ation

- The error was introduced with this PR (#4708)
@ulteq ulteq changed the title Advanced Ballistics - Drag model revamp Advanced Ballistics - Drag model revamp & Spin drift correction Sep 29, 2017
double A = -1;
double M = -1;
double calculateRetard(int DragFunction, double DragCoefficient, double Velocity, double Mach) {
std::vector<double> machNumbers = {};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Performance optimization would be to have these tables be built at compile-time.
Or making them global variables and just selecting a pointer to them here.
Because this way you have a memory allocation and memcpy everytime a drag function is choosen.

for (int i = 0; i < machNumbers.size(); i++) {
if (machNumbers[i] >= m) {
int previousIdx = std::max(0, i - 1);
double lcd = dragCoefficients[previousIdx];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

longer variable names would be neat here. I have no idea what lcd/lmn/cd mean.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. Even though all we do here is a linear interpolation between the data points.

@@ -309,7 +249,7 @@ double calculateZeroAngle(double zeroRange, double muzzleVelocity, double boreHe

v = std::sqrt(vx*vx + vy*vy);

double retard = calculateRetard(dragModel, ballisticCoefficient, v);
double retard = calculateRetard(dragModel, ballisticCoefficient, v, SPEED_OF_SOUND(15));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are calculating this constant.. at runtime. Everytime the function is called. Why?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RELEVANT VARIABLE NAME

Copy link
Contributor Author

@ulteq ulteq Sep 30, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dedmen, I expect it to be optimized away by the compiler.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It won't be here. because std::sqrt is not constexpr.

Copy link
Contributor Author

@ulteq ulteq Sep 30, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GCC 7.2.0 is smart enough. I will test VS 2017 tomorrow.

Copy link
Contributor Author

@ulteq ulteq Oct 1, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Visual Studio 2017 produces the exact same assembly code in both cases:

#define SPEED_OF_SOUND(t) (331.3 + std::sqrt(1 + t / 273.15f))
...
double r = calcR(dragModel, ballisticCoefficient, v, SPEED_OF_SOUND(15));
#define SPEED_OF_SOUND(t) (331.3 + std::sqrt(1 + t / 273.15f))
...
const float c = SPEED_OF_SOUND(15);
double r = calcR(dragModel, ballisticCoefficient, v, c);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

moving it into a const float doesn't change that std::sqrt is not constexpr before C++17.
Actually.. Not even C++17 has constexpr sqrt.
Does that assembly code that it produces calculate the Speed of sound. Or does it use a constant? If it calculates then it does exactly what I said

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just did a release compile. And yes it is calling sqrt at runtime.

Copy link
Contributor Author

@ulteq ulteq Oct 1, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will just replace it with 340.275.

const std::vector<double> machNumbersG8 = { 0.00, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, 0.50, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.825, 0.85, 0.875, 0.90, 0.925, 0.95, 0.975, 1.0, 1.025, 1.05, 1.075, 1.10, 1.125, 1.15, 1.20, 1.25, 1.30, 1.35, 1.40, 1.45, 1.50, 1.55, 1.60, 1.65, 1.70, 1.75, 1.80, 1.85, 1.90, 1.95, 2.00, 2.05, 2.10, 2.15, 2.20, 2.25, 2.30, 2.35, 2.40, 2.45, 2.50, 2.60, 2.70, 2.80, 2.90, 3.00, 3.10, 3.20, 3.30, 3.40, 3.50, 3.60, 3.70, 3.80, 3.90, 4.00, 4.20, 4.40, 4.60, 4.80, 5.00 };

const std::vector<std::vector<double>> dragCoefficients = { {}, dragCoefficientsG1, dragCoefficientsG2, {}, {}, dragCoefficientsG5, dragCoefficientsG6, dragCoefficientsG7, dragCoefficientsG8, {} };
const std::vector<std::vector<double>> machNumbers = { {}, machNumbersG1, machNumbersG2, {},{}, machNumbersG5, machNumbersG6, machNumbersG7, machNumbersG8,{} };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry I completly forgot that. std::array is constexpr and would be a little better here.
You could then also use dragCoefficients.count() in line 137 instead of the hardcoded number. In case we ever get a G9 or smth.
(dragCoefficients.count() with vector is a bad idea though. Because that would be evaluated at runtime.)
It wouldn't make a noticeable runtime difference I think. It would safe some time when the extension is called first time and a little memory.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Premature optimization is the root of all evil.

@ulteq ulteq removed the status/WIP label Oct 3, 2017
@ulteq
Copy link
Contributor Author

ulteq commented Oct 3, 2017

Ready to use, if you ask me.

@@ -20,7 +20,7 @@
TRACE_10("firedEH:",_unit, _weapon, _muzzle, _mode, _ammo, _magazine, _projectile, _vehicle, _gunner, _turret);

// Parameterization
private ["_abort", "_AmmoCacheEntry", "_WeaponCacheEntry", "_opticsName", "_opticType", "_bulletTraceVisible", "_temperature", "_barometricPressure", "_bulletMass", "_bulletLength", "_muzzleVelocity", "_muzzleVelocityShift", "_bulletVelocity", "_bulletLength", "_barrelTwist", "_stabilityFactor", "_aceTimeSecond", "_barrelVelocityShift", "_ammoTemperatureVelocityShift"];
private ["_abort", "_AmmoCacheEntry", "_WeaponCacheEntry", "_opticsName", "_opticType", "_bulletTraceVisible", "_temperature", "_barometricPressure", "_bulletMass", "_bulletLength", "_muzzleVelocity", "_muzzleVelocityShift", "_bulletVelocity", "_bulletLength", "_barrelTwist", "_stabilityFactor", "_barrelVelocityShift", "_ammoTemperatureVelocityShift"];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

private keyword would be faster.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

private _abort = true;
is evaluated at compile-time.
private ARRAY is runtime.
Also private ARRAY assigns nil to that variable. and later when you initialize it you assign again. so using private ARRAY you assign a value to the variable one extra time.

Copy link
Contributor Author

@ulteq ulteq Oct 3, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can try to fix that in a separate PR. Feel free to make a GitHub issue for it.

But I think we're using private ARRAY in many places.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fun-fact. using private keyword is also faster than not using private at all.
using private ARRAY however is slower than not privatizing variables. on average.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah.. I'll make a PR that changes it everywhere where appropriate.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

private ARRAY is only in use because some components haven't gotten the love of cleanup yet since private VAR = VALUE was introduced.

@@ -33,7 +31,7 @@ private _aceTimeSecond = floor CBA_missionTime;
drop ["\A3\data_f\ParticleEffects\Universal\Refract","","Billboard",1,0.1,getPos _bullet,[0,0,0],0,1.275,1,0,[0.02*_caliber,0.01*_caliber],[[0,0,0,0.65],[0,0,0,0.2]],[1,0],0,0,"","",""];
};

_bullet setVelocity (_bulletVelocity vectorAdd (parseSimpleArray ("ace_advanced_ballistics" callExtension format["simulate:%1:%2:%3:%4:%5:%6:%7", _index, _bulletVelocity, _bulletPosition, ACE_wind, ASLToATL(_bulletPosition) select 2, _aceTimeSecond, CBA_missionTime - _aceTimeSecond])));
_bullet setVelocity (_bulletVelocity vectorAdd (parseSimpleArray ("ace_advanced_ballistics" callExtension format["simulate:%1:%2:%3:%4:%5:%6:%7", _index, _bulletVelocity, _bulletPosition, ACE_wind, ASLToATL(_bulletPosition) select 2, CBA_missionTime toFixed 6])));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor error. format still expects 7 elements but you only give 6. Doesn't cause any runtime error and the extension doesn't care. So not a problem.

@PabstMirror PabstMirror merged commit be482ea into master Oct 6, 2017
@PabstMirror PabstMirror deleted the advanced-ballistics-drag-model-revamp branch October 6, 2017 18:05
@ThiagoGattiCarvalho
Copy link

I predict bullet drops in Excel using Point-Mass formulas and my results are the same as Litz Advanced Ballistics software.

Good thing is that I can turn it into a Monte Carlo simulation by adding randomness to muzzle velocity. If I also add controlled randomness to range estimation and consecutive drop error (simulating AI) then, I have a WEZ simulation, just like Litz.

So, my suggestion is the inclusion a new ACE parameter:
ace_muzzleVelocityVariation = 10; // meaning muzzle velocity could be - 10 to + 10 m/s according to a normal distribution.

Anyway,

My key parameter for trajectory simulation are:

  1. Air density calculation from temperature and humidity, like Litz' Advanced Ballistics Poit-Mass Solver does. I still struggle to achieve this.
  2. Speed of sound calculation for the given weather (which is always changing).
  3. Bullet data, like you already have.
  4. A reference table relating mach speed and CD - Coefficient of Drag, which you already have
  5. A good interpolation method for reading the above table.
  6. Very very important, to the simulation interval. For 1200 FPS I calculate accurate numbers but, it is too much resource consuming, which may lead to the next topic.
  7. A good gravity constant, which may be different than 9.81 for the sake of bullet drop and FPS optimization.

This is an example

t [s] | t lag [s] | vx [m/s] | vy [m/s] | vz [m/s] | v [m/s] | M | CD | FD [N] | ax [m/s2] | ay [m/s2] | az [m/s2] | x [m] | y [m] | z [m]

0.0000 | 0.0000 | 834.45 | 11.78 | 11.01 | 834.60 | 2.45 | 0.2725 | 0.000760 | -529.40 | -17.28 | -6.99 | 0.00 | 0.00 | 0.00
0.0008 | 0.0000 | 834.01 | 11.77 | 11.01 | 834.16 | 2.45 | 0.2726 | 0.000760 | -528.98 | -17.27 | -6.98 | 0.70 | 0.01 | 0.00
0.0017 | 0.0000 | 833.56 | 11.75 | 11.01 | 833.72 | 2.45 | 0.2727 | 0.000761 | -528.55 | -17.26 | -6.98 | 1.39 | 0.02 | 0.00
0.0025 | 0.0000 | 833.12 | 11.74 | 11.01 | 833.28 | 2.45 | 0.2727 | 0.000761 | -528.13 | -17.25 | -6.98 | 2.08 | 0.03 | 0.00
0.0033 | 0.0000 | 832.68 | 11.73 | 11.01 | 832.84 | 2.45 | 0.2728 | 0.000761 | -527.70 | -17.24 | -6.98 | 2.78 | 0.04 | 0.00
0.0042 | 0.0000 | 832.24 | 11.71 | 11.01 | 832.40 | 2.45 | 0.2729 | 0.000761 | -527.28 | -17.23 | -6.98 | 3.47 | 0.05 | 0.00
0.0050 | 0.0000 | 831.80 | 11.70 | 11.01 | 831.96 | 2.44 | 0.2729 | 0.000761 | -526.86 | -17.22 | -6.97 | 4.17 | 0.06 | 0.00
0.0058 | 0.0000 | 831.37 | 11.68 | 11.01 | 831.52 | 2.44 | 0.2730 | 0.000762 | -526.43 | -17.20 | -6.97 | 4.86 | 0.07 | 0.00
0.0067 | 0.0000 | 830.93 | 11.67 | 11.01 | 831.08 | 2.44 | 0.2731 | 0.000762 | -526.01 | -17.19 | -6.97 | 5.55 | 0.08 | 0.00
0.0075 | 0.0000 | 830.49 | 11.65 | 11.01 | 830.64 | 2.44 | 0.2731 | 0.000762 | -525.59 | -17.18 | -6.97 | 6.24 | 0.09 | 0.00
0.0083 | 0.0000 | 830.05 | 11.64 | 11.01 | 830.21 | 2.44 | 0.2732 | 0.000762 | -525.17 | -17.17 | -6.97 | 6.94 | 0.10 | 0.00
0.0092 | 0.0000 | 829.61 | 11.63 | 11.01 | 829.77 | 2.44 | 0.2733 | 0.000762 | -524.74 | -17.16 | -6.96 | 7.63 | 0.11 | 0.00

@ThiagoGattiCarvalho
Copy link

ThiagoGattiCarvalho commented Oct 24, 2017

I mean, it is important to predict exact results in Excel, because it means we are in control here.

Another important feature I think would be nice to share is the calculation of air friction.

You can take all the values of my mod if you want. BTW, why don't you add all the ammo to ACE? I have even made the icons. Just wait one week and I will release an update.

I have simulated all ammo, one-by-one in Litz Point-Mass Solver and then took note of TOF to reach 408 m/s, which is the start of the transonic region. Then I have used Excel's solver on my drop calculator to tell me which BI AirFriction value makes that bullet reach 408 m/s in the noted TOF. This way I know exactly the realistic AirFriction/Drag value required to decelerate the bullet.

@dedmen
Copy link
Contributor

dedmen commented Oct 24, 2017

Right now our SQF code is a bigger performance problem than the ballistics calculation inside the extension.

@ThiagoGattiCarvalho
Copy link

ThiagoGattiCarvalho commented Oct 24, 2017 via email

@ulteq
Copy link
Contributor Author

ulteq commented Oct 24, 2017

Another important feature I think would be nice to share is the calculation of air friction.

@QuickDagger, our airFriction values are generated automatically, based on the advanced ballistics drag model.

why don't you add all the ammo to ACE

We would also needs guns that are able to shoot it. I think it makes more sense to deliver the ammo classes as part of 3rd party weapon packs. At least until magazine groups are working.

Just wait one week and I will release an update.

Your ammo will work perfectly fine with ACE3, if you add those config entries: https://ace3mod.com/wiki/framework/advanced-ballistics-framework.html

If you have any questions or suggestions, please consider joining the discussion on: https://ace3public.slack.com/messages/C04CLGZCK/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/enhancement Release Notes: **IMPROVED:**
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants