mc_rtc::Configuration
設定このチュートリアルでは、ロボットの質量中心(CoM: Center of Mass)を制御します。先のチュートリアルと同じく、質量中心を20cm下げてから元の位置に戻す関数を記述します。
質量中心を動かす前に、接触面を考慮する必要があります。先のコントローラーでは、接触面のセットは空のままでしたが、何も問題は起こりませんでした。しかし、質量中心を制御する場合、そのコマンドをそのまま使用すると、ロボットが地面の下に沈んだり空中に浮いたりしてしまいます。これは、単に接触面がないためです(姿勢の誤差を最小限に抑えつつ質量中心を動かしたい場合は、接触面を空にするのが最もよい方法です)。
そこで、ロボットの足と地面との間に接触面を追加します。
// コンストラクター内
addContact({robot().name(), "ground", "LeftFoot", "AllGround"});
addContact({robot().name(), "ground", "RightFoot", "AllGround"});
# コンストラクター内
self.addContact(self.robot().name(), "ground", "LeftFoot", "AllGround")
self.addContact(self.robot().name(), "ground", "RightFoot", "AllGround")
注: ロボットの現在の表面を「見つける」方法については、表面の可視化に関するチュートリアルを参照してください。
ここまでは、キネマティクスモードでコントローラーを実行してきました。次に力学モードに切り替えると、以下のことが行えるようになります。
モードを切り替えるには、コード内のkinematicsConstraint
をdynamicsConstraint
に変更します。kinematicsConstraints
によって適用されていた制約条件は、dynamicsConstraint
でも適用されます。
以下の作業を行います。
// 質量中心タスクのヘッダーをインクルードする(ヘッダー)
#include <mc_tasks/CoMTask.h>
// クラス内のプライベートメンバー(ヘッダー)
std::shared_ptr<mc_tasks::CoMTask> comTask;
// コンストラクター内でタスクを作成して問題に追加する
comTask = std::make_shared<mc_tasks::CoMTask>(robots(), 0, 10.0, 1000.0);
solver().addTask(comTask);
// 姿勢制御タスクの剛性を下げる
postureTask->stiffness(1);
// reset関数内で、現在の質量中心に合わせてタスクをリセットする
comTask->reset();
# mc_tasksモジュールをインポートする
import mc_tasks
# コンストラクター内でタスクを作成して問題に追加する
self.comTask = mc_tasks.CoMTask(self.robots(), 0, 10.0, 1000.0)
self.qpsolver.addTask(self.comTask)
# 姿勢制御タスクの剛性を下げる
self.postureTask.stiffness(1)
# resetコールバック関数内で、現在の質量中心に合わせてタスクをリセットする
self.comTask.reset()
今回の例では、以下の点を考慮してタスクを作成します。
robots()
を使用する10.0
で引っ張る。このパラメーターは、ロボットを目標に向かって引っ張る「ばね」の強さを規定します。1000
を割り当てる。この重みは、最適化問題におけるタスクの優先度を表します。今回の場合、デフォルトの姿勢の重みは5.0
であるため、質量中心タスクのほうが優先されます。なお、タスクの誤差は正規化されないため、状況に応じて重みを調節する必要があります。switch_com_target()
関数を使用して、先のチュートリアルと同様のメソッドを実装します。ここでは、bool型変数comDown
と質量中心の初期位置を表すEigen::Vector3d
変数comZero
が追加されていると仮定します。
void MyFirstController::switch_com_target()
{
// comZeroは、reset関数内で
// 以下のように取得される:
// comZero = comTask->com();
if(comDown) { comTask->com(comZero - Eigen::Vector3d{0, 0, 0.2}); }
else { comTask->com(comZero); }
comDown = !comDown;
}
def switch_com_target(self):
# self.comZeroは、質量中心タスクのリセット後、
# reset関数内で以下のように取得される:
# self.comZero = self.comTask.com()
if self.comDown:
self.comTask.com(self.comZero - eigen.Vector3d(0, 0, 0.2))
else:
self.comTask.com(self.comZero)
self.comDown = not self.comDown
最後に、質量中心タスクの誤差を監視して目標を変更します。
bool MyFirstController::run()
{
if(comTask->eval().norm() < 0.01)
{
switch_com_target();
}
return mc_control::MCController::run();
}
def run_callback(self):
if self.comTask.eval().norm() < 0.01:
self.switch_com_target()
return True
このコントローラーを実行すると、ロボットが上下に動くのが分かります。次のチュートリアルでは、エンドエフェクターを動かす方法と、タスクの構成をディスクから読み込む方法について見ていきます。
このコントローラーの完全なソースは、こちらから入手できます。