Main Content

Radar Sensing with Reconfigurable Intelligent Surfaces (RIS)

Since R2024b

Introduction

Reconfigurable intelligent surface (RIS) is a key technology for future wireless systems, such as 6G. An RIS is a rectangular plane formed with many reflecting elements. As the name suggests, elements in an RIS can be individually configured to achieve the desired reflection pattern. Because of this capability, RISs can be deployed in an RF environment to improve the propagation channel, especially when a line-of-sight (LOS) link is not available. This is particularly useful for 6G and future wireless systems as these systems are aiming at mmWave band and beyond, in which the multipath propagation is so weak that the link relies on the LOS path. In the Introduction to Reconfigurable Intelligent Surfaces (RIS) example, we showed how an RIS can help maintain a wireless communication link under such situations.

Because the spectrum resources are so precious, future wireless systems are expected to perform multiple functions. In addition to the regular communication tasks, the future wireless systems will also be capable of performing sensing tasks. For example, human activity monitoring is a popular application area for radar in 60 GHz band. This example shows how a RIS can help improve target detection when the target is outside a radar's field of view.

Scene Setup

Consider a scene shown in the following diagram, where there is a radar in one room and a person in a separate room. Depending on the material, the wall that separates the two rooms could introduce significant propagation loss that effectively blocks the direct path between the radar and the person.

RISSensingSetup.png

To model this scene, assume the radar is at the origin. The radar operates at 60 GHz, which is a popular band for healthcare applications.

fc = 60e9;
c = physconst('lightspeed');
lambda = c/fc;
pos_trx = [0;0;3];
vel_trx = [0;0;0];
plat_trx = phased.Platform('InitialPosition',pos_trx,'Velocity',vel_trx,'OrientationAxesOutputPort',true);

The radar is equipped with an 8-element ULA. To model such a scene, the array is formed with elements whose pattern has a uniform illumination within a 120-degree sector. Since we do not model the wall explicitly, such an idealized pattern is used to make sure the person is outside the radar's field of view that there is no direct path between the radar and the target. As a result, the resulting array pattern's field of view is also about 120 degrees.

antelement = phased.CustomAntennaElement('MagnitudePattern',-inf(181,361));
antelement.MagnitudePattern(:,121:241) = 0;
Ntrx = 8;
antarray = phased.ULA('NumElements',Ntrx,'ElementSpacing',lambda/2,'Element',antelement);

clf;
patternAzimuth(antarray,fc,'Type','powerdb');

Figure contains an axes object. The hidden axes object contains 3 objects of type line, text. This object represents 60 GHz .

The human is modeled as a point target with an RCS of 1 square meter.

human = phased.RadarTarget('MeanRCS',1,'OperatingFrequency',fc,'PropagationSpeed',c);
pos_human = [3;10;0]; 
speed_human_mph = 6;
vel_human = speed_human_mph*1600/3600*[1/sqrt(2);1/sqrt(2);0];
plat_human = phased.Platform('InitialPosition',pos_human,'Velocity',vel_human,'OrientationAxesOutputPort',true);

RIS Setup

From the diagram, we can see that the target is out of the radar's field of view. Therefore, there is no LOS path available, and the radar cannot detect the target. To improve the detectability, we can add more radars into the scene so at least one direct path will be available between the target and a radar. However, such a configuration requires multiple radars and can be costly. On the other hand, RIS, as an emerging technique that can modify the propagation environment, provides an alternative approach to solve such issues. RIS is normally passive, thus requiring no expensive TR modules. By adopting the RIS at the correct location, the target can be detected even without a LOS path.

An RIS needs to have enough elements, at least hundreds of them according to the literature, to provide enough gain to compensate for the loss in a non-line-of-sight (NLOS) path. This example uses a RIS with a 20-by-20 array, which is 400 elements in total. Each element in the surface is a reflector antenna. At 60 GHz, such a surface can fit into a 10-by-10 square centimeters space, so it is very feasible. For more information about the element, please refer to the Electromagnetic Analysis of Intelligent Reflecting Surface (Antenna Toolbox) example. The RIS is placed within the radar's field of view facing the radar so the transmitted signal can bounce off the RIS and reach the target.

riselement = design(reflector,fc);
riselement.Spacing = lambda/2;
riselement.GroundPlaneLength = 0.5*lambda;
riselement.GroundPlaneWidth = 0.5*lambda;
riselement.TiltAxis = [1 0 0];
riselement.Tilt = 90;
Nr_ris = 20;
Nc_ris = 20;
ris = helperRISSurface('Size',[Nr_ris Nc_ris],'ElementSpacing',[lambda/2 lambda/2],'OperatingFrequency',fc,'ReflectorElement',riselement);

pos_ris = [10;5;3];
vel_ris = [0;0;0];
plat_ris = phased.Platform('InitialPosition',pos_ris,'Velocity',vel_ris,'InitialOrientationAxes',azelaxes(180,0),'OrientationAxesOutputPort',true);

With the RIS, the scene is plotted below.

fov = beamwidth(antelement,fc);
helperPlotScene({pos_trx,pos_human,pos_ris},{vel_trx,vel_human,vel_ris},fov);

Figure contains an axes object. The axes object with xlabel X (m), ylabel Y (m) contains 7 objects of type line, text, patch. One or more of the lines displays its values using only markers These objects represent Radar, Human, RIS, Radar Coverage.

Human Detection with Radar

FMCW signal is a common waveform used for human activity monitoring. The following code section simulates the received signal at the radar. When you check the box of the variable hasRIS, the received signal will include the effect of the RIS. Otherwise, the RIS is not used.

max_range = 50;
ts = 5.5*range2time(max_range,c);
range_res = 0.1;
pulse_bw = rangeres2bw(range_res,c);
fs = 2*pulse_bw;

wav = phased.FMCWWaveform('SampleRate',fs,'SweepBandwidth',pulse_bw,'SweepTime',ts);

Nsweeps = 64;

hasRIS = true;
[y,ang_ris_from_rx,xref] = helperSimulateEcho(fc,fs,c,plat_trx,plat_ris,plat_human,wav,antarray,human,ris,Nsweeps,hasRIS);

Next, we perform the beamforming to the received signal to further improve the signal to noise ratio. Because the RIS is deployed in a known position, the beamforming direction is known.

bf = phased.PhaseShiftBeamformer('PropagationSpeed',c,'OperatingFrequency',fc,'DirectionSource','Input port',...
    'SensorArray',antarray);

y_bf = zeros(round(ts*fs),Nsweeps,'like',1i);
for m = 1:Nsweeps
    y_bf(:,m) = bf(y(:,:,m),ang_ris_from_rx);
end

The beamformed signal can then be dechirped. The range-Doppler map of the resulting signal is shown below.

y_bf_dechirp = dechirp(y_bf,xref);

rd = phased.RangeDopplerResponse('RangeMethod','FFT','PropagationSpeed',c,...
    'SampleRate',fs,'SweepSlope',pulse_bw/ts,'DopplerOutput','Speed','OperatingFrequency',fc);
rdm_handle = plotResponse(rd,y_bf_dechirp,'Unit','db');
ylim([0 max_range])
xlim([-100 100])
rdm_axis = rdm_handle.Parent;
hold(rdm_axis,'on')
rangesum_truth = norm(pos_trx-pos_ris)+norm(pos_ris-pos_human);
speedsum_truth = radialspeed(pos_ris,vel_ris,pos_trx,vel_trx)+radialspeed(pos_human,vel_human,pos_ris,vel_ris);
plot(speedsum_truth,rangesum_truth,'ko','MarkerSize',10);

Figure contains an axes object. The axes object with title Range-Speed Response Pattern, xlabel Speed (m/s), ylabel Range (meters) contains 2 objects of type image, line. One or more of the lines displays its values using only markers

The circle in the image indicates the expected range-Doppler location of the human. The plot clearly shows that the person is properly detected. If you run the script without using the RIS, you will see no detection in the range-Doppler map.

RIS Aided Scanning

The simulation in the previous section shows that the RIS can help detect the person that is not detectable otherwise. In addition, RIS also allows us to scan the beam to search the space if the target direction is not known. Because both the radar and the RIS are static, we can scan the beam by controlling the phase of each element in the RIS to search for the human target.

scan_az = -60:0;
scan_el = -20:-13;
[rxsigpow,ang_car_from_ris] = helperSimulateScanning(fc,fs,c,plat_trx,plat_ris,plat_human,wav,antarray,human,ris,scan_az,scan_el);

clf;
im_handle = imagesc(scan_az,scan_el,rxsigpow);
xlabel('Azimmuth Angle (deg)');
ylabel('Elevation Angle (deg)');
title('Angular Response Relative to RIS');
im_ax = im_handle.Parent;
hold(im_ax,'on');
plot(ang_car_from_ris(1),ang_car_from_ris(2),'ko','MarkerSize',10);

Figure contains an axes object. The axes object with title Angular Response Relative to RIS, xlabel Azimmuth Angle (deg), ylabel Elevation Angle (deg) contains 2 objects of type image, line. One or more of the lines displays its values using only markers

As shown in the figure, the person is found in the correct direction, as marked by the black circle. With the range and Doppler information from the previous section and the direction information from above, the person can be properly localized in the scene.

Summary

This example shows how a RIS can be used to improve the sensing capability of a radar system. With the help of the RIS, a target outside of the radar's field of view can be successfully detected and positioned.

References

[1] Stefano Buzzi, Emanuele Grossi, Marco Lops, and Luca Venturino, Radar Target Detection Aided by Reconfigurable Intelligent Surfaces, IEEE Signal Processing Letters, Vol. 28, 2021

[2] Sudeep Prabhakar Chepuri, Nir Shlezinger, Fan Liu, George C. Alexandropoulos, Stefano Buzzi, and Yonina C. Eldar, Integrated Sensing and Communications with Reconfigurable Intelligent Surfaces, IEEE Signal processing Magazine, September, 2023

Helper Functions

Echo Simulation

function [y,ang_ris_from_rx,xref] = helperSimulateEcho(fc,fs,c,plat_trx,plat_ris,plat_car,wav,antarray,car,ris,Nsweeps,hasRIS)

tx = phased.Transmitter('PeakPower',db2pow(40)*1e-3,'Gain',10);
rx = phased.Receiver('Gain',10,'NoiseFigure',0,'SampleRate',fs);
stv_antarray = phased.SteeringVector('SensorArray',antarray,'PropagationSpeed',c);

txant = phased.Radiator('Sensor',antarray,'OperatingFrequency',fc,'PropagationSpeed',c,'WeightsInputPort',true);
rxant = phased.Collector('Sensor',antarray,'OperatingFrequency',fc,'PropagationSpeed',c,'WeightsInputPort',true);

tx_car_chan = phased.FreeSpace('OperatingFrequency',fc,'SampleRate',fs,'PropagationSpeed',c,...
    'TwoWayPropagation',false,'MaximumDistanceSource','Property','MaximumDistance',500);
tx_ris_chan = phased.FreeSpace('OperatingFrequency',fc,'SampleRate',fs,'PropagationSpeed',c,...
    'TwoWayPropagation',false,'MaximumDistanceSource','Property','MaximumDistance',500);
ris_car_chan = phased.FreeSpace('OperatingFrequency',fc,'SampleRate',fs,'PropagationSpeed',c,...
    'TwoWayPropagation',false,'MaximumDistanceSource','Property','MaximumDistance',500);
car_rx_chan = phased.FreeSpace('OperatingFrequency',fc,'SampleRate',fs,'PropagationSpeed',c,...
    'TwoWayPropagation',false,'MaximumDistanceSource','Property','MaximumDistance',500);
car_ris_chan = phased.FreeSpace('OperatingFrequency',fc,'SampleRate',fs,'PropagationSpeed',c,...
    'TwoWayPropagation',false,'MaximumDistanceSource','Property','MaximumDistance',500);
ris_rx_chan = phased.FreeSpace('OperatingFrequency',fc,'SampleRate',fs,'PropagationSpeed',c,...
    'TwoWayPropagation',false,'MaximumDistanceSource','Property','MaximumDistance',500);

Ntrx = getDOF(txant.Sensor);
ts = wav.SweepTime;
y = zeros(round(ts*fs),Ntrx,Nsweeps,'like',1i);
stv_ris = getSteeringVector(ris);
for m = 1:Nsweeps
    [pos_trx,vel_trx,ax_trx] = plat_trx(ts);
    [pos_ris,vel_ris,ax_ris] = plat_ris(ts);
    [pos_car,vel_car,ax_car] = plat_car(ts);

    xref = wav();
    x_tx = tx(xref);
    [~,ang_car_from_tx] = rangeangle(pos_car,pos_trx,ax_trx);
    [~,ang_ris_from_tx] = rangeangle(pos_ris,pos_trx,ax_trx);
    x_tx_car = txant(x_tx,ang_car_from_tx,conj(stv_antarray(fc,ang_car_from_tx)));
    y_tx_car = tx_car_chan(x_tx_car,pos_trx,pos_car,vel_trx,vel_car);
    
    [range_tx_from_ris,ang_tx_from_ris] = rangeangle(pos_trx,pos_ris,ax_ris);
    [range_car_from_ris,ang_car_from_ris] = rangeangle(pos_car,pos_ris,ax_ris);
    stv_trx_from_ris = stv_ris(fc,ang_tx_from_ris);
    stv_car_from_ris = stv_ris(fc,ang_car_from_ris);
    
    x_tx_ris = txant(x_tx,ang_ris_from_tx,conj(stv_antarray(fc,ang_ris_from_tx)));
    x_tx_ris_propagated = tx_ris_chan(x_tx_ris,pos_trx,pos_ris,vel_trx,vel_ris);
    y_tx_ris = ris(x_tx_ris_propagated,ang_tx_from_ris,ang_car_from_ris,conj(stv_trx_from_ris).*conj(stv_car_from_ris));
    y_tx_ris_car = ris_car_chan(y_tx_ris,pos_ris,pos_car,vel_ris,vel_car);
    
    if hasRIS
        y_car = car(y_tx_car+y_tx_ris_car);
    else
        y_car = car(y_tx_car);
    end
    y_car_rx_propagated = car_rx_chan(y_car,pos_car,pos_trx,vel_car,vel_trx);
    
    ang_rx_from_ris = ang_tx_from_ris;
    y_car_ris_propagated = car_ris_chan(y_car,pos_car,pos_ris,vel_car,vel_ris);
    y_car_ris = ris(y_car_ris_propagated,ang_car_from_ris,ang_rx_from_ris,conj(stv_trx_from_ris).*conj(stv_car_from_ris));
    
    y_car_ris_rx_propagated = ris_rx_chan(y_car_ris,pos_ris,pos_trx,vel_ris,vel_trx);
    
    [~,ang_ris_from_rx] = rangeangle(pos_ris,pos_trx,ax_trx);
    [~,ang_car_from_rx] = rangeangle(pos_car,pos_trx,ax_trx);
    if hasRIS
        y_car_rx = rxant([y_car_rx_propagated y_car_ris_rx_propagated],[ang_car_from_rx,ang_ris_from_rx],ones(Ntrx,1));
    else
        y_car_rx = rxant(y_car_rx_propagated,ang_car_from_rx,ones(Ntrx,1));
    end
    y(:,:,m) = rx(y_car_rx);
    
end

end

RIS Scanning

function [rxsigpow,ang_car_from_ris] = helperSimulateScanning(fc,fs,c,plat_trx,plat_ris,plat_car,wav,antarray,car,ris,scan_az,scan_el)

tx = phased.Transmitter('PeakPower',db2pow(40)*1e-3,'Gain',10);
rx = phased.Receiver('Gain',10,'NoiseFigure',0,'SampleRate',fs);
stv_antarray = phased.SteeringVector('SensorArray',antarray,'PropagationSpeed',c);

txant = phased.Radiator('Sensor',antarray,'OperatingFrequency',fc,'PropagationSpeed',c,'WeightsInputPort',true);
rxant = phased.Collector('Sensor',antarray,'OperatingFrequency',fc,'PropagationSpeed',c,'WeightsInputPort',true);

tx_car_chan = phased.FreeSpace('OperatingFrequency',fc,'SampleRate',fs,'PropagationSpeed',c,...
    'TwoWayPropagation',false,'MaximumDistanceSource','Property','MaximumDistance',500);
tx_ris_chan = phased.FreeSpace('OperatingFrequency',fc,'SampleRate',fs,'PropagationSpeed',c,...
    'TwoWayPropagation',false,'MaximumDistanceSource','Property','MaximumDistance',500);
ris_car_chan = phased.FreeSpace('OperatingFrequency',fc,'SampleRate',fs,'PropagationSpeed',c,...
    'TwoWayPropagation',false,'MaximumDistanceSource','Property','MaximumDistance',500);
car_rx_chan = phased.FreeSpace('OperatingFrequency',fc,'SampleRate',fs,'PropagationSpeed',c,...
    'TwoWayPropagation',false,'MaximumDistanceSource','Property','MaximumDistance',500);
car_ris_chan = phased.FreeSpace('OperatingFrequency',fc,'SampleRate',fs,'PropagationSpeed',c,...
    'TwoWayPropagation',false,'MaximumDistanceSource','Property','MaximumDistance',500);
ris_rx_chan = phased.FreeSpace('OperatingFrequency',fc,'SampleRate',fs,'PropagationSpeed',c,...
    'TwoWayPropagation',false,'MaximumDistanceSource','Property','MaximumDistance',500);

bf = phased.PhaseShiftBeamformer('PropagationSpeed',c,'OperatingFrequency',fc,'DirectionSource','Input port',...
    'SensorArray',txant.Sensor);

Ntrx = getDOF(txant.Sensor);
stv_ris = getSteeringVector(ris);

ts = wav.SweepTime;
[pos_trx,vel_trx,ax_trx] = plat_trx(ts);
[pos_ris,vel_ris,ax_ris] = plat_ris(ts);
[pos_car,vel_car,ax_car] = plat_car(ts);

xref = wav();
x_tx = tx(xref);
[~,ang_car_from_tx] = rangeangle(pos_car,pos_trx,ax_trx);
[~,ang_ris_from_tx] = rangeangle(pos_ris,pos_trx,ax_trx);
x_tx_car = txant(x_tx,ang_car_from_tx,conj(stv_antarray(fc,ang_car_from_tx)));
y_tx_car = tx_car_chan(x_tx_car,pos_trx,pos_car,vel_trx,vel_car);

[range_tx_from_ris,ang_tx_from_ris] = rangeangle(pos_trx,pos_ris,ax_ris);
[range_car_from_ris,ang_car_from_ris] = rangeangle(pos_car,pos_ris,ax_ris);
stv_trx_from_ris = stv_ris(fc,ang_tx_from_ris);

x_tx_ris = txant(x_tx,ang_ris_from_tx,conj(stv_antarray(fc,ang_ris_from_tx)));
x_tx_ris_propagated = tx_ris_chan(x_tx_ris,pos_trx,pos_ris,vel_trx,vel_ris);

y_tx_ris_car = ris_car_chan(x_tx_ris_propagated,pos_ris,pos_car,vel_ris,vel_car);

y_car = car(y_tx_car+y_tx_ris_car);
y_car_rx_propagated = car_rx_chan(y_car,pos_car,pos_trx,vel_car,vel_trx);
y_car_ris_propagated = car_ris_chan(y_car,pos_car,pos_ris,vel_car,vel_ris);
y_car_ris_rx_propagated = ris_rx_chan(y_car_ris_propagated,pos_ris,pos_trx,vel_ris,vel_trx);

ang_rx_from_ris = ang_tx_from_ris;
[~,ang_ris_from_rx] = rangeangle(pos_ris,pos_trx,ax_trx);
[~,ang_car_from_rx] = rangeangle(pos_car,pos_trx,ax_trx);
rxsigpow = zeros(numel(scan_el),numel(scan_az));
for m = 1:numel(scan_az)
    for n = 1:numel(scan_el)
        scanAngle = [scan_az(m);scan_el(n)];
        stv_scan = stv_ris(fc,scanAngle);
        y_tx_ris = ris(y_car_ris_rx_propagated,ang_tx_from_ris,ang_car_from_ris,conj(stv_trx_from_ris).*conj(stv_scan));
        y_car_ris = ris(y_tx_ris,ang_car_from_ris,ang_rx_from_ris,conj(stv_trx_from_ris).*conj(stv_scan));
        y_car_rx = rxant([y_car_rx_propagated y_car_ris],[ang_car_from_rx,ang_ris_from_rx],ones(Ntrx,1));
        y = rx(y_car_rx);
        y_bf = bf(y,ang_ris_from_rx);  
        rxsigpow(n,m) = rms(y_bf);
    end
end

end

Scene Plotting

function helperPlotScene(pos,vel,fov)

tp = theaterPlot('XLim',[-10 20],'Ylim',[-10 20],'Zlim',[-10 20]);
trxp = platformPlotter(tp,'DisplayName','Radar','Marker','.');
pos_trx = pos{1};
vel_trx = vel{1};
plotPlatform(trxp,pos_trx.',vel_trx.',{'Radar'});

humanp = platformPlotter(tp,'Displayname','Human','Marker','*');
pos_human = pos{2};
vel_human = vel{2};
plotPlatform(humanp,pos_human.',vel_human.',{'Human'});

if numel(pos) == 3
    risp = platformPlotter(tp,'DisplayName','RIS','Marker','s','MarkerSize',20);
    pos_ris = pos{3};
    vel_ris = vel{3};
    plotPlatform(risp,pos_ris.',vel_ris.',{'RIS'});
end

trxcovp = coveragePlotter(tp,'DisplayName','Radar Coverage');
trxconfig = struct('Index',1,'LookAngle',[0;0],'ScanLimits',[0 90;0 20],'Range',200,'FieldOfView',[fov;0],...
    'Position',pos_trx.','Orientation',eye(3));
plotCoverage(trxcovp,trxconfig);

end