まぐらぼ

Unity/Android、Microsoft系のWPFをやってます。

DMM.make料金

https://akiba.dmm-make.com/files/information/MachineList.pdf

https://akiba.dmm-make.com/about/machinesDetail/32
ライセンス有の場合、
1block: 500 円
2block以降: 500 円 /block
※1block = 30分

https://akiba.dmm-make.com/about/machinesDetail/43
LEF-12
1block: 1,000 円
2block以降:1,000 円 /block
※1block = 1時間


刺しゅうミシン PR655
https://akiba.dmm-make.com/about/machinesDetail/52
1block: 1,000 円
2block以降: 1,000 円 /block
※1block = 1時間

jetbot/コントローラー

jetbotとコントローラーが接続してください。次のURLでコントローラーボタン押下の挙動が確認できます。
html5gamepad.com

Jupyterのスクリプトからコントローラーに接続すると次の表示がでます。

f:id:o-maguro:20200211231703p:plain
正常動作の場合はkey widget がでます。

controller = widgets.Controller(index=1) # replace with index of your controller

INDEX=0に変更しました。
他PCから接続した場合はうまく動きませんでした。jetsonにHDMLケーブルとキーボード・マウス接続して起動したらうまくいきました。理由は不明。

jetbot/Road Following/ライントレース/Line Trace

コントローラーが動作することを確認してからの方がよいと思う。
回帰(regression)学習を行う。
前の衝突回避のように教師データ(写真)を作成する

緑の点を動かして教師データを撮影していきます。

jetbot_collision_avoidance

collition_avoidance/data_collection.ipynb
カメラは224x224

import traitlets
import ipywidgets.widgets as widgets
from IPython.display import display
from jetbot import Camera, bgr8_to_jpeg

camera = Camera.instance(width=224, height=224)

image = widgets.Image(format='jpeg', width=224, height=224) # this width and height doesn't necessarily have to match the camera

camera_link = traitlets.dlink((camera, 'value'), (image, 'value'), transform=bgr8_to_jpeg)

display(image)

データセットフォルダを作成する。すでに存在する場合は何もしない。
import os

blocked_dir = 'dataset/blocked'
free_dir = 'dataset/free'

we have this "try/except" statement because these next functions can throw an error if the directories exist already
try:
os.makedirs(free_dir)
os.makedirs(blocked_dir)
except FileExistsError:
print('Directories not created becasue they already exist')

UIの表示

button_layout = widgets.Layout(width='128px', height='64px')
free_button = widgets.Button(description='add free', button_style='success', layout=button_layout)
blocked_button = widgets.Button(description='add blocked', button_style='danger', layout=button_layout)
free_count = widgets.IntText(layout=button_layout, value=len(os.listdir(free_dir)))
blocked_count = widgets.IntText(layout=button_layout, value=len(os.listdir(blocked_dir)))

display(widgets.HBox([free_count, free_button]))
display(widgets.HBox([blocked_count, blocked_button]))

free_button -> save_freeにバインドしている
blocked_button-> save_blockedにバインドしている
from uuid import uuid1

def save_snapshot(directory):
image_path = os.path.join(directory, str(uuid1()) + '.jpg')
with open(image_path, 'wb') as f:
f.write(image.value)

def save_free():
global free_dir, free_count
save_snapshot(free_dir)
free_count.value = len(os.listdir(free_dir))

def save_blocked():
global blocked_dir, blocked_count
save_snapshot(blocked_dir)
blocked_count.value = len(os.listdir(blocked_dir))

free_button.on_click(lambda x: save_free())
blocked_button.on_click(lambda x: save_blocked())


display(image)
display(widgets.HBox([free_count, free_button]))
display(widgets.HBox([blocked_count, blocked_button]))

「学習」

つぎのように、黒線の手前(障害物をさける)にロボットを移動して、写真撮影をします。
つぎにすこしバックして前進できる写真をとります

合計100枚くらいあると良さそう。

train_dataset, test_dataset = torch.utils.data.random_split(dataset, [len(dataset) - 50, 50])

(撮影した画像を訓練データとテストデータに分割する際に、後半50個をテストデータとしている。)
Place the robot in a scenario where it's blocked and press add blocked
Place the robot in a scenario where it's free and press add free
Repeat 1, 2
'''


学習が終わったら「best_model.pth」ができます。
PCでやった方が早いですが、jetsonでもそこまでかからないので起動後にお風呂でも入りましょう。

「実行」
live_demo.ipynb を実行します。実行をすすめて次の画面が出ることを確認します。
f:id:o-maguro:20200211012025p:plain


camera.observe(update, names='value') # this attaches the 'update' function to the 'value' traitlet of our camera  まで実行して、しばらく待つとロボット(車体)が動きます。

赤字の部分が編集した行です。個体差あるので調整する必要ありそうです。

import torch.nn.functional as F
import time

robot.left_motor.beta = 0.012
robot.right_motor.beta = 0.0

def update(change):
global blocked_slider, robot
x = change['new']
x = preprocess(x)
y = model(x)

# we apply the `softmax` function to normalize the output vector so it sums to 1 (which makes it a probability distribution)
y = F.softmax(y, dim=1)

prob_blocked = float(y.flatten()[0])

blocked_slider.value = prob_blocked

if prob_blocked < 0.5:
robot.forward(0.10) else:
robot.left(0.1)
time.sleep(0.001)

update({'new': camera.value}) # we call the function once to intialize