Creating Graphics For The Channel Impulse Response in Underwater Acoustics With MATLAB

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 9

Creating graphics for the channel impulse response

in underwater acoustics with MATLAB


Leon Nguyen
lnn009@ucsd.edu
Version 1.0 August 21, 2015

(1) ASRA Sta06 (Tx4) VLA2: JD1440833


0
24
27.75
31.5

35.25

10

46.5
50.25
15
54
57.75
61.5

20

65.25
69
25

72.75
76.5
80.25
45

50

55

60
65
Time Delay (ms)

70

75

80

30

Normalized magnitude (dB)

Rx Channel Depth (m)

39
42.75

Introduction

The channel impulse response (CIR) is an important measure for any medium
of communication. From LTI theory, an impulse response allows for a system output to be predicted based on the system input. Because many
channels for communication are time-varying, having frequent updates of
the CIR (known as channel probing) is key to being able to interpret communications sequences. This is a brief tutorial that goes over the process of
creating CIR plots via MATLAB 2014a.
We will use the Shallow-water Acoustic Variability EXperiment 2015 (SAVEX15)
dataset obtained by the Marine Physical Laboratory. The SAVEX15 experiment carried out research to explore the use of underwater acoustics as a
means of communication. Being able to communicate underwater would
allow for autonomous underwater vehicles (AUVs) to perform environmental monitoring and ocean exploration while continuously sending data back
to research labsthis would eliminate the need for expensive sea trips and
would allow for higher-frequency data collection.

Experiment Background

SAVEX15 took place in shallow waters of 100 m depth from May 1428,
2015 in an area 100 km southwest of Jeju Island, Korea in the Northern
East China Sea.
The the method for the channel probing experiments from SAVEX15 can
be simply stated: play a channel probing sound signal from a transducer
and record it with a receiver positioned some kilometers away from the
transducer. There were two main sets of experiments: the first involved
a stationary source and a stationary receiver, and the second involved a
moving source and a stationary receiver. In the former, the source was a
vertical array of 8 elements with 7.5 m of spacing in between, and the first
transducer was positioned at a depth of 20 m. Each transducer is played
one-at-a-time in a round-robin format to observe the effect of source depth
on acoustic propagation. In the latter, the source was attached to a vessel
at a depth of around 4050 m while the vessel was towed by the ship at
a speed of about 1.52 m/s. In both cases, the receiver recorded audio at
100 kHz and it consisted of a vertical array of 16 elements with 3.75 m of
spacing in between, where the first receiver was positioned at a depth of 24

m. The receiver also high-pass filtered the signal with a cutoff frequency of
500 Hz to remove low frequency ship noise.
For the stationary source experiments, the transmission schedule repeated
every hour, and each minute consisted of a transmission. There were 16
minutes from the hour devoted to channel probing source signals. For the
moving source experiments, the transmission schedule repeated every 4 minutes, with the first minute being devoted to channel probing. The source
signals consisted of variations of linear frequency modulated (LFM) chirps
and maximal length sequences (MLS), also known as m-sequences. The
LFM chirp was 60 ms long, and it was appended with 60 ms of silence to repeat periodically every 120 ms. The MLS period ranged from 25.5127 ms,
and they were repeated periodically without any silence in between. Both
source signals were repeated to fill up about 55 seconds of the minute.

Recipe

We will follow a simple method for obtaining the CIR:


1. Read the source signal and the received signal time series
2. Compensate for Doppler effect time compression or dilation in the
received signal if there is relative motion between the source and the
receiver
3. Use matched filtering to obtain a CIR estimate
4. Take the real part of the analytic signal to obtain an envelope of the
matched filter output
5. Rearrange the envelope time series into a matrix that displays a timevarying CIR plot

3.1

Reading the source and receiver signals

First, we want to save one period of our source sequences into a .mat file
so we can easily call load() in our MATLAB script. If we are given the
whole 1 minute source file, we only want to extract one period of the source
signal. For the LFM chirp, it is only necessary to save the 60 ms of the chirp
sounding. For extracting one period of a MLS, it is useful to know parameters such as the symbol rate or duration (which tell us how many samples it
3

takes to convey one digit, or symbol, of the MLS), the degree of generating
polynomial (which tells us how many symbols there are in one period), the
sequence duration (which is derived from the previous two measures to tell
us the length of one period), and the group delay of the filter used to pulse
shape the MLS (which tells us when the source sequence begins). It might
be useful to call plot() and cross-reference the waveform with the MLS
symbols to confirm that the extracted period is correct.
Second, to read the received signal, we need to use the proprietary sioread()
function to decode the recorded signals. It is possible to read all of the receiver channels at once, which will create an n m matrix with n being the
amount of samples in the recording and m being the number of channels.
As such, the matrix is organized column-wise, where each column represents
the recording of a specific channel.
If processing is to be done in the baseband, frequency shift the spectral components of the signal to zero frequency (baseband) by point-wise multiplying
the time signal with
exp(1i*2*pi*carrierFrequency*timeIndex(1:numel(signal))).
Note that in the moving source experiments, an additional frequency shift
is needed to account for the Doppler frequency shift (detailed in the next
section) in the received signal. Afterwards, low-pass filter the baseband
signal and downsample() to take advantage of the bandwidth. If filtering is
done with an IIR filter higher than the second order, create a more accurate
filter by splitting the filter up into a cascade of biquadratic filters, or secondorder sections. This is preferable because quantization from computational
precision errors in calculating transfer function coefficients can change the
location of finely-placed poles and zeros, potentially causing an unstable
filter. To implement, request the zeros, poles, and gain form of the filter,
e.g. [z,p,k] = butter(n,Wn). Then call [sos,g] = zp2sos(z,p,k) to
get the second-order section form of the filter along with the gain, and filter
via sosfilt(sos,signal)*g. If filtering is done with an FIR filter, then
an efficient polyphase filter can be implemented with consideration of the
downsampling factor to achieve lower-order FIR filters.

3.2

Doppler effect compensation

To undo the time compression or dilation associated with the Doppler effect
in the moving source experiments, we need to resample the received signal
[1]. This can be done with interp1(x,v,xq,linear), where x is the
original time index according to the sampling frequency, and v is the signal
to be interpolated to the new time index xq. If
x = (0:numberOfSamples - 1)/samplingFrequency,
then
xq = (0:numberOfSamples*(1 - beta) - 1)/(samplingFrequency*(1 beta)).
The Doppler parameter beta = radialVelocity/c tells us the resampling
rate as a function of the radial velocity component and the speed of sound,
where the radial velocity is defined positive for motion away from the receiver (time dilation) and negative for motion towards the receiver (time
compression). Be sure to use a rounding function such as ceil() to ensure
that the final time index in xq is an integer.
To find the right radial velocity value, it may be useful to create a separate
function that performs matched filtering (detailed in the next section) on a
signal that has been Doppler compensated for a wide range of radial velocity
values. This allows us to see which radial velocity value returns the greatest
matched filter output and gives us a good approximation for the correct
Doppler compensation. Since our moving source is moving around 1.52
m/s, we can test various values in steps of 0.01 m/s between 2.5 and 2.5
m/s. This clearly means that a lot of resampling and matched filtering will
be done, so we can expedite the process by resampling the shorter source
signal instead of the longer received signal and matched filtering to only
the first 3 periods of the received signal. We can go even further to reduce
the source signal by only considering, for example, half of its MLS symbols.
Because the source signal will be short, the resampling may not actually
change the signal because the resampling rate is very close to unity for our
range of Doppler parameters. Therefore, we can interpolate our source signal with interp(), perform the resampling, and interpolating the 3 period
portion of the received signal before matched filtering.

For Doppler compensation in the baseband, there is a Doppler frequency


shift dopplerFrequency = beta*carrierFrequency which must be taken
into account to properly shift the received signal to baseband. Therefore,
we add this Doppler frequency to the carrier frequency when performing the
frequency shift.

3.3

Matched filtering

To perform matched filtering, simply flip the source signal with flipud()
and use fftfilt() to do a frequency-domain matched filtering. If processing is done in the baseband, take the complex conjugate of the source signal
with conj() in addition to flipping, and take the complex magnitude of the
matched filter output via abs() to avoid complex arithmetic in subsequent
steps.
To detect the first matched filter output peak, set up a threshold to create
a binary vector, e.g. output > threshold. It might be more tractable to
compare the threshold to the derivative of the matched filter output via
diff(), then take max() of the resulting binary vector to get the time index
that corresponds to the first matched filter output that clears the threshold.
Because we are working with multiple channels, through [~,indices] =
max(thresholdDetections == 1,[],1), we will get a row vector of time
indices that correspond to the first matched filter peak of each channel column vector. To find a suitable time index to represent all of the channels,
throw away any time indices that fail to meet the threshold or are not within
a reasonable time range where the first peak would appear. Then take the
time index that is closest to the median of the remaining time indicesthis
should give a robust starting time period for all of the receiving channels
and even for subsequent transmissions in the stationary source experiments.
Once the time index of the first matched filter peak is known, we can use
our knowledge of how many repetitions of the period there are to truncate
the matched filter output from a half-period before the first peak and a
half-period after the last peak.

3.4

Taking the envelope

The envelope creates a smooth waveform of the matched filter output, which
oscillates to the carrier frequency. Simply use abs(hilbert())note that
hilbert() calculates the analytic signal instead of the Hilbert transform,

so we are in fact taking the real part of the analytic signal. If processing
is done in the baseband, the envelope was already attained by taking the
complex magnitude of the matched filter output.

3.5

Reshaping to create a CIR plot

At this point, we have a matrix of column-wise envelopes of the matched


filter outputs for each receiver channel. Each column contains a series of
matched filter peaks, and there are as many peaks per column as the number of times the source signal was repeated within the 1 minute transmission.
We want to reshape each column into a matrix that shows the CIR, then
concatenate all of the matrices vertically. Each matrix displays an CIR of
one particular receiver channel, and since the receiver array oriented the
channels vertically in the water column, a natural display of all of the receiver channels would be to vertically stack their individual CIRs to observe
the acoustic propagation and multipath of the overall channel.
One way to accomplish this would be to first reshape the 2-dimensional
matrix of column-wise envelopes into a 3-dimensional matrix of page-wise
CIRs, where we use pages to refer to the third dimension. This can be done
by
reshape(envelopes,samplesPerPeriod,numberOfRepetitions,numberOfChannels).
Now, each page has a periods worth of samples organized row-wise on the
y-axis, and the 1-minute-transmissions worth of samples organized columnwise on the x-axis. We refer to the first quantity as time delay because it
shows how the CIR is delayed, or spread out, over a certain time interval,
and we refer to the second quantity as geotime, which shows how the CIR
changes over time.
We want to eventually display time delay column-wise on the x-axis so that
the y-axis can more-naturally convey the depth of the receiver channel in the
water column. Therefore, we can transpose each page of the 3-dimensional
matrix by a 2-1-3 permutation via permute(). Note that because reshape()
(and MATLAB in general) redistributes elements column-wise first, we cannot perform the transpose operation within the reshape() call, and thus
we need to use permute() afterwards.
Because we want to reshape() the 3-dimensional matrix once more to stack
7

all of the pages in a 2-dimensional matrix, we need another permutation so


that the pages are stacked vertically after the reshape(). As such, for a
pure indexing reason, we want to permute 1-3-2. Ergo, we can combine
the previous transpose operation permutation with this one to achieve a
2-3-1 permutation via permute(CIR,[2 3 1]). Finally, we can perform the
aforementioned reshape() to arrive back to a 2-dimensional matrix with
reshape(CIR,numberOfRepetitions*numberOfChannels,samplesPerPeriod,1).
Afterwards, we can normalize the matrix for plotting purposes and plot the
CIR via imagesc(). An example is shown below. On the left is a CIR for
one channel. On the right is each of the 16 channel CIRs vertically stacked,
where we suppress the geotime information in favor of the water column
depth of each receiver element.

55
50
Rx Channel Depth (m)

45

Geotime (s)

40
35
30
25
20
15
10
5
0 2 4 6 8 10 12 14 16 18
Time Delay (ms)

24
27.75
31.5
35.25
39
42.75
46.5
50.25
54
57.75
61.5
65.25
69
72.75
76.5
80.25
0 2 4 6 8 10 12 14 16 18
Time Delay (ms)

Figure 1: The single CIR on the left represents the fifth receiver element at
42.75 m on the right. These color plots show a 30 dB range.

3.6

Creating an animation

After batch-processing a series of CIRs for a multi-hour transmission, a nice


way to visualize how the CIR changes throughout the hours of the transmission is to make an animated .gif. It is convenient to number the filenames
of the CIRs when batch processing so that when viewed in a folder, the
alphabetical ordering of the filenames correspond with the chronological ordering of the CIRs. Then, one can use a program such as ImageMagick to
batch process the creation of these animated .gif movies with a script. An
example call would be
convert -delay 50 -loop 0 ~/folder/*.png ~/folder/movie.gif,
where -delay 50 indicates a 50 ms delay between the frames of the animation, -loop 0 indicates an infinite number of loops of the animation, and
*.png indicates to take all of the .png image files in the folder to use as
frames in the animation. This is why it is useful to alphabetically order the
filenames so that the animation frames show the chronological evolution of
the CIR.

Postface

Hopefully, in future versions, Ill get to refine the prose, include more graphics, add an appendix that contains background material for the signal processing concepts employed, and compare the IIR filters created in MATLAB
via transfer function coefficients versus a series of biquadratic filters represented by a second-order section.

References
[1] H. C. Song. Time reversal communication with a mobile source. The
Journal of the Acoustical Society of America, 134(4):26232626, 2013.

You might also like