mvsim_main.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 
00010 #include <mvsim/mvsim.h>
00011 
00012 #include <chrono>
00013 #include <thread>
00014 
00015 #include <mrpt/system/os.h>  // kbhit()
00016 #include <mrpt/utils/CTicTac.h>
00017 
00018 #include <rapidxml_utils.hpp>
00019 #include <iostream>
00020 
00021 using namespace mvsim;
00022 
00023 struct TThreadParams
00024 {
00025         World* world;
00026         volatile bool closing;
00027         TThreadParams() : world(NULL), closing(false) {}
00028 };
00029 void usage(const char* argv0);
00030 void thread_update_GUI(TThreadParams& thread_params);
00031 World::TGUIKeyEvent gui_key_events;
00032 std::string msg2gui;
00033 
00034 int main(int argc, char** argv)
00035 {
00036         try
00037         {
00038                 if (argc != 2)
00039                 {
00040                         usage(argv[0]);
00041                         return -1;
00042                 }
00043 
00044                 World world;
00045 
00046                 // Load from XML:
00047                 rapidxml::file<> fil_xml(argv[1]);
00048                 world.load_from_XML(fil_xml.data(), argv[1]);
00049 
00050                 // Launch GUI thread:
00051                 TThreadParams thread_params;
00052                 thread_params.world = &world;
00053                 std::thread thGUI =
00054                         std::thread(thread_update_GUI, std::ref(thread_params));
00055 
00056                 // Run simulation:
00057                 mrpt::utils::CTicTac tictac;
00058                 double t_old = tictac.Tac();
00059                 double REALTIME_FACTOR = 1.0;
00060                 bool do_exit = false;
00061                 size_t teleop_idx_veh = 0;  // Index of the vehicle to teleop
00062 
00063                 while (!do_exit && !mrpt::system::os::kbhit())
00064                 {
00065                         // Simulation
00066                         // ============================================================
00067                         // Compute how much time has passed to simulate in real-time:
00068                         double t_new = tictac.Tac();
00069                         double incr_time = REALTIME_FACTOR * (t_new - t_old);
00070 
00071                         if (incr_time >= world.get_simul_timestep())  // Just in case the
00072                                                                                                                   // computer is *really
00073                                                                                                                   // fast*...
00074                         {
00075                                 // Simulate:
00076                                 world.run_simulation(incr_time);
00077 
00078                                 // t_old_simul = world.get_simul_time();
00079                                 t_old = t_new;
00080                         }
00081 
00082                         // I could use 10ms here but chono literals are since gcc 4.9.3
00083                         std::this_thread::sleep_for(std::chrono::milliseconds(10));
00084 
00085                         // GUI msgs, teleop, etc.
00086                         // ====================================================
00087 
00088                         std::string txt2gui_tmp;
00089                         World::TGUIKeyEvent keyevent = gui_key_events;
00090 
00091                         // Global keys:
00092                         switch (keyevent.keycode)
00093                         {
00094                                 case 27:
00095                                         do_exit = true;
00096                                         break;
00097                                 case '1':
00098                                 case '2':
00099                                 case '3':
00100                                 case '4':
00101                                 case '5':
00102                                 case '6':
00103                                         teleop_idx_veh = keyevent.keycode - '1';
00104                                         break;
00105                         };
00106 
00107                         {  // Test: Differential drive: Control raw forces
00108                                 const World::TListVehicles& vehs = world.getListOfVehicles();
00109                                 txt2gui_tmp += mrpt::format(
00110                                         "Selected vehicle: %u/%u\n",
00111                                         static_cast<unsigned>(teleop_idx_veh + 1),
00112                                         static_cast<unsigned>(vehs.size()));
00113                                 if (vehs.size() > teleop_idx_veh)
00114                                 {
00115                                         // Get iterator to selected vehicle:
00116                                         World::TListVehicles::const_iterator it_veh = vehs.begin();
00117                                         std::advance(it_veh, teleop_idx_veh);
00118 
00119                                         // Get speed: ground truth
00120                                         {
00121                                                 const vec3& vel = it_veh->second->getVelocityLocal();
00122                                                 txt2gui_tmp += mrpt::format(
00123                                                         "gt. vel: lx=%7.03f, ly=%7.03f, w= %7.03fdeg/s\n",
00124                                                         vel.vals[0], vel.vals[1],
00125                                                         mrpt::utils::RAD2DEG(vel.vals[2]));
00126                                         }
00127                                         // Get speed: ground truth
00128                                         {
00129                                                 const vec3& vel =
00130                                                         it_veh->second->getVelocityLocalOdoEstimate();
00131                                                 txt2gui_tmp += mrpt::format(
00132                                                         "odo vel: lx=%7.03f, ly=%7.03f, w= %7.03fdeg/s\n",
00133                                                         vel.vals[0], vel.vals[1],
00134                                                         mrpt::utils::RAD2DEG(vel.vals[2]));
00135                                         }
00136 
00137                                         // Generic teleoperation interface for any controller that
00138                                         // supports it:
00139                                         {
00140                                                 ControllerBaseInterface* controller =
00141                                                         it_veh->second->getControllerInterface();
00142                                                 ControllerBaseInterface::TeleopInput teleop_in;
00143                                                 ControllerBaseInterface::TeleopOutput teleop_out;
00144                                                 teleop_in.keycode = keyevent.keycode;
00145                                                 controller->teleop_interface(teleop_in, teleop_out);
00146                                                 txt2gui_tmp += teleop_out.append_gui_lines;
00147                                         }
00148                                 }
00149                         }
00150 
00151                         // Clear the keystroke buffer
00152                         if (keyevent.keycode != 0) gui_key_events = World::TGUIKeyEvent();
00153 
00154                         msg2gui = txt2gui_tmp;  // send txt msgs to show in the GUI
00155 
00156                 }  // end while()
00157 
00158                 thread_params.closing = true;
00159                 thGUI.join();  // TODO: It could break smth
00160         }
00161         catch (const std::exception& e)
00162         {
00163                 std::cerr << "ERROR: " << e.what() << std::endl;
00164                 return 1;
00165         }
00166         return 0;
00167 }
00168 
00169 void thread_update_GUI(TThreadParams& thread_params)
00170 {
00171         while (!thread_params.closing)
00172         {
00173                 World::TUpdateGUIParams guiparams;
00174                 guiparams.msg_lines = msg2gui;
00175 
00176                 thread_params.world->update_GUI(&guiparams);
00177 
00178                 // Send key-strokes to the main thread:
00179                 if (guiparams.keyevent.keycode != 0)
00180                         gui_key_events = guiparams.keyevent;
00181 
00182                 std::this_thread::sleep_for(std::chrono::milliseconds(25));
00183         }
00184 }
00185 
00186 void usage(const char* argv0)
00187 {
00188         std::cerr << "Usage:\n"
00189                                  " "
00190                           << argv0 << " [WORLD_MODEL.xml]\n";
00191 }


mvsim
Author(s):
autogenerated on Thu Sep 7 2017 09:27:48