Introduction to Radar Scenario Clutter Simulation
This example shows how to generate monostatic surface clutter signals and detections in a radar scenario. Clutter detections will be generated with a monostatic radarDataGenerator
, and clutter return signals will be generated with a radarTransceiver,
using both homogenous surfaces and real terrain data from a DTED file. theaterPlot
is used to visualize the scenario surface and clutter generation.
Configure Scenario for Clutter Generation
Configuration of a radar scenario to simulate surface clutter involves creating a radarScenario
object, adding platforms with mounted radars, adding surface objects that define the physical properties of the scenario surface, and enabling clutter generation for a specific radar in the scene.
Select a Radar Model
Clutter generation is performed as part of the scenario detect
and receive
methods. These methods are used to generate simulated radar detections and IQ signals, respectively. For detections, which consist of measurement-level data along with useful metadata, use the radarDataGenerator
. For raw IQ signals, use the radarTransceiver
.
This section begins with a radarDataGenerator
. Define some typical medium-PRF pulse-Doppler parameters for a side-looking airborne radar. Use a -90 degree mounting yaw angle so the radar faces to the right of the platform and a 10 degree depression angle so the radar is pointed towards the surface. The mounting roll angle can be 0 to indicate no rotation about the antenna boresight. Use a center frequency of 5 GHz, range resolution of 150 m, and a 12 kHz PRF with 64 pulses per coherent processing interval (CPI).
mountAng = [-90 10 0]; fc = 5e9; rngRes = 150; prf = 12e3; numPulses = 64;
The radarDataGenerator
is a statistical model that does not directly emulate an antenna pattern. Instead, it has properties that define the field of view and angular resolution. Use 10 degrees for the field of view and angular resolution in each direction. This configuration is comparable to simulating a single mainlobe with no angle estimation.
fov = [10 10]; angRes = fov;
Construct a radarDataGenerator
from these parameters. The radar updates once per CPI. The mounting angles point the radar in a broadside direction. Let the field of view and angular resolution equal the beamwidth. Set DetectionCoordinates
to 'Scenario'
to output detections in scenario coordinates for easier inspection of the results. Calculate the unambiguous range and radial speed and enable range and range-rate ambiguities for the radar. The ambiguities can be calculated with the time2range
and dop2speed
functions.
c = physconst('lightspeed'); lambda = freq2wavelen(fc); rangeRateRes = lambda/2*prf/numPulses; unambRange = time2range(1/prf); unambRadialSpd = dop2speed(prf/4,lambda); cpiTime = numPulses/prf; rdr = radarDataGenerator(1,'No scanning','UpdateRate',1/cpiTime,'MountingAngles',mountAng,... 'DetectionCoordinates','Scenario','HasINS',true,'HasElevation',true,'HasFalseAlarms',false, ... 'HasRangeRate',true,'HasRangeAmbiguities',true,'HasRangeRateAmbiguities',true, ... 'MaxUnambiguousRadialSpeed',unambRadialSpd,'MaxUnambiguousRange',unambRange,'CenterFrequency',fc, ... 'FieldOfView',fov,'AzimuthResolution',angRes(1),'ElevationResolution',angRes(2), ... 'RangeResolution',rngRes,'RangeRateResolution',rangeRateRes);
Create a Scenario
The radarScenario
object is the top-level manager for the simulation. A radar scenario may be Earth-centered, where the WGS84 Earth model is used, or it may be flat. Use a flat-Earth scenario to enable use of simple kinematic trajectories for the platforms. Set UpdateRate
to 0 to let the scenario derive an update rate from the objects in the scenario.
scenario = radarScenario('UpdateRate',0,'IsEarthCentered',false);
Add a radar platform to the scenario. Use a straight-line kinematic trajectory starting 1.5 km up, and moving in the +Y direction at 70 m/s, at a dive angle of 10 degrees. Orient the platform so the platform-frame +X direction is the direction of motion. Use the Sensors
property to mount the radar.
rdrAlt = 1.5e3; rdrSpd = 70; rdrDiveAng = 10; rdrPos = [0 0 rdrAlt]; rdrVel = rdrSpd*[0 cosd(rdrDiveAng) -sind(rdrDiveAng)]; rdrOrient = rotz(90).'; rdrTraj = kinematicTrajectory('Position',rdrPos,'Velocity',rdrVel,'Orientation',rdrOrient); rdrplat = platform(scenario,'Sensors',rdr,'Trajectory',rdrTraj);
Define the Scenario Surface
Physical properties of the scenario surface can be specified by using the scenario landSurface
and seaSurface
methods to define regions of land and sea surface types. Each surface added to the scene is a rectangular region with an associated radar reflectivity model and reference height. Land surfaces may additionally have associated static terrain data, and sea surfaces may have an associated spectral motion model. If no terrain data or spectral model is used, a surface may be unbounded, allowing for homogeneous clutter generation.
Create a simple unbounded land surface with a constant-gamma reflectivity model. Use the surfaceReflectivityLand
function to create a reflectivity model and attach the reflectivity model to the surface with the RadarReflectivity
parameter. Use a gamma value of -20 dB.
refl = surfaceReflectivityLand('Model','ConstantGamma','Gamma',-20); srf = landSurface(scenario,'RadarReflectivity',refl)
srf = LandSurface with properties: RadarReflectivity: [1x1 surfaceReflectivityLand] ReflectionCoefficient: [1x1 radar.scenario.SurfaceReflectionCoefficient] ReflectivityMap: 1 ReferenceHeight: 0 Boundary: [2x2 double] Terrain: []
The ReferenceHeight
property gives the constant height of the surface when no terrain is specified, or the origin height to which terrain is referenced if terrain is specified. The ReflectivityMap
property is relevant only when a custom reflectivity model is used, and allows different reflectivity curves to be associated to different parts of the surface. The Boundary
property gives the rectangular boundary of the surface in two-point form. Elements of Boundary
can be +/-inf to indicate the surface is unbounded in one or more directions. Check the boundary of the surface created above to see that it is unbounded in all directions.
srf.Boundary
ans = 2×2
-Inf Inf
-Inf Inf
Access the SurfaceManager
property of the scenario to see the surface objects that have been added, as well as any additional options related to the scenario surface.
scenario.SurfaceManager
ans = SurfaceManager with properties: EnableMultipath: 0 UseOcclusion: 1 Surfaces: [1x1 radar.scenario.LandSurface]
The UseOcclusion
property can be set false to disable line-of-sight occlusions by the surface, such as by terrain.
Enable Clutter Generation
Clutter Generator
Monostatic clutter generation is enabled for a specific radar by using the scenario clutterGenerator
method. This method accepts parameter name-value pairs to configure clutter generation. This configuration is performed on a radar-by-radar basis so that multiple radars can be simulated simultaneously with clutter generation settings appropriate for each radar. The clutterGenerator
method will return a handle to the ClutterGenerator
object.
Reflections from large continuous surfaces are approximated by a set of point scatterers. By default, the ClutterGenerator
operates in "uniform" scatterer distribution mode. In this mode, scatterers are placed randomly with a uniform density on the surface. This is a flexible mode that can be used for any surface and radar configuration. See the section below titled "Simulate Smooth Surface Clutter for a Range-Doppler Radar" for a demonstration of a different scatterer distribution mode that can adapt to range-Doppler resolution cells under some scenario constraints. When operating in uniform scatterer distribution mode, the Resolution
property specifies the nominal spacing of clutter scatterers used to represent the surface reflection.
The UseBeam
property is a logical scalar indicating whether or not automatic mainlobe clutter generation should be used (see the next section titled "Clutter Regions" for more details). The RangeLimit
property is used to place an upper bound on the range of clutter generation, which is important for cases when mainlobe clutter generation is being used and has an unbounded footprint.
Create a ClutterGenerator
object, enabling clutter generation for the radar created above. Use a Resolution
of half the radar's range resolution in order to get a couple of clutter scatterers per range sample. Set UseBeam
to true to enable automatic clutter generation within the field of view of the radar. Use a RangeLimit
of 12 km, which is just shorter than the unambiguous range.
clutRes = rngRes/2; clutRngLimit = 12e3; clut = clutterGenerator(scenario,rdr,'Resolution',clutRes,'UseBeam',true,'RangeLimit',clutRngLimit)
clut = ClutterGenerator with properties: ScattererDistribution: "Uniform" Resolution: 75 Regions: [1x0 radar.scenario.RingClutterRegion] UseBeam: 1 UseShadowing: 1 RangeLimit: 12000 Radar: [1x1 radarDataGenerator] SeedSource: "Auto"
The UseShadowing
property is a logical scalar used to enable/disable shadowing (surface self-occlusion). Shadowing is only relevant for surfaces with terrain data or a spectral model.
The clutter generator has two read-only properties. The Radar
property stores a handle to the associated radar object, which was passed to the clutterGenerator
method. The Regions
property contains the set of user-defined "clutter regions".
Clutter Regions
Surface clutter is distributed over the entire range interval starting from the radar altitude and extending to the horizon range (or if using a flat-Earth scenario). It is distributed in elevation angle from -90 degrees up to the horizon elevation angle, and over all 360 degrees of azimuth. Finally, surface clutter is distributed in Doppler as a result of platform motion.
There are two options available to designate regions of the surface for clutter generation. The first is automatic mainlobe clutter, which generates clutter inside the footprint of the mainlobe of the radar antenna. This is only possible when the radar being used has a well-defined beam with azimuth and elevation two-sided beamwidths less than 180 degrees. For the radarDataGenerator
, the "beam" is actually the field of view defined by the FieldOfView
property, the footprint of which consists of contours of constant azimuth and elevation angle. For the radarTransceiver
, a conical or fan-shaped beam is assumed based on the array type, and the beam is considered out to 3 dB below the peak gain.
The second option is to use the ringClutterRegion
method of the clutter generator to specify a ring-shaped region of the scenario surface within which clutter is to be generated. This type of region is defined by a minimum and maximum ground range (relative to the radar nadir point) and an extent and center angle in azimuth. This region type is useful for capturing sidelobe and backlobe clutter return, mainlobe clutter return outside the 3 dB width, or to generate clutter from any other region of interest, such as at the location of a target platform.
The figure below illustrates these two region types. The beam footprint region is displayed as a magenta ellipse where the beam intersects the ground. Two ring regions are shown, one directly underneath the radar for capturing altitude return, and another for capturing some backlobe clutter return.
To demonstrate the utility of the customizable ring-shaped regions at capturing clutter return from arbitrary lobes of the antenna pattern, the above geometry is shown again below in a top-down view, with a gain pattern projected onto the ground. Note that a significant backlobe has been encompassed by a ring region. A circular region (which can be achieved by setting the minimum ground range to 0) can be used to capture altitude return. An additional region encompassing the mainlobe is also shown to demonstrate how this can be used to capture more of the mainlobe return, such as from null to null.
The radarDataGenerator
is a statistics-based detectability simulator, and only simulates mainlobe detections within the field of view. As such, having UseBeam
of the ClutterGenerator
set to true is sufficient to completely capture the effect of clutter interference on the detectability of target platforms when using a radarDataGenerator
.
Visualize and Run Scenario
Theater Plotter
The theaterPlot
object can be used along with a variety of theater plotters to create customizable visual representations of the scenario. Start by creating the theater plot.
tp = theaterPlot;
Now create plotter objects for the scenario surface, clutter regions, and resulting radar detections. The values specified for the DisplayName
properties are used for the legend entries.
surfPlotter = surfacePlotter(tp,'DisplayName','Scenario Surface'); clutPlotter = clutterRegionPlotter(tp,'DisplayName','Clutter Region'); detPlotter = detectionPlotter(tp,'DisplayName','Radar Detections','Marker','.','MarkerEdgeColor','magenta','MarkerSize',4);
Now that the scenario, clutter generator, and plotters are configured, use the detect
method on the scenario to simulate a single frame and collect detections.
dets = detect(scenario);
Plot the clutter region, which in this case is simply the beam footprint, along with the detection positions. Since the land surface used here is unbounded, the plotSurface
call should come last so that the surface plot extends over the appropriate axis limits. The clutterRegionData
method on the clutter generator is used to get plot data for the clutter region plotter. Similarly, for the surface plotter, the surfacePlotterData
method on the scenario surface manager is used.
plotClutterRegion(clutPlotter,clutterRegionData(clut))
detpos = cell2mat(cellfun(@(t) t.Measurement(1:3).',dets,'UniformOutput',0));
plotDetection(detPlotter,detpos)
plotSurface(surfPlotter,surfacePlotterData(scenario.SurfaceManager))
The detection positions can be seen arranged along radial lines corresponding to the radar's azimuth and Doppler resolution bins. The radarDataGenerator
adds noise to the positions of detections, so may return detections with positions that fall outside the beam footprint.
Simulate Clutter IQ Signals
Now you will create a radarTransceiver
with similar radar system parameters and simulate clutter at the signal level. The function helperMakeTransceiver
is provided to quickly create a transceiver with the desired system parameters.
Define the desired beamwidth. For comparison to the above scenario, simply let the beamwidth equal the field of view that was used.
beamwidth3dB = fov;
The resulting radarTransceiver
will use a phased.CustomAntennaElement
to approximate a uniform rectangular array with the specified beamwidth, which is recommended to speed up simulations when only a sum beam is needed.
useCustomElem = true; rdriq = helperMakeTransceiver(beamwidth3dB,fc,rngRes,prf,useCustomElem);
Use the same mounting angles and number of pulses as before.
rdriq.MountingAngles = mountAng; rdriq.NumRepetitions = numPulses;
Re-create the same scenario, using this new radar model. Start by calling release
on System Objects that will be re-used.
release(rdrTraj) scenario = radarScenario('UpdateRate',0,'IsEarthCentered',false); platform(scenario,'Sensors',rdriq,'Trajectory',rdrTraj); landSurface(scenario,'RadarReflectivity',refl);
Enable clutter generation for the radar. This time, disable the beam footprint clutter region in favor of a custom ring-shaped region.
clutterGenerator(scenario,rdriq,'Resolution',clutRes,'UseBeam',false,'RangeLimit',clutRngLimit);
If the clutterGenerator
method was called without any output argument, as above, the handle to the constructed ClutterGenerator
may still be found with the scenario getClutterGenerator
method by passing in a handle to the associated radar.
clut = getClutterGenerator(scenario,rdriq);
After creating the ClutterGenerator
, you can use the ringClutterRegion
method to create a null-to-null footprint region for clutter generation. Use a simple estimate of the null-to-null beamwidth as about 2.5 times the 3 dB beamwidth, then find the minimum elevation angle to encompass the near edge of the beam, and finally convert that to a minimum ground range for the region.
beamwidthNN = 2.5*beamwidth3dB; minel = -mountAng(2) - beamwidthNN(2)/2; minrad = -rdrAlt/tand(minel);
For the max radius parameter, simply find the ground range corresponding to the clutter range limit specified earlier.
maxrad = sqrt(clut.RangeLimit^2 - rdrAlt^2);
The azimuth span will equal the null-to-null beamwidth, and the azimuth center will be 0 degrees since the beam is pointing along the +X direction in scenario coordinates.
azspan = beamwidthNN(1); azc = 0; ringClutterRegion(clut,minrad,maxrad,azspan,azc)
ans = RingClutterRegion with properties: MinRadius: 3.6213e+03 MaxRadius: 1.1906e+04 AzimuthSpan: 25 AzimuthCenter: 0
Using the provided helper function, plot the ground-projected antenna pattern along with the ring clutter region you just created. The ring region created above nicely encompasses the entire mainlobe.
helperPlotGroundProjectedPattern(clut)
Run the simulation again for one frame, this time using the scenario receive
method to simulate IQ signals.
iqsig = receive(scenario); PH = iqsig{1};
Since the radarTransceiver
used a single custom element, the resulting signal will be formatted with fast-time samples along the first dimension and pulse index (slow time) along the second dimension. This is the phase history (PH) matrix. Plot a DC-centered range-Doppler map (RDM) using the helperPlotRDM
function.
figure helperPlotRDM(PH,rngRes,prf,numPulses)
Use the provided helper function to re-create the theater plot visualization and view the ring clutter region.
helperTheaterPlot(clut)
Simulate Surface Range Profiles for a Scanning Radar
The automatic mainlobe clutter option supports scanning radars. In this section you will re-create the scenario to use a stationary scanning linear array that collects a single pulse per scan position. You will add a few stationary surface targets and view the resulting range profiles.
Start by re-creating the radar object. This time, only pass the azimuth beamwidth to the helper function, which indicates a linear array should be used. The custom element cannot be used for a linear array if the automatic mainlobe clutter option is being used, so that the ClutterGenerator
has knowledge of the array geometry. Reduce the range resolution to 75 meters to reduce the clutter power in gate.
useCustomElem = false; rngRes = 75; rdriq = helperMakeTransceiver(beamwidth3dB(1),fc,rngRes,prf,useCustomElem);
Set the same mounting angles as used earlier, and configure the transceiver for 1 repetition, which indicates a single pulse per scan position.
numPulses = 1; rdriq.MountingAngles = mountAng; rdriq.NumRepetitions = numPulses;
Now configure an electronic sector scan. Set the scanning limits to cover 30 degrees in azimuth, with no elevation scanning. Setting the scan rate to the PRF indicates a single pulse per scan position.
rdriq.ElectronicScanMode = 'Sector';
rdriq.ElectronicScanLimits = [-15 15;0 0];
rdriq.ElectronicScanRate = [prf; 0];
Re-create the scenario and platform. Set the scenario stop time to run 1 full scan. Use a homogeneous unbounded land surface with the same reflectivity model as used earlier.
scenario = radarScenario('UpdateRate',0,'IsEarthCentered',false,'StopTime',30/prf); platform(scenario,'Sensors',rdriq,'Position',rdrPos,'Orientation',rotz(90).'); landSurface(scenario,'RadarReflectivity',refl);
Enable clutter generation, using only the 3 dB beam footprint for clutter generation.
clutterGenerator(scenario,rdriq,'Resolution',clutRes,'UseBeam',true,'RangeLimit',clutRngLimit);
Add three bright point targets spaced 2 km apart along the cross-range direction at a down-range of 8 km.
tgtRCS = 40; % dBsm platform(scenario,'Position',[8e3 -2e3 0],'Signatures',rcsSignature('Pattern',tgtRCS)); platform(scenario,'Position',[8e3 0 0],'Signatures',rcsSignature('Pattern',tgtRCS)); platform(scenario,'Position',[8e3 2e3 0],'Signatures',rcsSignature('Pattern',tgtRCS));
Run the simulation, collecting the range profile at each scan position, and plotting with a scenario overview. Use the info
output from receive
to record the look angle used by the radar on each frame.
rangeGates = (0:ceil((unambRange-rngRes)/rngRes))*rngRes; frame = 0; while advance(scenario) frame = frame + 1; [iqsig,info] = receive(scenario); lookAng(:,frame) = info.ElectronicAngle; rangeProfiles(:,frame) = 20*log10(abs(sum(iqsig{1},2))); if frame == 1 % Initial plotting ax(1) = subplot(1,2,1); helperPlotClutterScenario(scenario,[],[],ax(1)) ax(2) = subplot(1,2,2); rpHndl = plot(ax(2),rangeGates/1e3,rangeProfiles(:,frame)); tHndl=title(sprintf('Frame: %d, Azimuth: %.1f deg',frame,lookAng(1,frame))); grid on xlabel('Range (km)') ylabel('Range Profile (dBW)') else % Update plots helperPlotClutterScenario(scenario,[],[],ax(1)) rpHndl.YData = rangeProfiles(:,frame); tHndl.String = sprintf('Frame: %d, Azimuth: %.1f deg',frame,lookAng(1,frame)); end drawnow limitrate nocallbacks end
Plot the range profiles against range and azimuth scan angle.
figure imagesc(lookAng(1,:),rangeGates/1e3,rangeProfiles); set(gca,'ydir','normal') xlabel('Azimuth Scan Angle (deg)') ylabel('Range (km)') title('Clutter Range Profiles (dBW)') colorbar
The three target signals are barely visible around 8 km range.
Simulate Smooth Surface Clutter for a Range-Doppler Radar
Up till now you have simulated surface clutter using the "uniform" scatterer distribution mode. For flat-Earth scenarios, the radarTransceiver
radar model, and smooth surfaces (no terrain or spectral model associated with the surface), a faster range-Doppler-adaptive mode is available which uses a minimal number of clutter scatterers and a more accurate calculation of the clutter power in each range-Doppler resolution cell.
Re-create the radarTransceiver, again with a linear array. The automatic mainlobe region will not be used in this section, so use a custom element to speed things up.
useCustomElem = true; rdriq = helperMakeTransceiver(beamwidth3dB(1),fc,rngRes,prf,useCustomElem);
This time, instead of scanning, you will just simulate a single frame with 64 pulses, and perform Doppler processing. The NumRepetitions
property, along with the specified PRF, determines the Doppler resolution of the adaptive scatterers.
numPulses = 64; rdriq.MountingAngles = mountAng; rdriq.NumRepetitions = numPulses;
Create the scenario as before with the simple homogenous surface.
scenario = radarScenario('UpdateRate',0,'IsEarthCentered',false); landSurface(scenario,'RadarReflectivity',refl);
The radar is again flying in the +Y direction while facing in the +X direction.
release(rdrTraj) platform(scenario,'Sensors',rdriq,'Trajectory',rdrTraj);
Enable clutter generation. To use the range-Doppler-adaptive scatterers, specify "RangeDopplerCells"
for the ScattererDistribution
property. To encompass the three targets, use a ring-shaped region with 60 degrees of azimuth span, and the same min/max radius used earlier.
clut = clutterGenerator(scenario,rdriq,'ScattererDistribution','RangeDopplerCells','UseBeam',false,'RangeLimit',clutRngLimit); ringClutterRegion(clut,minrad,maxrad,60,0);
Add the same three bright targets.
platform(scenario,'Position',[8e3 -2e3 0],'Signatures',rcsSignature('Pattern',tgtRCS)); platform(scenario,'Position',[8e3 0 0],'Signatures',rcsSignature('Pattern',tgtRCS)); platform(scenario,'Position',[8e3 2e3 0],'Signatures',rcsSignature('Pattern',tgtRCS));
Run the simulation for a single frame, form the sum beam, and plot the RDM.
iqsig = receive(scenario); PH = iqsig{1}; helperPlotRDM(PH,rngRes,prf,numPulses);
The targets are more visible than in the range-angle case thanks to the Doppler spreading of clutter. With such a large clutter region, the same scenario could be expected to take upwards of 35x longer to simulate with the uniform scatterer distribution.
Clutter from Terrain Data
In the previous sections, you simulated homogeneous clutter from an unbounded flat surface. In this section, you will use a DTED file to simulate clutter return from real terrain data in an Earth-centered scenario. You will collect two frames of clutter return - one with shadowing enabled and one without shadowing, and compare the results.
Start by creating the scenario, this time setting the IsEarthCentered
flag to true in order to use a DTED file, which consists of surface height samples over a latitude/longitude grid.
scenario = radarScenario('UpdateRate',0,'IsEarthCentered',true);
Again use the landSurface
method, passing in the name of the desired DTED file for the value of the Terrain
parameter. The Boundary
parameter can be used to constrain the domain of the loaded data. In general, as little of the terrain data should be loaded as needed for the specific application. In this case, you will use a 0.15-by-0.15 degree section of DTED that is referenced to a given latitude-longitude coordinate.
refLLA = [39.43; -105.84]; bdry = refLLA + [0 1;-1/2 1/2]*0.15;
Continue using the same constant-gamma reflectivity model. Use an output argument to get a handle to the created surface object.
srf = landSurface(scenario,'Terrain','n39_w106_3arc_v2.dt1','Boundary',bdry,'RadarReflectivity',refl);
Use the surface height
method to place the platform above the reference point at the altitude specified earlier.
srfHeight = height(srf,refLLA); rdrAlt = srfHeight + rdrAlt; rdrPos1 = [refLLA; rdrAlt];
In this scenario, the radar will travel in a straight line West at the same speed used earlier.
rdrVelWest = [-rdrSpd 0 0];
Earth-centered scenarios require trajectory information to be specified with waypoints in latitude/longitude/altitude (LLA) format using the geoTrajectory
object. Set the ReferenceFrame
to ENU, and use the enu2lla function to find the second waypoint corresponding to the desired velocity vector. If the orientation of the platform is not specified, it will be set automatically such that the platform +X direction corresponds to the direction of motion (West). As such, the -90 degree mounting yaw angle will point the radar North.
toa = [0;1]; % Times of arrival at each waypoint rdrPos2 = enu2lla(rdrVelWest,rdrPos1.','ellipsoid').'; rdrTrajGeo = geoTrajectory('Waypoints',[rdrPos1, rdrPos2].','TimeOfArrival',toa,'ReferenceFrame','ENU'); platform(scenario,'Sensors',rdriq,'Trajectory',rdrTrajGeo);
Create the clutter generator. Surface shadowing is enabled by default.
clut = clutterGenerator(scenario,rdriq,'Resolution',clutRes,'UseBeam',false,'RangeLimit',clutRngLimit);
Create a ring-shaped region with the same parameters as earlier. For Earth-centered scenarios, azimuth angles in scenario coordinates are referenced clockwise from North, so an azimuth center of 0 here still coincides with the radar's look direction.
ringClutterRegion(clut,minrad,maxrad,azspan,azc);
Simulate clutter return for one frame and save the resulting phase history.
iqsig = receive(scenario); PH_withShadowing = iqsig{1};
The theater plot does not support visualizations of Earth-centered scenarios, so use the provided helper function to show a scenario overview in a local ENU frame. This time, the terrain is plotted along with the radar frame and clutter patches. Notice the shadowed region can be seen in the plot as a gap in the clutter patches (cyan). Those patches are obstructed by other parts of the terrain that are closer to the radar.
helperPlotClutterScenario(scenario)
title('Clutter patches - with terrain shadowing')
To see the difference when shadowing is not used, turn shadowing off, run the simulation for another frame, and save the result.
clut.UseShadowing = false; iqsig = receive(scenario); PH_noShadowing = iqsig{1};
Plot the scenario overview and notice that some of the clutter region has been filled in with clutter patches. Notice there are still some gaps visible. This is because clutter patches that are facing away from the radar, such as if they are on the other side of a hill, will never be visible, regardless of the value of the UseShadowing
property.
helperPlotClutterScenario(scenario)
title('Clutter patches - without terrain shadowing')
Now to see the effect of shadowing in the RDM, plot the clutter return signals recorded previously side-by-side.
figure subplot(1,2,1) helperPlotRDM(PH_withShadowing,rngRes,prf,numPulses) title('RDM - with terrain shadowing') subplot(1,2,2) helperPlotRDM(PH_noShadowing,rngRes,prf,numPulses) title('RDM - without terrain shadowing') set(gcf,'Position',get(gcf,'Position')+[0 0 560 0])
While both cases have "blank" regions due to hills that slope away from the radar, there is also a significant amount of surface return that is visible in the right figure and not visible in the left due to shadowing.
Shadowing is an important phenomenon when simulating clutter return from real surfaces, but it may be disabled for analysis purposes or if not needed.
Conclusion
In this example, you saw how to configure a radar scenario to include clutter return as part of the detect
and receive
methods, generating clutter detections and IQ signals with the radarDataGenerator
and radarTransceiver
, respectively. You saw how to define a region of the scenario surface with an associated reflectivity model, and how to specify regions of interest for clutter generation. Surface shadowing is simulated when generating clutter returns from surfaces with terrain, and a faster range-Doppler-adaptive mode can be used for flat-Earth scenarios with smooth surfaces.
Supporting Functions
helperTheaterPlot
function helperTheaterPlot(clut,params) arguments clut params.Parent = [] params.Detections = [] params.ShowPatches = false end if isempty(params.Parent) % Make new figure for theater plot figure tp = theaterPlot('Parent',gca); else % Use specified axes cla(params.Parent) tp = theaterPlot('Parent',params.Parent); end % Find targets tgts = clut.Scenario.Platforms(2:end); if ~isempty(tgts) tgtPos = cell2mat(cellfun(@(t) t.Position,tgts.','UniformOutput',0)); end % Get detection positions if ~isempty(params.Detections) detPos = cell2mat(cellfun(@(t) t.Measurement(1:3).',params.Detections,'UniformOutput',0)); end % Make plotters if ~isempty(tgts) platPlotter = platformPlotter(tp,'DisplayName','Target','Marker','+','MarkerEdgeColor','r'); end if ~isempty(params.Detections) detPlotter = detectionPlotter(tp,'DisplayName','Radar Detections','Marker','.','MarkerEdgeColor','magenta','MarkerSize',4); end clutPlotter = clutterRegionPlotter(tp,'DisplayName','Clutter Region','ShowPatchCenters',params.ShowPatches); surfPlotter = surfacePlotter(tp,'DisplayName','Scenario Surface'); % Do plotting if ~isempty(tgts) plotPlatform(platPlotter,tgtPos); end plotHeight = 1; plotClutterRegion(clutPlotter,clutterRegionData(clut,plotHeight)) if ~isempty(params.Detections) plotDetection(detPlotter,detPos) end plotSurface(surfPlotter,surfacePlotterData(clut.Scenario.SurfaceManager)) end
helperMakeTransceiver
function rdr = helperMakeTransceiver( bw,fc,rangeRes,prf,useCustomElem ) % This helper function creates a radarTransceiver from some basic system % parameters. c = physconst('lightspeed'); rdr = radarTransceiver; rdr.TransmitAntenna.OperatingFrequency = fc; rdr.ReceiveAntenna.OperatingFrequency = fc; rdr.Waveform.PRF = prf; sampleRate = c/(2*rangeRes); sampleRate = prf*round(sampleRate/prf); % adjust to match constraint with PRF rdr.Receiver.SampleRate = sampleRate; rdr.Waveform.SampleRate = sampleRate; rdr.Waveform.PulseWidth = 2*rangeRes/c; if isempty(bw) % Use an isotropic element rdr.TransmitAntenna.Sensor = phased.IsotropicAntennaElement; rdr.ReceiveAntenna.Sensor = phased.IsotropicAntennaElement; else % Get the number of elements required to meet the specified beamwidth sinc3db = 0.8859; N = round(sinc3db*2./(bw(:).'*pi/180)); N = flip(N); lambda = freq2wavelen(fc,c); if numel(N) == 1 % Use a back-baffled ULA array = phased.ULA(N,lambda/2); array.Element.BackBaffled = true; else % Use URA array = phased.URA(N,lambda/2); end if useCustomElem % Use a custom element corresponding to the sum beam az = -180:.4:180; el = -90:.4:90; G = pattern(array,fc,az,el,'Type','efield','normalize',false); M = 20*log10(abs(G)); P = angle(G); E = phased.CustomAntennaElement('FrequencyVector',[fc-1 fc+1],... 'AzimuthAngles',az,'ElevationAngles',el,'MagnitudePattern',M,'PhasePattern',P); rdr.TransmitAntenna.Sensor = E; rdr.ReceiveAntenna.Sensor = E; else rdr.TransmitAntenna.Sensor = array; rdr.ReceiveAntenna.Sensor = array; end end end
helperPlotGroundProjectedPattern
function helperPlotGroundProjectedPattern( clut ) % Input a ClutterGenerator that has an associated radarTransceiver. Plots % the clutter regions and ground-projected gain pattern. Assumes a flat % infinite ground plane at Z=0. Naz = 360*4; Nel = 90*4; % Force update the patch generator sensor data clut.PatchGenerator.updateSensorData(clut.Platform,clut.Radar,clut.Scenario.SimulationTime,clut.UseBeam); pos = clut.PatchGenerator.SensorData.Position; fc = clut.PatchGenerator.SensorData.CenterFrequency; B = clut.PatchGenerator.SensorData.SensorFrame; maxGndRng = clut.RangeLimit; % Get azimuth/elevation grid in scenario coordinates azScen = linspace(-180,180,Naz); maxEl = -atand(pos(3)/maxGndRng); elScen = linspace(-90,maxEl,Nel); % Convert az/el to sensor frame [losxScen,losyScen,loszScen] = sph2cart(azScen*pi/180,elScen.'*pi/180,1); R = B.'; losx = R(1,1)*losxScen + R(1,2)*losyScen + R(1,3)*loszScen; losy = R(2,1)*losxScen + R(2,2)*losyScen + R(2,3)*loszScen; losz = R(3,1)*losxScen + R(3,2)*losyScen + R(3,3)*loszScen; [az,el,~] = cart2sph(losx,losy,losz); az = az*180/pi; el = el*180/pi; % Get gain pattern sensor = clut.Radar.TransmitAntenna.Sensor; G = sensor(fc,[az(:) el(:)].'); G = reshape(G,size(az)); G = G/max(G(:)); rtg = -pos(3)./loszScen; surf(losxScen.*rtg,losyScen.*rtg,zeros(size(az)),20*log10(abs(G))) axis equal shading flat view(0,90) clim([-60 0]) hold on for reg = clut.Regions helperPlotClutterRegion(reg,pos); end hold off end
helperPlotRDM
function helperPlotRDM( PH,rangeRes,prf,numPulses ) % This helper function forms and plots an RDM from a phase history matrix c = physconst('lightspeed'); % Form DC-centered RDM and convert to dBW RDM = fftshift(fft(PH,[],2),2); RDM = 20*log10(abs(RDM)); % Range and Doppler bins rngBins = 0:rangeRes:c/(2*prf); dopBins = -prf/2:prf/numPulses:prf/2-prf/numPulses; % Plot imagesc(dopBins,rngBins/1e3,RDM); set(gca,'ydir','normal') xlabel('Doppler (Hz)') ylabel('Range (km)') mx = max(RDM(:)); if ~isinf(mx) clim([mx-60 mx]); end colorbar end