JointSpringForceField.inl

Go to the documentation of this file.
00001 /******************************************************************************
00002 *       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 3      *
00003 *                (c) 2006-2008 MGH, INRIA, USTL, UJF, CNRS                    *
00004 *                                                                             *
00005 * This library is free software; you can redistribute it and/or modify it     *
00006 * under the terms of the GNU Lesser General Public License as published by    *
00007 * the Free Software Foundation; either version 2.1 of the License, or (at     *
00008 * your option) any later version.                                             *
00009 *                                                                             *
00010 * This library is distributed in the hope that it will be useful, but WITHOUT *
00011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
00012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
00013 * for more details.                                                           *
00014 *                                                                             *
00015 * You should have received a copy of the GNU Lesser General Public License    *
00016 * along with this library; if not, write to the Free Software Foundation,     *
00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
00018 *******************************************************************************
00019 *                               SOFA :: Modules                               *
00020 *                                                                             *
00021 * Authors: The SOFA Team and external contributors (see Authors.txt)          *
00022 *                                                                             *
00023 * Contact information: contact@sofa-framework.org                             *
00024 ******************************************************************************/
00025 #ifndef SOFA_COMPONENT_FORCEFIELD_JOINTSPRINGFORCEFIELD_INL
00026 #define SOFA_COMPONENT_FORCEFIELD_JOINTSPRINGFORCEFIELD_INL
00027 
00028 #include <sofa/component/forcefield/JointSpringForceField.h>
00029 #include <sofa/core/componentmodel/topology/BaseMeshTopology.h>
00030 #include <sofa/helper/io/MassSpringLoader.h>
00031 #include <sofa/helper/gl/template.h>
00032 #include <sofa/helper/gl/Cylinder.h>
00033 #include <sofa/helper/gl/Axis.h>
00034 #include <sofa/helper/system/config.h>
00035 #include <assert.h>
00036 #include <iostream>
00037 using std::cerr;
00038 using std::endl;
00039 
00040 namespace sofa
00041 {
00042 
00043 namespace component
00044 {
00045 
00046 namespace forcefield
00047 {
00048 
00049 
00050 template<class DataTypes>
00051 JointSpringForceField<DataTypes>::JointSpringForceField(MechanicalState* object1, MechanicalState* object2)
00052 : Inherit(object1, object2)
00053   , springs(initData(&springs,"spring","pairs of indices, stiffness, damping, rest length"))
00054   , showLawfulTorsion(initData(&showLawfulTorsion, false, "show lawful Torsion", "dislpay the lawful part of the joint rotation"))
00055   , showExtraTorsion(initData(&showExtraTorsion, false, "show illicit Torsion", "dislpay the illicit part of the joint rotation"))
00056 {
00057 }
00058     
00059 template<class DataTypes>
00060 JointSpringForceField<DataTypes>::JointSpringForceField()
00061 : springs(initData(&springs,"spring","pairs of indices, stiffness, damping, rest length"))
00062 , showLawfulTorsion(initData(&showLawfulTorsion, false, "show lawful Torsion", "dislpay the lawful part of the joint rotation"))
00063 , showExtraTorsion(initData(&showExtraTorsion, false, "show illicit Torsion", "dislpay the illicit part of the joint rotation"))
00064 {
00065 }
00066 
00067                   
00068 template <class DataTypes>
00069 void JointSpringForceField<DataTypes>::init()
00070 {
00071     this->Inherit::init();
00072 }
00073 
00074 template<class DataTypes>
00075 void JointSpringForceField<DataTypes>::addSpringForce( double& /*potentialEnergy*/, VecDeriv& f1, const VecCoord& p1, const VecDeriv& v1, VecDeriv& f2, const VecCoord& p2, const VecDeriv& v2, int , /*const*/ Spring& spring)
00076 {
00077     int a = spring.m1;
00078     int b = spring.m2;
00079 
00080     Mat Mr01, Mr10;
00081     p1[a].writeRotationMatrix(Mr01);
00082     invertMatrix(Mr10, Mr01);
00083 
00084     Vector damping(spring.kd, spring.kd, spring.kd);
00085 
00086     //store the referential of the spring (p1) to use it in addSpringDForce() 
00087     springRef[a] = p1[a];
00088 
00089     //compute p2 position and velocity, relative to p1 referential
00090     Coord Mp1p2 = p2[b] - p1[a];
00091     Deriv Vp1p2 = v2[b] - v1[a];
00092 
00093     //compute elongation
00094     Mp1p2.getCenter() -= spring.initTrans;
00095     //compute torsion
00096     Mp1p2.getOrientation() =  Mp1p2.getOrientation() * spring.initRot.inverse();
00097 
00098     //-- decomposing spring torsion in 2 parts (lawful rotation and illicit rotation) to fix bug with large rotations
00099     Vector dRangles = Mp1p2.getOrientation().toEulerVector();
00100         //lawful torsion = spring torsion in the axis where ksr is null 
00101     Vector lawfulRots( (Real)spring.freeMovements[3], (Real)spring.freeMovements[4], (Real)spring.freeMovements[5] );
00102     spring.lawfulTorsion = Quat::createFromRotationVector(dRangles.linearProduct(lawfulRots));
00103     Mat MRLT;
00104     spring.lawfulTorsion.toMatrix(MRLT);
00105         //extra torsion = spring torsion in the other axis (ksr not null), expressed in the lawful torsion reference axis
00106         // |--> we apply rotation forces on it, and then go back to world reference axis
00107     spring.extraTorsion = spring.lawfulTorsion.inverse()*Mp1p2.getOrientation();
00108 
00109     //--
00110     //--test limit angles
00111     Vector dTorsion = spring.lawfulTorsion.toEulerVector();
00112     bool bloc=false;
00113     for (unsigned int i=0; i<3; i++){
00114         if (spring.freeMovements[3+i] && dRangles[i] < spring.limitAngles[i*2]){
00115             spring.bloquage[i] = spring.blocStiffnessRot;
00116             dTorsion[i] -= spring.limitAngles[i*2];
00117             bloc=true;
00118         }
00119         else if (spring.freeMovements[3+i] && dRangles[i] > spring.limitAngles[i*2+1]){
00120             spring.bloquage[i] = spring.blocStiffnessRot;
00121             dTorsion[i] -= spring.limitAngles[i*2+1];
00122             bloc=true;
00123         }
00124     }
00125     //--
00126 
00127     //compute stiffnesses components
00128     Vector kst( spring.freeMovements[0]==0?spring.hardStiffnessTrans:spring.softStiffnessTrans, spring.freeMovements[1]==0?spring.hardStiffnessTrans:spring.softStiffnessTrans, spring.freeMovements[2]==0?spring.hardStiffnessTrans:spring.softStiffnessTrans);
00129     Vector ksrH( spring.freeMovements[3]!=0?(Real)0.0:spring.hardStiffnessRot, spring.freeMovements[4]!=0?(Real)0.0:spring.hardStiffnessRot, spring.freeMovements[5]!=0?(Real)0.0:spring.hardStiffnessRot);
00130     Vector ksrS( spring.freeMovements[3]==0?(Real)0.0:spring.softStiffnessRot, spring.freeMovements[4]==0?(Real)0.0:spring.softStiffnessRot, spring.freeMovements[5]==0?(Real)0.0:spring.softStiffnessRot);
00131 
00132     //compute directional force (relative translation is expressed in world coordinates)
00133     Vector fT0 = Mr01 * (kst.linearProduct(Mr10 * Mp1p2.getCenter())) + damping.linearProduct(Vp1p2.getVCenter());
00134     //compute rotational force (relative orientation is expressed in p1)
00135     Vector fR0 = Mr01 * MRLT * ( ksrH.linearProduct(spring.extraTorsion.toEulerVector())) + damping.linearProduct(Vp1p2.getVOrientation());
00136     fR0 += Mr01 * ( ksrS.linearProduct(spring.lawfulTorsion.toEulerVector())) + damping.linearProduct(Vp1p2.getVOrientation());
00137     //--
00138     if(bloc)
00139         fR0 += Mr01 * ( spring.bloquage.linearProduct( dTorsion)) + damping.linearProduct(Vp1p2.getVOrientation());
00140 
00141     const Deriv force(fT0, fR0 );
00142     //affect forces
00143     f1[a] += force;
00144     f2[b] -= force;
00145 
00146 }
00147 
00148 template<class DataTypes>
00149 void JointSpringForceField<DataTypes>::addSpringDForce(VecDeriv& f1, const VecDeriv& dx1, VecDeriv& f2, const VecDeriv& dx2, int , /*const*/ Spring& spring)
00150 {
00151     const int a = spring.m1;
00152     const int b = spring.m2;
00153     const Deriv Mdx1dx2 = dx2[b]-dx1[a];
00154 
00155     Mat Mr01, Mr10;
00156     springRef[a].writeRotationMatrix(Mr01);
00157     invertMatrix(Mr10, Mr01);
00158 
00159     Vector kst( spring.freeMovements[0]==0?spring.hardStiffnessTrans:spring.softStiffnessTrans, spring.freeMovements[1]==0?spring.hardStiffnessTrans:spring.softStiffnessTrans, spring.freeMovements[2]==0?spring.hardStiffnessTrans:spring.softStiffnessTrans);
00160     Vector ksr( spring.freeMovements[3]==0?spring.hardStiffnessRot:spring.softStiffnessRot+spring.bloquage[0], spring.freeMovements[4]==0?spring.hardStiffnessRot:spring.softStiffnessRot+spring.bloquage[1], spring.freeMovements[5]==0?spring.hardStiffnessRot:spring.softStiffnessRot+spring.bloquage[2]);
00161     
00162     //compute directional force
00163     Vector df0 = Mr01 * (kst.linearProduct(Mr10*Mdx1dx2.getVCenter() ));
00164     //compute rotational force
00165     Vector dR0 = Mr01 * (ksr.linearProduct(Mr10* Mdx1dx2.getVOrientation()));
00166 
00167     const Deriv dforce(df0,dR0);
00168 
00169     f1[a]+=dforce;
00170     f2[b]-=dforce;
00171 
00172     //--
00173     spring.bloquage=Vector();
00174 }
00175 
00176 template<class DataTypes>
00177 void JointSpringForceField<DataTypes>::addForce(VecDeriv& f1, VecDeriv& f2, const VecCoord& x1, const VecCoord& x2, const VecDeriv& v1, const VecDeriv& v2)
00178 {
00179     helper::vector<Spring>& springs = *this->springs.beginEdit();
00180 
00181     springRef.resize(x1.size());
00182     
00183     f1.resize(x1.size());
00184     f2.resize(x2.size());
00185     m_potentialEnergy = 0;
00186     for (unsigned int i=0; i<springs.size(); i++)
00187     {
00188         this->addSpringForce(m_potentialEnergy,f1,x1,v1,f2,x2,v2, i, springs[i]);
00189     }
00190     this->springs.endEdit();
00191 }
00192 
00193 template<class DataTypes>
00194 void JointSpringForceField<DataTypes>::addDForce(VecDeriv& df1, VecDeriv& df2, const VecDeriv& dx1, const VecDeriv& dx2)
00195 {
00196     df1.resize(dx1.size());
00197     df2.resize(dx2.size());
00198 
00199     //const helper::vector<Spring>& springs = this->springs.getValue();
00200     helper::vector<Spring>& springs = *this->springs.beginEdit();
00201     for (unsigned int i=0; i<springs.size(); i++) {
00202         this->addSpringDForce(df1,dx1,df2,dx2, i, springs[i]);
00203     }
00204     this->springs.endEdit();
00205 }
00206 
00207 template<class DataTypes>
00208 void JointSpringForceField<DataTypes>::draw()
00209 {
00210     if (!((this->mstate1 == this->mstate2)?getContext()->getShowForceFields():getContext()->getShowInteractionForceFields())) return;
00211     const VecCoord& p1 = *this->mstate1->getX();
00212     const VecCoord& p2 = *this->mstate2->getX();
00213 
00214     glDisable(GL_LIGHTING);
00215     bool external = (this->mstate1!=this->mstate2);
00216     const helper::vector<Spring>& springs = this->springs.getValue();
00217     
00218     for (unsigned int i=0; i<springs.size(); i++)
00219     {
00220         Real d = (p2[springs[i].m2]-p1[springs[i].m1]).getCenter().norm();
00221         if (external)
00222         {
00223             if (d<springs[i].initTrans.norm()*0.9999)
00224                 glColor4f(1,0,0,1);
00225             else
00226                 glColor4f(0,1,0,1);
00227         }
00228         else
00229         {
00230             if (d<springs[i].initTrans.norm()*0.9999)
00231                 glColor4f(1,0.5f,0,1);
00232             else
00233                 glColor4f(0,1,0.5f,1);
00234         }
00235         glBegin(GL_LINES);
00236         helper::gl::glVertexT(p1[springs[i].m1].getCenter());
00237         helper::gl::glVertexT(p2[springs[i].m2].getCenter());
00238         glEnd();
00239 
00240         if(springs[i].freeMovements[3] == 1){
00241             helper::gl::Cylinder::draw(p1[springs[i].m1].getCenter(), p1[springs[i].m1].getOrientation(), Vector(1,0,0));
00242         }
00243         if(springs[i].freeMovements[4] == 1){
00244             helper::gl::Cylinder::draw(p1[springs[i].m1].getCenter(), p1[springs[i].m1].getOrientation(), Vector(0,1,0));
00245         }
00246         if(springs[i].freeMovements[5] == 1){
00247             helper::gl::Cylinder::draw(p1[springs[i].m1].getCenter(), p1[springs[i].m1].getOrientation(), Vector(0,0,1));
00248         }
00249 
00250         //---debugging
00251         if (showLawfulTorsion.getValue())
00252             helper::gl::Axis::draw(p1[springs[i].m1].getCenter(), p1[springs[i].m1].getOrientation()*springs[i].lawfulTorsion, 0.5);
00253         if (showExtraTorsion.getValue())
00254             helper::gl::Axis::draw(p1[springs[i].m1].getCenter(), p1[springs[i].m1].getOrientation()*springs[i].extraTorsion, 0.5);
00255     }
00256 
00257 }
00258 
00259 } // namespace forcefield
00260 
00261 } // namespace component
00262 
00263 } // namespace sofa
00264 
00265 #endif
00266 

Generated on Sun Nov 23 02:59:43 2008 for Sofa by  doxygen 1.5.7.1