mc_rtc::Configuration
設定このチュートリアルでは、mc_rtc用の新しいコントローラを作成する方法について説明します。今回の例では、JVRC1ロボットの首を左右に振るという簡単な動作にトライします。
注: mc_rtcのコントローラーは、すべてMCController
クラスから派生しています。シンプルなコントローラーを記述する場合も、このクラスから派生させて必要な機能を記述してください。このチュートリアルでもその方法を使用します。ただし、より複雑なコントローラーを作成する場合は、有限オートマトン機能を使用することを推奨します。
mc_rtcで用意されているmc_rtc_new_controller
を使用して新しいコントローラープロジェクトをセットアップします。
注: このツールを使用するには、Debian系のシステムで用意されているGit for PythonとpipのGitPythonが必要です。
このチュートリアルでは、以下のコマンドを実行し、MyFirstController
という名前のチュートリアル用コントローラーを作成します。
新たに作成されたmy_first_controller
フォルダーに移動します。このフォルダーには以下のファイルが自動生成されています。
コントローラーをビルドするには、CMakeといつものツールを使用してCMakeを実行し、コードをビルドしてインストールします。LinuxまたはMacOSの場合、一般に以下のように実行します。
注: sudo
は、mc_rtcが特権ディレクトリにインストールされている場合のみ実行する必要があります。
JVRC1ロボットと新たにインストールされたコントローラーを使用できるように、mc_rtcの設定ファイルを編集します。
さらに、前のセクションの説明に従ってコントローラーを実行します。お疲れ様でした。これで、最初のコントローラーのビルドと実行ができました。
まず、新しいPythonパッケージを作成します。
注: ここではposixシェルを使用していることを前提とします。
次に、my_first_controller.py
フォルダーにmy_first_controller
というファイルを作成します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import mc_control
import mc_rbdyn
import mc_rtc
class MyFirstController(mc_control.MCPythonController):
def __init__(self, rm, dt):
self.qpsolver.addConstraintSet(self.kinematicsConstraint)
self.qpsolver.addConstraintSet(self.contactConstraint)
self.qpsolver.addTask(self.postureTask)
def run_callback(self):
return True
def reset_callback(self, data):
pass
@staticmethod
def create(robot, dt):
env = mc_rbdyn.get_robot_module("env", mc_rtc.MC_ENV_DESCRIPTION_PATH, "ground")
return MyFirstController([robot,env], dt)
また、モジュール内でコントローラーを使用できるように、__init__.py
を編集します。
JVRC1ロボットと新しいコントローラーを使用できるように、mc_rtcの設定ファイルを編集します。
Python 2とPython 3のどちらかを強制的に使用したい場合や、この両方がインストールされている場合は、Python2
Python3を明示的に指定する必要があります。
これを行うには、my_first_controller
フォルダーがPythonのパス上に存在している必要があります。実際、この設定を使用すると、mc_rtcによってコントローラーが以下のように作成されます。
通常、my_first_controller
フォルダーが$HOME/my_python_controllers
にある場合、mc_rtc_ticker
を以下のように実行します。
C++のコントローラーでは、必要に応じてmc_control::MCController::run()
関数とmc_control::MCController::reset()
関数の呼び出しをバイパスできます。一方、Pythonのコントローラーでは、C++と同様の処理が実行された後に、run_callback(self)
とreset_callback(self, data)
が常に呼び出されます。
Use the mc-rtc/new-controller template project. This is equivalent to using the mc_rtc_new_controller
tool with extra goodies.
まず、コンストラクターを見てみましょう。
これらは非常に似ています。ここでは、基底クラスの既存のオブジェクトを使用して、基本的なコントローラーをセットアップします。
次に、reset
関数を見てみましょう。この関数は、コントローラーの起動時(インターフェイスによって起動されたときや、コントローラーがオンラインになったとき)に呼び出されます。
ここでは、単純にMCController
クラスにデリゲートします(Pythonの場合は暗黙的にデリゲートされます)。 reset_data
reset_dataには、インターフェイスによって与えられたロボットの初期状態が格納されています。デフォルトの実装では、ロボットが正しく初期化されたかどうかが確認され、姿勢制御タスクの目標として現在のロボットの姿勢が正しく設定されたかどうかが確認されます。
次に、run
関数が定義されています。この関数は、コントローラーのループ処理が実行されるたびに呼び出されます。
ここでも、MCController
クラスにデリゲートしています(先ほどと同じく、Pythonの場合は暗黙的にデリゲートされます)。この関数は、すべての処理が正しく実行された場合はtrueを返し、制御が中断された場合はfalseを返します。デフォルトの実装では、ユーザーのプログラムによって指定されたタスクと制約条件と共に二次計画法ソルバーが実行され、処理の結果得られた加速度を使用してロボットの目標状態が更新されます。
そして、コードの最後でコントローラーがmc_rtcに読み込まれます。
この部分を修正する必要はおそらくありませんが、コメントに記載された点に注意してください。
まず、2つのプロパティをコントローラーに追加します。一つは、動かそうとしている首関節のインデックスを保持するプロパティ、もう一つは、首をどの方向に動かそうとしているかを示すプロパティです。
関節のインデックスを初期化するには、ロボットのクラスを調べる必要があります。JVRC1では、首のヨー方向の関節名はNECK_Y
となっています。そこで、コントローラーのコンストラクターで以下のコードを実行します。
次に、ロボットの顔を左と右のどちらに向かせるかに応じて目標を更新する関数を記述します。
注: postureTask->posture()
で現在の目標を取得し、postureTask->posture(new_posture)
でその目標を変更して全身の姿勢の目標を更新することもできます。ただし、ここでは人間にとってより読みやすいバージョンを使用しました。
run関数を編集します。
注: postureTask->eval().norm()
を監視して、タスクのトータルの誤差を取得することもできます。ただし、今回は首のヨー方向の関節のみに着目します。
このコントローラーを実行すると、ロボットが首を左右に振るのが分かります。次のチュートリアルでも、引き続きこのコントローラーを使用します。ただし、次回のサンプルコードでは、首を左右に振る今回のコードは使用しません。
このコントローラーの完全なソースは、こちらから入手できます。
このコントローラーを別のロボットで使いたくなったものの、ロボットのどの関節を使用できるかが分からない場合があると思います。そのような場合は、以下のスニペットにより、今回のサンプルコード内でNECK_Y
の代わりに使用できる自由度1の関節のリストが出力されます。