mvsim-cli-launch.cpp
Go to the documentation of this file.
1 /*+-------------------------------------------------------------------------+
2  | MultiVehicle simulator (libmvsim) |
3  | |
4  | Copyright (C) 2014-2020 Jose Luis Blanco Claraco |
5  | Copyright (C) 2017 Borys Tymchenko (Odessa Polytechnic University) |
6  | Distributed under 3-clause BSD License |
7  | See COPYING |
8  +-------------------------------------------------------------------------+ */
9 
10 #include <mrpt/core/exceptions.h>
11 #include <mvsim/World.h>
12 
13 #include <rapidxml_utils.hpp>
14 #include <thread>
15 
16 #include "mvsim-cli.h"
17 
18 struct TThreadParams
19 {
20  mvsim::World* world = nullptr;
21  std::mutex closingMtx;
22 
23  TThreadParams() = default;
24 
25  bool isClosing()
26  {
27  closingMtx.lock();
28  bool ret = closing_;
29  closingMtx.unlock();
30  return ret;
31  }
32  void closing(bool v)
33  {
34  closingMtx.lock();
35  closing_ = v;
36  closingMtx.unlock();
37  }
38 
39  private:
40  bool closing_ = false;
41 };
42 static void mvsim_server_thread_update_GUI(TThreadParams& thread_params);
44 std::mutex gui_key_events_mtx;
45 std::string msg2gui;
46 
48 {
49  using namespace mvsim;
50 
51  // check args:
52  bool badArgs = false;
53  const auto& unlabeledArgs = argCmd.getValue();
54  if (unlabeledArgs.size() != 2) badArgs = true;
55 
56  if (argHelp.isSet() || badArgs)
57  {
58  fprintf(
59  stdout,
60  R"XXX(Usage: mvsim launch <WORLD_MODEL.xml>
61 
62 Available options:
63  -v, --verbosity Set verbosity level: DEBUG, INFO (default), WARN, ERROR
64 )XXX");
65  return 0;
66  }
67 
68  const auto sXMLfilename = unlabeledArgs.at(1);
69 
70  // Start network server:
72 
73  mvsim::World world;
74 
75  world.setMinLoggingLevel(
76  mrpt::typemeta::TEnumType<mrpt::system::VerbosityLevel>::name2value(
77  argVerbosity.getValue()));
78 
79  // Load from XML:
80  rapidxml::file<> fil_xml(sXMLfilename.c_str());
81  world.load_from_XML(fil_xml.data(), sXMLfilename.c_str());
82 
83  // Attach world as a mvsim communications node:
84  world.connectToServer();
85 
86  // Launch GUI thread:
87  TThreadParams thread_params;
88  thread_params.world = &world;
89  std::thread thGUI =
90  std::thread(&mvsim_server_thread_update_GUI, std::ref(thread_params));
91 
92  // Run simulation:
93  mrpt::system::CTicTac tictac;
94  double t_old = tictac.Tac();
95  double REALTIME_FACTOR = 1.0;
96  bool do_exit = false;
97  size_t teleop_idx_veh = 0; // Index of the vehicle to teleop
98 
99  while (!do_exit && !mrpt::system::os::kbhit())
100  {
101  // Simulation
102  // ============================================================
103  // Compute how much time has passed to simulate in real-time:
104  double t_new = tictac.Tac();
105  double incr_time = REALTIME_FACTOR * (t_new - t_old);
106 
107  // Just in case the computer is *really fast*...
108  if (incr_time >= world.get_simul_timestep())
109  {
110  // Simulate:
111  world.run_simulation(incr_time);
112 
113  // t_old_simul = world.get_simul_time();
114  t_old = t_new;
115  }
116 
117  // I could use 10ms here but chono literals are since gcc 4.9.3
118  std::this_thread::sleep_for(std::chrono::milliseconds(10));
119 
120  // GUI msgs, teleop, etc.
121  // ====================================================
122 
123  std::string txt2gui_tmp;
124  gui_key_events_mtx.lock();
126  gui_key_events_mtx.unlock();
127 
128  // Global keys:
129  switch (keyevent.keycode)
130  {
131  case GLFW_KEY_ESCAPE:
132  do_exit = true;
133  break;
134  case '1':
135  case '2':
136  case '3':
137  case '4':
138  case '5':
139  case '6':
140  teleop_idx_veh = keyevent.keycode - '1';
141  break;
142  };
143 
144  { // Test: Differential drive: Control raw forces
145  const World::VehicleList& vehs = world.getListOfVehicles();
146  txt2gui_tmp += mrpt::format(
147  "Selected vehicle: %u/%u\n",
148  static_cast<unsigned>(teleop_idx_veh + 1),
149  static_cast<unsigned>(vehs.size()));
150  if (vehs.size() > teleop_idx_veh)
151  {
152  // Get iterator to selected vehicle:
153  World::VehicleList::const_iterator it_veh = vehs.begin();
154  std::advance(it_veh, teleop_idx_veh);
155 
156  // Get speed: ground truth
157  {
158  const mrpt::math::TTwist2D& vel =
159  it_veh->second->getVelocityLocal();
160  txt2gui_tmp += mrpt::format(
161  "gt. vel: lx=%7.03f, ly=%7.03f, w= %7.03fdeg/s\n",
162  vel.vx, vel.vy, mrpt::RAD2DEG(vel.omega));
163  }
164  // Get speed: ground truth
165  {
166  const mrpt::math::TTwist2D& vel =
167  it_veh->second->getVelocityLocalOdoEstimate();
168  txt2gui_tmp += mrpt::format(
169  "odo vel: lx=%7.03f, ly=%7.03f, w= %7.03fdeg/s\n",
170  vel.vx, vel.vy, mrpt::RAD2DEG(vel.omega));
171  }
172 
173  // Generic teleoperation interface for any controller that
174  // supports it:
175  {
176  ControllerBaseInterface* controller =
177  it_veh->second->getControllerInterface();
180  teleop_in.keycode = keyevent.keycode;
181  controller->teleop_interface(teleop_in, teleop_out);
182  txt2gui_tmp += teleop_out.append_gui_lines;
183  }
184  }
185  }
186 
187  // Clear the keystroke buffer
188  gui_key_events_mtx.lock();
189  if (keyevent.keycode != 0) gui_key_events = World::TGUIKeyEvent();
190  gui_key_events_mtx.unlock();
191 
192  msg2gui = txt2gui_tmp; // send txt msgs to show in the GUI
193 
194  } // end while()
195 
196  thread_params.closing(true);
197 
198  thGUI.join(); // TODO: It could break smth
199 
200  return 0;
201 }
202 
204 {
205  while (!thread_params.isClosing())
206  {
208  guiparams.msg_lines = msg2gui;
209 
210  thread_params.world->update_GUI(&guiparams);
211 
212  // Send key-strokes to the main thread:
213  if (guiparams.keyevent.keycode != 0)
214  {
215  gui_key_events_mtx.lock();
216  gui_key_events = guiparams.keyevent;
217  gui_key_events_mtx.unlock();
218  }
219 
220  std::this_thread::sleep_for(std::chrono::milliseconds(25));
221  }
222 }
const GLdouble * v
void commonLaunchServer()
std::mutex gui_key_events_mtx
Represents data loaded from a file.
virtual void teleop_interface(const TeleopInput &in, TeleopOutput &out)
const VehicleList & getListOfVehicles() const
Definition: World.h:195
TCLAP::SwitchArg argHelp("h","help","Shows more detailed help for command", cmd)
mvsim::World::TGUIKeyEvent gui_key_events
int BASE_IMPEXP fprintf(FILE *fil, const char *format,...) MRPT_NO_THROWS MRPT_printf_format_check(2
std::multimap< std::string, VehicleBase::Ptr > VehicleList
Definition: World.h:173
std::string msg2gui
TGUIKeyEvent keyevent
Keystrokes in the window are returned here.
Definition: World.h:114
double get_simul_timestep() const
Simulation fixed-time interval for numerical integration.
Definition: World.h:73
TCLAP::ValueArg< std::string > argVerbosity("v","verbose","Verbosity level", false,"INFO","ERROR|WARN|INFO|DEBUG", cmd)
std::string BASE_IMPEXP format(const char *fmt,...) MRPT_printf_format_check(1
bool isSet() const
std::string msg_lines
Messages to show.
Definition: World.h:115
TCLAP::UnlabeledMultiArg< std::string > argCmd("command","Command to run. Run 'mvsim help' to list commands.", false,"", cmd)
int launchSimulation()
void load_from_XML(const std::string &xml_text, const std::string &fileNameForPath=std::string("."))
bool BASE_IMPEXP kbhit() MRPT_NO_THROWS
void connectToServer()
Definition: World.cpp:205
void run_simulation(double dt)
Definition: World.cpp:71
void update_GUI(TUpdateGUIParams *params=nullptr)
Definition: World_gui.cpp:633
static void mvsim_server_thread_update_GUI(TThreadParams &thread_params)
int keycode
0=no Key. Otherwise, ASCII code.
Definition: World.h:103


mvsim
Author(s):
autogenerated on Fri May 7 2021 03:05:51