00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "phyhinge.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 void PhyHinge::construct( const wVector& axis, const wVector& centre, real startAngle, PhyObject* parent, PhyObject* child, bool cp ) {
00034 dof = new PhyDOF( this, axis, centre, false );
00035 dofsv << dof;
00036 dofv = 1;
00037
00038
00039 localMatrixParent = wMatrix::grammSchmidt(axis);
00040
00041 wVector start = centre;
00042 wVector end = child->matrix().w_pos;
00043 if ( parent ) {
00044 start -= parent->matrix().w_pos;
00045 }
00046 wVector newx = (start-end).normalize();
00047 if ( isnan(newx[0]) || isnan(newx[1]) || isnan(newx[2]) ) {
00048
00049
00050 } else {
00051
00052
00053
00054 real sinAngle = (newx * localMatrixParent.x_ax) % localMatrixParent.z_ax;
00055 real cosAngle = newx % localMatrixParent.x_ax;
00056 real angle = atan2( sinAngle, cosAngle );
00057 wQuaternion ql( axis, angle );
00058 localMatrixParent = localMatrixParent * wMatrix( ql, wVector(0,0,0) );
00059 }
00060 localMatrixParent.w_pos = centre;
00061 localMatrixParent.sanitifize();
00062
00063
00064 if ( parent ) {
00065 globalMatrixParent = localMatrixParent * parent->matrix();
00066 } else {
00067 globalMatrixParent = localMatrixParent;
00068 }
00069 localMatrixChild = globalMatrixParent * child->matrix().inverse();
00070
00071 localMatrixParent.w_pos = wVector(0,0,0);
00072
00073
00074
00075 wQuaternion q( axis, startAngle );
00076 localMatrixParent = localMatrixParent * wMatrix( q, wVector(0,0,0) );
00077 localMatrixParent.w_pos = centre;
00078 if ( parent ) {
00079 globalMatrixParent = localMatrixParent * parent->matrix();
00080 } else {
00081 globalMatrixParent = localMatrixParent;
00082 }
00083
00084 dof->setAxis( globalMatrixParent.z_ax );
00085 dof->setXAxis( globalMatrixParent.x_ax );
00086 dof->setYAxis( globalMatrixParent.y_ax );
00087 dof->setCentre( globalMatrixParent.w_pos );
00088
00089 if ( !localMatrixParent.sanityCheck() ) {
00090 qWarning( "Sanity Check Failed on localMatrixParent" );
00091 }
00092 if ( !localMatrixChild.sanityCheck() ) {
00093 qWarning( "Sanity Check Failed on localMatrixChild" );
00094 }
00095
00096 if ( cp ) {
00097 createPrivateJoint();
00098 }
00099 }
00100
00101 PhyHinge::PhyHinge( const wVector& axis, const wVector& centre, real startAngle, PhyObject* parent, PhyObject* child, bool cp )
00102 : PhyJoint( parent, child ) {
00103 construct( axis, centre, startAngle, parent, child, cp );
00104 }
00105
00106 PhyHinge::PhyHinge( const wVector& axis, const wVector& centre, PhyObject* parent, PhyObject* child, bool cp )
00107 : PhyJoint( parent, child ) {
00108 construct( axis, centre, 0, parent, child, cp );
00109 }
00110
00111 PhyHinge::PhyHinge( const wVector& axis, real startAngle, PhyObject* parent, PhyObject* child, bool cp )
00112 : PhyJoint( parent, child ) {
00113 construct( axis, wVector(0,0,0), startAngle, parent, child, cp );
00114 }
00115
00116 PhyHinge::PhyHinge( const wVector& axis, PhyObject* parent, PhyObject* child, bool cp )
00117 : PhyJoint( parent, child ) {
00118 construct( axis, wVector(0,0,0), 0, parent, child, cp );
00119 }
00120
00121 PhyHinge::PhyHinge( const wVector& axis, const wVector& centre, const wVector& x_axis, PhyObject* parent, PhyObject* child, bool cp )
00122 : PhyJoint( parent, child ) {
00123 dof = new PhyDOF( this, axis, centre, false );
00124 dofsv << dof;
00125 dofv = 1;
00126
00127
00128 localMatrixParent.x_ax = x_axis;
00129 localMatrixParent.y_ax = axis * x_axis;
00130 localMatrixParent.z_ax = axis;
00131 localMatrixParent.w_pos = centre;
00132 localMatrixParent.sanitifize();
00133
00134
00135 if ( parent ) {
00136 globalMatrixParent = localMatrixParent * parent->matrix();
00137 } else {
00138 globalMatrixParent = localMatrixParent;
00139 }
00140 localMatrixChild = globalMatrixParent * child->matrix().inverse();
00141 if ( parent ) {
00142 globalMatrixParent = localMatrixParent * parent->matrix();
00143 } else {
00144 globalMatrixParent = localMatrixParent;
00145 }
00146
00147 dof->setAxis( globalMatrixParent.z_ax );
00148 dof->setXAxis( globalMatrixParent.x_ax );
00149 dof->setYAxis( globalMatrixParent.y_ax );
00150 dof->setCentre( globalMatrixParent.w_pos );
00151
00152 if ( !localMatrixParent.sanityCheck() ) {
00153 qWarning( "Sanity Check Failed on localMatrixParent" );
00154 }
00155 if ( !localMatrixChild.sanityCheck() ) {
00156 qWarning( "Sanity Check Failed on localMatrixChild" );
00157 }
00158
00159 if ( cp ) {
00160 createPrivateJoint();
00161 }
00162 }
00163
00164 wVector PhyHinge::centre() const {
00165
00166 if ( parent() ) {
00167 globalMatrixParent = localMatrixParent * parent()->matrix();
00168 }
00169 return globalMatrixParent.w_pos;
00170 }
00171
00172 void PhyHinge::createPrivateJoint() {
00173 #ifdef WORLDSIM_USE_NEWTON
00174 priv->joint = NewtonConstraintCreateUserJoint( worldpriv->world, 6, PhyJointPrivate::userBilateralHandler, 0, priv->child, priv->parent );
00175 NewtonJointSetUserData( priv->joint, this );
00176 #endif
00177 }
00178
00179 void PhyHinge::updateJointInfo() {
00180
00181
00182
00183 if ( parent() ) {
00184 globalMatrixParent = localMatrixParent * parent()->matrix();
00185 }
00186 globalMatrixChild = localMatrixChild * child()->matrix();
00187
00188 if ( !globalMatrixParent.sanityCheck() ) {
00189 qWarning( "Sanity Check Failed on globalMatrixParent" );
00190 }
00191 if ( !globalMatrixChild.sanityCheck() ) {
00192 qWarning( "Sanity Check Failed on globalMatrixChild" );
00193 }
00194
00195 dof->setAxis( globalMatrixParent.z_ax );
00196 dof->setXAxis( globalMatrixParent.x_ax );
00197 dof->setYAxis( globalMatrixParent.y_ax );
00198 dof->setCentre( globalMatrixParent.w_pos );
00199
00200 PhyDOF* dof = dofsv[0];
00201
00202
00203 real sinAngle = (globalMatrixParent.x_ax * globalMatrixChild.x_ax) % globalMatrixChild.z_ax;
00204 real cosAngle = globalMatrixChild.x_ax % globalMatrixParent.x_ax;
00205 real angle = atan2( sinAngle, cosAngle );
00206 real vel;
00207
00208
00209
00210 if (enabled) {
00211
00212
00213
00214
00215 wVector omegaParent, omegaChild;
00216 #ifdef WORLDSIM_USE_NEWTON
00217 if ( parent() ) {
00218 NewtonBodyGetOmega( priv->parent, &omegaParent[0] );
00219 } else {
00220 omegaParent = wVector(0, 0, 0);
00221 }
00222 NewtonBodyGetOmega( priv->child, &omegaChild[0] );
00223 #endif
00224 real velP = omegaParent % globalMatrixChild.z_ax;
00225 real velC = omegaChild % globalMatrixChild.z_ax;
00226 vel = velC - velP;
00227
00228 } else {
00229 vel = (angle - dof->position()) / (world()->timeStep());
00230 }
00231 dof->setPosition( angle );
00232 dof->setVelocity( vel );
00233 }
00234
00235 void PhyHinge::updateJoint( real timestep ) {
00236
00237 if (!enabled) {
00238 return;
00239 }
00240
00241
00242 updateJointInfo();
00243
00244 const real angle = dof->position();
00245 const real vel = dof->velocity();
00246
00247 #ifdef WORLDSIM_USE_NEWTON
00248
00249 NewtonUserJointAddLinearRow( priv->joint, &globalMatrixChild.w_pos[0], &globalMatrixParent.w_pos[0], &globalMatrixChild.x_ax[0] );
00250 NewtonUserJointSetRowStiffness( priv->joint, 1.0 );
00251 NewtonUserJointAddLinearRow( priv->joint, &globalMatrixChild.w_pos[0], &globalMatrixParent.w_pos[0], &globalMatrixChild.y_ax[0] );
00252 NewtonUserJointSetRowStiffness( priv->joint, 1.0 );
00253 NewtonUserJointAddLinearRow( priv->joint, &globalMatrixChild.w_pos[0], &globalMatrixParent.w_pos[0], &globalMatrixChild.z_ax[0] );
00254 NewtonUserJointSetRowStiffness( priv->joint, 1.0 );
00255
00256
00257
00258
00259
00260
00261
00262 real len = 50000.0;
00263 wVector qChild( globalMatrixChild.w_pos + globalMatrixChild.z_ax.scale(len) );
00264 wVector qParent( globalMatrixParent.w_pos + globalMatrixParent.z_ax.scale(len) );
00265 NewtonUserJointAddLinearRow( priv->joint, &qChild[0], &qParent[0], &globalMatrixChild.x_ax[0] );
00266 NewtonUserJointSetRowStiffness( priv->joint, 1.0 );
00267 NewtonUserJointAddLinearRow( priv->joint, &qChild[0], &qParent[0], &globalMatrixChild.y_ax[0] );
00268 NewtonUserJointSetRowStiffness( priv->joint, 1.0 );
00269
00270 if ( dof->isLimited() ) {
00271 real lolimit;
00272 real hilimit;
00273 dof->limits( lolimit, hilimit );
00274 if ( angle < lolimit ) {
00275 real relAngle = lolimit - angle;
00276
00277
00278 NewtonUserJointAddAngularRow( priv->joint, relAngle, &globalMatrixChild.z_ax[0] );
00279 NewtonUserJointSetRowStiffness( priv->joint, dof->stiffness() );
00280 NewtonUserJointSetRowSpringDamperAcceleration( priv->joint, 50000.0, 100 );
00281
00282 NewtonUserJointSetRowMinimumFriction( priv->joint, 0.0 );
00283 return;
00284 } else if ( angle > hilimit ) {
00285 real relAngle = hilimit - angle;
00286
00287
00288 NewtonUserJointAddAngularRow( priv->joint, relAngle, &globalMatrixChild.z_ax[0] );
00289 NewtonUserJointSetRowStiffness( priv->joint, dof->stiffness() );
00290 NewtonUserJointSetRowSpringDamperAcceleration( priv->joint, 50000.0, 100 );
00291
00292 NewtonUserJointSetRowMaximumFriction( priv->joint, 0.0 );
00293 return;
00294 }
00295 }
00296
00297
00298
00299 real force, accel, wishangle, wishvel, sign;
00300 switch( dof->motion() ) {
00301 case PhyDOF::force:
00302
00303
00304
00305
00306 force = fabs( dof->appliedForce() );
00307 accel = 2.0*dof->appliedForce();
00308 NewtonUserJointAddAngularRow( priv->joint, 0.0, &globalMatrixChild.z_ax[0] );
00309 NewtonUserJointSetRowMinimumFriction( priv->joint, -force );
00310 NewtonUserJointSetRowMaximumFriction( priv->joint, +force );
00311 NewtonUserJointSetRowAcceleration( priv->joint, accel );
00312 NewtonUserJointSetRowStiffness( priv->joint, dof->stiffness() );
00313 break;
00314 case PhyDOF::vel:
00315
00316 accel = 0.8*( dof->desiredVelocity() - vel ) / ( timestep );
00317 wishangle = (dof->desiredVelocity()*timestep);
00318 NewtonUserJointAddAngularRow( priv->joint, wishangle, &globalMatrixChild.z_ax[0] );
00319 NewtonUserJointSetRowAcceleration( priv->joint, accel );
00320 NewtonUserJointSetRowStiffness( priv->joint, dof->stiffness() );
00321 break;
00322 case PhyDOF::off:
00323 case PhyDOF::pos:
00324 wishangle = dof->desiredPosition() - angle;
00325 wishvel = wishangle / timestep;
00326 if ( fabs(wishvel) > dof->maxVelocity() ) {
00327 sign = (wishvel<0) ? -1.0 : +1.0;
00328 wishvel = sign*dof->maxVelocity();
00329 }
00330 accel = 0.8*( wishvel - vel ) / ( timestep );
00331 NewtonUserJointAddAngularRow( priv->joint, wishangle, &globalMatrixChild.z_ax[0] );
00332 NewtonUserJointSetRowAcceleration( priv->joint, accel );
00333 NewtonUserJointSetRowStiffness( priv->joint, dof->stiffness() );
00334
00335
00336
00337 break;
00338 default:
00339 break;
00340 }
00341 #endif
00342
00343 }
00344
00345 }