Sonar image formation from Phased Array Systems toolbox

I am currently using the Phased Array Systems toolbox at the following link:
I have successfully modified the code to produce 20 figures of time against absolute value of received signal. I have these plots available.
I am looking to form a complete forward-look sonar image from these plots. I understand that the positions of my targets can be stationary or moving, and only one of them has motion. However, a signal would need to be sent from the projector in multiple azimuth angles, in order to get a beamformed image.
Could someone suggest code to modify which already forms forward scan images from my described code above? It does not have to be complete, I am able to modify the code to my needs once I have a template that produces the images.

답변 (1개)

Umar
Umar 대략 16시간 전
편집: Torsten 대략 12시간 전
Hi @Michael,
Got a working template for you, plus a bit more detail than I first gave.
Attached: 1. forward_look_sonar_scan.m — drops straight into your example, this is the one to use. 2. forward_look_sonar_report.pdf — explains the reasoning and shows a second approach for comparison, with images. 3. forward_look_sonar_demo.py — same two approaches worked out in plain Python/NumPy, just to see them side by side (there's no MATLAB toolbox equivalent in Python, so this rebuilds the array math directly).
You already said it yourself in the post — you need to send the signal out at multiple azimuth angles to build the image. That's transmit steering, and it's also the only option that fits what you've got, since you're running a single hydrophone on receive rather than an array. So forward_look_sonar_scan.m wraps your existing pulse simulation in an outer azimuth loop, steers the projector array to each angle in turn using a steering-vector weight vector fed into phased.Radiator (WeightsInputPort true), and stacks each look's range profile into a range-azimuth image. Drop your real target positions/velocities/TS patterns in and you're set.
One thing worth knowing about for later: once you're re-transmitting a steered pulse for every azimuth, scan time adds up fast as your sector or resolution grows. The way round that is a hydrophone array on receive instead of the single one you've got, with beamforming done digitally after just one ping. That's a hardware swap though, not a code change, so I wouldn't jump to it unless scan time actually becomes a problem — it's in the PDF and the Python file if you want to see how it compares.
%% Forward-Look Sonar Image Formation Template
% Extends the "Underwater Target Detection with an Active Sonar System"
% example to sweep a set of azimuth (bearing) angles, steering the
% projector array's transmit beam to each one in turn, and assembling a
% range-azimuth (sector-scan) image -- the classic display format for a
% forward-look sonar (FLS).
%
% This is a TEMPLATE: two targets, one stationary and one moving, are
% kept from the original example purely as a working example. Swap in
% your own target positions/velocities/TS patterns as needed.
%% Underwater environment (unchanged from original example)
warning('off')
numPaths = 5;
propSpeed = 1520;
channelDepth = 100;
isopath{1} = phased.IsoSpeedUnderwaterPaths(...
'ChannelDepth',channelDepth,'NumPathsSource','Property', ...
'NumPaths',numPaths,'PropagationSpeed',propSpeed, ...
'BottomLoss',0.5,'TwoWayPropagation',true);
isopath{2} = phased.IsoSpeedUnderwaterPaths(...
'ChannelDepth',channelDepth,'NumPathsSource','Property', ...
'NumPaths',numPaths,'PropagationSpeed',propSpeed, ...
'BottomLoss',0.5,'TwoWayPropagation',true);
fc = 20e3; % Operating frequency (Hz)
channel{1} = phased.MultipathChannel('OperatingFrequency',fc);
channel{2} = phased.MultipathChannel('OperatingFrequency',fc);
%% Targets -- one stationary, one moving (edit positions/velocities to suit)
tgt{1} = phased.BackscatterSonarTarget('TSPattern',-5*ones(181,361));
tgt{2} = phased.BackscatterSonarTarget('TSPattern',-15*ones(181,361));
tgtplat{1} = phased.Platform('InitialPosition',[500; 1000; -70],'Velocity',[0; 0; 0]);
tgtplat{2} = phased.Platform('InitialPosition',[500; 0; -40],'Velocity',[5; 0; 0]); % moving target
%% Waveform
maxRange = 5000;
rangeRes = 10;
prf = propSpeed/(2*maxRange);
pulse_width = 2*rangeRes/propSpeed;
pulse_bw = 1/pulse_width;
fs = 2*pulse_bw;
wav = phased.RectangularWaveform('PulseWidth',pulse_width,'PRF',prf,'SampleRate',fs);
channel{1}.SampleRate = fs;
channel{2}.SampleRate = fs;
%% Transmitter platform and array
plat = phased.Platform('InitialPosition',[0; 0; -60],'Velocity',[0; 0; 0]);
proj = phased.IsotropicProjector('FrequencyRange',[0 30e3], ...
'VoltageResponse',80,'BackBaffled',true);
[ElementPosition,ElementNormal] = helperSphericalProjector(8,fc,propSpeed);
projArray = phased.ConformalArray('ElementPosition',ElementPosition, ...
'ElementNormal',ElementNormal,'Element',proj);
%% Receiver
hydro = phased.IsotropicHydrophone('FrequencyRange',[0 30e3],'VoltageSensitivity',-140);
rx = phased.ReceiverPreamp('Gain',20,'NoiseFigure',10,'SampleRate',fs, ...
'SeedSource','Property','Seed',2007);
%% Radiator/collector -- KEY CHANGE: radiator now accepts explicit steering weights
radiator = phased.Radiator('Sensor',projArray,'OperatingFrequency',fc, ...
'PropagationSpeed',propSpeed,'WeightsInputPort',true);
collector = phased.Collector('Sensor',hydro,'OperatingFrequency',fc, ...
'PropagationSpeed',propSpeed);
% Steering-vector object used to point the transmit beam at each scan angle
sv = phased.SteeringVector('SensorArray',projArray,'PropagationSpeed',propSpeed);
%% Define the azimuth scan sector
azScan = -60:2:60; % degrees -- the forward-look sector to be scanned
numAz = numel(azScan);
xmits = 10; % pulses non-coherently integrated per look direction
x = wav();
t = (0:size(x,1)-1)/fs;
sonarImage = zeros(size(x,1),numAz); % rows = range (time), cols = azimuth
%% Sweep azimuth and build the range-azimuth image
for k = 1:numAz
scanAng = [azScan(k); 0]; % [az; el] look direction for this column
w = sv(fc,scanAng); % transmit steering weights toward scanAng
rx_pulses = zeros(size(x,1),xmits);
for j = 1:xmits
[sonar_pos,sonar_vel] = plat(1/prf);
for i = 1:2 % loop over targets
[tgt_pos,tgt_vel] = tgtplat{i}(1/prf);
[paths,dop,aloss,tgtAng,srcAng] = isopath{i}( ...
sonar_pos,tgt_pos,sonar_vel,tgt_vel,1/prf);
% Radiate with the STEERED weights (points the main beam at
% azScan(k)) while srcAng still supplies the correct
% phase/geometry toward the true target bearing, so multipath
% propagation to the physical target location stays correct.
tsig = radiator(x,srcAng,w);
tsig = channel{i}(tsig,paths,dop,aloss);
tsig = tgt{i}(tsig,tgtAng);
rsig = collector(tsig,srcAng);
rx_pulses(:,j) = rx_pulses(:,j) + rx(rsig);
end
end
sonarImage(:,k) = abs(pulsint(rx_pulses,'noncoherent'));
end
%% Display 1: range-azimuth ("waterfall"/B-scan) image
range_axis = t*propSpeed/2; % one-way range from two-way travel time
figure
imagesc(azScan, range_axis, 20*log10(sonarImage./max(sonarImage(:))))
set(gca,'YDir','normal')
xlabel('Azimuth (deg)')
ylabel('Range (m)')
title('Forward-Look Sonar Image (Range-Azimuth)')
colormap('jet')
colorbar
caxis([-40 0])
%% Display 2: classic "fan"/polar forward-look sonar display
[AZ,RNG] = meshgrid(azScan,range_axis);
[Xd,Yd] = pol2cart(deg2rad(90-AZ),RNG); % 0 deg azimuth points "forward" (up)
figure
pcolor(Xd,Yd,20*log10(sonarImage./max(sonarImage(:))))
shading interp
axis equal tight
xlabel('Cross-range (m)')
ylabel('Along-range (m)')
title('Forward-Look Sonar Fan Display')
colormap('jet')
colorbar
caxis([-40 0])
function [ElementPosition,ElementNormal] = helperSphericalProjector(N,fc,prop_speed)
% This function helperSphericalProjector is only in support of
% ActiveSonarExample. It may be removed in a future release.
% Copyright 2016 The MathWorks, Inc.
azang = repmat((0:N-1)*360/(N)-180,N,1);
elang = repmat((0:N-1)'*180/(N-1)-90,1,N);
r = fc/prop_speed*ones(size(azang));
x = r.*cosd(elang).*cosd(azang);
y = r.*cosd(elang).*sind(azang);
z = r.*sind(elang);
ElementPosition = [x(:)';y(:)';z(:)'];
ElementNormal = [azang(:)';elang(:)'];
% [EOF]
end

제품

릴리스

R2026a

질문:

2026년 7월 14일 17:37

편집:

대략 12시간 전

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by