10 #include <mrpt/core/exceptions.h> 11 #include <mrpt/core/round.h> 12 #include <mrpt/system/os.h> 21 MRPT_TODO(
"win32: add SetConsoleCtrlHandler");
63 size_t teleopIdxVeh = 0;
66 std::optional<LaunchData>
app;
70 app->thread_params.closing(
true);
72 if (
app->thGUI.joinable())
app->thGUI.join();
75 if (
app->world.getTimeLogger().isEnabledKeepWholeHistory())
77 const std::string sFil =
"mvsim_profiler.m";
78 std::cout <<
"\n***SAVING PROFILER DATA TO***: " << sFil << std::endl;
79 app->world.getTimeLogger().saveToMFile(sFil);
82 app->world.free_opengl_resources();
88 std::cerr <<
"Caught signal " << s <<
". Shutting down..." << std::endl;
95 struct sigaction sigIntHandler;
98 sigemptyset(&sigIntHandler.sa_mask);
99 sigIntHandler.sa_flags = 0;
101 sigaction(SIGINT, &sigIntHandler,
nullptr);
108 using namespace mvsim;
110 std::string txt2gui_tmp;
113 txt2gui_tmp += mrpt::format(
114 "Selected vehicle: %u/%u\n",
115 static_cast<unsigned>(
app->teleopIdxVeh + 1),
116 static_cast<unsigned>(vehs.size()));
117 if (vehs.size() >
app->teleopIdxVeh)
120 World::VehicleList::const_iterator it_veh = vehs.begin();
121 std::advance(it_veh,
app->teleopIdxVeh);
125 const mrpt::math::TTwist2D& vel =
126 it_veh->second->getVelocityLocal();
127 txt2gui_tmp += mrpt::format(
128 "gt. vel: lx=%7.03f, ly=%7.03f, w= %7.03fdeg/s\n", vel.vx,
129 vel.vy, mrpt::RAD2DEG(vel.omega));
133 const mrpt::math::TTwist2D& vel =
134 it_veh->second->getVelocityLocalOdoEstimate();
135 txt2gui_tmp += mrpt::format(
136 "odo vel: lx=%7.03f, ly=%7.03f, w= %7.03fdeg/s\n", vel.vx,
137 vel.vy, mrpt::RAD2DEG(vel.omega));
144 it_veh->second->getControllerInterface();
158 using namespace mvsim;
161 bool badArgs =
false;
162 const auto& unlabeledArgs =
cli->argCmd.getValue();
163 if (unlabeledArgs.size() != 2) badArgs =
true;
165 if (
cli->argHelp.isSet() || badArgs)
169 R
"XXX(Usage: mvsim launch <WORLD_MODEL.xml> [options] 172 --headless Launch without GUI (e.g. suitable for dockerized envs.) 173 --full-profiler Enable full profiling (generates file with all timings) 174 --realtime-factor <1.0> Run slower (<1) or faster (>1) than real time if !=1.0 175 -v, --verbosity Set verbosity level: DEBUG, INFO (default), WARN, ERROR 183 const auto verbosityLevel =
184 mrpt::typemeta::TEnumType<mrpt::system::VerbosityLevel>::name2value(
185 cli->argVerbosity.getValue());
187 if (verbosityLevel <= mrpt::system::LVL_INFO)
189 mrpt::system::consoleColorAndStyle(
190 mrpt::system::ConsoleForegroundColor::BRIGHT_YELLOW);
193 <<
"====================================================\n" 194 <<
" MVSIM simulator running. Press CTRL+C to end. \n" 195 <<
"====================================================\n" 197 mrpt::system::consoleColorAndStyle(
198 mrpt::system::ConsoleForegroundColor::DEFAULT);
201 const auto sXMLfilename = unlabeledArgs.at(1);
205 app->world.setMinLoggingLevel(verbosityLevel);
208 if (
cli->argFullProfiler.isSet())
209 app->world.getTimeLogger().enableKeepWholeHistory();
211 if (
cli->argHeadless.isSet())
app->world.headless(
true);
217 app->world.load_from_XML(fil_xml.data(), sXMLfilename.c_str());
219 catch (
const std::exception& e)
221 std::cerr <<
"Error: " << e.what() << std::endl;
230 app->world.connectToServer();
233 app->thread_params.world = &
app->world;
235 if (!
cli->argHeadless.isSet())
238 app->thGUI = std::thread(
244 app->thGUI = std::thread(
249 const double tAbsInit = mrpt::Clock::nowDouble();
250 const double rtFactor =
cli->argRealTimeFactor.getValue();
256 if (
app->world.simulator_must_close())
break;
261 double tNew = mrpt::Clock::nowDouble();
263 rtFactor * (tNew - tAbsInit) -
app->world.get_simul_time();
264 int incrTimeSteps =
static_cast<int>(
265 std::floor(incrTime /
app->world.get_simul_timestep()));
268 if (incrTimeSteps > 0)
270 app->world.run_simulation(
271 incrTimeSteps *
app->world.get_simul_timestep());
274 std::this_thread::sleep_for(std::chrono::milliseconds(10));
310 if (
app->thread_params.isClosing()) doExit =
true;
323 ASSERT_(thread_params.
world);
335 gui_key_events = guiparams.
keyevent;
339 std::this_thread::sleep_for(std::chrono::milliseconds(25));
342 catch (
const std::exception& e)
344 std::cerr <<
"[mvsim_server_thread_update_GUI] Exception: " << e.what()
353 ASSERT_(thread_params.
world);
359 std::this_thread::sleep_for(std::chrono::microseconds(mrpt::round(
366 catch (
const std::exception& e)
368 std::cerr <<
"[mvsim_server_thread_update_GUI] Exception: " << e.what()
void commonLaunchServer()
std::mutex gui_key_events_mtx
bool simulator_must_close() const
Represents data loaded from a file.
static void mvsim_server_thread_headless(TThreadParams &thread_params)
mvsim::World::TGUIKeyEvent gui_key_events
std::multimap< std::string, VehicleBase::Ptr > VehicleList
TThreadParams thread_params
TGUIKeyEvent keyevent
Keystrokes in the window are returned here.
std::string mvsim_launch_handle_teleop(const mvsim::World::TGUIKeyEvent keyevent)
double get_simul_timestep() const
Simulation fixed-time interval for numerical integration.
std::string msg_lines
Messages to show.
void mvsim_install_signal_handler()
std::unique_ptr< cli_flags > cli
std::string append_gui_lines
void mvsim_launch_shutdown()
std::optional< LaunchData > app
void update_GUI(TUpdateGUIParams *params=nullptr)
virtual void teleop_interface([[maybe_unused]] const TeleopInput &in, [[maybe_unused]] TeleopOutput &out)
void mvsim_signal_handler(int s)
void internalGraphicsLoopTasksForSimulation()
static void mvsim_server_thread_update_GUI(TThreadParams &thread_params)
int keycode
0=no Key. Otherwise, ASCII code.