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 5 m × 5 m Flat Plate¶
A flat conducting plate is a canonical scatterer with a well-known analytical solution. It is fundamental for validating simulation tools and understanding specular reflection.
Theoretical RCS at normal incidence for a rectangular plate $L_x \times L_y$:
$$\sigma_{max} = \frac{4\pi L_x^2 L_y^2}{\lambda^2}$$
For this 5 m × 5 m plate at 1 GHz (λ = 0.3 m): $\sigma_{max} \approx 45.4$ dBsm.
The RCS falls off rapidly with angle from broadside — a narrow main lobe because the plate is electrically large (~17λ at 1 GHz).
Monostatic vs. Bistatic:
- Monostatic: TX and RX co-located; maximum RCS at normal incidence.
- Bistatic: TX and RX at separate locations; peak RCS when the observation angle mirrors the incidence angle (specular condition).
Material effects:
- PEC (Perfect Electric Conductor): 100% reflection — maximum possible RCS.
- Dielectric (e.g., glass, εᵣ = 5): Partial reflection via Fresnel equations → reduced RCS.
This Example¶
- Target: 5 m × 5 m flat plate (STL)
- Monostatic: PEC vs. glass (εᵣ = 5) at 1 GHz, vertical polarization
- Bistatic: V-pol vs. H-pol, incident at 45°, 1 GHz
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)))
model_path = "../models/plate5x5.stl"
Visualize 3D Model¶
Display the plate geometry. The plate lies in the XY plane, with normal along Z.
ms = pymeshlab.MeshSet()
ms.load_new_mesh(model_path)
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)
Monostatic RCS¶
In monostatic configuration the incident and observation angles are identical. Both PEC and glass targets are simulated and compared.
| Parameter | Value |
|---|---|
| Frequency | 1 GHz (L-band, λ = 0.3 m) |
| Azimuth φ | −90° to +90°, 0.5° steps |
| Elevation θ | 90° (fixed) |
| Polarization | [0, 0, 1] (vertical) |
| Ray density | 4 rays/λ² |
- PEC: ideal metal, no
permittivitykey → defaults to perfect conductor - Glass:
permittivity = 5(εᵣ = 5, partial reflection)
# Import time module for performance measurement
import time
# Import RCS simulation function
from radarsimpy.simulator import sim_rcs
# Define observation angles for monostatic configuration
phi = np.arange(-90, 90, 0.5) # Azimuth: -90° to +90° in 0.5° steps
theta = np.zeros_like(phi) + 90 # Elevation: fixed at 90° (horizontal)
# Radar parameters
freq = 1e9 # Frequency: 1 GHz (L-band)
pol = [0, 0, 1] # Vertical polarization
density = 4 # Ray density: 4 rays per wavelength²
# Target configuration 1: Perfect Electric Conductor (PEC)
target_pec = {
"model": model_path,
"unit": "m",
"location": (0, 0, 0),
# No permittivity specified → defaults to PEC
}
# Target configuration 2: Glass plate with dielectric properties
target_glass = {
"model": model_path,
"unit": "m",
"location": (0, 0, 0),
"permittivity": 5, # Relative permittivity εᵣ = 5 (typical glass)
}
# Start timing
tic = time.time()
# Simulate RCS for PEC plate
# Add small constant (1e-6) to avoid log10(0) for nulls
rcs_pec = 10 * np.log10(
sim_rcs([target_pec], freq, phi, theta, pol, density=density) + 0.000001
)
# Simulate RCS for glass plate
rcs_glass = 10 * np.log10(
sim_rcs([target_glass], freq, phi, theta, pol, density=density) + 0.000001
)
# End timing
toc = time.time()
# Display execution time
print("Exec time: " + str(toc - tic) + " s")
Exec time: 0.709101676940918 s
Visualize Monostatic RCS¶
Expect a sharp peak at 0° (broadside) for both materials, with PEC ~10–15 dB higher than glass. The narrow main lobe (~3–4°) results from the large electrical size (5 m / 0.3 m ≈ 17λ).
fig = go.Figure()
fig.add_trace(go.Scatter(x=phi, y=rcs_pec, mode='lines', name="PEC (Perfect Conductor)"))
fig.add_trace(go.Scatter(x=phi, y=rcs_glass, mode='lines', name="Glass (εᵣ = 5)"))
fig.update_layout(
title="Monostatic RCS vs Observation Angle (1 GHz, Vertical Polarization)",
yaxis=dict(title="RCS (dBsm)"),
xaxis=dict(title="Azimuth Angle φ (Degrees)", dtick=20),
height=500,
legend=dict(x=0.02, y=0.98),
)
show(fig)
Bistatic RCS¶
In the bistatic case, the transmitter is fixed at 45° incidence (φ = 45°) and the receiver scans −90° to +90°. Both V-pol and H-pol are compared.
The specular reflection condition is: $$\phi_{scatter} = -\phi_{incident} \quad (\text{Snell's law in reflection})$$
So for a 45° incident wave, the specular peak appears at −45° in the bistatic angle sweep.
| Parameter | Value |
|---|---|
| Frequency | 1 GHz |
| Incident azimuth φ | 45° |
| Scatter azimuth | −90° to +90°, 0.5° steps |
| Elevation θ | 90° (fixed) |
| Ray density | 4 rays/λ² |
# Define observation angles for bistatic configuration
obs_phi = np.arange(-90, 90, 0.5) # Observation azimuth sweep
obs_theta = 90 # Observation elevation (horizontal)
# Radar parameters
freq = 1e9 # Frequency: 1 GHz
pol = [0, 1, 0] # Will be overridden in sim_rcs calls
density = 1 # Ray density: 1 ray per λ² (faster for bistatic)
# Initialize RCS arrays for two polarizations
rcs_vpol = np.zeros_like(obs_phi) # Vertical polarization results
rcs_hpol = np.zeros_like(obs_phi) # Horizontal polarization results
# Fixed incident wave direction
inc_phi = 45 # Incident azimuth: 45° (illumination from side)
inc_theta = 90 # Incident elevation: 90° (horizontal)
# Target configuration (PEC only)
target_pec = {
"model": model_path,
"location": (0, 0, 0),
}
# Start timing
tic = time.time()
# Loop through each observation angle
for phi_idx, phi_ang in enumerate(obs_phi):
# Simulate bistatic RCS with vertical incident polarization
rcs_vpol[phi_idx] = 10 * np.log10(
sim_rcs(
[target_pec],
freq,
inc_phi=inc_phi, # Incident azimuth
inc_theta=inc_theta, # Incident elevation
inc_pol=[0, 0, 1], # Vertical polarization
obs_phi=phi_ang, # Observation azimuth (varies)
obs_theta=obs_theta, # Observation elevation
density=density,
)
+ 0.0000001 # Avoid log10(0)
)
# Simulate bistatic RCS with horizontal incident polarization
rcs_hpol[phi_idx] = 10 * np.log10(
sim_rcs(
[target_pec],
freq,
inc_phi=inc_phi,
inc_theta=inc_theta,
inc_pol=[0, 1, 0], # Horizontal polarization
obs_phi=phi_ang,
obs_theta=obs_theta,
density=density,
)
+ 0.0000001
)
# End timing
toc = time.time()
# Display execution time
print("Exec time: " + str(toc - tic) + " s")
Exec time: 1.5223045349121094 s
Visualize Bistatic RCS¶
The specular peak at −45° is marked with an annotation. V-pol and H-pol have different Fresnel reflection coefficients, resulting in different RCS levels and null positions.
fig = go.Figure()
fig.add_trace(go.Scatter(x=obs_phi, y=rcs_vpol, mode='lines', name="Vertical Polarization"))
fig.add_trace(go.Scatter(x=obs_phi, y=rcs_hpol, mode='lines', name="Horizontal Polarization"))
fig.add_vline(
x=-45,
line_dash="dot",
line_color="gray",
annotation_text="Specular (-45°)",
annotation_position="top",
)
fig.update_layout(
title="Bistatic RCS vs Observation Angle (Incident: 45°, 1 GHz)",
yaxis=dict(title="RCS (dBsm)"),
xaxis=dict(title="Observation Angle φ (Degrees)", dtick=20),
height=500,
)
show(fig)
Summary¶
- Flat plate RCS peaks sharply at broadside; PEC gives maximum RCS, glass (εᵣ = 5) gives ~10–15 dB lower.
- Bistatic RCS peaks at the specular angle (−45° for 45° incidence); V-pol and H-pol differ due to Fresnel coefficients.
- The simulated peak closely matches the theoretical value: $\sigma_{max} = 4\pi L_x^2 L_y^2 / \lambda^2$.
Things to Try¶
| Experiment | Parameter to change | Observable effect |
|---|---|---|
| Different frequency | 3 GHz or 10 GHz | Main lobe narrows; peak RCS increases with f² |
| Higher permittivity | permittivity = 10 |
RCS approaches PEC |
| Tilt the plate | Rotate mesh about X/Y axis | Specular lobe shifts |
| Bistatic incidence angle | Change incident φ from 45° | Specular peak moves accordingly |
| Circular polarization | pol = [1/√2, 1j/√2, 0] |
Different polarimetric signature |