worldsim/src/phyballandsocket.cpp

00001 /********************************************************************************
00002  *  WorldSim -- library for robot simulations                                   *
00003  *  Copyright (C) 2008-2011 Gianluca Massera <emmegian@yahoo.it>                *
00004  *                                                                              *
00005  *  This program is free software; you can redistribute it and/or modify        *
00006  *  it under the terms of the GNU General Public License as published by        *
00007  *  the Free Software Foundation; either version 2 of the License, or           *
00008  *  (at your option) any later version.                                         *
00009  *                                                                              *
00010  *  This program is distributed in the hope that it will be useful,             *
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of              *
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               *
00013  *  GNU General Public License for more details.                                *
00014  *                                                                              *
00015  *  You should have received a copy of the GNU General Public License           *
00016  *  along with this program; if not, write to the Free Software                 *
00017  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA  *
00018  ********************************************************************************/
00019 
00020 #include "phyballandsocket.h"
00021 #include "private/phyjointprivate.h"
00022 #include "private/phyobjectprivate.h"
00023 #include "private/worldprivate.h"
00024 
00025 namespace farsa {
00026 
00027 PhyBallAndSocket::PhyBallAndSocket( const wVector& centre, PhyObject* parent, PhyObject* child, bool cp )
00028     : PhyJoint( parent, child ) {
00029     dofv = 0;
00030     //--- calculate the localMatrixParent
00031     localMatrixParent.x_ax = wVector::X();
00032     localMatrixParent.y_ax = wVector::Y();
00033     localMatrixParent.z_ax = wVector::Z();
00034     localMatrixParent.w_pos = centre;
00035     localMatrixParent.sanitifize();
00036     
00037     //--- calculate the local matrix respect to child object
00038     if ( parent ) {
00039         globalMatrixParent = localMatrixParent * parent->matrix();
00040     } else {
00041         globalMatrixParent = localMatrixParent;
00042     }
00043     localMatrixChild = globalMatrixParent * child->matrix().inverse();
00044     
00045     if ( !localMatrixParent.sanityCheck() ) {
00046         qWarning( "Sanity Check Failed" );
00047     }
00048     if ( !localMatrixChild.sanityCheck() ) {
00049         qWarning( "Sanity Check Failed" );
00050     }
00051     
00052     if ( cp ) {
00053         createPrivateJoint();
00054     }
00055 }
00056 
00057 wVector PhyBallAndSocket::centre() const {
00058     //--- calculate global matrix if necessary
00059     if ( parent() ) {
00060         globalMatrixParent = localMatrixParent * parent()->matrix();
00061     }
00062     return globalMatrixParent.w_pos;
00063 };
00064 
00065 void PhyBallAndSocket::createPrivateJoint() {
00066 #ifdef WORLDSIM_USE_NEWTON
00067     priv->joint = NewtonConstraintCreateUserJoint( worldpriv->world, 6, PhyJointPrivate::userBilateralHandler, 0, priv->child, priv->parent );
00068     NewtonJointSetUserData( priv->joint, this );
00069 #endif
00070 }
00071 
00072 void PhyBallAndSocket::updateJointInfo() {
00073     //--- calculate the global matrices
00074     //--- if parent doesn't exist, then globalMatrixParent and localMatrixParent coincide and
00075     //--- there is no need to re-assign it because it was already done in constructor
00076     if ( parent() ) {
00077         globalMatrixParent = localMatrixParent * parent()->matrix();
00078     }
00079     globalMatrixChild = localMatrixChild * child()->matrix();
00080 
00081     if ( !globalMatrixParent.sanityCheck() ) {
00082         qWarning( "Sanity Check Failed" );
00083     }
00084     if ( !globalMatrixChild.sanityCheck() ) {
00085         qWarning( "Sanity Check Failed" );
00086     }
00087 }
00088 
00089 void PhyBallAndSocket::updateJoint( real timestep ) {
00090     //--- calculate the global matrices
00091     //--- if parent doesn't exist, then globalMatrixParent and localMatrixParent coincide and
00092     //--- there is no need to re-assign it because it was already done in constructor
00093     if ( parent() ) {
00094         globalMatrixParent = localMatrixParent * parent()->matrix();
00095     }
00096     globalMatrixChild = localMatrixChild * child()->matrix();
00097 
00098     if ( !globalMatrixParent.sanityCheck() ) {
00099         qWarning( "Sanity Check Failed" );
00100     }
00101     if ( !globalMatrixChild.sanityCheck() ) {
00102         qWarning( "Sanity Check Failed" );
00103     }
00104 
00105 #ifdef WORLDSIM_USE_NEWTON
00106     UNUSED_PARAM( timestep );
00107     //--- Restrict the movement on the centre of the joint along all tree orthonormal direction
00108     NewtonUserJointAddLinearRow( priv->joint, &globalMatrixChild.w_pos[0], &globalMatrixParent.w_pos[0], &globalMatrixParent.x_ax[0] );
00109     NewtonUserJointSetRowStiffness( priv->joint, 1.0f );
00110     NewtonUserJointAddLinearRow( priv->joint, &globalMatrixChild.w_pos[0], &globalMatrixParent.w_pos[0], &globalMatrixParent.y_ax[0] );
00111     NewtonUserJointSetRowStiffness( priv->joint, 1.0f );
00112     NewtonUserJointAddLinearRow( priv->joint, &globalMatrixChild.w_pos[0], &globalMatrixParent.w_pos[0], &globalMatrixParent.z_ax[0] );
00113     NewtonUserJointSetRowStiffness( priv->joint, 1.0f );
00114 
00115 #endif
00116 
00117 }
00118 
00119 } // end namespace farsa