worldsim/src/phyfixed.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 "phyfixed.h"
00021 #include "private/phyjointprivate.h"
00022 #include "private/phyobjectprivate.h"
00023 #include "private/worldprivate.h"
00024 
00025 namespace farsa {
00026 
00027 PhyFixed::PhyFixed( 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 = wVector(0, 0, 0);
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 PhyFixed::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 PhyFixed::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 PhyFixed::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 PhyFixed::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     //--- In order to constraint the rotation about X and Y axis of the joint
00116     //--- we use LinearRow (that are stronger) getting a point far from objects along
00117     //--- the Z axis. Doing this if the two object rotates about X or Y axes then
00118     //--- the difference between qChild and qParent augments and then Newton Engine will apply
00119     //--- a corresponding force (that applyied outside the centre of the object will become
00120     //--- a torque) that will blocks any rotation about X and Y axis
00121     real len = 5000.0;
00122     wVector qChild( globalMatrixChild.w_pos + globalMatrixChild.z_ax.scale(len) );
00123     wVector qParent( globalMatrixParent.w_pos + globalMatrixParent.z_ax.scale(len) );
00124     NewtonUserJointAddLinearRow( priv->joint, &qChild[0], &qParent[0], &globalMatrixParent.x_ax[0] );
00125     NewtonUserJointSetRowStiffness( priv->joint, 1.0 );
00126     NewtonUserJointAddLinearRow( priv->joint, &qChild[0], &qParent[0], &globalMatrixParent.y_ax[0] );
00127     NewtonUserJointSetRowStiffness( priv->joint, 1.0 );
00128 
00129     NewtonUserJointAddAngularRow( priv->joint, 0.0f, &globalMatrixParent.z_ax[0] );
00130     NewtonUserJointSetRowStiffness( priv->joint, 1.0f );
00131 
00132     //--- In order to do the same with third axis (Z), I need others point along different axis
00133 /*  qChild = wVector( globalMatrixChild.w_pos + globalMatrixChild.y_ax.scale(len) );
00134     qParent = wVector( globalMatrixParent.w_pos + globalMatrixParent.y_ax.scale(len) );
00135     NewtonUserJointAddLinearRow( priv->joint, &qChild[0], &qParent[0], &globalMatrixParent.z_ax[0] );
00136     NewtonUserJointSetRowStiffness( priv->joint, 1.0 );*/
00137 #endif
00138 
00139 }
00140 
00141 } // end namespace farsa