FunnyGeek

Home > This page

かわいいロボットのラピロ[RAPIRO]を組み立てる。そして人工知能も持たせるので改造する。

ゴール設定(ラピロ[RAPIRO]を組み立てる)

ずーっと気になってたロボット「RAPIRO」、ラピロって読みます。このロボットの最大の特徴は、ラズベリーパイを内蔵して、ラピロを動作させることができることです。おもちゃにしては高いので、ラズパイを使いこなせるようになるまでは買わないって決めてたけど、箱型AIロボット「BB-2」を完成させることができたので、ついにオンラインショッピングでぽちっとしました。翌日には届いちゃう凄い時代です。早速、ロボットを組み立てますが、ついでにAIロボットとして完成させるためにカスタマイズ改造もしちゃいます。

ラピロのキメポーズ

ロボットの組み立て

この説明には、RAPIROの標準キットに無いカスタマイズ改造をしているのでご注意を。

モジュール単位の組み立て

ロボット胸部分にArduino互換の基盤をネジで取り付け、サーボモータには右足や左手など稼働部分のシールを貼るなど各モジュールを作っていきます。

部品を並べた図

サーボモーターの取り付け

腕や足などの関節部分にサーボモーターを取り付けます。RAPIROは部品点数が少なく、すごく単純化されているので、組み立ては少しコツがいるかも。

ロボット部品にサーボモーターを取り付けた図

下半身が完成した図

なんだかこわい図になってしまった。この後、サーボモーターのコネクタをRapiroのArduino基盤に接続する。配線が多いのでコンパクトにキレイに配線しないと胸の上側パーツがはまらないので根気よくやりましょう。

下半身完成の図

ラズパイ電子工作する(カスタマイズ)

Drスランプ・アラレちゃんが誕生する時を思い出しますね。ラピロ標準キットに無い、ラズパイとスピーカーを頭部分に内蔵します。スピーカーはアンプをハンダ付けしたり、コネクタを接続するなど電子工作しています。

Drスランプ・アラレちゃんが誕生するときの図

音声認識させるのでマイクを取り付ける(カスタマイズ)

電子工作実験の時に、台湾製の小型USBマイクだと声を認識できなかったので、もったいないけれど、マイク内蔵USBカメラをロボット本体のスカート内に取り付けした。このマイクとラズパイの相性はバッチリです。

マイクを取り付け

ラピロの頭の中(カスタマイズ)

人工知能(AI)ロボットに仕上げるための改造です。喋るための「スピーカー」は50mmでジャストフィットするよう設計されています。見るための「カメラ」は、Raspberry Pi3専用カメラモジュールを取り付け出来ます。聞くための「マイク」は体の中を通ってスカート内に設置しました。
ここで問題が発生。ラピロは元々、Raspberry Pi2を前後方向に実装できるよう設計されていたらしく、Raspberry Pi3になると変換アダプタを挟んで、図のように左右方向に設置するように変更になっており、USBコネクタを接続するスペースが凄く狭くなっています。USBカメラのケーブルコネクタをそのままでは接続できないため、180度折り返すことができる「USB変換コネクタ」を買ってきて、図のように頭に収めることが出来ました。

RAPIROの頭の中:ラズパイ、カメラ、スピーカー、マイク、温度計

ラピロの頭の中でスピーカーの音がこもってしまったので、ドリルを使って耳の穴を大きくしました。とてもキレイに音が聞こえるようになりました。

RAPIROの耳にスピーカーの穴を開ける

ラピロの改造レシピ

部品主な仕様
(ロボット本体)RAPIRO Arduino基盤を搭載、サーボモーター12個搭載
(頭脳)Raspberry Pi3 Model BCPUはクアッドコア1.2GHz(つまり4コア)、無線LAN搭載
(聞く)マイク内蔵USBカメラ Baffaro BSWHD06M
(話す)スピーカー サイズ50mm + 超小型BTLアンプ8Ω, 1.5V, ROHM製BU7150
(見る)カメラ基盤 Raspberry Pi Video Module Camera Board 775-7731
(感じる)温度計 DS18B20使用温度センサモジュール
(食べる:自宅)AC-DC電源 Input: 100V, Output: 12V, 5A
(食べる:外出時)充電式電池 eneloop pro 単三型 5本、

まとめ(RAPIROの組み立て)

ラピロの組み立てとラズパイ搭載などの改造を行いました。この後、Arduinoの初期設定を行うのですが、最終的にはプログラミングして、ダンスをさせるところまで出来ました。ラピロは標準キットでも動きますが、ラズパイを載せたり、カメラを取り付けたり、カスタマイズしてロボットの電子工作やプログラミングを勉強するのにとっても良いロボットです。値段も42,000円程度であり、けっして安くはないですが、他のロボットは高級すぎてとても手が出ないので予算面ではぎりぎりでしょうか。とか言って、改造費が追加で10,000円くらいかかってしまいましたけど。次は、ラピロの初期設定を行います

おまけ(実際の動画:RAPIROがダンスしてみた)

こちらは、ラピロが自分で音楽を流して踊ってみた動画です。

ラピロのダンスで使ったプログラム

自作したpythonプログラムと同じディレクトリにmp3ファイルがあります。Raspberry Pi3からラピロのArduino基盤へひたすらコマンドを送信しています。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import sys
import string
import traceback
import serial
import time
import subprocess

# RAPIROと通信するための初期設定
glbCom = serial.Serial('/dev/ttyAMA0', 57600, timeout = 10)  

if __name__ == '__main__':
    try:
            # mp3音楽を鳴らす(スピーカー出力、ボリューム1000)。
            cmd = "omxplayer -o local --vol -1000 song01miku.mp3"
            # mp3音楽を鳴らすが、後で音楽を途中停止できるようにsubprocessを使う。
            proc = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE)

            # ラピロへ動作コマンドを送信します。
            glbCom.write( "#M0" )
            time.sleep(1)
            glbCom.write( "#PS00A130T005" ) #頭左
            time.sleep(1)
            glbCom.write( "#PS00A090T005" ) #頭init
            time.sleep(0.5)
            glbCom.write( "#PS00A050T005" ) #頭右
            time.sleep(1)
            glbCom.write( "#PS00A090T005" ) #頭init
            time.sleep(1)
            glbCom.write( "#PS00A050S01A130T010" ) #胸左
            time.sleep(1)
            glbCom.write( "#PS00A130S01A050T010" ) #胸右
            time.sleep(1)
            glbCom.write( "#PS00A090S01A090T010" ) #胸init
            time.sleep(1)
            glbCom.write( "#PS02A040S05A130T005" ) #両手ちょい前
            time.sleep(0.5)
            glbCom.write( "#PS02A000S05A180T005" ) #両手init
            time.sleep(1)
            glbCom.write( "#PS02A040S05A130T005" ) #両手ちょい前
            time.sleep(0.5)
            glbCom.write( "#PS02A000S05A180T005" ) #両手init
            time.sleep(2)
            glbCom.write( "#PS00A040S02A090S03A040S09A110T010" ) #右見て、手を伸ばす
            time.sleep(2)
            glbCom.write( "#PS00A090S02A000S03A130S09A090T010" ) #init
            time.sleep(2)
            glbCom.write( "#PS00A140S05A090S06A140S11A110T010" ) #左見て、手を伸ばす
            time.sleep(2)
            glbCom.write( "#PS00A090S05A180S06A050S11A090T010" ) #init
            time.sleep(2)
            glbCom.write( "#PS08A100S10A080T003" ) #足開く
            time.sleep(0.3)
            glbCom.write( "#PS08A090S10A090T003" ) #足init
            time.sleep(0.3)
            glbCom.write( "#PS08A100S10A080T003" ) #足開く
            time.sleep(0.3)
            glbCom.write( "#PS08A090S10A090T003" ) #足init
            time.sleep(2)
            glbCom.write( "#PS00A050S01A130S02A090S05A130S09A070S11A090T001" ) #体左ひねり・ポ
            time.sleep(1)
            glbCom.write( "#PS02A040S05A090T003" ) #コ
            time.sleep(0.3)
            glbCom.write( "#PS02A090S05A130T003" ) #ポ
            time.sleep(0.3)
            glbCom.write( "#PS02A040S05A090T003" ) #コ
            time.sleep(0.3)
            glbCom.write( "#PS02A090S05A130T003" ) #ポ
            time.sleep(0.3)
            glbCom.write( "#M0" )
            time.sleep(1)
            glbCom.write( "#PS00A130S01A050S02A040S05A090S11A110T001" ) #体右ひねり・ポ
            time.sleep(1)
            glbCom.write( "#PS02A090S05A130T003" ) #コ
            time.sleep(0.3)
            glbCom.write( "#PS02A040S05A090T003" ) #ポ
            time.sleep(0.3)
            glbCom.write( "#PS02A090S05A130T003" ) #コ
            time.sleep(0.3)
            glbCom.write( "#PS02A040S05A090T003" ) #ポ
            time.sleep(0.3)
            glbCom.write( "#M0" )
            time.sleep(0.5)
            glbCom.write( "#PR000G000B000T003" ) #LED-黒
            time.sleep(0.5)
            glbCom.write( "#PR000G000B255T003" ) #LED-あお
            time.sleep(0.5)
            glbCom.write( "#PR000G000B000T003" ) #LED-黒
            time.sleep(0.5)
            glbCom.write( "#PR000G000B255T003" ) #LED-あお
            time.sleep(0.5)
            glbCom.write( "#PR000G000B000T003" ) #LED-黒
            time.sleep(0.5)
            glbCom.write( "#PR255G000B000T010" ) #LED-赤
            time.sleep(0.5)
            glbCom.write( "#PS00A130S01A050S02A130S05A130S08A070S10A050T003" ) #両足-左
            time.sleep(0.7)
            glbCom.write( "#PS00A090S01A090S02A090S05A090S08A090S10A090T003" ) #両足init
            time.sleep(0.7)
            glbCom.write( "#PS00A050S01A130S02A040S05A040S08A130S10A110T003" ) #両足-右
            time.sleep(0.7)
            glbCom.write( "#PS00A090S01A090S02A090S05A090S08A090S10A090T003" ) #両足init
            time.sleep(0.7)
            glbCom.write( "#PS02A090S04A070S05A090S07A110T003" ) #両手つかむ
            time.sleep(0.5)
            glbCom.write( "#PS02A090S04A110S05A090S07A070T003" ) #両手離す
            time.sleep(0.5)
            glbCom.write( "#PS02A090S04A070S05A090S07A110T003" ) #両手つかむ
            time.sleep(0.5)
            glbCom.write( "#PS02A090S04A110S05A090S07A070T003" ) #両手離す
            time.sleep(0.5)
            glbCom.write( "#PS02A180S03A040S05A000S06A140T010" ) #万歳
            time.sleep(0.7)
            glbCom.write( "#PS02A180S03A040S05A000S06A060T005" ) #左手上げて
            time.sleep(0.7)
            glbCom.write( "#PS02A180S03A120S05A000S06A140T005" ) #右手上げて
            time.sleep(0.7)
            glbCom.write( "#PS02A180S03A040S05A000S06A060T005" ) #左手上げて
            time.sleep(0.7)
            glbCom.write( "#PS02A180S03A120S05A000S06A140T005" ) #右手上げて
            time.sleep(0.7)
            glbCom.write( "#PS02A180S03A040S05A000S06A060T005" ) #左手上げて
            time.sleep(0.7)
            glbCom.write( "#PS02A180S03A120S05A000S06A140T005" ) #右手上げて
            time.sleep(0.7)
            glbCom.write( "#PS02A180S03A040S05A000S06A060T005" ) #左手上げて
            time.sleep(0.7)
            glbCom.write( "#PS02A180S03A120S05A000S06A140T005" ) #右手上げて
            time.sleep(0.7)
            glbCom.write( "#PS02A180S03A040S05A000S06A140T005" ) #万歳
            time.sleep(0.7)
            glbCom.write( "#PS00A160S01A020S02A090S03A040S05A130S06A100T005" ) #右パンチ
            time.sleep(1)
            glbCom.write( "#PS00A020S01A160S02A040S03A070S05A090S06A140T005" ) #左パンチ
            time.sleep(1)
            glbCom.write( "#PS00A160S01A020S02A090S03A040S05A130S06A100T005" ) #右パンチ
            time.sleep(1)
            glbCom.write( "#PS00A020S01A160S02A040S03A070S05A090S06A140T005" ) #左パンチ
            time.sleep(1)
            glbCom.write( "#PS00A160S01A020S02A090S03A040S05A130S06A100T005" ) #右パンチ
            time.sleep(1)
            glbCom.write( "#PS00A020S01A160S02A040S03A070S05A090S06A140T005" ) #左パンチ
            time.sleep(1)
            glbCom.write( "#PS00A160S01A020S02A090S03A040S05A130S06A100T005" ) #右パンチ
            time.sleep(1)
            glbCom.write( "#PS00A090S01A090S02A040S03A130S05A130S06A050T010" ) #左パンチ
            time.sleep(1)
            glbCom.write( "#PS02A180S03A040S05A000S06A140S09A030S11A140T010" ) #のびー
            time.sleep(3)
            glbCom.write( "#PS01A090S02A040S03A070S05A130S06A100S09A085S11A085T007" ) #戻る
            time.sleep(2)
            glbCom.write( "#PS00A130S01A050S02A130S05A090T005" ) #右1
            time.sleep(0.7)
            glbCom.write( "#PS00A130S01A050S02A040S05A040T005" ) #右2
            time.sleep(0.7)
            glbCom.write( "#PS00A130S01A050S02A130S05A090T005" ) #右1
            time.sleep(0.7)
            glbCom.write( "#PS00A130S01A050S02A040S05A040T005" ) #右2
            time.sleep(0.7)
            glbCom.write( "#PS00A130S01A050S02A130S05A090T005" ) #右1
            time.sleep(0.7)
            glbCom.write( "#PS00A130S01A050S02A040S05A040T005" ) #右2
            time.sleep(0.7)
            glbCom.write( "#PS00A090S01A090S02A040S03A070S05A130S06A100T005" ) #正面
            time.sleep(0.7)
            glbCom.write( "#PS00A050S01A130S02A130S03A070S05A130S06A100T005" ) #左1
            time.sleep(0.7)
            glbCom.write( "#PS00A050S01A130S02A040S03A070S05A040S06A100T005" ) #左2
            time.sleep(0.7)
            glbCom.write( "#PS00A050S01A130S02A130S03A070S05A130S06A100T005" ) #左1
            time.sleep(0.7)
            glbCom.write( "#PS00A050S01A130S02A040S03A070S05A040S06A100T005" ) #左2
            time.sleep(0.7)
            glbCom.write( "#PS00A050S01A130S02A130S03A070S05A130S06A100T005" ) #左1
            time.sleep(0.7)
            glbCom.write( "#PS00A050S01A130S02A040S03A070S05A040S06A100T005" ) #左2
            time.sleep(0.7)
            glbCom.write( "#PS00A090S01A090S02A040S03A070S05A130S06A100T005" ) #正面
            time.sleep(0.7)
            glbCom.write( "#PS00A050S01A050S02A090S03A070S06A100S10A050T005" ) #右1
            time.sleep(1)
            glbCom.write( "#PS00A050S01A050S02A000S03A070S05A130S06A100S10A050T003" ) #右2
            time.sleep(0.8)
            glbCom.write( "#PS00A050S01A050S02A090S03A070S05A040S06A100S10A050T003" ) #右3
            time.sleep(0.8)
            glbCom.write( "#PS00A050S01A050S02A180S03A070S05A090S06A100S10A050T003" ) #右4
            time.sleep(0.8)
            glbCom.write( "#PS00A050S01A050S02A000S03A070S05A130S06A100S10A050T003" ) #右2
            time.sleep(0.8)
            glbCom.write( "#PS00A050S01A050S02A090S03A070S05A040S06A100S10A050T003" ) #右3
            time.sleep(0.8)
            glbCom.write( "#PS00A050S01A050S02A180S03A070S05A090S06A100S10A050T003" ) #右4
            time.sleep(0.8)
            glbCom.write( "#PS00A090S01A090S02A040S05A130S08A090S10A090T005" ) #初期
            time.sleep(1)
            glbCom.write( "#PS00A130S01A130S02A090S03A070S05A040S06A100T003" ) #左1
            time.sleep(0.7)
            glbCom.write( "#PS00A130S01A130S02A130S03A040S05A130S06A050T003" ) #左2
            time.sleep(0.7)
            glbCom.write( "#PS00A130S01A130S02A040S03A130S05A040S06A100T003" ) #左3
            time.sleep(0.7)
            glbCom.write( "#PS00A130S01A130S02A090S03A070S05A040S06A100T003" ) #左1
            time.sleep(0.7)
            glbCom.write( "#PS00A130S01A130S02A130S03A040S05A130S06A050T003" ) #左2
            time.sleep(0.7)
            glbCom.write( "#PS00A130S01A130S02A040S03A130S05A040S06A100T003" ) #左3
            time.sleep(0.7)
            glbCom.write( "#PS00A090S01A090S02A040S05A130S08A090S10A090T005" ) #初期
            time.sleep(1)
            glbCom.write( "#M8" ) #さよなら
            time.sleep(8)

            proc.stdin.write("q") #音楽停止

    except:
        print ('--------------------------------------------')
        print ('[rapiro_dance.py]')
        print ('--------------------------------------------')
        print ( traceback.format_exc(sys.exc_info()[2]) )
        print ('--------------------------------------------')

    finally:
        time.sleep(2)
        glbCom.write( "#M0" )
        print("(^_^)> 完了!\n")
  

パソコンとRapiro間の通信トラブルシューティング

ラピロが正常に動かない時のチェックリストを作りました。
[ ]PC - Raprio間の通信(ファームウェアのインストール)
[ ]PC - Raprio間の通信(ラピロ動作する)
[ ]PC - Raprio間のUSBケーブル(USBケーブルはデータ通信用か[充電専用USBケーブルはNG])
[ ]シリアルコンソールのdisable(無効化)
[ ]PCとラズパイは、競合するのでPCと接続するケーブルは外す
[ ]ラズパイ - Rapiro間の通信速度が一致しているか(例:serial.Serial('/dev/ttyAMA0', 57600, timeout = 10))
[ ]ラズパイ - Rapiro間の通信(ただしエラーは出ない)
[ ]ラズパイ - Rapiro間の配線が正しい端子に繋がっているか
[ ]電源配線が正しい端子に繋がっているか

▲上に戻る