파이썬을 이용한 재밍에 대한 효과와 레이다의 탐지 성능에의 영향을 한 번에 볼 수 있는 툴을 만들어 보고 이에 대한 파이썬 코드를 소개한다.
파이썬 코드의 기본적인 구조는 ChatGPT를 통해 만들었다.
개 요
이번에 설명할 분석 툴은 재밍 신호에 의해 레이다의 성능이 어떻게 바뀌는지 알아볼 수 있다.
재밍 신호에 의한 레이다의 성능은 Burn-through Range의 변화와 레이다 탐지확률의 변화로 확인한다.
기본적으로 레이다 파라미터를 정의하고 재머의 제원도 정의하여 수식에 의해 Burn-through Range와 레이다의 탐지확률 그래프를 결과로 나타낸다.
사실, 이 프로그램은 이전에 이미 만들었던 것으로 아래의 글에 이론적인 원리나 수식, 의미에 대해서 확인할 수 있다.
Jamming 효과 분석 방법
재밍 신호가 상대 레이다에 대해 어느 정도의 효과가 있는 지를 분석하는 방법 중 기본이 되는 것에는 Burn-Through Range 분석과 레이다 탐지 확률 분석이 있다. 여기서 Burn-Through Range와 자체보호용
superhky.tistory.com
다만 이전에 프로그램과는 약간의 수정을 하였다.
이전 프로그램은 레이다 파라미터와 재머의 파라미터를 일일이 입력을 해야 했는데, 여기에서는 값을 쉽게 바꿀 수 있는 slide bar를 사용하고 또한 interactive 방식을 사용하여 바뀐 값은 바로 결과에 영향을 주도록 수정하였다.
파이썬 코드 설명
파이썬 프로그램을 전문적으로 배우지 않은 상태에서 이전의 프로그램은 구글링으로 하나하나 찾아가면서 코딩을 하였다.
그러나 이번에는 레이다 방정식이나 SNR, JSR과 같은 이론적인 수식을 제외하고는 ChatGPT를 통해 프로그래밍하였다.
우선은 기본적인 요구사항을 잘 정리하여 ChatGPT로 기본 프로그램 골격을 만든다.
예를 들면, 레이다 파라미터를 입력하고 입력에 대한 결과를 그래프로 출력하며 Interactive 한 방식으로 결과를 업데이트할 수 있는 기능을 요구하는 방식이다.
이런 식으로 기본적인 프로그램의 기본 골격이 만들어지면 여기서부터 직접 확장해 나가던지 아니면 점점 더 디테일한 요구사항을 ChatGPT에 요구하여 만들어 나가도 된다.
이렇게 해서 만든 프로그램의 결과 화면은 다음과 같다.

왼쪽은 레이다 파라미터와 재머 파라미터를 slid bar를 이용하여 입력하면 결과는 Burn-Through Range와 Radar Detection Probability에 직접 영향을 주어 결과가 바로 변화하게 된다.
파이썬 프로그램의 구조는 Class의 하부에 여러 definition들로 구성된다.
Definition들은 화면을 구성하기 위한 정의, 입력 slide bar에 기능을 넣기 위한 정의, 결과 그래프를 업데이트하기 위한 정의로 구성된다.
[ 화면 구성 Definition ]
def __init__(self):
super(MyWindow, self).__init__()
self.setWindowTitle("Interactive Radar-Jammer Effectiveness Plot")
# Main widget and layout
self.main_widget = QWidget()
self.main_layout = QHBoxLayout() # Horizontal layout for parameters and graphics
self.main_widget.setLayout(self.main_layout)
self.setCentralWidget(self.main_widget)
# Left side layout (parameters)
self.parameters_layout = QVBoxLayout()
self.main_layout.addLayout(self.parameters_layout)
# Graphics layout (right side)
self.graphics_layout = QVBoxLayout()
self.main_layout.addLayout(self.graphics_layout)
# Add graphics to the right side
self.graphicsView_1 = pg.PlotWidget(title="Burn-Through Range")
self.graphicsView_1.setBackground('w')
self.graphicsView_1.setLabel('left', 'Power at radar receiver (dBm)')
self.graphicsView_1.setLabel('bottom', 'Range from radar to target (m)')
self.graphicsView_1.addLegend()
self.graphicsView_1.showGrid(x=True, y=True)
self.graphicsView_2 = pg.PlotWidget(title="Radar Detection Probability with Jammer")
self.graphicsView_2.setBackground('w')
self.graphicsView_2.setLabel('left', 'Radar Detection Probability')
self.graphicsView_2.setLabel('bottom', 'Range from radar to target (m)')
self.graphicsView_2.showGrid(x=True, y=True)
self.graphics_layout.addWidget(self.graphicsView_1)
self.graphics_layout.addWidget(self.graphicsView_2)
# Add "RADAR PARAMETERS" title
self.sliders_title = QLabel("RADAR PARAMETERS")
self.sliders_title.setStyleSheet("font-size: 25px; font-weight: bold; margin: 10px 0;")
self.parameters_layout.addWidget(self.sliders_title)
# Sliders layout for radar
self.sliders_layout = QVBoxLayout()
self.sliders = {}
self.slider_labels = {}
# Add sliders for radar parameters
self.add_slider("freq", "Frequency (Hz)", 1e8, 10e9, 9e9, step=1e8)
self.add_slider("pt", "Transmit Power (W)", 10, 10e6, 100e3, step=10)
self.add_slider("gt", "Tx Antenna Gain (dB)", 1, 1e3, 35)
self.add_slider("gr", "Rx Antenna Gain (dB)", 1, 1e3, 35)
self.add_slider("bn", "Receive Bandwidth (Hz)", 1e3, 100e6, 5e6, step=1e3)
self.add_slider("fn", "Noise Coefficient (dB)", 1, 100, 3)
self.add_slider("ls", "System Loss (dB)", 1, 100, 5)
self.add_slider("sig", "Target RCS (dBsm)", 0, 100, 10)
self.parameters_layout.addLayout(self.sliders_layout)
# Add "JAMMER PARAMETERS" title
self.sliders_title_1 = QLabel("JAMMER PARAMETERS")
self.sliders_title_1.setStyleSheet("font-size: 25px; font-weight: bold; margin: 10px 0;")
self.parameters_layout.addWidget(self.sliders_title_1)
# Sliders layout for jammer
self.sliders_layout_1 = QVBoxLayout()
self.sliders_1 = {}
self.slider_labels_1 = {}
# Add sliders for jammer parameters
self.add_slider_1("pj", "Jamming Power (W)", 1, 10e3, 10, step=10)
self.add_slider_1("gj", "Antenna Gain (dB)", 0, 1e3, 1e-10, step=1)
self.add_slider_1("jn", "Jamming Bandwidth (Hz)", 1, 1e9, 20e6, step=100)
self.add_slider_1("rj", "Polarization Loss", 0, 10, 0.5, step=0.1)
self.add_slider_1("tj", "System Loss (dB)", 0, 30, 5, step=1)
self.add_slider_1("jsr", "Required Jammer to Signal Ratio (dB)", 0, 50, 1, step=1)
self.parameters_layout.addLayout(self.sliders_layout_1)
# Initialize the plots
self.update_plots()
코드의 맨 처음은 이 프로그램의 타이틀을 규정한다.
그리고 main widget과 왼쪽 레이다 파라미터 및 재머 파라미터 입력을 위한 layout, 그리고 오른쪽의 그래프가 위치할 layout을 만든다.
출력 그래프는 graphicsView_1과 graphicsView_2의 타이틀과 백그라운드 색, 각 축의 라벨을 정의한다.
그다음은 레이다 파라미터와 재머 파라미터의 입력 항목들을 add_slider와 add_slider_1을 통해 정의한다.
각 입력 파라미터는 입력 변수, 타이틀, 최솟값과 최댓값, 디폴트값을 설정하고 바를 통해 증감시킬 단위는 step을 통해 정의한다.
[ Slide bar Definition ]
Slide bar는 크게 레이다와 재머의 두 개로 구분하여 정의하고 Slide bar의 값은 다음에 나올 slider_value_changed 정의와 연결되도록 되어 결과가 입력 값의 변화에 반응하여 결과가 업데이트된다.
def add_slider(self, name, label, min_val, max_val, default, step=1):
layout = QHBoxLayout()
label_widget = QLabel(f"{label}: {default:.2e}" if isinstance(default, float) else f"{label}: {default}")
slider = QSlider()
slider.setOrientation(1) # Vertical orientation
slider.setMinimum(int(min_val / step))
slider.setMaximum(int(max_val / step))
slider.setValue(int(default / step))
slider.valueChanged.connect(lambda: self.slider_value_changed(name, label, slider.value() * step))
self.sliders[name] = slider
self.slider_labels[name] = label_widget
layout.addWidget(label_widget)
layout.addWidget(slider)
self.sliders_layout.addLayout(layout)
def add_slider_1(self, name, label, min_val, max_val, default, step=1):
layout = QHBoxLayout()
label_widget = QLabel(f"{label}: {default:.2e}" if isinstance(default, float) else f"{label}: {default}")
slider = QSlider()
slider.setOrientation(1) # Vertical orientation
slider.setMinimum(int(min_val / step))
slider.setMaximum(int(max_val / step))
slider.setValue(int(default / step))
slider.valueChanged.connect(lambda: self.slider_value_changed_1(name, label, slider.value() * step))
self.sliders_1[name] = slider
self.slider_labels_1[name] = label_widget
layout.addWidget(label_widget)
layout.addWidget(slider)
self.sliders_layout_1.addLayout(layout)
[ 슬라이더 바 변경 Definitino ]
여기서는 레이다 파라미터와 재머 파라미터에서의 변화된 값을 가지고 update_plot 정의를 시행시킨다.
def slider_value_changed(self, name, label, value):
self.slider_labels[name].setText(f"{label}: {value:.2e}" if isinstance(value, float) else f"{label}: {value}")
self.update_plots()
def slider_value_changed_1(self, name, label, value):
self.slider_labels_1[name].setText(f"{label}: {value:.2e}" if isinstance(value, float) else f"{label}: {value}")
self.update_plots()
[ 결과 업데이트 Definition ]
이 정의는 레이다 파라미터 값과 재머 파라미터 값을 가지고 Burn-Through Range를 계산하고 또한 Radar Detection Probability를 계산하는 부분이다.
앞에서 얘기했듯이 수식적인 부분은 이전 발행 글을 참고하길 바란다.
def update_plots(self):
#Radar parameters
pt = 10 * np.log10(self.sliders["pt"].value())
gt = self.sliders["gt"].value()
gr = self.sliders["gr"].value()
bn = 10 * np.log10(self.sliders["bn"].value())
fn = self.sliders["fn"].value()
ls = self.sliders["ls"].value()
sig = self.sliders["sig"].value()
lam = 20 * np.log10((3 * 10**8) / self.sliders["freq"].value())
k = 10*np.log10(1.38*(10**-23))
temp = 10*np.log10(290)
#Jammer Paramteters
pj = 10 * np.log10(self.sliders_1["pj"].value())
gj = self.sliders_1["gj"].value()
jn = 10*np.log10(self.sliders_1["jn"].value())
rj = 10*np.log10(self.sliders_1["rj"].value())
tj = self.sliders_1["tj"].value()
jsr = self.sliders_1["jsr"].value()
i=0
sn=[]
s_j=[]
for i in range (1, 100000):
sn.append((pt+gt+gr+sig+lam)-(30*np.log10(4*(np.pi))+k+temp+bn+fn+ls+40*np.log10(i)))
s_j.append((pj+gj+gr+lam)-(20*np.log10(4*(np.pi))+k+temp+bn+tj+rj+jsr+20*np.log10(i)))
i=i+1
i=0
sj=[]
for i in range (1, 100000):
sj.append((pt+gt+gr+sig+tj+rj+20*np.log10(i))-(10*np.log10(4*np.pi)+pj+gj+gr+fn+ls+40*np.log10(i))+(jn-bn))
i=i+1
sn_new = 10**(np.array(sn)/10)
sj_new = 10**(np.array(sj)/10)
i=0
xj = []
for i in range (1, 99500):
xj.append(0.5*(1+erf(np.sqrt(0.5+(1/((1/sn_new[i])+(1/sj_new[i]))))-(np.sqrt(np.log(1/1e-6))))))
i=i+1
self.graphicsView_1.clear()
self.graphicsView_2.clear()
pen_1 = pg.mkPen('b', width=3)
pen_2 = pg.mkPen('r', width=3)
self.graphicsView_1.plot(sn, pen=pen_1, name="Target")
self.graphicsView_1.plot(s_j, pen=pen_2, name="Jammer")
self.graphicsView_2.plot(xj, pen=pen_1, name="Detection Probability")
결 과
실제 재밍 신호에 의한 레이다의 성능 변화 또는 재밍의 효과도를 분석하고자 한다면 위의 [결과 업데이트 Definition] 부분이 이 프로그램에서 가장 핵심이 되는 부분이 되겠다.
그러나 파이썬 프로그래밍을 공부하는 측면에서 봤을 때 이 프로그램에서 가장 어려웠던 부분이고 꼭 수정하고자 했던 부분은 레이다와 재머 파라미터 값 입력을 쉽게 하기 위해 slide bar를 적용하고 파라미터 값의 변경에 따라 interactive 하게 결과 그래프를 업데이트하도록 하는 부분이었다.
혼자 구글링을 통해 프로그래밍을 했다면 꽤 오랜 시간이 걸렸을 것 같은데 ChatGPT를 통해 프로그래밍한 결과는 2일밖에 걸리지 않았다.
실제로 ChatGPT가 짠 부분 중 [Slide bar 변경 Definition] 부분은 내 실력으로는 아무리 공부해도 쉽게 짤 수 없는 부분이란 생각이다.
프로그램의 결과 화면은 위에서 봤듯이, 왼쪽에는 레이다 파라미터 및 재머 파라미터를 조절할 수 있는 slide bar가 있고 오른쪽에는 Burn-Through Range 결과 그래프와 레이다 탐지확률 그래프가 배치된다.
그래서 다음과 같이 파라미터를 조절하면 결과는 즉시 반영된다.
예를 들면, 레이다의 출력을 키우면 레이다의 탐지확률이 높아지고 Burn-Through Range도 늘어나며 표적의 RCS를 높여도 마찬가지이다.
그러나 재머의 출력을 키우면 이와 반대로 Burn-Through Range가 짧아지고 레이다의 탐지확률도 재밍의 영향을 받아 줄어들게 된다.

'Python' 카테고리의 다른 글
Flet을 이용한 로또 1등 번호 생성기 (11) | 2024.09.24 |
---|---|
Python 프로그램을 안드로이드 앱으로 만들기 (3) | 2024.08.04 |
ChatGPT API를 이용한 간단한 챗봇 만들기 (0) | 2023.07.02 |
머신 러닝을 통한 위협 레이다 신호 분류 (기본) (2) | 2023.02.26 |
로또 번호 생성기 & ChatGPT (0) | 2023.01.07 |
댓글