Funny Snowman

FunnySnowman > Geek<ギーク>なコトをやってみよっと

ラピロを自由自在に操るためにpythonスクリプトで動かす。

ゴール設定(pythonスクリプトでラピロを操作する)

前回までに、ラピロに最初から設定されている10個の動作ができるようになった。今度は、pythonスクリプトで各関節のパラメータをデータ送信してラピロを自由自在に操ってみます。

ラピロ(Rapiro)を操作する

事前準備(Pythonスクリプトを書く)

最小のPythonスクリプト

これだけでも動作する最小のスクリプトを実行すると、ちょっとだけラピロが右を向きます。ラズパイのGPIOピン(TXD, RXD)経由で、ラピロのArduino基盤とシリアル通信をします。もしも、実行時に"serial.serialutil.SerialException: write failed:"のようなエラーが表示される場合は、このttyAMA0がOSのコンソールになっている場合があるらしいので、コンソールをOFFにする必要があります。あちこちのブログを読みながら、いろいろいじって上手く動くようになったのですがどの手順が正しかったのか分からないので記載していません。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# rapiro.py

import serial

glbCom = serial.Serial('/dev/ttyAMA0', 57600, timeout = 10)  # connect to RAPIRO

glbCom.write( "#PS00A050T005" ) #顔 やや右
    

ラピロの動作を拡張するPythonスクリプト

顔を左右に向く、腕と足の向きを変える、ラピロLEDの色を変更するなどをコマンドラインで実行できます。他のpythonモジュールからrapiro.pyをimportしてrapiro.face("left")なんて実行も可能です。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# rapiro.py

import os
import sys
import serial
import time
import random

# -------------------------------
# 定義
# -------------------------------
glbCom = serial.Serial('/dev/ttyAMA0', 57600, timeout = 10)  # connect to RAPIRO

# -------------------------------
# ラピロ頭を動かす。
# -------------------------------
def face( strCommand ):
    if ( strCommand == "RIGHT" ):
        glbCom.write( "#PS00A050T005" ) #顔 やや右
    elif ( strCommand == "LEFT" ):
        glbCom.write( "#PS00A130T005" ) #顔 やや左
    elif ( strCommand == "FRONT" ):
        glbCom.write( "#PS00A090T005" ) #顔 正面
    elif ( strCommand == "RANDOM" ):
        intRang = random.randint(40,140)
        strCmd = "#PS00A{0:03d}".format(intRang) + "T005"
        glbCom.write( strCmd )
    else:
        print( "該当しないので、ラピロ何もしません" )

# -------------------------------
# ラピロ腕を動かす。
# -------------------------------
def arm( strCommand ):
    if ( strCommand == "RIGHT" ):
        glbCom.write( "#PS00A130S01A050S02A090S03A070T006" ) #うで やや右
    elif ( strCommand == "LEFT" ):
        glbCom.write( "#PS00A050S01A130S05A090S06A100T006" ) #うで やや左
    elif ( strCommand == "FRONT" ):
        glbCom.write( "#PS00A090S01A090S02A090S03A090S05A090S06A090T006" ) #うで 正面
    else:
        print( "該当しないので、ラピロ何もしません" )

# -------------------------------
# ラピロ足を動かす。
# -------------------------------
def leg( strCommand ):
    if ( strCommand == "RIGHT" ):
        glbCom.write( "#PS08A110S10A100T010" ) #足 やや右
    elif ( strCommand == "LEFT" ):
        glbCom.write( "#PS08A080S10A070T010" ) #足 やや左
    elif ( strCommand == "FRONT" ):
        glbCom.write( "#PS08A090S10A090T010" ) #足 正面
    elif ( strCommand == "JUMP" ):
        glbCom.write( "#PS09A070S11A110S02A180S03A070S05A000S06A100T010" ) #のびー
    else:
        print( "該当しないので、ラピロ何もしません" )

# -------------------------------
# ラピロ初期位置
# -------------------------------
def reset():
    glbCom.write( "#M0" )

# -------------------------------
# ラピロのLED:色指定
# -------------------------------
def led( strCommand ):
    if ( strCommand == "RED" ):
        glbCom.write( "#PR255G000B000T002" ) #LED-赤
    elif ( strCommand == "GREEN" ):
        glbCom.write( "#PR000G255B000T002" ) #LED-緑
    elif ( strCommand == "BLUE" ):
        glbCom.write( "#PR000G000B255T002" ) #LED-青
    elif ( strCommand == "WHITE" ):
        glbCom.write( "#PR255G255B255T002" ) #LED-白
    elif ( strCommand == "PINK" ):
        glbCom.write( "#PR255G125B255T002" ) #LED-ピンク
    elif ( strCommand == "BLACK" ):
        glbCom.write( "#PR000G000B000T002" ) #LED-黒
    else:
        print( "該当しないので、ラピロ何もしません" )

# -------------------------------
# ラピロのLED:指定秒数だけランダムに点灯を繰り返し
# -------------------------------
def ledrandom(intLoop):

    while(intLoop>0):

        intRang = random.randint(0,255)
        strCmd = "#PR{0:03d}".format(intRang)

        intRang = random.randint(0,255)
        strCmd = strCmd + "G{0:03d}".format(intRang)

        intRang = random.randint(0,255)
        strCmd = strCmd + "B{0:03d}".format(intRang)

        strCmd = strCmd + "T010"
        glbCom.write( strCmd )
        intLoop = intLoop - 1
        time.sleep(1)

# -------------------------------
# ラピロのコマンドを直接実行
# -------------------------------
def direct( strCommand ):
    glbCom.write( strCommand )

# -------------------------------
# 危険:パルプンテ(責任持てませんので、実行する場合は自己責任で)
# -------------------------------
def parupunte( intLoop ):

    while(intLoop>0):
        strCommand = "#P"
        for intServo in range(0, 12):
            if( intServo == 0 or intServo == 1 or intServo == 2 or intServo ==5 ):
                intAngle =random.randint(20, 160)
            elif( intServo == 3 ):
                intAngle =random.randint(60, 110)
            elif( intServo == 4 or intServo == 7 ):
                intAngle =random.randint(80, 90)
            elif( intServo == 6 ):
                intAngle =random.randint(60, 120)
            elif( intServo == 8 or intServo == 9 or intServo == 10 or intServo == 11 ):
                intAngle =random.randint(70, 110)

            strCommand = strCommand + "S{0:02d}".format(intServo) + "A{0:03d}".format(intAngle)
        strCommand = strCommand + "T010"
        glbCom.write( strCommand )
        ledrandom(1)
        time.sleep(1)
        intLoop = intLoop - 1
    reset()

# ======================================
# コマンドラインモードで実行する場合
# ======================================
if __name__ == '__main__':

    if (len(sys.argv) <=1):
        print("Syntax: rapiro.py \"コマンド(ex. face direct )\" \"値(ex. right #M0)\" ")
        sys.exit()
    else:
        strTemp  = sys.argv[1].upper()
        strValue = sys.argv[2].upper()

        if ( strTemp == "FACE" ):
            face( strValue )

        elif ( strTemp == "ARM" ):
            arm( strValue )

        elif ( strTemp == "LEG" ):
            leg( strValue )

        elif ( strTemp == "LED" ):
            led( strValue )

        elif ( strTemp == "RESET" ):
            reset()

        elif ( strTemp == "DIRECT" ):
            direct(strValue)

        elif ( strTemp == "LEDRANDOM" ):
            ledrandom(int(strValue))

        elif ( strTemp == "PARUPUNTE" ):
            parupunte(int(strValue))

        else:
            print("該当コマンドが見つからないので、ラピロ何もしません")


#サーボ番号と稼働範囲
#
#00 : Head yaw        :  0 -  90 - 180
#01 : Waist yaw       :  0 -  90 - 180
#02 : R Sholder roll  :  0 -   0 - 180
#03 : R Sholder pitch : 40 - 130 - 130
#04 : R Hand grip     : 60 -  90 - 110
#05 : L Sholder roll  :  0 - 180 - 180
#06 : L Sholder pitch : 50 -  50 - 140
#07 : L Hand grip     : 60 -  90 - 110
#08 : R Foot yaw      : 70 -  90 - 130
#09 : Foot pitch      : 70 -  90 - 110
#10 : L Foot yaw      : 50 -  90 - 110
#11 : L Foot pitch    : 50 -  90 - 110

#シリアルコマンド	動作	目の色
#M0	停止	青
#M1	前進	青
#M2	後退	青
#M3	右に曲がる	青
#M4	左に曲がる	青
#M5	両手を振る	緑
#M6	右手を振る	黄
#M7	両手を握る	青
#M8	左手を振る	赤
#M9	右手を伸ばす	青

  

実験(ラピロをpythonスクリプトで動かす)

ラピロにpythonスクリプトで、「頭を左に」とか「腕を右に」とか指示を出すことができるようになりました。コマンドラインの実行コマンドはこんな感じ(↓)。足が変なポーズになるとサーボモータがブーンと音を立てて負荷がかかるようなので、時々「リセット:元の位置」にしてあげます。ダイレクトにラピロのコマンドも実行できるので、ポーズのコマンドをテストすることもできます。

$ python rapiro.py "face" "left"
$ python rapiro.py "arm" "right"
$ python rapiro.py "leg" "left"
$ python rapiro.py "led" "red"
$ python rapiro.py "reset" "0"              # 元の位置に戻ります(#M0と同じ)。
$ python rapiro.py "direct" "#M7"           # ラピロの標準動作パターンも実行できます。
$ python rapiro.py "direct" "#PS01A100T010" # ラピロのサーボ操作等をダイレクトに実行できます。
$ python rapiro.py "ledrandom" "10"         # 10秒間10回、ランダムに色を変えてLED点灯します。
  

何が起こるか分からない「パルプンテ」は責任持てないので、実行するときは自己責任でお願いします(ラピロが倒れないように支えるなど気を付けて)。

まとめ(pythonスクリプトでラピロを操作する)

Pythonスクリプトで、ラピロの動作コマンドを書いて、簡単に動作パターンを拡張できました。ラピロのチャットボットなど会話に合わせてジェスチャーできると面白そうです。

Pythonスクリプトで動作パターンを拡張したラピロ

▲上に戻る