12 #include <argos3/core/utility/logging/argos_log.h>
13 #include <argos3/core/utility/profiler/profiler.h>
14 #include <argos3/core/utility/string_utilities.h>
15 #include <argos3/core/utility/plugins/dynamic_loading.h>
16 #include <argos3/core/utility/math/rng.h>
17 #include <argos3/core/simulator/space/space_no_threads.h>
18 #include <argos3/core/simulator/space/space_multi_thread_balance_quantity.h>
19 #include <argos3/core/simulator/space/space_multi_thread_balance_length.h>
20 #include <argos3/core/simulator/visualization/default_visualization.h>
21 #include <argos3/core/simulator/physics_engine/physics_engine.h>
22 #include <argos3/core/simulator/loop_functions.h>
23 #include <argos3/core/simulator/entity/composable_entity.h>
24 #include <argos3/core/simulator/entity/embodied_entity.h>
31 #if __cplusplus >= 201103L
33 using auto_ptr = std::unique_ptr<T>;
41 CSimulator::CSimulator() :
42 m_pcVisualization(NULL),
44 m_pcLoopFunctions(NULL),
45 m_unMaxSimulationClock(0),
46 m_bWasRandomSeedSet(false),
49 m_bHumanReadableProfile(true),
50 m_bRealTimeClock(false),
51 m_bTerminated(false) {}
56 CSimulator::~CSimulator() {
61 if(m_pcVisualization != NULL)
delete m_pcVisualization;
63 for(CMedium::TMap::iterator it = m_mapMedia.begin();
64 it != m_mapMedia.end(); ++it) {
70 for(CPhysicsEngine::TMap::iterator it = m_mapPhysicsEngines.begin();
71 it != m_mapPhysicsEngines.end(); ++it) {
74 m_mapPhysicsEngines.clear();
75 m_vecPhysicsEngines.clear();
77 if(m_pcSpace != NULL) {
81 CDynamicLoading::UnloadAllLibraries();
88 static auto_ptr<CSimulator> pcSimulatorInstance(
new CSimulator());
89 return *(pcSimulatorInstance.get());
95 CPhysicsEngine& CSimulator::GetPhysicsEngine(
const std::string& str_id)
const {
96 CPhysicsEngine::TMap::const_iterator it = m_mapPhysicsEngines.find(str_id);
97 ARGOS_ASSERT(it != m_mapPhysicsEngines.end(),
"Physics engine \"" << str_id <<
"\" not found.")
105 TControllerConfigurationMap::iterator it = m_mapControllerConfig.find(str_id);
106 if(it == m_mapControllerConfig.end()) {
109 return *(it->second);
115 void CSimulator::LoadExperiment() {
117 m_tConfiguration.LoadFile(m_strExperimentConfigFileName);
118 m_tConfigurationRoot = *m_tConfiguration.FirstChildElement();
128 void CSimulator::Init() {
130 InitFramework(
GetNode(m_tConfigurationRoot,
"framework"));
132 InitControllers(
GetNode(m_tConfigurationRoot,
"controllers"));
134 if(
NodeExists(m_tConfigurationRoot,
"loop_functions")) {
136 InitLoopFunctions(
GetNode(m_tConfigurationRoot,
"loop_functions"));
143 InitPhysics(
GetNode(m_tConfigurationRoot,
"physics_engines"));
145 InitMedia(
GetNode(m_tConfigurationRoot,
"media"));
147 InitSpace(
GetNode(m_tConfigurationRoot,
"arena"));
149 if(
NodeExists(m_tConfigurationRoot,
"loop_functions")) {
150 m_pcLoopFunctions->Init(
GetNode(m_tConfigurationRoot,
"loop_functions"));
158 if(
NodeExists(m_tConfigurationRoot,
"visualization") &&
159 ((itVisualization = itVisualization.begin(&
GetNode(m_tConfigurationRoot,
"visualization"))) != itVisualization.end())) {
160 InitVisualization(
GetNode(m_tConfigurationRoot,
"visualization"));
163 LOG <<
"[INFO] No visualization selected." << std::endl;
168 m_pcProfiler->Start();
175 void CSimulator::Reset() {
177 m_bTerminated =
false;
179 if(m_bWasRandomSeedSet) {
180 CRandom::SetSeedOf(
"argos", m_unRandomSeed);
184 struct timeval sTimeValue;
185 ::gettimeofday(&sTimeValue, NULL);
186 UInt32 unSeed =
static_cast<UInt32>(sTimeValue.tv_usec);
187 CRandom::SetSeedOf(
"argos", unSeed);
188 m_unRandomSeed = unSeed;
189 LOG <<
"[INFO] Using random seed = " << m_unRandomSeed << std::endl;
191 CRandom::GetCategory(
"argos").ResetRNGs();
195 for(CMedium::TMap::iterator it = m_mapMedia.begin();
196 it != m_mapMedia.end(); ++it) {
200 for(CPhysicsEngine::TMap::iterator it = m_mapPhysicsEngines.begin();
201 it != m_mapPhysicsEngines.end(); ++it) {
205 m_pcLoopFunctions->Reset();
213 void CSimulator::Destroy() {
215 if (m_pcLoopFunctions != NULL) {
216 m_pcLoopFunctions->Destroy();
217 delete m_pcLoopFunctions;
218 m_pcLoopFunctions = NULL;
221 if(m_pcVisualization != NULL) {
222 m_pcVisualization->Destroy();
225 if(m_pcSpace != NULL) {
226 m_pcSpace->Destroy();
229 for(CMedium::TMap::iterator it = m_mapMedia.begin();
230 it != m_mapMedia.end(); ++it) {
231 it->second->Destroy();
237 for(CPhysicsEngine::TMap::iterator it = m_mapPhysicsEngines.begin();
238 it != m_mapPhysicsEngines.end(); ++it) {
239 it->second->Destroy();
242 m_mapPhysicsEngines.clear();
243 m_vecPhysicsEngines.clear();
245 if(CRandom::ExistsCategory(
"argos")) {
246 CRandom::RemoveCategory(
"argos");
259 m_pcProfiler->Stop();
260 m_pcProfiler->Flush(m_bHumanReadableProfile);
269 void CSimulator::Execute() {
270 m_pcVisualization->Execute();
276 void CSimulator::UpdateSpace() {
284 bool CSimulator::IsExperimentFinished()
const {
290 if (m_unMaxSimulationClock > 0 &&
291 m_pcSpace->GetSimulationClock() >= m_unMaxSimulationClock) {
295 return m_pcLoopFunctions->IsExperimentFinished();
306 tSystem =
GetNode(t_tree,
"system");
308 if(m_unThreads == 0) {
309 LOG <<
"[INFO] Not using threads" << std::endl;
313 LOG <<
"[INFO] Using " << m_unThreads <<
" parallel threads" << std::endl;
314 std::string strThreadingMethod =
"balance_quantity";
316 if(strThreadingMethod ==
"balance_quantity") {
317 LOG <<
"[INFO] Chosen method \"balance_quantity\": threads will be assigned the same"
319 <<
"[INFO] number of tasks, independently of the task length."
321 m_pcSpace =
new CSpaceMultiThreadBalanceQuantity();
323 else if(strThreadingMethod ==
"balance_length") {
324 LOG <<
"[INFO] Chosen method \"balance_length\": threads will be assigned different"
326 <<
"[INFO] numbers of tasks, depending on the task length."
328 m_pcSpace =
new CSpaceMultiThreadBalanceLength();
331 THROW_ARGOSEXCEPTION(
"Error parsing the <system> tag. Unknown threading method \"" << strThreadingMethod <<
"\". Available methods: \"balance_quantity\" and \"balance_length\".");
336 LOG <<
"[INFO] Not using threads" << std::endl;
337 m_pcSpace =
new CSpaceNoThreads();
341 tExperiment =
GetNode(t_tree,
"experiment");
344 if(!m_bWasRandomSeedSet)
350 if(m_unRandomSeed != 0) {
351 CRandom::CreateCategory(
"argos", m_unRandomSeed);
352 LOG <<
"[INFO] Using random seed = " << m_unRandomSeed << std::endl;
353 m_bWasRandomSeedSet =
true;
357 m_bWasRandomSeedSet =
false;
358 struct timeval sTimeValue;
359 ::gettimeofday(&sTimeValue, NULL);
360 UInt32 unSeed =
static_cast<UInt32>(sTimeValue.tv_usec);
361 m_unRandomSeed = unSeed;
362 CRandom::CreateCategory(
"argos", unSeed);
363 LOG <<
"[INFO] Using random seed = " << unSeed << std::endl;
365 m_pcRNG = CRandom::CreateRNG(
"argos");
371 CPhysicsEngine::SetSimulationClockTick(1.0 /
static_cast<Real>(unTicksPerSec));
374 GetNodeAttributeOrDefault<Real>(tExperiment,
378 m_unMaxSimulationClock = fExpLength * unTicksPerSec;
379 LOG <<
"[INFO] Total experiment length in clock ticks = "
380 << (m_unMaxSimulationClock ?
ToString(m_unMaxSimulationClock) :
"unlimited")
384 if(m_bRealTimeClock) {
385 LOG <<
"[INFO] Using the real-time clock." << std::endl;
392 std::string strFormat;
394 if(strFormat ==
"human_readable") {
395 m_bHumanReadableProfile =
true;
397 else if(strFormat ==
"table") {
398 m_bHumanReadableProfile =
false;
401 THROW_ARGOSEXCEPTION(
"Unrecognized profile format \"" << strFormat <<
"\". Accepted values are \"human_readable\" and \"table\".");
405 m_pcProfiler =
new CProfiler(strFile, bTrunc);
408 catch(CARGoSException& ex) {
418 std::string strLibrary, strLabel;
421 if(! strLibrary.empty()) {
422 CDynamicLoading::LoadLibrary(strLibrary);
424 m_pcLoopFunctions = CFactory<CLoopFunctions>::New(strLabel);
426 catch(CARGoSException& ex) {
439 if(! t_tree.NoChildren()) {
441 std::string strLibrary;
444 for(it = it.begin(&t_tree);
445 it != it.end(); ++it) {
450 catch(CARGoSException& ex) {
451 std::string strValue;
452 it->GetValue(&strValue);
456 if(m_mapControllerConfig.find(strId) != m_mapControllerConfig.end()) {
464 CDynamicLoading::LoadLibrary(strLibrary);
467 m_mapControllerConfig.insert(std::pair<std::string, TConfigurationNode*>(strId, &(*it)));
470 catch(CARGoSException& ex) {
481 m_pcSpace->Init(t_tree);
483 catch(CARGoSException& ex) {
495 for(itEngines = itEngines.begin(&t_tree);
496 itEngines != itEngines.end();
499 CPhysicsEngine* pcEngine = CFactory<CPhysicsEngine>::New(itEngines->Value());
502 pcEngine->Init(*itEngines);
504 if(m_mapPhysicsEngines.find(pcEngine->GetId()) == m_mapPhysicsEngines.end()) {
506 m_mapPhysicsEngines[pcEngine->GetId()] = pcEngine;
507 m_vecPhysicsEngines.push_back(pcEngine);
511 THROW_ARGOSEXCEPTION(
"A physics engine with id \"" << pcEngine->GetId() <<
"\" exists already. The ids must be unique!");
514 catch(CARGoSException& ex) {
522 catch(CARGoSException& ex) {
530 void CSimulator::InitPhysics2() {
533 CPhysicsEngine::TMap::iterator it;
534 for(it = m_mapPhysicsEngines.begin(); it != m_mapPhysicsEngines.end(); ++it) {
535 CPhysicsEngine& cPhysicsEngine = *(it->second);
538 cPhysicsEngine.PostSpaceInit();
540 catch(CARGoSException& ex) {
542 std::ostringstream ossMsg;
543 ossMsg <<
"Error executing post-space initialization of physics engine \"" << cPhysicsEngine.GetId() <<
"\"";
544 cPhysicsEngine.Destroy();
549 catch(CARGoSException& ex) {
561 for(itMedia = itMedia.begin(&t_tree);
562 itMedia != itMedia.end();
565 CMedium* pcMedium = CFactory<CMedium>::New(itMedia->Value());
568 pcMedium->Init(*itMedia);
570 if(m_mapMedia.find(pcMedium->GetId()) == m_mapMedia.end()) {
572 m_mapMedia[pcMedium->GetId()] = pcMedium;
573 m_vecMedia.push_back(pcMedium);
577 THROW_ARGOSEXCEPTION(
"A medium with id \"" << pcMedium->GetId() <<
"\" exists already. The ids must be unique!");
580 catch(CARGoSException& ex) {
588 catch(CARGoSException& ex) {
596 void CSimulator::InitMedia2() {
599 CMedium::TMap::iterator it;
600 for(it = m_mapMedia.begin(); it != m_mapMedia.end(); ++it) {
601 CMedium& cMedium = *(it->second);
604 cMedium.PostSpaceInit();
606 catch(CARGoSException& ex) {
608 std::ostringstream ossMsg;
609 ossMsg <<
"Error executing post-space initialization of medium \"" << cMedium.GetId() <<
"\"";
615 catch(CARGoSException& ex) {
627 itVisualization = itVisualization.begin(&t_tree);
629 m_pcVisualization = CFactory<CVisualization>::New(itVisualization->Value());
631 m_pcVisualization->Init(*itVisualization);
633 catch(CARGoSException& ex) {