본문 바로가기

통신이론

LFM펄스, FMCW 레이다

여태껏 통신에 대한 글은 이제 얼추 제 애초 목표에 근접하게 거의 다 쓴 것 같습니다. 밑천이 거의 다 떨어져 간다고 할까요!ㅎㅎㅎ

그간 나름대로 통신에 대해 정리하는 글이 제 일에도 도움이 되었으며, 누군가에게 조금이라도 도움이 되리란 기대를 가지고, 또는 실제로 그런 감사와 응원도 받으면서 즐거운 시간을 보낸 것 같습니다. 다만 최근에 우려되는 부분은 점점 AI의 성능과 쓰임이 커지다보니, 이제 블로그도 시들시들 해지고 희미해져 가는 느낌이 드는 것입니다. 단적으로 방문객수가 확 떨어지고 예전만큼 회복이 안되는 것 같아요. 마치 네이버 검색의 하락처럼요. 여러 블로거분들도 혹시 느끼시죠? 저만 그런거 아니죠?? ㅠ,,ㅠ

 

아이러니하지만, 이번 주제도 AI가 짜준 소스코드를 바탕으로 쓰는 글입니다. 저는 chatGPT가 짜준 코드를 약간 수정·보완하여 이를 기반으로 펄스, FMCW 레이다에 대해 설명해 보고, 검증해 볼까해요. 웹서핑으로는 이런 예제를 찾기 힘들었지만, AI는 뚝딱 만들더군요. 아주 상세하고 친절하게 말이죠.

레이다의 가장 큰 특징은 꼽자면, 일반적인 무선통신과는 달리 송신기와 수신기가 일체화되어 송신과 수신이 동시에 동작한다는 점 입니다. 참고로 레이다(Radar)는 전파를 이용한 반면 라이다(LiDAR)는 레이저(빛)를 이용하여 더 높은 해상도와 정밀도를 가지는 대신 비용이 높고 기상조건에 취약한 특징이 있습니다.

그리고 파형에 따른 대표적인 3개의 레이다는 아래와 같고, 차례로 살펴볼게요. 

 

1. 펄스 레이다

ㅇ 가장 고전적이면서도 널리 쓰이는 방식

ㅇ 하나의 안테나만을 사용하여 짧은 시간 동안 펄스 송신하고 나머지 시간 동안 반사파가 돌아오길 기다리는 수신 구조

ㅇ 펄스 레이다에서는 기존 좁은 펄스신호 보다 LFM(Linear frequency modulation)이 더 일반적으로 사용되고,

    이것은 전력과 열 문제를 극복할 수있는 Chirp 신호를 사용하는 펄스 압축 기법을 사용

ㅇ 항공기·선박 관제, 기상 레이더에 활용

ㅇ 거리 r = ct / 2   ,   거리분해능 △r ∝ τ(펄스 폭)

<예제1.> 기존 펄스 신호와 LFM 압축 펄스 신호를 사용하는 레이다의 신호처리 및 탐지 시뮬레이션을 비교해 보라!
레이다에 반사되는 신호는 거리의 4제곱으로 감소되는데 이것도 포함할 것.

 

<기존 펄스 레이다 a.송신신호 파형, b.송신신호 스펙트럼, c.탐지>

<LFM 압축 펄스 레이다 a.송신신호(Chirp) 파형, b.송신신호 스펙트럼, c.탐지>

 

2. CW (Continuous Wave) 레이다

ㅇ 도플러(Doppler) 레이다라고도 함

ㅇ 목표물에 반사된 신호는 circulator에 의해 주파수혼합기(Mixer)에 입력되고,

    송신신호와 곱해져 두 신호의 합과 차 신호가 발생하는데, 차 신호만 필터링하면 도플러 주파수를 걸러낼 수 있다.

    도플러 주파수(fd)는 목표물의 속도에 비례하므로 아래식을 이용해 속도 측정가능

ㅇ fd = 2v/λ (∵ 전파가 갔다가 다시 돌아오기 때문에 왕복경로의 시간변화률은 2v)

ㅇ 속도계, 과속 단속 센서에 활용

 

3. FMCW (Frequency Modulated Continuous Wave) 레이다

ㅇ CW레이더의 거리측정 불가 단점을 보완한 주파수 변조형 연속파 레이다이고, 

    펄스 레이더 대비 소출력이기 때문에 탐지 거리는 짧음

ㅇ 연속파를 쏘되 주파수를 시간에 따라 변조시키는 방식

    이렇게 하면 CW의 한계였던 거리 측정 문제를 해결할 수 있어, 거리와 속도를 동시에 측정하는 것이 가능

    2개 이상의 RX 안테나를 활용하면 도래각(Angle of Arrival, AoA) 추정도 가능

ㅇ FMCW 레이다는 LFM신호가 목표물에 반사되어 온 수신파의 시간지연에 의해 발생되는 Beat frequency(fb)와 

    수신신호의 도플러 편이(fd<<fb)에 의해 변형된 신호를 수신

    ※ 매우 짧은 거리를 이동한 경우 fd는, beat 신호 의 주파수(fb)에 비해 신호의 위상이 훨씬 민감하게 변화

ㅇ Mixer 통과 후 저역통과필터 처리된 beat 신호의 순시주파수 fb = B/Tc · 2r/c   ∝ 거리분해능

ㅇ 자율주행, 차량용 레이더에 활용

<예제2.> 77GHz FMCW 차량용 레이다의 신호처리 및 탐지 기능을 시뮬레이션하라!
단 대역폭은 200 ㎒, chirp 지속시간(Tc) 40 ㎲, chirp 개수 128개 이다.
목표물은 임의의 거리, 속도, 진폭 정보를 가지는 3개로 할 것

<소스코드>


import numpy as np
import matplotlib.pyplot as plt

# ==========================================================
# 1. FMCW Radar parameters
# ==========================================================

c = 3e8                  # speed of light [m/s]

fc = 77e9                # carrier frequency = 77 GHz
wavelength = c / fc

B = 200e6                # chirp bandwidth = 200 MHz
Tchirp = 40e-6           # chirp duration = 40 us

slope = B / Tchirp       # FMCW chirp slope [Hz/s]

Fs = 500e6                 # ADC sampling rate = 2 MHz
Ns = int(Fs * Tchirp)    # samples per chirp

Nchirps = 128             # number of chirps

# ==========================================================
# 2. Targets
# ==========================================================

targets = [ {"R": 10.0, "v": 20.0, "amp": 1.0 },
            {"R": 25.0, "v": 0.5, "amp": 0.6},
            {"R": 20.0, "v": -23.0, "amp": 0.7} ]

# ==========================================================
# 3. Time axis
# ==========================================================

t_fast = np.arange(Ns) / Fs

# beat signal array
# rows    = chirps (slow time)
# columns = ADC samples (fast time)
beat_signal = np.zeros( (Nchirps, Ns), dtype=complex )

# ==========================================================
# 4. Generate FMCW transmit / receive signals
# ==========================================================

rng = np.random.default_rng(0)

for m in range(Nchirps):

    # absolute time
    t_abs = m * Tchirp + t_fast

    # ------------------------------------------------------
    # Transmitted FMCW chirp
    #
    # phase = 2*pi * (1/2 * slope * t^2)
    # ------------------------------------------------------

    tx = np.exp( 1j * 2*np.pi * (0.5 * slope * t_fast**2) )

    rx = np.zeros(Ns, dtype=complex)

    # ------------------------------------------------------
    # Generate reflections from each target
    # ------------------------------------------------------

    for target in targets:

        R = target["R"]
        v = target["v"]
        amp = target["amp"]

        # round-trip propagation delay
        tau = 2 * R / c

        # Doppler frequency
        fd = 2 * v / wavelength  

        # delayed time
        td = t_fast - tau

        # received chirp , doppler effect add
        reflected = amp * np.exp( 1j*2*np.pi * (0.5 * slope * td**2 + fd * t_abs) )

        rx += reflected

    # ------------------------------------------------------
    # Add complex Gaussian noise
    # ------------------------------------------------------

    noise = 0.15 * ( rng.standard_normal(Ns) + 1j * rng.standard_normal(Ns) )

    rx += noise

    # ------------------------------------------------------
    # Mixer
    #
    # Beat = TX * conjugate(RX)
    # ------------------------------------------------------

    beat_signal[m, :] = tx * np.conj(rx)   # mixer

# ==========================================================
# 5. RANGE FFT
# ==========================================================

# Window
range_window = np.hanning(Ns)

range_fft = np.fft.fft(beat_signal * range_window, axis=1)

# Only positive beat frequencies
range_fft = range_fft[:, :Ns // 2]

# ----------------------------------------------------------
# Convert beat frequency -> range
# fb = slope * tau
# fb = 2 * slope * R / c
# R = c * fb / (2 * slope)
# ----------------------------------------------------------

beat_freq = ( np.arange(Ns//2) * Fs / Ns )

ranges = ( c * beat_freq / (2 * slope) )

# ==========================================================
# 6. DOPPLER FFT
# ==========================================================

doppler_window = np.hanning(Nchirps)[:, None]   # (64, 1)
#doppler_window = np.ones(Nchirps)[:, None]

range_doppler = np.fft.fft( range_fft * doppler_window, axis=0 )

range_doppler = np.fft.fftshift(range_doppler, axes=0)

# Doppler frequency axis
doppler_freq = np.fft.fftshift( np.fft.fftfreq(Nchirps, d=Tchirp) )

# ----------------------------------------------------------
# Convert Doppler frequency -> velocity
# fd = 2*v/lambda
# v = fd*lambda/2
# Minus sign here comes from our mixer convention
# ----------------------------------------------------------

velocities = ( -doppler_freq * wavelength / 2 )


# ==========================================================
# 7. Range-Doppler magnitude
# ==========================================================

mag = np.abs(range_doppler)   # magnitude

rd_db = 20 * np.log10( mag/(np.max(mag) + 1e-12) + 1e-12 )

# ==========================================================
# 11. Plot Range-Doppler Map
# ==========================================================

plt.figure(figsize=(10, 6))

plt.imshow( rd_db, aspect="auto", origin="lower",
    extent=[ranges[0], ranges[-1], velocities[0], velocities[-1]] )

plt.xlabel("Range [m]")
plt.ylabel("Velocity [m/s]")

plt.title("FMCW Range-Doppler Map")

plt.colorbar(label="Relative Power [dB]")

plt.xlim(0, 30)

plt.show(block=False)

<실행결과>

FMCW 레이다의 range-doppler map

3개 목표물을 잘 탐지하고 있네요.

그럼 최대 피크값을 가지는 시간지연에 의해 발생되는 Beat frequency를 찾아 볼까요?!

약 fb=315㎑ → r = c * fb / (2 * slope) = 9.45m 거리를 약간의 오차가 있지만 잘 탐지합니다. 검증 ok!

beat_signal의 스펙트럼

 

다음은 물체의 속도에 따른 수신신호의 도플러 편이를 찾아 볼게요.

약 fd=-10.35㎑ → v = -fd*wavelength/2 = 20.16 m/s 속도도 오차가 약간 있지만 탐지 ok!

range_fft[:,13]의 스펙트럼

 

여러분! 감사합니다. 수고하셨습니다!

 

<참고자료>

1. RADAR (RAdio Detection And Ranging) — I'm not a robot

2. Pulse Radar의 LFM : 네이버 블로그

3. 장병준 (2021). 무선통신과 레이다. 홍릉

4. FMCW 레이더의 원리