Humanoid RTCs (Python)
研究やホビーで使用される小型ヒューマノイドロボット(以下、ヒューマノイド)を動作させるRTCを作成する方法を解説します。
このページでは以下の知識を説明なく使用しますので、各解説ページで使用方法を学んでから読み進めてください。
1. はじめに
今回は、以下のRTCを作成し、ヒューマノイドを動作させる方法を学びます。
ヒューマノイドには、HPIジャパン製のGR-001を用います。
作成するRTCは以下のようになります。
-
GR-001
GR-001を動作させます。
GR-001のローカル座標系に対して、位置・姿勢を指示して制御します。
-
TimedPose2DConsoleIn
GR-001の位置・姿勢をコンソールから指令します。
本解説で想定するシステムは、以下の様になります。
シリアルケーブルを通して、PCとGR-001のコントローラ(RPU-11)を接続します。
5. おわりに
小型ヒューマノイドを動作させるRTCを作成しました。
任意の位置に移動できるよう、逆運動学を解き、歩行パターンを生成しました。
このように、リアルタイムに歩行パターンを生成できれるようになればさまざまなシステムにヒューマノイドを組み込むことができます。
今回示した手法はGR-001以外にも応用可能です。
ぜひ、自分のロボット用に応用してRTCを作ってみてください。
参考文献
-
「RPU-10取扱説明書」<http://www.futaba.co.jp/robot/download/manuals>(2014/04/22アクセス)
2. GR-001 RTC
GR-001 RTCを作成します。
このRTCの構成や、アルゴリズムの細かい点についてはロボコンマガジン 2014年5月号をご覧ください。
GR-001 RTCはTimedPose2D型のデータを受け取れるよう作成します。
TimedPose2Dは二次元平面の位置(x, y)と姿勢(heading)を格納できるデータ型です。
指定された位置と姿勢に、以下のような手順で移動させます。
(a) 目標位置までの距離と角度を計算します。
(b) 目標方向に旋回します。
(c) 目標位置まで直進します。
(d) 目標姿勢に移動させます。
それではソースコードを解説します。
-
1行目
シリアル通信のためにPYSERIALモジュールをインポートします。
-
2行目
数値計算のためにmathモジュールをインクルードします。
-
21行目
シリアルオブジェクトをインスタンス化します。
-
23-26行目
逆運動学の計算に必要なボディーパラメータを格納する変数を定義します。
self.shin_length: すねリンクの長さ mmを格納します。
self.thigh_length: ももリンクの長さ mmを格納します。
self.foot_length: 脚リンクの長さ(すねリンクの長さ + ももリンクの長さ) mmを格納します。
self.ready_z: 一般的なヒューマノイドロボットは膝を伸ばしたまま歩くことは出来ないので、適度に膝を曲げる必要があります。
この値は足裏の高さ mmに相当し、両足を上げることで結果的に膝を曲げることができます。
-
31-41行目
シリアルポートをオープンする関数です。
シリアル通信に関してはSerial Servo RTCsで解説していますので、そちらをご覧ください。
-
41-43行目
シリアルポートをクローズする関数です。
シリアル通信に関してはSerial Servo RTCsで解説していますので、そちらをご覧ください。
-
73-107行目
ロボットの動作を行う関数です。
move_robot(各シリアルサーボのデータを格納した二次元リスト)
複数のRSサーボにロングパケットモードを用いてGR-001のコントローラRPU-11を通して送信します。
RSシリーズのロングパケットモードは以下の様なパケットを送信します。
[Header] [ID] [Flags] [Address] [Length] [Count] [VID] [Data] [VID] [Data] ・・・ [Sum]
Header: パケットの先頭を表します。ここでは0xFA、0xAFとなります。
ID: 常に0x00を指定します。
Flags: 常に0x00を指定します。
Address: メモリーマップ上のアドレスを表します。Lengthに指定した長さのデータをメモリーマップに書き込みます。
Length: サーボ1つ分のデータの長さ(byte数)を指定します。Length = VID + Dataのバイト数
Count: サーボの数を表します。
Sum: チェックサムです。IDからDataまでの各バイトの排他的論理和(XOR)を計算した値を設定します。
また、RPU-11を通してシリアルサーボに命令を送る場合は、以下のようにHeaderとLengthを頭に付けます。
[RPU header] [Length] [RSシリーズの通常パケット]
RPU header: RS485通信のためのパケットを表します。送信のみの場合は0x53Hを使用します。
Length: RSシリーズの通常のパケットの長さを指定します。
-
48行目
RPU-11用のパケットは後で追加します。
まずは通常のロングパケットモードのパケットを作り、リストに格納します。
-
49-54行目
各シリアルサーボのIDや位置、移動時間を順番にリストに追加します。
-
56-59行目
チェックサムを計算し、リストに追加します。
-
61行目
RPU-11用のパケットを格納したリストを作り、これまで作成したパケットが格納されたリストと結合します。
-
63行目
コマンドを出力します。
-
65-66行目
余弦定理を用いて、3つの辺の長さから内角の値を返します。
内角の大きさ calculation_law_cosines(l_1 mm, l_2 mm, l_3 mm)
各辺と求める角度の関係は以下の様になっています。
l_3で指定した辺の対角αの値が戻り値として返されます。
4. 動作確認
作成したRTCを実行して下さい。
GR-001 RTCのポート名は必ず変更し、各環境に合うよう設定してください。
その後、各RTCを接続し、Activateします。
Activate後にTimedPose2DConsoleIn RTCから姿勢と位置を入力します。
するとGR-001が移動するのが確認できます。
なお、GR-001 RTCの実行時に「Permission denied」と表示された場合はsudoを付けて実行してください。
もしくは、以下のコマンドを入力して、dialoutにユーザーを追加してください。
3. TimedPose2DConsoleIn RTC
TimedPose2DConsoleIn RTCを作成します。
テンプレートを以下に従って設定てください。
-
モジュール名
TimedPose2DConsoleIn
-
ベンダ名
あなたの名前
-
モジュールカテゴリ
Console
-
実行周期
1000
-
アクションコールバック
onInitialize
onExecute
-
データポート
・pose2dポート
ポート名(OutPort) pose2d
データ型 RTC::TimedPose2D
変数名 pose2d
表示位置 RIGHT
-
言語
Python
プロジェクトの設定が終わったら、TimedPose2DConsoleIn.pyに以下のコードを記述します。
以下のコードは抜粋となります。生成したテンプレートに当てはめて下さい。
コードの解説をします。
-
4-5行目
OpenRTM-aist Python版では、データ型の初期化が間違っていることがあります。
TimedPose2D型も初期化の引数が間違っていますので、修正してください。
-
11-14行目
TimedPose2D構造体のメンバを、順にユーザに入力させます。
-
16行目
タイムスタンプをセットします。
-
18行目
ポートから出力します。
以上で、TimedPose2DConsoleInのコーディングは終了です。

ここで説明するRTCは以下の様な構成で動作を確認しています。
-
ヒューマノイドロボット
HPIジャパン製 GR-001 RS301,302サーボ仕様
テンプレートを以下に従って設定てください。
-
モジュール名
GR001
-
ベンダ名
あなたの名前
-
モジュールカテゴリ
Humanoid
-
実行周期
1000
-
アクションコールバック
onInitialize
onActivated
onDeactivated
onAborting
onExecute
-
データポート
・pose2dポート
ポート名(InPort) pose2d
データ型 RTC::TimedPose2D
変数名 pose2d
表示位置 LEFT
-
コンフィギュレーション
・portコンフィギュレーション: デバイスのポート番号
名称 conf_port
データ型 string
デフォルト値 COM1
変数名 conf_port
・baudrateコンフィギュレーション: 通信のボーレート bps
名称 conf_baudrate
データ型 long
デフォルト値 115200
変数名 conf_baudrate
・walk durationコンフィギュレーション: 歩行時のシリアルサーボの移動時間 10ms
名称 conf_walk_duration
データ型 long
デフォルト値 50
変数名 conf_walk_duration
・step xコンフィギュレーション: 1ステップの移動量 mm
名称 conf_step_x
データ型 double
デフォルト値 40
変数名 conf_step_x
・step thetaコンフィギュレーション: 1ステップの旋回量 deg
名称 conf_step_theta
データ型 double
デフォルト値 30
変数名 conf_step_theta
・step zコンフィギュレーション: 歩行時の足上げ量 mm
名称 conf_step_z
データ型 double
デフォルト値 20
変数名 conf_step_z
・ready zコンフィギュレーション: 初期姿勢 mm(足の高さから算出)
名称 conf_ready_z
データ型 double
デフォルト値 5
変数名 conf_ready_z
・ready durationコンフィギュレーション: 初期姿勢移動時の移動時間 10ms
名称 conf_ready_duration
データ型 short
デフォルト値 200
変数名 conf_ready_duration
・shin lengthコンフィギュレーション: すねリンクの長さ mm
名称 conf_shin_length
データ型 double
デフォルト値 60
変数名 conf_shin_length
・thigh lengthコンフィギュレーション: ももリンクの長さ mm
名称 conf_thigh_length
データ型 double
デフォルト値 50
変数名 conf_thigh_length
・rollコンフィギュレーション: 歩行時の重心移動量 0.1deg
名称 conf_roll
データ型 short
デフォルト値 150
変数名 conf_roll
-
言語
Python
プロジェクトの設定が終わったら、GR001.pyに以下のコードを記述します。
以下のコードは抜粋となります。生成したテンプレートに当てはめて下さい。


-
68-87行目
足先の逆運動学を計算します。
足関節の角度 calculation_ik(足先の踏み出し量 mm, 足先の高さ mm)
各リンクや角度の表記は以下のようになっています。
右脚と左脚の動作にはmove_right_foot関数と、move_left_foot関数を使用します。
-
175-187行目
ロボットの歩行を制御する関数です。
指定された移動量とステップの幅から歩行回数を決定し、最後に初期姿勢をとるように帳尻をあわせます。
walk(移動量 mm, 1ステップの幅 mm, 足上げ量 mm, ロール軸の移動量 0.1deg, 移動時間 10ms)
-
177-178行目
歩行回数を移動量と1ステップの幅から求めます。
また、ステップ幅以下のあまり量を求めます。
-
180-181行目
求めた歩行回数分歩行させます。
-
183-184行目
あまり量がある場合は、あまり分だけ歩行させます。
-
186-187行目
初期姿勢に移動するよう、最後に帳尻をあわせます。
-
189-206行目
ロボットを右旋回させる関数です。
step_right_turn(1ステップの回転角 deg , 足上げ量 mm, ロール軸の移動量 0.1deg, 移動時間 10ms)
脚を上げている間に、遊脚している脚のヨー軸を回転させることで旋回します。
-
192行目
右脚を遊脚させます。
-
194-196行目
右脚ヨー軸を指定された1ステップの旋回角度分だけ移動させ、その間スリープさせます。
-
198行目
右脚を着地させます。
-
201行目
左脚を遊脚させます。
-
203-205行目
右脚ヨー軸を初期位置に移動させ、その間スリープします。
-
207行目
左脚を着地させます。
-
209-227行目
ロボットを左旋回させる関数です。
step_left_turn関数と左右が入れ替わっただけで、あとは同様の処理を行います。
-
229-254行目
ロボットの旋回を制御する関数です。
指定された旋回角度 degだけ、1ステップの回転角から旋回回数を決定し、最後に初期姿勢をとるように帳尻をあわせます。
-
231-232行目
旋回回数を旋回角度と1ステップの回転角から求めます。
また、ステップ幅以下のあまり量を求めます。
-
234-237行目
旋回時に腕と脚が干渉するため、左右の脇を開いて干渉を回避します。
脇を適当な角度開くよう、ロボットを動作させます。
-
239-243行目
旋回角が負の場合は右旋回を行い、0より大きい場合は左旋回を行います。
-
245-249行目
あまりがある場合は、あまり分だけ旋回させます。
-
251-254行目
開いた脇を元に戻します。
-
256-270行目
Activate時にシリアルポートのオープンや、コンフィギュレーションの読み込みを行います。
-
257行目
コンフィギュレーションに設定されたポートと、ボーレートでシリアルポートをオープンします。
-
259-262行目
脛リンク、腿リンクの長さと、初期位置をコンフィギュレーションから読み込みます。
また、コンフィギュレーションの値から脚リンクの長さを計算します。
-
264行目
ポートがオープンするまで十分な時間スリープします。
-
266行目
ロボットを初期姿勢に移動させます。
-
273行目
ポートをクローズします。
-
277-320行目
onExecute時には、pose2dポートから入力があった場合、指定の位置・姿勢に移動します。
-
279-284行目
pose2dの値を読み込み、読み込んだ値を変数に格納します。
-
288行目
目標位置(x,y)から、移動距離lを求めます。
-
290-302行目
旋回角thetaを求めます。
-
291-302行目
xが0ではないとき旋回角thetaをmath.atan2関数で求めます。
-
294-302行目
もしthetaが0でないとき、thetaだけ旋回させます。
thetaはラジアンですので、度数に変換してturn関数に与えます。
turn関数のその他の引数には、コンフィギュレーションで指定した値を渡します。
最後に、適度にスリープします。
-
304-312行目
もしlが0より大きい場合は、walk関数を使って歩行させます。
walk関数のその他の引数には、コンフィギュレーションで指定した値を渡します。
最後に、適度にスリープします。
-
314-320行目
もしheadingが0ではない場合は、先ほどと同様にturn関数を使って旋回させます。
-
324-325行目
エラー時にポートをクローズします。
以上で、GR-001のコーディングは終了です。
今回はコードが長く、大変でしょうが頑張って最後までコーディングしてみて下さい。
GR-001以外のヒューマノイドでも、同様の構造でRTC化できると思います。
ぜひ、お手元のヒューマノイドでお試し下さい。

-
69-78行目
脚のリンクの長さと、角度を計算します。
-
80-84行目
角度のphiの値を求めます。
zが0出ないとき、math.atan2関数を使ってphiの値を求めます。
-
86-90行目
th_1、th_2、th_3の値を求めます。
これらの値は各脚のシリアルサーボの位置(角度)となります。
求めた値を各角度を返します。
-
92-93行目
RSシリーズのサーボは0.1 deg単位で指示するので、角度を10倍して返します。
角度 0.1deg convert_rs(角度 deg)
-
95-96行目
度数を、ラジアンに変換して返します。
角度 rad to_degree(角度 deg)
-
98-118行目
ロボットを初期姿勢に移動させます。
set_ready_position(初期高さ mm, 移動時間 10ms)
初期高さ mmは初期姿勢を計算するための足先の高さです。
ここではready_zを指定することを想定しています。
-
99-100行目
各関節の角度の計算は腰の座標系で行うので、足先の座標系から腰の座標系に変換します。
-
102-104行目
初期姿勢時の各関節の角度を計算し、RS用に単位を変換したあとタプルに格納します。
-
106-115行目
複数のシリアルサーボのデータを二次元のリストに格納します。
-
117-118行目
シリアルサーボのデータをmove_robot関数に与えて、GR-001を動作させます。
その後、動作時間の間スリープさせます。
-
120-141行目
ロボットの右脚を動作させる関数です。
move_right_foot(足の踏み出し量 mm, 足のあげ量 mm, ロール軸の移動量 0.1deg, 移動時間 10ms)
足の踏み出し量と足のあげ量は、足先の目標位置(x, z)です。
ロール軸の移動量は、重心を移動するための股と足首関節の移動量です。
ロボットが脚を上げるには、反対の脚に重心を移動する必要があり、そのときのにロール軸を回転させて移動させます。
各ロール軸に体重移動量を指定する以外は、set_ready_position関数と同様の処理を行います。
-
143-164行目
ロボットの左脚を動作させる関数です。
move_right_foot関数と左右が入れ替わっただけで、あとは同様の処理を行います。
-
166-173行目
ロボットを歩行させる関数です。
step_forward(1ステップの幅 mm, 足あげ量 mm, ロール軸の移動量 0.1deg, 移動時間 10ms)
ステップは1回の移動量です。右脚と左脚はstep / 2ずつ移動します。
1ステップの幅と足のあげ量の関係は下図の用になります。
今回はstep / 4の位置で脚をあげることで、三角形の足先軌道を描きます。

動作の様子は、以下の動画をご覧ください。
$ sudo gpasswd –a <ユーザ名> dialout