├── fig
├── demo.png
├── model1.png
├── model2.png
├── transition1.png
└── transition2.png
├── .gitignore
├── README.md
├── vae_generate_lidar.ipynb
└── cGAN_generate_lidar.ipynb
/fig/demo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huangjuite/radar-navigation/HEAD/fig/demo.png
--------------------------------------------------------------------------------
/fig/model1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huangjuite/radar-navigation/HEAD/fig/model1.png
--------------------------------------------------------------------------------
/fig/model2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huangjuite/radar-navigation/HEAD/fig/model2.png
--------------------------------------------------------------------------------
/fig/transition1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huangjuite/radar-navigation/HEAD/fig/transition1.png
--------------------------------------------------------------------------------
/fig/transition2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huangjuite/radar-navigation/HEAD/fig/transition2.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | build/
2 | devel/
3 | result*
4 | *.egg-info
5 | *.pyc
6 | .catkin_workspace
7 | log
8 | .vscode/
9 | procman/bot2-procman/lcmtypes/c/*
10 | procman/bot2-procman/lcmtypes/cpp/*
11 | procman/bot2-procman/pod-build/*
12 | procman/bot2-procman/python/src/bot_procman/build_prefix.py
13 | .ipynb_checkpoints/
14 | *.pkl
15 | bags/*/
16 | __pycache__
17 | events.*
18 | *.pth
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Enabling Learning-based Navigation in Obscurants with Lightweight, Low-cost Millimeter Wave Radar Using Cross-modal Contrastive Learning of Representations
2 |
3 | ## Intro
4 | This repo demonstrate using generative model to reconstruct mmWave radar range data to dense range data closer to LiDAR ground truth.
5 |
6 | The reconstructed range data can be used as signals for control policys.
7 | Futher details please refer to our [website](https://ARG-NCTU.github.io/projects/deeprl-mmWave.html).
8 |
9 |
11 |
12 |
13 | ## Dataset
14 | [dataset on our google drive](https://drive.google.com/drive/u/0/folders/1FMkjvJl070_LxqcNBFeBedPsZFoy0VNe)
15 |
16 | To run the inference model on colab. Please create a short cut of the dataset to your own google drive
17 |
18 |
20 |
22 |
23 | ## inference model
24 | [pretrained model on our google drive](https://drive.google.com/drive/u/2/folders/1oz7vF7SROx8Q85B1cLGpNItQHwsZkCKr)
25 |
26 | To run the inference model on colab. Please also create a short cut of pretrained models to your own google drive
27 |
28 |
30 |
32 |
33 |
34 | ## run colab
35 | - cGAN generate
36 | - [](https://colab.research.google.com/github/huangjuite/radar-navigation/blob/master/cGAN_generate_lidar.ipynb)
37 |
38 | - VAE generate
39 | - [](https://colab.research.google.com/github/huangjuite/radar-navigation/blob/master/vae_generate_lidar.ipynb)
40 |
41 |
42 |
--------------------------------------------------------------------------------
/vae_generate_lidar.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "nbformat": 4,
3 | "nbformat_minor": 0,
4 | "metadata": {
5 | "kernelspec": {
6 | "display_name": "Python 3",
7 | "language": "python",
8 | "name": "python3"
9 | },
10 | "language_info": {
11 | "codemirror_mode": {
12 | "name": "ipython",
13 | "version": 3
14 | },
15 | "file_extension": ".py",
16 | "mimetype": "text/x-python",
17 | "name": "python",
18 | "nbconvert_exporter": "python",
19 | "pygments_lexer": "ipython3",
20 | "version": "3.6.9"
21 | },
22 | "colab": {
23 | "name": "vae_generate_lidar.ipynb",
24 | "provenance": []
25 | },
26 | "accelerator": "GPU"
27 | },
28 | "cells": [
29 | {
30 | "cell_type": "code",
31 | "metadata": {
32 | "id": "UJLg_uaFqf2V"
33 | },
34 | "source": [
35 | "import os\n",
36 | "import io\n",
37 | "import cv2\n",
38 | "import copy\n",
39 | "import math\n",
40 | "import random\n",
41 | "import numpy as np\n",
42 | "import pickle as pkl\n",
43 | "from tqdm import tqdm, trange\n",
44 | "from typing import Deque, Dict, List, Tuple\n",
45 | "import matplotlib.pyplot as plt\n",
46 | "\n",
47 | "\n",
48 | "import torch\n",
49 | "import torch.nn as nn\n",
50 | "import torch.nn.functional as F\n",
51 | "import torch.optim as optim\n",
52 | "from torch.utils.data.dataset import Dataset\n",
53 | "from torch.utils.data import DataLoader, random_split\n",
54 | "\n"
55 | ],
56 | "execution_count": 1,
57 | "outputs": []
58 | },
59 | {
60 | "cell_type": "markdown",
61 | "metadata": {
62 | "id": "Ca4eB4Gxqf2Z"
63 | },
64 | "source": [
65 | "## dataset\n",
66 | "\n",
67 | " Load dataset from your google drive.\n",
68 | " Please add a short cut of our dataset on google drive to your own google drive.\n",
69 | " Change the \"main_path\" of the dataset if necessary."
70 | ]
71 | },
72 | {
73 | "cell_type": "code",
74 | "metadata": {
75 | "id": "VtEy0lUxqp6M",
76 | "outputId": "d2c4be62-2d5f-499c-a26a-fd37109077c4",
77 | "colab": {
78 | "base_uri": "https://localhost:8080/",
79 | "height": 35
80 | }
81 | },
82 | "source": [
83 | "from google.colab import drive\n",
84 | "drive.mount('/content/gdrive')"
85 | ],
86 | "execution_count": 2,
87 | "outputs": [
88 | {
89 | "output_type": "stream",
90 | "text": [
91 | "Mounted at /content/gdrive\n"
92 | ],
93 | "name": "stdout"
94 | }
95 | ]
96 | },
97 | {
98 | "cell_type": "code",
99 | "metadata": {
100 | "scrolled": true,
101 | "id": "7vg8gr-Yqf2Z",
102 | "outputId": "5ac148d7-1f83-4df6-ee9d-0fa25bb29adc",
103 | "colab": {
104 | "base_uri": "https://localhost:8080/",
105 | "height": 35
106 | }
107 | },
108 | "source": [
109 | "paths = []\n",
110 | "main_path = '/content/gdrive/My Drive/transitions/'\n",
111 | "dirs = os.listdir(main_path)\n",
112 | "dirs.sort()\n",
113 | "for d in dirs:\n",
114 | " dirs1 = os.listdir(main_path+'/'+d)\n",
115 | " dirs1.sort()\n",
116 | " for p in dirs1:\n",
117 | " paths.append(main_path+'/'+d+'/'+p)\n",
118 | " # print(paths[-1])\n",
119 | "print('%d episodes'%len(paths))\n"
120 | ],
121 | "execution_count": 3,
122 | "outputs": [
123 | {
124 | "output_type": "stream",
125 | "text": [
126 | "228 episodes\n"
127 | ],
128 | "name": "stdout"
129 | }
130 | ]
131 | },
132 | {
133 | "cell_type": "code",
134 | "metadata": {
135 | "id": "pgYz_jarqf2d",
136 | "outputId": "3b6ced08-2a0e-4ac9-c6b1-d834c6e8edf0",
137 | "colab": {
138 | "base_uri": "https://localhost:8080/",
139 | "height": 35
140 | }
141 | },
142 | "source": [
143 | "class MMDataset(Dataset):\n",
144 | " def __init__(self, paths):\n",
145 | " self.transitions = []\n",
146 | "\n",
147 | " for p in tqdm(paths):\n",
148 | " with open(p, \"rb\") as f:\n",
149 | " demo = pkl.load(f, encoding=\"bytes\")\n",
150 | " self.transitions.extend(demo)\n",
151 | " \n",
152 | " def __getitem__(self,index):\n",
153 | " mm_scan = self.transitions[index][b'mm_scan']\n",
154 | " laser_scan = self.transitions[index][b'laser_scan']\n",
155 | " mm_scan = torch.Tensor(mm_scan).reshape(1,-1)\n",
156 | " laser_scan = torch.Tensor(laser_scan).reshape(1,-1)\n",
157 | " \n",
158 | " return mm_scan, laser_scan\n",
159 | " \n",
160 | " def __len__(self):\n",
161 | " return len(self.transitions)\n",
162 | "\n",
163 | " \n",
164 | "batch_size = 16\n",
165 | "mm_dataset = MMDataset(paths)\n",
166 | "\n",
167 | "loader = DataLoader(dataset=mm_dataset,\n",
168 | " batch_size=batch_size,\n",
169 | " shuffle=True,\n",
170 | " num_workers=4)\n"
171 | ],
172 | "execution_count": 4,
173 | "outputs": [
174 | {
175 | "output_type": "stream",
176 | "text": [
177 | "100%|██████████| 228/228 [02:25<00:00, 1.57it/s]\n"
178 | ],
179 | "name": "stderr"
180 | }
181 | ]
182 | },
183 | {
184 | "cell_type": "markdown",
185 | "metadata": {
186 | "id": "xqmER4KDqf2g"
187 | },
188 | "source": [
189 | "## hyper parameters"
190 | ]
191 | },
192 | {
193 | "cell_type": "code",
194 | "metadata": {
195 | "id": "_w0mwItAqf2h"
196 | },
197 | "source": [
198 | "hyper_parameter = dict(\n",
199 | " kernel=3,\n",
200 | " stride=2,\n",
201 | " padding=2,\n",
202 | " latent=128,\n",
203 | " deconv_dim=32,\n",
204 | " deconv_channel=128,\n",
205 | " adjust_linear=235,\n",
206 | " epoch=100,\n",
207 | " learning_rate=0.001,\n",
208 | ")\n",
209 | "class Struct:\n",
210 | " def __init__(self, **entries):\n",
211 | " self.__dict__.update(entries)\n",
212 | "config = Struct(**hyper_parameter)"
213 | ],
214 | "execution_count": 5,
215 | "outputs": []
216 | },
217 | {
218 | "cell_type": "markdown",
219 | "metadata": {
220 | "id": "8oKinQAWqf2j"
221 | },
222 | "source": [
223 | "## model"
224 | ]
225 | },
226 | {
227 | "cell_type": "code",
228 | "metadata": {
229 | "id": "HSCKIfJfqf2k"
230 | },
231 | "source": [
232 | "class MMvae(nn.Module):\n",
233 | " def __init__(self):\n",
234 | " super(MMvae, self).__init__()\n",
235 | " kernel = 3\n",
236 | " stride = 2\n",
237 | " self.conv = nn.Sequential(\n",
238 | " nn.Conv1d(1, 64, kernel_size=kernel, stride=stride),\n",
239 | " nn.ReLU(),\n",
240 | " nn.Conv1d(64, 64, kernel_size=kernel, stride=stride),\n",
241 | " nn.ReLU()\n",
242 | " )\n",
243 | " \n",
244 | " dim = 64*59\n",
245 | " self.linear1=nn.Sequential(\n",
246 | " nn.Linear(dim,512),\n",
247 | " nn.ReLU()\n",
248 | " )\n",
249 | " self.en_fc1=nn.Linear(512,config.latent)\n",
250 | " self.en_fc2=nn.Linear(512,config.latent)\n",
251 | " \n",
252 | " self.de_fc1=nn.Sequential(\n",
253 | " nn.Linear(config.latent,config.deconv_channel*config.deconv_dim),\n",
254 | " nn.ReLU()\n",
255 | " )\n",
256 | " \n",
257 | " self.de_conv =nn.Sequential(\n",
258 | " nn.ConvTranspose1d(config.deconv_channel, config.deconv_channel//2, kernel, stride=stride, padding=config.padding),\n",
259 | "# nn.ReLU(),\n",
260 | " nn.ConvTranspose1d(config.deconv_channel//2, config.deconv_channel//4, kernel, stride=stride, padding=config.padding),\n",
261 | "# nn.ReLU(),\n",
262 | " nn.ConvTranspose1d(config.deconv_channel//4, 1, kernel, stride=stride, padding=config.padding),\n",
263 | "# nn.ReLU(),\n",
264 | " )\n",
265 | " self.adjust_linear=nn.Sequential(\n",
266 | " nn.Linear(config.adjust_linear,241),\n",
267 | " nn.ReLU()\n",
268 | " )\n",
269 | "\n",
270 | " \n",
271 | " def encoder(self,x):\n",
272 | " x = self.conv(x)\n",
273 | " x = x.view(x.size(0),-1)\n",
274 | " x = self.linear1(x)\n",
275 | " mean = self.en_fc1(x)\n",
276 | " logvar = self.en_fc2(x)\n",
277 | " return mean, logvar\n",
278 | "\n",
279 | " def reparameter(self, mean, logvar):\n",
280 | " std = torch.exp(0.5*logvar)\n",
281 | " eps = torch.randn_like(std)\n",
282 | " return mean + eps*std\n",
283 | "\n",
284 | " def decoder(self,x):\n",
285 | " x = self.de_fc1(x)\n",
286 | " x = x.view(-1, config.deconv_channel, config.deconv_dim)\n",
287 | " x = self.de_conv(x)\n",
288 | " x = self.adjust_linear(x)\n",
289 | " return x\n",
290 | "\n",
291 | " def forward(self,x):\n",
292 | " mean, logvar = self.encoder(x)\n",
293 | " x = self.reparameter(mean, logvar)\n",
294 | " x = self.decoder(x)\n",
295 | " return x ,mean ,logvar"
296 | ],
297 | "execution_count": 6,
298 | "outputs": []
299 | },
300 | {
301 | "cell_type": "markdown",
302 | "metadata": {
303 | "id": "M9p8UDYFqf2n"
304 | },
305 | "source": [
306 | "## load model\n",
307 | "\n",
308 | " Load model from your google drive.\n",
309 | " Please add a short cut of our inference model on google drive to your own google drive.\n",
310 | " Change the \"model_path\" of the dataset if necessary. "
311 | ]
312 | },
313 | {
314 | "cell_type": "code",
315 | "metadata": {
316 | "scrolled": false,
317 | "id": "_-OT3hAEqf2n",
318 | "outputId": "157db66c-0138-47b8-9de1-e71d45dac4fe",
319 | "colab": {
320 | "base_uri": "https://localhost:8080/",
321 | "height": 54
322 | }
323 | },
324 | "source": [
325 | "device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\n",
326 | "print('device, ',device)\n",
327 | "model = MMvae()\n",
328 | "model.to(device)\n",
329 | "model_path = '/content/gdrive/My Drive/deploy_model/vae/0726_1557.pth'\n",
330 | "model.load_state_dict(torch.load(model_path))"
331 | ],
332 | "execution_count": 7,
333 | "outputs": [
334 | {
335 | "output_type": "stream",
336 | "text": [
337 | "device, cuda:0\n"
338 | ],
339 | "name": "stdout"
340 | },
341 | {
342 | "output_type": "execute_result",
343 | "data": {
344 | "text/plain": [
345 | ""
346 | ]
347 | },
348 | "metadata": {
349 | "tags": []
350 | },
351 | "execution_count": 7
352 | }
353 | ]
354 | },
355 | {
356 | "cell_type": "markdown",
357 | "metadata": {
358 | "id": "Cv74SaEpqf2r"
359 | },
360 | "source": [
361 | "## visualize examples"
362 | ]
363 | },
364 | {
365 | "cell_type": "code",
366 | "metadata": {
367 | "id": "FVdIzAeGqf2s"
368 | },
369 | "source": [
370 | "def laser_visual(lasers=[], show=False, range_limit=6):\n",
371 | " colors = ['#3483EB','#FFA500','#15B01D']\n",
372 | " fig = plt.figure(figsize=(8, 8))\n",
373 | " for i, l in enumerate(lasers):\n",
374 | " # fig = plt.figure(figsize=(8, 8))\n",
375 | " angle = 120\n",
376 | " xp = []\n",
377 | " yp = []\n",
378 | " for r in l:\n",
379 | " if r <= range_limit:\n",
380 | " yp.append(r * math.cos(math.radians(angle)))\n",
381 | " xp.append(r * math.sin(math.radians(angle)))\n",
382 | " angle -= 1\n",
383 | " plt.xlim(-6, 6)\n",
384 | " plt.ylim(-6, 6)\n",
385 | " # plt.axis('off')\n",
386 | " plt.plot(xp, yp, 'x', color=colors[i])\n",
387 | " plt.show()\n"
388 | ],
389 | "execution_count": 8,
390 | "outputs": []
391 | },
392 | {
393 | "cell_type": "code",
394 | "metadata": {
395 | "id": "ewAqFzV3qf2v",
396 | "outputId": "461b16d2-3dc1-4cdc-85dc-195cc88a11f0",
397 | "colab": {
398 | "base_uri": "https://localhost:8080/",
399 | "height": 487
400 | }
401 | },
402 | "source": [
403 | "data1 = None\n",
404 | "for mm_scan, laser_scan in loader:\n",
405 | " mm_scan = mm_scan.to(device)\n",
406 | " \n",
407 | " x_hat ,mean ,logvar = model(mm_scan)\n",
408 | " \n",
409 | " x = x_hat.detach().cpu().numpy().reshape(batch_size,-1)[0]\n",
410 | " laser = laser_scan.numpy().reshape(batch_size,-1)[0]\n",
411 | " mm = mm_scan.detach().cpu().numpy().reshape(batch_size,-1)[0]\n",
412 | " \n",
413 | " laser_visual([laser, x, mm], show=True, range_limit=4.9)\n",
414 | " data1 = [laser, x, mm]\n",
415 | " break"
416 | ],
417 | "execution_count": 9,
418 | "outputs": [
419 | {
420 | "output_type": "display_data",
421 | "data": {
422 | "image/png": "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\n",
423 | "text/plain": [
424 | ""
425 | ]
426 | },
427 | "metadata": {
428 | "tags": [],
429 | "needs_background": "light"
430 | }
431 | }
432 | ]
433 | }
434 | ]
435 | }
--------------------------------------------------------------------------------
/cGAN_generate_lidar.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "nbformat": 4,
3 | "nbformat_minor": 0,
4 | "metadata": {
5 | "kernelspec": {
6 | "display_name": "Python 3",
7 | "language": "python",
8 | "name": "python3"
9 | },
10 | "language_info": {
11 | "codemirror_mode": {
12 | "name": "ipython",
13 | "version": 3
14 | },
15 | "file_extension": ".py",
16 | "mimetype": "text/x-python",
17 | "name": "python",
18 | "nbconvert_exporter": "python",
19 | "pygments_lexer": "ipython3",
20 | "version": "3.6.9"
21 | },
22 | "colab": {
23 | "name": "cGAN_generate_lidar.ipynb",
24 | "provenance": []
25 | },
26 | "accelerator": "GPU"
27 | },
28 | "cells": [
29 | {
30 | "cell_type": "markdown",
31 | "metadata": {
32 | "id": "P_VunP7mcLdF"
33 | },
34 | "source": [
35 | "## cGAN generate LiDAR"
36 | ]
37 | },
38 | {
39 | "cell_type": "code",
40 | "metadata": {
41 | "id": "jXbqhZBHcLdG"
42 | },
43 | "source": [
44 | "import os\n",
45 | "import io\n",
46 | "import cv2\n",
47 | "import copy\n",
48 | "import math\n",
49 | "import random\n",
50 | "import numpy as np\n",
51 | "import pickle as pkl\n",
52 | "from tqdm import tqdm, trange\n",
53 | "from typing import Deque, Dict, List, Tuple\n",
54 | "import matplotlib.pyplot as plt\n",
55 | "\n",
56 | "\n",
57 | "import torch\n",
58 | "import torch.nn as nn\n",
59 | "import torch.nn.functional as F\n",
60 | "import torch.optim as optim\n",
61 | "from torch.autograd import Variable\n",
62 | "from torch.utils.data.dataset import Dataset\n",
63 | "from torch.utils.data import DataLoader, random_split\n",
64 | "\n"
65 | ],
66 | "execution_count": 1,
67 | "outputs": []
68 | },
69 | {
70 | "cell_type": "markdown",
71 | "metadata": {
72 | "id": "f1qtyFZicLdK"
73 | },
74 | "source": [
75 | "## dataset\n",
76 | "\n",
77 | " Load dataset from your google drive.\n",
78 | " Please add a short cut of our dataset on google drive to your own google drive.\n",
79 | " Change the \"main_path\" of the dataset if necessary."
80 | ]
81 | },
82 | {
83 | "cell_type": "code",
84 | "metadata": {
85 | "id": "79mIlikZiu92",
86 | "outputId": "0d709ee2-7966-48ec-86b1-1026c2401595",
87 | "colab": {
88 | "base_uri": "https://localhost:8080/",
89 | "height": 35
90 | }
91 | },
92 | "source": [
93 | "from google.colab import drive\n",
94 | "drive.mount('/content/gdrive')"
95 | ],
96 | "execution_count": 2,
97 | "outputs": [
98 | {
99 | "output_type": "stream",
100 | "text": [
101 | "Drive already mounted at /content/gdrive; to attempt to forcibly remount, call drive.mount(\"/content/gdrive\", force_remount=True).\n"
102 | ],
103 | "name": "stdout"
104 | }
105 | ]
106 | },
107 | {
108 | "cell_type": "code",
109 | "metadata": {
110 | "scrolled": true,
111 | "id": "YqeNMpGCcLdK",
112 | "outputId": "1e762023-ed41-41cd-f3c5-c6b5617462ae",
113 | "colab": {
114 | "base_uri": "https://localhost:8080/",
115 | "height": 35
116 | }
117 | },
118 | "source": [
119 | "paths = []\n",
120 | "main_path = '/content/gdrive/My Drive/transitions/'\n",
121 | "dirs = os.listdir(main_path)\n",
122 | "dirs.sort()\n",
123 | "for d in dirs:\n",
124 | " dirs1 = os.listdir(main_path+'/'+d)\n",
125 | " dirs1.sort()\n",
126 | " for p in dirs1:\n",
127 | " paths.append(main_path+'/'+d+'/'+p)\n",
128 | " # print(paths[-1])\n",
129 | "print('%d episodes'%len(paths))\n"
130 | ],
131 | "execution_count": 3,
132 | "outputs": [
133 | {
134 | "output_type": "stream",
135 | "text": [
136 | "228 episodes\n"
137 | ],
138 | "name": "stdout"
139 | }
140 | ]
141 | },
142 | {
143 | "cell_type": "code",
144 | "metadata": {
145 | "id": "14HAQLFucLdO",
146 | "outputId": "7338d1ce-f233-4a77-9db5-3f73f6c0b310",
147 | "colab": {
148 | "base_uri": "https://localhost:8080/",
149 | "height": 35
150 | }
151 | },
152 | "source": [
153 | "class MMDataset(Dataset):\n",
154 | " def __init__(self, paths):\n",
155 | " self.transitions = []\n",
156 | "\n",
157 | " for p in tqdm(paths):\n",
158 | " with open(p, \"rb\") as f:\n",
159 | " demo = pkl.load(f, encoding=\"bytes\")\n",
160 | " self.transitions.extend(demo)\n",
161 | " \n",
162 | " def __getitem__(self,index):\n",
163 | " mm_scan = self.transitions[index][b'mm_scan']\n",
164 | " laser_scan = self.transitions[index][b'laser_scan']\n",
165 | " mm_scan = torch.Tensor(mm_scan).reshape(1,-1)\n",
166 | " laser_scan = torch.Tensor(laser_scan).reshape(1,-1)\n",
167 | " \n",
168 | " return mm_scan, laser_scan\n",
169 | " \n",
170 | " def __len__(self):\n",
171 | " return len(self.transitions)\n",
172 | "\n",
173 | " \n",
174 | "batch_size = 16\n",
175 | "mm_dataset = MMDataset(paths)\n",
176 | "\n",
177 | "loader = DataLoader(dataset=mm_dataset,\n",
178 | " batch_size=batch_size,\n",
179 | " shuffle=True,\n",
180 | " num_workers=4)\n"
181 | ],
182 | "execution_count": 4,
183 | "outputs": [
184 | {
185 | "output_type": "stream",
186 | "text": [
187 | "100%|██████████| 228/228 [00:05<00:00, 40.39it/s]\n"
188 | ],
189 | "name": "stderr"
190 | }
191 | ]
192 | },
193 | {
194 | "cell_type": "markdown",
195 | "metadata": {
196 | "id": "vR_682nicLdR"
197 | },
198 | "source": [
199 | "## hyper parameters"
200 | ]
201 | },
202 | {
203 | "cell_type": "code",
204 | "metadata": {
205 | "id": "Y9F8bdeOcLdR"
206 | },
207 | "source": [
208 | "hyper_parameter = dict(\n",
209 | " kernel=3,\n",
210 | " stride=2,\n",
211 | " padding=2,\n",
212 | " deconv_dim=32,\n",
213 | " deconv_channel=128,\n",
214 | " adjust_linear=235,\n",
215 | " epoch=500,\n",
216 | " beta1=0.5,\n",
217 | " learning_rate=0.0002,\n",
218 | " nz=100,\n",
219 | " lambda_l1=100,\n",
220 | ")\n",
221 | "class Struct:\n",
222 | " def __init__(self, **entries):\n",
223 | " self.__dict__.update(entries)\n",
224 | "config = Struct(**hyper_parameter)"
225 | ],
226 | "execution_count": 5,
227 | "outputs": []
228 | },
229 | {
230 | "cell_type": "markdown",
231 | "metadata": {
232 | "id": "85dWFlDCcLdU"
233 | },
234 | "source": [
235 | "## model"
236 | ]
237 | },
238 | {
239 | "cell_type": "code",
240 | "metadata": {
241 | "id": "yNAlrgJXcLdU"
242 | },
243 | "source": [
244 | "class Generator(nn.Module):\n",
245 | " def __init__(self):\n",
246 | " super(Generator, self).__init__()\n",
247 | " kernel = 3\n",
248 | " stride = 2\n",
249 | " self.conv = nn.Sequential(\n",
250 | " nn.Conv1d(1, 64, kernel_size=kernel, stride=stride),\n",
251 | " nn.ReLU(),\n",
252 | " nn.Conv1d(64, 64, kernel_size=kernel, stride=stride),\n",
253 | " nn.ReLU()\n",
254 | " )\n",
255 | " \n",
256 | " dim = 64*59\n",
257 | " self.linear=nn.Sequential(\n",
258 | " nn.Linear(dim,512),\n",
259 | " nn.ReLU(),\n",
260 | " nn.Linear(512,128)\n",
261 | " )\n",
262 | " \n",
263 | "# self.n_fc1=nn.Linear(config.nz, 128)\n",
264 | "# self.n_fc2=nn.Linear(128, 128)\n",
265 | " \n",
266 | "# self.fc_combine=nn.Linear(128*2, 128)\n",
267 | " \n",
268 | " self.de_fc1=nn.Sequential(\n",
269 | " nn.Linear(128,config.deconv_channel*config.deconv_dim),\n",
270 | " nn.ReLU()\n",
271 | " )\n",
272 | " \n",
273 | " self.de_conv =nn.Sequential(\n",
274 | " nn.ConvTranspose1d(config.deconv_channel, config.deconv_channel//2, kernel, stride=stride, padding=config.padding),\n",
275 | " nn.ConvTranspose1d(config.deconv_channel//2, config.deconv_channel//4, kernel, stride=stride, padding=config.padding),\n",
276 | " nn.ConvTranspose1d(config.deconv_channel//4, 1, kernel, stride=stride, padding=config.padding),\n",
277 | " )\n",
278 | " self.adjust_linear=nn.Sequential(\n",
279 | " nn.Linear(config.adjust_linear,241),\n",
280 | " nn.ReLU()\n",
281 | " )\n",
282 | "\n",
283 | " \n",
284 | " def encoder(self,x):\n",
285 | " x = self.conv(x)\n",
286 | " x = x.view(x.size(0),-1)\n",
287 | " x = self.linear(x)\n",
288 | " return x\n",
289 | "\n",
290 | " def decoder(self,x):\n",
291 | " x = self.de_fc1(x)\n",
292 | " x = x.view(-1, config.deconv_channel, config.deconv_dim)\n",
293 | " x = self.de_conv(x)\n",
294 | " x = self.adjust_linear(x)\n",
295 | " return x\n",
296 | "\n",
297 | " def forward(self, x):\n",
298 | " x = self.encoder(x)\n",
299 | "# n = self.n_fc1(n)\n",
300 | "# n = self.n_fc2(n)\n",
301 | " \n",
302 | "# x = torch.cat((x,n),dim=-1)\n",
303 | "# x = self.fc_combine(x)\n",
304 | " \n",
305 | " x = self.decoder(x)\n",
306 | " return x"
307 | ],
308 | "execution_count": 6,
309 | "outputs": []
310 | },
311 | {
312 | "cell_type": "code",
313 | "metadata": {
314 | "id": "sTNajyBWcLdX"
315 | },
316 | "source": [
317 | "class Discriminator(nn.Module):\n",
318 | " def __init__(self):\n",
319 | " super(Discriminator, self).__init__()\n",
320 | " kernel = 3\n",
321 | " stride = 2\n",
322 | " self.conv = nn.Sequential(\n",
323 | " nn.Conv1d(2, 64, kernel_size=kernel, stride=stride),\n",
324 | " nn.ReLU(),\n",
325 | " nn.Conv1d(64, 64, kernel_size=kernel, stride=stride),\n",
326 | " nn.ReLU()\n",
327 | " )\n",
328 | " \n",
329 | " dim = 64*59\n",
330 | " self.linear=nn.Sequential(\n",
331 | " nn.Linear(dim,512),\n",
332 | " nn.ReLU(),\n",
333 | " nn.Linear(512,128),\n",
334 | " nn.ReLU(),\n",
335 | " nn.Linear(128, 1),\n",
336 | " nn.Sigmoid(),\n",
337 | " )\n",
338 | "\n",
339 | " def forward(self, x):\n",
340 | " \n",
341 | " x = self.conv(x)\n",
342 | " x = x.view(x.size(0),-1)\n",
343 | " x = self.linear(x)\n",
344 | " \n",
345 | " return x"
346 | ],
347 | "execution_count": 7,
348 | "outputs": []
349 | },
350 | {
351 | "cell_type": "markdown",
352 | "metadata": {
353 | "id": "npt_JqzGcLda"
354 | },
355 | "source": [
356 | "## load model\n",
357 | "\n",
358 | " Load model from your google drive.\n",
359 | " Please add a short cut of our inference model on google drive to your own google drive.\n",
360 | " Change the \"model_path\" of the dataset if necessary. "
361 | ]
362 | },
363 | {
364 | "cell_type": "code",
365 | "metadata": {
366 | "id": "1r_OdviacLda",
367 | "outputId": "a1bcb9f9-da76-4e28-c727-ef894d360881",
368 | "colab": {
369 | "base_uri": "https://localhost:8080/",
370 | "height": 508
371 | }
372 | },
373 | "source": [
374 | "device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\n",
375 | "print('device, ',device)\n",
376 | "model = Generator()\n",
377 | "\n",
378 | "# bce logits loss L1:0.1163\n",
379 | "model_path = '/content/gdrive/My Drive/deploy_model/cgan/0827_1851.pth'\n",
380 | "\n",
381 | "model.load_state_dict(torch.load(model_path))\n",
382 | "model.to(device)\n"
383 | ],
384 | "execution_count": 8,
385 | "outputs": [
386 | {
387 | "output_type": "stream",
388 | "text": [
389 | "device, cuda:0\n"
390 | ],
391 | "name": "stdout"
392 | },
393 | {
394 | "output_type": "execute_result",
395 | "data": {
396 | "text/plain": [
397 | "Generator(\n",
398 | " (conv): Sequential(\n",
399 | " (0): Conv1d(1, 64, kernel_size=(3,), stride=(2,))\n",
400 | " (1): ReLU()\n",
401 | " (2): Conv1d(64, 64, kernel_size=(3,), stride=(2,))\n",
402 | " (3): ReLU()\n",
403 | " )\n",
404 | " (linear): Sequential(\n",
405 | " (0): Linear(in_features=3776, out_features=512, bias=True)\n",
406 | " (1): ReLU()\n",
407 | " (2): Linear(in_features=512, out_features=128, bias=True)\n",
408 | " )\n",
409 | " (de_fc1): Sequential(\n",
410 | " (0): Linear(in_features=128, out_features=4096, bias=True)\n",
411 | " (1): ReLU()\n",
412 | " )\n",
413 | " (de_conv): Sequential(\n",
414 | " (0): ConvTranspose1d(128, 64, kernel_size=(3,), stride=(2,), padding=(2,))\n",
415 | " (1): ConvTranspose1d(64, 32, kernel_size=(3,), stride=(2,), padding=(2,))\n",
416 | " (2): ConvTranspose1d(32, 1, kernel_size=(3,), stride=(2,), padding=(2,))\n",
417 | " )\n",
418 | " (adjust_linear): Sequential(\n",
419 | " (0): Linear(in_features=235, out_features=241, bias=True)\n",
420 | " (1): ReLU()\n",
421 | " )\n",
422 | ")"
423 | ]
424 | },
425 | "metadata": {
426 | "tags": []
427 | },
428 | "execution_count": 8
429 | }
430 | ]
431 | },
432 | {
433 | "cell_type": "markdown",
434 | "metadata": {
435 | "id": "fofwexSxcLdd"
436 | },
437 | "source": [
438 | "## visualize"
439 | ]
440 | },
441 | {
442 | "cell_type": "code",
443 | "metadata": {
444 | "id": "T0ZBUAA3cLde"
445 | },
446 | "source": [
447 | "def laser_visual(lasers=[], show=False, range_limit=6):\n",
448 | " colors = ['#3483EB','#FFA500','#15B01D']\n",
449 | " fig = plt.figure(figsize=(8, 8))\n",
450 | " for i, l in enumerate(lasers):\n",
451 | " # fig = plt.figure(figsize=(8, 8))\n",
452 | " angle = 120\n",
453 | " xp = []\n",
454 | " yp = []\n",
455 | " for r in l:\n",
456 | " if r <= range_limit:\n",
457 | " yp.append(r * math.cos(math.radians(angle)))\n",
458 | " xp.append(r * math.sin(math.radians(angle)))\n",
459 | " angle -= 1\n",
460 | " plt.xlim(-6, 6)\n",
461 | " plt.ylim(-6, 6)\n",
462 | " # plt.axis('off')\n",
463 | " plt.plot(xp, yp, 'x', color=colors[i])\n",
464 | " plt.show()\n"
465 | ],
466 | "execution_count": 9,
467 | "outputs": []
468 | },
469 | {
470 | "cell_type": "code",
471 | "metadata": {
472 | "scrolled": false,
473 | "id": "IFUUegxMcLdg",
474 | "outputId": "a56a43ef-4603-454f-fe7b-5e57fd3d9542",
475 | "colab": {
476 | "base_uri": "https://localhost:8080/",
477 | "height": 487
478 | }
479 | },
480 | "source": [
481 | "data1 = None\n",
482 | "for mm_scan, laser_scan in loader:\n",
483 | " mm_scan = mm_scan.to(device)\n",
484 | " x_hat = model(mm_scan)\n",
485 | " \n",
486 | " x = x_hat.detach().cpu().numpy().reshape(batch_size,-1)[0]\n",
487 | " laser = laser_scan.numpy().reshape(batch_size,-1)[0]\n",
488 | " mm = mm_scan.detach().cpu().numpy().reshape(batch_size,-1)[0]\n",
489 | " \n",
490 | " laser_visual([laser, x, mm], show=True, range_limit=4.9)\n",
491 | " data1 = [laser, x, mm]\n",
492 | " \n",
493 | " break"
494 | ],
495 | "execution_count": 15,
496 | "outputs": [
497 | {
498 | "output_type": "display_data",
499 | "data": {
500 | "image/png": "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kbqgUBYREbGJ2oayFnqJiIjYhEJZRETEJhTKIiIiNqFQFhERsQmFsoiIiE0olEVERGxCoSwiImITCmURERGbUCiLiIjYhEJZRETEJhTKIiIiNqFQFhERsQmFsoiIiE0olEVERGxCoSwiImITCmURERGbUCiLiIjYhEJZRETEJhTKIiIiNqFQFhERsQmFsoiIiE0olEVERGxCoSwiImITCmURERGbUCiLiIjYhEJZRETEJhTKIiIiNqFQFhERsQmFsoiIiE0olEVERGxCoSwiImITCmURERGbUCiLiIjYhEJZRETEJhTKIiIiNnFEoWxZ1qOWZa23LGuNZVlvWZbVNFgNExERaWiOtKf8EXC6MeYM4Htg/JE3SUREpGE6olA2xiwyxvjKHn4NtDnyJomIiDRMwZxT/iuwMIjXExERaVBchzrBsqyPgZbVPPV/xph3ys75P8AHzK7hOqOAUQDHH3/872qsiIhIODtkKBtjBtb0vGVZ1wEXAwOMMaaG67wAvADgdrsPep6IiEhDdchQrollWecDY4G+xpiC4DRJRESkYTrSOeWngTjgI8uyVlmW9VwQ2iQiItIgHVFP2RjTNlgNERERaehU0UtERMQmFMoiIiI2oVAWERGxCYWyiIiITSiURUREbEKhLCIiYhMKZREREZtQKIuIiNiEQllERMQmFMoiIiI2oVAWERGxCYWyiIiITSiURUREbEKhLCIiYhMKZREREZtQKIuIiNiEQllERMQmFMoiIiI2oVAWERGxCYWyiIiITSiURUREbEKhLCIiYhMKZREREZtQKIuIiNiEQllERMQmFMoiIiI2oVAWERGxCYWyiIiITSiURUREbEKhLCIiYhMKZREREZtQKIuIiNiEQllERMQmFMoiIiI2oVAWERGxCYWyiIiITSiURUREbEKhLCIiYhMKZREREZtQKIuIiNiEQllERMQmFMoiIiI2oVAWERGxCYWyiIiITSiURUREbEKhLCIiYhMKZREREZtQKIuIiNiEQllERMQmFMoiIiI2oVAWERGxCYWyiIiITSiURUREbEKhLCIiYhMKZREREZtQKIuIiNiEQllERMQmFMoiIiI2oVAWERGxCYWyiIiITSiURUREbEKhLCIiYhMKZREREZtQKIuIiNhEUELZsqwxlmUZy7JaBON6IiIiDdERh7JlWccBg4Cfjrw5IiIi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\n",
501 | "text/plain": [
502 | ""
503 | ]
504 | },
505 | "metadata": {
506 | "tags": [],
507 | "needs_background": "light"
508 | }
509 | }
510 | ]
511 | },
512 | {
513 | "cell_type": "code",
514 | "metadata": {
515 | "id": "rNiHJNispA6U"
516 | },
517 | "source": [
518 | ""
519 | ],
520 | "execution_count": 10,
521 | "outputs": []
522 | }
523 | ]
524 | }
--------------------------------------------------------------------------------