ARGoS
3
A parallel, multi-engine simulator for swarm robotics
|
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 }