ARGoS 3
A parallel, multi-engine simulator for swarm robotics
simulator.cpp
Go to the documentation of this file.
1
7#include "simulator.h"
8
9#include <iostream>
10#include <memory>
11#include <string>
12#include <sys/time.h>
13#include <argos3/core/utility/logging/argos_log.h>
14#include <argos3/core/utility/profiler/profiler.h>
15#include <argos3/core/utility/string_utilities.h>
16#include <argos3/core/utility/plugins/dynamic_loading.h>
17#include <argos3/core/utility/math/rng.h>
18#include <argos3/core/simulator/space/space_no_threads.h>
19#include <argos3/core/simulator/space/space_multi_thread_balance_quantity.h>
20#include <argos3/core/simulator/space/space_multi_thread_balance_length.h>
21#include <argos3/core/simulator/visualization/default_visualization.h>
22#include <argos3/core/simulator/physics_engine/physics_engine.h>
23#include <argos3/core/simulator/loop_functions.h>
24#include <argos3/core/simulator/entity/composable_entity.h>
25#include <argos3/core/simulator/entity/embodied_entity.h>
26
27namespace argos {
28
29 /****************************************/
30 /****************************************/
31
32 CSimulator::CSimulator() :
33 m_pcVisualization(nullptr),
34 m_pcSpace(nullptr),
35 m_pcLoopFunctions(nullptr),
36 m_unMaxSimulationClock(0),
37 m_bWasRandomSeedSet(false),
38 m_unThreads(0),
39 m_pcProfiler(nullptr),
40 m_bHumanReadableProfile(true),
41 m_bRealTimeClock(false),
42 m_bTerminated(false) {}
43
44 /****************************************/
45 /****************************************/
46
47 CSimulator::~CSimulator() {
48 if(IsProfiling()) {
49 delete m_pcProfiler;
50 }
51 /* Delete the visualization */
52 if(m_pcVisualization != nullptr) delete m_pcVisualization;
53 /* Delete all the media */
54 for(auto it = m_mapMedia.begin();
55 it != m_mapMedia.end(); ++it) {
56 delete it->second;
57 }
58 m_mapMedia.clear();
59 m_vecMedia.clear();
60 /* Delete all the physics engines */
61 for(auto it = m_mapPhysicsEngines.begin();
62 it != m_mapPhysicsEngines.end(); ++it) {
63 delete it->second;
64 }
65 m_mapPhysicsEngines.clear();
66 m_vecPhysicsEngines.clear();
67 /* Delete the space and the dynamic linking manager */
68 if(m_pcSpace != nullptr) {
69 delete m_pcSpace;
70 }
71 /* Get rid of all libraries */
72 CDynamicLoading::UnloadAllLibraries();
73 }
74
75 /****************************************/
76 /****************************************/
77
78 CSimulator& CSimulator::GetInstance() {
79 static std::unique_ptr<CSimulator> pcSimulatorInstance(new CSimulator());
80 return *(pcSimulatorInstance.get());
81 }
82
83 /****************************************/
84 /****************************************/
85
86 CPhysicsEngine& CSimulator::GetPhysicsEngine(const std::string& str_id) const {
87 auto it = m_mapPhysicsEngines.find(str_id);
88 ARGOS_ASSERT(it != m_mapPhysicsEngines.end(), "Physics engine \"" << str_id << "\" not found.")
89 return *(it->second);
90 }
91
92 /****************************************/
93 /****************************************/
94
95 TConfigurationNode& CSimulator::GetConfigForController(const std::string& str_id) {
96 auto it = m_mapControllerConfig.find(str_id);
97 if(it == m_mapControllerConfig.end()) {
98 THROW_ARGOSEXCEPTION("Can't find XML configuration for controller id \"" << str_id << "\"");
99 }
100 return *(it->second);
101 }
102
103 /****************************************/
104 /****************************************/
105
106 void CSimulator::Load(ticpp::Document& t_tree) {
107 /* Build configuration tree */
108 m_tConfiguration = t_tree;
109 m_tConfigurationRoot = *m_tConfiguration.FirstChildElement();
110 /* Init the experiment */
111 Init();
112 LOG.Flush();
113 LOGERR.Flush();
114 }
115
116 /****************************************/
117 /****************************************/
118
119 void CSimulator::LoadExperiment() {
120 /* Build configuration tree */
121 m_tConfiguration.LoadFile(m_strExperimentConfigFileName);
122 m_tConfigurationRoot = *m_tConfiguration.FirstChildElement();
123 /* Init the experiment */
124 Init();
125 LOG.Flush();
126 LOGERR.Flush();
127 }
128
129 /****************************************/
130 /****************************************/
131
132 void CSimulator::Init() {
133 /* General configuration */
134 InitFramework(GetNode(m_tConfigurationRoot, "framework"));
135 /* Initialize controllers */
136 InitControllers(GetNode(m_tConfigurationRoot, "controllers"));
137 /* Create loop functions */
138 if(NodeExists(m_tConfigurationRoot, "loop_functions")) {
139 /* User specified a loop_functions section in the XML */
140 InitLoopFunctions(GetNode(m_tConfigurationRoot, "loop_functions"));
141 }
142 else {
143 /* No loop_functions in the XML */
144 m_pcLoopFunctions = new CLoopFunctions;
145 }
146 /* Physics engines */
147 InitPhysics(GetNode(m_tConfigurationRoot, "physics_engines"));
148 /* Media */
149 InitMedia(GetNode(m_tConfigurationRoot, "media"));
150 /* Space */
151 InitSpace(GetNode(m_tConfigurationRoot, "arena"));
152 /* Call user init function */
153 if(NodeExists(m_tConfigurationRoot, "loop_functions")) {
154 m_pcLoopFunctions->Init(GetNode(m_tConfigurationRoot, "loop_functions"));
155 }
156 /* Physics engines */
157 InitPhysics2();
158 /* Media */
159 InitMedia2();
160 /* Initialise visualization */
161 TConfigurationNodeIterator itVisualization;
162 if(NodeExists(m_tConfigurationRoot, "visualization") &&
163 ((itVisualization = itVisualization.begin(&GetNode(m_tConfigurationRoot, "visualization"))) != itVisualization.end())) {
164 InitVisualization(GetNode(m_tConfigurationRoot, "visualization"));
165 }
166 else {
167 LOG << "[INFO] No visualization selected." << std::endl;
168 m_pcVisualization = new CDefaultVisualization();
169 }
170 /* Start profiling, if needed */
171 if(IsProfiling()) {
172 m_pcProfiler->Start();
173 }
174 }
175
176 /****************************************/
177 /****************************************/
178
179 void CSimulator::Reset() {
180 /* Reset terminated flag */
181 m_bTerminated = false;
182 /* if random seed is 0 or is not specified, init with the current timeval */
183 if(m_bWasRandomSeedSet) {
184 CRandom::SetSeedOf("argos", m_unRandomSeed);
185 }
186 else {
187 /* Prepare the default value based on the current clock time */
188 struct timeval sTimeValue;
189 ::gettimeofday(&sTimeValue, nullptr);
190 auto unSeed = static_cast<UInt32>(sTimeValue.tv_usec);
191 CRandom::SetSeedOf("argos", unSeed);
192 m_unRandomSeed = unSeed;
193 LOG << "[INFO] Using random seed = " << m_unRandomSeed << std::endl;
194 }
195 CRandom::GetCategory("argos").ResetRNGs();
196 /* Reset the space */
197 m_pcSpace->Reset();
198 /* Reset the media */
199 for(auto it = m_mapMedia.begin();
200 it != m_mapMedia.end(); ++it) {
201 it->second->Reset();
202 }
203 /* Reset the physics engines */
204 for(auto it = m_mapPhysicsEngines.begin();
205 it != m_mapPhysicsEngines.end(); ++it) {
206 it->second->Reset();
207 }
208 /* Reset the loop functions */
209 m_pcLoopFunctions->Reset();
210 LOG.Flush();
211 LOGERR.Flush();
212 }
213
214 /****************************************/
215 /****************************************/
216
217 void CSimulator::Destroy() {
218 /* Call user destroy function */
219 if (m_pcLoopFunctions != nullptr) {
220 m_pcLoopFunctions->Destroy();
221 delete m_pcLoopFunctions;
222 m_pcLoopFunctions = nullptr;
223 }
224 /* Destroy the visualization */
225 if(m_pcVisualization != nullptr) {
226 m_pcVisualization->Destroy();
227 }
228 /* Destroy simulated space */
229 if(m_pcSpace != nullptr) {
230 m_pcSpace->Destroy();
231 }
232 /* Destroy media */
233 for(auto it = m_mapMedia.begin();
234 it != m_mapMedia.end(); ++it) {
235 it->second->Destroy();
236 delete it->second;
237 }
238 m_mapMedia.clear();
239 m_vecMedia.clear();
240 /* Destroy physics engines */
241 for(auto it = m_mapPhysicsEngines.begin();
242 it != m_mapPhysicsEngines.end(); ++it) {
243 it->second->Destroy();
244 delete it->second;
245 }
246 m_mapPhysicsEngines.clear();
247 m_vecPhysicsEngines.clear();
248 /* Get rid of ARGoS category */
249 if(CRandom::ExistsCategory("argos")) {
250 CRandom::RemoveCategory("argos");
251 }
252 /* Free up factory data */
261 /* Stop profiling and flush the data */
262 if(IsProfiling()) {
263 m_pcProfiler->Stop();
264 m_pcProfiler->Flush(m_bHumanReadableProfile);
265 }
266 LOG.Flush();
267 LOGERR.Flush();
268 }
269
270 /****************************************/
271 /****************************************/
272
273 void CSimulator::Execute() {
274 m_pcVisualization->Execute();
275 }
276
277 /****************************************/
278 /****************************************/
279
280 void CSimulator::UpdateSpace() {
281 /* Update the space */
282 m_pcSpace->Update();
283 }
284
285 /****************************************/
286 /****************************************/
287
288 bool CSimulator::IsExperimentFinished() const {
289 /* Check if the simulation must be terminated */
290 if(m_bTerminated) {
291 return true;
292 }
293 /* Check simulation clock */
294 if (m_unMaxSimulationClock > 0 &&
295 m_pcSpace->GetSimulationClock() >= m_unMaxSimulationClock) {
296 return true;
297 }
298 /* Call loop function */
299 return m_pcLoopFunctions->IsExperimentFinished();
300 }
301
302 /****************************************/
303 /****************************************/
304
305 void CSimulator::InitFramework(TConfigurationNode& t_tree) {
306 try {
307 /* Parse the 'system' node */
308 if(NodeExists(t_tree, "system")) {
309 TConfigurationNode tSystem;
310 tSystem = GetNode(t_tree, "system");
311 GetNodeAttributeOrDefault(tSystem, "threads", m_unThreads, m_unThreads);
312 if(m_unThreads == 0) {
313 LOG << "[INFO] Not using threads" << std::endl;
314 m_pcSpace = new CSpaceNoThreads();
315 }
316 else {
317 LOG << "[INFO] Using " << m_unThreads << " parallel threads" << std::endl;
318 std::string strThreadingMethod = "balance_quantity";
319 GetNodeAttributeOrDefault(tSystem, "method", strThreadingMethod, strThreadingMethod);
320 if(strThreadingMethod == "balance_quantity") {
321 LOG << "[INFO] Chosen method \"balance_quantity\": threads will be assigned the same"
322 << std::endl
323 << "[INFO] number of tasks, independently of the task length."
324 << std::endl;
325 m_pcSpace = new CSpaceMultiThreadBalanceQuantity();
326 }
327 else if(strThreadingMethod == "balance_length") {
328 LOG << "[INFO] Chosen method \"balance_length\": threads will be assigned different"
329 << std::endl
330 << "[INFO] numbers of tasks, depending on the task length."
331 << std::endl;
332 m_pcSpace = new CSpaceMultiThreadBalanceLength();
333 }
334 else {
335 THROW_ARGOSEXCEPTION("Error parsing the <system> tag. Unknown threading method \"" << strThreadingMethod << "\". Available methods: \"balance_quantity\" and \"balance_length\".");
336 }
337 }
338 }
339 else {
340 LOG << "[INFO] Not using threads" << std::endl;
341 m_pcSpace = new CSpaceNoThreads();
342 }
343 /* Get 'experiment' node */
344 TConfigurationNode tExperiment;
345 tExperiment = GetNode(t_tree, "experiment");
346 /* Parse random seed */
347 /* Buffer to hold the random seed */
348 if(!m_bWasRandomSeedSet)
349 GetNodeAttributeOrDefault(tExperiment,
350 "random_seed",
351 m_unRandomSeed,
352 static_cast<UInt32>(0));
353 /* if random seed is 0 or is not specified, init with the current timeval */
354 if(m_unRandomSeed != 0) {
355 CRandom::CreateCategory("argos", m_unRandomSeed);
356 LOG << "[INFO] Using random seed = " << m_unRandomSeed << std::endl;
357 m_bWasRandomSeedSet = true;
358 }
359 else {
360 /* Prepare the default value based on the current clock time */
361 m_bWasRandomSeedSet = false;
362 struct timeval sTimeValue;
363 ::gettimeofday(&sTimeValue, nullptr);
364 auto unSeed = static_cast<UInt32>(sTimeValue.tv_usec);
365 m_unRandomSeed = unSeed;
366 CRandom::CreateCategory("argos", unSeed);
367 LOG << "[INFO] Using random seed = " << unSeed << std::endl;
368 }
369 m_pcRNG = CRandom::CreateRNG("argos");
370 /* Set the simulation clock tick length */
371 UInt32 unTicksPerSec;
372 GetNodeAttribute(tExperiment,
373 "ticks_per_second",
374 unTicksPerSec);
375 CPhysicsEngine::SetSimulationClockTick(1.0 / static_cast<Real>(unTicksPerSec));
376 /* Set the maximum simulation duration (in seconds) */
377 Real fExpLength;
378 GetNodeAttributeOrDefault<Real>(tExperiment,
379 "length",
380 fExpLength,
381 0.0f);
382 m_unMaxSimulationClock = static_cast<UInt32>(fExpLength * unTicksPerSec);
383 LOG << "[INFO] Total experiment length in clock ticks = "
384 << (m_unMaxSimulationClock ? ToString(m_unMaxSimulationClock) : "unlimited")
385 << std::endl;
386 /* Check for the 'real_time' attribute */
387 GetNodeAttributeOrDefault(tExperiment, "real_time", m_bRealTimeClock, m_bRealTimeClock);
388 if(m_bRealTimeClock) {
389 LOG << "[INFO] Using the real-time clock." << std::endl;
390 }
391 /* Get the profiling tag, if present */
392 if(NodeExists(t_tree, "profiling")) {
393 TConfigurationNode& tProfiling = GetNode(t_tree, "profiling");
394 std::string strFile;
395 GetNodeAttribute(tProfiling, "file", strFile);
396 std::string strFormat;
397 GetNodeAttribute(tProfiling, "format", strFormat);
398 if(strFormat == "human_readable") {
399 m_bHumanReadableProfile = true;
400 }
401 else if(strFormat == "table") {
402 m_bHumanReadableProfile = false;
403 }
404 else {
405 THROW_ARGOSEXCEPTION("Unrecognized profile format \"" << strFormat << "\". Accepted values are \"human_readable\" and \"table\".");
406 }
407 bool bTrunc = true;
408 GetNodeAttributeOrDefault(tProfiling, "truncate_file", bTrunc, bTrunc);
409 m_pcProfiler = new CProfiler(strFile, bTrunc);
410 }
411 }
412 catch(CARGoSException& ex) {
413 THROW_ARGOSEXCEPTION_NESTED("Failed to initialize the simulator. Parse error inside the <framework> tag.", ex);
414 }
415 }
416
417 /****************************************/
418 /****************************************/
419
420 void CSimulator::InitLoopFunctions(TConfigurationNode& t_tree) {
421 try {
422 std::string strLibrary, strLabel;
423 GetNodeAttributeOrDefault(t_tree, "library", strLibrary, strLibrary);
424 GetNodeAttribute(t_tree, "label", strLabel);
425 if(! strLibrary.empty()) {
426 CDynamicLoading::LoadLibrary(strLibrary);
427 }
428 m_pcLoopFunctions = CFactory<CLoopFunctions>::New(strLabel);
429 }
430 catch(CARGoSException& ex) {
431 THROW_ARGOSEXCEPTION_NESTED("Error initializing loop functions", ex);
432 }
433 }
434
435 /****************************************/
436 /****************************************/
437
438 void CSimulator::InitControllers(TConfigurationNode& t_tree) {
439 /*
440 * Go through controllers, loading the library of each of them
441 * and storing type, id and XML tree of each of them for later use
442 */
443 if(! t_tree.NoChildren()) {
444 try {
445 std::string strLibrary;
446 std::string strId;
448 for(it = it.begin(&t_tree);
449 it != it.end(); ++it) {
450 /* Get controller id */
451 try {
452 GetNodeAttribute(*it, "id", strId);
453 }
454 catch(CARGoSException& ex) {
455 std::string strValue;
456 it->GetValue(&strValue);
457 THROW_ARGOSEXCEPTION_NESTED("Controller type \"" << strValue << "\" has no assigned id.", ex);
458 }
459 /* Bomb out if id is already in map */
460 if(m_mapControllerConfig.find(strId) != m_mapControllerConfig.end()) {
461 THROW_ARGOSEXCEPTION("Controller id \"" << strId << "\" duplicated");
462 }
463 /* Optionally, process "library" attribute if present */
464 if(NodeAttributeExists(*it, "library")) {
465 /* Get library name */
466 GetNodeAttribute(*it, "library", strLibrary);
467 /* Load library */
468 CDynamicLoading::LoadLibrary(strLibrary);
469 }
470 /* Store XML info in map by id */
471 m_mapControllerConfig.insert(std::pair<std::string, TConfigurationNode*>(strId, &(*it)));
472 }
473 }
474 catch(CARGoSException& ex) {
475 THROW_ARGOSEXCEPTION_NESTED("Error initializing controllers", ex);
476 }
477 }
478 }
479
480 /****************************************/
481 /****************************************/
482
483 void CSimulator::InitSpace(TConfigurationNode& t_tree) {
484 try {
485 m_pcSpace->Init(t_tree);
486 }
487 catch(CARGoSException& ex) {
488 THROW_ARGOSEXCEPTION_NESTED("Failed to initialize the space.", ex);
489 }
490 }
491
492 /****************************************/
493 /****************************************/
494
495 void CSimulator::InitPhysics(TConfigurationNode& t_tree) {
496 try {
497 /* Cycle through the physics engines */
499 for(itEngines = itEngines.begin(&t_tree);
500 itEngines != itEngines.end();
501 ++itEngines) {
502 /* Create the physics engine */
503 CPhysicsEngine* pcEngine = CFactory<CPhysicsEngine>::New(itEngines->Value());
504 try {
505 /* Initialize the engine */
506 pcEngine->Init(*itEngines);
507 /* Check that an engine with that ID does not exist yet */
508 if(m_mapPhysicsEngines.find(pcEngine->GetId()) == m_mapPhysicsEngines.end()) {
509 /* Add it to the lists */
510 m_mapPhysicsEngines[pcEngine->GetId()] = pcEngine;
511 m_vecPhysicsEngines.push_back(pcEngine);
512 }
513 else {
514 /* Duplicate id -> error */
515 THROW_ARGOSEXCEPTION("A physics engine with id \"" << pcEngine->GetId() << "\" exists already. The ids must be unique!");
516 }
517 }
518 catch(CARGoSException& ex) {
519 /* Error while executing engine init, destroy what done to prevent memory leaks */
520 pcEngine->Destroy();
521 delete pcEngine;
522 THROW_ARGOSEXCEPTION_NESTED("Error initializing physics engine type \"" << itEngines->Value() << "\"", ex);
523 }
524 }
525 }
526 catch(CARGoSException& ex) {
527 THROW_ARGOSEXCEPTION_NESTED("Failed to initialize the physics engines. Parse error in the <physics_engines> subtree.", ex);
528 }
529 }
530
531 /****************************************/
532 /****************************************/
533
534 void CSimulator::InitPhysics2() {
535 try {
536 /* Cycle through the physics engines */
537 CPhysicsEngine::TMap::iterator it;
538 for(it = m_mapPhysicsEngines.begin(); it != m_mapPhysicsEngines.end(); ++it) {
539 CPhysicsEngine& cPhysicsEngine = *(it->second);
540 try {
541 /* Initialize the physicsengine */
542 cPhysicsEngine.PostSpaceInit();
543 }
544 catch(CARGoSException& ex) {
545 /* Error while executing physicsengine post space init, destroy what done to prevent memory leaks */
546 std::ostringstream ossMsg;
547 ossMsg << "Error executing post-space initialization of physics engine \"" << cPhysicsEngine.GetId() << "\"";
548 cPhysicsEngine.Destroy();
549 THROW_ARGOSEXCEPTION_NESTED(ossMsg.str(), ex);
550 }
551 }
552 }
553 catch(CARGoSException& ex) {
554 THROW_ARGOSEXCEPTION_NESTED("Failed to initialize the physics engines. Parse error in the <physics_engines> subtree.", ex);
555 }
556 }
557
558 /****************************************/
559 /****************************************/
560
561 void CSimulator::InitMedia(TConfigurationNode& t_tree) {
562 try {
563 /* Cycle through the media */
565 for(itMedia = itMedia.begin(&t_tree);
566 itMedia != itMedia.end();
567 ++itMedia) {
568 /* Create the medium */
569 CMedium* pcMedium = CFactory<CMedium>::New(itMedia->Value());
570 try {
571 /* Initialize the medium */
572 pcMedium->Init(*itMedia);
573 /* Check that an medium with that ID does not exist yet */
574 if(m_mapMedia.find(pcMedium->GetId()) == m_mapMedia.end()) {
575 /* Add it to the lists */
576 m_mapMedia[pcMedium->GetId()] = pcMedium;
577 m_vecMedia.push_back(pcMedium);
578 }
579 else {
580 /* Duplicate id -> error */
581 THROW_ARGOSEXCEPTION("A medium with id \"" << pcMedium->GetId() << "\" exists already. The ids must be unique!");
582 }
583 }
584 catch(CARGoSException& ex) {
585 /* Error while executing medium init, destroy what done to prevent memory leaks */
586 pcMedium->Destroy();
587 delete pcMedium;
588 THROW_ARGOSEXCEPTION_NESTED("Error initializing medium type \"" << itMedia->Value() << "\"", ex);
589 }
590 }
591 }
592 catch(CARGoSException& ex) {
593 THROW_ARGOSEXCEPTION_NESTED("Failed to initialize the media. Parse error in the <media> subtree.", ex);
594 }
595 }
596
597 /****************************************/
598 /****************************************/
599
600 void CSimulator::InitMedia2() {
601 try {
602 /* Cycle through the media */
603 CMedium::TMap::iterator it;
604 for(it = m_mapMedia.begin(); it != m_mapMedia.end(); ++it) {
605 CMedium& cMedium = *(it->second);
606 try {
607 /* Initialize the medium */
608 cMedium.PostSpaceInit();
609 }
610 catch(CARGoSException& ex) {
611 /* Error while executing medium post space init, destroy what done to prevent memory leaks */
612 std::ostringstream ossMsg;
613 ossMsg << "Error executing post-space initialization of medium \"" << cMedium.GetId() << "\"";
614 cMedium.Destroy();
615 THROW_ARGOSEXCEPTION_NESTED(ossMsg.str(), ex);
616 }
617 }
618 }
619 catch(CARGoSException& ex) {
620 THROW_ARGOSEXCEPTION_NESTED("Failed to initialize the media. Parse error in the <media> subtree.", ex);
621 }
622 }
623
624 /****************************************/
625 /****************************************/
626
627 void CSimulator::InitVisualization(TConfigurationNode& t_tree) {
628 try {
629 /* Consider only the first visualization */
630 TConfigurationNodeIterator itVisualization;
631 itVisualization = itVisualization.begin(&t_tree);
632 /* Create the visualization */
633 m_pcVisualization = CFactory<CVisualization>::New(itVisualization->Value());
634 /* Initialize the visualization */
635 m_pcVisualization->Init(*itVisualization);
636 }
637 catch(CARGoSException& ex) {
638 THROW_ARGOSEXCEPTION_NESTED("Failed to initialize the visualization. Parse error in the <visualization> subtree.", ex);
639 }
640 }
641
642 /****************************************/
643 /****************************************/
644
645}
unsigned int UInt32
32-bit unsigned integer.
Definition datatypes.h:97
float Real
Collects all ARGoS code.
Definition datatypes.h:39
#define ARGOS_ASSERT(condition, message)
When code is compiled in debug, this macro throws an ARGoS exception with the passed message if the s...
#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.
CARGoSLog LOGERR(std::cerr, SLogColor(ARGOS_LOG_ATTRIBUTE_BRIGHT, ARGOS_LOG_COLOR_RED))
Definition argos_log.h:180
bool NodeAttributeExists(TConfigurationNode &t_node, const std::string &str_attribute)
Returns true if the specified attribute of a node exists.
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.
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::string ToString(const T &t_value)
Converts the given parameter to a std::string.
void GetNodeAttribute(TConfigurationNode &t_node, const std::string &str_attribute, T &t_buffer)
Returns the value of a node's attribute.
For argos::CTCPSocket::EEvent to be used in std::unordered_set<> and std::unordered_map<>,...
Definition tcp_socket.h:191
A set of hook functions to customize an experimental run.
The core class of ARGOS.
Definition simulator.h:62
Basic factory template.
Definition factory.h:59