# 🚨 The Isotropic Illumination Problem — Why Shenron Cannot See the Car **Date:** 2026-04-14 **Engineer:** Fox ADAS Pipeline | Antigravity AI **Status:** 🔴 CRITICAL — Root Cause Identified, Implementation Deferred **Prerequisite Reading:** [Shenron_debug.md](./Shenron_debug.md) (Iterations 01–26) --- ## Executive Summary After 30+ iterations of calibrating RCS physics, fixing coordinate bugs, tuning CFAR thresholds, adjusting gain, and increasing ray density, the **AWRL1432 radar still cannot reliably detect a vehicle at 25m in a straight-line braking scenario.** The root cause is **not** in the signal processing, the CFAR threshold, or the gain. It is a fundamental architectural omission in the Shenron physics engine: > **Shenron does not simulate the radar's antenna radiation pattern.** > Every scatterer in the scene — whether it's at 0° (directly ahead) or at 80° (a distant wall) — receives and returns energy as if it were perfectly on boresight. This single missing physics element explains **why 30 iterations of downstream tuning have failed to reliably produce the car as a detection**, and why the Radarbook (with 8 vRx) sometimes succeeds where the 1432 (6 vRx) consistently fails. --- ## The Evidence ### Diagnostic Script Output (`track_full_state.py`) The following table shows where the **strongest peak** in each radar's Range-Doppler map is located: | Frame | Radar | Range (m) | **Angle (deg)** | Magnitude (dB) | | :--- | :--- | :--- | :--- | :--- | | 6 | **1432** | 20.76 | **76.57°** | 138.5 | | 6 | R-Book | 20.39 | **-84.93°** | 142.4 | | 8 | **1432** | 20.76 | **76.57°** | 142.0 | | 8 | R-Book | 20.39 | **73.14°** | 142.0 | | 14 | **1432** | 7.65 | **69.00°** | 135.5 | | 14 | R-Book | 20.39 | **-84.93°** | 141.7 | **The car is at 0° azimuth (straight ahead).** Yet the strongest detection is consistently at **70–85°** — far off to the side. This is because the side-clutter (barriers, walls, trees at those wide angles) is returning the **same power** as the car, since Shenron treats all angles equally. ### Visual Confirmation (Range-Azimuth Heatmap) The RA heatmap from the dashboard shows **complete, uniform energy rings** extending from -90° to +90°. In a real radar, you would see a focused **120° sector** with significant energy roll-off beyond ±60°. --- ## Why Previous Iterations Could Not Fix This Looking back at the iteration history, here is what each major tuning attempt was actually fighting against: | Iteration | What We Tried | Why It Felt Like It Worked | Why It Didn't Actually Fix It | | :--- | :--- | :--- | :--- | | **10** | Metal Roughness tuning | Reduced some specular reflections | Clutter at 80° was still as loud as car at 0° | | **14a** | **Vertical** Gaussian Damping | Killed ceiling/floor clutter by 90% | Only addressed **elevation**. Azimuthal clutter was untouched. | | **16** | Area-Density Integration (+234%) | Boosted car signal significantly | Also boosted wall/barrier signal by the same 234% | | **26** | Pure 1/R⁴ alignment | Correct physics — distance now matters | But **angle** still doesn't matter. A wall at 80° at 20m is just as "loud" as a car at 0° at 20m | | **This Session** | Gain 110→115dB, CFAR 20→15, voxel_rho 0.05→0.02 | Peak SNR rose from 15→21 dB | The peak is at 76°, not 0°. We boosted the wrong target. | > [!CAUTION] > **The fundamental issue:** Every iteration that "lifts all boats" (gain, density, normalization) lifts the **clutter equally** with the target. Without angular selectivity, the car can never be louder than the surrounding environment unless it is physically closer or has a dramatically higher RCS. --- ## The Missing Physics: Antenna Radiation Pattern ### What a Real Radar Does A real FMCW radar's patch antenna array has a **directional gain pattern**. The transmitted energy is concentrated in a forward-facing beam. A typical 77 GHz ADAS radar has: - **3dB Beamwidth (Azimuth):** ±60° (120° total) - **Gain at Boresight (0°):** Maximum (0 dB relative) - **Gain at ±60°:** -3 dB (half power) - **Gain at ±80°:** -10 to -15 dB (almost invisible) - **Gain at ±90°:** -20 dB or below (effectively blind) This means a wall at 80° would return **10–15 dB less power** than a car at 0°, even if they were at the same range with the same RCS. The car would dominate the detection. ### What Shenron Currently Does ``` Sceneset.py → get_loss_3(): # --- Iteration 14a: Vertical Antenna Gain (Gaussian Damping) --- phi_deg = np.rad2deg(np.abs(np.pi/2 - elev_angle)) G_vertical = np.exp(-2.77 * np.power(phi_deg / radar.vertical_beamwidth, 2)) P_incident = (1 / np.power(rho, tx_dist_loss_exponent)) * K_sq * G_vertical # ^^^^^^^^^^^ # Only VERTICAL gain is applied. # There is NO horizontal/azimuthal gain. ``` The `P_incident` calculation includes: - ✅ **Distance decay** (`1/R²`) — Correct - ✅ **Vertical beam pattern** (`G_vertical`) — Added in Iteration 14a - ❌ **Horizontal beam pattern** (`G_horizontal`) — **MISSING** Every LiDAR point, regardless of its azimuth angle relative to the radar boresight, receives the same transmit power. The ADC synthesis in `heatmap_gen_fast.py` then faithfully encodes these equal-power returns into the beamforming vectors, creating the uniform rings we see in the RA heatmap. --- ## The Proposed Fix ### Implementation (Single Line Addition) In `Sceneset.py`, inside `get_loss_3()`, after the vertical gain calculation: ```python # --- Iteration 14a: Vertical Antenna Gain (Gaussian Damping) --- phi_deg = np.rad2deg(np.abs(np.pi/2 - elev_angle)) G_vertical = np.exp(-2.77 * np.power(phi_deg / radar.vertical_beamwidth, 2)) # --- NEW: Horizontal Antenna Gain (Azimuthal Beam Pattern) --- # theta is computed in specularpoints() as: # theta = pi/2 - arctan(x / y) where y=forward, x=side # This means theta=pi/2 (90°) is boresight (straight ahead). # The azimuth offset from boresight is: az_offset = |pi/2 - theta| az_offset_deg = np.rad2deg(np.abs(np.pi/2 - theta_for_gain)) # degrees off boresight G_horizontal = np.exp(-2.77 * np.power(az_offset_deg / radar.horizontal_beamwidth, 2)) P_incident = (1 / np.power(rho, tx_dist_loss_exponent)) * K_sq * G_vertical * G_horizontal ``` ### ConfigureRadar.py Addition Add `self.horizontal_beamwidth` to each radar profile: | Radar | `horizontal_beamwidth` | Physical Basis | | :--- | :--- | :--- | | **awrl1432** | `60.0` (±60° = 120° total) | 6 vRx, narrow-beam ADAS profile | | **radarbook** | `90.0` (±90° = 180° total) | 8 vRx, wider research-grade beam | | **ti_cascade** | `60.0` | MIMO cascade, comparable to 1432 | ### Coordinate Note > [!WARNING] > The `theta` variable passed to `heatmap_gen` is the **angular position** of each scatterer in radar coordinates (`pi/2 - arctan(x/y)`). This is the correct variable to use for the azimuthal gain. However, it is computed in `specularpoints()` and returned alongside `rho`, `loss`, and `speed`. It is **not currently passed** to `get_loss_3()`. The fix requires either: > 1. Passing `theta` into `get_loss_3()` as a new argument, or > 2. Re-computing the azimuth angle inside `get_loss_3()` from the point coordinates. --- ## Impact Assessment: What Happens to Previous Iterations? > [!IMPORTANT] > **This is a "tide change" fix, not an additive tweak.** Once implemented, the energy landscape of the entire simulation changes fundamentally. Here is what to expect: ### Parameters That Will Likely Need Re-Tuning | Parameter | Current Value | Expected Direction | Reason | | :--- | :--- | :--- | :--- | | **Gain (dB)** | 115 | **↓ Decrease** back toward 105–110 | With clutter suppressed, the car will be the dominant target again. The current 115dB was compensating for clutter competition. | | **CFAR Threshold** | 15 | **↑ Increase** back toward 18–20 | Lower threshold was needed to "dig out" the car from equal-power clutter. With clutter gone, sensitivity can be reduced to avoid ground noise. | | **voxel_rho** | 0.02 | **↑ Increase** back toward~0.05 | Higher ray density was needed to "outpower" the clutter. With beam shaping, fewer rays on the car will still dominate. | | **Metal Roughness** (Iter 10) | 0.00005 | Likely unchanged | Material physics is orthogonal to beam pattern. | | **Z-Filter** (Iter 13) | -2.2m | Likely unchanged | Ground clutter filtering is still needed regardless of azimuth. | | **Vertical Beamwidth** (Iter 14a) | 20.0° | Likely unchanged | Elevation damping is still correct and complementary. | ### Parameters That Should Remain Stable - **Bandwidth (137.2 MHz):** Hardware-derived, not a compensation knob. - **Chirps (128):** Hardware-derived. - **Coordinate System:** Locked since Iteration 05. - **Semantic Tag Mapping:** Bug fix, not tuning. - **1/R⁴ Power Law (Iter 26):** Correct physics, complementary to beam pattern. ### The Core Prediction Once the horizontal beam pattern is implemented: 1. The car at 0° will be the **dominant detection** in Range-Doppler. The peak tracker should lock onto Range Bin 19 consistently. 2. Side-clutter at 80° will be attenuated by **~15-20 dB**, effectively removing it from CFAR contention. 3. The RA heatmap will transform from "full rings" to a **focused 120° sector** — matching what you see on real hardware. 4. **Many of the compensatory tuning parameters (gain, CFAR, voxel density) can likely be relaxed** back to more physically accurate values, because they were fighting the wrong battle. --- ## Why the Radarbook Sometimes Worked The Radarbook succeeded in some frames not because it has a beam pattern (it doesn't either), but because: 1. **8 vRx vs 6 vRx:** More antennas = narrower main lobe in the Angle-FFT output. The DSP-level beamforming partially compensates for the missing physics-level beam shaping. 2. **Higher Doppler Resolution:** With 128 chirps at a much longer `chirp_rep` (0.75ms vs 36.4µs), the Radarbook has ~3.5x better velocity resolution. This allows it to separate the (slightly) moving car from the static side-clutter in the Doppler domain, even if both are equally loud in the Range domain. The 1432, with fewer antennas and coarser Doppler bins, has no such "escape hatch." --- ## Recommended Implementation Order 1. **Implement `G_horizontal` in `get_loss_3()`** — The single most impactful change. 2. **Run Braking scenario with current settings** (115dB gain, CFAR 15, voxel 0.02) — This will likely produce a very dense, accurate point cloud because the car now has a 15-20dB advantage. 3. **Gradually relax compensatory parameters** — Bring gain back toward 110, CFAR toward 18, and voxel toward 0.05, verifying detection stability at each step. 4. **Final Calibration** — Once stable, this becomes the new "Iteration 31" baseline. --- ## Key Files for Implementation | File | Change Required | | :--- | :--- | | `scripts/ISOLATE/e2e_agent_sem_lidar2shenron_package/shenron/Sceneset.py` | Add `G_horizontal` to `get_loss_3()` | | `scripts/ISOLATE/e2e_agent_sem_lidar2shenron_package/ConfigureRadar.py` | Add `horizontal_beamwidth` to all profiles | | `scripts/ISOLATE/e2e_agent_sem_lidar2shenron_package/shenron/Sceneset.py` | Pass `theta` (or recompute azimuth) into `get_loss_3()` | --- *Generated by Antigravity AI | Fox CARLA ADAS Pipeline | 2026-04-14*