前回、ハードウェアについて説明したので、今回からは、ソフトウェアの話になる。だが本題に入る前に、理解しやすいように、まずはシステムの概要について整理しておきたい。

システムを構成する主な要素

システムの構成をまとめた図が以下である。

システム構成図

ベースとなるロボットは市販キットの「KHR-3HV」(近藤科学)で、これには、図中のサーボモーター「KRS-2552」が17個と、制御ボード「RCB-4」が含まれている。RCB-4には、サーボモーター制御用の端子のほか、10個のアナログ入力端子(AD1~AD10)と10個のデジタル入出力端子(PIO1~PIO10)も用意され、センサーなどの利用が可能だ。

加速度センサーは旧モデルの「RAS-1」を使っているが、後継品の「RAS-2」でも構わない。PSDセンサーは、前方監視用をAD5とAD6に、落下防止用をAD10に付けた。なお、このほか歩行を安定させるジャイロセンサーがAD1とAD2に接続されているのだが、本稿には関係ないのでこの図では省略している。

KHR-3HVでは、専用ソフトウェア「HeartToHeart4」を使い、歩行や攻撃のモーションを作成することができる。モーションデータをRCB-4に書き込み、コントローラの各ボタンに割り当てておけば、押したボタンに応じたモーションが発動するという仕組みになっている。

今回の自律システムでも、各モーションをコントローラのボタンに割り当てるところまでは変わらない。違うのは、物理的なコントローラは使わず、PCから「ボタンを押した」コマンドを送信するということだ。PCが仮想的なコントローラのボタンを押してロボットを操作している、と考えると分かりやすいだろう。

KHR-3HV用のコントローラ。今回開発した自律システムでは、仮想的にこのボタンを押しているようなイメージになる

ROBO-ONE autoのルール上、無線制御にする必要があったため、Bluetoothモジュール「KBT-1」を購入してKHR-3HVに搭載したが、有線でも良ければKBT-1は不要だ。もし大会に出場するつもりがないのであれば、KHR-3HVに付属のUSBアダプタだけでも有線による制御は可能。しかし、ロボットは動き回るので、なるべく無線化した方がいいとは思う。

開発環境のセットアップ

では、次はPC側の開発環境について説明する。RCB-4に対し、シリアル通信でコマンドを送れさえすればプログラム言語は何でも構わないのだが、筆者は「Python」を使っている。Pythonはライブラリも豊富だし、何よりコンパイル不要なのでトライ&エラーが非常に楽だ(筆者にとっては、楽であることは何より重要)。

使用したPythonのバージョンは2.7である。Pythonには2.x系と3.x系があり、一部に互換性が無いというややこしい問題があるのだが、2.7を採用したのは、単に「今まで2.7を使ってきたから」というだけの理由だ。今から新規にインストールするのであれば3.x系でも良いと思うが、恐らくプログラムの修正が必要になるので注意して欲しい。

また、シリアル通信のために「pySerial」というパッケージも追加してある。ここでインストール方法までは説明しないので、各自で調べて対応して欲しい。なお、Pythonのプログラムを書くのはテキストエディタでも問題無いのだが、やはり統合環境の方が何かと楽なので、筆者は「PyScripter」というソフトウェアを利用している。

それでは実際に、PCからRCB-4を制御する方法を見てみよう。まず話を簡単にするために、シンプルなサンプルプログラム「com_test.py」を用意した。これは、KHR-3HVのバッテリ電圧を調べ、何ボルトなのか表示するものである。

PyScripter上でcom_test.pyを実行した結果。バッテリ電圧は11.2vと表示されている

サンプルプログラムの仕組み

かなり短いプログラムなので、順に1つ1つ説明していこう。

com_test.py

# coding: UTF-8
import serial

def s2i(data): #Short(2バイト)をIntに変換
    num = data[1]*256+data[0]
    if num >= 0x8000:
        num -= 0x10000
    return(num)

def main():
    #シリアル通信オープン
    com_num = 8 #COMポート番号
    try:
        ser = serial.Serial(com_num-1, 115200,parity=serial.PARITY_EVEN,timeout=1)
        print(u"シリアルポートをオープンしました")
    except:
        print(u"シリアルポートがオープンできません")
        exit()

    #コマンド送信
    com_line = [0x0A,0x00,0x20,0x00,0x00,0x00,0x22,0x00,0x02,0x4E] #AD0リード命令
    ser.write(com_line)

    #データ受信
    r_data = [ord(ser.read())]
    for i in range(r_data[0]-1):
        r_data.append(ord(ser.read()))

    #電圧計算
    vout = s2i(r_data[2:4])
    v_bat = vout*25.0/1024.0
    print(u"電圧:"+str(round(v_bat,1))+"v")

    #シリアル通信クローズ
    ser.close()
    print(u"シリアルポートを切断しました")

#メイン関数実行
main()

メイン関数main()の最初の処理はシリアル通信の初期化である。com_numにCOMポート番号が入るが、この番号はPC環境ごとに異なるので注意して欲しい。またRCB-4との通信速度は115200(bps)と指定しているが、これもRCB-4の設定によっては違う可能性があるので確認して欲しい。

その次の処理で、RCB-4にコマンドを送信している。com_lineへの代入で並んでいる16進数がコマンド列である。数字だけ見ても理解できないが、このコマンドを翻訳すると「AD0のデータをCOMポートに出力せよ」ということ。基板上に並んでいるAD1~AD10とは別に、AD0が内部で電源に接続されているため、この値を調べれば電源電圧が分かるわけだ。

送信するコマンド列は、近藤科学が以下URLで公開している「RCB-4コマンドリファレンス」「RCB-4プログラミングマニュアル」などのドキュメントを読めば作成方法を理解できるが、やや面倒。ここでは、手っ取り早くコマンドを用意できる便利な方法を紹介しよう。

近藤科学 RCB-4リファレンスセット Ver.2.2

このコマンド列は、フォーマットを読めばMOV命令であることが分かる。1バイト目がコマンド列のサイズで、2バイト目が命令の種類を表す(RCB-4コマンドリファレンスより)

それは、上記リファレンスセットに含まれている「RCB4CommandGenerator LE」(Rcb4CommandGeneratorLE.exe)というツールを使い、コマンド列を自動生成する方法だ。「センサー読み取り」タブを開き、「アナログポート」で「00」を選択して「コマンド生成」ボタンを押すと、下の欄に、com_lineで入力したのと同じ数列が表示されるはずだ。

RCB4CommandGeneratorを使うと、実行したい内容を選択するだけで、簡単にコマンド列を生成することができる

コマンドを送信したあとは、RCB-4からデータを受信している。受信データはすべてr_dataに入っているが、ここで欲しいAD0のデータは、3バイト目(下位バイト)と4バイト目(上位バイト)だけだ。データが上位バイトと下位バイトに分かれていると扱いにくいので、s2i関数で統合し(vout)、それを実際の電圧値に変換して表示している(v_bat)。

次回はセンサーを使ってみる

このサンプルプログラムがエラー無く動き、ちゃんと電圧値を返すことができていれば、とりあえず開発環境の準備はOKだと言える。これと同じ方法で、AD5に接続したPSDセンサーの値も読み込むことができるのだが、その方法については、また次回の説明ということにしたい。

PSDセンサーのテストプログラム。これについては、次回説明したい