NVlabs / sionna

Sionna: An Open-Source Library for Next-Generation Physical Layer Research
https://nvlabs.github.io/sionna
Other
811 stars 230 forks source link

Using Sionna for synthetic aperture radar simulation: variance in path propagation delays #448

Closed adeschemps closed 5 months ago

adeschemps commented 5 months ago

Hello, first and foremost, thanks to Sionna's authors for this amazing tool. I would like to use it for synthetic aperture radar (SAR) simulations. I am aware that radar simulations is not exactly within Sionna planned scope, but I would like to know if there is hope for my experiment or not. In synthetic aperture radar, for a single point reflector, the received signal exhibits a quadratic phase in the azimuth dimension as the platform moves through the synthetic aperture, because the range to the target first decreases (until the point of closest approach) then increases. As a first sanity check, I would like to check wether or not this is true with the raytracing component of Sionna. I wrote the following code, which is as close to the scattering tutorial as possible:

from sionna.rt import load_scene, PlanarArray, Transmitter, Receiver
from sionna.constants import SPEED_OF_LIGHT, PI
import sionna

import matplotlib.pyplot as plt
import tensorflow as tf
import numpy as np 

from tqdm import tqdm

CPI_length=64
aperture_size = 100 
dist=500 

scene = load_scene(sionna.rt.scene.simple_reflector)
scene.frequency = 10e9

for object in scene.objects:

    scene.get(object).radio_material.scattering_coefficient = 0.5

# Configure the transmitter and receiver arrays
scene.tx_array = PlanarArray(num_rows=1,
                             num_cols=1,
                             vertical_spacing=0.5,
                             horizontal_spacing=0.5,
                             pattern="iso",
                             polarization="V")

scene.rx_array = scene.tx_array

scene.add(Transmitter(name="tx", position=[0,0,0]))
scene.add(Receiver(name="rx", position=[0,0,0]))

x_pos = np.linspace(-aperture_size*0.5, aperture_size*0.5, CPI_length)
y_pos, z_pos = np.ones(CPI_length)*(dist / np.sqrt(2)), np.ones(CPI_length)*(dist / np.sqrt(2))
radar_trajectory = np.array([x_pos, y_pos, z_pos]).T 

mean_tau, range_ = [], []

with tqdm(range(CPI_length)) as pbar:

    for pulse in pbar:

        scene.transmitters["tx"].position = radar_trajectory[pulse]
        scene.receivers["rx"].position = radar_trajectory[pulse] 
        scene.transmitters["tx"].look_at([0,0,0])
        scene.receivers["rx"].look_at([0,0,0]) 

        paths = scene.compute_paths(los=False, 
                                    reflection=True, 
                                    scattering=True,
                                    scat_random_phases=False,
                                    scat_keep_prob=1.0,
                                    num_samples=1e7,
                                    max_depth=1)
        paths.normalize_delays=False
        ai, tau = paths.cir()

        mean_tau.append(tf.reduce_mean(tau).numpy())
        range_.append(np.linalg.norm(radar_trajectory[pulse]))

fig, ax = plt.subplots(figsize=(16,27), nrows=3)

ax[0].plot(np.array(range_))
ax[0].grid()
ax[0].set_title("theoretical quadratic range to reflector")
ax[0].set_xlabel("pulse index (azimuth dimension)")
ax[0].set_ylabel("range to reflector (meters)")

ax[1].plot(0.5*np.array(mean_tau)*SPEED_OF_LIGHT)
ax[1].set_title("average length of ray to reflector")
ax[1].grid()
ax[1].set_xlabel("pulse index (azimuth dimension)")
ax[1].set_ylabel("range to reflector (meters)")

# phase error caused by range error at X-band (10GHz frequency)
mean_tau, range_ = np.array(mean_tau), np.array(range_)
phase_diff = 2*PI*scene.frequency*(mean_tau - 2*range_*(1/SPEED_OF_LIGHT))

ax[2].plot(phase_diff)
ax[2].grid()
ax[2].set_title("phase difference (in radians) caused by the range between Sionna RT and theoretical range")
ax[2].set_xlabel("pulse index (azimuth dimension)")
ax[2].set_ylabel("phase difference (radians)")

plt.savefig("sionna_sanity_check.png", bbox_inches="tight")
plt.close()

After running this I get the following plot: sionna_sanity_check which shows a significant difference between the theoretical quadratic range and the average length of rays to the reflector. While those differences are small with respect to the overall length of the ray (less than 10cm over a 500m long ray), the carrier frequency term in the propagation phase of the SAR signal model leads to large differences in phase between both range models.

Is this an intrinsic issue with the inner workings of sionna and mitsuba which is not easily fixable or is there something that I can do to reduce this range "error" ?

Thanks in advance to anybody who can provide insight into this issue. Please ask if anything is unclear.

faycalaa commented 5 months ago

Hi, I think that you observe this noise because (i) the reflector has a surface area of 1m2, leading to different scattered paths having different delays, and (ii) because of the high distance between the radar and the reflector, you get a very little number of paths which is not enough to average out the noise due to the varying delays.

By reducing the distance between the radar and the reflector (I reduced dist to 50m), I obtained a significantly higher number of paths leading to less noisy distance estimate.