forwardDynamics.C

src/rigidBodyDynamics/rigidBodyModel/forwardDynamics.C

ソースコード
/*---------------------------------------------------------------------------*\
  =========                 |
  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
   \\    /   O peration     |
    \\  /    A nd           | www.openfoam.com
     \\/     M anipulation  |
-------------------------------------------------------------------------------
    Copyright (C) 2016 OpenFOAM Foundation
-------------------------------------------------------------------------------
License
    This file is part of OpenFOAM.
    OpenFOAM is free software: you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    for more details.
    You should have received a copy of the GNU General Public License
    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "rigidBodyModel.H"
#include "rigidBodyModelState.H"
#include "rigidBodyRestraint.H"
// * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * * //
void Foam::RBD::rigidBodyModel::applyRestraints
(
    scalarField& tau,
    Field<spatialVector>& fx,
    const rigidBodyModelState& state
) const
{
    if (restraints_.empty())
    {
        return;
    }
    forAll(restraints_, ri)
    {
        DebugInfo << "Restraint " << restraints_[ri].name();
        // Accumulate the restraint forces
        restraints_[ri].restrain(tau, fx, state);
    }
}
void Foam::RBD::rigidBodyModel::forwardDynamics
(
    rigidBodyModelState& state,
    const scalarField& tau,
    const Field<spatialVector>& fx
) const
{
    const scalarField& q = state.q();
    const scalarField& qDot = state.qDot();
    scalarField& qDdot = state.qDdot();
    DebugInFunction
        << "q = " << q << nl
        << "qDot = " << qDot << nl
        << "tau = " << tau << endl;
    // Joint state returned by jcalc
    joint::XSvc J;
    v_[0] = Zero;
    for (label i=1; i<nBodies(); i++)
    {
        const joint& jnt = joints()[i];
        jnt.jcalc(J, q, qDot);
        S_[i] = J.S;
        S1_[i] = J.S1;
        Xlambda_[i] = J.X & XT_[i];
        const label lambdai = lambda_[i];
        if (lambdai != 0)
        {
            X0_[i] = Xlambda_[i] & X0_[lambdai];
        }
        else
        {
            X0_[i] = Xlambda_[i];
        }
        v_[i] = (Xlambda_[i] & v_[lambdai]) + J.v;
        c_[i] = J.c + (v_[i] ^ J.v);
        IA_[i] = I(i);
        pA_[i] = v_[i] ^* (I(i) & v_[i]);
        if (fx.size())
        {
            pA_[i] -= *X0_[i] & fx[i];
        }
    }
    for (label i=nBodies()-1; i>0; i--)
    {
        const joint& jnt = joints()[i];
        const label qi = jnt.qIndex();
        if (jnt.nDoF() == 1)
        {
            U1_[i] = IA_[i] & S1_[i];
            Dinv_[i].xx() = 1/(S1_[i] && U1_[i]);
            u_[i].x() = tau[qi] - (S1_[i] && pA_[i]);
            const label lambdai = lambda_[i];
            if (lambdai != 0)
            {
                const spatialTensor Ia
                (
                    IA_[i] - (U1_[i]*(Dinv_[i].xx()*U1_[i]))
                );
                const spatialVector pa
                (
                    pA_[i] + (Ia & c_[i]) + U1_[i]*(Dinv_[i].xx()*u_[i].x())
                );
                IA_[lambdai] +=
                    spatialTensor(Xlambda_[i].T())
                  & Ia
                  & spatialTensor(Xlambda_[i]);
                pA_[lambdai] += Xlambda_[i].T() & pa;
            }
        }
        else
        {
            U_[i] = IA_[i] & S_[i];
            Dinv_[i] = (S_[i].T() & U_[i]).inv();
            u_[i] = tau.block<vector>(qi) - (S_[i].T() & pA_[i]);
            const label lambdai = lambda_[i];
            if (lambdai != 0)
            {
                spatialTensor Ia
                (
                    IA_[i]
                  - (U_[i] & Dinv_[i] & U_[i].T())
                );
                spatialVector pa
                (
                    pA_[i]
                  + (Ia & c_[i])
                  + (U_[i] & Dinv_[i] & u_[i])
                );
                IA_[lambdai] +=
                    spatialTensor(Xlambda_[i].T())
                  & Ia
                  & spatialTensor(Xlambda_[i]);
                pA_[lambdai] += Xlambda_[i].T() & pa;
            }
        }
    }
    a_[0] = spatialVector(Zero, -g_);
    for (label i=1; i<nBodies(); i++)
    {
        const joint& jnt = joints()[i];
        const label qi = jnt.qIndex();
        a_[i] = (Xlambda_[i] & a_[lambda_[i]]) + c_[i];
        if (jnt.nDoF() == 1)
        {
            qDdot[qi] = Dinv_[i].xx()*(u_[i].x() - (U1_[i] && a_[i]));
            a_[i] += S1_[i]*qDdot[qi];
        }
        else
        {
            vector qDdoti(Dinv_[i] & (u_[i] - (U_[i].T() & a_[i])));
            // Need to add mutable "block<vector>" to Field
            qDdot[qi] = qDdoti.x();
            qDdot[qi+1] = qDdoti.y();
            qDdot[qi+2] = qDdoti.z();
            a_[i] += (S_[i] & qDdoti);
        }
    }
    DebugInfo
        << "qDdot = " << qDdot << nl
        << "a = " << a_ << endl;
}
void Foam::RBD::rigidBodyModel::forwardDynamicsCorrection
(
    const rigidBodyModelState& state
) const
{
    DebugInFunction << endl;
    const scalarField& q = state.q();
    const scalarField& qDot = state.qDot();
    const scalarField& qDdot = state.qDdot();
    // Joint state returned by jcalc
    joint::XSvc J;
    v_[0] = Zero;
    a_[0] = spatialVector(Zero, -g_);
    for (label i=1; i<nBodies(); i++)
    {
        const joint& jnt = joints()[i];
        const label qi = jnt.qIndex();
        jnt.jcalc(J, q, qDot);
        S_[i] = J.S;
        S1_[i] = J.S1;
        Xlambda_[i] = J.X & XT_[i];
        const label lambdai = lambda_[i];
        if (lambdai != 0)
        {
            X0_[i] = Xlambda_[i] & X0_[lambdai];
        }
        else
        {
            X0_[i] = Xlambda_[i];
        }
        v_[i] = (Xlambda_[i] & v_[lambdai]) + J.v;
        c_[i] = J.c + (v_[i] ^ J.v);
        a_[i] = (Xlambda_[i] & a_[lambdai]) + c_[i];
        if (jnt.nDoF() == 1)
        {
            a_[i] += S1_[i]*qDdot[qi];
        }
        else
        {
            a_[i] += S_[i] & qDdot.block<vector>(qi);
        }
    }
    DebugInfo<< "a = " << a_ << endl;
}
// ************************************************************************* //
void Foam::RBD::rigidBodyModel::forwardDynamics
(
    rigidBodyModelState& state,
    const scalarField& tau,
    const Field<spatialVector>& fx
) const
{

const scalarField& q = state.q();
n個の剛体の位置姿勢:(Px1, Py1, Pz1, Rx1, Ry1, Rz1, Px2,…..)
const scalarField& qDot = state.qDot();
n 個の剛体の速度:(vx1, vy1, vz1, ωx1, ωy1, ωz1, vx2,…..)
scalarField& qDdot = state.qDdot();
n 個の剛体の加速度:(ax1, ay1, az1, dωx1, dωy1, dωz1, ax2,…..)
joint::XSvc J;
ジョイントの状態から空間行列, ベクトルを変数Jに格納(J.X, J.S, J.v, J.c, )
XSvcはX, S, v, cの4要素をまとめたクラス
- X : 空間座標変換行列
親から子へ座標変換を行う
- S : 運動部分空間ベクトル
ジョイントの自由度
- v : ジョイントの空間速度
親に対する子の相対的な速度(並進速度と角速度をまとめた6次元空間ベクトル)
ジョイントの速度$\dot{q}$に運動部分空間ベクトル$S$を乗算したベクトル($v=S\dot{q}$)
- c : バイアス空間加速度
ジョイントが動くことによって生じる、コリオリ加速度や遠心加速度などの項(6次元ベクトル)


Xlambda_[i] = J.X & XT_[i];
J.X:参照剛体の座標系の変位
XT_[i]:親剛体から見た参照剛体の座標系の初期変位
これらの内積なので, Xlambda_[i]は親剛体から見た現在の参照剛体の座標系の変位.
ここでいう変位は並進と回転どちらも含む.
const label lambdai = lambda_[i];
親剛体を番号を出力する. 計算空間は0
剛体1に剛体2と3の二つが接続されている場合、
lambda_[0] = -1:計算空間は-1だが, おそらくこれはダミー
lambda_[1] = 0:計算空間(0)が親
lambda_[2] = 1:剛体1(1)が親
lambda_[3] = 1:剛体1(1)が親

if (lambdai != 0)
	{
		X0_[i] = Xlambda_[i] & X0_[lambdai];
	}
else
	{
		X0_[i] = Xlambda_[i];
	}

このif文は参照剛体の親が計算空間か否かを判定する.
親が計算空間ではない場合, 親剛体の座標系の変位を内積する.
親が計算空間の場合, 計算空間は動かないので参照剛体の座標系の変位を格納する.
結果的に, 一連のプログラムによってX0_に全剛体の計算空間から見た座標系の変位が格納される.
剛体1,2,3が直列に接続されている場合でも,
剛体1:計算空間から見た座標系
剛体2:剛体1から見た座標系&計算空間から見た剛体1の座標系
剛体3:剛体1から見た座標系&(剛体1から見た座標系&計算空間から見た剛体1の座標系)
となるのですべて計算空間から見た値になる.