embodied_entity.cpp
Go to the documentation of this file.
1 
7 #include "embodied_entity.h"
8 #include "composable_entity.h"
9 #include <argos3/core/simulator/space/space.h>
10 #include <argos3/core/simulator/simulator.h>
11 #include <argos3/core/utility/string_utilities.h>
12 #include <argos3/core/utility/math/matrix/rotationmatrix3.h>
13 
14 namespace argos {
15 
16  /****************************************/
17  /****************************************/
18 
20  CEntity(pc_parent),
21  m_bMovable(true),
22  m_sBoundingBox(nullptr),
23  m_psOriginAnchor(nullptr) {}
24 
25  /****************************************/
26  /****************************************/
27 
29  const std::string& str_id,
30  const CVector3& c_position,
31  const CQuaternion& c_orientation,
32  bool b_movable) :
33  CEntity(pc_parent, str_id),
34  m_bMovable(b_movable),
35  m_sBoundingBox(nullptr),
36  m_psOriginAnchor(new SAnchor(*this,
37  "origin",
38  0,
39  CVector3(),
40  CQuaternion(),
41  c_position,
42  c_orientation)),
43  m_cInitOriginPosition(c_position),
44  m_cInitOriginOrientation(c_orientation) {
45  /* Add anchor to map and enable it */
47  EnableAnchor("origin");
48  }
49 
50  /****************************************/
51  /****************************************/
52 
54  if(!m_bMovable && m_sBoundingBox != nullptr) {
55  delete m_sBoundingBox;
56  }
57  for(auto it = m_mapAnchors.begin();
58  it != m_mapAnchors.end(); ++it) {
59  /* it->second points to the current anchor */
60  delete it->second;
61  }
62  m_mapAnchors.clear();
63  }
64 
65  /****************************************/
66  /****************************************/
67 
69  try {
70  /* Initialize base entity */
71  CEntity::Init(t_tree);
72  /* Get the position of the entity */
74  /* Get the orientation of the entity */
76  /* Create origin anchor */
77  m_psOriginAnchor = new SAnchor(*this,
78  "origin",
79  0,
80  CVector3(),
81  CQuaternion(),
84  /* Add anchor to map and enable it */
86  EnableAnchor("origin");
87  /* Embodied entities are movable by default */
88  m_bMovable = true;
89  }
90  catch(CARGoSException& ex) {
91  THROW_ARGOSEXCEPTION_NESTED("Failed to initialize embodied entity \"" << GetContext() << GetId() << "\".", ex);
92  }
93  }
94 
95  /****************************************/
96  /****************************************/
97 
99  /* Reset origin anchor first */
102  /* Reset other anchors */
103  SAnchor* psAnchor;
104  for(auto it = m_mapAnchors.begin();
105  it != m_mapAnchors.end(); ++it) {
106  /* it->second points to the current anchor */
107  psAnchor = it->second;
108  if(psAnchor->Index > 0) {
109  /* Calculate global position and orientation */
110  psAnchor->Position = psAnchor->OffsetPosition;
112  psAnchor->Position += m_cInitOriginPosition;
114  }
115  }
116  }
117 
118  /****************************************/
119  /****************************************/
120 
121  SAnchor& CEmbodiedEntity::AddAnchor(const std::string& str_id,
122  const CVector3& c_offset_position,
123  const CQuaternion& c_offset_orientation) {
124  /* Make sure the anchor id is unique */
125  if(m_mapAnchors.count(str_id) > 0 ) {
126  THROW_ARGOSEXCEPTION("Embodied entity \"" << GetContext() + GetId() << "\" already has an anchor with id " << str_id);
127  }
128  /* Calculate anchor position */
129  CVector3 cPos = c_offset_position;
131  cPos += m_psOriginAnchor->Position;
132  /* Calculate anchor orientation */
133  CQuaternion cOrient = m_psOriginAnchor->Orientation * c_offset_orientation;
134  /* Create anchor */
135  auto* psAnchor = new SAnchor(*this,
136  str_id,
137  m_mapAnchors.size(),
138  c_offset_position,
139  c_offset_orientation,
140  cPos,
141  cOrient);
142  /* Add anchor to map */
143  m_mapAnchors[str_id] = psAnchor;
144  return *psAnchor;
145  }
146 
147  /****************************************/
148  /****************************************/
149 
150  void CEmbodiedEntity::EnableAnchor(const std::string& str_id) {
151  /* Lookup the anchor id */
152  auto it = m_mapAnchors.find(str_id);
153  /* Found? */
154  if(it == m_mapAnchors.end()) {
155  THROW_ARGOSEXCEPTION("Embodied entity \"" << GetContext() + GetId() << "\" has no anchor with id " << str_id);
156  }
157  /* Now it->second points to the requested anchor */
158  /* Increase the in-use count */
159  ++(it->second->InUseCount);
160  /* Add to vector of enabled anchors if necessary */
161  if(it->second->InUseCount == 1) {
162  m_vecEnabledAnchors.push_back(it->second);
163  }
164  }
165 
166  /****************************************/
167  /****************************************/
168 
169  void CEmbodiedEntity::DisableAnchor(const std::string& str_id) {
170  /* Cannot disable the origin anchor */
171  if(str_id == "origin") return;
172  /* Lookup the anchor id */
173  auto it = std::find(m_vecEnabledAnchors.begin(),
174  m_vecEnabledAnchors.end(),
175  str_id);
176  /* Found? */
177  if(it == m_vecEnabledAnchors.end()) return;
178  /* Now *it points to the requested anchor */
179  /* Decrease the in-use count */
180  --((*it)->InUseCount);
181  /* Remove from vector of enabled anchors if necessary */
182  if((*it)->InUseCount == 0) {
183  m_vecEnabledAnchors.erase(it);
184  }
185  }
186 
187  /****************************************/
188  /****************************************/
189 
190  const SAnchor& CEmbodiedEntity::GetAnchor(const std::string& str_id) const {
191  /* Lookup the anchor id */
192  auto it = m_mapAnchors.find(str_id);
193  /* Found? */
194  if(it == m_mapAnchors.end()) {
195  THROW_ARGOSEXCEPTION("Embodied entity \"" << GetContext() + GetId() << "\" has no anchor with id " << str_id);
196  }
197  /* Now it->second points to the requested anchor */
198  return *(it->second);
199  }
200 
201  /****************************************/
202  /****************************************/
203 
204  SAnchor& CEmbodiedEntity::GetAnchor(const std::string& str_id) {
205  /* Lookup the anchor id */
206  auto it = m_mapAnchors.find(str_id);
207  /* Found? */
208  if(it == m_mapAnchors.end()) {
209  THROW_ARGOSEXCEPTION("Embodied entity \"" << GetContext() + GetId() << "\" has no anchor with id " << str_id);
210  }
211  /* Now it->second points to the requested anchor */
212  return *(it->second);
213  }
214 
215  /****************************************/
216  /****************************************/
217 
218  bool CEmbodiedEntity::IsAnchorEnabled(const std::string& str_id) {
219  /* Lookup the anchor id */
220  std::map<std::string, SAnchor*>::const_iterator it = m_mapAnchors.find(str_id);
221  /* Found? */
222  if(it == m_mapAnchors.end()) {
223  THROW_ARGOSEXCEPTION("Embodied entity \"" << GetContext() + GetId() << "\" has no anchor with id " << str_id);
224  }
225  /* Now it->second points to the requested anchor */
226  return (it->second->InUseCount > 0);
227  }
228 
229  /****************************************/
230  /****************************************/
231 
233  if(GetPhysicsModelsNum() == 0) {
234  /* No engine associated to this entity */
235  THROW_ARGOSEXCEPTION("CEmbodiedEntity::GetBoundingBox() : entity \"" << GetContext() << GetId() << "\" is not associated to any engine");
236  }
237  return *m_sBoundingBox;
238  }
239 
240  /****************************************/
241  /****************************************/
242 
244  return m_tPhysicsModelVector.size();
245  }
246 
247  /****************************************/
248  /****************************************/
249 
250  void CEmbodiedEntity::AddPhysicsModel(const std::string& str_engine_id,
251  CPhysicsModel& c_physics_model) {
252  if(m_bMovable && GetPhysicsModelsNum() > 0) {
253  THROW_ARGOSEXCEPTION(GetContext() << GetId() << " is a movable embodied entity and can't have more than 1 physics engine entity associated");
254  }
255  m_tPhysicsModelMap[str_engine_id] = &c_physics_model;
256  m_tPhysicsModelVector.push_back(&c_physics_model);
258  }
259 
260  /****************************************/
261  /****************************************/
262 
263  void CEmbodiedEntity::RemovePhysicsModel(const std::string& str_engine_id) {
264  auto itMap = m_tPhysicsModelMap.find(str_engine_id);
265  if(itMap == m_tPhysicsModelMap.end()) {
266  THROW_ARGOSEXCEPTION("Entity \"" << GetContext() << GetId() << "\" has no associated entity in physics engine " << str_engine_id);
267  }
268  auto itVec = std::find(m_tPhysicsModelVector.begin(),
269  m_tPhysicsModelVector.end(),
270  itMap->second);
271  m_tPhysicsModelMap.erase(itMap);
272  m_tPhysicsModelVector.erase(itVec);
274  }
275 
276  /****************************************/
277  /****************************************/
278 
279  const CPhysicsModel& CEmbodiedEntity::GetPhysicsModel(size_t un_idx) const {
280  if(un_idx > m_tPhysicsModelVector.size()) {
281  THROW_ARGOSEXCEPTION("CEmbodiedEntity::GetPhysicsModel: entity \"" << GetContext() << GetId() << "\": the passed index " << un_idx << " is out of bounds, the max allowed is " << m_tPhysicsModelVector.size());
282  }
283  return *m_tPhysicsModelVector[un_idx];
284  }
285 
286  /****************************************/
287  /****************************************/
288 
290  if(un_idx > m_tPhysicsModelVector.size()) {
291  THROW_ARGOSEXCEPTION("CEmbodiedEntity::GetPhysicsModel: entity \"" << GetContext() << GetId() << "\": the passed index " << un_idx << " is out of bounds, the max allowed is " << m_tPhysicsModelVector.size());
292  }
293  return *m_tPhysicsModelVector[un_idx];
294  }
295 
296  /****************************************/
297  /****************************************/
298 
299  const CPhysicsModel& CEmbodiedEntity::GetPhysicsModel(const std::string& str_engine_id) const {
300  auto it = m_tPhysicsModelMap.find(str_engine_id);
301  if(it == m_tPhysicsModelMap.end()) {
302  THROW_ARGOSEXCEPTION("Entity \"" << GetContext() << GetId() << "\" has no associated entity in physics engine \"" << str_engine_id << "\"");
303  }
304  return *(it->second);
305  }
306 
307  /****************************************/
308  /****************************************/
309 
310  CPhysicsModel& CEmbodiedEntity::GetPhysicsModel(const std::string& str_engine_id) {
311  auto it = m_tPhysicsModelMap.find(str_engine_id);
312  if(it == m_tPhysicsModelMap.end()) {
313  THROW_ARGOSEXCEPTION("Entity \"" << GetContext() << GetId() << "\" has no associated entity in physics engine \"" << str_engine_id << "\"");
314  }
315  return *(it->second);
316  }
317 
318  /****************************************/
319  /****************************************/
320 
321  bool CEmbodiedEntity::MoveTo(const CVector3& c_position,
322  const CQuaternion& c_orientation,
323  bool b_check_only,
324  bool b_ignore_collisions) {
325  /* Can't move an entity with no model associated */
326  if(GetPhysicsModelsNum() == 0) return false;
327  /* Save current position and orientation */
328  CVector3 cOriginalPosition = m_psOriginAnchor->Position;
329  CQuaternion cOriginalOrientation = m_psOriginAnchor->Orientation;
330  /* Treat specially the case of movable entity */
331  if(m_bMovable) {
332  /* Move entity and check for collisions */
333  m_tPhysicsModelVector[0]->MoveTo(c_position, c_orientation);
334  bool bNoCollision = b_ignore_collisions || (! m_tPhysicsModelVector[0]->IsCollidingWithSomething());
335  /* Depending on the presence of collisions... */
336  if(bNoCollision && !b_check_only) {
337  /* No collision and not a simple check */
338  /* Tell the caller that we managed to move the entity */
339  return true;
340  }
341  else {
342  /* Collision or just a check, undo changes */
343  m_tPhysicsModelVector[0]->MoveTo(cOriginalPosition, cOriginalOrientation);
344  /* Tell the caller about collisions */
345  return bNoCollision;
346  }
347  }
348  else {
349  /* The entity is not movable, go through all the models */
350  size_t i;
351  bool bNoCollision = true;
352  for(i = 0; i < m_tPhysicsModelVector.size() && bNoCollision; ++i) {
353  m_tPhysicsModelVector[i]->MoveTo(c_position, c_orientation);
354  bNoCollision = b_ignore_collisions || !m_tPhysicsModelVector[i]->IsCollidingWithSomething();
355  }
356  if(bNoCollision && !b_check_only) {
357  /* No collision and not a simple check */
359  /* Tell the caller that we managed to move the entity */
360  return true;
361  }
362  else {
363  /* No collision or just a check, undo changes */
364  for(size_t j = 0; j < i; ++j) {
365  m_tPhysicsModelVector[j]->MoveTo(cOriginalPosition, cOriginalOrientation);
366  }
367  /* Tell the caller about collisions */
368  return bNoCollision;
369  }
370  }
371  }
372 
373  /****************************************/
374  /****************************************/
375 
376 #define CHECK_CORNER(MINMAX, COORD, OP) \
377  if(m_sBoundingBox->MINMAX ## Corner.Get ## COORD() OP sBBox.MINMAX ## Corner.Get ## COORD()) { \
378  m_sBoundingBox->MINMAX ## Corner.Set ## COORD(sBBox.MINMAX ## Corner.Get ## COORD()); \
379  }
380 
382  if(GetPhysicsModelsNum() > 0) {
383  /*
384  * There is at least one physics engine entity associated
385  */
386  if(m_bMovable) {
387  /* The bounding box points directly to the associated model bounding box */
388  m_sBoundingBox = &m_tPhysicsModelVector[0]->GetBoundingBox();
389  }
390  else {
391  /* The bounding box is obtained taking the extrema of all the bboxes of all the engines */
392  if(m_sBoundingBox == nullptr) {
394  }
395  *m_sBoundingBox = m_tPhysicsModelVector[0]->GetBoundingBox();
396  for(size_t i = 1; i < GetPhysicsModelsNum(); ++i) {
397  const SBoundingBox& sBBox = m_tPhysicsModelVector[0]->GetBoundingBox();
398  CHECK_CORNER(Min, X, >);
399  CHECK_CORNER(Min, Y, >);
400  CHECK_CORNER(Min, Z, >);
401  CHECK_CORNER(Max, X, <);
402  CHECK_CORNER(Max, Y, <);
403  CHECK_CORNER(Max, Z, <);
404  }
405  }
406  }
407  else {
408  /*
409  * No physics engine entity associated
410  */
411  if(! m_bMovable && m_sBoundingBox != nullptr) {
412  /* A non-movable entity has its own bounding box, delete it */
413  delete m_sBoundingBox;
414  }
415  m_sBoundingBox = nullptr;
416  }
417  }
418 
419  /****************************************/
420  /****************************************/
421 
423  /* If no model is associated, you can't call this function */
424  if(m_tPhysicsModelVector.empty()) {
425  THROW_ARGOSEXCEPTION("CEmbodiedEntity::IsCollidingWithSomething() called on entity \"" <<
426  GetContext() << GetId() <<
427  "\", but this entity has not been added to any physics engine.");
428  }
429  /* Special case: if there is only one model, check that directly */
430  if(m_tPhysicsModelVector.size() == 1) {
431  return m_tPhysicsModelVector[0]->IsCollidingWithSomething();
432  }
433  /* Multiple associations, go through them */
434  else {
435  /* Return true at the first detected collision */
436  for(size_t i = 0; i < m_tPhysicsModelVector.size(); ++i) {
438  return true;
439  }
440  }
441  /* If you get here it's because there are collisions */
442  return false;
443  }
444  }
445 
446  /****************************************/
447  /****************************************/
448 
449  bool operator==(const SAnchor* ps_anchor,
450  const std::string& str_id) {
451  return (ps_anchor->Id == str_id);
452  }
453 
454  /****************************************/
455  /****************************************/
456 
457  void CEmbodiedEntitySpaceHashUpdater::operator()(CAbstractSpaceHash<CEmbodiedEntity>& c_space_hash,
458  CEmbodiedEntity& c_element) {
459  /* Translate the min corner of the bounding box into the map's coordinate */
460  c_space_hash.SpaceToHashTable(m_nMinX, m_nMinY, m_nMinZ, c_element.GetBoundingBox().MinCorner);
461  /* Translate the max corner of the bounding box into the map's coordinate */
462  c_space_hash.SpaceToHashTable(m_nMaxX, m_nMaxY, m_nMaxZ, c_element.GetBoundingBox().MaxCorner);
463  /* Finally, go through the affected cells and update them */
464  for(SInt32 nK = m_nMinZ; nK <= m_nMaxZ; ++nK) {
465  for(SInt32 nJ = m_nMinY; nJ <= m_nMaxY; ++nJ) {
466  for(SInt32 nI = m_nMinX; nI <= m_nMaxX; ++nI) {
467  c_space_hash.UpdateCell(nI, nJ, nK, c_element);
468  }
469  }
470  }
471  }
472 
473  /****************************************/
474  /****************************************/
475 
477  m_cGrid(c_grid) {}
478 
480  try {
481  /* Get cell of bb min corner, clamping it if is out of bounds */
482  m_cGrid.PositionToCell(m_nMinI, m_nMinJ, m_nMinK, c_entity.GetBoundingBox().MinCorner);
483  m_cGrid.ClampCoordinates(m_nMinI, m_nMinJ, m_nMinK);
484  /* Get cell of bb max corner, clamping it if is out of bounds */
485  m_cGrid.PositionToCell(m_nMaxI, m_nMaxJ, m_nMaxK, c_entity.GetBoundingBox().MaxCorner);
486  m_cGrid.ClampCoordinates(m_nMaxI, m_nMaxJ, m_nMaxK);
487  /* Go through cells */
488  for(SInt32 m_nK = m_nMinK; m_nK <= m_nMaxK; ++m_nK) {
489  for(SInt32 m_nJ = m_nMinJ; m_nJ <= m_nMaxJ; ++m_nJ) {
490  for(SInt32 m_nI = m_nMinI; m_nI <= m_nMaxI; ++m_nI) {
491  m_cGrid.UpdateCell(m_nI, m_nJ, m_nK, c_entity);
492  }
493  }
494  }
495  /* Continue with the other entities */
496  return true;
497  }
498  catch(CARGoSException& ex) {
499  THROW_ARGOSEXCEPTION_NESTED("While updating the embodied entity grid for embodied entity \"" << c_entity.GetContext() << c_entity.GetId() << "\"", ex);
500  }
501  }
502 
503  /****************************************/
504  /****************************************/
505 
509  class CSpaceOperationAddEmbodiedEntity : public CSpaceOperationAddEntity {
510  public:
511  void ApplyTo(CSpace& c_space, CEmbodiedEntity& c_entity) {
512  /* Add entity to space */
513  c_space.AddEntity(c_entity);
514  /* Try to add entity to physics engine(s) */
515  c_space.AddEntityToPhysicsEngine(c_entity);
516  }
517  };
518  REGISTER_SPACE_OPERATION(CSpaceOperationAddEntity, CSpaceOperationAddEmbodiedEntity, CEmbodiedEntity);
519 
520  class CSpaceOperationRemoveEmbodiedEntity : public CSpaceOperationRemoveEntity {
521  public:
522  void ApplyTo(CSpace& c_space, CEmbodiedEntity& c_entity) {
523  /* Get a reference to the root entity */
524  CEntity* pcRoot = &c_entity;
525  while(pcRoot->HasParent()) {
526  pcRoot = &pcRoot->GetParent();
527  }
528  /* Remove entity from all physics engines */
529  try {
530  while(c_entity.GetPhysicsModelsNum() > 0) {
531  c_entity.GetPhysicsModel(0).GetEngine().RemoveEntity(*pcRoot);
532  }
533  }
534  catch(CARGoSException& ex) {
535  /*
536  * It is safe to ignore errors because they happen only when an entity
537  * is completely removed from the space. In this case, the body is
538  * first removed from the composable entity, and then the embodied entity
539  * is asked to clear up the physics models. In turn, this last operation
540  * searches for the body component, which is not there anymore.
541  *
542  * It is anyway useful to search for the body component because, when robots
543  * are transferred from an engine to another, only the physics model is to be
544  * removed.
545  */
546  }
547  /* Remove entity from space */
548  c_space.RemoveEntity(c_entity);
549  }
550  };
551  REGISTER_SPACE_OPERATION(CSpaceOperationRemoveEntity, CSpaceOperationRemoveEmbodiedEntity, CEmbodiedEntity);
556  /****************************************/
557  /****************************************/
558 
559 }
#define CHECK_CORNER(MINMAX, COORD, OP)
#define THROW_ARGOSEXCEPTION_NESTED(message, nested)
This macro throws an ARGoS exception with the passed message and nesting the passed exception.
#define THROW_ARGOSEXCEPTION(message)
This macro throws an ARGoS exception with the passed message.
signed int SInt32
32-bit signed integer.
Definition: datatypes.h:93
unsigned int UInt32
32-bit unsigned integer.
Definition: datatypes.h:97
The namespace containing all the ARGoS related code.
Definition: ci_actuator.h:12
bool operator==(const SAnchor *ps_anchor, const std::string &str_id)
Returns true if the anchor id matches the given id.
void GetNodeAttributeOrDefault(TConfigurationNode &t_node, const std::string &str_attribute, T &t_buffer, const T &t_default)
Returns the value of a node's attribute, or the passed default value.
ticpp::Element TConfigurationNode
The ARGoS configuration XML node.
REGISTER_SPACE_OPERATION(CSpaceOperationAddEntity, CSpaceOperationAddCFloorEntity, CFloorEntity)
T Max(const T &t_v1, const T &t_v2)
Returns the bigger of the two passed arguments.
Definition: general.h:95
T Min(const T &t_v1, const T &t_v2)
Returns the smaller of the two passed arguments.
Definition: general.h:77
Basic class for an entity that contains other entities.
This entity is a link to a body in the physics engine.
CQuaternion m_cInitOriginOrientation
void DisableAnchor(const std::string &str_id)
Disables an anchor.
virtual void AddPhysicsModel(const std::string &str_engine_id, CPhysicsModel &c_physics_model)
Adds a new physics model to this embodied entity.
bool IsAnchorEnabled(const std::string &str_id)
Returns true if the given anchor is enabled, false otherwise.
void RemovePhysicsModel(const std::string &str_engine_id)
Removes a physics model from this embodied entity.
CEmbodiedEntity(CComposableEntity *pc_parent)
Class constructor.
const SAnchor & GetAnchor(const std::string &str_id) const
Returns the wanted anchor as a const reference.
const SBoundingBox & GetBoundingBox() const
Returns the bounding box of this embodied entity.
CPhysicsModel::TVector m_tPhysicsModelVector
std::map< std::string, SAnchor * > m_mapAnchors
void CalculateBoundingBox()
Calculates the bounding box of this entity.
std::vector< SAnchor * > m_vecEnabledAnchors
virtual bool IsCollidingWithSomething() const
Returns true if this entity is colliding with another object.
virtual ~CEmbodiedEntity()
Class destructor.
const CPhysicsModel & GetPhysicsModel(size_t un_idx) const
Returns a physics model associated to this entity.
UInt32 GetPhysicsModelsNum() const
Returns the number of physics models associated to this entity.
SBoundingBox * m_sBoundingBox
virtual bool MoveTo(const CVector3 &c_position, const CQuaternion &c_orientation, bool b_check_only=false, bool b_ignore_collisions=false)
Moves the entity to the wanted position and orientation.
virtual void Init(TConfigurationNode &t_tree)
Initializes the state of the entity from the XML configuration tree.
CPhysicsModel::TMap m_tPhysicsModelMap
void EnableAnchor(const std::string &str_id)
Enables an anchor.
SAnchor & AddAnchor(const std::string &str_id, const CVector3 &c_rel_position=CVector3(), const CQuaternion &c_rel_orientation=CQuaternion())
Adds an anchor to the embodied entity.
virtual void Reset()
Resets the state of the entity to whatever it was after Init() or the standalone constructor was call...
virtual bool operator()(CEmbodiedEntity &c_entity)
CEmbodiedEntityGridUpdater(CGrid< CEmbodiedEntity > &c_grid)
The basic entity type.
Definition: entity.h:90
const std::string & GetId() const
Returns the id of this entity.
Definition: entity.h:157
std::string GetContext() const
Returns the context of this entity.
Definition: entity.cpp:79
virtual void Init(TConfigurationNode &t_tree)
Initializes the state of the entity from the XML configuration tree.
Definition: entity.cpp:40
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
std::string Id
The id of the anchor.
Definition: physics_model.h:42
UInt32 Index
The index of the anchor assigned by the embodied entity.
Definition: physics_model.h:45
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 AddEntity(ENTITY &c_entity)
Adds an entity of the given type.
Definition: space.h:274
virtual void AddEntityToPhysicsEngine(CEmbodiedEntity &c_entity)
Definition: space.cpp:186
The exception that wraps all errors in ARGoS.
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