mc_rtc::Configuration
設定接触面自由度は、接触面上で特定の自由度を持った動きを可能にする機能です。具体的には、接触面上で1つ以上の軸に沿った自由な動き(平行移動または回転)を可能にする機能です。
これは、特定の方向の動きを許可したり制限したりするのに使用されます。
接触面自由度は、ContactConstraintのみを修飾します。Tasks::QPContactConstr.h
に、接触面自由度に関するプロトタイプ宣言がありますので、それを見てみましょう。
bool addDofContact(const ContactId& contactId, const Eigen::MatrixXd& dof);
bool removeDofContact(const ContactId& contactId);
void updateDofContacts();
void resetDofContacts();
接触面自由度は、一般に以下の流れで使用します。
ContactIDを見つけるには、以下のように、mc_rbdyn::Contact
を作成してcontactId
メソッドを呼び出すのが一番よい方法です。
mc_rbdyn::Contact contact;
tasks::qp::contactId cId = contact.contactId(robots());
例:
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
「仮想的な」接触面です。動きは全く制限されていません。
1 0 0 0 0 0
0 1 0 0 0 0
0 0 1 0 0 0
0 0 0 1 0 0
0 0 0 0 1 0
0 0 0 0 0 1
すべての動きが制限されています(通常の接触面)
1 0 0 0 0 0
0 1 0 0 0 0
0 0 1 0 0 0
0 0 0 1 0 0
0 0 0 0 1 0
0 0 0 0 0 0
法線方向の平行移動を除きすべての動きが制限されています(接触面の挿入に便利です)。
1 0 0 0 0 0
0 1 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 1
典型的なスライドする平らな接触面です。法線軸周りの回転と、接線軸方向(x軸方向とy軸方向)の平行移動が可能です。
回転では、接触面の中心が回転軸となります。これは、円筒の周囲でグリッパーを回転させようとしたときに問題となります(グリッパーの回転軸が円筒の軸と異なるため)。
それでは、HRP2のデフォルトのサンプル(地面に立つサンプル)を試してみましょう。コンストラクターでは以下のように定義されています。
solver().setContacts({
{robots(), 0, 1, "LeftFoot", "AllGround"},
{robots(), 0, 1, "RightFoot", "AllGround"}
});
では、右足を垂直に動かしてみます。
// reset()で以下を実行
Eigen::Matrix6d dof = Eigen::Matrix6d::Identity();
dof(5,5) = 0;
tasks::qp::ContactId ContactId = mc_rbdyn::Contact(robots(), 0, 1, "RightFoot", "AllGround").contactId(robots());
contactConstraint().contactConstr->addDofContact(ContactId, dof);
contactConstraint().contactConstr->updateDofContacts();
次に、足が垂直に動くのを制限するため、EndEffectorTaskを追加し、この制約条件が正しく機能するか確認します。
//ヘッダファイルに以下を追加
std::shared_ptr<mc_tasks::EndEffectorTask> efTask;
//cppファイルに以下を追加
// コンストラクタ部分
efTask = std::make_shared<mc_tasks::EndEffectorTask>("R_FOOT", robots(), 0, 5.0, 100);
efTask->addToSolver(solver());
// reset()関数部分
efTask->resetTask(robots(), 0);
efTask->add_ef_pose(sva::PTransformd(Eigen::Vector3d(0.2, 0., 0.2)));
これを実行すると、JVRC1の足が完全に垂直に動くのが分かります。
注: この手順はキネマティクスモードで実行してください。そうでない場合、ロボットの体重を左足に乗せるという最初のステップを追加しない限り、ロボットが転倒します。
次に、これを少し変更して、スライドする平らな接触面をシミュレートしてみましょう。行列dof
を編集し、EndEffectorTask
のターゲットを変更します。
Eigen::Matrix6d dof = Eigen::Matrix6d::Identity();
dof(2,2) = 0;
dof(3,3) = 0;
dof(4,4) = 0;
efTask->add_ef_pose(sva::PTransformd(sva::RotX(1.)*sva::RotY(1.)*sva::RotZ(1.),Eigen::Vector3d(0.2, -0.2, 0.2)));
今度は、接触面は同じ高さで水平を保ったままですが、接触面内で垂直軸周りに回転します。
この場合もキネマティクスモードでしか正しく機能しません。