nyabot’s diary

電気猫の夢を見るお話

3DCADサービス「TinkerCAD」を使って、ロボットの3Dモデルを作ってみる

f:id:sizohu:20190712155325p:plain
nyabot-cadimage

機体を作るために、設計図を描きたい。
主にアルミ板で作ることにしたので、各パーツを切り出すための図面が欲しい。
そのためにまずは、全体の造形や各部の構造について、イメージを明確にしておく必要があるのでは、と考えた。

3DCADでイメージを確定させる

ロボットを作るにあたって、こんな感じにしようかな、という漠然とした形状のイメージはあった。しかし、実際のサイズ感であったり、素材を切り出したりする際の大きさなどについては、脳内や紙の上では早々に限界を感じていた。

調べてみると、設計図を書くにあたっては、CADというソフトウェアを用いることが現代の主流らしい。 これなら今まで曖昧だったイメージを、破綻のない状態で確定できるのでは、と思いやってみることに。

正直、使いこなせるか・今後も使うか不明なものには、極力お金をかけたくない。
長期的に使うツールなら、当然それなりのコストを払うべきなのだろうけれど。

そこで今回は無料のCADを使って、次のような方法を取ることにした。

  • 3次元でモデルを作る
  • 3Dモデルをもとに、設計図を書く

有料のCADソフトだと、自動で平面図も出力できるらしい。すごい。でも使い方の説明とか見てもさっぱりわからなかった。私には早すぎたので断念。

TinkerCADが良さそう

色々調べたところ、無料で使うという点を重視すると「TinkerCAD」が良さそう。

www.tinkercad.com

特徴を挙げると以下のような感じ。

  • フリー
  • クラウドベース
  • 少機能、簡易的
  • 日本語対応
  • 運営母体が大きい

機能は限られるものの、簡単な操作で立体モデルを作ることができる。
私の作業環境はノートPCなので、クラウドベースでWebブラウザで動作するのも嬉しい。
さらに、運営母体がもともと高機能なCADソフトを開発、販売している会社らしい。寄らば大樹の影。将来的に高機能なソフトに乗り換えるかもしれないし、そうでなくても急にサービスがなくなったりするリスクが低い、はず。

実際に使ってみると、チュートリアルが充実しているおかげで大体の基本操作はすぐにわかるようになった。 ただ、ツールの使い方次第で出来ることやスピードには雲泥の差がありそう。もちろん自分は泥のほう。

サービス自体は日本語対応しているけれど、チュートリアルのテキストは英語だったので、Chromeのグーグル翻訳拡張(選択範囲を自動翻訳してくれるやつ)を使うと調子良い。

コンポーネントとして予めRaspberry Pi、ブレッドボード、サーボモータ等が用意されているので、電子工作に最適な感じ。

経緯とか

自作ロボットについて色々と調べてみると、どうやら一般的には初めに設計を行うらしい。設計図を書くべきなのだ、たぶん。 とはいえ、私のような電子工作の超初心者には、ロボットが最終的にどの程度の大きさになるかの予測すら難しい。 Raspberry Piサーボモータの大きさも、必要なその他の機械の寸法も、一切わからない状態からのスタートなわけで。加えて、どのようにモーターが動くか・動かせるか、とかも手探りしながら進めるしかない。さらに言えば、自分の興味やモチベーションがどこまで続くかもわからない。

と、いろいろな課題があったわけだけど、色々と学び動かすうちに、ようやく、これは完成まで行くだろうと自信が出てきた。
そんな経緯で、今更の設計に至る。

ロボットに使用する素材の選定

ロボットの機体を作るための素材選びについてのメモ。

選考基準は次のようなもの。

  • ある程度の耐久性がある
  • 素人でも加工できる(切ったり折ったり曲げたり穴を開けたりできる)
  • 安価に手に入る

使用素材1 アルミ板

プラ板やアルミ板が候補になったが、プラ板は折り曲げるのが難しく、曲面も作れるアルミ板に決定。
一口にアルミ板と言っても様々な種類や厚みがあるらしい。

通販(Amazon,ヨドバシ)で安価に手頃なサイズで入手可能な、光のアルミ板を試してみた。

光 アルミ0.3×100×300mm HA0313

光 アルミ0.3×100×300mm HA0313

光 アルミ板0.8×400×600mm 00782429-1 HA0846

光 アルミ板0.8×400×600mm 00782429-1 HA0846

0.3mmはハサミでも切れる一方、自重で大きくたわむくらいにペラペラで、今回の用途には適さない感じ。
0.8mmは強度的には十分に思える厚み。普通のハサミでは切れない。

アルミ板の切断方法

切断と穴開けは色々と試行錯誤した。

金切りばさみという金属を切る専用のハサミがあるらしい。が高い。
カッターで線を入れて、細かく繰り返し折り曲げるときれいに切ることができる。

また、ダイソーの万能ばさみなら金属板も切れる、という情報をWEBで見つけ、試したところちゃんと切れる。 カッターを使った方法の方がきれいにまっすぐ切れるので、パーツに応じて切断方法は使い分けることに。

アルミ板の穴あけ

アルミ板に穴を開けるのには電動のハンドドリルと金工用のドリル刃を使用。
穴を開けたい板の下にいらない木材を当てておくと良い。 また、目打ち等で穴を開けたい位置を凹ませておく(少し穴を開けておく)と、刃が滑らず狙った位置に穴が開く。

使用素材2 PP板

アルミ板は端子が接触する場所には使えないので、ラズパイを固定する土台には100均で売っていたPP板を使うことにした。厚さは2mm。 力を加えるとしなるものの、かなり強度があり、アルミ板と同様の方法でなんとか切断できる。

ラズベリーパイとPCA9685で複数のサーボモータを動かす

前回まではソフト面をいじっていたけれど、今回からハードを作っていく。

電子工作の基礎知識の習得

ラズパイは色々できるらしいものの具体的なことはさっぱりわかっていなかったので、まずは基礎知識を習得する。

「カラー図解 最新 Raspberry Piで学ぶ電子工作」という本を買った。

ラズパイを用いた電子工作について、本当に基礎から細かく丁寧に書かれていて、わかりやすい良書でした。
特に、電流や抵抗の話から説明してくれるのはとてもありがたかった。「そういえば小中学校でやったような…」という程度の知識しかなかった、つまり知識が全くなかった私も、すんなり理解することができた。
ラズパイや電子工作の書籍って入門書ちっくなものでも2、3000円するものが多いので、この価格でこの内容はすごくお買い得な感じ。

書籍の演習で用いるパーツセットが秋月電子通商で購入できるので、それを合わせて購入して学ぶと吉。
書籍をざっと読んでから、必要なパーツだけバラで買ってもいい。

Lチカができたところで多少の感動を覚えたりする。
モーターを動かすところあたりまで進めると、なんとなくラズパイを用いた電子工作のやり方がわかってくる。

複数のサーボモータを動かす(前準備)

書籍にも書かれているが、ラズパイはそのままではサーボモータを2台までしか動かすことができないらしい。
今回はドライバを用いて、16台のサーボモータを動かすことに挑戦する。

多脚歩行するロボットを目指す

これから作ろうとしているのは、ロボットのボディ。ラズパイやバッテリーをのせる土台と、それを支えて動かすための足。
電子工作初心者向けの指南でありがちなのは四輪とかキャタピラとかで、でもそれじゃロマンがない。
二足や四足は姿勢の制御が大変らしい。また、それぞれの足にかかる負担も大きいので、しっかりした構造やサーボが必要な模様。
当初から予定していた6足なら、3本ずつ足を前に出すことで安定して歩行できる。という理由もあり、6(+2n)足で歩行するロボットを作ることに決定。

色々調べる中で、日本では他国と比べて多脚ロボットの人気が低いらしい、という話を読んだ。真偽はわからないものの、確かにロボットといえば二足歩行のイメージが強い。漫画やアニメの影響が強いのかもしれない。多脚好きとしては少し悲しい。

PCA9685とサーボモータを購入

「ラズパイ サーボ 複数」でググるとこれを使うといいらしいことがわかる。
とりあえずAmazonで購入する。高いものもあるけど、精度を求めないなら安いやつでいいらしい。懐に優しい。

サーボモータも必要数購入する。メジャーな製品だと、TowerProのSG90というものがよく使われるらしい。秋月電子通商で1個400円。

同じ大きさで、別のメーカーが出しているものもあったりする。壊れやすいらしいがよくわからない。安いものだと、10個セットで2,000円強くらいでAmazonで売っている。

今回は12個(6足×2自由度)、または16個(8足×2自由度)、将来的には24個(8足×3自由度)+αくらい使いたいなと思っていたので、安価なもので試してみることに。
サーボモータには色々種類があり、1,000円〜2,000円以上のものもいくつもあるみたいなので、お金に余裕があればそういうのを買うといいと思う。買いたい。

一つのPCA9685で操作できるサーボモータは最大16個。6足でも3自由度にしてしまうと足りないので、今回は6足2自由度の足に12個、加えて2自由度の足兼アームを二つで4個使用することにし、合わせて16個のサーボモータを用意する。

安価なサーボモータは消耗品、というのをネットで読んだので、10個セットを2つ購入して、4個は予備にした。
また、サーボモータの動力には乾電池(単三4本)を用いる。前述の書籍連動キットには電池ボックスが含まれるので、それを使う。

複数のサーボモータを動かす(配線)

電池ボックス、PCA9685、ラズパイをそれぞれ接続する。

ラズパイ PCA9685
3.3V(1番ピン) VCC
GND(6番ピン) GND
SDA(3番ピン) SDA
SCL(5番ピン) SCL

PCA9685と電池ボックスの接続方法はこちらがわかりやすい。

https://snapguide.com/guides/bezeri-pi-tosabodoraibanojie-sok/

ネジを緩めて、コードを差し込んで、閉める。右(V+)が赤、左(GND)が黒。
ネジを開け閉めする際、一般的な家庭にあるような太めのドライバーだと入らないことがあるので、精密ドライバーがあると良い。

続いて、PCA9685にサーボモータを接続する。
サーボモータのオレンジが黄、赤が赤、茶色が黒になる向きでつなぐ。

複数のサーボモータを動かす(プログラム)

ラズパイの設定

Raspberry PiのI2Cを有効にする。以下の記事が詳しい。

qiita.com

$ sudo raspi-config

「Interfacing Options」 → 「I2C」 → 「はい」を選択。

上記記事にあったので、通信速度の設定追記もしておく。
初期値は100000では通信速度が早すぎてエラーが生じるとのこと。

$ sudo nano /boot/config.txt

最終行に以下の記述を追加。

dtparam=i2c_baudrate=10000

ラズパイの更新、I2Cのチャンネルチェック

$sudo apt-get update
$sudo apt-get upgrade
$sudo apt-get dist-upgrade
$sudo apt-get install python-dev and python3-dev
$sudo apt-get -y install python-smbus i2c-tools

$sudo i2cdetect -y 1

最後のコマンドで、PCA9685が接続されているチャンネルが表示される。
0x40と0x70の二つで、後ほどプログラムを書く際にこれを用いる。

Adfruitのライブラリをインストール

$ cd ~

$ git clone https://github.com/adafruit/Adafruit_Python_PCA9685.git
$ git clone https://github.com/adafruit/Adafruit_Python_GPIO.git
$ git clone https://github.com/adafruit/Adafruit_Python_PureIO.git

$ cd Adafruit_Python_PCA9685
$ sudo python setup.py install
$ sudo python3 setup.py install

$ cd ../Adafruit_Python_GPIO
$ sudo python setup.py install
$ sudo python3 setup.py install

$ cd ../Adafruit_Python_PureIO
$ sudo python setup.py install
$ sudo python3 setup.py install

python3は違いがまだよくわかっていないが、とりあえず入れとこうというよくない考えによるインストール。

動作させるプログラム

以下で公開されているコードを拝借。色々ご説明がありとても助かる。動かすサーボの数など、必要に応じて書き換える。

Raspberry Pi講座 PWMコントローラ ( PCA9685 ) - Hobby robot laboratory

PCA9685で複数サーボモーターをコントロール - Qiita

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import Adafruit_PCA9685
import time

class servo_Class:
    #ChannelはPCA9685のサーボモータの接続チャンネル
    #ZeroOffsetはサーボモータの基準位置調節用パラメータ
    def __init__(self, Channel, ZeroOffset):
        self.Channel = Channel
        self.ZeroOffset = ZeroOffset

        #Adafruit_PCA9685の初期化
        self.pwm = Adafruit_PCA9685.PCA9685(address=0x40)
        self.pwm.set_pwm_freq(60)

    # 角度設定
    def SetPos(self,pos):
        #PCA9685はパルスで角度を制御しており、パルス150~650が角度0~180に対応
        pulse = (650-150)/180*pos+150+self.ZeroOffset
        self.pwm.set_pwm(self.Channel, 0, pulse)

    # 終了処理
    def Cleanup(self):
        #サーボを90°にセット
        self.SetPos(90)

if __name__ == '__main__':
    Servo0 = servo_Class(Channel=0, ZeroOffset=0)
    Servo1 = servo_Class(Channel=1, ZeroOffset=0)
    Servo2 = servo_Class(Channel=2, ZeroOffset=0)
    Servo3 = servo_Class(Channel=3, ZeroOffset=0)

    try:
        while True:
            print '30'
            Servo0.SetPos(30)
            Servo1.SetPos(30)
            Servo2.SetPos(30)
            Servo3.SetPos(30)
            time.sleep(2)

            print '150'
            Servo0.SetPos(150)
            time.sleep(0.1)
            Servo1.SetPos(150)
            time.sleep(0.1)
            Servo2.SetPos(150)
            time.sleep(0.1)
            Servo3.SetPos(150)
            time.sleep(2)

    except KeyboardInterrupt:
        print("\nCtl+C")
    except Exception as e:
        print(str(e))
    finally:
        Servo0.Cleanup()
        Servo1.Cleanup()
        Servo2.Cleanup()
        Servo3.Cleanup()
        print("\nexit program")

こんな感じでテストしてみた。動いた。楽しい。
実際には上記のコードに少し書き加えて、PCA9685一つで動かせる最大数の16個のサーボモータを動かしてみた。動いた。とても楽しい。

つづく。

任意のホットワードでGoogleAssistantを起動させる

前回、前々回でRaspberry PiGoogle AssistantとSnowboyを入れた。

nyabot.hatenablog.com

nyabot.hatenablog.com

今回は、Snowboyを用いて自分の作成したホットワードでGoogleAssistantを起動させる。
方法については、以下の記事を参考にさせていただきました。めっちゃ感謝。

https://blog.mi.hdm-stuttgart.de/index.php/2017/08/18/2576/

SnowboyからGoogleAssistantのpushtotalkを呼び出す

/snowboy/examples/Python3/ ディレクトリにあるdemo.pyを複製して、ohayo.pyを作成。
記述を以下のように一部変更。

import snowboydecoder
import sys
import signal
from googlesamples.assistant.grpc.pushtotalk import main
interrupted = False

def signal_handler(signal, frame):
    global interrupted
    interrupted = True

def interrupt_callback():
    global interrupted
    return interrupted

model = "resources/models/ohayo.pmdl"

# capture SIGINT signal, e.g., Ctrl+C
signal.signal(signal.SIGINT, signal_handler)

detector = snowboydecoder.HotwordDetector(model, sensitivity=0.5)
print('Listening... Press Ctrl+C to exit')

# main loop
detector.start(detected_callback=main,
               interrupt_check=interrupt_callback,
               sleep_time=0.03)

detector.terminate()

model = "resources/models/ohayo.pmdl"の部分は自分の作成したpmdlファイルに合わせて適宜書き換えてください。
僕の場合は「おはよう」を登録した「ohayo.pmdl」を作成しました(過去記事参照)。

GoogleAssistantのpushtotalk.pyを書き換える

次に、以下のディレクトリにあるpushtotalk.pyを書き換える。
/home/pi/env/nyabot/lib/python3.5/site-packages/googlesamples/assistant/grpc
ディレクトリ名「nyabot」は仮想環境名によって変わるので注意。適宜変更されたし。)

  • リピートしないようにする
  • キー入力を待たず、すぐに待受状態にする

書き換え箇所は、ファイルの最後の方にある以下の部分。

wait_for_user_trigger = not once
while True:
    if wait_for_user_trigger:
        click.pause(info='Press Enter to send a new request...')
    continue_conversation = assistant.converse()

上記の部分を以下の内容に書き換え。

wait_for_user_trigger = once
while True:
    if wait_for_user_trigger:
        return
    continue_conversation = assistant.converse()

pulseaudioをインストールする

これだけだと、環境によってはエラーが発生する模様。した。
pulseaudioをインストールすると解決するらしい。

sounddevice.PortAudioError: Error opening RawStream: Device unavailable [PaErrorCode -9985] in the grpc sample · Issue #219 · googlesamples/assistant-sdk-python · GitHub

pulseaudioは古いラズパイにはデフォルトで入っていたみたい?だけど、僕のにはなかったのでインストール。

$ sudo apt update
$ sudo apt install pulseaudio

任意のホットワードでGoogleAssistantが起動する!

これで、自分の作成したホットワードでGoogleAssistantが起動するようになった。

$ source env/nyabot/bin/activate
(nyabot)$ python snowboy/examples/Python3/ohayo.py

「おはよう(←ホットワード)、明日の東京の天気は?」
「明日の東京の天気は晴れです。」

あとはホットワードを変えれば、彼または彼女は、HAL9000にもドラえもんにもなってくれる。
きっとこんな感じ。

「HAL(←ホットワード)、君の名前は?」
「私はGoogleアシスタントです。」

なるほど。課題は多い。今回はここまで。
つづく。

追記

君の本当の名前を知りたかったよ……。

nyabot.hatenablog.com

音声認識のSnowboyをラズパイに入れる

前回はGoogle Assistantを入れた。

nyabot.hatenablog.com

引き続き以下のブログを参考にさせていただき、今回はSnowboyを導入するメモ。

【ラズパイ】Voice KitにSnowboyを入れてホットワードでSwithBotを操る【よしこちゃん】 - Oh My Enter!

実際にやってみたところ、2019年2月現在、発生するエラーや対処法も上記の記事で書かれている通りだった。ありがたみ極まる。
リンクが有効な限り、上記のブログを直接参考にされたし。

依存関係の解決

(nyabot)$ sudo apt-get install swig3.0 python-pyaudio python3-pyaudio sox  
(nyabot)$ pip install pyaudio  
(nyabot)$ sudo apt-get install libatlas-base-dev

ソース類一式をダウンロード

(nyabot)$ git clone https://github.com/Kitt-AI/snowboy.git

ホットワード検出ライブラリをビルド

(nyabot)$ cd snowboy  
(nyabot)~/snowboy $ cd swig/Python3  
(nyabot)~/snowboy/swig/Python3 $ make

失敗するので、Makefileをnanoエディタで開き、

(nyabot)~/snowboy/swig/Python3 $ nano Makefile

下記の部分を書き換える。

# SWIG := swig // コメントアウトする
SWIG := swig3.0 // この行を追加する

再びmake。

(nyabot)~/snowboy/swig/Python3 $ make

ファイル_snowboydetect.soが生成されていることを確認

(nyabot)~/snowboy/swig/Python3 $ ls
(nyabot)$ cd ~/snowboy/examples/Python3/  
(nyabot)~/snowboy/examples/Python3 $ python demo.py resources/models/snowboy.umdl

先ほどと同様に、上記でもエラーが発生するので、snowboydecoder.py を一部(一時的に)書き換える。

(nyabot)~/snowboy/examples/Python3 $ nano snowboydecoder.py
# from . import snowboydetect // コメントアウトする  
import snowboydetect // この行を追加する

再び以下のコマンドを実行。

(nyabot)~/snowboy/examples/Python3 $ python demo.py resources/models/snowboy.umdl

待ち受けに入るので、「snowboy」と呼びかけてピコーンと鳴ればOK.

音声認識をテスト

テストファイルとして「おはよう」を登録したohayo.pmdlをSnowboyで作成。
mvとかscpとかでファイルを/home/pi/snowboy/resources/modelsに移す。

(nyabot)~/snowboy/examples/Python3 $ python demo.py resources/models/ohayo.pmdl

「おはよう」「ピコーン!」OK.

つづく。