├── chapter_01 ├── main_chapter01_00_12a.pdf ├── main_chapter01_00_12b.pdf ├── main_chapter01_01_13.pdf ├── main_chapter01_03_16a.pdf ├── main_chapter01_03_16b.pdf ├── RadarConstants.py ├── main_chapter01_02.py ├── RadarEquations.py ├── chapter_01.py ├── main_chapter01_04.py ├── RadarBasics.py ├── main_chapter01_01.py ├── main_chapter01_00.py └── main_chapter01_03.py ├── LICENSE ├── README.md └── .gitignore /chapter_01/main_chapter01_00_12a.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AshivDhondea/simulations_radar_systems_design/HEAD/chapter_01/main_chapter01_00_12a.pdf -------------------------------------------------------------------------------- /chapter_01/main_chapter01_00_12b.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AshivDhondea/simulations_radar_systems_design/HEAD/chapter_01/main_chapter01_00_12b.pdf -------------------------------------------------------------------------------- /chapter_01/main_chapter01_01_13.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AshivDhondea/simulations_radar_systems_design/HEAD/chapter_01/main_chapter01_01_13.pdf -------------------------------------------------------------------------------- /chapter_01/main_chapter01_03_16a.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AshivDhondea/simulations_radar_systems_design/HEAD/chapter_01/main_chapter01_03_16a.pdf -------------------------------------------------------------------------------- /chapter_01/main_chapter01_03_16b.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AshivDhondea/simulations_radar_systems_design/HEAD/chapter_01/main_chapter01_03_16b.pdf -------------------------------------------------------------------------------- /chapter_01/RadarConstants.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on 21 October 2017 4 | 5 | Commonly used radar constants 6 | 7 | @author: Ashiv Dhondea 8 | """ 9 | # ---------------------------------------------------------------------------- # 10 | c = 299792458.; # [m/s] 11 | # --------------------------------------------------------------------------- # 12 | boltzmann_constant = 1.38064852e-23; # [watt sec/K] 13 | 14 | -------------------------------------------------------------------------------- /chapter_01/main_chapter01_02.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on 26 January 2018 4 | 5 | Listing 1.4. MATLAB Program “ref_snr.m” 6 | in Mahafza radar book 7 | 8 | @author: Ashiv Dhondea 9 | """ 10 | 11 | import RadarBasics as RB 12 | 13 | # ------------------------------------------------------------------------- # 14 | Rref = 86e3; # reference range 15 | tau_ref = 0.1e-6; # reference pulse width 16 | SNRref = 20.; # Ref SNR in dB 17 | snrref = RB.fn_dB_to_Power(SNRref) 18 | 19 | Sigmaref = 0.1; # ref RCS in m^2 20 | Lossp_dB = 2; # processing loss in dB 21 | lossp = RB.fn_dB_to_Power(Lossp_dB); 22 | # Enter desired value 23 | tau = tau_ref; 24 | R = 120e3; 25 | rangeratio = (Rref / R)**4; 26 | Sigma = 0.2; 27 | # Implement Eq. (1.60) 28 | snr = snrref * (tau / tau_ref) * (1. / lossp) * (Sigma / Sigmaref) * rangeratio; 29 | snr = RB.fn_Power_to_dB(snr) 30 | print('SNR at 120 km = %.1f dB' %snr) -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Ashiv Dhondea 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # simulations_radar_systems_design 2 | A bunch of Python scripts and modules built to emulate MATLAB files of the book "MATLAB simulations for radar systems design" by Mahafza & Elsherbeni; 3 | 4 | The book provides MATLAB code which, unfortunately, many people cannot run. I do not have a MATLAB license for my personal use, so I have decided to port some of the MATLAB code to Python to play around with and hopefully learn something. 5 | 6 | If you use the code provided here for projects or research papers, please cite this repo and, of course, cite the source of the original MATLAB code. 7 | 8 | Have fun with radar engineering! 9 | 10 | ### Prerequisites 11 | These scripts and modules use the typical Python libraries for computational science and engineering, such as numpy and matplotlib. In addition, to obtain nice plots with LaTeX annotations, you must have LaTeX on your computer. 12 | 13 | * **Ashiv Dhondea** - *Initial work* - [AshivDhondea](https://github.com/AshivDhondea) 14 | 15 | ## License 16 | 17 | This project is licensed under the MIT License - see the [LICENSE.md](https://github.com/AshivDhondea/simulations_radar_systems_design/blob/master/LICENSE) file for details 18 | 19 | ## Acknowledgments 20 | 21 | * This repo is built on MATLAB code provided for the book "MATLAB simulations for radar systems design" by Mahafza & Elsherbeni. The MATLAB files can be downloaded at https://www.crcpress.com/MATLAB-Simulations-for-Radar-Systems-Design/Mahafza-Elsherbeni/p/book/9781584883920 under the Resource/Downloads/Uploads tab. 22 | * The provision of the source MATLAB code for free is gratefully acknowledged. 23 | -------------------------------------------------------------------------------- /chapter_01/RadarEquations.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on 21 October 2017 4 | 5 | @author: Ashiv Dhondea 6 | """ 7 | import math 8 | import numpy as np 9 | 10 | import RadarBasics as RB 11 | import RadarConstants as RC 12 | 13 | # ------------------------------------------------------------------------- # 14 | def fnCalculate_ReceivedPower(P_Tx,G_Tx,G_Rx,rho_Rx,rho_Tx,wavelength,RCS): 15 | """ 16 | Calculate the received power at the bistatic radar receiver. 17 | 18 | equation 5 in " PERFORMANCE ASSESSMENT OF THE MULTIBEAM RADAR 19 | SENSOR BIRALES FOR SPACE SURVEILLANCE AND TRACKING" 20 | 21 | Note: ensure that the distances rho_Rx,rho_Tx,wavelength are converted to 22 | metres before passing into this function. 23 | 24 | Created on: 26 May 2017 25 | """ 26 | denominator = (4*math.pi)**3 * (rho_Rx**2)*(rho_Tx**2); 27 | numerator = P_Tx*G_Tx*G_Rx*RCS*(wavelength**2); 28 | P_Rx = numerator/denominator; 29 | return P_Rx 30 | 31 | def fnCalculate_ReceivedSNR(P_Rx,T0,bandwidth,radar_loss): 32 | """ 33 | Calculate the SNR at the bistatic radar receiver. 34 | 35 | equation 7 in " PERFORMANCE ASSESSMENT OF THE MULTIBEAM RADAR 36 | SENSOR BIRALES FOR SPACE SURVEILLANCE AND TRACKING" 37 | 38 | Note: output is not in decibels. 39 | 40 | Created on: 26 May 2017 41 | Edited: 42 | 21.10.17: included the term radar_loss, symbol L in eqn 1.56 in Mahafza radar book 43 | """ 44 | k_B = RC.boltzmann_constant; 45 | snr = P_Rx/(k_B*bandwidth*T0*radar_loss); 46 | return snr 47 | 48 | 49 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | 49 | # Translations 50 | *.mo 51 | *.pot 52 | 53 | # Django stuff: 54 | *.log 55 | local_settings.py 56 | 57 | # Flask stuff: 58 | instance/ 59 | .webassets-cache 60 | 61 | # Scrapy stuff: 62 | .scrapy 63 | 64 | # Sphinx documentation 65 | docs/_build/ 66 | 67 | # PyBuilder 68 | target/ 69 | 70 | # Jupyter Notebook 71 | .ipynb_checkpoints 72 | 73 | # pyenv 74 | .python-version 75 | 76 | # celery beat schedule file 77 | celerybeat-schedule 78 | 79 | # SageMath parsed files 80 | *.sage.py 81 | 82 | # dotenv 83 | .env 84 | 85 | # virtualenv 86 | .venv 87 | venv/ 88 | ENV/ 89 | 90 | # Spyder project settings 91 | .spyderproject 92 | .spyproject 93 | 94 | # Rope project settings 95 | .ropeproject 96 | 97 | # mkdocs documentation 98 | /site 99 | 100 | # mypy 101 | .mypy_cache/ 102 | -------------------------------------------------------------------------------- /chapter_01/chapter_01.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on 26 January 2018 4 | 5 | @author: Ashiv Dhondea 6 | """ 7 | import numpy as np 8 | import math 9 | import RadarBasics as RB 10 | import RadarConstants as RC 11 | 12 | # ------------------------------------------------------------------------- # 13 | speed_light = RC.c; # [m/s] 14 | # ------------------------------------------------------------------------- # 15 | def fn_Calc_PulseWidth_RadarEq(P_Tx, G_Tx, G_Rx, rho_Rx, rho_Tx, wavelength, RCS, snr, T0, radar_loss): 16 | """ 17 | Implements eqn 1.57 in Mahafza book. 18 | """ 19 | k_B = RC.boltzmann_constant; 20 | numerator = (4*math.pi)**3 * (rho_Rx**2)*(rho_Tx**2)*snr* k_B*T0*radar_loss; 21 | denominator = P_Tx*G_Tx*G_Rx*RCS*(wavelength**2); 22 | pulse_width = numerator/denominator; 23 | return pulse_width 24 | 25 | def fn_Calc_SearchVolume(az,el): 26 | """ 27 | az,el in deg 28 | eqn 1.61 in Mahafza book 29 | """ 30 | return az*el/(57.296**2) # steradians 31 | 32 | def fn_power_aperture(snr,tsc,rcs,rho,te,nf,loss,az_angle,el_angle): 33 | """ 34 | implements Listing 1.5. MATLAB Function “power_aperture.m” 35 | % This program implements Eq. (1.67) 36 | 37 | """ 38 | Tsc = RB.fn_Power_to_dB(tsc); # convert Tsc into dB 39 | Sigma = RB.fn_Power_to_dB(rcs);# convert sigma to dB 40 | four_pi = RB.fn_Power_to_dB(4.0 * math.pi); # (4pi) in dB 41 | k_B = RC.boltzmann_constant; 42 | k_db = RB.fn_Power_to_dB(k_B); # Boltzman’s constant in dB 43 | Te = RB.fn_Power_to_dB(te) #noise temp. in dB 44 | range_pwr4_db = RB.fn_Power_to_dB(rho**4); # target range^4 in dB 45 | omega = fn_Calc_SearchVolume(az_angle,el_angle) # compute search volume in steradians 46 | Omega = RB.fn_Power_to_dB(omega)# search volume in dB 47 | # implement Eq. (1.67) 48 | PAP = snr + four_pi + k_db + Te + nf + loss + range_pwr4_db + Omega - Sigma - Tsc; 49 | return PAP -------------------------------------------------------------------------------- /chapter_01/main_chapter01_04.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on 26 January 2018 4 | 5 | Chapter 1 example on power aperture product 6 | Mahafza book 7 | 8 | @author: Ashiv Dhondea 9 | """ 10 | import math 11 | import numpy as np 12 | 13 | import RadarBasics as RB 14 | import RadarConstants as RC 15 | 16 | # ------------------------------------------------------------------------- # 17 | def fn_Calc_SearchVolume(az,el): 18 | """ 19 | az,el in deg 20 | eqn 1.61 in Mahafza book 21 | """ 22 | return az*el/(57.296**2) # steradians 23 | 24 | def fn_power_aperture(snr,tsc,rcs,rho,te,nf,loss,az_angle,el_angle): 25 | """ 26 | implements Listing 1.5. MATLAB Function “power_aperture.m” 27 | % This program implements Eq. (1.67) 28 | 29 | """ 30 | Tsc = RB.fn_Power_to_dB(tsc); # convert Tsc into dB 31 | Sigma = RB.fn_Power_to_dB(rcs);# convert sigma to dB 32 | four_pi = RB.fn_Power_to_dB(4.0 * math.pi); # (4pi) in dB 33 | k_B = RC.boltzmann_constant; 34 | k_db = RB.fn_Power_to_dB(k_B); # Boltzman’s constant in dB 35 | Te = RB.fn_Power_to_dB(te) #noise temp. in dB 36 | range_pwr4_db = RB.fn_Power_to_dB(rho**4); # target range^4 in dB 37 | omega = fn_Calc_SearchVolume(az_angle,el_angle) # compute search volume in steradians 38 | Omega = RB.fn_Power_to_dB(omega)# search volume in dB 39 | # implement Eq. (1.67) 40 | PAP = snr + four_pi + k_db + Te + nf + loss + range_pwr4_db + Omega - Sigma - Tsc; 41 | return PAP 42 | 43 | 44 | 45 | # ------------------------------------------------------------------------- # 46 | T_sc = 2.; # [s] 47 | noise_fig_dB = 8. ;# [dB] 48 | 49 | losses_dB = 6.; 50 | rho=75e3; # [m] 51 | snr_req_dB = 20.; # [dB] 52 | 53 | T_e = 290; # [K] 54 | rcs = 3.162; # [m^2] 55 | 56 | az = 180.; 57 | el = 135.; 58 | PAP = fn_power_aperture(snr_req_dB,T_sc,rcs,rho,T_e,noise_fig_dB,losses_dB,az,el) 59 | print('power aperture product = %.1f dB' %PAP) -------------------------------------------------------------------------------- /chapter_01/RadarBasics.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on 21 October 2017 4 | 5 | Python functions implementing basic radar calculations 6 | 7 | Makes extensive use of numpy arrays to ensure that scalar and array inputs 8 | are both handled fine. 9 | 10 | Ref: 11 | 1. Principles of Modern Radar, vol 1. aka POMR 12 | 13 | @author: Ashiv Dhondea 14 | """ 15 | import math 16 | import numpy as np 17 | 18 | import RadarConstants as RC 19 | # ------------------------------------------------------------------------- # 20 | # The following functions are compatible with numpy array inputs. 21 | # e.g allow you to convert an array of power values to decibels easily. 22 | def fn_Power_to_dB(p): 23 | """ 24 | Convert power from watts to decibels 25 | """ 26 | return 10*np.log10(p); 27 | 28 | def fn_dB_to_Power(dB): 29 | """ 30 | Convert decibels to watts 31 | """ 32 | vec10 = 10.*np.ones_like(dB); 33 | exponents = 0.1*dB; 34 | return np.power(vec10,exponents) 35 | # ------------------------------------------------------------------------- # 36 | # Use numpy arrays for maximum flexibility wrt inputs 37 | def fnCalculate_Wavelength_or_Frequency(speed_light,freq): 38 | """ 39 | # wavelength in metres if speed_light in m/s and freq in hertz 40 | # frequency in hertz if speed_light in m/s and wavelenght in metres 41 | """ 42 | return np.divide(speed_light,freq ) 43 | # ------------------------------------------------------------------------- # 44 | def fnCalculate_Monostatic_RangeResolution(speed_light,bandwidth): 45 | """ 46 | Calculate the monostatic range resolution 47 | speed_light in [m/s] 48 | bandwidth in [Hz] 49 | """ 50 | return np.divide(speed_light,2*bandwidth) 51 | 52 | def fnCalculate_Monostatic_VelocityResolution(wavelength,pulse_width): 53 | """ 54 | Calculate the monostatic velocity resolution 55 | wavelength in [m] 56 | pulse_width in [s] 57 | """ 58 | return np.divide(wavelength,2*pulse_width) 59 | # ------------------------------------------------------------------------- # 60 | def fnCalculate_TimeBandwidthProduct(pulse_width,bandwidth): 61 | return np.multiply(pulse_width,bandwidth) -------------------------------------------------------------------------------- /chapter_01/main_chapter01_01.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on 26 January 2018 4 | 5 | implements Listing 1.3. MATLAB Program “fig1_13.m” 6 | in Mahafza radar book 7 | 8 | 9 | @author: Ashiv Dhondea 10 | """ 11 | import numpy as np 12 | import math 13 | 14 | import RadarBasics as RB 15 | import RadarConstants as RC 16 | 17 | # Importing what's needed for nice plots. 18 | import matplotlib.pyplot as plt 19 | from matplotlib import rc 20 | rc('font', **{'family': 'serif', 'serif': ['Helvetica']}) 21 | rc('text', usetex=True) 22 | params = {'text.latex.preamble' : [r'\usepackage{amsmath}', r'\usepackage{amssymb}']} 23 | plt.rcParams.update(params) 24 | 25 | # ------------------------------------------------------------------------- # 26 | speed_light = RC.c; # [m/s] 27 | # ------------------------------------------------------------------------- # 28 | # Radar parameters 29 | P_Tx = 1.e6; # [W] 30 | centre_freq = 5.6e9; #[Hz] 31 | G_Tx_dB = 40.; # [dB] 32 | G_Tx = RB.fn_dB_to_Power(G_Tx_dB) 33 | G_Rx = G_Tx; 34 | RCS = 0.1 #[m^2] 35 | te = 300.; # [K] 36 | nf = 5.; #[dB] 37 | 38 | T0 = RB.fn_dB_to_Power(nf)*te 39 | radar_loss = RB.fn_dB_to_Power(6.0); 40 | # ------------------------------------------------------------------------- # 41 | rho_Tx = np.array([75e3,100e3,150e3],dtype=np.float64) # [m] 42 | snr_db = np.linspace(5.,20.,200); # SNR values from 5 dB to 20 dB 200 points 43 | 44 | snr = RB.fn_dB_to_Power(snr_db); #10.^(0.1.*snr_db); % convert snr into base 10 45 | 46 | 47 | wavelength = RB.fnCalculate_Wavelength_or_Frequency(speed_light,centre_freq); # [m] 48 | 49 | def fn_Calc_PulseWidth_RadarEq(P_Tx, G_Tx, G_Rx, rho_Rx, rho_Tx, wavelength, RCS, snr, T0, radar_loss): 50 | """ 51 | Implements eqn 1.57 in Mahafza book. 52 | """ 53 | k_B = RC.boltzmann_constant; 54 | numerator = (4*math.pi)**3 * (rho_Rx**2)*(rho_Tx**2)*snr* k_B*T0*radar_loss; 55 | denominator = P_Tx*G_Tx*G_Rx*RCS*(wavelength**2); 56 | pulse_width = numerator/denominator; 57 | return pulse_width 58 | 59 | pulse_width_array = np.zeros([np.shape(rho_Tx)[0],np.shape(snr)[0]],dtype=np.float64); 60 | for i in range(0,np.shape(rho_Tx)[0]): 61 | for j in range(0,np.shape(snr)[0]): 62 | pulse_width_array[i,j] = fn_Calc_PulseWidth_RadarEq(P_Tx,G_Tx,G_Tx,rho_Tx[i],rho_Tx[i],wavelength,RCS,snr[j],T0,radar_loss) 63 | 64 | # ------------------------------------------------------------------------- # 65 | 66 | fig = plt.figure(1); 67 | ax = fig.gca() 68 | plt.rc('text', usetex=True) 69 | plt.rc('font', family='serif') 70 | fig.suptitle(r"\textbf{Pulse width versus required SNR for three different detection range values}" ,fontsize=12); 71 | i = 0; 72 | plt.semilogy(snr_db,1e6*pulse_width_array[i,:],label=r"$\rho = %0.1f~\mathrm{km}$" %(rho_Tx[i]/1e3)); 73 | i = 1; 74 | plt.semilogy(snr_db,1e6*pulse_width_array[i,:],linestyle='-.',label=r"$\rho = %0.1f~\mathrm{km}$" %(rho_Tx[i]/1e3)); 75 | i = 2; 76 | plt.semilogy(snr_db,1e6*pulse_width_array[i,:],linestyle='--',label=r"$\rho = %0.1f~\mathrm{km}$" %(rho_Tx[i]/1e3)); 77 | plt.xlim(5,20) 78 | 79 | ax.set_ylabel(r"Pulse width $\tau~[\mathrm{\mu s}]$") 80 | ax.set_xlabel(r'Minimum required SNR $[\mathrm{dB}]$'); 81 | plt.legend(loc='best') 82 | plt.grid(True,which='both',linestyle=(0,[0.7,0.7]),lw=0.4,color='black') 83 | fig.savefig('main_chapter01_01_13.pdf',bbox_inches='tight',pad_inches=0.11,dpi=10) -------------------------------------------------------------------------------- /chapter_01/main_chapter01_00.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on 21 October 2017 4 | 5 | implements Listing 1.2. MATLAB Program “fig1_12.m” 6 | in Mahafza radar book 7 | 8 | @author: Ashiv Dhondea 9 | """ 10 | 11 | import numpy as np 12 | 13 | import RadarBasics as RB 14 | import RadarConstants as RC 15 | import RadarEquations as RE 16 | 17 | # Importing what's needed for nice plots. 18 | import matplotlib.pyplot as plt 19 | from matplotlib import rc 20 | rc('font', **{'family': 'serif', 'serif': ['Helvetica']}) 21 | rc('text', usetex=True) 22 | params = {'text.latex.preamble' : [r'\usepackage{amsmath}', r'\usepackage{amssymb}']} 23 | plt.rcParams.update(params) 24 | 25 | # ------------------------------------------------------------------------- # 26 | speed_light = RC.c; # [m/s] 27 | # ------------------------------------------------------------------------- # 28 | # Radar parameters 29 | P_Tx = 1.5e6; # [W] 30 | centre_freq = 5.6e9; #[Hz] 31 | G_Tx_dB = 45.; # [dB] 32 | G_Tx = RB.fn_dB_to_Power(G_Tx_dB) 33 | G_Rx = G_Tx; 34 | RCS = 0.1 #[m^2] 35 | bandwidth = 5e6; # [Hz] 36 | te = 290.; # [K] 37 | nf = 3; #[dB] 38 | T0 = RB.fn_dB_to_Power(nf)*te 39 | radar_loss = RB.fn_dB_to_Power(6.0); 40 | 41 | wavelength = RB.fnCalculate_Wavelength_or_Frequency(speed_light,centre_freq); 42 | 43 | rho_Tx = np.linspace(25e3,165e3,1000); # target range 25 -165 km, 1000 points 44 | 45 | P_Rx1 = np.zeros([np.shape(rho_Tx)[0]],dtype=np.float64); 46 | P_Rx2 = np.zeros([np.shape(rho_Tx)[0]],dtype=np.float64); 47 | P_Rx3 = np.zeros([np.shape(rho_Tx)[0]],dtype=np.float64); 48 | snr_Rx_1 = np.zeros([np.shape(rho_Tx)[0]],dtype=np.float64); 49 | snr_Rx_2 = np.zeros([np.shape(rho_Tx)[0]],dtype=np.float64); 50 | snr_Rx_3 = np.zeros([np.shape(rho_Tx)[0]],dtype=np.float64); 51 | 52 | 53 | snr_Rx_2_04 = np.zeros([np.shape(rho_Tx)[0]],dtype=np.float64); 54 | snr_Rx_3_18 = np.zeros([np.shape(rho_Tx)[0]],dtype=np.float64); 55 | 56 | for index in range(len(rho_Tx)): 57 | P_Rx1[index] = RE.fnCalculate_ReceivedPower(P_Tx,G_Tx,G_Rx,rho_Tx[index],rho_Tx[index],wavelength,RCS); 58 | P_Rx2[index] = RE.fnCalculate_ReceivedPower(P_Tx,G_Tx,G_Rx,rho_Tx[index],rho_Tx[index],wavelength,RCS/10.); 59 | P_Rx3[index] = RE.fnCalculate_ReceivedPower(P_Tx,G_Tx,G_Rx,rho_Tx[index],rho_Tx[index],wavelength,RCS*10.); 60 | snr_Rx_1[index] = RE.fnCalculate_ReceivedSNR(P_Rx1[index],T0,bandwidth,radar_loss); 61 | snr_Rx_2[index] = RE.fnCalculate_ReceivedSNR(P_Rx2[index],T0,bandwidth,radar_loss) 62 | snr_Rx_3[index] = RE.fnCalculate_ReceivedSNR(P_Rx3[index],T0,bandwidth,radar_loss) 63 | 64 | snr_Rx_2_04[index] = RE.fnCalculate_ReceivedSNR(P_Rx1[index]*0.4,T0,bandwidth,radar_loss) 65 | snr_Rx_3_18[index] = RE.fnCalculate_ReceivedSNR(P_Rx1[index]*1.8,T0,bandwidth,radar_loss) 66 | 67 | snr_Rx_1_dB = RB.fn_Power_to_dB(snr_Rx_1); 68 | snr_Rx_2_dB = RB.fn_Power_to_dB(snr_Rx_2); 69 | snr_Rx_3_dB = RB.fn_Power_to_dB(snr_Rx_3); 70 | 71 | rcs1 = RB.fn_Power_to_dB(RCS); 72 | rcs2 = RB.fn_Power_to_dB(RCS/10.) 73 | rcs3 = RB.fn_Power_to_dB(RCS*10.) 74 | 75 | snr_Rx_2_04_dB = RB.fn_Power_to_dB(snr_Rx_2_04); 76 | snr_Rx_3_18_dB = RB.fn_Power_to_dB(snr_Rx_3_18); 77 | 78 | # ------------------------------------------------------------------------- # 79 | 80 | fig = plt.figure(1); 81 | ax = fig.gca() 82 | plt.rc('text', usetex=True) 83 | plt.rc('font', family='serif') 84 | fig.suptitle(r"\textbf{SNR versus detection range for three different values of RCS}" ,fontsize=12); 85 | plt.plot(rho_Tx/1000.,snr_Rx_3_dB,label=r"$\sigma = %f~\mathrm{dBsm}$" %rcs3) 86 | plt.plot(rho_Tx/1000.,snr_Rx_1_dB,linestyle='-.',label=r"$\sigma = %f~\mathrm{dBsm}$" %rcs1) 87 | plt.plot(rho_Tx/1000.,snr_Rx_2_dB,linestyle='--',label=r"$\sigma = %f~\mathrm{dBsm}$" %rcs2) 88 | ax.set_ylabel(r"SNR $[\mathrm{dB}]$") 89 | ax.set_xlabel(r'Detection range $[\mathrm{km}]$'); 90 | plt.legend(loc='best') 91 | plt.grid(True,which='both',linestyle=(0,[0.7,0.7]),lw=0.4,color='black') 92 | fig.savefig('main_chapter01_00_12a.pdf',bbox_inches='tight',pad_inches=0.11,dpi=10) 93 | 94 | fig = plt.figure(2); 95 | ax = fig.gca() 96 | plt.rc('text', usetex=True) 97 | plt.rc('font', family='serif') 98 | fig.suptitle(r"\textbf{SNR versus detection range for three different values of radar peak power}" ,fontsize=12); 99 | plt.plot(rho_Tx/1000.,snr_Rx_3_18_dB,label=r"$P_\text{Tx} = 2.16~\mathrm{MW}$") 100 | plt.plot(rho_Tx/1000.,snr_Rx_1_dB,linestyle='-.',label=r"$P_\text{Tx} = 1.5~\mathrm{MW}$") 101 | plt.plot(rho_Tx/1000.,snr_Rx_2_04_dB,linestyle='--',label=r"$P_\text{Tx} = 0.6~\mathrm{MW}$" ) 102 | ax.set_ylabel(r"SNR $[\mathrm{dB}]$") 103 | ax.set_xlabel(r'Detection range $[\mathrm{km}]$'); 104 | plt.legend(loc='best') 105 | plt.grid(True,which='both',linestyle=(0,[0.7,0.7]),lw=0.4,color='black') 106 | fig.savefig('main_chapter01_00_12b.pdf',bbox_inches='tight',pad_inches=0.11,dpi=10) 107 | -------------------------------------------------------------------------------- /chapter_01/main_chapter01_03.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on 26 January 2018 4 | 5 | Listing 1.5 and 1.6 6 | in Mahafza radar book 7 | creates fig 1-16 8 | 9 | @author: Ashiv Dhondea 10 | """ 11 | import math 12 | import numpy as np 13 | 14 | import RadarBasics as RB 15 | import RadarConstants as RC 16 | 17 | # Importing what's needed for nice plots. 18 | import matplotlib.pyplot as plt 19 | from matplotlib import rc 20 | rc('font', **{'family': 'serif', 'serif': ['Helvetica']}) 21 | rc('text', usetex=True) 22 | params = {'text.latex.preamble' : [r'\usepackage{amsmath}', r'\usepackage{amssymb}']} 23 | plt.rcParams.update(params) 24 | # ------------------------------------------------------------------------- # 25 | 26 | def fn_Calc_SearchVolume(az,el): 27 | """ 28 | az,el in deg 29 | eqn 1.61 in Mahafza book 30 | """ 31 | return az*el/(57.296**2) # steradians 32 | 33 | def fn_power_aperture(snr,tsc,rcs,rho,te,nf,loss,az_angle,el_angle): 34 | """ 35 | implements Listing 1.5. MATLAB Function “power_aperture.m” 36 | % This program implements Eq. (1.67) 37 | 38 | """ 39 | Tsc = RB.fn_Power_to_dB(tsc); # convert Tsc into dB 40 | Sigma = RB.fn_Power_to_dB(rcs);# convert sigma to dB 41 | four_pi = RB.fn_Power_to_dB(4.0 * math.pi); # (4pi) in dB 42 | k_B = RC.boltzmann_constant; 43 | k_db = RB.fn_Power_to_dB(k_B); # Boltzman’s constant in dB 44 | Te = RB.fn_Power_to_dB(te) #noise temp. in dB 45 | range_pwr4_db = RB.fn_Power_to_dB(rho**4); # target range^4 in dB 46 | omega = fn_Calc_SearchVolume(az_angle,el_angle) # compute search volume in steradians 47 | Omega = RB.fn_Power_to_dB(omega)# search volume in dB 48 | # implement Eq. (1.67) 49 | PAP = snr + four_pi + k_db + Te + nf + loss + range_pwr4_db + Omega - Sigma - Tsc; 50 | return PAP 51 | # ------------------------------------------------------------------------- # 52 | tsc = 2.5; # Scan time is 2.5 seconds 53 | rcs = 0.1; # radar cross section in m squared 54 | te = 900.0; # effective noise temperature in Kelvins 55 | snr = 15; # desired SNR in dB 56 | nf = 6.0; #noise figure in dB 57 | loss = 7.0; # radar losses in dB 58 | 59 | az_angle = 2.; # search volume azimuth extent in degrees 60 | el_angle = 2.; # search volume elevation extent in degrees 61 | rho_Tx = np.linspace(20e3,250e3,1000); # range to target 20 Km 250 Km, 1000 points 62 | 63 | 64 | rcs_array = np.array([rcs/10,rcs,rcs*10.],dtype=np.float64); 65 | rcs_array_db = RB.fn_Power_to_dB(rcs_array) 66 | power_aperture = np.zeros([np.shape(rcs_array)[0],np.shape(rho_Tx)[0]],dtype=np.float64); 67 | for i_rho in range(0,np.shape(rho_Tx)[0]): 68 | for i_rcs in range(0,np.shape(rcs_array)[0]): 69 | power_aperture[i_rcs,i_rho] = fn_power_aperture(snr,tsc,rcs_array[i_rcs],rho_Tx[i_rho],te,nf,loss,az_angle,el_angle); 70 | 71 | 72 | # ------------------------------------------------------------------------- # 73 | fig = plt.figure(1); 74 | ax = fig.gca() 75 | plt.rc('text', usetex=True) 76 | plt.rc('font', family='serif') 77 | fig.suptitle(r"\textbf{Power aperture product versus detection range}" ,fontsize=12); 78 | i = 0; 79 | plt.plot(rho_Tx/1e3,power_aperture[i,:],label=r"$\sigma = %0.1f~\mathrm{dBsm}$" %rcs_array_db[i]); 80 | i = 1; 81 | plt.plot(rho_Tx/1e3,power_aperture[i,:],linestyle='-.',label=r"$\sigma = %0.1f~\mathrm{dBsm}$" %rcs_array_db[i]); 82 | i = 2; 83 | plt.plot(rho_Tx/1e3,power_aperture[i,:],linestyle='--',label=r"$\sigma = %0.1f~\mathrm{dBsm}$" %rcs_array_db[i]); 84 | 85 | ax.set_ylabel(r"Power aperture product $[\mathrm{dB}]$") 86 | ax.set_xlabel(r'Detection range $[\mathrm{km}]$'); 87 | plt.legend(loc='best') 88 | plt.grid(True,which='both',linestyle=(0,[0.7,0.7]),lw=0.4,color='black') 89 | fig.savefig('main_chapter01_03_16a.pdf',bbox_inches='tight',pad_inches=0.11,dpi=10) 90 | # ------------------------------------------------------------------------- # 91 | 92 | wavelength = 0.03; # wavelength in meters 93 | G = 45; # antenna gain in dB 94 | ae = np.linspace(1.,25.,1000);# aperture size 1 to 25 meter squared, 1000 points 95 | Ae = RB.fn_Power_to_dB(ae) 96 | rho = 250e3; # range of interest is 250 Km 97 | pap = np.zeros([np.shape(rcs_array)[0]],dtype=np.float64); 98 | Pave = np.zeros([np.shape(rcs_array)[0],np.shape(Ae)[0]],dtype=np.float64); 99 | 100 | for i in range(0,np.shape(pap)[0]): 101 | pap[i] = fn_power_aperture(snr,tsc,rcs_array[i],rho,te,nf,loss,az_angle,el_angle); 102 | for j in range(0,np.shape(Ae)[0]): 103 | Pave[i,j] = pap[i] - Ae[j]; 104 | # ------------------------------------------------------------------------- # 105 | fig = plt.figure(2); 106 | ax = fig.gca() 107 | plt.rc('text', usetex=True) 108 | plt.rc('font', family='serif') 109 | fig.suptitle(r"\textbf{Radar average power versus power aperture product}" ,fontsize=12); 110 | i = 0; 111 | plt.plot(ae,Pave[i,:],label=r"$\sigma = %0.1f~\mathrm{dBsm}$" %rcs_array_db[i]); 112 | i = 1; 113 | plt.plot(ae,Pave[i,:],linestyle='-.',label=r"$\sigma = %0.1f~\mathrm{dBsm}$" %rcs_array_db[i]); 114 | i = 2; 115 | plt.plot(ae,Pave[i,:],linestyle='--',label=r"$\sigma = %0.1f~\mathrm{dBsm}$" %rcs_array_db[i]); 116 | 117 | ax.set_ylabel(r"$P_{\text{av}}~[\mathrm{dB}]$") 118 | ax.set_xlabel(r'Aperture size $[\mathrm{m^2}]$'); 119 | plt.legend(loc='best') 120 | plt.grid(True,which='both',linestyle=(0,[0.7,0.7]),lw=0.4,color='black') 121 | fig.savefig('main_chapter01_03_16b.pdf',bbox_inches='tight',pad_inches=0.11,dpi=10) 122 | 123 | 124 | --------------------------------------------------------------------------------