import radarsimpy
print("`RadarSimPy` used in this example is version: " + str(radarsimpy.__version__))
`RadarSimPy` used in this example is version: 15.2.0
Radar Cross Section (RCS) of a Corner Reflector¶
A corner reflector (trihedral reflector) consists of three mutually perpendicular conducting surfaces. Incident radar waves undergo triple-bounce reflections, returning directly to the source over a wide range of angles — making it an ideal calibration target with a large, stable, predictable RCS.
Theoretical maximum RCS for edge length $a$:
$$\sigma_{max} = \frac{4\pi a^4}{3\lambda^2}$$
Key properties:
- RCS ∝ $a^4$ (edge length to the fourth power)
- RCS ∝ $f^2$ (frequency squared, since λ = c/f → expect +20 dB/decade)
- Wide retroreflective beamwidth (~40–60° for trihedral)
- Polarization-preserving: triple bounce maintains incident polarization
Applications: radar calibration, SAR ground control points, marine navigation aids, controlled reference targets for algorithm validation.
This Example¶
- Target: Trihedral corner reflector 3D model (STL)
- Frequency sweep: 1–79 GHz → observe f² RCS growth
- Angular sweep: −90° to +90° azimuth at 77 GHz → characterize beamwidth
3D Model Loading¶
Import Required Modules¶
import pymeshlab
import numpy as np
import plotly.graph_objs as go
from IPython.display import Image, display
# Set to True for interactive plots; False renders a static JPEG (e.g. for HTML export)
INTERACTIVE = False
def show(fig):
if INTERACTIVE:
fig.show()
else:
display(Image(fig.to_image(format="jpg", scale=2)))
target = {
"model": "../models/cr.stl",
"unit": "m",
"location": (0, 0, 0),
}
Visualize 3D Model¶
Display the trihedral structure to verify the three mutually perpendicular surfaces that produce retroreflection.
ms = pymeshlab.MeshSet()
ms.load_new_mesh(target["model"])
t_mesh = ms.current_mesh()
v_matrix = np.array(t_mesh.vertex_matrix())
f_matrix = np.array(t_mesh.face_matrix())
fig = go.Figure()
fig.add_trace(
go.Mesh3d(
x=v_matrix[:, 0],
y=v_matrix[:, 1],
z=v_matrix[:, 2],
i=f_matrix[:, 0],
j=f_matrix[:, 1],
k=f_matrix[:, 2],
intensity=v_matrix[:, 2],
colorscale="Viridis",
)
)
fig["layout"]["scene"]["aspectmode"] = "data"
fig["layout"]["scene"]["camera"] = {"eye": {"x": -1.5, "y": -1.5, "z": 1.25}}
fig["layout"]["height"] = 500
fig["layout"]["margin"] = dict(l=5, r=0, b=10, t=10)
show(fig)
RCS vs Frequency¶
Sweep 1–79 GHz at boresight (φ = 0°, θ = 90°) to verify the $f^2$ (20 dB/decade) frequency dependence predicted by theory. High ray density (density=10) is used for accuracy since physical optics improves at higher electrical size.
| Parameter | Value |
|---|---|
| Frequency | 1–79 GHz, 1 GHz steps |
| Azimuth φ | 0° (boresight) |
| Elevation θ | 90° |
| Polarization | [0, 1, 0] (horizontal) |
| Ray density | 10 rays/λ² |
# Import time module for performance measurement
import time
# Import RCS simulation function
from radarsimpy.simulator import sim_rcs
# Define observation angles (boresight configuration)
phi = 0 # Azimuth: 0° (looking into corner)
theta = 90 # Elevation: 90° (horizontal plane)
# Frequency sweep parameters
freq = np.arange(1, 79, 1) * 1e9 # 1-79 GHz in 1 GHz steps
# Radar configuration
pol = [0, 1, 0] # Horizontal polarization
density = 10 # High ray density for accuracy (10 rays per λ)
# Initialize RCS array
rcs = np.zeros_like(freq)
# Start timing
tic = time.time()
# Compute RCS for each frequency
for f_idx, f in enumerate(freq):
# Simulate RCS and convert to dBsm
rcs[f_idx] = 10 * np.log10(sim_rcs([target], f, phi, theta, pol, density=density))
# End timing
toc = time.time()
# Display execution time
print("Exec time: " + str(toc - tic) + " s")
Exec time: 1.1381280422210693 s
Visualize RCS vs Frequency¶
The slope should approach +20 dB/decade (10× frequency → 100× RCS). Deviations at low frequencies occur where the physical optics approximation becomes less accurate (target size ≈ λ).
fig = go.Figure()
fig.add_trace(go.Scatter(
x=freq / 1e9,
y=rcs,
mode='lines+markers',
name='Simulated RCS',
))
fig.update_layout(
title="Corner Reflector RCS vs Frequency (Horizontal Polarization)",
yaxis=dict(title="RCS (dBsm)"),
xaxis=dict(title="Frequency (GHz)", dtick=10),
height=500,
)
show(fig)
RCS vs Observation Angle¶
At 77 GHz, sweep φ from −90° to +90° to characterize the retroreflective beamwidth. Lower ray density (density=1) is sufficient here since the angular pattern is smoother than the frequency response.
| Parameter | Value |
|---|---|
| Frequency | 77 GHz |
| Azimuth φ | −90° to +90°, 0.5° steps |
| Elevation θ | 90° (fixed) |
| Polarization | [0, 0, 1] (vertical) |
| Ray density | 1 ray/λ² |
Expect a symmetric peak at 0° with a −3 dB beamwidth of ~40–60°, dropping rapidly outside the main lobe.
# Define angular sweep parameters
phi = np.arange(-90, 90, 0.5) # Azimuth angles: -90° to +90° in 0.5° steps
theta = np.zeros_like(phi) + 90 # Elevation: fixed at 90° (horizontal plane)
# Radar configuration for angular analysis
freq = 77e9 # Operating frequency: 77 GHz (automotive radar)
pol = [0, 0, 1] # Vertical polarization
density = 1 # Ray density: 1 ray per λ² (faster computation)
# Start timing
tic = time.time()
# Simulate RCS for all observation angles
# Single function call is more efficient than loop
rcs = 10 * np.log10(sim_rcs([target], freq, phi, theta, pol, density=density))
# End timing
toc = time.time()
# Display execution time
print("Exec time: " + str(toc - tic) + " s")
Exec time: 0.1382312774658203 s
Visualize Angular Response¶
The dashed red line marks the −3 dB point below peak RCS for easy beamwidth measurement. The pattern should be symmetric about 0° due to the corner's geometry.
fig = go.Figure()
fig.add_trace(go.Scatter(x=phi, y=rcs, mode='lines', name='RCS Pattern'))
fig.update_layout(
title="Corner Reflector RCS vs Observation Angle (77 GHz, Vertical Pol)",
yaxis=dict(title="RCS (dBsm)"),
xaxis=dict(title="Azimuth Angle (Degrees)", dtick=20),
height=500,
)
show(fig)
Summary¶
- Corner reflector RCS grows as $f^2$ (+20 dB/decade) — confirmed by the frequency sweep.
- The retroreflective beamwidth is ~40–60° (wide enough for easy field alignment).
- High ray density is needed for accurate frequency-sweep results; lower density suffices for angular patterns.
- Triple-bounce geometry preserves polarization, making the corner reflector a clean calibration reference.
Things to Try¶
| Experiment | Parameter to change | Observable effect |
|---|---|---|
| Scale the geometry | Load larger/smaller STL | RCS shifts by $a^4$ |
| Higher frequency | Extend freq to 94 GHz |
Continued f² growth |
| Horizontal polarization | pol = [0, 1, 0] |
Compare with vertical pol |
| Full 3D pattern | Vary both φ and θ | 2D RCS heatmap |
| Ray density test | Compare density = 1 vs 10 | Accuracy vs speed trade-off |