Warning: include(php/utility.php): Failed to open stream: No such file or directory in /home/argos/argos3/doc/api/embedded/a00823_source.php on line 2

Warning: include(): Failed opening 'php/utility.php' for inclusion (include_path='.:/usr/lib64/php') in /home/argos/argos3/doc/api/embedded/a00823_source.php on line 2
The ARGoS Website

dynamics3d_engine.cpp
Go to the documentation of this file.
1 
7 #include "dynamics3d_engine.h"
8 
9 #include <argos3/core/simulator/simulator.h>
10 #include <argos3/core/simulator/space/space.h>
11 #include <argos3/core/simulator/entity/embodied_entity.h>
12 #include <argos3/plugins/simulator/physics_engines/dynamics3d/dynamics3d_model.h>
13 #include <argos3/plugins/simulator/physics_engines/dynamics3d/dynamics3d_plugin.h>
14 #include <argos3/plugins/simulator/physics_engines/dynamics3d/bullet/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h>
15 #include <algorithm>
16 
17 namespace argos {
18 
19  /****************************************/
20  /****************************************/
21 
23  m_pcRNG(nullptr),
24  m_cRandomSeedRange(0,1000),
25  m_cBroadphase(),
26  m_cConfiguration(),
27  m_cDispatcher(&m_cConfiguration),
28  m_cSolver(),
29  m_cWorld(&m_cDispatcher,
30  &m_cBroadphase,
31  &m_cSolver,
32  &m_cConfiguration),
33  m_unIterations(10),
34  m_fDeltaT(0) {}
35 
36  /****************************************/
37  /****************************************/
38 
40  /* Initialize parent */
41  CPhysicsEngine::Init(t_tree);
42  /* Create the random number generator */
43  m_pcRNG = CRandom::CreateRNG("argos");
44  /* Parse the iterations attribute */
45  GetNodeAttributeOrDefault(t_tree, "iterations", m_unIterations, m_unIterations);
46  m_fDeltaT = GetPhysicsClockTick() / static_cast<btScalar>(m_unIterations);
47  /* Set random seed */
48  m_cSolver.setRandSeed(m_pcRNG->Uniform(m_cRandomSeedRange));
49  /* Disable gravity by default */
50  m_cWorld.setGravity(btVector3(0.0,0.0,0.0));
51  /* Load the plugins */
52  TConfigurationNodeIterator tPluginIterator;
53  for(tPluginIterator = tPluginIterator.begin(&t_tree);
54  tPluginIterator != tPluginIterator.end();
55  ++tPluginIterator) {
56  CDynamics3DPlugin* pcPlugin = CFactory<CDynamics3DPlugin>::New(tPluginIterator->Value());
57  pcPlugin->SetEngine(*this);
58  pcPlugin->Init(*tPluginIterator);
59  AddPhysicsPlugin(tPluginIterator->Value(), *pcPlugin);
60  }
61  }
62 
63  /****************************************/
64  /****************************************/
65 
67  /* Call reset to set up the simulation */
68  Reset();
69  }
70 
71  /****************************************/
72  /****************************************/
73 
75  /* Remove and reset all physics models */
76  for(CDynamics3DModel::TMap::iterator itModel = std::begin(m_tPhysicsModels);
77  itModel != std::end(m_tPhysicsModels);
78  ++itModel) {
79  /* Remove model from plugins */
80  for(CDynamics3DPlugin::TMap::iterator itPlugin = std::begin(m_tPhysicsPlugins);
81  itPlugin != std::end(m_tPhysicsPlugins);
82  ++itPlugin) {
83  itPlugin->second->UnregisterModel(*itModel->second);
84  }
85  /* Reset the model */
86  itModel->second->RemoveFromWorld(m_cWorld);
87  itModel->second->Reset();
88  }
89  /* Run the destructors on bullet's components */
90  m_cWorld.~btMultiBodyDynamicsWorld();
91  m_cSolver.~btMultiBodyConstraintSolver();
92  m_cDispatcher.~btCollisionDispatcher();
93  m_cConfiguration.~btDefaultCollisionConfiguration();
94  m_cBroadphase.~btDbvtBroadphase();
95  /* Rerun the constructors for the bullet's components */
96  new (&m_cBroadphase) btDbvtBroadphase;
97  new (&m_cConfiguration) btDefaultCollisionConfiguration;
98  new (&m_cDispatcher) btCollisionDispatcher(&m_cConfiguration);
99  new (&m_cSolver) btMultiBodyConstraintSolver;
100  new (&m_cWorld) btMultiBodyDynamicsWorld(&m_cDispatcher,
101  &m_cBroadphase,
102  &m_cSolver,
103  &m_cConfiguration);
104  /* Provide the same random seed to the solver */
105  m_cSolver.setRandSeed(m_pcRNG->Uniform(m_cRandomSeedRange));
106  /* Reset the plugins */
107  for(CDynamics3DPlugin::TMap::iterator itPlugin = std::begin(m_tPhysicsPlugins);
108  itPlugin != std::end(m_tPhysicsPlugins);
109  ++itPlugin) {
110  itPlugin->second->Reset();
111  }
112  /* Set up the call back for the plugins */
113  m_cWorld.setInternalTickCallback([] (btDynamicsWorld* pc_world, btScalar f_time_step) {
114  CDynamics3DEngine* pc_engine = static_cast<CDynamics3DEngine*>(pc_world->getWorldUserInfo());
115  pc_world->clearForces();
116  for(std::pair<const std::string, CDynamics3DPlugin*>& c_plugin :
117  pc_engine->GetPhysicsPlugins()) {
118  c_plugin.second->Update();
119  }
120  }, static_cast<void*>(this), true);
121  /* Add the models back into the engine */
122  for(CDynamics3DModel::TMap::iterator itModel = std::begin(m_tPhysicsModels);
123  itModel != std::end(m_tPhysicsModels);
124  ++itModel) {
125  /* Add model to plugins */
126  for(CDynamics3DPlugin::TMap::iterator itPlugin = std::begin(m_tPhysicsPlugins);
127  itPlugin != std::end(m_tPhysicsPlugins);
128  ++itPlugin) {
129  itPlugin->second->RegisterModel(*itModel->second);
130  }
131  /* Add model to world */
132  itModel->second->AddToWorld(m_cWorld);
133  }
134  /* Initialize any multi-body constraints */
135  for (SInt32 i = 0; i < m_cWorld.getNumMultiBodyConstraints(); i++) {
136  m_cWorld.getMultiBodyConstraint(i)->finalizeMultiDof();
137  }
138  }
139 
140  /****************************************/
141  /****************************************/
142 
144  /* Destroy all physics models */
145  for(CDynamics3DModel::TMap::iterator itModel = std::begin(m_tPhysicsModels);
146  itModel != std::end(m_tPhysicsModels);
147  ++itModel) {
148  /* Remove model from the plugins first */
149  for(CDynamics3DPlugin::TMap::iterator itPlugin = std::begin(m_tPhysicsPlugins);
150  itPlugin != std::end(m_tPhysicsPlugins);
151  ++itPlugin) {
152  itPlugin->second->UnregisterModel(*itModel->second);
153  }
154  /* Destroy the model */
155  itModel->second->RemoveFromWorld(m_cWorld);
156  delete itModel->second;
157  }
158  /* Destroy all plug-ins */
159  for(CDynamics3DPlugin::TMap::iterator itPlugin = std::begin(m_tPhysicsPlugins);
160  itPlugin != std::end(m_tPhysicsPlugins);
161  ++itPlugin) {
162  itPlugin->second->Destroy();
163  delete itPlugin->second;
164  }
165  /* Empty the maps */
166  m_tPhysicsPlugins.clear();
167  m_tPhysicsModels.clear();
168  }
169 
170  /****************************************/
171  /****************************************/
172 
174  /* Update the physics state from the entities */
175  for(CDynamics3DModel::TMap::iterator it = m_tPhysicsModels.begin();
176  it != std::end(m_tPhysicsModels); ++it) {
177  it->second->UpdateFromEntityStatus();
178  }
179  /* Step the simuation forwards */
180  m_cWorld.stepSimulation(GetPhysicsClockTick(), m_unIterations, m_fDeltaT);
181  /* Update the simulated space */
182  for(CDynamics3DModel::TMap::iterator it = std::begin(m_tPhysicsModels);
183  it != std::end(m_tPhysicsModels);
184  ++it) {
185  it->second->UpdateEntityStatus();
186  }
187  }
188 
189  /****************************************/
190  /****************************************/
191 
193  const CRay3& c_ray) const {
194  /* Convert the start and end ray vectors to the bullet coordinate system */
195  btVector3 cRayStart(c_ray.GetStart().GetX(), c_ray.GetStart().GetZ(), -c_ray.GetStart().GetY());
196  btVector3 cRayEnd(c_ray.GetEnd().GetX(), c_ray.GetEnd().GetZ(), -c_ray.GetEnd().GetY());
197  btCollisionWorld::ClosestRayResultCallback cResult(cRayStart, cRayEnd);
198  /* The default flag/algorithm 'kF_UseSubSimplexConvexCastRaytest' is too approximate for
199  our purposes */
200  cResult.m_flags |= btTriangleRaycastCallback::kF_UseGjkConvexCastRaytest;
201  /* Run the ray test */
202  m_cWorld.rayTest(cRayStart, cRayEnd, cResult);
203  /* Examine the results */
204  if (cResult.hasHit() && cResult.m_collisionObject->getUserPointer() != nullptr) {
205  Real f_t = (cResult.m_hitPointWorld - cRayStart).length() / c_ray.GetLength();
206  CDynamics3DModel* pcModel =
207  static_cast<CDynamics3DModel*>(cResult.m_collisionObject->getUserPointer());
208  t_data.push_back(SEmbodiedEntityIntersectionItem(&(pcModel->GetEmbodiedEntity()), f_t));
209  }
210  }
211 
212  /****************************************/
213  /****************************************/
214 
216  return m_tPhysicsModels.size();
217  }
218 
219  /****************************************/
220  /****************************************/
221 
223  SOperationOutcome cOutcome =
224  CallEntityOperation<CDynamics3DOperationAddEntity, CDynamics3DEngine, SOperationOutcome>
225  (*this, c_entity);
226  return cOutcome.Value;
227  }
228 
229  /****************************************/
230  /****************************************/
231 
233  SOperationOutcome cOutcome =
234  CallEntityOperation<CDynamics3DOperationRemoveEntity, CDynamics3DEngine, SOperationOutcome>
235  (*this, c_entity);
236  return cOutcome.Value;
237  }
238 
239  /****************************************/
240  /****************************************/
241 
242  void CDynamics3DEngine::AddPhysicsModel(const std::string& str_id,
243  CDynamics3DModel& c_model) {
244  /* Add model to world */
245  c_model.AddToWorld(m_cWorld);
246  /* Notify the plugins of the added model */
247  for(CDynamics3DPlugin::TMap::iterator itPlugin = std::begin(m_tPhysicsPlugins);
248  itPlugin != std::end(m_tPhysicsPlugins);
249  ++itPlugin) {
250  itPlugin->second->RegisterModel(c_model);
251  }
252  /* Add a pointer to the model to the map of models */
253  m_tPhysicsModels[str_id] = &c_model;
254  }
255 
256  /****************************************/
257  /****************************************/
258 
259  void CDynamics3DEngine::RemovePhysicsModel(const std::string& str_id) {
260  CDynamics3DModel::TMap::iterator itModel = m_tPhysicsModels.find(str_id);
261  if(itModel != std::end(m_tPhysicsModels)) {
262  /* Notify the plugins of model removal */
263  for(CDynamics3DPlugin::TMap::iterator itPlugin = std::begin(m_tPhysicsPlugins);
264  itPlugin != std::end(m_tPhysicsPlugins);
265  ++itPlugin) {
266  itPlugin->second->UnregisterModel(*(itModel->second));
267  }
268  /* Remove the model from world */
269  itModel->second->RemoveFromWorld(m_cWorld);
270  /* Destroy the model */
271  delete itModel->second;
272  /* Remove the model from the map */
273  m_tPhysicsModels.erase(itModel);
274  }
275  else {
276  THROW_ARGOSEXCEPTION("The model \"" << str_id <<
277  "\" was not found in the dynamics 3D engine \"" <<
278  GetId() << "\"");
279  }
280  }
281 
282  /****************************************/
283  /****************************************/
284 
285  void CDynamics3DEngine::AddPhysicsPlugin(const std::string& str_id,
286  CDynamics3DPlugin& c_plugin) {
287  m_tPhysicsPlugins[str_id] = &c_plugin;
288  }
289 
290  /****************************************/
291  /****************************************/
292 
293  void CDynamics3DEngine::RemovePhysicsPlugin(const std::string& str_id) {
294  CDynamics3DPlugin::TMap::iterator it = m_tPhysicsPlugins.find(str_id);
295  if(it != std::end(m_tPhysicsPlugins)) {
296  delete it->second;
297  m_tPhysicsPlugins.erase(it);
298  }
299  else {
300  THROW_ARGOSEXCEPTION("The plugin \"" << str_id <<
301  "\" was not found in the dynamics 3D engine \"" <<
302  GetId() << "\"");
303  }
304  }
305 
306  /****************************************/
307  /****************************************/
308 
310  "dynamics3d",
311  "Michael Allwright [allsey87@gmail.com]",
312  "1.0",
313  "A 3D dynamics physics engine",
314  "This physics engine is a 3D dynamics engine based on the Bullet Physics SDK\n"
315  "(https://github.com/bulletphysics/bullet3).\n\n"
316  "REQUIRED XML CONFIGURATION\n\n"
317  " <physics_engines>\n"
318  " ...\n"
319  " <dynamics3d id=\"dyn3d\" />\n"
320  " ...\n"
321  " </physics_engines>\n\n"
322  "The 'id' attribute is necessary and must be unique among the physics engines.\n\n"
323  "OPTIONAL XML CONFIGURATION\n\n"
324  "The physics engine supports a number of plugins that add features to the\n"
325  "simulation. In the example below, a floor plane has been added which has a\n"
326  "height of 1 cm and dimensions of the floor as specified in the arena node. By\n"
327  "default, there is no gravity in simulation. This can be changed by adding a\n"
328  "gravity node with a single attribute 'g' which is the downwards acceleration\n"
329  "caused by gravity. Finally, there is a magnetism plugin. This plugin applies\n"
330  "forces and torques to bodies in the simulation whose model contains a magnet\n"
331  "equipped entity. The 'max_distance' attribute is an optional optimization\n"
332  "that sets the maximum distance at which two magnetic dipoles will interact\n"
333  "with each other. In the example, this distance has been set to 4 cm.\n\n"
334  " <physics_engines>\n"
335  " ...\n"
336  " <dynamics3d id=\"dyn3d\">\n"
337  " <floor height=\"0.01\"/>\n"
338  " <gravity g=\"10\" />\n"
339  " <magnetism max_distance=\"0.04\" />\n"
340  " </dynamics3d>\n"
341  " ...\n"
342  " </physics_engines>\n\n",
343  "Usable"
344  );
345 
346  /****************************************/
347  /****************************************/
348 
349 }
virtual void AddToWorld(btMultiBodyDynamicsWorld &c_world)=0
signed int SInt32
32-bit signed integer.
Definition: datatypes.h:93
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.
float Real
Collects all ARGoS code.
Definition: datatypes.h:39
#define THROW_ARGOSEXCEPTION(message)
This macro throws an ARGoS exception with the passed message.
CVector3 & GetEnd()
Definition: ray3.h:45
Real GetX() const
Returns the x coordinate of this vector.
Definition: vector3.h:93
virtual void SetEngine(CDynamics3DEngine &c_engine)
virtual bool AddEntity(CEntity &c_entity)
Adds an entity to the physics engine.
void RemovePhysicsPlugin(const std::string &str_id)
The basic entity type.
Definition: entity.h:89
Real GetY() const
Returns the y coordinate of this vector.
Definition: vector3.h:109
Real GetPhysicsClockTick() const
Returns the length of the physics engine tick.
virtual void Init(TConfigurationNode &t_tree)
Initializes the resource.
REGISTER_PHYSICS_ENGINE(CDynamics2DEngine,"dynamics2d","Carlo Pinciroli [ilpincy@gmail.com]","1.0","A 2D dynamics physics engine.","This physics engine is a 2D dynamics engine based on the Chipmunk library\n""(http://code.google.com/p/chipmunk-physics) version 6.0.1.\n\n""REQUIRED XML CONFIGURATION\n\n"" <physics_engines>\n"" ...\n"" <dynamics2d id=\"dyn2d\" />\n"" ...\n"" </physics_engines>\n\n""The 'id' attribute is necessary and must be unique among the physics engines.\n""It is used in the subsequent section <arena_physics> to assign entities to\n""physics engines. If two engines share the same id, initialization aborts.\n\n""OPTIONAL XML CONFIGURATION\n\n""It is possible to set how many iterations this physics engine performs between\n""each simulation step. By default, this physics engine performs 10 steps every\n""two simulation steps. This means that, if the simulation step is 100ms, the\n""physics engine step is, by default, 10ms. Sometimes, collisions and joints are\n""not simulated with sufficient precision using these parameters. By increasing\n""the number of iterations, the temporal granularity of the solver increases and\n""with it its accuracy, at the cost of higher computational cost. To change the\n""number of iterations per simulation step use this syntax:\n\n"" <physics_engines>\n"" ...\n"" <dynamics2d id=\"dyn2d\"\n"" iterations=\"20\" />\n"" ...\n"" </physics_engines>\n\n""The plane of the physics engine can be translated on the Z axis, to simulate\n""for example hovering objects, such as flying robots. To translate the plane\n""2m up the Z axis, use the 'elevation' attribute as follows:\n\n"" <physics_engines>\n"" ...\n"" <dynamics2d id=\"dyn2d\"\n"" elevation=\"2.0\" />\n"" ...\n"" </physics_engines>\n\n""When not specified, the elevation is zero, which means that the plane\n""corresponds to the XY plane.\n\n""The friction parameters between the ground and movable boxes and cylinders can\n""be overridden. You can set both the linear and angular friction parameters.\n""The default value is 1.49 for each of them. To override the values, use this\n""syntax (all attributes are optional):\n\n"" <physics_engines>\n"" ...\n"" <dynamics2d id=\"dyn2d\"\n"" <friction box_linear_friction=\"1.0\"\n"" box_angular_friction=\"2.0\"\n"" cylinder_linear_friction=\"3.0\"\n"" cylinder_angular_friction=\"4.0\" />\n"" </dynamics2d>\n"" ...\n"" </physics_engines>\n\n""For the the robots that use velocity-based control, such as ground robots with\n""the differential_steering actuator (e.g. the foot-bot and the e-puck), it is\n""possible to customize robot-specific attributes that set the maximum force and\n""torque the robot has. The syntax is as follows, taking a foot-bot as example:\n\n"" <arena ...>\n"" ...\n"" <foot-bot id=\"fb0\">\n"" <body position=\"0.4,2.3,0.25\" orientation=\"45,0,0\" />\n"" <controller config=\"mycntrl\" />\n"" <!-- Specify new value for max_force and max_torque -->\n"" <dynamics2d>\n"" <differential_steering max_force=\"0.1\" max_torque=\"0.1\"/>\n"" </dynamics2d>\n"" </foot-bot>\n"" ...\n"" </arena>\n\n""The attributes 'max_force' and 'max_torque' are both optional, and they take the\n""robot-specific default if not set. Check the code of the dynamics2d model of the\n""robot you're using to know the default values.\n\n""By default, this engine uses the bounding-box tree method for collision shape\n""indexing. This method is the default in Chipmunk and it works well most of the\n""times. However, if you are running simulations with hundreds or thousands of\n""identical robots, a different shape collision indexing is available: the spatial\n""hash. The spatial hash is a grid stored in a hashmap. To get the max out of this\n""indexing method, you must set two parameters: the cell size and the suggested\n""minimum number of cells in the space. According to the documentation of\n""Chipmunk, the cell size should correspond to the size of the bounding box of the\n""most common object in the simulation; the minimum number of cells should be at\n""least 10x the number of objects managed by the physics engine. To use this\n""indexing method, use this syntax (all attributes are mandatory):\n\n"" <physics_engines>\n"" ...\n"" <dynamics2d id=\"dyn2d\"\n"" <spatial_hash cell_size=\"1.0\"\n"" cell_num=\"2.0\" />\n"" </dynamics2d>\n"" ...\n"" </physics_engines>\n","Usable")
ticpp::Element TConfigurationNode
The ARGoS configuration XML node.
Type to use as return value for operation outcome.
Definition: entity.h:352
virtual size_t GetNumPhysicsModels()
const std::string & GetId() const
Returns the id of this physics engine.
void RemovePhysicsModel(const std::string &str_id)
CRadians Uniform(const CRange< CRadians > &c_range)
Returns a random value from a uniform distribution.
Definition: rng.cpp:87
std::vector< SEmbodiedEntityIntersectionItem > TEmbodiedEntityIntersectionData
virtual void Init(TConfigurationNode &t_tree)
Initializes the resource.
static TYPE * New(const std::string &str_label)
Creates a new object of type TYPE
Definition: factory_impl.h:48
void AddPhysicsPlugin(const std::string &str_id, CDynamics3DPlugin &c_plugin)
virtual void Init(TConfigurationNode &t_tree)
CEmbodiedEntity & GetEmbodiedEntity()
Returns the embodied entity associated to this physics model.
virtual void CheckIntersectionWithRay(TEmbodiedEntityIntersectionData &t_data, const CRay3 &c_ray) const
Check which objects in this engine intersect the given ray.
ticpp::Iterator< ticpp::Element > TConfigurationNodeIterator
The iterator for the ARGoS configuration XML node.
CVector3 & GetStart()
Definition: ray3.h:37
Real GetLength() const
Definition: ray3.h:96
virtual void Destroy()
Undoes whatever was done by Init().
static CRNG * CreateRNG(const std::string &str_category)
Creates a new RNG inside the given category.
Definition: rng.cpp:326
virtual void Reset()
Resets the resource.
std::map< std::string, CDynamics3DPlugin * > & GetPhysicsPlugins()
The namespace containing all the ARGoS related code.
Definition: ci_actuator.h:12
Real GetZ() const
Returns the z coordinate of this vector.
Definition: vector3.h:125
virtual void PostSpaceInit()
Executes extra initialization activities after the space has been initialized.
void AddPhysicsModel(const std::string &str_id, CDynamics3DModel &c_model)
virtual bool RemoveEntity(CEntity &c_entity)
Removes an entity from the physics engine.