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 
13 #include <algorithm>
14 
15 namespace argos {
16 
17  /****************************************/
18  /****************************************/
19 
21  GetNodeAttributeOrDefault(t_tree, "force_constant", m_fForceConstant, m_fForceConstant);
22  GetNodeAttributeOrDefault(t_tree, "max_distance", m_fMaxDistance, m_fMaxDistance);
23  }
24 
25  /****************************************/
26  /****************************************/
27 
29  for(std::shared_ptr<CDynamics3DModel::CAbstractBody>& ptr_body : c_model.GetBodies()) {
31  ptr_body->GetData().Dipoles) {
32  m_vecDipoles.emplace_back(ptr_body,
33  s_dipole.GetField,
34  s_dipole.Offset);
35  }
36  }
37  }
38 
39  /****************************************/
40  /****************************************/
41 
43  auto itRemove =
44  std::remove_if(std::begin(m_vecDipoles),
45  std::end(m_vecDipoles),
46  [&c_model] (const SMagneticDipole& c_magnetic_dipole) {
47  return(&(c_magnetic_dipole.Body->GetModel()) == &c_model);
48  });
49  m_vecDipoles.erase(itRemove, std::end(m_vecDipoles));
50  }
51 
52  /****************************************/
53  /****************************************/
54 
56  if(m_vecDipoles.size() < 2) {
57  /* Nothing to do */
58  return;
59  }
60  for(auto itDipole0 = std::begin(m_vecDipoles);
61  itDipole0 != (std::end(m_vecDipoles) - 1);
62  ++itDipole0) {
63  for(auto itDipole1 = std::next(itDipole0, 1);
64  itDipole1 != std::end(m_vecDipoles);
65  ++itDipole1) {
66  const btTransform& cTransformDipole0 = itDipole0->Offset * itDipole0->Body->GetTransform();
67  const btTransform& cTransformDipole1 = itDipole1->Offset * itDipole1->Body->GetTransform();
68  const btVector3& cPositionDipole0 = cTransformDipole0.getOrigin();
69  const btVector3& cPositionDipole1 = cTransformDipole1.getOrigin();
70  /* calculate the distance between the two magnetic bodies */
71  btScalar fDistance = cPositionDipole0.distance(cPositionDipole1);
72  /* optimization - don't calculate magnetism for dipoles more than m_fMaxDistance apart */
73  if(fDistance > m_fMaxDistance) {
74  continue;
75  }
76  /* perform Barnes-hut algorithm */
77  /* calculate the normalized seperation between the two dipoles, pointing from Dipole1 to Dipole0*/
78  const btVector3& cNormalizedSeparation =
79  btVector3(cPositionDipole0 - cPositionDipole1) / fDistance;
80  /* calculate the rotated field of dipole 0 */
81  const btVector3& cRotatedFieldDipole0 =
82  itDipole0->Body->GetTransform().getBasis() * itDipole0->GetField();
83  /* calculate the rotated field of dipole 1 */
84  const btVector3& cRotatedFieldDipole1 =
85  itDipole1->Body->GetTransform().getBasis() * itDipole1->GetField();
86  /* We now have cRotatedFieldDipole0 and cRotatedFieldDipole1 as the magnetic moments
87  (i.e., m0, m1), cNormalizedSeparation as the direction unit vector from Dipole 1
88  to Dipole 0 (i.e., n), fDistance is the scalar distance between the dipoles (i.e.,
89  d), and B0 is the magnetic flux density at Dipole 0.
90  B0 = u0/4pi * [3n(n.m1) - m1] / d^3
91  T0 = m0 * B0
92  = u0.4pi/d^3 * [3 (m1.n)(m0 * n) - m0 * m1]
93 
94  F0 = grad(m0.B0)
95  = u0.4pi/d^4 * [-15n(m0.n)(m1.n) + 3n(m0.m1) + 3(m0(m1.n)+m1(m0.n))]
96  */
97  /* calculate the intermediate cross and dot products */
98  const btVector3& cCrossProduct01 = cRotatedFieldDipole0.cross(cRotatedFieldDipole1);
99  const btVector3& cCrossProduct0 = cRotatedFieldDipole0.cross(cNormalizedSeparation);
100  const btVector3& cCrossProduct1 = cRotatedFieldDipole1.cross(cNormalizedSeparation);
101  btScalar fDotProduct01 = cRotatedFieldDipole0.dot(cRotatedFieldDipole1);
102  btScalar fDotProduct0 = cRotatedFieldDipole0.dot(cNormalizedSeparation);
103  btScalar fDotProduct1 = cRotatedFieldDipole1.dot(cNormalizedSeparation);
104  /* calculate the magnetic force and torque */
105  const btVector3& cTorque0 =
106  ((3 * fDotProduct1 * cCrossProduct0) - cCrossProduct01) *
107  m_fForceConstant / btPow(fDistance, 3);
108  const btVector3& cTorque1 =
109  ((3 * fDotProduct0 * cCrossProduct1) + cCrossProduct01) *
110  m_fForceConstant / btPow(fDistance, 3);
111  const btVector3& cForce = (m_fForceConstant / btPow(fDistance, 4)) *
112  ((-15 * cNormalizedSeparation * fDotProduct1 * fDotProduct0) +
113  (3 * cNormalizedSeparation * fDotProduct01) +
114  (3 * (fDotProduct1 * cRotatedFieldDipole0 + fDotProduct0 * cRotatedFieldDipole1)));
115  /* apply torques and forces to the bodies */
116  itDipole0->Body->ApplyForce(cForce, (itDipole0->Offset).getOrigin());
117  itDipole0->Body->ApplyTorque(cTorque0);
118  itDipole1->Body->ApplyForce(-cForce, (itDipole1->Offset).getOrigin());
119  itDipole1->Body->ApplyTorque(cTorque1);
120  }
121  }
122  }
123 
124  /****************************************/
125  /****************************************/
126 
128  "magnetism",
129  "Michael Allwright [allsey87@gmail.com]",
130  "1.0",
131  "Applies forces and torques between magnetic dipoles in the simulation",
132  "For a description on how to use this plugin, please consult the documentation\n"
133  "for the dynamics3d physics engine plugin",
134  "Usable");
135 
136  /****************************************/
137  /****************************************/
138 
139 }
The namespace containing all the ARGoS related code.
Definition: ci_actuator.h:12
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")
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.
virtual void RegisterModel(CDynamics3DModel &c_model)
virtual void UnregisterModel(CDynamics3DModel &c_model)
virtual void Init(TConfigurationNode &t_tree)
std::vector< std::shared_ptr< CAbstractBody > > & GetBodies()