World.cpp
Go to the documentation of this file.
00001 /*+-------------------------------------------------------------------------+
00002   |                       MultiVehicle simulator (libmvsim)                 |
00003   |                                                                         |
00004   | Copyright (C) 2014  Jose Luis Blanco Claraco (University of Almeria)    |
00005   | Copyright (C) 2017  Borys Tymchenko (Odessa Polytechnic University)     |
00006   | Distributed under GNU General Public License version 3                  |
00007   |   See <http://www.gnu.org/licenses/>                                    |
00008   +-------------------------------------------------------------------------+ */
00009 #include <mvsim/World.h>
00010 
00011 #include <mrpt/system/filesystem.h>  // filePathSeparatorsToNative()
00012 
00013 #include <iostream>  // for debugging
00014 #include <algorithm>  // count()
00015 #include <stdexcept>
00016 #include <map>
00017 
00018 using namespace mvsim;
00019 using namespace std;
00020 
00021 // Default ctor: inits empty world.
00022 World::World()
00023         : m_gravity(9.81),
00024           m_simul_time(0.0),
00025           m_simul_timestep(0.010),
00026           m_b2d_vel_iters(6),
00027           m_b2d_pos_iters(3),
00028           m_base_path("."),
00029           m_box2d_world(NULL)
00030 {
00031         this->clear_all();
00032 }
00033 
00034 // Dtor.
00035 World::~World()
00036 {
00037         this->clear_all();
00038         delete m_box2d_world;
00039         m_box2d_world = NULL;
00040 }
00041 
00042 // Resets the entire simulation environment to an empty world.
00043 void World::clear_all(bool acquire_mt_lock)
00044 {
00045         try
00046         {
00047                 if (acquire_mt_lock) m_world_cs.lock();
00048 
00049                 // Reset params:
00050                 m_simul_time = 0.0;
00051 
00052                 // (B2D) World contents:
00053                 // ---------------------------------------------
00054                 delete m_box2d_world;
00055                 m_box2d_world = new b2World(b2Vec2_zero);
00056 
00057                 // Define the ground body.
00058                 b2BodyDef groundBodyDef;
00059                 m_b2_ground_body = m_box2d_world->CreateBody(&groundBodyDef);
00060 
00061                 // Clear lists of objs:
00062                 // ---------------------------------------------
00063                 for (TListVehicles::iterator it = m_vehicles.begin();
00064                          it != m_vehicles.end(); ++it)
00065                         delete it->second;
00066                 m_vehicles.clear();
00067 
00068                 for (std::list<WorldElementBase*>::iterator it =
00069                                  m_world_elements.begin();
00070                          it != m_world_elements.end(); ++it)
00071                         delete *it;
00072                 m_world_elements.clear();
00073 
00074                 for (TListBlocks::iterator it = m_blocks.begin(); it != m_blocks.end();
00075                          ++it)
00076                         delete it->second;
00077                 m_blocks.clear();
00078 
00079                 if (acquire_mt_lock) m_world_cs.unlock();
00080         }
00081         catch (std::exception&)
00082         {
00083                 if (acquire_mt_lock) m_world_cs.unlock();
00084                 throw;  // re-throw
00085         }
00086 }
00087 
00089 void World::run_simulation(double dt)
00090 {
00091         m_timlogger.registerUserMeasure("run_simulation.dt", dt);
00092 
00093         // sanity checks:
00094         ASSERT_(dt > 0);
00095         ASSERT_(m_simul_timestep > 0);
00096 
00097         // Run in time steps:
00098         const double end_time = m_simul_time + dt;
00099         const double timetol =
00100                 1e-6;  // tolerance for rounding errors summing time steps
00101         while (m_simul_time < (end_time - timetol))
00102         {
00103                 // Timestep: always "simul_step" for the sake of repeatibility
00104                 internal_one_timestep(m_simul_timestep);
00105         }
00106 }
00107 
00109 void World::internal_one_timestep(double dt)
00110 {
00111         m_timer_iteration.Tic();
00112 
00113         TSimulContext context;
00114         context.b2_world = m_box2d_world;
00115         context.simul_time = m_simul_time;
00116         context.dt = dt;
00117 
00118         // 1) Pre-step
00119         {
00120                 CTimeLoggerEntry tle(m_timlogger, "timestep.0.prestep");
00121                 for (TListVehicles::iterator it = m_vehicles.begin();
00122                          it != m_vehicles.end(); ++it)
00123                         it->second->simul_pre_timestep(context);
00124 
00125                 for (TListVehicles::iterator it = m_vehicles.begin();
00126                          it != m_vehicles.end(); ++it)
00127                 {
00128                         VehicleBase::TListSensors& sensors = it->second->getSensors();
00129                         for (VehicleBase::TListSensors::iterator itSen = sensors.begin();
00130                                  itSen != sensors.end(); ++itSen)
00131                         {
00132                                 (*itSen)->simul_pre_timestep(context);
00133                         }
00134                 }
00135 
00136                 for (TListBlocks::iterator it = m_blocks.begin(); it != m_blocks.end();
00137                          ++it)
00138                         it->second->simul_pre_timestep(context);
00139 
00140                 for (std::list<WorldElementBase*>::iterator it =
00141                                  m_world_elements.begin();
00142                          it != m_world_elements.end(); ++it)
00143                         (*it)->simul_pre_timestep(context);
00144         }
00145 
00146         // 2) Run dynamics
00147         {
00148                 CTimeLoggerEntry tle(
00149                         m_timlogger, "timestep.1.dynamics_integrator");
00150 
00151                 m_box2d_world->Step(dt, m_b2d_vel_iters, m_b2d_pos_iters);
00152                 m_simul_time += dt;  // Avance time
00153         }
00154 
00155         // 3) Save dynamical state into vehicles classes
00156         {
00157                 CTimeLoggerEntry tle(
00158                         m_timlogger, "timestep.3.save_dynstate");
00159 
00160                 context.simul_time = m_simul_time;
00161                 for (TListVehicles::iterator it = m_vehicles.begin();
00162                          it != m_vehicles.end(); ++it)
00163                 {
00164                         it->second->simul_post_timestep_common(context);
00165                         it->second->simul_post_timestep(context);
00166                 }
00167                 for (TListBlocks::iterator it = m_blocks.begin(); it != m_blocks.end();
00168                          ++it)
00169                 {
00170                         it->second->simul_post_timestep_common(context);
00171                         it->second->simul_post_timestep(context);
00172                 }
00173         }
00174 
00175         // 4) Post-step:
00176         {
00177                 CTimeLoggerEntry tle(m_timlogger, "timestep.4.poststep");
00178                 for (TListVehicles::iterator it = m_vehicles.begin();
00179                          it != m_vehicles.end(); ++it)
00180                         it->second->simul_post_timestep(context);
00181 
00182                 for (TListVehicles::iterator it = m_vehicles.begin();
00183                          it != m_vehicles.end(); ++it)
00184                 {
00185                         VehicleBase::TListSensors& sensors = it->second->getSensors();
00186                         for (VehicleBase::TListSensors::iterator itSen = sensors.begin();
00187                                  itSen != sensors.end(); ++itSen)
00188                         {
00189                                 (*itSen)->simul_post_timestep(context);
00190                         }
00191                 }
00192 
00193                 for (TListBlocks::iterator it = m_blocks.begin(); it != m_blocks.end();
00194                          ++it)
00195                         it->second->simul_post_timestep(context);
00196 
00197                 for (std::list<WorldElementBase*>::iterator it =
00198                                  m_world_elements.begin();
00199                          it != m_world_elements.end(); ++it)
00200                         (*it)->simul_post_timestep(context);
00201         }
00202 
00203         const double ts = m_timer_iteration.Tac();
00204         m_timlogger.registerUserMeasure(
00205                 (ts > dt ? "timestep_too_slow_alert" : "timestep"), ts);
00206 }
00207 
00210 std::string World::resolvePath(const std::string& s_in) const
00211 {
00212         std::string ret;
00213         const std::string s = mrpt::system::trim(s_in);
00214 
00215         // Relative path? It's not if:
00216         // "X:\*", "/*"
00217         // -------------------
00218         bool is_relative = true;
00219         if (s.size() > 2 && s[1] == ':' && (s[2] == '/' || s[2] == '\\'))
00220                 is_relative = false;
00221         if (s.size() > 0 && (s[0] == '/' || s[0] == '\\')) is_relative = false;
00222         if (is_relative)
00223         {
00224                 ret = m_base_path;
00225                 if (!ret.empty() && ret[ret.size() - 1] != '/' &&
00226                         ret[ret.size() - 1] != '\\')
00227                         ret += string("/");
00228                 ret += s;
00229         }
00230         else
00231                 ret = s;
00232 
00233         // Expand macros: (TODO)
00234         // -------------------
00235 
00236         return mrpt::system::filePathSeparatorsToNative(ret);
00237 }
00238 
00240 void World::runVisitorOnVehicles(VehicleVisitorBase& v)
00241 {
00242         for (TListVehicles::iterator it = m_vehicles.begin();
00243                  it != m_vehicles.end(); ++it)
00244                 v.visit(it->second);
00245 }
00246 
00248 void World::runVisitorOnWorldElements(WorldElementVisitorBase& v)
00249 {
00250         for (std::list<WorldElementBase*>::iterator it = m_world_elements.begin();
00251                  it != m_world_elements.end(); ++it)
00252                 v.visit(*it);
00253 }


mvsim
Author(s):
autogenerated on Thu Jun 6 2019 22:08:35