Beamforming#
This guide covers beamforming techniques including beam steering, amplitude tapering for sidelobe control, null steering for interference rejection, and multi-beam synthesis.
Beam Steering#
Basic steering points the main beam toward a desired direction by applying appropriate phase shifts to each element.
import phased_array as pa
import numpy as np
# Create array
geom = pa.create_rectangular_array(16, 16, dx=0.5, dy=0.5)
k = pa.wavelength_to_k(1.0)
# Steer to theta=30 deg, phi=45 deg
weights = pa.steering_vector(
k, geom.x, geom.y,
theta0_deg=30,
phi0_deg=45
)
# All weights have unit magnitude, varying phase
print(f"Magnitude range: {np.abs(weights).min():.2f} to {np.abs(weights).max():.2f}")
The steering vector applies phase shifts:
where \(u_0 = \sin\theta_0\cos\phi_0\) and \(v_0 = \sin\theta_0\sin\phi_0\).
Amplitude Tapering#
Amplitude tapering (windowing) reduces sidelobe levels at the cost of increased beamwidth and reduced aperture efficiency.
Taylor Taper#
Most commonly used for radar arrays. Provides specified sidelobe level with a controlled number of nearly-equal sidelobes before rolloff.
# -30 dB sidelobes, 4 nearly-equal sidelobes
taper = pa.taylor_taper_2d(16, 16, sidelobe_dB=-30, nbar=4)
# Apply to steering weights
weights = pa.steering_vector(k, geom.x, geom.y, theta0_deg=20, phi0_deg=0)
weights_tapered = weights * taper
# Check efficiency loss
efficiency = pa.compute_taper_efficiency(taper)
loss_dB = pa.compute_taper_directivity_loss(taper)
print(f"Efficiency: {efficiency:.2%}, Loss: {loss_dB:.2f} dB")
Chebyshev Taper#
Provides equi-ripple sidelobes (all sidelobes at the same level). Offers the narrowest beamwidth for a given sidelobe level.
taper = pa.chebyshev_taper_2d(16, 16, sidelobe_dB=-30)
Comparison of Tapers#
Taper |
Characteristics |
Typical Use |
Efficiency |
|---|---|---|---|
Uniform |
Narrowest beam, -13 dB SLL |
Maximum directivity needed |
100% |
Taylor |
Specified SLL, controlled rolloff |
Radar, communications |
~85-95% |
Chebyshev |
Equi-ripple sidelobes |
Minimum beamwidth for SLL |
~80-90% |
Hamming |
Good SLL, simple |
General purpose |
~73% |
Gaussian |
Very low sidelobes, no nulls |
Low-intercept radar |
~70-85% |
Example comparing tapers:
import matplotlib.pyplot as plt
tapers = {
'Uniform': np.ones(256),
'Taylor -30dB': pa.taylor_taper_2d(16, 16, sidelobe_dB=-30),
'Chebyshev -30dB': pa.chebyshev_taper_2d(16, 16, sidelobe_dB=-30),
'Hamming': pa.hamming_taper_2d(16, 16),
}
for name, taper in tapers.items():
weights = pa.steering_vector(k, geom.x, geom.y, 0, 0) * taper
theta_deg, E_plane, _ = pa.compute_pattern_cuts(geom.x, geom.y, weights, k)
plt.plot(theta_deg, E_plane, label=name)
plt.xlabel('Theta (deg)')
plt.ylabel('Pattern (dB)')
plt.legend()
plt.grid(True)
plt.ylim(-60, 0)
Null Steering#
Null steering places pattern nulls in specific directions to reject interference while maintaining gain in the desired direction.
Projection Method#
Projects the desired steering vector onto the null space of interference directions. Simple and effective for a few nulls.
# Main beam at 20 deg, nulls at 35 and 50 deg
null_directions = [(35, 0), (50, 0)]
weights = pa.null_steering_projection(
geom, k,
theta_main_deg=20,
phi_main_deg=0,
null_directions=null_directions
)
# Verify null depth
for theta_null, phi_null in null_directions:
depth = pa.compute_null_depth(geom, k, weights, (theta_null, phi_null))
print(f"Null at {theta_null} deg: {depth:.1f} dB")
LCMV Beamformer#
Linearly Constrained Minimum Variance - more flexible, allows specifying response at multiple directions.
# Constraints: (theta, phi, desired_response)
constraints = [
(20, 0, 1.0+0j), # Unity gain at 20 deg
(35, 0, 0.0+0j), # Null at 35 deg
(50, 0, 0.0+0j), # Null at 50 deg
]
weights = pa.null_steering_lcmv(
geom, k,
constraints=constraints
)
Multi-Beam Synthesis#
Generate multiple simultaneous beams for tracking multiple targets or providing spatial coverage.
Superposition Method#
Simple sum of steering vectors. Beams share the available gain.
# Beams at 15, 30, and 45 degrees
beam_directions = [(15, 0), (30, 0), (45, 0)]
weights = pa.multi_beam_weights_superposition(
geom, k,
beam_directions
)
# Each beam is ~3 dB below single-beam gain
Orthogonal Beams#
Minimizes inter-beam coupling using orthogonalization.
weights_list = pa.multi_beam_weights_orthogonal(
geom, k,
beam_directions
)
# Returns list of weight vectors, one per beam
# Beams are designed to be orthogonal to each other
# Check beam isolation
isolation = pa.compute_beam_isolation(geom, k, weights_list, beam_directions)
print(f"Beam isolation: {isolation:.1f} dB")
Monopulse Patterns#
Sum and difference patterns for angle tracking.
weights_sum, weights_diff = pa.monopulse_weights(
geom, k,
theta0_deg=20,
phi0_deg=0,
plane='azimuth' # or 'elevation'
)
# Sum pattern: conventional beam
# Difference pattern: null on axis, used for tracking
Applying Tapers to Arbitrary Geometries#
For non-rectangular arrays, use apply_taper_to_geometry:
# Create elliptical array
geom = pa.create_elliptical_array(a=4, b=3, dx=0.5)
# Apply taper based on position
weights = pa.apply_taper_to_geometry(
geom,
taper_type='taylor',
sidelobe_dB=-30
)
Best Practices#
Start with Taylor taper for most applications - good balance of beamwidth and sidelobe control.
Use nbar >= 4 for Taylor tapers to avoid excessive beamwidth increase.
Verify null depths after null steering - finite array size limits achievable null depth.
Consider efficiency loss when selecting tapers - aggressive sidelobe control can cost 2-3 dB of directivity.
For multi-beam, check isolation between beams when directions are close.