Bakulog

獏の夢日記的な何か。

Kinectセンサーを使ってSoftbank Pepperを動かす

タイトルの通りです。

もくじ

  1.  概要
  2.  動画の紹介
  3.  手元で再現してみたい人へ
  4.  ソースコードに関する注意
  5.  質問とか

 

1. 概要

2014年に開発者向けに販売されて以来Softbank Pepperはソフトバンクから「自律したロボット」という特徴を前面に出して売られてますが、いっぽう開発者にとってはNAOqi Frameworkとセンサ/モーターが載ってるだけのLinuxという側面もあるので、例えばPepperを外部から手動操作するリモコン的なソフトを作れます。株式会社ネクストさんの「pepperくんをブラウザから動かすコントローラを作ろう」などはお手軽さがメリットとなる事例として参考になります(個人的にJSあまり書きたくないのでやりませんが…)。

 

しかし、普通のスマホゲームパッドといったユーザーインターフェースでは操作の自由度に限界があり、Pepperの全身に仕込まれた15個前後のモーターに角度指示を自在に出すのは実質ムリです。

そこで今回使ったのがXbox One Kinectセンサー

このセンサーですが以前のKinectより段違いに性能が高く、Windows向けのAPIも良く整備されてます。APIの機能はいろいろあるのですが、今回は特に「ヒトを検出して各関節の姿勢情報を取得する」、つまりいわゆるモーションセンサ機能を用います。この姿勢情報というのは原理的にはPepperに再現させたい姿勢をほぼそのまま表したデータなので、このデータを適当に整形してPCとPepperで通信が確立できれば、人の動きをPepperにマネさせられそうな予感がします。ということで、実際にやってみましょう。

 

2. 動画の紹介

動いてる様子のデモをニコニコ動画に上げてます。動画中でも触れてますが撮影はアトリエ秋葉原で行っています。

上の動画では編集で顔を隠してますが、実際はPepperがきちんと動いてるか心配なので基本Pepperをガン見してました。

 

 

3. 手元で再現してみたい人へ

ここから先は具体的なプログラムの実行手順の話です。Pepperの開発環境であるChoregrapheの使い方を知っており、手元にPepperがある前提で話を進めます。アトリエ秋葉原のワークショップで言うと2つ目のワークショップ程度の知識を想定しています。

 

 

3-1. SDKのインストール

では、まずKinectセンサーを買う前にPCを用意し、SDKをインストールします。PCは何でもいいわけではないことに注意して下さい!特に以下の3点をクリアしてるかはポイントになります。

  • Windows 8/8.1(現状だとWin10は対応してなさそう?)
  • USB3.0端子(たぶん必須)
  • DirectX 11対応環境

SDKのダウンロード方法や手元のPCでKinectが使えそうか確認する具体的な手順は「Kinect for Windows v2 購入前に確認すべきことと、その方法」に詳しく書かれてますので、コチラを参考にSDKのインストールを済ませてください。この記事にもありますが事前チェックをサボってるとセンサーを買うだけ損になる可能性もあります。

 

3-2. センサーとアダプターの入手

PC環境が確認できたら「Xbox One Kinect センサー」および「Xbox One Kinect センサー PC用アダプター」を買います。アダプターが必要な事に注意です。

上にはAmazon(ニコニコ市場越し)のリンクで貼ってますが個人的にはMicrosoft公式かヨドバシカメラでの購入をオススメします。

 

3-3. プログラムの入手

実行ファイルとかソースはGitHubに置いてるので拾ってって下さい。ソースはMITライセンスで公開しています。

本プログラム(Kinect for Pepper)は3つのプログラムで構成されています。これらは"programs"フォルダに入ってますが、その中で直接触るのは以下の3ファイルです。

  • "PC/KinectForPepper.exe"(C#プログラム)
  • "Server/kfp_server.py"(Pythonスクリプト)
  • "Pepper/KinectForPepper.pml"(Choregrapheプロジェクト)

もしPythonが入ってないのあればPython公式ページから2.7系の最新版をダウンロード、インストールしておいてください。たぶんPython3.4では動きません。

また実行するだけなら不要なハズですが、C#プログラムの作成にはVisual Studio 2015 Communityが用いられており"src"フォルダ以下がC#プロジェクトの中身です。

 

3-4. 実行前の準備: IPアドレスの確認と下準備

プログラム実行前にネットワーク環境を確認します。コマンドプロンプト(スタート画面で"cmd"と打って出てくるやつ)を起動し、"ipconfig"と打ち込んで自分のIPアドレスを確認します。

ipconfig_example

上の例だと"192.168.1.2"がIPアドレスになります。IPアドレスが確認できたら"programs/Server/kfp_server.py"を適当なテキストエディタで開き、下記の"host"変数として確認したIPアドレスを入れます。文字列として代入するのでシングルクオーテーションかダブルクオーテーションで囲って下さい。

# -*- coding: utf-8 -*-

import socket
import select

import joint_data_process

def main():
    #このhostの内容を必要に応じて変更
    host = '192.168.1.2' #上の画像の場合はこう
    port = 13000
    backlog = 10

    #...

 

またChoregrapheで"programs/Pepper/KinectForPepper.pml"を開き、root階層の"Realtime"および"Monomane"ボックスについて設定を開き(左下のスパナマークをクリック)、"serverIP"の部分にさっき確認したIPアドレスを書き込みます。

[caption id="attachment_4011" align="alignnone" width="300"]choregraphe_kfp 設定画面(※最新版ではボックス設定がちょっと変更されています)[/caption]

 

3-5. プログラムを順番に実行

やっと準備が整ったので実行してみましょう!

まずPythonプログラムを実行します。コマンドプロンプトを立ち上げて"kfp_server.py"のあるディレクトリまで移動し、下記のコマンドでスクリプトを実行します。

python kfp_server.py

見かけ上なにも起きてないように見えるかもしれませんが、サーバープログラムは起動できてるので問題ありません。コマンドプロンプト画面はそのまま閉じずに放置します。

 

次にPCへKinectセンサーを接続し、C#プログラムを動かします。"KinectForPepper.exe"をダブルクリックで実行し、出てきたウィンドウの下側で"IP Address"のテキストボックスに先ほど確認したIPアドレスを書き込みます。アドレスを書き込めたら「接続」ボタンを押します。Kinectの正面に人が立つと、黒いウィンドウの中にヒトの姿勢情報が映るようになります。

[caption id="attachment_4021" align="alignnone" width="300"]kfp_csharp KinectForPepper.exeの実行画面(※最新版ではちょっとGUIの見た目が変わってます)[/caption]

蛇足ですが、こちらのプログラムは描画部分に関してKinect for Windows SDK 2.0のサンプルである"BodyBasic-WPF"のソースを一部使っています。サンプルコードはSDKに付属でついてきてるので元コードの方も是非ご覧下さい。

 

この時点でPC上では2つのプログラムが実行中になっているかと思います。最後にChoregrapheでPepperと接続し、さきほど開いた"KinectForPepper.pml"のプログラムを実行します。

このプログラムはPepper App Challengeに出して落選したやつなのですが、指示に従ってタブレットをタッチしたり頭を触ったり音声認識をさせつつPepperが動く、というアプリになっています。詳細な挙動については実際に動かして確認してください。

注意としてヒトの姿勢によってはPepperがうまく姿勢を再現できなかったり手首があらぬ方向に曲がったりしますが、まあそのへんはご勘弁ください。完成度はそこまで保障してないので…

 

4. ソースコードに関する注意

注意点というか改善点を二つ。

 

4-1. たのしいさんすう

本記事の最初の方に「原理的にはKinectから得られる姿勢データってPepperに再現させたい姿勢とほぼ等価ですよ」的な事を書きましたが、これはあくまで「原理原則がそうだ」という話であって実際の計算は割と泥臭いことになってます。例えば手首のひねり角度計算はこんな感じ。

private static void SetWristYaws(RobotJointAngles robot, Body body)
{
    if (body.Joints[JointType.ElbowRight].TrackingState == TrackingState.Tracked &&
        body.Joints[JointType.WristRight].TrackingState == TrackingState.Tracked)
    {
        var rElbowZ = Quartanion.UnitZ.RotateBy(GetOrientation(body, JointType.ElbowRight));
        var rWristY = Quartanion.UnitY.RotateBy(GetOrientation(body, JointType.WristRight));
        var rWristX = Quartanion.UnitX.RotateBy(GetOrientation(body, JointType.WristRight));

        var rCos = rElbowZ.Product(rWristX);
        double rSign = Math.Sign(rElbowZ.Cross(rWristX).Product(rWristY));
        robot.RWristYaw = (float)(Math.Acos(rCos) * rSign);
    }
}

こうした「ヒトの姿勢情報をロボットの角度値に変換する」という計算は全てC#プログラムの中でも"BodyToJointAngles.cs"中で定義されています。

計算の詳細は追わなくて構いませんが、座標変換とか外積内積とか使った上で逆三角関数に通して角度を得るコードが現れます。ナゼこんなのが出てくるかというと、Kinectが姿勢表現に使っているクオータニオン(四元数)をPepperが使ってるオイラー角(ロール・ピッチ・ヨー)表現に直さなければいけないからです。このあたりは座標変換とかの基礎知識やPepperの角度方向定義を調べながらのけっこう面倒な作業になります。

 

これらの計算は「まあ動けばいいかな」程度に作ったので完成度がそこまで高くありません。自分でよりよい方法が思いついたら書き換えて使ってください。なおKinectクオータニオンを変換して捌く際にはこちらのQ&Aを見ておいた方がやりやすいかなーと思います。

 

4-2. サーバープログラムをサーバーPCへ

このプログラムをわざわざ「クライアント」「サーバー」「Pepper」の3段階構成に分割したのは、この構成でサーバーをグローバルな場所に置いてしまえば数百km離れたイベント会場とかにもモーションをモーションを送り込めますよ、という将来的なメリットを見越しての設計です。

ただし今回やった範囲ではサーバープログラムはローカルPCで実行してるのでそういったメリットは特にないです。もしお手元にドメインとってるサーバ計算機があればサーバ経由でPepper動かすのも面白いかもしれません。

 

5. 質問とか

質問やバグ報告についてはここのコメントに書くかnjslyr.trpg@gmail.comへのメール、あるいはTwitterへお願いします。

また時期によりますが2015年度中であればアトリエ秋葉原にそこそこ通ってるので、「アトリエ秋葉原で動かすとこ見たい!」というお話もあればぜひどうぞ。