{ "cells": [ { "cell_type": "markdown", "id": "b237b957-6e4f-4784-97b5-ccd1d910a4cd", "metadata": {}, "source": [ "# DDM MIMO\n", "\n", "You can open this workbook in Google Colab to experiment with mmWrt \n", "[![](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/matt-chv/mmWrt/blob/main/docs/MIMO_DDM.ipynb)\n", "\n", "Below is an intro to mmWrt for simple targets position in (X,Y) plane based on 2D FFT (Range, Azimuth) FFTs with a DDM MIMO.\n", "\n", "## DDM MIMO ULA" ] }, { "cell_type": "code", "execution_count": 1, "id": "fe509725-1ac0-4347-8be0-6b1f7c5247e1", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "running from git folder, using local path (latest) mmWrt code c:\\git\\mmWrt\n", "version: 0.0.11-pre.3\n", "last run on 2026-06-27 12:22:53.599929\n" ] } ], "source": [ "# Install a pip package in the current Jupyter kernel\n", "import sys\n", "from os.path import abspath, basename, join, pardir\n", "import datetime\n", "\n", "# hack to handle if running from git cloned folder or stand alone (like Google Colab)\n", "cw = basename(abspath(join(\".\")))\n", "dp = abspath(join(\".\",pardir))\n", "if cw==\"docs\" and basename(dp) == \"mmWrt\":\n", " # running from cloned folder\n", " print(\"running from git folder, using local path (latest) mmWrt code\", dp)\n", " sys.path.insert(0, dp)\n", "else:\n", " print(\"running standalone, need to ensure mmWrt is installed\")\n", " !{sys.executable} -m pip install mmWrt\n", "\n", "from os.path import abspath, join, pardir\n", "import sys\n", "from numpy.fft import fft, fftshift\n", "from scipy.signal import find_peaks\n", "import matplotlib.pyplot as plt\n", "from numpy import arange, cos, sin, pi, zeros\n", "\n", "from mmWrt.Scene import Antenna, Medium, Radar, Receiver, Scatterer, TransmitterDDM\n", "from mmWrt.Raytracing import rt_points\n", "from mmWrt import __version__ as mmWrt_version\n", "print(\"version:\", mmWrt_version)\n", "\n", "print(\"last run on \", datetime.datetime.now())" ] }, { "cell_type": "code", "execution_count": 42, "id": "9c51acf6-a832-4297-b517-242376d6edb6", "metadata": {}, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from scipy.fft import fft, fft2\n", "from numpy import pi, array, abs as np_abs\n", "\n", "f0 = 61e9\n", "# Number of ADC samples\n", "NA = 64\n", "# Number of TX channels\n", "NT = 2\n", "# Number of RX channels\n", "NR = 8\n", "# Number of chirps (used for speed)\n", "NC=32\n", "\n", "tic0 = 1.2e-3\n", "\n", "void = Medium()\n", "c = void.v\n", "lambda0 = c/f0\n", "_fs = 2e5/2\n", "_k = 28e10 # chirp slope\n", "chirp_start_freq0 = f0\n", "chirp_period0 = 1.2e-3\n", "chirp_bw0 = 0.2e9\n", "chirp_end_time0 = chirp_bw0/_k\n", "chirp_slope0 = _k\n", "chirp_count0 = NC\n", "\n", "TXs = [Antenna(x=NR*lambda0/2*i) for i in range(NT)]\n", "RXs = [Antenna(x=lambda0/2*i) for i in range(NR)]\n", "\n", "radar = Radar(transmitter=TransmitterDDM(chirp_start_freq=chirp_start_freq0,\n", " chirp_end_time=chirp_end_time0,\n", " chirp_slope=chirp_slope0,\n", " antennas=TXs,\n", " chirp_period=chirp_period0,\n", " chirp_count=chirp_count0,\n", " conf={\"TX_phaser_slopes\":\n", " [0, pi/2]}),\n", " receiver=Receiver(adc_sample_rate=_fs,\n", " adc_sample_count_max=2048,\n", " adc_sample_count=NA,\n", " antennas=RXs),\n", " debug=False)\n", "r1, theta1 = 10.1, 0\n", "x1, y1 = r1*cos(theta1), r1*sin(theta1)\n", "r2, theta2 = 15.1, pi/2\n", "x2, y2 = r2*cos(theta2), r2*sin(theta2)\n", "r3, theta3 = 20.1, pi*0.8\n", "x3, y3 = r3*cos(theta3), r3*sin(theta3)\n", "\n", "target1 = Scatterer(x1, y1, 0) # 0 degrees on x-axis <=> -pi/2 vs bore sight\n", "target2 = Scatterer(x2, y2, 0) # pi/2 degrees vs x-ax <=> 0 degree vs bore sight\n", "target3 = Scatterer(x3, y3, 0) # 180 degrees on x-axis <=> pi/2 vs boresight\n", "scatterers = [target1, target2, target3]\n", "\n", "bb = rt_points([radar],\n", " scatterers,\n", " radar,\n", " debug=False)\n", "\n", "fast_time_axis = 3\n", "slow_time_axis = 1\n", "cube = bb[\"adc_cube\"][0, :, 0, :]\n", "# bb[frame_i, chirp_i, tx_i, rx_i, adc_i]\n", "# virtual_cube_RX0 = bb[\"adc_cube\"][0,:,0,:]\n", "#virtual_cube_RX1 = bb[\"adc_cube\"][0,:,1,:]\n", "Z = fft2(cube)[:, :NA//2] # , axis=fast_time_axis), axis=slow_time_axis)\n", "Z = fft(fft(bb[\"adc_cube\"],axis=fast_time_axis),axis=slow_time_axis)\n", "#Z0 = abs(fft2(virtual_cube_RX0))\n", "#Z1 = abs(fft2(virtual_cube_RX1))\n", "\n", "fig, (ax0) = plt.subplots(ncols=1)\n", "ax0.set_xlabel(\"Range\")\n", "ax0.set_ylabel(\"Velocity\")\n", "ax0.set_title('Velocity-Range 2D FFT')\n", "ax0.imshow(np_abs(Z[0,:,0,:NA//2])) #, cmap='bone_r')\n", "sub_doppler_ghost1 = plt.Circle((0.45, 0.29), 0.02, fill=False, color=\"white\")\n", "sub_doppler_ghost2 = plt.Circle((0.56, 0.29), 0.02, fill=False, color=\"white\")\n", "sub_doppler_ghost3 = plt.Circle((0.67, 0.29), 0.02, fill=False, color=\"white\")\n", "fig.text(0.3, 0.35, f\"Doppler ghost from DDM\", color=\"white\", fontsize=12)\n", "fig.add_artist(sub_doppler_ghost1)\n", "fig.add_artist(sub_doppler_ghost2)\n", "fig.add_artist(sub_doppler_ghost3)\n", "plt.show()\n" ] }, { "cell_type": "code", "execution_count": 43, "id": "aa089eaf-d7c6-4274-98a7-d9b5b9fa72e7", "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAioAAADRCAYAAADi+plAAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjMsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvZiW1igAAAAlwSFlzAAAPYQAAD2EBqD+naQAAJmtJREFUeJzt3Qd4FFX3+PGTQgKEIr1ILwIRiHQREBQELEgTLKDBAkp5AMGG+gqCgqAgiAgiUl5QIiCxgEhHiiLSQXoHaaL0Ekgy/+fc/2/3zaaQZDdkJ7vfz/MMZCezM3cns9mTc8+9E2BZliUAAAA2FOjtBgAAAKSEQAUAANgWgQoAALAtAhUAAGBbBCoAAMC2CFQAAIBtEagAAADbIlABAAC2RaACAABsi0AFAADYFoEK4CWfffaZBAQESL169TJsnzt37jT7zJ49u5w7dy7Nz1uxYoV5nmMJCgqSwoULy2OPPWb26Sv++OMP6dWrl9x5550SFhYmpUqVko4dO8qePXuSbNukSRPn+QgMDJQ8efJIpUqV5Omnn5bFixen+ZhdunRxObcJl59//tlsc+jQoRS3ufvuu2XQoEEpfj/hom0GfE2wtxsA+KuvvvpKypQpI+vWrZN9+/ZJhQoVPN7njBkzpGjRonL27FmZM2eOvPDCC+l6fu/evaVOnTpy48YN2bp1q0yYMMEEMdu3bzf7zeqGDx8ua9askQ4dOkj16tXl5MmT8umnn0rNmjVl7dq1UrVqVZftS5QoIcOGDTNfX7582fyc5s6da86zBjj6f7Zs2VI9bmhoqEyaNCnJ+oiICJfHTz75pDz00EMu6woVKiTFihVzuT4uXbok3bt3l7Zt20q7du2c64sUKZKOswFkEXpTQgCZ68CBA3ozUGvu3LlWoUKFrEGDBnm8z/j4eKtMmTJWv379rLZt21pNmjRJ83OXL19u2jN79myX9ePHjzfrhw8fbvmCNWvWWDExMS7r9uzZY4WGhlqdOnVyWd+4cWPrzjvvTLKP2NhYq0ePHua8vPbaa6keMzIy0goLC7vpNgcPHjT7+/DDD9P0Ov7++2+z/cCBA9O0PZCV0fUDeCmbki9fPnn44YdN94o+Ts6BAwfMX//58+eXnDlzmm6A+fPnJ7utZgq0C+GJJ54wy8qVK+XYsWMetbNRo0bm//3797us/+ijj+See+6RAgUKSI4cOaRWrVomg5OYdkdoV8t3331nshWaWdBuF0eXR0Kaualdu7bptipfvrx8/vnnzi6PxDSTocfUY+u50dd79OjRVF+PtjkkJMRlXcWKFU2b0trFpd1in3zyiYSHh5tszPnz59P0PADuIVABvEADE03Z64empvv37t1r6icSOnXqlPlgXbhwofTo0UPef/99uXbtmjz66KMSHR2d7D71A167blq1amUCm5kzZ3rUTg18lAZVCY0ZM0Zq1KghgwcPlqFDh0pwcLAJqJILolavXm3ar8HEiBEjzGto3769/PPPP85tNm3aJC1btjTr3n33XXn++efNvjXASUzPwzPPPGMCjFGjRknfvn1l6dKlcu+996arLsfBsixzrgsWLJjm52iwoj+3K1eumNeXFmfOnHFZkgtwdH+Jt9NuOMCveTulA/ib9evXm7T94sWLnV02JUqUsPr06eOyXd++fc12q1atcq67ePGiVbZsWdPFExcX51x//fp1q0CBAtZbb73lXPfUU09ZERER6er6mTx5sulWOH78uPXzzz9bFSpUsAICAqx169a5bH/lyhWXx3r8qlWrWvfff7/Let1nSEiItW/fPue6LVu2mPVjx451rmvVqpWVM2dO66+//nKu27t3rxUcHGy2dTh06JAVFBRkvf/++y7H2bZtm9k28fq0mD59ujnGl19+maauH4fo6GjzvDFjxqTa9aPbJV50/4m7fpJb9GeTGF0/8CcU0wKZTDMfWvR43333mcfatfH444+b7oyRI0eav9bVTz/9JHXr1pWGDRs6n5srVy7p1q2bDBgwQHbs2OEs/lywYIHJRuhf+Q76tWZW/vzzT9O1kRbPPfdckkLO6dOnmyxNQtrl4qCFu3FxcaabKLkMTrNmzUymx0GLWHUEjXZrKX3ukiVLTGFo8eLFndtp8eiDDz4oP/74o3OdFrLGx8ebQlbNNjhooa9mWJYvXy5vvvmmpNWuXbukZ8+eUr9+fYmMjJT00J+FunjxYqrbandWwteRXJZK6c9WM1M3K7gF/A2BCpCJ9EM5KirKBCkHDx50rtchyhqkaBdG8+bNzbrDhw8nO3S5SpUqzu87AhUNcsqWLWtqQHRkitLgQLt/NDDS7hmlo1wSyps3r0vQ8c4775iAQ0eVaPeStlWH5iY2b948ee+992Tz5s0SExPjXJ9cPYkOAU5MP6Q1wFGn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yqFDh2T8+PESFRUlx44dEytBmiwkJEQaNWok3bp1k/bt20tgIMkaAADgmTRHE71795aIiAg5ePCgvPfee7Jjxw45f/68XL9+XU6ePCk//fSTNGzYUN555x2pXr26/PHHHx42DQAA+Ls0Z1TCwsLkwIEDUqBAgSTfK1y4sNx///1mGThwoPz8889y9OhRqVOnzk33OWzYMJk7d67s2rVLcuTIIffcc48MHz5cKlWq5N6rAQAAPiXASth/k8latmwpTzzxhAloYmNj5c0335Tt27ebbI0GRqm5cOGC5M2bV5pIawkOyJYpbQa8glE/8BPBZUu7/dzYQ0c8Ozjvk0wTa92QFfK96ZnJkydPxhfTagakcuXKyX5v4cKF0qJFizTtRzMvCU2dOtVkZzZs2CD33ntvku1jYmLMkjBQAQAAvsutiteaNWvKuHHjXNZpANGrVy9p3bq1243RyErlz58/xa4izaA4lpIlS7p9LAAA4KOBimY+tGj2oYceklOnTsnmzZulRo0asmTJElm1apVbDYmPj5e+fftKgwYNpGrVqsluM2DAABPMOBatgwEAAL7LrUClY8eOsmXLFrlx44aZP6V+/frSuHFj2bhxY6oFtCnp2bOnqU/Roc8p0XlatC8r4QIAAHyXR1Po69DkuLg4sxQrVkyyZ8/u1n60y2jevHmycuVKKVGihCdNAgAA/p5R0axHtWrVTJ3Inj17ZP78+TJx4kQz4ZsOYU4rHXCkQUp0dLQsW7ZMypYt605zAACAj3IrUHn++edl6NCh8sMPP5jp8x944AHZtm2b3H777XLXXXelq7tnxowZ8vXXX0vu3LnNxHG6XL161Z1mAQAAH+NW14/WoiSelC1fvnwya9YsmT59epr3o9PxqyZNmrisnzJlinTp0sWdpgEAAH8PVG42c+zTTz+d5v14ca45AADgS4FKv3790rzTUaNGudseAIA/i41z/7n88evfgcqmTZuSdP/otPeO7IoW1QYFBUmtWrUyvpUAAMAvpTlQWb58uUvGRItfp02bZmpT1NmzZ+XZZ581I38AAAC8dlNCHd2zaNEiM9lbQjphW/PmzeX48eOSGbgpIfwGNyWEnwgu6f5cWrFHj2VoW2CPmxIGuhsg/P3330nW67qLFy+6s0sAAICMCVTatm1runnmzp0rx44dM8u3335r5ldp166dO7sEAADI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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from scipy.signal import find_peaks\n", "# generate virtual antennas\n", "\n", "# important to declare the zeros as complex otherwise assignement\n", "# forces a type cast to real\n", "# virtual_cube = zeros(( NC//NT, NT * NR, NA//2)).astype(complex)\n", "\n", "\"\"\"for tx_idx in range(NT):\n", " for rx_idx in range(NR):\n", " # virtual antenna index =\n", " # tx_idx*NT+ rx_idx\n", " virtual_rx_idx = tx_idx*NR+ rx_idx\n", " virtual_cube[:,virtual_rx_idx,:] = Z[0, tx_idx*NC//NT:(tx_idx+1)*NC//NT, 0, rx_idx, :NA//2]\"\"\"\n", "virtual_cube = Z[0,:,:,:]\n", "#virtual_cube = virtual_cube[0,0, :, :]\n", "#doppler_axis=None as removed\n", "rx_axis = 1\n", "# range_axis=1\n", "A = fftshift(fft(virtual_cube, axis=rx_axis), axes=rx_axis)\n", "# plot AoA at zero Doppler\n", "plt.xlabel(\"Range (idx)\")\n", "plt.ylabel(\"AoA (idx)\")\n", "plt.title('AoA-Range 2D FFT')\n", "plt.imshow(abs(A[0,:,:NA//2]))\n", "plt.show()" ] }, { "cell_type": "markdown", "id": "71a0b855-096d-403a-aa9d-f92a56174a6b", "metadata": {}, "source": [ "## Dummy sub doppler" ] }, { "cell_type": "code", "execution_count": 73, "id": "8fc20144-646f-479d-8619-0f0929102d32", "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAbQAAAHHCAYAAADXgq0pAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjMsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvZiW1igAAAAlwSFlzAAAPYQAAD2EBqD+naQAANihJREFUeJzt3QmYFNW5+P+3Z2UHWQdkEUQBF0xERBQBFVliFITrngiRSFRAAY06xt1cQUyCYBDvjcqoV0QxgltEAVlcwAgEERcUAhmUTTEMMMCs9Xvek3/3v3sYoA9MTVef/n6epxim+/SZU1Xd9fY5deqtkOd5ngAAkOTSEt0AAACqAgENAOAEAhoAwAkENACAEwhoAAAnENAAAE4goAEAnEBAAwA4gYAGAHACAQ1JIRQKyf333+9L3Rs3bjT15+Xl+VI/gOpBQEOVuuSSS6RWrVqye/fug5a55pprJCsrS3bs2CFB9be//c2XAKp1avAML5mZmXLcccfJzTffLDt37hRXvPrqq3LFFVdIu3btzPuhQ4cOcuutt1a6jtHbIyMjQxo2bChdunSRW265Rb744ou4/6Zux+i6opf9+/ebMvql5WBl7rzzTundu/dBn49e/PpyhaOTcZSvBw4IVm+88YbMnj1brr322gOe37t3r7z22mvSv39/adSokQRBmzZtZN++fSa4RAe0qVOn+nbgmjZtmtSpU0cKCwtlwYIF8vjjj8vKlSvlgw8+EBeMGDFCWrRoIb/4xS+kdevW8tlnn8mf//xns111PWvWrBlT/sILLzTvF00tW1BQIJ9++qk8++yz8sQTT8gjjzwi48aNi+vv/uQnPzGBsyL9AhXtwQcflLZt28Y8dsopp8gFF1wgv/71ryOPffLJJzJlyhS56667pFOnTpHHO3fuHPe2QDXS5MRAVdm7d69Xt25dr1+/fpU+P2PGDE2G7c2cOdOqXn3Nfffd51WXkSNHmr9Z1XQdtN7vv/8+5vErrrjCPP7xxx97Lli4cOEBjz377LNmHf/yl7/EPK6P6fau6IcffvC6d+9unn/rrbcO+zfbtGnjXXTRRYcsM336dFPfJ598Etd6zJo1y5SvbH0QPAw5okrpN+/BgwebXsf27dsPeH7GjBlSt25dMzSpdAhqzJgx0qpVK8nOzpb27dubb+Tl5eWH/Vv/+Mc/ZMCAAVKvXj3T29Fv18uWLTugnP6NsWPHmiEp/RstW7Y0vYEffvih0nNow4YNM70zFT3MpMderWPgwIEH/A0d0qpfv7785je/OYKtJnLuueean+vXr4889uOPP8ptt90mp556qlk/XU9dX+29RFu0aJFp38svvyz//d//bdavRo0aZnusW7fugL+l66ZDgbqvzjzzTHn//ffNUJsu0YqKiuS+++4z+0S3m+6j22+/3Tx+OBXrUpdeeqn5+eWXX8a1TbQHP3PmTDMMqesFHA5DjvBl2FGHi/QAO2rUqJgD9DvvvCNXXXWVOZjq8GOvXr3ku+++M4FAh6Y++ugjyc3NlS1btshjjz120L/x+eefmyCgB3k9yOpw4f/8z/+YA+nixYulW7duptyePXtMOT2IXnfddXL66aebQPb666/Lt99+K40bNz6gbm3L5s2bZd68efL8889HHtegoUNoEydONOui53rCdJh1165d5vkjoUFVHXPMMZHH/vnPf8qcOXPksssuM8Nj27ZtM+uo20zPLemQXrQJEyZIWlqaCYI6bKft1H3x8ccfxwx16j7RbaJBXv/uoEGDzN/VQBimXyj0S4cOgerwoQ636bDhpEmT5OuvvzbtsrV161bzs7JtfjD6ntD1Xbhwodm+ur8PpaSkJPJFJUzP4ekSTbdPxXI27UJAJbqLCPeUlpZ6zZs3N8NF0Z588kkzfPPOO++Y3x966CGvdu3a3tdffx1T7s477/TS09O9/Pz8gw45Dho0yMvKyvLWr18feWzz5s1muLNnz56Rx+69917z2ldfffWAdpaXl5ufGzZsMGV0OOpwQ45r1641j0+bNi3m8UsuucQ77rjjInUebshR69Fhx40bN3rPPPOMV7NmTa9JkyZeYWFhpOz+/fu9srKymNdrW7Ozs70HH3ww8pgOh2mdnTp18oqKiiKPT5482Tz+2Wefmd/1uUaNGnldu3b1SkpKIuXy8vJMuV69ekUee/755720tDTv/fffr3Qffvjhh56t4cOHm/1acX8fbMgx7JZbbjFlPv3008MOOWq5ikv0+yY85FjZUhmGHJMLQ46ocunp6XLllVfK0qVLIz2P8HBjs2bNzFCYmjVrlukpaO9Avy2Hlz59+khZWZksWbKk0vr1uXfffdf0LHToLKx58+Zy9dVXm16FfptXf/3rX+W0006LDHdF0x6XrRNPPNH0/l544YXI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bd261XPFrbfe6i1atMjbsGGD9+GHH3p9+vTxGjdubGZYJbPdu3d7//jHP8yib90//elP5v//+te/zPMTJkww+/K1117zVq9ebWYCtm3b1tu3b5/nynrqc7fddpuZIab7d/78+d7pp5/unXDCCd7+/fu9ZHHjjTd69evXN+/TLVu2RJa9e/dGytxwww1e69atvffee89bvny51717d7Mkk8Ot57p167wHH3zQrJ/uT33vtmvXzuvZs6eXLO68804za1Pbr587/T0UCnnvvvtute/HlAto6vHHHzcbOCsry0zjX7ZsmeeSK664wmvevLlZv2OPPdb8rh+cZLdw4UJzgK+46DT28NT9e+65x2vWrJn50nLBBRd4a9eu9VxaTz0Q9u3b12vSpImZDt2mTRvv+uuvT7ovZJWtny7Tp0+PlNEvIjfddJOZAl6rVi3v0ksvNcHApfXMz883wathw4bmPdu+fXvvt7/9rVdQUOAli+uuu868D/V4o+9L/dyFg1l170duHwMAcEJKnUMDALiLgAYAcAIBDQDgBAIaAMAJBDQAgBMIaAAAJxDQAABOIKABAJxAQAOq2bBhwyQUCplF89xpfr/bb7896e6sDQQNt48BEnRPs+nTp5ubH+pNEPV2GxrgHnnkkUQ3DUha9NCABMjOzjZ3B2jVqpUMGjTI3NF33rx55jnNnH/VVVfJscceK7Vq1TL3yHrxxRdjXt+7d2+5+eabTc9O736sdd1///0xZfSmtT169JAaNWqYmy3Onz/fBM05c+ZEymzatEkuv/xyc4shrWfgwIGycePGatoKQNUioAEJpjd9/Oijj8ztjZQOPeptN9566y3znN4A8pe//KX8/e9/j3nds88+K7Vr1za3yJk4caI8+OCDkaCod2bXQKkBUZ//3//9X/nd734X83rtHfbr18/cxfz999+XDz/80NxtWHuPeg8rIOn4kvIYwEFp1vz09HSvdu3aJsO6fgzT0tK8V1555aCvueiii8xtgcJ69erl9ejRI6ZM165dvTvuuMP8/+233/YyMjJisprPmzfP/K3Zs2eb359//nmvQ4cO5i4FYUVFRV7NmjW9d955p0rXGagOnEMDEuC8886TadOmSWFhoUyaNEkyMjJkyJAhkd7Vww8/LC+//LJ89913prekN0vU3la0zp07x/yuN4Tcvn175CaKOpwZfVfgM888M6b8p59+au6KrD20aNpD1BvCAsmGgAYkgA4V6i3r1TPPPGNuWf/000/L8OHD5dFHHzW3r3/sscfM+TMtO2bMmAOGAXWGZDQ9P6Z3Cra5k7kObb7wwgsHPNekSZMjXjcgUQhoQIKlpaXJXXfdJePGjZOrr77anMvSyRm/+MUvzPMapL7++mszsSNeHTp0MBM+tm3bJs2aNTOPffLJJzFlTj/9dHnppZekadOmUq9evSpeK6D6MSkECIDLLrtM0tPTZerUqXLCCSeYyR06UeTLL7+U3/zmNyYw2bjwwgvl+OOPN5cDrF692gTJu+++O9KTU9dcc400btzYBE+dFLJhwwZZtGiRmT357bff+rKegJ8IaEAA6Dm0UaNGmdmKt956q+k96QxEnZ6v58F0xqINDY46PV+HFbt27Sq//vWvI7McdRq/0nNyS5YskdatW8vgwYOlU6dOZshTz6HRY0MyCunMkEQ3AoD/tJem16XpRBDtvQGuIaABjpo9e7a5rkyHMDWI3XLLLXLMMcfIBx98kOimAb5gUgjgqN27d8sdd9wh+fn55lyZZiP54x//mOhmAb6hhwYAcAKTQgAATiCgAQCcQEADADiBgAYAcAIBDQDgBAIaAMAJBDQAgBMIaAAAJxDQAADigv8H6CwGgpTDlqsAAAAASUVORK5CYII=", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "range peaks (array([13, 18, 24, 40, 46, 51]), {})\n", "first range bin 13\n", "doppler peaks (array([15, 21]), {'peak_heights': array([358.50552368, 393.99209595])})\n", "sub doppler width 10\n", "min 15\n", "12.0\n" ] } ], "source": [ "from numpy import mean, concatenate, array, pi\n", "\n", "radar = Radar(transmitter=TransmitterDDM(chirp_end_time=chirp_end_time0,\n", " chirp_slope=chirp_slope0,\n", " chirp_period=chirp_period0,\n", " chirp_count=chirp_count0,\n", " antennas=TXs,\n", " conf={\"TX_phaser_slopes\":\n", " [0, -pi/3]}),\n", " receiver=Receiver(adc_sample_rate=_fs, \n", " adc_sample_count_max=2048,\n", " adc_sample_count=NA,\n", " antennas=RXs),\n", " debug=False)\n", "\n", "r1, theta1 = 10.1, 0\n", "x1, y1 = r1*cos(theta1), r1*sin(theta1)\n", "r2, theta2 = 15.1, pi/2\n", "x2, y2 = r2*cos(theta2), r2*sin(theta2)\n", "r3, theta3 = 20.1, pi*0.8\n", "x3, y3 = r3*cos(theta3), r3*sin(theta3)\n", "\n", "v1 = 1.\n", "scatterer1 = Scatterer(x1, y1, 0, xt= lambda t: x1+v1*t) # 0 degrees on x-axis <=> -pi/2 vs bore sight\n", "scatterer2 = Scatterer(x2, y2, 0) # pi/2 degrees vs x-ax <=> 0 degree vs bore sight\n", "scatterer3 = Scatterer(x3, y3, 0) # 180 degrees on x-axis <=> pi/2 vs boresight\n", "scatterers = [scatterer1, scatterer2, scatterer3]\n", "\n", "bb = rt_points([radar],\n", " scatterers,\n", " radar,\n", " debug=False)\n", "fast_time_axis = 3\n", "slow_time_axis = 1\n", "cube = bb[\"adc_cube\"]\n", "# bb[frame_i, chirp_i, tx_i, rx_i, adc_i]\n", "virtual_cube_RX0 = bb[\"adc_cube\"][0,:,0,:]\n", "virtual_cube_RX1 = bb[\"adc_cube\"][0,:,1,:]\n", "Z = fft(fft(cube, axis=fast_time_axis), axis=slow_time_axis)\n", "Z0 = abs(fft2(virtual_cube_RX0))\n", "Z1 = abs(fft2(virtual_cube_RX1))\n", "\n", "fig, (ax0) = plt.subplots(ncols=1)\n", "ax0.set_xlabel(\"Range\")\n", "ax0.set_ylabel(\"Velocity\")\n", "ax0.set_title('Velocity-Range 2D FFT')\n", "ax0.imshow(abs(Z[0, :, 0,:NA//2]))\n", "plt.show()\n", "\n", "# find peaks\n", "range_pks = find_peaks(abs(Z[0,0,0,:]))\n", "print(\"range peaks\", range_pks)\n", "range_bin_idx = range_pks[0][0]\n", "print(\"first range bin\",range_bin_idx)\n", "doppler_peaks = find_peaks(abs(Z[0,:,0,range_bin_idx]), height=100)\n", "print(\"doppler peaks\", doppler_peaks)\n", "doppler_peaks = doppler_peaks[0]\n", "sub_dop_width = NC//(NT+1)\n", "print(\"sub doppler width\", sub_dop_width)\n", "print(\"min\", min(doppler_peaks))\n", "if min(doppler_peaks) >= sub_dop_width:\n", " dopplers = [d-(idx+1)*sub_dop_width-1 for idx,d in enumerate(doppler_peaks)]\n", " # print(\"dopplers shifted\", dopplers)\n", " print(sub_dop_width+mean(dopplers))" ] }, { "cell_type": "code", "execution_count": 74, "id": "4c94a91c-38f0-460b-b7ca-c08a7486de0f", "metadata": {}, "outputs": [], "source": [ "# non regression hook\n", "# ensure first range bin does not have velocity \n", "# < NF//NT\n", "assert min(doppler_peaks) == 15\n" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.9" } }, "nbformat": 4, "nbformat_minor": 5 }