Estimating supersonic Iranian missile velocity in the atmosphere
In this article, I will show you the estimation of the landing velocity of one of the rockets used against Haifa. The original video was published on YouTube on Jun 17, 2025.
From this video, it is possible to see at least two missiles producing a Mach cone near the landing point.
To observe a Mach cone, which is the conical shock wave produced by an object moving faster than the speed of sound in a medium, certain conditions are necessary. While the Mach cone itself exists regardless of visibility, seeing it depends on factors like humidity and lighting:
- Humidity: High humidity can help visualise the Mach cone because it affects the way light interacts with the air. Moisture particles can scatter light, making the cone more visible against the background.
- Lighting Conditions: Good lighting is crucial because it enhances the contrast between the cone and its surroundings. Bright, clear lighting helps highlight the shock wave's shape and presence.
This is why it is not always possible to observe it for every missile in the final seconds of flight.

The frame from the video with the landing of the warhead of one of the Iranian rockets against Haifa.
Mach-cone theory
The detailed Mach cone theory is described in the related article here: Mach cone theory / Oreshnik.
Briefly, we need to find the angle of the match cone, and this will give the velocity of the object in the speed of sound. The ratio \(M = \frac{c}{v}\) is called the Mach number, which quantifies the speed of the object relative to the speed. By measuring the angle \(\theta\) of the Mach cone, one can calculate the object's Mach number as:
\[M = \frac{1}{sin(\theta)}\]
Iranian missile measurements
The measurements from the observation of the Oreshnick Mach-cone give the results between 2 and 3 Mach numbers, which corresponds to an average velocity of 857 m/s or 3000 km/hr or 1900 miles/hour.
Code
To easily calculate the angle from an image, I create the following Python-based code:
import matplotlib.pyplot as plt
import numpy as np
import os
directory = 'best'
###############################################################################
def calculate_angle_and_plot(l1, l2):
x1, y1 = zip(*l1)
x2, y2 = zip(*l2)
slope1, intercept1 = np.polyfit(x1, y1, 1)
slope2, intercept2 = np.polyfit(x2, y2, 1)
# Generate lines for the plot
x = np.linspace(0, img.shape[1], 100) # Generate x values for line plotting
y1 = slope1 * x + intercept1
y2 = slope2 * x + intercept2
# Filter points that fall outside the y-range of the image
vi1 = (y1 >= 0) & (y1 <= img.shape[0])
vi2 = (y2 >= 0) & (y2 <= img.shape[0])
# Plot the lines
plt.plot(x[vi1], y1[vi1], 'r-')
plt.plot(x[vi2], y2[vi2], 'b-')
# angle
A = np.arctan(np.abs((slope2 - slope1) / (1 + slope1 * slope2)))
AD = np.degrees(A)
M = 1/np.sin(A/2)
# Display the angle on the image
plt.text(
10, img.shape[0]//10,
f"Angle: {AD/2:.2f}°; Mach: {M:.1f}",
color="white",
fontsize=14,
)
plt.draw()
return M, AD/2
def onclick(event):
global step
if event.xdata and event.ydata:
if step == 1:
line1.append((event.xdata, event.ydata))
plt.plot(event.xdata, event.ydata, 'rx')
elif step == 2:
line2.append((event.xdata, event.ydata))
plt.plot(event.xdata, event.ydata, 'bx')
plt.draw()
def on_key(event):
global step, Mach
if event.key == 'escape':
if step == 1 and len(line1) > 1:
step = 2
print(f"Place points on the SECOND side of the Mach cone and press ESC")
elif step == 2 and len(line2) > 2:
step = 3
# Calculate and display the angle
M, MA = calculate_angle_and_plot(line1, line2)
Mach.append(M)
print(f"Mach angle: {MA:.2f}°; Mach velocity: {M:.1f} ... Press ESC")
elif step == 3:
plt.close()
def find_png(directory):
all_files = os.listdir(directory)
png_files = [os.path.join(directory, f) for f in all_files if f.endswith('.png')]
sorted_png_files = sorted(png_files)
return sorted_png_files
###################################################################################
Mach = []
images = find_png(directory)
for F in images:
step = 1
line1 = []
line2 = []
print(f"Image: {F}")
print(f"Place points on the FIRST side of the Mach cone and press ESC")
img = plt.imread(F)
plt.figure(figsize=(12, 8))
plt.imshow(img)
plt.connect('button_press_event', onclick)
plt.connect('key_press_event', on_key)
plt.show()
print(f"Velocity: max={max(Mach):.2f}; min={min(Mach):.2f}; average={sum(Mach)/len(Mach):.2f} Mach")
The full description of this code will be given later.
Published: 2025-06-20 07:22:24
Updated: 2025-06-20 07:47:03