ミリ波周波数変調連続波 (FMCW) レーダーは、無線周波数 (RF) 電磁波を放射して検出することで機能します。この技術は独自の特性を備えているため、インタラクティブ システムやアプリケーションにさまざまな利点をもたらします。照明条件、環境ノイズ、天候に左右されずに動作し、迅速かつ正確な検知機能を提供します。
さらに、さまざまな材料を透過できるため、さまざまなデバイスや環境に組み込むのに最適です。このセンサーは、ミリ波 RF 周波数の小型の固体半導体ユニットとして構築できます。つまり、レーダー チップです。このチップはコンパクトで、消費電力が少なく、可動部品がなく、コスト効率よく大量生産できます。
mmWave FMCW レーダーは、次のような多くのデバイスで使用できます。
さらに、mmWave FMCW レーダーをディープラーニング モデルと組み合わせて使用することで、さまざまなタスクを解決できます。
これらのアプリケーションはすべて、カメラを使わず、消費電力が非常に低いデバイスと比較的小さな NN で解決できることに注意してください。
今後数年間で、多くの家電製品が、ディープラーニングアルゴリズムを搭載したこのタイプのセンサーを積極的に使用し、上記の問題を解決するようになるでしょう。さらに、2021年には、IEEE 802.11aу Wi-Fi規格が承認されました。この規格では、同じ無線周波数と動作原理が使用され、Wi-FiルーターがmmWave FMCWレーダーと同じ機能にアクセスできるようになります。
この記事と次の 2 つの記事では、次の内容を取り上げます。
この記事では、mmWave FMCW レーダー信号の処理方法について説明します。ほとんどの図を生成するために使用されたコードは、 Google Colabまたは記事の最後からアクセスできます。
mmWave FMCW レーダーからの信号により、視野内のすべての物体までの距離、速度、角度位置 (方位角と仰角) を測定できます。レーダーからの信号は、以下の図のように、画像軸に沿った距離/速度/角度を含む非常に小さな解像度の画像 (通常は約 32x32 - 256x64 ピクセル) の形式で処理できます - 距離-ドップラー (距離-速度) 距離-角度画像。
センサーは、複数 (1 つ以上) の全方向性送信アンテナと複数 (1 つ以上) の受信アンテナで構成されています。送信アンテナと受信アンテナは同時に動作します。レーダーの視野は通常約 120° で、最大距離は数センチメートルから数十メートルです。
通常、距離を測定するには、時刻t1に信号を発信し、時刻t2にその反射を受信する必要があります。距離はd=(t2-t1)*cとして計算できます。ここで、 cは光速です。電波は光速で移動するためです。
FMCW ミリ波レーダー アンテナは全方向性であり、レーダー視野内のすべてのオブジェクトの時間t1とt2を測定する方法が必要です。これには、FMCW (周波数変調連続波) 信号が使用されます。レーダーの主なコンポーネントはチャープです。チャープは、下の図に示すように、時間とともに周波数が直線的に増加する正弦波無線信号です。
チャープは、開始周波数 (f_start) と終了周波数 (f_end)、帯域幅 ( B=f_end-f_start )、およびチャープ時間 (Tc) によって特徴付けられます。チャープ時間の範囲は、数マイクロ秒から数ミリ秒です。開始周波数は通常、レーダー アプリケーションに応じて約 30、60、または 77GHz です。チャープ帯域幅の範囲は、約 0.5GHz から数 GHz です。
受信 (Rx) アンテナと送信 (Tx) アンテナは同時に動作します。シンセサイザーは 1 つのチャープを連続的に生成し、送信アンテナ Tx とミキサーに送ります。同時に、Rx アンテナで受信した信号もミキサーに送られます。ミキサーは、Tx に送信された信号と Rx で受信した信号の差を出力します。
チャープ信号の周波数は既知の線形法則(傾き)に従って時間とともに変化します。つまり、レーダーの前に1つの物体がある場合、この物体は次のような信号x_outを生成します。
時間を測定せずにミキサーからの信号を分析するだけで、レーダー視野内のすべての物体までの距離を測定できます: d=(F_obj*c)/(2*S)。文献では、 x_out信号は「IF 信号」(中間周波数信号) と呼ばれています。
センサー設計のさらなる利点: 信号の搬送周波数は通常 30GHz または 60GHz 程度です。このような周波数の信号をデジタル化する必要がある場合、ADC には非常に高い要件が課せられます。すべての信号分析は、通常数 MHz 程度の周波数の IF 信号に対して行われるため、ADC の要件は大幅に緩和されます。
上で示したように、レーダー FoV 内のすべてのオブジェクトまでの距離を見つけるには、信号x_out をその周波数成分に分解する必要があります。フーリエ変換は、時間領域信号を周波数領域に変換するアルゴリズムです。
IF 信号のフーリエ変換により複数のトーンが明らかになり、各トーンの周波数はレーダーからの各オブジェクトまでの距離に比例します。文献では、このフーリエ変換は高速時間フーリエ変換または距離フーリエ変換とも呼ばれます。
問題: 同じ距離に複数のオブジェクトがある場合、距離 FFT では 2 つのオブジェクトを区別できないため、問題が発生します。ただし、オブジェクトが異なる速度で移動する場合は、速度によって分離できます。
チャープは通常、次々に、またはわずかに遅れて繰り返されます。文献では、2 つのチャープの開始間の時間はチャープ繰り返し時間と呼ばれています。複数のチャープ (通常 16 ~ 256) が積み重ねられてレーダー フレームを形成します。フレーム時間 = チャープ繰り返し時間 * チャープ数。通常、1 フレームの時間は数十マイクロ秒から数十ミリ秒です。
複数のチャープを積み重ねる理由は何でしょうか? IF 信号の位相は、レーダー視野内の物体の大小の振動に非常に敏感です。エンジンの振動周波数や、人や動物の心拍を測定するためにも使用できます。
時間の経過に伴う位相変化(チャープからチャープへの位相変化)を分析することで、特定の範囲における物体の速度を測定することができます。
mmWave FMCW レーダーで速度を測定するアルゴリズムは非常にシンプルです。
フレーム内の各チャープにフーリエ変換を適用します。各周波数は、オブジェクトまでの特定の距離に対応します。各周波数が特定の範囲に対応するため、これらの周波数は範囲ビンと呼ばれることもあります。
元のIF信号が非複素数値で表現されている場合、ナイキスト・シャノン定理に従って周波数の後半部分(範囲ビン)を破棄する必要がある。
各範囲ビンに別のフーリエ変換を適用します。時間の経過に伴う位相の変化を周波数に分解します。周波数は特定のドップラー(速度)値に対応します。
問題: 同じ距離に同じ速度で移動する2つの物体がある場合、距離ドップラー画像では1つのピークが生成されます。しかし、受信Rxアンテナが複数ある場合は、角度位置によって物体を区別できる可能性があります。
前に説明したように、距離がわずかに変化すると位相が変化します。時間的に離れたチャープ間の位相変化は、物体の速度を計算するために使用されます。空間的に離れたチャープ(異なる Rx アンテナで受信されたチャープ)間の位相変化は、角度の推定に使用できます。
複数の受信アンテナ Rx を使用した角度推定アルゴリズムは非常にシンプルです。
Tx アンテナを使用してチャープのフレームを送信します。
すべての Rx アンテナで受信したフレームの 2D フーリエ変換 (距離ドップラー画像) を計算します。各 Rx アンテナの距離ドップラー画像には、同じ場所とドップラーのピークがありますが、位相は異なります (位相差は Rx アンテナ間の距離に対応します)。
位相差 (ω) を使用して物体の到着角度を推定します。すべての Rx アンテナに 3 番目のフーリエ変換を適用します。
import os import numpy as np import scipy import scipy.io as spio import matplotlib.pyplot as plt import matplotlib.gridspec as gridspec import math
RAMP-CNN プロジェクトから mmWave FMCW レーダー データの例をダウンロードします。
!pip uninstall gdown -y && pip install gdown !gdown -V !gdown --folder https://drive.google.com/drive/folders/1Eg-8R45RPvifNf2VYI_MG-LRjdkLOHTf -O /content/sample_slice_data
ファイルからデータを読み込みます。
file_name = '/content/sample_slice_data/2019_04_30/2019_04_30_pbms002/2019_04_30_pbms002_000000.mat' mat = spio.loadmat(file_name, squeeze_me=True) adc_data = np.asarray(mat["adc_data"]) print(adc_data.shape) # ADC samples, vRx, chirps - (128, 8, 255) print(adc_data.dtype) # complex128
視覚化機能。
def show_one_chirp(one_chirp_data, y_label='amplitude', x_label='One chirp'): plt.figure(figsize=[5, 4]) plt.plot(one_chirp_data) plt.xlabel(x_label) plt.ylabel(y_label) plt.show() def show_image(image_data, image_name, x_label='', y_label=''): plt.imshow(image_data) plt.title(image_name) plt.xlabel(x_label) plt.ylabel(y_label) plt.show() def show_3_images(img_data1, img_data2, img_data3): plt.figure(figsize=(10, 8)) plt.subplot(2, 2, 1) plt.imshow(img_data1[0], aspect=1.44) plt.title(img_data1[1]) plt.xlabel(img_data1[2]) plt.ylabel(img_data1[3]) plt.subplot(2, 2, 2) plt.imshow(img_data2[0], aspect=1.0) plt.title(img_data2[1]) plt.xlabel(img_data2[2]) plt.ylabel(img_data2[3]) plt.subplot(2, 2, 3) plt.imshow(img_data3[0], aspect=1.0) plt.title(img_data3[1]) plt.xlabel(img_data3[2]) plt.ylabel(img_data3[3]) plt.show()
チャープの 1 つの ADC データを表示します。
show_one_chirp(np.absolute(adc_data[:,0,0]), x_label='IF signal of a chirp')
範囲FFTの後にチャープを表示します。
chirp_fft = np.fft.fft(adc_data[:,0,0]) show_one_chirp(np.absolute(chirp_fft), x_label='IF signal amplitude (range)', y_label='Amplitude')
時間領域と周波数領域でレーダー フレームを表示します。
# show all chirps show_one_chirp(np.absolute(adc_data[:,0,:]), x_label='IF signal of frame chirps') show_image(np.absolute(np.fft.fft(adc_data[:,:,:], axis=0).mean(1)), 'range FFT', x_label='Chirps', y_label='Range')
レーダー データから距離、ドップラー、角度を取得します。
def get_range_doppler_angle(adc_data_in): # adc_data_in - ADC samples, vRx, chirps samples_in = adc_data_in.shape[0] range_window = np.hamming(samples_in).reshape(-1,1,1) range_data = np.fft.fft(adc_data_in*range_window, samples_in, axis=0) # chirps_in = range_data.shape[2] doppler_window = np.hamming(chirps_in).reshape(1,1,-1) range_doppler_data = np.fft.fftshift(np.fft.fft(range_data*doppler_window, chirps_in, axis=2), axes=2) # # samples, vRx, chirps angle_window = np.hamming(range_doppler_data.shape[1]).reshape(1,-1,1) angle_bins=180 rda_data = np.fft.fftshift(np.fft.fft(range_doppler_data*angle_window, angle_bins, axis=1), axes=1) return range_data, range_doppler_data, rda_data
range_image, range_doppler_image, rda_cube = get_range_doppler_angle(adc_data)
show_3_images([np.absolute(range_image.mean(axis=1)), 'range doppler', 'Doppler', 'Range'], [np.absolute(rda_cube.mean(axis=2)), 'range angle', 'Angle', 'Range'], [np.absolute(rda_cube.mean(axis=0)), 'angle doppler', 'Doppler', 'Angle'] )
次の 2 つの記事では、次の内容を取り上げます。