Computational Embodied Neuroscience Simulator  1.1
3D simulation library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends
cens_physics.cpp
Go to the documentation of this file.
1 // Computational Embodied Neuroscience Simulator (CENS) Library
2 // Copyright (c) 2010 Francesco Mannella
3 //
4 // cens_physics.cpp
5 // Copyright (c) 2010 Francesco Mannella
6 //
7 // This file is part of CENS library.
8 //
9 // CENS library is free software: you can redistribute it and/or modify
10 // it under the terms of the GNU General Public License as published by
11 // the Free Software Foundation, either version 3 of the License, or
12 // (at your option) any later version.
13 //
14 // CENS library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 // GNU General Public License for more details.
18 //
19 // You should have received a copy of the GNU General Public License
20 // along with CENS library. If not, see <http://www.gnu.org/licenses/>.
21 
22 #include "cens_physics.h"
23 #include "cens_utils.h"
24 
25 namespace cens {
26 
27 
32 
34 
36 
37 
39  m_phDynamicsWorld(0),
40  m_phDefaultContactProcessingThreshold(BT_LARGE_FLOAT),
41  m_phParameterManager(physics_params_filename)
42  {
44  }
45 
47 
49  {
50 
51  //cleanup in the reverse order of creation/initialization
52 
53  //remove the rigidbodies from the dynamics world and delete them
54  for (int i=m_phDynamicsWorld->getNumCollisionObjects()-1; i>=0 ;i--)
55  {
56 
57  btCollisionObject* obj =
58  m_phDynamicsWorld->getCollisionObjectArray()[i];
59  btRigidBody* body = btRigidBody::upcast(obj);
60  if (body && body->getMotionState())
61  {
62  delete body->getMotionState();
63  }
64  m_phDynamicsWorld->removeCollisionObject( obj );
65  delete obj;
66 
67  }
68 
69  // delete dynamic memories
70 
71  for( int i=0; i<m_phTouchSensors.size(); i++) {
72  delete m_phTouchSensors[i];
73  }
74 
75  for( int i=0; i<m_phCollisionShapes.size(); i++) {
76  delete m_phCollisionShapes[i];
77  }
78 
79  delete m_phDynamicsWorld;
80  delete m_phSolver;
81  delete m_phBroadphase;
82  delete m_phDispatcher;
84 
85  }
86 
88 
90  {
91 
93  // PARAMETERS //////////////////////////////////////////////
94 
98 
100  {
101  m_phGravity << 0.0, 0.0, -9.8;
102  m_phStep = 0.05;
103  m_phSubstep = 20;
104 
106  }
108 
110  //the default btDefaultCollisionConfiguration
112  new btSoftBodyRigidBodyCollisionConfiguration();
113 
115  //For parallel processing you can use a
116  //diffent dispatcher (see Extras/BulletMultiThreaded)
117  m_phDispatcher =
118  new btCollisionDispatcher(m_phCollisionConfiguration);
119  m_phSoftBodyWorldInfo.m_dispatcher = m_phDispatcher;
120 
121  m_phBroadphase = new btDbvtBroadphase();
122  m_phSoftBodyWorldInfo.m_broadphase = m_phBroadphase;
123 
125  //For parallel processing you can use a
126  //different solver (see Extras/BulletMultiThreaded)
127  btSequentialImpulseConstraintSolver* sol =
128  new btSequentialImpulseConstraintSolver;
129  m_phSolver = sol;
130 
131  //Initialize the dynamicsWorld
133  new btSoftRigidDynamicsWorld(
136  m_phSolver,
138 
139  // set tick callback
140  //m_phDynamicsWorld->setInternalTickCallback(internalTickCallback);
141 
142  //set gravity
143  m_phDynamicsWorld->getDispatchInfo().m_enableSPU = true;
144  m_phDynamicsWorld->setGravity(
145  btVector3(
146  m_phGravity.x(),
147  m_phGravity.y(),
148  m_phGravity.z()) );
149 
150  //set soft body gravity
151  m_phSoftBodyWorldInfo.m_gravity.setValue(
152  m_phGravity.x(),
153  m_phGravity.y(),
154  m_phGravity.z() );
155  m_phSoftBodyWorldInfo.m_sparsesdf.Initialize();
156 
157  initObjects();
158 
159  }
160 
162 
164  {
165  m_phDynamicsWorld->stepSimulation( m_phStep , m_phSubstep );
166 
167  for(int i=0; i<m_phTouchSensors.size(); i++)
168  {
169  CENSTouchSensor *sensor = m_phTouchSensors[i];
170 
171  if(sensor->body.isInWorld())
172  m_phDynamicsWorld->contactTest(&(sensor->body),*sensor);
173  }
174  }
175 
177 
179  float mass,
180  const btTransform& startTransform,
181  btCollisionShape* shape)
182  {
183 
184  btAssert((!shape || shape->getShapeType() != INVALID_SHAPE_PROXYTYPE));
185 
186  //rigidbody is dynamic if and only if mass
187  //is non zero, otherwise static
188  bool isDynamic = (mass != 0.f);
189 
190  btVector3 localInertia(0,0,0);
191  if (isDynamic)
192  shape->calculateLocalInertia(mass,localInertia);
193 
194  //using motionstate is recommended,
195  //it provides interpolation capabilities,
196  //and only synchronizes 'active' objects
197 
198  btDefaultMotionState* myMotionState =
199  new btDefaultMotionState(startTransform);
200 
201  btRigidBody::btRigidBodyConstructionInfo cInfo(
202  mass,
203  myMotionState,
204  shape,
205  localInertia);
206 
207  btRigidBody* body =
208  new btRigidBody(cInfo);
209 
210  body->setContactProcessingThreshold(
212 
213  m_phDynamicsWorld->addRigidBody(body);
214 
215  return body;
216 
217  }
219 
221  float mass,
222  btCollisionShape* shape ) {
223 
224  if( shape->isConvex() ) {
225 
226  const btConvexShape* convexShape =
227  static_cast<const btConvexShape*>(shape);
228  btShapeHull hull(convexShape);
229 
230  if(hull.buildHull(convexShape->getMargin())) {
231 
232  btSoftBody *body = btSoftBodyHelpers::CreateFromConvexHull(
233  m_phSoftBodyWorldInfo, hull.getVertexPointer(), hull.numVertices() );
234 
235  body->setTotalMass(mass,true);
236 
237  m_phDynamicsWorld->addSoftBody(body);
238 
239  return body;
240  }
241 
242  }
243 
244  return 0;
245 
246  }
247 
249 
250  btTransform &CENSPhysics::getTransformFromBody(btRigidBody *body) {
251 
252 
253  return body->getWorldTransform();
254 
255  }
256 
258 
259  btTransform &CENSPhysics::getTransformFromBody(btSoftBody *body) {
260 
261  return body->getWorldTransform();
262 
263  }
266  CENSNonCollidingTable _non_colliding_table ) {
267 
268  CENSNonCollidingTable::iterator it = _non_colliding_table.begin();
269  for(;it != _non_colliding_table.end(); ++it)
270  {
271  m_phNonCollidingTable[it->first]=it->second;
272  }
273 
274  m_phDispatcher->setNearCallback(
275  (void (*)(btBroadphasePair&, btCollisionDispatcher&,
276  const btDispatcherInfo&))(collisionFilteringCallback));
277  }
278 
280 
282  {
283  // create
285  // add to list
286  m_phTouchSensors.push_back(sensor);
287 
288  return sensor;
289  }
290 
292 
293  void collisionFilteringCallback(btBroadphasePair& collisionPair,
294  btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo) {
295 
296  btCollisionObject *proxy0 = (btCollisionObject *)(collisionPair.m_pProxy0->m_clientObject);
297  btCollisionObject *proxy1 = (btCollisionObject *)(collisionPair.m_pProxy1->m_clientObject);
298  bool dispatch=true;
299 
301 
302  CENSNonCollidingTable::iterator it = nct.begin();
303  for(;it != nct.end(); ++it)
304  {
305  bool enabled = it->second;
306  if(not enabled)
307  {
308  btCollisionObject *ncb0 = it->first.first;
309  btCollisionObject *ncb1 = it->first.second;
310 
311  if( (ncb0 == proxy0) and (ncb1 == proxy1) or
312  (ncb0 == proxy1) and (ncb1 == proxy0) )
313  dispatch=false;
314  }
315  }
316 
317  // Do your collision logic here
318  // Only dispatch the Bullet collision information
319  // if you want the physics to continue
320  if(dispatch)
321  dispatcher.defaultNearCallback(collisionPair, dispatcher, dispatchInfo);
322  }
323 
325 
326  void internalTickCallback(btDynamicsWorld *world, btScalar timestep)
327  {
328  }
329 
333 
334  std::map<CENSHingeConstraint *, float> CENSHingeConstraint::angles;
335 
336  void CENSHingeConstraint::setPDMotorTarget(float targetAngle,
337  float kp , float ki , float kd , float dt ) {
338 
339  // control limits
340  if (getLowerLimit() < getUpperLimit())
341  {
342  if (targetAngle < getLowerLimit())
343  targetAngle = getLowerLimit();
344  else if (targetAngle > getUpperLimit())
345  targetAngle = getUpperLimit();
346  }
347 
348  btScalar curAngle = getHingeAngle(
349  m_rbA.getCenterOfMassTransform(),
350  m_rbB.getCenterOfMassTransform());
351 
352 
353  static btScalar prev_error = 0;
354  static btScalar integral = 0;
355 
356  // compute PID current torque
357  btScalar error = targetAngle - curAngle;
358  integral += error*dt;
359  btScalar derivative = (error - prev_error)/dt;
360  prev_error = error;
361 
362  btScalar torque = kp*error +ki*integral + kd*derivative;
363 
364  //compute K
365  btVector3 axisA =
366  m_rbA.getCenterOfMassTransform().getBasis() *
367  getAFrame().getBasis().getColumn(2);
368  float kHinge =
369  1.0f /
370  (getRigidBodyA().computeAngularImpulseDenominator(axisA) +
371  getRigidBodyB().computeAngularImpulseDenominator(axisA));
372 
373  //compute and set current velocity
374  float velocity = torque/kHinge;
375  enableAngularMotor(true, velocity, getMaxMotorImpulse() );
376 
377  // update angle storage
378  angles[this] = curAngle;
379 
380  }
381 
383 
384  std::map<CENSSliderConstraint *, float> CENSSliderConstraint::positions;
385 
386  void CENSSliderConstraint::setMotorTarget(float targetPos, float dt ) {
387 
388  // control limits
389  btScalar lowerLimit = getTranslationalLimitMotor()->m_lowerLimit[0];
390  btScalar upperLimit = getTranslationalLimitMotor()->m_upperLimit[0];
391  if (lowerLimit < upperLimit)
392  {
393  if (targetPos < lowerLimit)
394  targetPos = lowerLimit;
395  else if (targetPos > upperLimit)
396  targetPos = upperLimit;
397  }
398 
399  // compute linear velocity
400  calculateTransforms();
401  btScalar curPos = getRelativePivotPosition(0);
402 
403  btScalar dPos = targetPos - curPos;
404  btScalar velocity = dPos / dt;
405 
406  getTranslationalLimitMotor()->m_enableMotor[0] = true;
407  getTranslationalLimitMotor()->m_targetVelocity = btVector3(-velocity,0,0);
408 
409  positions[this] = curPos;
410 
411  }
412 
414 
416  float kp , float ki, float kd , float dt ) {
417 
418  // control limits
419  btScalar lowerLimit = getTranslationalLimitMotor()->m_lowerLimit[0];
420  btScalar upperLimit = getTranslationalLimitMotor()->m_upperLimit[0];
421  if (lowerLimit < upperLimit)
422  {
423  if (targetPos < lowerLimit)
424  targetPos = lowerLimit;
425  else if (targetPos > upperLimit)
426  targetPos = upperLimit;
427  }
428 
429  calculateTransforms();
430  btScalar curPos = getRelativePivotPosition(0);
431 
432  static btScalar prev_error = 0;
433  static btScalar integral = 0;
434 
435  // compute PID current force
436  btScalar error = targetPos - curPos;
437  integral += error*dt;
438  btScalar derivative = (error - prev_error)/dt;
439  prev_error = error;
440 
441  btScalar force = kp*error +ki*integral + kd*derivative;
442 
443 
444  //compute and set current velocity on the x axis
445  float velocity = -force ;
446 
447  getTranslationalLimitMotor()->m_enableMotor[0] = true;
448  getTranslationalLimitMotor()->m_targetVelocity = btVector3(velocity,0,0);
449 
450  // // update pos storage
451  positions[this] = curPos;
452 
453  }
454 
455 }
btSoftBodyWorldInfo m_phSoftBodyWorldInfo
Definition: cens_physics.h:336
Computational Embodied Neuroscience Simulator library.
Definition: cens_engine.cpp:29
btSoftRigidDynamicsWorld * m_phDynamicsWorld
Definition: cens_physics.h:322
static CENSNonCollidingTable m_phNonCollidingTable
Definition: cens_physics.h:331
CENSParameterManager m_phParameterManager
Definition: cens_physics.h:347
void addParameter(std::string parname, std::string &par)
virtual void initObjects()
Definition: cens_physics.h:226
btScalar m_phDefaultContactProcessingThreshold
Definition: cens_physics.h:341
btAlignedObjectArray< btCollisionShape * > m_phCollisionShapes
Definition: cens_physics.h:325
btCollisionDispatcher * m_phDispatcher
Definition: cens_physics.h:338
Vector3f m_phGravity
Definition: cens_physics.h:342
virtual void initCENSPhysics()
btAlignedObjectArray< CENSTouchSensor * > m_phTouchSensors
Definition: cens_physics.h:328
void internalTickCallback(btDynamicsWorld *world, btScalar timestep)
btBroadphaseInterface * m_phBroadphase
Definition: cens_physics.h:337
btRigidBody & body
The body the sensor is monitoring.
Definition: cens_physics.h:93
virtual void cens_physics_step()
virtual btSoftBody * localCreateSoftBody(float mass, btCollisionShape *shape)
btConstraintSolver * m_phSolver
Definition: cens_physics.h:339
virtual CENSTouchSensor * addTouchSensor(btRigidBody *body)
void collisionFilteringCallback(btBroadphasePair &collisionPair, btCollisionDispatcher &dispatcher, const btDispatcherInfo &dispatchInfo)
virtual btRigidBody * localCreateRigidBody(float mass, const btTransform &startTransform, btCollisionShape *shape)
static std::map< CENSHingeConstraint *, float > angles
Definition: cens_physics.h:419
btDefaultCollisionConfiguration * m_phCollisionConfiguration
Definition: cens_physics.h:340
void setMotorTarget(float targetPos, float dt=.05)
void setPDMotorTarget(float targetPos, float kp=3, float ki=0, float kd=.5, float dt=.05)
virtual ~CENSPhysics()
static const char * physics_params_filename
Definition: cens_physics.h:51
void setPDMotorTarget(float targetAngle, float kp=3, float ki=0, float kd=.5, float dt=.05)
btTransform & getTransformFromBody(btRigidBody *body)
virtual void setCollisionFilter(CENSNonCollidingTable _non_colliding_table)
friend void collisionFilteringCallback(btBroadphasePair &collisionPair, btCollisionDispatcher &dispatcher, const btDispatcherInfo &dispatchInfo)
std::map< CENSNCPair, bool > CENSNonCollidingTable
Definition: cens_physics.h:77
static std::map< CENSSliderConstraint *, float > positions
Definition: cens_physics.h:461