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

winds are sorting by until_distance value in a Shot.__init__ #88

Merged
merged 1 commit into from
Aug 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions py_ballisticcalc/conditions.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ class Shot:
weapon: Weapon
ammo: Ammo
atmo: Atmo
winds: List[Wind]
winds: List[Wind] # use property Shot.winds to get sorted winds

def __init__(self,
weapon: Weapon,
Expand All @@ -257,9 +257,8 @@ def __init__(self,
self.weapon = weapon
self.ammo = ammo
self.atmo = atmo or Atmo.icao()
self.winds = winds or [Wind()]

# NOTE: Calculator assumes that winds are sorted by Wind.until_distance (ascending)
# sort winds by Wind.until distance
self.winds = sorted(winds or [Wind()], key=lambda wind: wind.until_distance.raw_value)

@property
def barrel_elevation(self) -> Angular:
Expand Down
77 changes: 54 additions & 23 deletions tests/test_computer.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,30 +22,31 @@ def setUp(self):
self.atmosphere = Atmo.icao() # Standard sea-level atmosphere
self.calc = Calculator()
self.baseline_shot = Shot(weapon=self.weapon, ammo=self.ammo, atmo=self.atmosphere)
self.baseline_trajectory = self.calc.fire(shot=self.baseline_shot, trajectory_range=self.range, trajectory_step=self.step)
self.baseline_trajectory = self.calc.fire(shot=self.baseline_shot, trajectory_range=self.range,
trajectory_step=self.step)

#region Cant_angle
# region Cant_angle
def test_cant_zero_elevation(self):
"""Cant_angle = 90 degrees with zero barrel elevation should match baseline with:
drop+=sight_height, windage-=sight_height
"""
canted = copy.copy(self.baseline_shot)
canted.cant_angle = Angular.Degree(90)
t = self.calc.fire(canted, trajectory_range=self.range, trajectory_step=self.step)
self.assertAlmostEqual(t.trajectory[5].height.raw_value-self.weapon.sight_height.raw_value,
self.baseline_trajectory[5].height.raw_value)
self.assertAlmostEqual(t.trajectory[5].windage.raw_value+self.weapon.sight_height.raw_value,
self.baseline_trajectory[5].windage.raw_value)
self.assertAlmostEqual(t.trajectory[5].height.raw_value - self.weapon.sight_height.raw_value,
self.baseline_trajectory[5].height.raw_value)
self.assertAlmostEqual(t.trajectory[5].windage.raw_value + self.weapon.sight_height.raw_value,
self.baseline_trajectory[5].windage.raw_value)

def test_cant_positive_elevation(self):
"""Cant_angle = 90 degrees with positive barrel elevation and zero twist should match baseline with:
drop+=sight_height, windage-=sight_height at muzzle, increasingly positive down-range
"""
canted = Shot(weapon=Weapon(sight_height=self.weapon.sight_height, twist=0, zero_elevation=Angular.Mil(2)),
ammo=self.ammo, atmo=self.atmosphere, cant_angle=Angular.Degree(90))
ammo=self.ammo, atmo=self.atmosphere, cant_angle=Angular.Degree(90))
t = self.calc.fire(canted, trajectory_range=self.range, trajectory_step=self.step)
self.assertAlmostEqual(t.trajectory[5].height.raw_value-self.weapon.sight_height.raw_value,
self.baseline_trajectory[5].height.raw_value, 2)
self.assertAlmostEqual(t.trajectory[5].height.raw_value - self.weapon.sight_height.raw_value,
self.baseline_trajectory[5].height.raw_value, 2)
self.assertAlmostEqual(t.trajectory[0].windage.raw_value, -self.weapon.sight_height.raw_value)
self.assertGreater(t.trajectory[5].windage.raw_value, t.trajectory[3].windage.raw_value)

Expand All @@ -54,14 +55,15 @@ def test_cant_zero_sight_height(self):
drop+=baseline.sight_height, windage no change
"""
canted = Shot(weapon=Weapon(sight_height=0, twist=self.weapon.twist),
ammo=self.ammo, atmo=self.atmosphere, cant_angle=Angular.Degree(90))
ammo=self.ammo, atmo=self.atmosphere, cant_angle=Angular.Degree(90))
t = self.calc.fire(canted, trajectory_range=self.range, trajectory_step=self.step)
self.assertAlmostEqual(t.trajectory[5].height.raw_value-self.weapon.sight_height.raw_value,
self.baseline_trajectory[5].height.raw_value)
self.assertAlmostEqual(t.trajectory[5].height.raw_value - self.weapon.sight_height.raw_value,
self.baseline_trajectory[5].height.raw_value)
self.assertAlmostEqual(t.trajectory[5].windage, self.baseline_trajectory[5].windage)
#endregion Cant_angle

#region Wind
# endregion Cant_angle

# region Wind
def test_wind_from_left(self):
"""Wind from left should increase windage"""
shot = Shot(weapon=self.weapon, ammo=self.ammo, atmo=self.atmosphere,
Expand Down Expand Up @@ -89,9 +91,10 @@ def test_wind_from_front(self):
winds=[Wind(Velocity(5, Velocity.MPH), Angular(6, Angular.OClock))])
t = self.calc.fire(shot, trajectory_range=self.range, trajectory_step=self.step)
self.assertLess(t.trajectory[5].height, self.baseline_trajectory[5].height)
#endregion Wind

#region Twist

# endregion Wind

# region Twist
def test_no_twist(self):
"""Barrel with no twist should have no spin drift"""
shot = Shot(weapon=Weapon(twist=0), ammo=self.ammo, atmo=self.atmosphere)
Expand All @@ -111,9 +114,10 @@ def test_twist(self):
self.assertLess(twist_left.trajectory[5].windage.raw_value, 0)
# Faster twist should produce larger drift:
self.assertGreater(-twist_left.trajectory[5].windage.raw_value, twist_right.trajectory[5].windage.raw_value)
#endregion Twist

#region Atmo
# endregion Twist

# region Atmo
def test_humidity(self):
"""Increasing relative humidity should decrease drop (due to decreasing density)"""
humid = Atmo(humidity=.9) # 90% humidity
Expand Down Expand Up @@ -141,12 +145,13 @@ def test_pressure(self):
shot = Shot(weapon=self.weapon, ammo=self.ammo, atmo=thin)
t = self.calc.fire(shot=shot, trajectory_range=self.range, trajectory_step=self.step)
self.assertGreater(t.trajectory[5].height, self.baseline_trajectory[5].height)
#endregion Atmo

#region Ammo
# endregion Atmo

# region Ammo
def test_ammo_drag(self):
"""Increasing ballistic coefficient (bc) should decrease drop"""
tdm = DragModel(self.dm.BC+0.5, self.dm.drag_table, self.dm.weight, self.dm.diameter, self.dm.length)
tdm = DragModel(self.dm.BC + 0.5, self.dm.drag_table, self.dm.weight, self.dm.diameter, self.dm.length)
slick = Ammo(tdm, self.ammo.mv)
shot = Shot(weapon=self.weapon, ammo=slick, atmo=self.atmosphere)
t = self.calc.fire(shot=shot, trajectory_range=self.range, trajectory_step=self.step)
Expand All @@ -173,7 +178,33 @@ def test_powder_sensitivity(self):
self.assertLess(t.trajectory[0].velocity, self.baseline_trajectory[0].velocity)
set_global_use_powder_sensitivity(previous)

#endregion Ammo
# endregion Ammo

# region Shot
def test_winds_sort(self):
winds = [
Wind(Unit.MPS(0), Unit.Degree(90), Unit.Meter(100)),
Wind(Unit.MPS(1), Unit.Degree(60), Unit.Meter(300)),
Wind(Unit.MPS(2), Unit.Degree(30), Unit.Meter(200)),
Wind(Unit.MPS(2), Unit.Degree(30), Unit.Meter(50)),
]

# sorted_winds = sorted(winds, key=lambda winds: winds.until_distance.raw_value)

# print()
shot = Shot(
None, None, 0, 0, 0, None,
winds
)
sorted_winds = shot.winds
self.assertIs(sorted_winds[0], winds[3])
self.assertIs(sorted_winds[1], winds[0])
self.assertIs(sorted_winds[2], winds[2])
self.assertIs(sorted_winds[3], winds[1])


# endregion Shot


if __name__ == '__main__':
unittest.main()