Springhead Users Manual

7.5 関節

Fig. 7.1: Constraint class hierarchy

拘束とは剛体と剛体の間に作用してその相対的運動に制約を加える要素です. 拘束のクラス階層をFig. 7.1に示します. まず拘束は関節と接触に分かれます.関節はユーザが作成しますが,接触は衝突判定結 果にもとづいて自動的に生成・削除されます. 関節はさらにいくつかの種類に分けられます.

細かな説明は後回しにして,まずは関節の作成方法から見ていきます.

関節の作成

以下ではもっとも使用頻度の高いヒンジの作成を例にとって関節の作成方法を説明します. ヒンジを作成するには次のようにします.

PHSolidIf* solid0 = phScene->GetSolids()[0];
PHSolidIf* solid1 = phScene->GetSolids()[1];


PHHingeJointDesc desc;
desc.poseSocket.Pos() = Vec3d( 1.0, 0.0, 0.0);
desc.posePlug.Pos()        = Vec3d(-1.0, 0.0, 0.0);
PHHingeJointIf* joint
     = phScene->CreateJoint(solid0, solid1, desc)->Cast();

作成したい関節の種類に応じたディスクリプタを作成し,これをPHSceneCreateJoint関数に渡して関節を作成します. このとき,ディスクリプタとともに連結したい剛体のインタフェースも渡します. CreateJointPHJointIf*を返しますので,作成した関節のインタフェースを得るにはCastで動的キャストします.

関節に関するPHSceneの関数を以下に示します.

PHSceneIf

PHJointIf*

CreateJoint(PHSolidIf*, PHSolidIf*, const PHJointDesc&)

int

NJoint()

PHJointIf*

GetJoint(int i)

NJointはシーン中の関節の個数を返します.GetJointi番目の関節を取得します.

ソケットとプラグ
(a) before connection
(b) after connection

Fig. 7.2: Socket and plug

さて,上の例でディスクリプタに値を設定している箇所に注目してください.この部分で関節の取り付け位置を指定しています. Springheadでは,ソケットとプラグと呼ばれるローカル座標系を用いて関節の取り付け位置を表現します. ソケットとプラグとは,その名前 から連想するように,連結する剛体に取り付ける金具のようなものです. CreateJointの第\( 1 \)引数の剛体にソケットがつき,第\( 2 \)引数の剛体にプラグがつきます. ソケットとプラグがそれぞれの剛体のどの位置に取り付けられるかを指定するのがディスク リプタのposeSocketposePlugです. 上の例ではソケットの位置が\( (1,0,0) \),プラグの位置が\( (-1,0,0) \)でした(Fig. 7.2(a)). この場合はFig. 7.2(b)のように剛体が連結されます. 後述するように,ヒンジはソケットとプラグのz軸を一致させる拘束です. したがって連結された剛体同士はソケットとプラグのz軸を回転軸として相対的に回 転することができます.

ソケットとプラグに関するディスクリプタとインタフェースを紹介します.

PHConstraintDesc

Posed

poseSocket

ソケットの位置と向き

Posed

posePlug

プラグの位置と向き

PHConstraintIf

PHSolidIf*

GetSocketSolid()

ソケット側の剛体

PHSolidIf*

GetPlugSolid()

プラグ側の剛体

void

GetSocketPose(Posed&)

void

SetSocketPose(const Posed&)

void

GetPlugPose(Posed&)

void

SetPlugPose(const Posed&)

void

GetRelativePose(Posed&)

相対的な位置と向き

void

GetRelativeVelocity(Vec3d&, Vec3d&)

相対速度

void

GetConstraintForce(Vec3d&, Vec3d&)

拘束力

GetRelativePoseはソケット座標系から見たプラグ座標系の相対的な位置と向きを取得します. 同様に,GetRelativeVelocityはソケットからみたプラグの相対速度をソケット座標系で取得します. ここで第\( 1 \)引数が並進速度,第\( 2 \)引数が角速度です. GetConstraintForceはこの拘束が剛体に加えた拘束力を取得します(第\( 1 \)引数が並進力,第\( 2 \)引数がモーメント). 具体的には,ソケット側剛体に作用した拘束力をソケット座標系で表現したものが得られます. プラグ 側剛体には作用反作用の法則によって逆向きの力が作用しますが,これを直接取得する関数は用意されていません.

関節の種類

Springheadで使用可能な関節の種類は

の5種類です.種類ごとに,自由度・拘束の仕方・変位の求め方が異なります.

ヒンジ

Fig. 7.3: Hinge joint

ヒンジは\( 1 \)軸回転関節です. ヒンジは,Fig 7.3に示すようにソケットと プラグのz軸が一致するように拘束します. このときソケットのy軸とプラグのy軸の成す角(x軸同士でも同じことですが)が関節変位となります.

関節変位を取得するAPIは\( 1 \)自由度関節(PH1DJointIf)で共通です.そのためヒンジに限らずスライダ・パスジョイントでも使用できます.

PH1DJointIfクラス

double GetPosition()

   

関節の変位を取得します.変位のはかり方は関節の種類に依存します.

スライダ

Fig. 7.4: Slider joint

スライダは\( 1 \)自由度の直動関節です. スライダは,Fig 7.4に示すようにソ ケットとプラグのz軸が同一直線上に乗り,かつ両者のx軸,y軸が同じ向きを向くように拘束します. このときソケットの原点からプラグの原点までが関節変位となります.

パスジョイント

パスジョイントはソケットとプラグの相対位置関係を\( 1 \)パラメータの自由曲線で表現する関節です.詳しくは後述します.

T.B.D.

ボールジョイント
(a) (b)

Fig. 7.5: Ball Joint

ボールジョイントは\( 3 \)自由度の回転関節です. ボールジョイントはFig 7.5(a)に示す ようにソケットとプラグの原点が一致するように拘束します. ソケット座標系をプラグ座標系に変換するようなクォータニオンが変位となります.

一方で,ボールジョイントの変位はオイラー角の一種であるSwing-Twist座標系(Fig 7.5(b))で取得することもできます. ソケットとプラグのz軸同士がなす角をスイング角(Swing),プラグのz軸をソケット のx-y平面への射影がソケットのx軸となす角をスイング方位角(Swing-Dir),プラグのz軸周りの回転角度をツイスト角(Twist)と呼びます.Swing-Twist座標系は,後述するボールジョイントの関節可動範囲の指定に用います.

この2種類の変位は,それぞれに対応した関数で取得することができます. PHBallJointクラス

Quaterniond GetPosition()

   

ソケット座標系をプラグ座標系に変換するようなクォータニオンを返します.

Vec3d GetAngle()

   

Swing-Twist座標系で表現された関節変位を返します.

バネ

Fig. 7.6: Spring

剛体間を連結するダンパ付きバネです.ソケット座標系とプラグ座標系が一致するときが自然状態で,位置の変位・姿勢の変位に比例して自然状態に戻すような力・モーメントを発生します.並進運動に作用するバネ・ダンパ係数と,回転運動に作用するバネ・ダンパ係数 はディスクリプタによってそれぞれ設定できます.

PHSpringDesc
Vec3d spring & 並進運動に対するバネ係数
Vec3d damper & 並進運動に対するダンパ係数
double springOri & 回転運動に対するバネ係数
double damperOri & 回転運動に対するダンパ係数
有効化と無効化
PHConstraintDesc

bool

bEnabled

有効/無効フラグ

PHConstraintIf

void

Enable(bool)

bool

IsEnabled()

有効な拘束は拘束力を生じます.無効化された拘束は存在しないのと同じ状態になりますが, 削除するのと異なりいつでも再度有効化することができます. 作成直後の拘束は有効化されています.

関節制御
\( 1 \)自由度関節の場合
PHJoint1DDesc

double

spring

可動範囲下限

double

damper

可動範囲上限

double

targetPosition

可動範囲制限用バネ係数

double

targetVelocity

可動範囲制限用ダンパ係数

double

offsetForce

double

fMax

PHJoint1DIf

double & GetPosition() & 関節変位を取得

double & GetVelocity() & 関節速度を取得

void & SetSpring(double) &

double & GetSpring() &

void & SetDamper(double) &

double & GetDamper() &

void & SetTargetPosition(double) &

double & GetTargetPosition() &

void & SetTargetVelocity(double) &

double & GetTargetVelocity() &

void & SetOffsetForce(double) &

double & GetOffsetForce() &

void & SetTorqueMax(double) & 最大関節トルクを設定

double & GetTorqueMax() & 最大関節トルクを取得

関節を駆動する力\( f \)は次式で与えられます.

\{begin}{align*}   f = K(p_0 - p) + D(v_0 - v) + f_0 \{end}{align*}

ここで\( p \)\( v \)はそれぞれ関節変位と関節速度でGetPositionGetVelocityで取得できます. その他の記号とデ ィスクリプタ変数との対応は以下の通りです.

\( K \) spring
\( D \) damper
\( p_0 \) targetPosition
\( v_0 \) targetVelocity
\( f_0 \) offsetForce

上の式はバネ・ダンパモデルとPD制御則の二通りの解釈ができます. 前者としてとらえるなら\( K \)はバネ係数,\( D \)はダンパ係数,\( p_0 \)はバネの自然長,\( v_0 \)は基準速度となります. 後者としてとらえる場合は\( K \)はPゲイン,\( D \)はDゲイン,\( p_0 \)は目標変位,\( v_0 \)は目標速度となります. また,\( f_0 \)は関節トルクのオフセット項です. 上の式で得られた関節トルクは最後に\( \pm   \)fMaxの範囲に収まるようにクランプされます.

ボールジョイントの場合

ヒンジと同様に,バネダンパモデル・PD制御を実現します. ボールジョイントの変位はクォータニオンで表されるため,目標変位targetPositionはクォータニオンで,目標速度targetVelocityは回転ベクトルで与えます.

PHBallJointDesc
double spring & バネ係数
double damper & ダンパ係数
Quaterniond targetPosition & 目標変位
Vec3d targetVelocity & 目標速度
Vec3d offsetForce & モータートルク
double fMax & 関節トルクの限度
可動域制限

CreateLimitは可動範囲制約オブジェクトのディスクリプタを引数にとります. \( 1 \)自由度関節の可動範囲制約の場合,Vec2d rangeが可動域を表します.range[0]が可動域の下限, range[1]が上限です.range[0] <range[1]が満たされているときに限り可動範囲制約が有効となります. デフォルトではrange[0] >range[1]となる値が設定されていて,可動範囲制約は無効となっています.

関節の変位が可動範囲限界に到達したとき,範囲を超過しないように可動範囲制約の拘束力が作用します. このとき,関節変位を範囲内に押し戻す力はバネ・ダンパモデルで計算されます. このバネ係数とダンパ係数はそれぞれディスクリプタのspringdamperで指定します.

可動範囲用のspringdamperは初期値でも十分大きな値が設定されていますが,関節制御において非常に大きなバネ・ダンパ係数を用いると可動範囲制約のバネ・ダンパが負けてしまうことがあります.その場合には関節制御より大きな係数を 適切に再設定すると,可動範囲内で関節を制御する事ができるようになります.

\( 1 \)自由度関節の場合

PH1DJointLimitDescクラス

Vec2d range

   

可動範囲を表します.range[0]が下限,range[1]が上限です.

double spring

   

double damper

   

可動範囲を制限するためのバネ・ダンパモデルの係数です.

PH1DJointLimitIfクラス

IsOnLimit()

   

現在の関節姿勢が可動範囲外にある時にtrueを返します.この関数がtrueを返すような時,関節には可動域制約を実現するための拘束力が発生しています.

ボールジョイントの場合

ボールジョイントの可動範囲はFig 7.5(b)に示すSwing-Twist座標系によって指定します.

ボールジョイントに対しては2種類の可動範囲制約を使用することができます.

ここではConeLimitについて説明します(SplineLimitについては後述します).

PHBallJointConeLimitDescクラス

Vec2d limitSwing

   

スイング角の可動範囲です.概念的には,関節が一定以上に折れ曲がらないようにする制約です(スイング角の下限を設定する事もできるので,実際には一定以上にまっすぐにならないようにする機能も有しています).

limitSwing[0]が下限,limitSwing[1]が上限です.limitSwingを取得・設定するためのAPIは

PHBallJointConeLimitIf::[Set|Get]SwingRange(range)

です.

limitSwing[0] >limitSwing[1]となる時は無効化されます.デフォルトではlimitSwing[0] >limitSwing[1]となる値がセットされています.

Vec2d limitTwist

   

ツイスト角の可動範囲です.概念的には,関節が一定以上にねじれないようにするための制約です.

limitTwist[0]が下限,limitTwist[1]が上限です.limitTwistを取得・設定するためのAPIは

PHBallJointConeLimitIf::[Set|Get]TwistRange(range)

です.

limitTwist[0] >limitTwist[1]となる時は無効化されます.デフォルトではlimitTwist[0] >limitTwist[1]となる値がセットされています.

double spring

   

double damper

   

可動範囲を制限するためのバネ・ダンパモデルの係数です.\( 1 \)自由度関節の場合と同じです.

PHBallJointConeLimitIfクラス

IsOnLimit()

   

現在の関節姿勢が可動範囲外にある時にtrueを返します.\( 1 \)自由度関節の場合と同じです.

ボールジョイントの自由曲線可動域
パスジョイント
弾塑性変形バネダンパ