00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "physuspension.h"
00021 #include "private/phyjointprivate.h"
00022 #include "private/phyobjectprivate.h"
00023 #include "private/worldprivate.h"
00024
00025
00026 #ifdef FARSA_WIN
00027 #include <float.h>
00028 #define isnan(x) _isnan(x)
00029 #endif
00030
00031 namespace farsa {
00032
00033 PhySuspension::PhySuspension( const wVector& axis, const wVector& centre, const wVector& x_axis, PhyObject* parent, PhyObject* child, bool cp )
00034 : PhyJoint( parent, child ) {
00035 dof = new PhyDOF( this, axis, centre, false );
00036 dofsv << dof;
00037 dofv = 1;
00038
00039
00040 localMatrixParent.x_ax = x_axis;
00041 localMatrixParent.y_ax = axis * x_axis;
00042 localMatrixParent.z_ax = axis;
00043 localMatrixParent.w_pos = centre;
00044 localMatrixParent.sanitifize();
00045
00046
00047 if ( parent ) {
00048 globalMatrixParent = localMatrixParent * parent->matrix();
00049 } else {
00050 globalMatrixParent = localMatrixParent;
00051 }
00052 localMatrixChild = globalMatrixParent * child->matrix().inverse();
00053 if ( parent ) {
00054 globalMatrixParent = localMatrixParent * parent->matrix();
00055 } else {
00056 globalMatrixParent = localMatrixParent;
00057 }
00058
00059 dof->setAxis( globalMatrixParent.z_ax );
00060 dof->setXAxis( globalMatrixParent.x_ax );
00061 dof->setYAxis( globalMatrixParent.y_ax );
00062 dof->setCentre( globalMatrixParent.w_pos );
00063
00064 if ( !localMatrixParent.sanityCheck() ) {
00065 qWarning( "Sanity Check Failed on localMatrixParent" );
00066 }
00067 if ( !localMatrixChild.sanityCheck() ) {
00068 qWarning( "Sanity Check Failed on localMatrixChild" );
00069 }
00070
00071 if ( cp ) {
00072 createPrivateJoint();
00073 }
00074 }
00075
00076 wVector PhySuspension::centre() const {
00077
00078 if ( parent() ) {
00079 globalMatrixParent = localMatrixParent * parent()->matrix();
00080 }
00081 return globalMatrixParent.w_pos;
00082 }
00083
00084 void PhySuspension::createPrivateJoint() {
00085 #ifdef WORLDSIM_USE_NEWTON
00086 priv->joint = NewtonConstraintCreateUserJoint( worldpriv->world, 6, PhyJointPrivate::userBilateralHandler, 0, priv->child, priv->parent );
00087 NewtonJointSetUserData( priv->joint, this );
00088 #endif
00089 }
00090
00091 void PhySuspension::updateJointInfo() {
00092
00093
00094
00095 if ( parent() ) {
00096 globalMatrixParent = localMatrixParent * parent()->matrix();
00097 }
00098 globalMatrixChild = localMatrixChild * child()->matrix();
00099
00100 if ( !globalMatrixParent.sanityCheck() ) {
00101 qWarning( "Sanity Check Failed on globalMatrixParent" );
00102 }
00103 if ( !globalMatrixChild.sanityCheck() ) {
00104 qWarning( "Sanity Check Failed on globalMatrixChild" );
00105 }
00106
00107 dof->setAxis( globalMatrixParent.z_ax );
00108 dof->setXAxis( globalMatrixParent.x_ax );
00109 dof->setYAxis( globalMatrixParent.y_ax );
00110 dof->setCentre( globalMatrixParent.w_pos );
00111
00112 PhyDOF* dof = dofsv[0];
00113
00114
00115 real sinAngle = (globalMatrixParent.x_ax * globalMatrixChild.x_ax) % globalMatrixChild.z_ax;
00116 real cosAngle = globalMatrixChild.x_ax % globalMatrixParent.x_ax;
00117 real angle = atan2( sinAngle, cosAngle );
00118 real vel;
00119
00120
00121
00122 if (enabled) {
00123
00124
00125
00126
00127 wVector omegaParent, omegaChild;
00128 #ifdef WORLDSIM_USE_NEWTON
00129 if ( parent() ) {
00130 NewtonBodyGetOmega( priv->parent, &omegaParent[0] );
00131 } else {
00132 omegaParent = wVector(0, 0, 0);
00133 }
00134 NewtonBodyGetOmega( priv->child, &omegaChild[0] );
00135 #endif
00136 real velP = omegaParent % globalMatrixChild.z_ax;
00137 real velC = omegaChild % globalMatrixChild.z_ax;
00138 vel = velC - velP;
00139
00140 } else {
00141 vel = (angle - dof->position()) / (world()->timeStep());
00142 }
00143 dof->setPosition( angle );
00144 dof->setVelocity( vel );
00145 }
00146
00147 void PhySuspension::updateJoint( real timestep ) {
00148
00149 if (!enabled) {
00150 return;
00151 }
00152
00153
00154 updateJointInfo();
00155
00156 const real angle = dof->position();
00157 const real vel = dof->velocity();
00158
00159 #ifdef WORLDSIM_USE_NEWTON
00160
00161 NewtonUserJointAddLinearRow( priv->joint, &globalMatrixChild.w_pos[0], &globalMatrixParent.w_pos[0], &globalMatrixParent.x_ax[0] );
00162 NewtonUserJointSetRowStiffness( priv->joint, 0.98f );
00163
00164 NewtonUserJointAddLinearRow( priv->joint, &globalMatrixChild.w_pos[0], &globalMatrixParent.w_pos[0], &globalMatrixParent.y_ax[0] );
00165 NewtonUserJointSetRowStiffness( priv->joint, 1.0f );
00166 NewtonUserJointAddLinearRow( priv->joint, &globalMatrixChild.w_pos[0], &globalMatrixParent.w_pos[0], &globalMatrixParent.z_ax[0] );
00167 NewtonUserJointSetRowStiffness( priv->joint, 1.0f );
00168
00169
00170
00171
00172
00173
00174
00175 real len = 5000.0;
00176 wVector qChild( globalMatrixChild.w_pos + globalMatrixChild.z_ax.scale(len) );
00177 wVector qParent( globalMatrixParent.w_pos + globalMatrixParent.z_ax.scale(len) );
00178 NewtonUserJointAddLinearRow( priv->joint, &qChild[0], &qParent[0], &globalMatrixParent.x_ax[0] );
00179 NewtonUserJointSetRowStiffness( priv->joint, 1.0 );
00180 NewtonUserJointAddLinearRow( priv->joint, &qChild[0], &qParent[0], &globalMatrixParent.y_ax[0] );
00181 NewtonUserJointSetRowStiffness( priv->joint, 1.0 );
00182
00183
00184
00185
00186
00187
00188 if ( dof->motion() == PhyDOF::vel ) {
00189
00190 real accel = 0.8f*( dof->desiredVelocity() - vel ) / ( timestep );
00191 NewtonUserJointAddAngularRow( priv->joint, 0.0f, &globalMatrixParent.z_ax[0] );
00192 NewtonUserJointSetRowAcceleration( priv->joint, accel );
00193 NewtonUserJointSetRowStiffness( priv->joint, dof->stiffness() );
00194 }
00195 #endif
00196
00197 }
00198
00199 }