Raspberry Piで自動運転やってみる 1.車体の準備

この記事は全3回のうちの1つ目の記事です。つづきもご覧ください。
[1.車体の準備（本記事）](https://qiita.com/stnk20/items/f614ae1471b9e555708a)
[2.自動ブレーキ](https://qiita.com/stnk20/items/0def24cd4e2ebe78bbbf)
[3.障害物回避](https://qiita.com/stnk20/items/1c7771dde55ffec18896)

# 概要
Raspberry Pi Zero Wを手に入れたので、自動運転をやってみたいと思います。
自動運転といっても本格的なものは難しいので、画像処理ベースで障害物を避けて走る機能を実現することにします。

作りたいのはこんなモノです：

- 小さい（部屋の中で遊べる）
- 障害物を避けて走る（ライントレースよりは賢いことをしたい）
- 本体だけの計算リソースで動く
- 距離センサーは使わない
- 汎用品をつかって簡単につくる
- 前輪ステアリング（戦車みたいな方式ではなく）

今回の記事は準備編ということで、モノを作ってラジコンとして動かすところまでについて、制作のポイントを記しておきます。

# 完成したもの

![IMG_20180504_113439287.jpg](https://qiita-image-store.s3.amazonaws.com/0/191697/0fc691be-0a66-03d7-5e8a-eb95086ef000.jpeg)
前から

![IMG_20180504_113445118.jpg](https://qiita-image-store.s3.amazonaws.com/0/191697/04c870b9-ccda-7945-4a8f-558d11d1bbcf.jpeg)
後から

![IMG_20180504_113602574.jpg](https://qiita-image-store.s3.amazonaws.com/0/191697/5644776b-e9f9-a8ea-965d-c67ac0361135.jpeg)
横から

![IMG_20180504_113535715.jpg](https://qiita-image-store.s3.amazonaws.com/0/191697/dcd38b50-ce4a-7401-b22f-52963b4b8827.jpeg)
サーボ・ステアリング部


# 部品構成

| モノ | 備考 |
|:----|:-----|
| バギー工作基本セット | http://www.tamiya.com/japan/products/70112/index.html |
| ユニバーサルプレートセット | http://www.tamiya.com/japan/products/70098/index.html |
| ユニバーサルアームセット | http://www.tamiya.com/japan/products/70143/index.html |
| モバイルバッテリー | http://amzn.asia/iyV9B5Z |
| Raspberrypi Zero W |  |
| カメラモジュール | https://shop.pimoroni.com/products/raspberry-pi-zero-camera-module |
| レンズコンバーター | 100円ショップにあります |
| ユニバーサル基板 | http://akizukidenshi.com/catalog/g/gP-12188/ |
| ピンソケット | |
| サーボモーター SG-90 | http://akizukidenshi.com/catalog/g/gM-08761/ |
| モータードライバー TA-7291P | http://akizukidenshi.com/catalog/g/gI-02001/ |
| 9軸センサー MPU-9250モジュール | http://amzn.asia/cdr65M9 |
| 電子部品・配線等 |  |
| エポキシ接着剤 | 100円ショップにあります |
| その他ネジや木材等 |  |

#車体について
* 車体はタミヤのセットを使います。ユニバーサルプレートセットを使って2階建て構成にすることで、回路やカメラのマウントが簡単になります。シャーシ上にバッテリー、2階部分に回路とサーボモーターを配置。
* ユニバーサルアームセットに入っているスペーサーを柱にします。
* シャーシへのネジ取り付けは下穴を開けておかないと割れますので注意。
* このキットはサスペンション付きなので、動く空間を確保しつつユニバーサルプレートをカット。
* サーボ取付け部は現物合わせしながら加工します。
* ステアリングとサーボの接続部は、硬めの針金をL字にしてエポキシ接着剤で固めています。見えにくいですが上記写真も参照ください。
* 前輪のブッシュが緩みがちなので、接着剤でとめておきます。
* カメラモジュール自体の画角が結構狭く、旋回時の行く先が見えないいので、対策のために魚眼コンバーターレンズを使います。
* 視野を確保するためにカメラ自体も後ろのほうに配置したほうが良いですが、ケーブル長に余裕がないので、とりあえずサーボモーターの裏側にマウントしています。カメラ配置に関してはもっと工夫した方がいいです。

# 電気系について
* 電池はLiPoや乾電池だと電圧変換が面倒なので、モバイルバッテリーをつかいます。微妙に車体サイズにハマるものが見つからないですが、とりあえずリストにあるもので。左右にはみ出しますがケーブル一体型なのでそこそこスッキリまとまります。
* Raspiの上に乗せる回路は秋月のFRISK基板がちょうどいい感じです。
* DCモーターの駆動に必要なモータードライバは、実績の多そうなTA7291Pを選びました。vrefを決めるために数kΩの抵抗を入れます。
* モータードライバはvrefを変えるのではなく、inputをpwmにして動かします（発熱を抑えられるらしい）。
* モーターの端子間には電子系への影響を抑えるためにコンデンサーを取り付けます。
* 9軸センサーモジュールはI2Cポートにつなぎます。
* サーボモーターはハードウェアPWMができるポートにつなぎます。これも電源はRaspiと共有します。
* 電源をモーターとRaspiとで共有していますので、電源の安定化のためコンデンサーをつけておきます。

# ソフトウェアについて
* RaspbianOSを使います。
* Gstreamerバックエンドとpythonモジュールを使える状態でOpenCV3.3をインストールします。
* rpicamsrcをインストールします。
* raspi-configでカメラやGPIOを設定します。
* GPIOでモーターを制御する方法や、PWMでサーボを制御する方法については他にも記事があるので割愛します。

# ラジコンとして動かす
各種IOを叩けば、後輪モーターやステアリングが動きます。こんな感じでクラス化しています：

```python:car_controller.py
import wiringpi as wp

class CarController(object):

    FORWARD_PIN = 6
    BACKWARD_PIN = 5

    STEER_PIN = 18
    STEER_MIN = 65
    STEER_MAX = 89

    def __init__(self):
        # slottle
        wp.wiringPiSetupGpio()
        wp.pinMode(CarController.FORWARD_PIN,1)
        wp.softPwmCreate(CarController.FORWARD_PIN,0,100)
        wp.pinMode(CarController.BACKWARD_PIN,1)
        wp.softPwmCreate(CarController.BACKWARD_PIN,0,100)
        # steering
        wp.wiringPiSetupGpio()
        wp.pinMode(CarController.STEER_PIN,2) # Hardware PWM
        wp.pwmSetMode(0)
        wp.pwmSetRange(1024)
        wp.pwmSetClock(375)
    
    def slottle(self,x):
        """
        x: -1.0 to 1.0
        """
        x = int(max(-100,min(100,100*x)))
        if 0<=x:
            wp.softPwmWrite(CarController.FORWARD_PIN,abs(x))
            wp.softPwmWrite(CarController.BACKWARD_PIN,0)
        if x<0:
            wp.softPwmWrite(CarController.FORWARD_PIN,0)
            wp.softPwmWrite(CarController.BACKWARD_PIN,abs(x))

    def steer(self,x):
        """
        x: -1.0 to 1.0
        """
        a = 0.5 * (CarController.STEER_MAX - CarController.STEER_MIN)
        b = 0.5 * (CarController.STEER_MAX + CarController.STEER_MIN)
        x = int(max(CarController.STEER_MIN,min(CarController.STEER_MAX, a*x+b)))
        wp.pwmWrite(CarController.STEER_PIN,x)

    def brake(self):
        wp.softPwmWrite(CarController.FORWARD_PIN,100)
        wp.softPwmWrite(CarController.BACKWARD_PIN,100)
```

rpicamsrcを使うと、Gstreamer経由でOpenCVによる画像処理や別のPCへのストリーミングなどができます。

ここまでやれば、「一人称カメラつきラジコン」として動かすことができます。これだけでも結構面白いです。
Websocket通信でスマホから操作する、Bluetoothジョイスティックで操作するなど工夫するといいと思います。本題からはずれるのでここでは割愛しますが、コードが整理できれば公開するかもしれません。

# つづき

[自動ブレーキ編](https://qiita.com/stnk20/items/0def24cd4e2ebe78bbbf)に続きます。