import radarsimpy
print("`RadarSimPy` used in this example is version: " + str(radarsimpy.__version__))
`RadarSimPy` used in this example is version: 15.2.0
RCS Polarimetry: Co-Pol vs. Cross-Pol¶
Radar polarization describes the orientation of the electric field vector. Common polarization states:
| State | Symbol | Electric Field |
|---|---|---|
| Vertical | V | Along elevation axis |
| Horizontal | H | Along azimuth axis |
| Left circular | LHCP | Rotating CCW (from receiver) |
| Right circular | RHCP | Rotating CW (from receiver) |
In polarimetric radar, the scattering matrix $[S]$ relates incident and scattered fields across all polarization combinations:
$$\begin{bmatrix} E_V^s \\ E_H^s \end{bmatrix} = \begin{bmatrix} S_{VV} & S_{VH} \\ S_{HV} & S_{HH} \end{bmatrix} \begin{bmatrix} E_V^i \\ E_H^i \end{bmatrix}$$
- Co-pol ($S_{VV}$, $S_{HH}$): transmit and receive with the same polarization
- Cross-pol ($S_{VH}$, $S_{HV}$): transmit one, receive the orthogonal
Corner reflector polarimetric behavior:
A trihedral corner reflector undergoes triple bounce, which preserves the incident polarization — so the co-pol RCS is large, and cross-pol is much smaller. The co-pol to cross-pol ratio (CDR) is a key polarimetric purity metric.
This Example¶
- Target: Trihedral corner reflector (STL)
- Frequency: 77 GHz
- Sweep: 0° to 360° azimuth
- VV (Co-pol): transmit V, receive V
- VH (Cross-pol): transmit V, receive H
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¶
The three mutually perpendicular surfaces of the trihedral corner reflector are visible — these produce the triple-bounce that preserves polarization.
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)
Polarimetric RCS Simulation¶
Two simulations at 77 GHz, sweeping 0°–360° azimuth, using the same geometry but different receive polarizations.
| Parameter | Value |
|---|---|
| Frequency | 77 GHz |
| Azimuth φ | 0°–360°, 1° steps |
| Elevation θ | 90° (fixed) |
| TX polarization | [0, 0, 1] (vertical, V) |
| RX polarization (Co-pol) | [0, 0, 1] → $S_{VV}$ |
| RX polarization (Cross-pol) | [0, 1, 0] → $S_{VH}$ |
| Ray density | 1 ray/λ² |
Expected results:
- $S_{VV}$ (Co-pol): large RCS in sectors where the corner faces the radar; symmetric pattern with ~3-fold rotational symmetry from the trihedral geometry
- $S_{VH}$ (Cross-pol): substantially lower RCS (15–25 dB below co-pol) — a signature of the triple-bounce polarization-preserving mechanism
# Import time module for performance measurement
import time
# Import RCS simulation function
from radarsimpy.simulator import sim_rcs
# Define observation angles
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 plane)
# Radar configuration
freq = 77e9 # Operating frequency: 77 GHz (automotive radar)
pol = [0, 0, 1] # Incident polarization: Vertical
pol_obs = [0, 1, 0] # Observation polarization for cross-pol: Horizontal
density = 3 # Ray density: 3 rays per wavelength²
# Start timing
tic = time.time()
# Simulate co-polarization RCS (VV: Vertical → Vertical)
# When obs_pol is not specified, it defaults to same as incident pol
co_rcs = 10 * np.log10(
sim_rcs([target], freq, phi, theta, pol, density=density)
)
# Simulate cross-polarization RCS (VH: Vertical → Horizontal)
# obs_pol parameter specifies different receive polarization
cross_rcs = 10 * np.log10(
sim_rcs([target], freq, phi, theta, pol, obs_pol=pol_obs, density=density)
)
# End timing
toc = time.time()
# Display execution time
print("Exec time: " + str(toc - tic) + " s")
Exec time: 1.1097238063812256 s
Visualize Polarimetric RCS¶
The co-pol (VV) pattern will show the trihedral's characteristic azimuthal lobes. The cross-pol (VH) response will be significantly lower — the gap between the two curves is the co-pol/cross-pol discrimination ratio.
fig = go.Figure()
fig.add_trace(go.Scatter(x=phi, y=co_rcs, mode='lines', name="Co-Pol (VV)"))
fig.add_trace(go.Scatter(x=phi, y=cross_rcs, mode='lines', name="Cross-Pol (VH)"))
fig.update_layout(
title="Polarimetric RCS: Co-Pol vs Cross-Pol (77 GHz)",
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)
Summary¶
- Trihedral corner reflectors preserve incident polarization (triple bounce) → high co-pol RCS, low cross-pol.
- The scattering matrix $[S]$ captures all polarimetric combinations; this example measures $S_{VV}$ and $S_{VH}$.
- VH/VV ratio quantifies polarimetric purity — useful for evaluating calibration target quality.
Things to Try¶
| Experiment | Parameter to change | Observable effect |
|---|---|---|
| HH co-pol | RX pol = [0, 1, 0], TX pol = [0, 1, 0] |
Should match VV for a symmetric target |
| HV cross-pol | TX [0, 1, 0], RX [0, 0, 1] |
Compare with VH (should be similar) |
| Circular polarization | TX/RX pol = [1/√2, 1j/√2, 0] |
Cross-pol level changes dramatically |
| Different frequency | Change freq to 24 GHz | Same qualitative pattern, different magnitude |
| Dihedral corner | Load a 2-bounce geometry | Dominant cross-pol due to double bounce |