Warning: include(php/utility.php): Failed to open stream: No such file or directory in /home/argos/argos3/doc/api/embedded/a00829_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/a00829_source.php on line 2
The ARGoS Website

dynamics3d_magnetism_plugin.cpp
Go to the documentation of this file.
1 
10 
11 #include <argos3/plugins/simulator/physics_engines/dynamics3d/dynamics3d_model.h>
12 #include <algorithm>
13 
14 #include <argos3/plugins/simulator/physics_engines/dynamics3d/dynamics3d_multi_body_object_model.h>
15 #include <argos3/plugins/simulator/physics_engines/dynamics3d/bullet/BulletDynamics/Featherstone/btMultiBodyLink.h>
16 
17 namespace argos {
18 
19  /****************************************/
20  /****************************************/
21 
23  GetNodeAttributeOrDefault(t_tree, "force_constant", m_fForceConstant, m_fForceConstant);
24  GetNodeAttributeOrDefault(t_tree, "max_distance", m_fMaxDistance, m_fMaxDistance);
25  }
26 
27  /****************************************/
28  /****************************************/
29 
31  CComposableEntity& cEntity = c_model.GetComposableEntity();
32  if(cEntity.HasComponent("magnets")) {
33  /* Get the list of bodies belonging to this model */
34  std::vector<CDynamics3DModel::CAbstractBody*>& cModelBodies = c_model.GetBodies();
35  /* Get the list of magnets belonging to the entity */
37  cEntity.GetComponent<CMagnetEquippedEntity>("magnets").GetInstances();
38  /* For each magnet */
39  for(CMagnetEquippedEntity::SInstance& s_instance : vecInstances) {
40  std::vector<CDynamics3DModel::CAbstractBody*>::iterator itMagneticBody =
41  std::find_if(std::begin(cModelBodies),
42  std::end(cModelBodies),
43  [&s_instance] (CDynamics3DModel::CAbstractBody* pc_body) {
44  /* If both the body and the magnet share the same anchor,
45  we have found our magnetic body */
46  return (&(s_instance.Anchor) == &(pc_body->GetAnchor()));
47  });
48  if(itMagneticBody != std::end(cModelBodies)) {
49  btTransform cOffset(btQuaternion(0.0f, 0.0f, 0.0f, 1.0f),
50  btVector3(s_instance.Offset.GetX(),
51  s_instance.Offset.GetZ(),
52  -s_instance.Offset.GetY()));
53  cOffset *= (*itMagneticBody)->GetData().CenterOfMassOffset;
54  m_vecDipoles.emplace_back(**itMagneticBody, s_instance.Magnet, cOffset);
55  }
56  }
57  }
58  }
59 
60  /****************************************/
61  /****************************************/
62 
64  std::vector<SMagneticDipole>::iterator itRemove =
65  std::remove_if(std::begin(m_vecDipoles),
66  std::end(m_vecDipoles),
67  [&c_model] (const SMagneticDipole& c_magnetic_dipole) {
68  return(&(c_magnetic_dipole.Body->GetModel()) == &c_model);
69  });
70  m_vecDipoles.erase(itRemove, std::end(m_vecDipoles));
71  }
72 
73  /****************************************/
74  /****************************************/
75 
77  if(m_vecDipoles.size() < 2) {
78  /* Nothing to do */
79  return;
80  }
81  for(std::vector<SMagneticDipole>::iterator itDipole0 = std::begin(m_vecDipoles);
82  itDipole0 != (std::end(m_vecDipoles) - 1);
83  ++itDipole0) {
84  for(std::vector<SMagneticDipole>::iterator itDipole1 = std::next(itDipole0, 1);
85  itDipole1 != std::end(m_vecDipoles);
86  ++itDipole1) {
87  const btTransform& cTransformDipole0 = itDipole0->Offset * itDipole0->Body->GetTransform();
88  const btTransform& cTransformDipole1 = itDipole1->Offset * itDipole1->Body->GetTransform();
89  const btVector3& cPositionDipole0 = cTransformDipole0.getOrigin();
90  const btVector3& cPositionDipole1 = cTransformDipole1.getOrigin();
91  /* calculate the distance between the two magnetic bodies */
92  btScalar fDistance = cPositionDipole0.distance(cPositionDipole1);
93  /* optimisation - don't calculate magnetism for dipoles more than m_fMaxDistance apart */
94  if(fDistance > m_fMaxDistance) {
95  continue;
96  }
97  /* perform Barnes-hut algorithm */
98  /* calculate the normalized seperation between the two dipoles, pointing from Dipole1 to Dipole0*/
99  const btVector3& cNormalizedSeparation =
100  btVector3(cPositionDipole0 - cPositionDipole1) / fDistance;
101  /* calculate the rotated field of dipole 0 */
102  const CVector3& cFieldDipole0 = itDipole0->Magnet->GetField();
103  const btVector3& cRotatedFieldDipole0 = itDipole0->Body->GetTransform().getBasis() *
104  btVector3(cFieldDipole0.GetX(), cFieldDipole0.GetZ(), -cFieldDipole0.GetY());
105  /* calculate the rotated field of dipole 1 */
106  const CVector3& cFieldDipole1 = itDipole1->Magnet->GetField();
107  const btVector3& cRotatedFieldDipole1 = itDipole1->Body->GetTransform().getBasis() *
108  btVector3(cFieldDipole1.GetX(), cFieldDipole1.GetZ(), -cFieldDipole1.GetY());
109  /* We now have cRotatedFieldDipole0 and cRotatedFieldDipole1 as the magnetic moments
110  (i.e., m0, m1), cNormalizedSeparation as the direction unit vector from Dipole 1
111  to Dipole 0 (i.e., n), fDistance is the scalar distance between the dipoles (i.e.,
112  d), and B0 is the magnetic flux density at Dipole 0.
113  B0 = u0/4pi * [3n(n.m1) - m1] / d^3
114  T0 = m0 * B0
115  = u0.4pi/d^3 * [3 (m1.n)(m0 * n) - m0 * m1]
116 
117  F0 = grad(m0.B0)
118  = u0.4pi/d^4 * [-15n(m0.n)(m1.n) + 3n(m0.m1) + 3(m0(m1.n)+m1(m0.n))]
119  */
120  /* calculate the intermediate cross and dot products */
121  const btVector3& cCrossProduct01 = cRotatedFieldDipole0.cross(cRotatedFieldDipole1);
122  const btVector3& cCrossProduct0 = cRotatedFieldDipole0.cross(cNormalizedSeparation);
123  const btVector3& cCrossProduct1 = cRotatedFieldDipole1.cross(cNormalizedSeparation);
124  btScalar fDotProduct01 = cRotatedFieldDipole0.dot(cRotatedFieldDipole1);
125  btScalar fDotProduct0 = cRotatedFieldDipole0.dot(cNormalizedSeparation);
126  btScalar fDotProduct1 = cRotatedFieldDipole1.dot(cNormalizedSeparation);
127  /* calculate the magnetic force and torque */
128  const btVector3& cTorque0 =
129  ((3 * fDotProduct1 * cCrossProduct0) - cCrossProduct01) *
130  m_fForceConstant / btPow(fDistance, 3);
131  const btVector3& cTorque1 =
132  ((3 * fDotProduct0 * cCrossProduct1) + cCrossProduct01) *
133  m_fForceConstant / btPow(fDistance, 3);
134  const btVector3& cForce = (m_fForceConstant / btPow(fDistance, 4)) *
135  ((-15 * cNormalizedSeparation * fDotProduct1 * fDotProduct0) +
136  (3 * cNormalizedSeparation * fDotProduct01) +
137  (3 * (fDotProduct1 * cRotatedFieldDipole0 + fDotProduct0 * cRotatedFieldDipole1)));
138  /* apply torques and forces to the bodies */
139  itDipole0->Body->ApplyForce(cForce, (itDipole0->Offset).getOrigin());
140  itDipole0->Body->ApplyTorque(cTorque0);
141  itDipole1->Body->ApplyForce(-cForce, (itDipole1->Offset).getOrigin());
142  itDipole1->Body->ApplyTorque(cTorque1);
143  }
144  }
145  }
146 
147  /****************************************/
148  /****************************************/
149 
151  "magnetism",
152  "Michael Allwright [allsey87@gmail.com]",
153  "1.0",
154  "Applies forces and torques between magnetic dipoles in the simulation",
155  "For a description on how to use this plugin, please consult the documentation\n"
156  "for the dynamics3d physics engine plugin",
157  "Usable");
158 
159  /****************************************/
160  /****************************************/
161 
162 }
A 3D vector class.
Definition: vector3.h:29
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.
Real GetX() const
Returns the x coordinate of this vector.
Definition: vector3.h:93
virtual void UnregisterModel(CDynamics3DModel &c_model)
Real GetY() const
Returns the y coordinate of this vector.
Definition: vector3.h:109
ticpp::Element TConfigurationNode
The ARGoS configuration XML node.
REGISTER_DYNAMICS3D_PLUGIN(CDynamics3DFloorPlugin,"floor","Michael Allwright [allsey87@gmail.com]","1.0","Inserts a floor into the 3D dynamics engine","For a description on how to use this plugin, please consult the documentation\n""for the dynamics3d physics engine plugin","Usable")
Basic class for an entity that contains other entities.
CComposableEntity & GetComposableEntity()
virtual void Init(TConfigurationNode &t_tree)
bool HasComponent(const std::string &str_component)
Returns true if this composable entity has a component with the given string label.
std::vector< CAbstractBody * > & GetBodies()
A container of CMagnetEntity.
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 RegisterModel(CDynamics3DModel &c_model)
CEntity & GetComponent(const std::string &str_component)
Returns the component with the passed string label.