Springhead Users Manual

7.7 接触

接触モデル

Fig. 7.7: Contact configuration

Springheadで採用している接触モデルについて説明します. 第7.3節で述べたように,PHSceneIf::Stepによってシミュレーションを1ステップ進めると, 初めに形状の交差判定と接触拘束の生 成が行われます. 交差する二つの形状の交差断面と,接触拘束の関係についてFig. 7.7に示します. 図では簡単のために二次元で描いていますが,実際には接触断面を表す多角形の各頂点に接触拘束が作られ ます. 接触拘束も他の拘束と同様にソケットとプラグで構成されます. 一方で,他の拘束とは違い接触拘束は交差判定アルゴリズムによって動的に生成・破棄されます. このため,接触し合う剛体のどちらにソケットあるいはプラグが取り付けられるかは状況依存であり, 外部から選択することはできません.

プラグおよびソケットの向きは次のようにして決まります. まず,x軸は接触法線と平行に向きます.ただしどちらが正の向きかは状況依存です. 次に,y軸は接触点における二つの剛体の相対速度ベクトルを接触断面へ投影した向きに向きます. 最後にz軸はx,y軸に直 交するように決まります.

以下では各接触拘束が課す条件について具体的に述べます. まず,法線方向の進入速度の大小に応じて衝突モデルと静的接触モデルのいずれかが選択されます.

\{begin}{align*} v^\mathrm {x} < -V^\mathrm {th} \;\; &\Rightarrow \;\; \text {\KLUDGE èąİ糥ãČćãČĞãČń} \\ v^\mathrm {x} \ge -V^\mathrm {th} \;\; &\Rightarrow \;\; \text
{\KLUDGE éİŹçŽĎæŐěèğęãČćãČĞãČń} \{end}{align*}

ここで\( v^\mathrm {x} \)はソケットから見たプラグの相対速度のx軸(接触法線)成分で,近づき合う向きを負とします. また,\( V^\mathrm {th} \)は衝突モデルへ切り替わる臨界速度です.

衝突モデルでは,1ステップ後の相対速度\( {v^\mathrm {x}}’ \)が跳ね返り係数\( e \)にもとづいて決まり,それを満たすような接触力が計算されます.

(7.1) \{begin}{align}   {v^\mathrm {x}}’ = - e \, v^\mathrm {x} \{end}{align}

ここで,跳ね返り係数は衝突する形状の物性値に定義された跳ね返り係数の平均値です.

静的接触モデルでは,形状同士の進入深度\( d \)が1ステップで所定の割合で減少するような接触力を求めます. つまり,1ステップ後の進入深度を\( d’ \)とすると

(7.2) \{begin}{align}   d’ = d - \gamma \mathrm {max}(d - d^\mathrm {tol}, 0) \{end}{align}

となります. ここで\( \gamma   \)は接触拘束の誤差修正率です. また,\( d^\mathrm {tol} \)は許容進入深度です.

最後に,接触力が満たすべき条件について述べます. まず,法線方向には反発力のみ作用することから,接触力のx軸成分\( f^\mathrm {x} \)には

\{begin}{align*}   f^\mathrm {x} \ge 0 \{end}{align*}

が課せられます. 一方で接触力のy軸成分\( f^\mathrm {y} \),z軸成分\( f^\mathrm {z} \)は摩擦力を表します. 摩擦力に関しては,その向きの相対速度にもとづき静 止摩擦か動摩擦かが判定され,それに応じて最大摩擦力の制約が課されます.

\{begin}{align*} -\mu _0 f^\mathrm {x} \le &f^\mathrm {y} \le \mu _0 f^\mathrm {x} & & \text {if} \; -V^\mathrm {f} \le v^\mathrm {y} \le V^\mathrm {f},\\ \mu f^\mathrm
{x} \le &f^\mathrm {y} \le \mu f^\mathrm {x} & & \text {otherwise} \{end}{align*}

ここで,静止摩擦係数\( \mu _0 \)および動摩擦係数\( \mu   \)は跳ね返り係数と同様に各形状の物性値の平均値が用いられます. また,\( V^\mathrm {f} \)は静止摩擦と動摩擦が切り替わる臨界速度です. z軸方向についても同様の制約が課されます.

接触モデルの関係するインタフェースには以下があります.

CDShapeIf

void

SetElasticity(float e)

跳ね返り係数を設定

float

GetElasticity()

跳ね返り係数を取得

void

SetStaticFriction(float mu0)

静摩擦係数を設定

float

GetStaticFriction()

静摩擦係数を取得

void

SetDynamicFriction(float mu)

動摩擦係数を設定

float

GetDynamicFriction()

動摩擦係数を取得

PHSceneIf

void

SetContactTolerance(double tol)

許容交差深度を設定

double

GetContactTolerance()

許容交差深度を取得

void

SetImpactThreshold(double vth)

最小衝突速度を設定

double

GetImpactThreshold()

最小衝突速度を取得

void

SetFrictionThreshold(double vf)

最小動摩擦速度を設定

double

GetFrictionThreshold()

最小動摩擦速度を取得

備考

接触力の取得

特定の剛体に作用する接触力を直接取得するためのインタフェースは用意されていません. このため,ユーザサイドである程度の計算を行う必要があります. 以下に,ある剛体に作用する接触力の合力を求める例を示します.

// given PHSceneIf* scene
// given PHSolidIf* solid


Vec3d fsum;        //< sum of contact forces applied to "solid"
Vec3d tsum;        //< sum of contact torques applied to "solid"


int N = scene->NContacts();
Vec3d f, t;
Posed pose;


for(int i = 0; i < N; i++){
     PHContactPointIf* con = scene->GetContact(i);
     con->GetConstraintForce(f, t);


     if(con->GetSocketSolid() == solid){
          con->GetSocketPose(pose);
          fsum -= pose.Ori() * f;
          tsum -= pose.Pos() % pose.Ori() * f;
     }
     if(con->GetPlugSolid() == solid){
          con->GetPlugPose(pose);
          fsum += pose.Ori() * f;
          tsum += pose.Pos() % pose.Ori() * f;
     }
}

まず,シーン中の接触拘束の数をPHSceneIf::NConstactsで取得し, forループ中で\( i \)番目の接触拘束をPHSceneIf::GetContactで取得します. 次 にPHConstraintIf::GetConstraintForceで接触力の並進力fとモーメントtを取得しますが, 接触拘束の場合モーメントは\( 0 \)ですので用いません. また,得られる拘束力はソケット/プラグ座標系で表したもので,作用点はソケット/プラグ座標系の 原点です. これを考慮して剛体に作用する力とモーメントへ変換し,合力に足し合わせていきます. 剛体がソケット側である場合は作用・反作用を考慮して符号を反転することに注意して下さい.

接触力計算の有効/無効の切り替え

多くのアプリケーションでは,すべての剛体の組み合わせに関して接触を取り扱う必要はありません. このような場合は必要な剛体の対に関してのみ接触を有効化することで計算コストを削減できます. Springheadでは,剛体の組み合わせ毎に交差判定および接触力計算 を行うかを切り替えることができます. これにはPHSceneIf::SetContactModeを用います.

PHSceneIf

void

SetContactMode(PHSolidIf* lhs, PHSolidIf* rhs, int mode)

void

SetContactMode(PHSolidIf** group, size_t length, int mode)

void

SetContactMode(PHSolidIf* solid, int mode)

void

SetContactMode(int mode)

一番目は剛体lhsrhsの対に関してモードを設定します. 二番目は配列[group, group + length)に格納された剛体の全組み合わせに関して設定します. 三番目は剛体solidと他の全剛体との組み合わせに関して設定しま す. 四番目はシーン中のすべての剛体の組み合わせに関して設定します.

設定可能なモードは以下の内の一つです.

PHSceneDesc::ContactMode

MODE_NONE

交差判定および接触力計算を行わない

MODE_LCP

交差判定を行い,拘束力計算法を用いる

MODE_PENALTY

交差判定を行い,ペナルティ反力法を用いる

デフォルトではすべての剛体対に関してMODE_LCPが選択されています. 例として,床面との接触以外をすべてオフにするには

// given PHSolidIf* floor


scene->SetContactMode(PHSceneDesc::MODE_NONE);
scene->SetContactMode(floor, PHSceneDesc::MODE_LCP);

とします.