dynamics3d_multi_body_object_model.cpp
Go to the documentation of this file.
1 
8 
9 #include <argos3/core/simulator/entity/composable_entity.h>
10 
11 #include <argos3/core/utility/math/matrix/transformationmatrix3.h>
12 
13 namespace argos {
14 
15  /****************************************/
16  /****************************************/
17 
19  CComposableEntity& c_entity,
20  UInt32 un_num_links,
21  bool b_fixed_base) :
22  CDynamics3DModel(c_engine, c_entity),
23  m_cMultiBody(un_num_links, 0.0f, btVector3(0,0,0), b_fixed_base, false),
24  m_unNumLinks(un_num_links),
25  m_bFixedBase(b_fixed_base) {
26  /* Register the origin anchor update method */
27  RegisterAnchorMethod(GetEmbodiedEntity().GetOriginAnchor(),
29  }
30 
31  /****************************************/
32  /****************************************/
33 
35  /* Run the multi-body destructor */
36  m_cMultiBody.~btMultiBody();
37  /* Rerun the multi-body constructor */
38  new (&m_cMultiBody) btMultiBody(m_unNumLinks,
39  m_vecBodies[0]->GetData().Mass,
40  m_vecBodies[0]->GetData().Inertia,
42  false);
43  /* Disable collisions between bodies in the same model */
44  m_cMultiBody.setHasSelfCollision(false);
45  /* Reset bodies */
46  for(const std::shared_ptr<CAbstractBody>& ptr_body : m_vecBodies) {
47  ptr_body->Reset();
48  }
49  /* TODO. For the moment, we rely on the class that derives from
50  this model to call UpdateEntityStatus after the joints
51  have been configured. This is ugly and should be fixed
52  by moving the code for joints into this class */
53  /* Synchronize with the entity in the space */
54  //UpdateEntityStatus();
55  }
56 
57  /****************************************/
58  /****************************************/
59 
60  void CDynamics3DMultiBodyObjectModel::AddToWorld(btMultiBodyDynamicsWorld& c_world) {
61  /* Prepare the multi-body (set up internal offsets, reserve memory) */
62  m_cMultiBody.finalizeMultiDof();
63  /* Add multi-body to the world */
64  c_world.addMultiBody(&m_cMultiBody);
65  /* Add the multi-body's links (collision objects) to the world */
66  for(const std::shared_ptr<CAbstractBody>& ptr_body : m_vecBodies) {
67  ptr_body->AddToWorld(c_world);
68  }
69  }
70 
71  /****************************************/
72  /****************************************/
73 
74  void CDynamics3DMultiBodyObjectModel::RemoveFromWorld(btMultiBodyDynamicsWorld& c_world) {
75  /* Remove the multi-body's links (collision objects) from the world */
76  for(const std::shared_ptr<CAbstractBody>& ptr_body : m_vecBodies) {
77  ptr_body->RemoveFromWorld(c_world);
78  }
79  /* Remove multi-body from the world */
80  c_world.removeMultiBody(&m_cMultiBody);
81  }
82 
83  /****************************************/
84  /****************************************/
85 
87  btVector3 cModelAabbMin, cModelAabbMax, cBodyAabbMin, cBodyAabbMax;
88  /* Initialize the bounding box with the base's AABB */
89  std::shared_ptr<CAbstractBody>& ptr_base = m_vecBodies[0];
90  ptr_base->GetShape().getAabb(ptr_base->GetTransform(), cModelAabbMin, cModelAabbMax);
91  /* Extend AABB to include other bodies */
92  for(const std::shared_ptr<CAbstractBody>& ptr_body : m_vecBodies) {
93  /* Get the axis aligned bounding box for the current body */
94  ptr_body->GetShape().getAabb(ptr_body->GetTransform(), cBodyAabbMin, cBodyAabbMax);
95  /* Update minimum corner */
96  cModelAabbMin.setX(cModelAabbMin.getX() < cBodyAabbMin.getX() ? cModelAabbMin.getX() : cBodyAabbMin.getX());
97  cModelAabbMin.setY(cModelAabbMin.getY() < cBodyAabbMin.getY() ? cModelAabbMin.getY() : cBodyAabbMin.getY());
98  cModelAabbMin.setZ(cModelAabbMin.getZ() < cBodyAabbMin.getZ() ? cModelAabbMin.getZ() : cBodyAabbMin.getZ());
99  /* Update maximum corner */
100  cModelAabbMax.setX(cModelAabbMax.getX() > cBodyAabbMax.getX() ? cModelAabbMax.getX() : cBodyAabbMax.getX());
101  cModelAabbMax.setY(cModelAabbMax.getY() > cBodyAabbMax.getY() ? cModelAabbMax.getY() : cBodyAabbMax.getY());
102  cModelAabbMax.setZ(cModelAabbMax.getZ() > cBodyAabbMax.getZ() ? cModelAabbMax.getZ() : cBodyAabbMax.getZ());
103  }
104  /* Write back the bounding box swapping the coordinate systems and the Y component */
105  GetBoundingBox().MinCorner.Set(cModelAabbMin.getX(), -cModelAabbMax.getZ(), cModelAabbMin.getY());
106  GetBoundingBox().MaxCorner.Set(cModelAabbMax.getX(), -cModelAabbMin.getZ(), cModelAabbMax.getY());
107  }
108 
109  /****************************************/
110  /****************************************/
111 
113  const CQuaternion& c_orientation) {
114  /* Calculate the destination transform */
115  const btTransform& cMoveToTransform =
116  btTransform(btQuaternion(c_orientation.GetX(),
117  c_orientation.GetZ(),
118  -c_orientation.GetY(),
119  c_orientation.GetW()),
120  btVector3(c_position.GetX(),
121  c_position.GetZ(),
122  -c_position.GetY()));
123  /* Calculate the origin anchor transform */
124  const SAnchor& sOriginAnchor = GetEmbodiedEntity().GetOriginAnchor();
125  const btTransform& cOriginAnchorTransform =
126  btTransform(btQuaternion(sOriginAnchor.Orientation.GetX(),
127  sOriginAnchor.Orientation.GetZ(),
128  -sOriginAnchor.Orientation.GetY(),
129  sOriginAnchor.Orientation.GetW()),
130  btVector3(sOriginAnchor.Position.GetX(),
131  sOriginAnchor.Position.GetZ(),
132  -sOriginAnchor.Position.GetY()));
133  /* Move the base of the model to the destination */
134  m_cMultiBody.setBaseWorldTransform(cMoveToTransform *
135  cOriginAnchorTransform.inverse() * m_cMultiBody.getBaseWorldTransform());
136  /* Move the remaining bodies */
137  btAlignedObjectArray<btQuaternion> vecRotations;
138  btAlignedObjectArray<btVector3> vecTranslations;
139  m_cMultiBody.updateCollisionObjectWorldTransforms(vecRotations, vecTranslations);
140  /* Update entity state */
142  }
143 
144  /****************************************/
145  /****************************************/
146 
148  /* Calculate the origin anchor's position and orientation from the base link's anchor */
149  const SAnchor& sBaseAnchor = m_vecBodies[0]->GetAnchor();
150  /* Calculate orientation */
151  CQuaternion cOriginAnchorOrientation = sBaseAnchor.OffsetOrientation.Inverse() *
152  sBaseAnchor.Orientation;
153  /* Calculate position */
154  CVector3 cOriginAnchorPosition = -sBaseAnchor.OffsetPosition;
155  cOriginAnchorPosition.Rotate(cOriginAnchorOrientation);
156  cOriginAnchorPosition += sBaseAnchor.Position;
157  /* Transfer to origin anchor */
158  s_anchor.Position = cOriginAnchorPosition;
159  s_anchor.Orientation = cOriginAnchorOrientation;
160  }
161 
162  /****************************************/
163  /****************************************/
164 
166  UInt32 un_link_index,
167  SAnchor* ps_anchor,
168  const std::shared_ptr<btCollisionShape>& ptr_shape,
169  const SData& s_data) :
170  CAbstractBody(c_model, ps_anchor, ptr_shape, s_data),
171  m_cModel(c_model),
172  m_unLinkIndex(un_link_index),
173  m_cMultiBodyLink(nullptr, 0) {}
174 
175  /****************************************/
176  /****************************************/
177 
179  /* Call the destructor */
180  m_cMultiBodyLink.~btMultiBodyLinkCollider();
181  /* Construct a new btMultiBodyLinkCollider in its place */
182  btMultiBody& cMultiBody = m_cModel.GetMultiBody();
183  new (&m_cMultiBodyLink) btMultiBodyLinkCollider(&cMultiBody, m_unLinkIndex);
184  /* Set up the btMultiBodyLinkCollider */
185  m_cMultiBodyLink.setCollisionShape(m_ptrShape.get());
186  m_cMultiBodyLink.setWorldTransform(m_sData.StartTransform *
187  m_sData.InverseCenterOfMassOffset);
188  m_cMultiBodyLink.setFriction(m_sData.Friction);
189  m_cMultiBodyLink.setUserPointer(&m_cModel);
190  cMultiBody.getLink(m_unLinkIndex).m_collider = &m_cMultiBodyLink;
191  }
192 
193  /****************************************/
194  /****************************************/
195 
196  void CDynamics3DMultiBodyObjectModel::CLink::AddToWorld(btMultiBodyDynamicsWorld& c_world) {
197  c_world.addCollisionObject(&m_cMultiBodyLink,
198  btBroadphaseProxy::DefaultFilter,
199  btBroadphaseProxy::AllFilter);
200  }
201 
202  /****************************************/
203  /****************************************/
204 
205  void CDynamics3DMultiBodyObjectModel::CLink::RemoveFromWorld(btMultiBodyDynamicsWorld& c_world) {
206  c_world.removeCollisionObject(&m_cMultiBodyLink);
207  }
208 
209  /****************************************/
210  /****************************************/
211 
212  void CDynamics3DMultiBodyObjectModel::CLink::ApplyForce(const btVector3& c_force) {
213  btMultiBody& cMultiBody = m_cModel.GetMultiBody();
214  cMultiBody.addLinkForce(m_unLinkIndex, c_force);
215  }
216 
217  /****************************************/
218  /****************************************/
219 
221  const btVector3& c_offset) {
222  btMultiBody& cMultiBody = m_cModel.GetMultiBody();
223  cMultiBody.addLinkForce(m_unLinkIndex, c_force);
224  cMultiBody.addLinkTorque(m_unLinkIndex, c_offset.cross(c_force));
225  }
226 
227  /****************************************/
228  /****************************************/
229 
230  void CDynamics3DMultiBodyObjectModel::CLink::ApplyTorque(const btVector3& c_torque) {
231  btMultiBody& cMultiBody = m_cModel.GetMultiBody();
232  cMultiBody.addLinkTorque(m_unLinkIndex, c_torque);
233  }
234 
235  /****************************************/
236  /****************************************/
237 
239  return m_cMultiBodyLink.getWorldTransform();
240  }
241 
242  /****************************************/
243  /****************************************/
244 
246  return m_unLinkIndex;
247  }
248 
249  /****************************************/
250  /****************************************/
251 
253  SAnchor* ps_anchor,
254  const std::shared_ptr<btCollisionShape>& ptr_shape,
255  const SData& s_data) :
256  CLink(c_model, -1, ps_anchor, ptr_shape, s_data) {}
257 
258  /****************************************/
259  /****************************************/
260 
262  /* Call the destructor */
263  m_cMultiBodyLink.~btMultiBodyLinkCollider();
264  /* Construct a new btMultiBodyLinkCollider in its place */
265  btMultiBody& cMultiBody = m_cModel.GetMultiBody();
266  new (&m_cMultiBodyLink) btMultiBodyLinkCollider(&cMultiBody, -1);
267  /* Set up the btMultiBodyLinkCollider */
268  m_cMultiBodyLink.setCollisionShape(m_ptrShape.get());
269  m_cMultiBodyLink.setWorldTransform(m_sData.StartTransform *
270  m_sData.InverseCenterOfMassOffset);
271  m_cMultiBodyLink.setFriction(m_sData.Friction);
272  m_cMultiBodyLink.setUserPointer(&m_cModel);
273  /* Set up the base */
274  cMultiBody.setBaseWorldTransform(m_sData.StartTransform * m_sData.InverseCenterOfMassOffset);
275  cMultiBody.setBaseCollider(&m_cMultiBodyLink);
276  }
277 
278  /****************************************/
279  /****************************************/
280 
281  void CDynamics3DMultiBodyObjectModel::CBase::ApplyForce(const btVector3& c_force) {
282  btMultiBody& cMultiBody = m_cModel.GetMultiBody();
283  cMultiBody.addBaseForce(c_force);
284  }
285 
286  /****************************************/
287  /****************************************/
288 
290  const btVector3& c_offset) {
291  btMultiBody& cMultiBody = m_cModel.GetMultiBody();
292  cMultiBody.addBaseForce(c_force);
293  cMultiBody.addBaseTorque(c_offset.cross(c_force));
294  }
295 
296  /****************************************/
297  /****************************************/
298 
299  void CDynamics3DMultiBodyObjectModel::CBase::ApplyTorque(const btVector3& c_torque) {
300  btMultiBody& cMultiBody = m_cModel.GetMultiBody();
301  cMultiBody.addBaseTorque(c_torque);
302  }
303 
304  /****************************************/
305  /****************************************/
306 
307 }
308 
unsigned int UInt32
32-bit unsigned integer.
Definition: datatypes.h:97
The namespace containing all the ARGoS related code.
Definition: ci_actuator.h:12
Basic class for an entity that contains other entities.
const SAnchor & GetOriginAnchor() const
Returns a const reference to the origin anchor associated to this entity.
An anchor related to the body of an entity.
Definition: physics_model.h:38
CQuaternion Orientation
The orientation of the anchor wrt the global coordinate system.
Definition: physics_model.h:53
CQuaternion OffsetOrientation
The initial orientation of the anchor wrt the body coordinate system.
Definition: physics_model.h:49
CVector3 Position
The position of the anchor wrt the global coordinate system.
Definition: physics_model.h:51
CVector3 OffsetPosition
The initial position of the anchor wrt the body coordinate system.
Definition: physics_model.h:47
void RegisterAnchorMethod(const SAnchor &s_anchor, void(MODEL::*pt_method)(SAnchor &))
Registers an anchor method.
CEmbodiedEntity & GetEmbodiedEntity()
Returns the embodied entity associated to this physics model.
const SBoundingBox & GetBoundingBox() const
Returns an axis-aligned box that contains the physics model.
CQuaternion Inverse() const
Definition: quaternion.h:98
Real GetW() const
Definition: quaternion.h:49
Real GetX() const
Definition: quaternion.h:53
Real GetZ() const
Definition: quaternion.h:61
Real GetY() const
Definition: quaternion.h:57
A 3D vector class.
Definition: vector3.h:31
CVector3 & Rotate(const CQuaternion &c_quaternion)
Rotates this vector by the given quaternion.
Definition: vector3.cpp:23
Real GetX() const
Returns the x coordinate of this vector.
Definition: vector3.h:105
void Set(const Real f_x, const Real f_y, const Real f_z)
Sets the vector contents from Cartesian coordinates.
Definition: vector3.h:155
Real GetY() const
Returns the y coordinate of this vector.
Definition: vector3.h:121
Real GetZ() const
Returns the z coordinate of this vector.
Definition: vector3.h:137
std::vector< std::shared_ptr< CAbstractBody > > m_vecBodies
virtual void UpdateEntityStatus()
Updates the status of the associated entity.
virtual void RemoveFromWorld(btMultiBodyDynamicsWorld &c_world)
virtual void CalculateBoundingBox()
Calculates the axis-aligned box that contains the entire physics model.
virtual void AddToWorld(btMultiBodyDynamicsWorld &c_world)
virtual void MoveTo(const CVector3 &c_position, const CQuaternion &c_orientation)
CDynamics3DMultiBodyObjectModel(CDynamics3DEngine &c_engine, CComposableEntity &c_entity, UInt32 un_num_links, bool b_fixed_base)
CLink(CDynamics3DMultiBodyObjectModel &c_model, UInt32 un_link_index, SAnchor *ps_anchor, const std::shared_ptr< btCollisionShape > &ptr_shape, const SData &s_data)
virtual void RemoveFromWorld(btMultiBodyDynamicsWorld &c_world)
virtual void AddToWorld(btMultiBodyDynamicsWorld &c_world)
CBase(CDynamics3DMultiBodyObjectModel &c_model, SAnchor *ps_anchor, const std::shared_ptr< btCollisionShape > &ptr_shape, const SData &s_data)