ARGoS 3
A parallel, multi-engine simulator for swarm robotics
physics_engine.cpp
Go to the documentation of this file.
1
6
7#include <cstdlib>
8#include "physics_engine.h"
9#include <argos3/core/utility/logging/argos_log.h>
10#include <argos3/core/utility/math/vector3.h>
11#include <argos3/core/utility/string_utilities.h>
12#include <argos3/core/simulator/simulator.h>
13#include <argos3/core/simulator/space/space.h>
14#include <argos3/core/simulator/entity/entity.h>
15
16namespace argos {
17
18 /****************************************/
19 /****************************************/
20
22 const CRay3& c_ray) {
23 /* This variable is instantiated at the first call of this function, once and forever */
24 static CSimulator& cSimulator = CSimulator::GetInstance();
25 /* Clear data */
26 t_data.clear();
27 /* Create a reference to the vector of physics engines */
28 CPhysicsEngine::TVector& vecEngines = cSimulator.GetPhysicsEngines();
29 /* Ask each engine to perform the ray query */
30 for(size_t i = 0; i < vecEngines.size(); ++i)
31 vecEngines[i]->CheckIntersectionWithRay(t_data, c_ray);
32 /* Remove duplicates */
33 // TODO
34 /* Return true if an intersection was found */
35 return !t_data.empty();
36 }
37
38 /****************************************/
39 /****************************************/
40
42 const CRay3& c_ray) {
43 /* Initialize s_item */
44 s_item.IntersectedEntity = nullptr;
45 s_item.TOnRay = 1.0f;
46 /* Perform full ray query */
49 /* Go through intersections and find the closest */
50 for(size_t i = 0; i < tData.size(); ++i) {
51 if(s_item.TOnRay > tData[i].TOnRay)
52 s_item = tData[i];
53 }
54 /* Return true if an intersection was found */
55 return (s_item.IntersectedEntity != nullptr);
56 }
57
58 /****************************************/
59 /****************************************/
60
62 const CRay3& c_ray,
63 CEmbodiedEntity& c_entity) {
64 /* Initialize s_item */
65 s_item.IntersectedEntity = nullptr;
66 s_item.TOnRay = 1.0f;
67 /* Perform full ray query */
70 /* Go through intersections and find the closest */
71 for(size_t i = 0; i < tData.size(); ++i) {
72 if(s_item.TOnRay > tData[i].TOnRay &&
73 &c_entity != tData[i].IntersectedEntity) {
74 s_item = tData[i];
75 }
76 }
77 /* Return true if an intersection was found */
78 return (s_item.IntersectedEntity != nullptr);
79 }
80
81 /****************************************/
82 /****************************************/
83
84 /* The default value of the simulation clock tick */
85 Real CPhysicsEngine::m_fSimulationClockTick = 0.1f;
86 Real CPhysicsEngine::m_fInverseSimulationClockTick = 1.0f / CPhysicsEngine::m_fSimulationClockTick;
87
88 /****************************************/
89 /****************************************/
90
92 TopFace(nullptr),
93 BottomFace(nullptr) {
94 }
95
96 /****************************************/
97 /****************************************/
98
100 try {
101 /* Parse top face, if specified */
102 if(NodeExists(t_node, "top")) {
103 TConfigurationNode& tNode = GetNode(t_node, "top");
105 GetNodeAttribute(tNode, "height", TopFace->Height);
106 }
107 /* Parse bottom face, if specified */
108 if(NodeExists(t_node, "bottom")) {
109 TConfigurationNode& tNode = GetNode(t_node, "bottom");
111 GetNodeAttribute(tNode, "height", BottomFace->Height);
112 }
113 /* Parse side faces, if specified */
114 if(NodeExists(t_node, "sides")) {
115 CVector2 cFirstPoint, cLastPoint, cCurPoint;
116 std::string strConnectWith;
117 TConfigurationNode& tNode = GetNode(t_node, "sides");
118 TConfigurationNodeIterator tVertexIt("vertex");
119 /* Get the first vertex */
120 tVertexIt = tVertexIt.begin(&tNode);
121 if(tVertexIt == tVertexIt.end()) {
122 THROW_ARGOSEXCEPTION("No <vertex> specified within <sides> section");
123 }
124 GetNodeAttribute(*tVertexIt, "point", cFirstPoint);
125 cLastPoint = cFirstPoint;
126 /* Go through the other vertices */
127 ++tVertexIt;
128 while(tVertexIt != tVertexIt.end()) {
129 /* Read vertex data and fill in segment struct */
130 GetNodeAttribute(*tVertexIt, "point", cCurPoint);
131 auto* psFace = new SVerticalFace;
132 psFace->BaseSegment.SetStart(cLastPoint);
133 psFace->BaseSegment.SetEnd(cCurPoint);
134 SideFaces.push_back(psFace);
135 /* Next vertex */
136 cLastPoint = cCurPoint;
137 ++tVertexIt;
138 }
139 /* Make sure that the boundary is a closed path */
140 if(SideFaces.size() < 3) {
141 THROW_ARGOSEXCEPTION("The <sides> path is not closed; at least 3 segments must be specified");
142 }
143 if(cLastPoint != cFirstPoint) {
144 auto* psFace = new SVerticalFace;
145 psFace->BaseSegment.SetStart(cLastPoint);
146 psFace->BaseSegment.SetEnd(cFirstPoint);
147 SideFaces.push_back(psFace);
148 }
149 }
150 }
151 catch(CARGoSException& ex) {
152 THROW_ARGOSEXCEPTION_NESTED("Error parsing physics engine <boundaries> information", ex);
153 }
154 }
155
156 /****************************************/
157 /****************************************/
158
160 if(TopFace) delete TopFace;
161 if(BottomFace) delete BottomFace;
162 while(!SideFaces.empty()) {
163 delete SideFaces.back();
164 SideFaces.pop_back();
165 }
166 }
167
168 /****************************************/
169 /****************************************/
170
172 return TopFace || BottomFace || (!SideFaces.empty());
173 }
174
175 /****************************************/
176 /****************************************/
177
179 m_unIterations(10),
180 m_fPhysicsClockTick(m_fSimulationClockTick) {}
181
182 /****************************************/
183 /****************************************/
184
186 try {
187 /* Get id from the XML */
188 GetNodeAttribute(t_tree, "id", m_strId);
189 /* Get iterations per time step */
190 GetNodeAttributeOrDefault(t_tree, "iterations", m_unIterations, m_unIterations);
191 m_fPhysicsClockTick = GetSimulationClockTick() / static_cast<Real>(m_unIterations);
192 LOG << "[INFO] The physics engine \""
193 << GetId()
194 << "\" will perform "
195 << m_unIterations
196 << " iterations per tick (dt = "
197 << GetPhysicsClockTick() << " sec)"
198 << std::endl;
199 /* Parse the boundary definition, if necessary */
200 if(NodeExists(t_tree, "boundaries")) {
201 m_sVolume.Init(GetNode(t_tree, "boundaries"));
202 }
203 }
204 catch(CARGoSException& ex) {
205 THROW_ARGOSEXCEPTION_NESTED("Error initializing a physics engine", ex);
206 }
207 }
208
209 /****************************************/
210 /****************************************/
211
213 if(! IsEntityTransferActive()) {
214 /*
215 * The engine has no boundaries, so the wanted point is in for sure
216 */
217 return true;
218 }
219 else {
220 /*
221 * Check the boundaries
222 */
223 /* Check top/bottom boundaries */
224 if((m_sVolume.TopFace && c_point.GetZ() > m_sVolume.TopFace->Height) ||
225 (m_sVolume.BottomFace && c_point.GetZ() < m_sVolume.BottomFace->Height)) {
226 return false;
227 }
228 /* Check side boundaries */
229 for(size_t i = 0; i < GetVolume().SideFaces.size(); ++i) {
230 const CVector2& cP0 = GetVolume().SideFaces[i]->BaseSegment.GetStart();
231 const CVector2& cP1 = GetVolume().SideFaces[i]->BaseSegment.GetEnd();
232 Real fCriterion =
233 (c_point.GetY() - cP0.GetY()) * (cP1.GetX() - cP0.GetX()) -
234 (c_point.GetX() - cP0.GetX()) * (cP1.GetY() - cP0.GetY());
235 if(fCriterion < 0.0f) {
236 return false;
237 }
238 }
239 return true;
240 }
241 }
242
243 /****************************************/
244 /****************************************/
245
247 m_vecTransferData.push_back(&c_entity);
248 }
249
250 /****************************************/
251 /****************************************/
252
254 for(size_t i = 0; i < m_vecTransferData.size(); ++i) {
255 RemoveEntity(m_vecTransferData[i]->GetRootEntity());
257 }
258 m_vecTransferData.clear();
259 }
260
261 /****************************************/
262 /****************************************/
263
265 return m_fSimulationClockTick;
266 }
267
268 /****************************************/
269 /****************************************/
270
272 return m_fInverseSimulationClockTick;
273 }
274
275 /****************************************/
276 /****************************************/
277
278 void CPhysicsEngine::SetSimulationClockTick(Real f_simulation_clock_tick) {
279 LOG << "[INFO] Using simulation clock tick = " << f_simulation_clock_tick << std::endl;
280 m_fSimulationClockTick = f_simulation_clock_tick;
281 m_fInverseSimulationClockTick = 1.0f / f_simulation_clock_tick;
282 }
283
284 /****************************************/
285 /****************************************/
286
287}
float Real
Collects all ARGoS code.
Definition datatypes.h:39
#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.
The namespace containing all the ARGoS related code.
Definition ci_actuator.h:12
ticpp::Iterator< ticpp::Element > TConfigurationNodeIterator
The iterator for the ARGoS configuration XML node.
bool GetClosestEmbodiedEntityIntersectedByRay(SEmbodiedEntityIntersectionItem &s_item, const CRay3 &c_ray)
Returns the closest intersection with an embodied entity to the ray start.
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.
CARGoSLog LOG(std::cout, SLogColor(ARGOS_LOG_ATTRIBUTE_BRIGHT, ARGOS_LOG_COLOR_GREEN))
Definition argos_log.h:179
bool NodeExists(TConfigurationNode &t_node, const std::string &str_tag)
Given a tree root node, returns true if one of its child nodes has the wanted name.
bool GetEmbodiedEntitiesIntersectedByRay(TEmbodiedEntityIntersectionData &t_data, const CRay3 &c_ray)
Checks whether the given ray intersects any entity.
TConfigurationNode & GetNode(TConfigurationNode &t_node, const std::string &str_tag)
Given a tree root node, returns the first of its child nodes with the wanted name.
std::vector< SEmbodiedEntityIntersectionItem > TEmbodiedEntityIntersectionData
void GetNodeAttribute(TConfigurationNode &t_node, const std::string &str_attribute, T &t_buffer)
Returns the value of a node's attribute.
This entity is a link to a body in the physics engine.
static Real GetSimulationClockTick()
Returns the simulation clock tick.
virtual bool IsPointContained(const CVector3 &c_point)
Returns true if the given point is contained in this physics engine.
virtual void ScheduleEntityForTransfer(CEmbodiedEntity &c_entity)
Schedules an entity of transfer.
std::vector< CPhysicsEngine * > TVector
static Real GetInverseSimulationClockTick()
Returns the inverse of GetSimulationClockTick().
SVolume & GetVolume()
Returns the boundary faces for the volume associated to this engine.
virtual void Init(TConfigurationNode &t_tree)
Initializes the resource.
const std::string & GetId() const
Returns the id of this physics engine.
Real GetPhysicsClockTick() const
Returns the length of the physics engine tick.
static void SetSimulationClockTick(Real f_simulation_clock_tick)
Sets the simulation clock tick.
virtual void TransferEntities()
Executes the transfer of entities to other engines.
bool IsEntityTransferActive() const
Returns true if entity transfer is active for this engine.
virtual bool RemoveEntity(CEntity &c_entity)=0
Removes an entity from the physics engine.
A boundary face for top/bottom parts of the volume.
A boundary face for side parts of the volume.
std::vector< SVerticalFace * > SideFaces
void Init(TConfigurationNode &t_node)
The core class of ARGOS.
Definition simulator.h:62
CSpace & GetSpace() const
Returns a reference to the simulated space.
Definition simulator.h:104
static CSimulator & GetInstance()
Returns the instance to the CSimulator class.
Definition simulator.cpp:78
CPhysicsEngine::TVector & GetPhysicsEngines()
Returns the list of currently existing physics engines.
Definition simulator.h:119
virtual void AddEntityToPhysicsEngine(CEmbodiedEntity &c_entity)
Definition space.cpp:186
The exception that wraps all errors in ARGoS.
void SetStart(const CVector2 &c_start)
Definition ray2.h:44
A 2D vector class.
Definition vector2.h:27
Real GetY() const
Returns the y coordinate of this vector.
Definition vector2.h:110
Real GetX() const
Returns the x coordinate of this vector.
Definition vector2.h:94
A 3D vector class.
Definition vector3.h:31
Real GetX() const
Returns the x coordinate of this vector.
Definition vector3.h:105
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