physuspension.cpp
1 /********************************************************************************
2  * WorldSim -- library for robot simulations *
3  * Copyright (C) 2008-2013 Gianluca Massera <emmegian@yahoo.it> *
4  * *
5  * This program is free software; you can redistribute it and/or modify *
6  * it under the terms of the GNU General Public License as published by *
7  * the Free Software Foundation; either version 2 of the License, or *
8  * (at your option) any later version. *
9  * *
10  * This program is distributed in the hope that it will be useful, *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13  * GNU General Public License for more details. *
14  * *
15  * You should have received a copy of the GNU General Public License *
16  * along with this program; if not, write to the Free Software *
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *
18  ********************************************************************************/
19 
20 #include "physuspension.h"
21 #include "mathutils.h"
22 #include "private/phyjointprivate.h"
23 #include "private/phyobjectprivate.h"
24 #include "private/worldprivate.h"
25 
26 namespace farsa {
27 
28 PhySuspension::PhySuspension( const wVector& axis, const wVector& centre, const wVector& x_axis, PhyObject* parent, PhyObject* child, bool cp )
29  : PhyJoint( parent, child ) {
30  dof = new PhyDOF( this, axis, centre, false );
31  dofsv << dof;
32  dofv = 1;
33  forceOnJoint = wVector(0.0, 0.0, 0.0);
34 
35  //--- calculate the localMatrixParent
36  //--- supposing that axis and x_axis are ortogonals
37  localMatrixParent.x_ax = x_axis;
38  localMatrixParent.y_ax = axis * x_axis;
39  localMatrixParent.z_ax = axis;
40  localMatrixParent.w_pos = centre;
42 
43  //--- calculate the local matrix respect to child object
44  if ( parent ) {
46  } else {
48  }
50  if ( parent ) {
52  } else {
54  }
55 
56  dof->setAxis( globalMatrixParent.z_ax );
57  dof->setXAxis( globalMatrixParent.x_ax );
58  dof->setYAxis( globalMatrixParent.y_ax );
59  dof->setCentre( globalMatrixParent.w_pos );
60 
61  if ( !localMatrixParent.sanityCheck() ) {
62  qWarning( "Sanity Check Failed on localMatrixParent" );
63  }
64  if ( !localMatrixChild.sanityCheck() ) {
65  qWarning( "Sanity Check Failed on localMatrixChild" );
66  }
67 
68  if ( cp ) {
70  }
71 }
72 
74  //--- calculate global matrix if necessary
75  if ( parent() ) {
77  }
78  return globalMatrixParent.w_pos;
79 }
80 
82 {
83  return forceOnJoint;
84 }
85 
87 #ifdef WORLDSIM_USE_NEWTON
88  priv->joint = NewtonConstraintCreateUserJoint( worldpriv->world, 6, PhyJointPrivate::userBilateralHandler, 0, priv->child, priv->parent );
89  NewtonJointSetUserData( priv->joint, this );
90 #endif
91 }
92 
94  //--- calculate the global matrices
95  //--- if parent doesn't exist, then globalMatrixParent and localMatrixParent coincide and
96  //--- there is no need to re-assign it because it was already done in constructor
97  if ( parent() ) {
99  }
101 
102  if ( !globalMatrixParent.sanityCheck() ) {
103  qWarning( "Sanity Check Failed on globalMatrixParent" );
104  }
105  if ( !globalMatrixChild.sanityCheck() ) {
106  qWarning( "Sanity Check Failed on globalMatrixChild" );
107  }
108 
109  dof->setAxis( globalMatrixParent.z_ax );
110  dof->setXAxis( globalMatrixParent.x_ax );
111  dof->setYAxis( globalMatrixParent.y_ax );
112  dof->setCentre( globalMatrixParent.w_pos );
113 
114  PhyDOF* dof = dofsv[0];
115  //--- calculate the rotation assuming the local X axis of joint frame as 0
116  //--- and following the right-hand convention
117  real sinAngle = (globalMatrixParent.x_ax * globalMatrixChild.x_ax) % globalMatrixChild.z_ax;
118  real cosAngle = globalMatrixChild.x_ax % globalMatrixParent.x_ax;
119  real angle = atan2( sinAngle, cosAngle );
120  real vel;
121  // Velocity is computed in two different ways depending on whether the joint is enabled or not:
122  // if it is, we use Newton functions to get the angular velocities (for a better result), otherwise
123  // we revert to computing the difference with the previous position divided by the timestep
124  if (enabled) {
125  //--- the velocity is calculated projecting the angular velocity of objects on the main axis (z_ax)
126  // This code is not general, becuase it is not appliable in the case of parent==NULL
127  // and also return different results respect to the kinematic way
128  // Then [Gianluca] comment it and replaced with the same code used in the kinematic mode
129  wVector omegaParent, omegaChild;
130 #ifdef WORLDSIM_USE_NEWTON
131  if ( parent() ) {
132  NewtonBodyGetOmega( priv->parent, &omegaParent[0] );
133  } else {
134  omegaParent = wVector(0, 0, 0);
135  }
136  NewtonBodyGetOmega( priv->child, &omegaChild[0] );
137 #endif
138  real velP = omegaParent % globalMatrixChild.z_ax;
139  real velC = omegaChild % globalMatrixChild.z_ax;
140  vel = velC - velP;
141  //vel = (angle - dof->position()) / (world()->timeStep());
142  } else {
143  vel = (angle - dof->position()) / (world()->timeStep());
144  }
145  dof->setPosition( angle );
146  dof->setVelocity( vel );
147 }
148 
149 void PhySuspension::updateJoint( real timestep ) {
150  // If the joint is disabled, we don't do anything here
151  if (!enabled) {
152  return;
153  }
154 
155  // Updating the global matrices and the dof
156  updateJointInfo();
157 
158  // const real angle = dof->position();
159  const real vel = dof->velocity();
160 
161 #ifdef WORLDSIM_USE_NEWTON
162  //--- Restrict the movement on the centre of the joint along all tree orthonormal direction
163  NewtonUserJointAddLinearRow( priv->joint, &globalMatrixChild.w_pos[0], &globalMatrixParent.w_pos[0], &globalMatrixParent.x_ax[0] );
164  NewtonUserJointSetRowStiffness( priv->joint, 0.98f );
165  //NewtonUserJointSetRowSpringDamperAcceleration( priv->joint, 20, 10 );
166  NewtonUserJointAddLinearRow( priv->joint, &globalMatrixChild.w_pos[0], &globalMatrixParent.w_pos[0], &globalMatrixParent.y_ax[0] );
167  NewtonUserJointSetRowStiffness( priv->joint, 1.0f );
168  NewtonUserJointAddLinearRow( priv->joint, &globalMatrixChild.w_pos[0], &globalMatrixParent.w_pos[0], &globalMatrixParent.z_ax[0] );
169  NewtonUserJointSetRowStiffness( priv->joint, 1.0f );
170 
171  //--- In order to constraint the rotation about X and Y axis of the joint
172  //--- we use LinearRow (that are stronger) getting a point far from objects along
173  //--- the Z axis. Doing this if the two object rotates about X or Y axes then
174  //--- the difference between qChild and qParent augments and then Newton Engine will apply
175  //--- a corresponding force (that applyied outside the centre of the object will become
176  //--- a torque) that will blocks any rotation about X and Y axis
177  real len = 5000.0;
178  wVector qChild( globalMatrixChild.w_pos + globalMatrixChild.z_ax.scale(len) );
179  wVector qParent( globalMatrixParent.w_pos + globalMatrixParent.z_ax.scale(len) );
180  NewtonUserJointAddLinearRow( priv->joint, &qChild[0], &qParent[0], &globalMatrixParent.x_ax[0] );
181  NewtonUserJointSetRowStiffness( priv->joint, 1.0 );
182  NewtonUserJointAddLinearRow( priv->joint, &qChild[0], &qParent[0], &globalMatrixParent.y_ax[0] );
183  NewtonUserJointSetRowStiffness( priv->joint, 1.0 );
184 // NewtonUserJointAddAngularRow( priv->joint, 0.0f, &globalMatrixParent.x_ax[0] );
185 // NewtonUserJointSetRowStiffness( priv->joint, 1.0f );
186 // NewtonUserJointAddAngularRow( priv->joint, 0.0f, &globalMatrixParent.y_ax[0] );
187 // NewtonUserJointSetRowStiffness( priv->joint, 0.98f );
188 
189  //--- The only motion supported is by velocity
190  if ( dof->motion() == PhyDOF::vel ) {
191  //--- I'm not sure that this implementation is correct
192  real accel = 0.8f*( dof->desiredVelocity() - vel ) / ( timestep );
193  NewtonUserJointAddAngularRow( priv->joint, 0.0f, &globalMatrixParent.z_ax[0] );
194  NewtonUserJointSetRowAcceleration( priv->joint, accel );
195  NewtonUserJointSetRowStiffness( priv->joint, dof->stiffness() );
196  if ( dof->maxForce() > 0.0 ) {
197  NewtonUserJointSetRowMinimumFriction( priv->joint, -dof->maxForce() );
198  NewtonUserJointSetRowMaximumFriction( priv->joint, +dof->maxForce() );
199  }
200  }
201 
202  //--- Retrive forces applied to the joint by the constraints
203  forceOnJoint.x = NewtonUserJointGetRowForce (priv->joint, 0);
204  forceOnJoint.y = NewtonUserJointGetRowForce (priv->joint, 1);
205  forceOnJoint.z = NewtonUserJointGetRowForce (priv->joint, 2);
206 #endif
207 
208 }
209 
210 } // end namespace farsa
virtual wVector getForceOnJoint() const
Returns the force applied to this joint.
int dofv
number of DOF
Definition: phyjoint.h:440
World * world()
Return the World.
Definition: phyjoint.h:412
wMatrix localMatrixParent
Local frame of the joint respect to the parent matrix.
Definition: physuspension.h:73
virtual wVector centre() const
Return the centre of this joint in world coordinate.
wVector forceOnJoint
The force applied to this joint.
Definition: physuspension.h:97
void createPrivateJoint()
Engine encapsulation.
wMatrix inverse() const
calculate the inverse of transformation matrix
Definition: wmatrix.h:258
real velocity() const
return the actual relative velocity of bodies along the axis of rotation/translation ...
Definition: phyjoint.h:145
real position() const
return the actual position of bodies For rotational DOF is the angle of rotation For linear DOF is t...
Definition: phyjoint.h:135
PhyJoint class.
Definition: phyjoint.h:359
const wMatrix & matrix() const
return a reference to the transformation matrix
Definition: wobject.cpp:47
bool sanityCheck()
return true if the transformation matrix is valid
Definition: wmatrix.h:431
QVector< PhyDOF * > dofsv
vector of DOF's joint
Definition: phyjoint.h:434
real timeStep() const
get the time step setted
Definition: world.cpp:342
wMatrix localMatrixChild
Local frame of the joint respect to the child matrix.
Definition: physuspension.h:75
wMatrix globalMatrixChild
Global Matrix respect to Child.
Definition: physuspension.h:93
PhyJointPrivate * priv
Engine encapsulation.
Definition: phyjoint.h:451
void sanitifize()
change the matrix in order to get a valid one that represent the same rotation/translation ...
Definition: wmatrix.h:450
real stiffness() const
return the stiffness
Definition: phyjoint.h:161
virtual PhyObject * parent()
Return the parent object; (NULL means an object attached to static world; see Netwon Documentation) ...
Definition: phyjoint.h:379
wVectorT< false > scale(real s) const
return a new wVectorT with element scaled by s
Definition: wvector.h:305
float real
real maxForce() const
returns the maximum force/torque.
Definition: phyjoint.h:188
real desiredVelocity() const
Return the desired position setted.
Definition: phyjoint.h:108
MotionMode motion() const
return the actual motion mode
Definition: phyjoint.h:113
wMatrix globalMatrixParent
Global Matrix respect to Parent.
Definition: physuspension.h:87
bool enabled
true if is enabled, false otherwise
Definition: phyjoint.h:442
PhyDOF class.
Definition: phyjoint.h:50
virtual void updateJointInfo()
Update the Joint informations (each PhyDOF will be updated)
virtual PhyObject * child()
Return the child object attached to this joint (see Newton Documentation)
Definition: phyjoint.h:371
PhySuspension(const wVector &axis, const wVector &centre, const wVector &x_axis, PhyObject *parent, PhyObject *child, bool cp=true)
Constructor.
PhyObject class.
Definition: phyobject.h:46