I'm steering to the wrong place but have a somewhat working steering animation
This commit is contained in:
parent
f50496ed5d
commit
023c20016f
@ -1,6 +1,6 @@
|
||||
# %% imports
|
||||
import numpy as np
|
||||
from utils import AnimatedPlot, dir_assets
|
||||
from utils import AnimatedPlot, db10, db20, dir_assets, wrap_phase
|
||||
|
||||
|
||||
# %%
|
||||
@ -17,7 +17,6 @@ class PcolorPlot(AnimatedPlot):
|
||||
self.element_x = np.linspace(-x_range / 2, x_range / 2, elements)
|
||||
self.element_y = np.zeros(elements)
|
||||
self.angle = np.deg2rad(angle_deg)
|
||||
self.element_phase = np.zeros(elements)
|
||||
self.element_phase = (
|
||||
np.dot(np.array([self.element_x, self.element_y]).T, [np.sin(self.angle), np.cos(self.angle)]) * 2 * np.pi
|
||||
)
|
||||
@ -104,18 +103,91 @@ class PcolorMagPlot(PcolorPlot):
|
||||
)
|
||||
|
||||
|
||||
class Steer(AnimatedPlot):
|
||||
def __init__(self, elements: int, spacing_lambda: float = 0.5, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
self.ax.remove()
|
||||
self.axs = [
|
||||
self.fig.add_subplot(3, 1, 1),
|
||||
self.fig.add_subplot(3, 1, 2),
|
||||
self.fig.add_subplot(3, 1, 3),
|
||||
]
|
||||
|
||||
self.spacing_lambda = spacing_lambda
|
||||
self.elements = elements
|
||||
|
||||
def update(self, t: float):
|
||||
for ax in self.axs:
|
||||
ax.clear()
|
||||
|
||||
# rewind, don't reset
|
||||
if t > 0.5:
|
||||
t = 1 - t
|
||||
t *= 2
|
||||
|
||||
angle = np.deg2rad((t * 2 - 1) * 90) # steering angle
|
||||
|
||||
def get_phase(position):
|
||||
return wrap_phase(np.sin(angle) * position * 2 * np.pi, deg=False)
|
||||
|
||||
ideal_position = self.spacing_lambda * np.linspace(-(self.elements - 1) / 2, (self.elements - 1) / 2, 1001)
|
||||
ideal_phase = get_phase(ideal_position)
|
||||
|
||||
element_position = self.spacing_lambda * np.linspace(
|
||||
-(self.elements - 1) / 2, (self.elements - 1) / 2, self.elements
|
||||
)
|
||||
element_phase = get_phase(element_position)
|
||||
element_taper = np.ones(self.elements)
|
||||
element_excitation = element_taper * np.exp(1j * element_phase)
|
||||
|
||||
theta = np.linspace(-90, 90, 361)
|
||||
fft_points = 128
|
||||
fft_period = 90 / self.spacing_lambda
|
||||
theta_fft = np.linspace(0, fft_period, fft_points, endpoint=False)
|
||||
ff_pattern = np.interp(
|
||||
theta,
|
||||
theta_fft,
|
||||
np.fft.fft(np.concat([element_excitation, np.zeros(fft_points - self.elements)]), norm="backward")
|
||||
/ self.elements,
|
||||
period=fft_period,
|
||||
)
|
||||
|
||||
self.fig.suptitle(f"{np.rad2deg(angle):+5.1f}° Steer")
|
||||
|
||||
rolloff = np.cos(np.deg2rad(theta))
|
||||
self.axs[0].set_ylabel("Farfield Magnitude [dB]")
|
||||
self.axs[0].plot(theta, db20(rolloff), color="gray")
|
||||
self.axs[0].plot(theta, db20(ff_pattern * rolloff))
|
||||
self.axs[0].set_xlim(-90, 90)
|
||||
self.axs[0].set_ylim(-30, 5)
|
||||
self.axs[0].set_xlabel("Theta [°]")
|
||||
self.axs[0].grid(True)
|
||||
self.axs[0].axvline(np.rad2deg(angle))
|
||||
|
||||
self.axs[1].set_ylabel("Excitation Phase")
|
||||
self.axs[1].stem(element_position, np.rad2deg(element_phase))
|
||||
self.axs[1].plot(ideal_position, np.rad2deg(ideal_phase), linestyle="--")
|
||||
self.axs[1].set_ylim(-200, 200)
|
||||
|
||||
self.axs[2].set_ylabel("Excitation Magnitude")
|
||||
self.axs[2].stem(element_position, element_taper)
|
||||
# self.axs[2].set_xlabel("Element")
|
||||
|
||||
|
||||
# %%
|
||||
def generate():
|
||||
for elements in [
|
||||
1,
|
||||
2,
|
||||
4,
|
||||
10,
|
||||
]:
|
||||
PcolorPhasePlot(elements=elements, angle_deg=45).save(dir_assets / "beamforming" / f"phase_xz_{elements}el.gif")
|
||||
PcolorMagPlot(elements=elements, angle_deg=45).save(
|
||||
dir_assets / "beamforming" / f"magnitude_xz_{elements}el.gif"
|
||||
)
|
||||
# for elements in [
|
||||
# 1,
|
||||
# 2,
|
||||
# 4,
|
||||
# 10,
|
||||
# ]:
|
||||
# PcolorPhasePlot(elements=elements, angle_deg=45).save(dir_assets / "beamforming" / f"phase_xz_{elements}el.gif")
|
||||
# PcolorMagPlot(elements=elements, angle_deg=45).save(
|
||||
# dir_assets / "beamforming" / f"magnitude_xz_{elements}el.gif"
|
||||
# )
|
||||
Steer(elements=16, spacing_lambda=0.5, frames=200).save(dir_assets / "beamforming" / "steering.gif", framerate=15)
|
||||
|
||||
|
||||
# %%
|
||||
|
@ -67,3 +67,28 @@ class AnimatedPlot(ABC):
|
||||
[0, 1]
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def db20(v):
|
||||
return 20 * np.log10(np.abs(v))
|
||||
|
||||
|
||||
def db10(v):
|
||||
return 10 * np.log10(np.abs(v))
|
||||
|
||||
|
||||
def db2v(db):
|
||||
return 10 ** (db / 20)
|
||||
|
||||
|
||||
def db2w(db):
|
||||
return 10 ** (db / 10)
|
||||
|
||||
|
||||
def wrap_phase(phase, deg: bool):
|
||||
if deg:
|
||||
maxval = 180
|
||||
else:
|
||||
maxval = np.pi
|
||||
|
||||
return (phase + maxval) % (2 * maxval) - maxval
|
||||
|
Loading…
x
Reference in New Issue
Block a user