ARGoS  3
A parallel, multi-engine simulator for swarm robotics
core/simulator/simulator.cpp
Go to the documentation of this file.
00001 
00007 #include "simulator.h"
00008 
00009 #include <iostream>
00010 #include <string>
00011 #include <sys/time.h>
00012 #include <argos3/core/utility/logging/argos_log.h>
00013 #include <argos3/core/utility/profiler/profiler.h>
00014 #include <argos3/core/utility/string_utilities.h>
00015 #include <argos3/core/utility/plugins/dynamic_loading.h>
00016 #include <argos3/core/utility/math/rng.h>
00017 #include <argos3/core/simulator/space/space_no_threads.h>
00018 #include <argos3/core/simulator/space/space_multi_thread_balance_quantity.h>
00019 #include <argos3/core/simulator/space/space_multi_thread_balance_length.h>
00020 #include <argos3/core/simulator/visualization/visualization.h>
00021 #include <argos3/core/simulator/physics_engine/physics_engine.h>
00022 #include <argos3/core/simulator/loop_functions.h>
00023 #include <argos3/core/simulator/entity/composable_entity.h>
00024 #include <argos3/core/simulator/entity/embodied_entity.h>
00025 
00026 namespace argos {
00027 
00028    /****************************************/
00029    /****************************************/
00030 
00031    CSimulator::CSimulator() :
00032       m_pcVisualization(NULL),
00033       m_pcSpace(NULL),
00034       m_pcLoopFunctions(NULL),
00035       m_unMaxSimulationClock(0),
00036       m_bWasRandomSeedSet(false),
00037       m_unThreads(0),
00038       m_pcProfiler(NULL),
00039       m_bHumanReadableProfile(true) {}
00040 
00041    /****************************************/
00042    /****************************************/
00043 
00044    CSimulator::~CSimulator() {
00045       if(IsProfiling()) {
00046          delete m_pcProfiler;
00047       }
00048       /* Delete the visualization */
00049       if(m_pcVisualization != NULL) delete m_pcVisualization;
00050       /* Delete all the media */
00051       for(CMedium::TMap::iterator it = m_mapMedia.begin();
00052           it != m_mapMedia.end(); ++it) {
00053          delete it->second;
00054       }
00055       m_mapMedia.clear();
00056       m_vecMedia.clear();
00057       /* Delete all the physics engines */
00058       for(CPhysicsEngine::TMap::iterator it = m_mapPhysicsEngines.begin();
00059           it != m_mapPhysicsEngines.end(); ++it) {
00060          delete it->second;
00061       }
00062       m_mapPhysicsEngines.clear();
00063       m_vecPhysicsEngines.clear();
00064       /* Delete the space and the dynamic linking manager */
00065       if(m_pcSpace != NULL) {
00066          delete m_pcSpace;
00067       }
00068    }
00069 
00070    /****************************************/
00071    /****************************************/
00072 
00073    CSimulator& CSimulator::GetInstance() {
00074       static std::auto_ptr<CSimulator> pcSimulatorInstance(new CSimulator());
00075       return *(pcSimulatorInstance.get());
00076    }
00077 
00078    /****************************************/
00079    /****************************************/
00080 
00081    CPhysicsEngine& CSimulator::GetPhysicsEngine(const std::string& str_id) const {
00082       CPhysicsEngine::TMap::const_iterator it = m_mapPhysicsEngines.find(str_id);
00083       ARGOS_ASSERT(it != m_mapPhysicsEngines.end(), "Physics engine \"" << str_id << "\" not found.")
00084          return *(it->second);
00085    }
00086 
00087    /****************************************/
00088    /****************************************/
00089 
00090    TConfigurationNode& CSimulator::GetConfigForController(const std::string& str_id) {
00091       TControllerConfigurationMap::iterator it = m_mapControllerConfig.find(str_id);
00092       if(it == m_mapControllerConfig.end()) {
00093          THROW_ARGOSEXCEPTION("Can't find XML configuration for controller id \"" << str_id << "\"");
00094       }
00095       return *(it->second);
00096    }
00097 
00098    /****************************************/
00099    /****************************************/
00100 
00101    void CSimulator::LoadExperiment() {
00102       /* Build configuration tree */
00103       m_tConfiguration.LoadFile(m_strExperimentConfigFileName);
00104       m_tConfigurationRoot = *m_tConfiguration.FirstChildElement();
00105       /* Init the experiment */
00106       Init();
00107       LOG.Flush();
00108       LOGERR.Flush();
00109    }
00110 
00111    /****************************************/
00112    /****************************************/
00113 
00114    void CSimulator::Init() {
00115       /* General configuration */
00116       InitFramework(GetNode(m_tConfigurationRoot, "framework"));
00117       /* Initialize controllers */
00118       InitControllers(GetNode(m_tConfigurationRoot, "controllers"));
00119       /* Create loop functions */
00120       if(NodeExists(m_tConfigurationRoot, "loop_functions")) {
00121          /* User specified a loop_functions section in the XML */
00122          InitLoopFunctions(GetNode(m_tConfigurationRoot, "loop_functions"));
00123       }
00124       else {
00125          /* No loop_functions in the XML */
00126          m_pcLoopFunctions = new CLoopFunctions;
00127       }
00128       /* Physics engines */
00129       InitPhysics(GetNode(m_tConfigurationRoot, "physics_engines"));
00130       /* Media */
00131       InitMedia(GetNode(m_tConfigurationRoot, "media"));
00132       /* Space */
00133       InitSpace(GetNode(m_tConfigurationRoot, "arena"));
00134       /* Call user init function */
00135       if(NodeExists(m_tConfigurationRoot, "loop_functions")) {
00136          m_pcLoopFunctions->Init(GetNode(m_tConfigurationRoot, "loop_functions"));
00137       }
00138       /* Media */
00139       InitMedia2();
00140       /* Initialise visualization */
00141       TConfigurationNodeIterator itVisualization;
00142       if(NodeExists(m_tConfigurationRoot, "visualization") &&
00143          ((itVisualization = itVisualization.begin(&GetNode(m_tConfigurationRoot, "visualization"))) != itVisualization.end())) {
00144          InitVisualization(GetNode(m_tConfigurationRoot, "visualization"));
00145       }
00146       else {
00147          LOG << "[INFO] No visualization selected." << std::endl;
00148          m_pcVisualization = new CVisualization();
00149       }
00150       /* Start profiling, if needed */
00151       if(IsProfiling()) {
00152          m_pcProfiler->Start();
00153       }
00154    }
00155 
00156    /****************************************/
00157    /****************************************/
00158 
00159    void CSimulator::Reset() {
00160       /* if random seed is 0 or is not specified, init with the current timeval */
00161       if(m_bWasRandomSeedSet) {
00162          CRandom::SetSeedOf("argos", m_unRandomSeed);
00163       }
00164       else {
00165          /* Prepare the default value based on the current clock time */
00166          struct timeval sTimeValue;
00167          ::gettimeofday(&sTimeValue, NULL);
00168          UInt32 unSeed = static_cast<UInt32>(sTimeValue.tv_usec);
00169          CRandom::SetSeedOf("argos", unSeed);
00170          m_unRandomSeed = unSeed;
00171          LOG << "[INFO] Using random seed = " << m_unRandomSeed << std::endl;
00172       }
00173       CRandom::GetCategory("argos").ResetRNGs();
00174       /* Reset the space */
00175       m_pcSpace->Reset();
00176       /* Reset the media */
00177       for(CMedium::TMap::iterator it = m_mapMedia.begin();
00178           it != m_mapMedia.end(); ++it) {
00179          it->second->Reset();
00180       }
00181       /* Reset the physics engines */
00182       for(CPhysicsEngine::TMap::iterator it = m_mapPhysicsEngines.begin();
00183           it != m_mapPhysicsEngines.end(); ++it) {
00184          it->second->Reset();
00185       }
00186       /* Reset the loop functions */
00187       m_pcLoopFunctions->Reset();
00188       LOG.Flush();
00189       LOGERR.Flush();
00190    }
00191 
00192    /****************************************/
00193    /****************************************/
00194 
00195    void CSimulator::Destroy() {
00196       /* Call user destroy function */
00197       if (m_pcLoopFunctions != NULL) {
00198          m_pcLoopFunctions->Destroy();
00199          delete m_pcLoopFunctions;
00200          m_pcLoopFunctions = NULL;
00201       }
00202       /* Destroy the visualization */
00203       if(m_pcVisualization != NULL) {
00204          m_pcVisualization->Destroy();
00205       }
00206       /* Destroy simulated space */
00207       if(m_pcSpace != NULL) {
00208          m_pcSpace->Destroy();
00209       }
00210       /* Destroy media */
00211       for(CMedium::TMap::iterator it = m_mapMedia.begin();
00212           it != m_mapMedia.end(); ++it) {
00213          it->second->Destroy();
00214          delete it->second;
00215       }
00216       m_mapMedia.clear();
00217       m_vecMedia.clear();
00218       /* Destroy physics engines */
00219       for(CPhysicsEngine::TMap::iterator it = m_mapPhysicsEngines.begin();
00220           it != m_mapPhysicsEngines.end(); ++it) {
00221          it->second->Destroy();
00222          delete it->second;
00223       }
00224       m_mapPhysicsEngines.clear();
00225       m_vecPhysicsEngines.clear();
00226       /* Get rid of ARGoS category */
00227       if(CRandom::ExistsCategory("argos")) {
00228          CRandom::RemoveCategory("argos");
00229       }
00230       /* Free up factory data */
00231       CFactory<CMedium>::Destroy();
00232       CFactory<CPhysicsEngine>::Destroy();
00233       CFactory<CVisualization>::Destroy();
00234       CFactory<CSimulatedActuator>::Destroy();
00235       CFactory<CSimulatedSensor>::Destroy();
00236       CFactory<CCI_Controller>::Destroy();
00237       CFactory<CEntity>::Destroy();
00238       CFactory<CLoopFunctions>::Destroy();
00239       /* Stop profiling and flush the data */
00240       if(IsProfiling()) {
00241          m_pcProfiler->Stop();
00242          m_pcProfiler->Flush(m_bHumanReadableProfile);
00243       }
00244       LOG.Flush();
00245       LOGERR.Flush();
00246    }
00247 
00248    /****************************************/
00249    /****************************************/
00250 
00251    void CSimulator::Execute() {
00252       m_pcVisualization->Execute();
00253    }
00254 
00255    /****************************************/
00256    /****************************************/
00257 
00258    void CSimulator::UpdateSpace() {
00259       /* Increase the simulation clock */
00260       m_pcSpace->IncreaseSimulationClock();
00261       /* Call loop functions */
00262       m_pcLoopFunctions->PreStep();
00263       LOG.Flush();
00264       LOGERR.Flush();
00265       /* Update the space */
00266       m_pcSpace->Update();
00267       LOG.Flush();
00268       LOGERR.Flush();
00269       /* Call loop functions */
00270       m_pcLoopFunctions->PostStep();
00271       LOG.Flush();
00272       LOGERR.Flush();
00273    }
00274 
00275    /****************************************/
00276    /****************************************/
00277 
00278    bool CSimulator::IsExperimentFinished() const {
00279       /*
00280         The experiment is considered finished when the simulation clock exceeds
00281         the maximum value set in the XML, or when one of the visualisations asks
00282         to terminate.
00283       */
00284       /* Check simulation clock */
00285       if (m_unMaxSimulationClock > 0 &&
00286           m_pcSpace->GetSimulationClock() >= m_unMaxSimulationClock) {
00287          return true;
00288       }
00289       /* Call loop function */
00290       return m_pcLoopFunctions->IsExperimentFinished();
00291    }
00292 
00293    /****************************************/
00294    /****************************************/
00295 
00296    void CSimulator::InitFramework(TConfigurationNode& t_tree) {
00297       try {
00298          /* Parse the 'system' node */
00299          if(NodeExists(t_tree, "system")) {
00300             TConfigurationNode tSystem;
00301             tSystem = GetNode(t_tree, "system");
00302             GetNodeAttributeOrDefault(tSystem, "threads", m_unThreads, m_unThreads);
00303             if(m_unThreads == 0) {
00304                LOG << "[INFO] Not using threads" << std::endl;
00305                m_pcSpace = new CSpaceNoThreads;
00306             }
00307             else {
00308                LOG << "[INFO] Using " << m_unThreads << " parallel threads" << std::endl;
00309                std::string strThreadingMethod = "balance_quantity";
00310                GetNodeAttributeOrDefault(tSystem, "method", strThreadingMethod, strThreadingMethod);
00311                if(strThreadingMethod == "balance_quantity") {
00312                   LOG << "[INFO]   Method \"balance_quantity\" chosen: threads will be assigned the same"
00313                       << std::endl
00314                       << "[INFO]   number of tasks, independently of the task length."
00315                       << std::endl;
00316                   m_pcSpace = new CSpaceMultiThreadBalanceQuantity;
00317                }
00318                else if(strThreadingMethod == "balance_length") {
00319                   LOG << "[INFO]   Method \"balance_quantity\" chosen: threads will be assigned different"
00320                       << std::endl
00321                       << "[INFO]   numbers of tasks, depending on the task length."
00322                       << std::endl;
00323                   m_pcSpace = new CSpaceMultiThreadBalanceLength;
00324                }
00325                else {
00326                   THROW_ARGOSEXCEPTION("Error parsing the <system> tag. Unknown threading method \"" << strThreadingMethod << "\". Available methods: \"balance_quantity\" and \"balance_length\".");
00327                }
00328             }
00329          }
00330          else {
00331             LOG << "[INFO] Not using threads" << std::endl;
00332             m_pcSpace = new CSpaceNoThreads;
00333          }
00334          /* Get 'experiment' node */
00335          TConfigurationNode tExperiment;
00336          tExperiment = GetNode(t_tree, "experiment");
00337          /* Parse random seed */
00338          /* Buffer to hold the random seed */
00339          GetNodeAttributeOrDefault(tExperiment,
00340                                    "random_seed",
00341                                    m_unRandomSeed,
00342                                    static_cast<UInt32>(0));
00343          /* if random seed is 0 or is not specified, init with the current timeval */
00344          if(m_unRandomSeed != 0) {
00345             CRandom::CreateCategory("argos", m_unRandomSeed);
00346             LOG << "[INFO] Using random seed = " << m_unRandomSeed << std::endl;
00347             m_bWasRandomSeedSet = true;
00348          }
00349          else {
00350             /* Prepare the default value based on the current clock time */
00351             m_bWasRandomSeedSet = false;
00352             struct timeval sTimeValue;
00353             ::gettimeofday(&sTimeValue, NULL);
00354             UInt32 unSeed = static_cast<UInt32>(sTimeValue.tv_usec);
00355             m_unRandomSeed = unSeed;
00356             CRandom::CreateCategory("argos", unSeed);
00357             LOG << "[INFO] Using random seed = " << unSeed << std::endl;
00358          }
00359          m_pcRNG = CRandom::CreateRNG("argos");
00360          /* Set the simulation clock tick length */
00361          UInt32 unTicksPerSec;
00362          GetNodeAttribute(tExperiment,
00363                           "ticks_per_second",
00364                           unTicksPerSec);
00365          CPhysicsEngine::SetSimulationClockTick(1.0 / static_cast<Real>(unTicksPerSec));
00366          /* Set the maximum simulation duration (in seconds) */
00367          Real fExpLength;
00368          GetNodeAttributeOrDefault<Real>(tExperiment,
00369                                          "length",
00370                                          fExpLength,
00371                                          0.0f);
00372          m_unMaxSimulationClock = fExpLength * unTicksPerSec;
00373          LOG << "[INFO] Total experiment length in clock ticks = "
00374              << (m_unMaxSimulationClock ? ToString(m_unMaxSimulationClock) : "unlimited")
00375              << std::endl;
00376          /* Get the profiling tag, if present */
00377          if(NodeExists(t_tree, "profiling")) {
00378             TConfigurationNode& tProfiling = GetNode(t_tree, "profiling");
00379             std::string strFile;
00380             GetNodeAttribute(tProfiling, "file", strFile);
00381             std::string strFormat;
00382             GetNodeAttribute(tProfiling, "format", strFormat);
00383             if(strFormat == "human_readable") {
00384                m_bHumanReadableProfile = true;
00385             }
00386             else if(strFormat == "table") {
00387                m_bHumanReadableProfile = false;
00388             }
00389             else {
00390                THROW_ARGOSEXCEPTION("Unrecognized profile format \"" << strFormat << "\". Accepted values are \"human_readable\" and \"table\".");
00391             }
00392             bool bTrunc = true;
00393             GetNodeAttributeOrDefault(tProfiling, "truncate_file", bTrunc, bTrunc);
00394             m_pcProfiler = new CProfiler(strFile, bTrunc);
00395          }
00396       }
00397       catch(CARGoSException& ex) {
00398          THROW_ARGOSEXCEPTION_NESTED("Failed to initialize the simulator. Parse error inside the <framework> tag.", ex);
00399       }
00400    }
00401 
00402    /****************************************/
00403    /****************************************/
00404 
00405    void CSimulator::InitLoopFunctions(TConfigurationNode& t_tree) {
00406       try {
00407          std::string strLibrary, strLabel;
00408          GetNodeAttributeOrDefault(t_tree, "library", strLibrary, strLibrary);
00409          GetNodeAttribute(t_tree, "label", strLabel);
00410          if(! strLibrary.empty()) {
00411             CDynamicLoading::LoadLibrary(strLibrary);
00412          }
00413          m_pcLoopFunctions = CFactory<CLoopFunctions>::New(strLabel);
00414       }
00415       catch(CARGoSException& ex) {
00416          THROW_ARGOSEXCEPTION_NESTED("Error initializing loop functions", ex);
00417       }
00418    }
00419 
00420    /****************************************/
00421    /****************************************/
00422 
00423    void CSimulator::InitControllers(TConfigurationNode& t_tree) {
00424       /*
00425        * Go through controllers, loading the library of each of them
00426        * and storing type, id and XML tree of each of them for later use
00427        */
00428       if(! t_tree.NoChildren()) {
00429          try {
00430             std::string strLibrary;
00431             std::string strId;
00432             TConfigurationNodeIterator it;
00433             for(it = it.begin(&t_tree);
00434                 it != it.end(); ++it) {
00435                /* Get controller id */
00436                try {
00437                   GetNodeAttribute(*it, "id", strId);
00438                }
00439                catch(CARGoSException& ex) {
00440                   std::string strValue;
00441                   it->GetValue(&strValue);
00442                   THROW_ARGOSEXCEPTION_NESTED("Controller type \"" << strValue << "\" has no assigned id.", ex);
00443                }
00444                /* Bomb out if id is already in map */
00445                if(m_mapControllerConfig.find(strId) != m_mapControllerConfig.end()) {
00446                   THROW_ARGOSEXCEPTION("Controller id \"" << strId << "\" duplicated");
00447                }
00448                /* Optionally, process "library" attribute if present */
00449                if(NodeAttributeExists(*it, "library")) {
00450                   /* Get library name */
00451                   GetNodeAttribute(*it, "library", strLibrary);
00452                   /* Load library */
00453                   CDynamicLoading::LoadLibrary(strLibrary);
00454                }
00455                /* Store XML info in map by id */
00456                m_mapControllerConfig.insert(std::pair<std::string, TConfigurationNode*>(strId, &(*it)));
00457             }
00458          }
00459          catch(CARGoSException& ex) {
00460             THROW_ARGOSEXCEPTION_NESTED("Error initializing controllers", ex);
00461          }
00462       }
00463    }
00464 
00465    /****************************************/
00466    /****************************************/
00467 
00468    void CSimulator::InitSpace(TConfigurationNode& t_tree) {
00469       try {
00470          m_pcSpace->Init(t_tree);
00471       }
00472       catch(CARGoSException& ex) {
00473          THROW_ARGOSEXCEPTION_NESTED("Failed to initialize the space.", ex);
00474       }
00475    }
00476 
00477    /****************************************/
00478    /****************************************/
00479 
00480    void CSimulator::InitPhysics(TConfigurationNode& t_tree) {
00481       try {
00482          /* Cycle through the physics engines */
00483          TConfigurationNodeIterator itEngines;
00484          for(itEngines = itEngines.begin(&t_tree);
00485              itEngines != itEngines.end();
00486              ++itEngines) {
00487             /* Create the physics engine */
00488             CPhysicsEngine* pcEngine = CFactory<CPhysicsEngine>::New(itEngines->Value());
00489             try {
00490                /* Initialize the engine */
00491                pcEngine->Init(*itEngines);
00492                /* Check that an engine with that ID does not exist yet */
00493                if(m_mapPhysicsEngines.find(pcEngine->GetId()) == m_mapPhysicsEngines.end()) {
00494                   /* Add it to the lists */
00495                   m_mapPhysicsEngines[pcEngine->GetId()] = pcEngine;
00496                   m_vecPhysicsEngines.push_back(pcEngine);
00497                }
00498                else {
00499                   /* Duplicate id -> error */
00500                   THROW_ARGOSEXCEPTION("A physics engine with id \"" << pcEngine->GetId() << "\" exists already. The ids must be unique!");
00501                }
00502             }
00503             catch(CARGoSException& ex) {
00504                /* Error while executing engine init, destroy what done to prevent memory leaks */
00505                pcEngine->Destroy();
00506                delete pcEngine;
00507                THROW_ARGOSEXCEPTION_NESTED("Error initializing physics engine type \"" << itEngines->Value() << "\"", ex);
00508             }
00509          }
00510       }
00511       catch(CARGoSException& ex) {
00512          THROW_ARGOSEXCEPTION_NESTED("Failed to initialize the physics engines. Parse error in the <physics_engines> subtree.", ex);
00513       }
00514    }
00515 
00516    /****************************************/
00517    /****************************************/
00518 
00519    void CSimulator::InitMedia(TConfigurationNode& t_tree) {
00520       try {
00521          /* Cycle through the media */
00522          TConfigurationNodeIterator itMedia;
00523          for(itMedia = itMedia.begin(&t_tree);
00524              itMedia != itMedia.end();
00525              ++itMedia) {
00526             /* Create the  medium */
00527             CMedium* pcMedium = CFactory<CMedium>::New(itMedia->Value());
00528             try {
00529                /* Initialize the medium */
00530                pcMedium->Init(*itMedia);
00531                /* Check that an medium with that ID does not exist yet */
00532                if(m_mapMedia.find(pcMedium->GetId()) == m_mapMedia.end()) {
00533                   /* Add it to the lists */
00534                   m_mapMedia[pcMedium->GetId()] = pcMedium;
00535                   m_vecMedia.push_back(pcMedium);
00536                }
00537                else {
00538                   /* Duplicate id -> error */
00539                   THROW_ARGOSEXCEPTION("A medium with id \"" << pcMedium->GetId() << "\" exists already. The ids must be unique!");
00540                }
00541             }
00542             catch(CARGoSException& ex) {
00543                /* Error while executing medium init, destroy what done to prevent memory leaks */
00544                pcMedium->Destroy();
00545                delete pcMedium;
00546                THROW_ARGOSEXCEPTION_NESTED("Error initializing medium type \"" << itMedia->Value() << "\"", ex);
00547             }
00548          }
00549       }
00550       catch(CARGoSException& ex) {
00551          THROW_ARGOSEXCEPTION_NESTED("Failed to initialize the media. Parse error in the <media> subtree.", ex);
00552       }
00553    }
00554 
00555    /****************************************/
00556    /****************************************/
00557 
00558    void CSimulator::InitMedia2() {
00559       try {
00560          /* Cycle through the media */
00561          CMedium::TMap::iterator it;
00562          for(it = m_mapMedia.begin(); it != m_mapMedia.end(); ++it) {
00563             CMedium& cMedium = *(it->second);
00564             try {
00565                /* Initialize the medium */
00566                cMedium.PostSpaceInit();
00567             }
00568             catch(CARGoSException& ex) {
00569                /* Error while executing medium post space init, destroy what done to prevent memory leaks */
00570                std::ostringstream ossMsg;
00571                ossMsg << "Error executing post-space initialization of medium \"" << cMedium.GetId() << "\"";
00572                cMedium.Destroy();
00573                THROW_ARGOSEXCEPTION_NESTED(ossMsg.str(), ex);
00574             }
00575          }
00576       }
00577       catch(CARGoSException& ex) {
00578          THROW_ARGOSEXCEPTION_NESTED("Failed to initialize the media. Parse error in the <media> subtree.", ex);
00579       }
00580    }
00581 
00582    /****************************************/
00583    /****************************************/
00584 
00585    void CSimulator::InitVisualization(TConfigurationNode& t_tree) {
00586       try {
00587          /* Consider only the first visualization */
00588          TConfigurationNodeIterator itVisualization;
00589          itVisualization = itVisualization.begin(&t_tree);
00590          /* Create the visualization */
00591          m_pcVisualization = CFactory<CVisualization>::New(itVisualization->Value());
00592          /* Initialize the visualization */
00593          m_pcVisualization->Init(*itVisualization);
00594       }
00595       catch(CARGoSException& ex) {
00596          THROW_ARGOSEXCEPTION_NESTED("Failed to initialize the visualization. Parse error in the <visualization> subtree.", ex);
00597       }
00598    }
00599 
00600    /****************************************/
00601    /****************************************/
00602 
00603 }