14 #include <mrpt/core/bits_math.h> 15 #include <mrpt/core/format.h> 16 #include <mrpt/gui/CDisplayWindowGUI.h> 17 #include <mrpt/img/CImage.h> 18 #include <mrpt/img/TColor.h> 19 #include <mrpt/math/TPoint3D.h> 20 #include <mrpt/obs/CObservation.h> 21 #include <mrpt/obs/CObservationImage.h> 22 #include <mrpt/obs/obs_frwds.h> 23 #include <mrpt/system/COutputLogger.h> 24 #include <mrpt/system/CTicTac.h> 25 #include <mrpt/system/CTimeLogger.h> 37 #if MVSIM_HAS_ZMQ && MVSIM_HAS_PROTOBUF 42 class SrvGetPoseAnswer;
44 class SrvSetPoseAnswer;
45 class SrvSetControllerTwist;
46 class SrvSetControllerTwistAnswer;
48 class SrvShutdownAnswer;
62 class World :
public mrpt::system::COutputLogger
80 void load_from_XML_file(
const std::string& xmlFileNamePath);
82 void internal_initialize();
92 const std::string& xml_text,
93 const std::string& fileNameForPath = std::string(
"."));
102 auto lck = mrpt::lockHelper(simul_time_mtx_);
109 auto lck = mrpt::lockHelper(simul_time_mtx_);
110 simulTime_ = newSimulatedTime;
120 auto lck = mrpt::lockHelper(simul_time_mtx_);
121 ASSERT_(simul_start_wallclock_time_.has_value());
122 return mrpt::Clock::fromDouble(
123 simulTime_ + simul_start_wallclock_time_.value());
127 double get_simul_timestep()
const;
147 void run_simulation(
double dt);
153 bool modifierShift =
false;
154 bool modifierCtrl =
false;
155 bool modifierAlt =
false;
156 bool modifierSuper =
false;
185 return gui_.clickedPt;
193 mrpt::opengl::CSetOfObjects::Ptr guiUserObjectsPhysical_,
200 void internalGraphicsLoopTasksForSimulation();
202 void internalRunSensorsOn3DScene(
203 mrpt::opengl::COpenGLScene& physicalObjects);
205 void internalUpdate3DSceneObjects(
206 mrpt::opengl::COpenGLScene& viz, mrpt::opengl::COpenGLScene& physical);
207 void internal_GUI_thread();
208 void internal_process_pending_gui_user_tasks();
211 bool pendingRunSensorsOn3DScene_ =
false;
215 pendingRunSensorsOn3DSceneMtx_.lock();
216 pendingRunSensorsOn3DScene_ =
true;
217 pendingRunSensorsOn3DSceneMtx_.unlock();
221 pendingRunSensorsOn3DSceneMtx_.lock();
222 pendingRunSensorsOn3DScene_ =
false;
223 pendingRunSensorsOn3DSceneMtx_.unlock();
227 pendingRunSensorsOn3DSceneMtx_.lock();
228 bool ret = pendingRunSensorsOn3DScene_;
229 pendingRunSensorsOn3DSceneMtx_.unlock();
238 std::atomic_bool gui_thread_running_ =
false;
239 std::atomic_bool simulator_must_close_ =
false;
244 gui_thread_start_mtx_.lock();
245 const bool v = simulator_must_close_;
246 gui_thread_start_mtx_.unlock();
251 gui_thread_start_mtx_.lock();
252 simulator_must_close_ = value;
253 gui_thread_start_mtx_.unlock();
258 guiUserPendingTasksMtx_.lock();
259 guiUserPendingTasks_.emplace_back(
f);
260 guiUserPendingTasksMtx_.unlock();
267 std::atomic_bool lastKeyEventValid_ =
false;
270 bool is_GUI_open()
const;
287 using BlockList = std::multimap<std::string, Block::Ptr>;
309 return worldElements_;
316 return simulableObjects_;
325 std::string local_to_abs_path(
const std::string& in_path)
const;
333 std::string xmlPathToActualPath(
const std::string& modelURI)
const;
359 const Simulable& ,
const mrpt::obs::CObservation::Ptr& )>;
363 callbacksOnObservation_.emplace_back(f);
368 const Simulable& veh,
const mrpt::obs::CObservation::Ptr& obs)
370 for (
const auto& cb : callbacksOnObservation_) cb(veh, obs);
377 void connectToServer();
382 void free_opengl_resources();
386 bool headless()
const {
return guiOptions_.headless; }
387 void headless(
bool setHeadless) { guiOptions_.headless = setHeadless; }
389 bool sensor_has_to_create_egl_context();
393 return userDefinedVariables_;
407 double gravity_ = 9.81;
413 mutable double simulTimestep_ = 0;
416 int b2dVelIters_ = 8, b2dPosIters_ = 3;
418 std::string serverAddress_ =
"localhost";
421 {
"server_address", {
"%s", &serverAddress_}},
422 {
"gravity", {
"%lf", &gravity_}},
423 {
"simul_timestep", {
"%lf", &simulTimestep_}},
424 {
"b2d_vel_iters", {
"%i", &b2dVelIters_}},
425 {
"b2d_pos_iters", {
"%i", &b2dPosIters_}},
434 double simulTime_ = 0;
439 std::string basePath_{
"."};
443 mrpt::opengl::CSetOfObjects::Ptr glUserObjsPhysical_ =
444 mrpt::opengl::CSetOfObjects::Create();
445 mrpt::opengl::CSetOfObjects::Ptr glUserObjsViz_ =
446 mrpt::opengl::CSetOfObjects::Create();
451 unsigned int win_w = 800, win_h = 600;
452 bool start_maximized =
true;
453 int refresh_fps = 20;
455 bool show_forces =
false;
456 bool show_sensor_points =
true;
457 double force_scale = 0.01;
458 double camera_distance = 80.0;
459 double camera_azimuth_deg = 45.0;
460 double camera_elevation_deg = 40.0;
461 double fov_deg = 60.0;
462 float clip_plane_min = 0.05f;
463 float clip_plane_max = 10e3f;
464 mrpt::math::TPoint3D camera_point_to{0, 0, 0};
466 bool headless =
false;
469 {
"win_w", {
"%u", &win_w}},
470 {
"win_h", {
"%u", &win_h}},
471 {
"ortho", {
"%bool", &ortho}},
472 {
"show_forces", {
"%bool", &show_forces}},
473 {
"show_sensor_points", {
"%bool", &show_sensor_points}},
474 {
"force_scale", {
"%lf", &force_scale}},
475 {
"fov_deg", {
"%lf", &fov_deg}},
476 {
"follow_vehicle", {
"%s", &follow_vehicle}},
477 {
"start_maximized", {
"%bool", &start_maximized}},
478 {
"refresh_fps", {
"%i", &refresh_fps}},
479 {
"headless", {
"%bool", &headless}},
480 {
"clip_plane_min", {
"%f", &clip_plane_min}},
481 {
"clip_plane_max", {
"%f", &clip_plane_max}},
482 {
"cam_distance", {
"%lf", &camera_distance}},
483 {
"cam_azimuth", {
"%lf", &camera_azimuth_deg}},
484 {
"cam_elevation", {
"%lf", &camera_elevation_deg}},
485 {
"cam_point_to", {
"%point3d", &camera_point_to}},
504 bool enable_shadows =
true;
505 int shadow_map_size = 2048;
507 double light_azimuth = mrpt::DEG2RAD(45.0);
508 double light_elevation = mrpt::DEG2RAD(70.0);
510 float light_clip_plane_min = 0.1f;
511 float light_clip_plane_max = 900.0f;
513 float shadow_bias = 1e-5;
514 float shadow_bias_cam2frag = 1e-5;
515 float shadow_bias_normal = 1e-4;
517 mrpt::img::TColor light_color = {0xff, 0xff, 0xff, 0xff};
518 float light_ambient = 0.5f;
520 float eye_distance_to_shadow_map_extension = 2.0f;
521 float minimum_shadow_map_extension_ratio = 0.005f;
524 {
"enable_shadows", {
"%bool", &enable_shadows}},
525 {
"shadow_map_size", {
"%i", &shadow_map_size}},
526 {
"light_azimuth_deg", {
"%lf_deg", &light_azimuth}},
527 {
"light_elevation_deg", {
"%lf_deg", &light_elevation}},
528 {
"light_clip_plane_min", {
"%f", &light_clip_plane_min}},
529 {
"light_clip_plane_max", {
"%f", &light_clip_plane_max}},
530 {
"light_color", {
"%color", &light_color}},
531 {
"shadow_bias", {
"%f", &shadow_bias}},
532 {
"shadow_bias_cam2frag", {
"%f", &shadow_bias_cam2frag}},
533 {
"shadow_bias_normal", {
"%f", &shadow_bias_normal}},
534 {
"light_ambient", {
"%f", &light_ambient}},
535 {
"eye_distance_to_shadow_map_extension",
536 {
"%f", &eye_distance_to_shadow_map_extension}},
537 {
"minimum_shadow_map_extension_ratio",
538 {
"%f", &minimum_shadow_map_extension_ratio}},
559 bool initialized_ =
false;
568 void internal_one_timestep(
double dt);
578 nanogui::Label* lbCpuUsage =
nullptr;
584 nanogui::CheckBox* cb =
nullptr;
594 mrpt::math::TPoint3D clickedPt{0, 0, 0};
596 void prepare_control_window();
597 void prepare_status_window();
598 void prepare_editor_window();
600 void handle_mouse_operations();
610 mrpt::opengl::COpenGLScene::Ptr worldVisual_ =
611 mrpt::opengl::COpenGLScene::Create();
630 void internal_gui_on_observation(
631 const Simulable& veh,
const mrpt::obs::CObservation::Ptr& obs);
632 void internal_gui_on_observation_3Dscan(
634 const std::shared_ptr<mrpt::obs::CObservation3DRangeScan>& obs);
635 void internal_gui_on_observation_image(
637 const std::shared_ptr<mrpt::obs::CObservationImage>& obs);
639 mrpt::math::TPoint2D internal_gui_on_image(
640 const std::string& label,
const mrpt::img::CImage& im,
int winPosX);
646 void setLightDirectionFromAzimuthElevation(
647 const float azimuth,
const float elevation);
651 mrpt::system::CTimeLogger timlogger_{
true ,
"mvsim::World"};
661 : node(n), currentBasePath(basePath)
673 std::function<void(const XmlParserContext&)>;
677 void register_standard_xml_tag_parsers();
682 xmlParsers_.emplace(xmlTagName, f);
685 const std::string& xmlTagName,
714 void internal_advertiseServices();
716 #if MVSIM_HAS_ZMQ && MVSIM_HAS_PROTOBUF 718 mvsim_msgs::SrvSetPoseAnswer srv_set_pose(
719 const mvsim_msgs::SrvSetPose& req);
720 mvsim_msgs::SrvGetPoseAnswer srv_get_pose(
721 const mvsim_msgs::SrvGetPose& req);
722 mvsim_msgs::SrvSetControllerTwistAnswer srv_set_controller_twist(
723 const mvsim_msgs::SrvSetControllerTwist& req);
724 mvsim_msgs::SrvShutdownAnswer srv_shutdown(
725 const mvsim_msgs::SrvShutdown& req);
void registerCallbackOnObservation(const on_observation_callback_t &f)
std::shared_ptr< Simulable > Ptr
void set_simul_timestep(double timestep)
std::function< void(const XmlParserContext &)> xml_tag_parser_function_t
std::unique_ptr< b2World > box2d_world_
bool simulator_must_close() const
mrpt::opengl::COpenGLScene worldPhysical_
double get_simul_time() const
std::map< std::string, TParamEntry > TParameterDefinitions
std::multimap< std::string, Simulable::Ptr > SimulableList
const WorldElementList & getListOfWorldElements() const
SimulableList simulableObjects_
std::mutex guiUserPendingTasksMtx_
std::mutex guiMsgLinesMtx_
std::mutex pendingRunSensorsOn3DSceneMtx_
std::vector< InfoPerObject > gui_cbObjects
std::map< std::string, xml_tag_parser_function_t > xmlParsers_
XmlParserContext(const rapidxml::xml_node< char > *n, const std::string &basePath)
std::mutex simulationStepRunningMtx_
std::multimap< std::string, VehicleBase::Ptr > VehicleList
InfoPerObject gui_selectedObject
const VehicleList & getListOfVehicles() const
std::string follow_vehicle
Vehicle name to follow (empty=none)
std::function< void(const Simulable &, const mrpt::obs::CObservation::Ptr &)> on_observation_callback_t
std::unique_ptr< b2World > & getBox2DWorld()
std::mutex lastKeyEventMtx_
void force_set_simul_time(double newSimulatedTime)
Normally should not be called by users, for internal use only.
std::function< void(Block &)> block_visitor_t
mrpt::gui::CDisplayWindowGUI::Ptr gui_win
mrpt::system::CTicTac timer_iteration_
mrpt::Clock::time_point get_simul_timestamp() const
std::shared_ptr< Block > Ptr
std::function< void(VehicleBase &)> vehicle_visitor_t
std::multimap< std::string, Block::Ptr > BlockList
TGUIKeyEvent keyevent
Keystrokes in the window are returned here.
A rigid body. These are created via b2World::CreateBody.
void register_tag_parser(const std::string &xmlTagName, void(World::*f)(const XmlParserContext &ctx))
void set_gravity(double accel)
std::mutex guiUserObjectsMtx_
auto & getListOfSimulableObjectsMtx()
std::mutex gui_thread_start_mtx_
std::recursive_mutex copy_of_objects_dynstate_mtx_
auto & physical_objects_mtx()
std::vector< on_observation_callback_t > callbacksOnObservation_
void simulator_must_close(bool value)
RemoteResourcesManager remoteResources_
std::string msg_lines
Messages to show.
const std::map< std::string, std::string > & user_defined_variables() const
IMGUI_API bool Button(const char *label, const ImVec2 &size=ImVec2(0, 0))
std::vector< nanogui::Label * > lbStatuses
const mvsim::Client & commsClient() const
const std::string currentBasePath
std::function< void(WorldElementBase &)> world_element_visitor_t
std::map< std::string, nanogui::Window * > guiObsViz_
by sensorLabel
std::vector< nanogui::Widget * > btns_selectedOps
bool pending_running_sensors_on_3D_scene()
void dispatchOnObservation(const Simulable &veh, const mrpt::obs::CObservation::Ptr &obs)
const mrpt::math::TPoint3D & gui_mouse_point() const
typedef void(GLAD_API_PTR *GLDEBUGPROC)(GLenum source
mrpt::opengl::CSetOfObjects::Ptr guiUserObjectsViz_
const SimulableList & getListOfSimulableObjects() const
const mrpt::gui::CDisplayWindowGUI::Ptr & gui_window() const
mrpt::system::CTimeLogger & getTimeLogger()
std::map< std::string, mrpt::math::TPose3D > copy_of_objects_dynstate_pose_
Updated in internal_one_step()
const BlockList & getListOfBlocks() const
void clear_pending_running_sensors_on_3D_scene()
std::set< std::string > copy_of_objects_had_collision_
std::mutex reset_collision_flags_mtx_
const std::unique_ptr< b2World > & getBox2DWorld() const
std::recursive_mutex worldPhysicalMtx_
b2Body * getBox2DGroundBody()
std::recursive_mutex world_cs_
VehicleList & getListOfVehicles()
LightOptions lightOptions_
std::map< std::string, std::string > userDefinedVariables_
BlockList & getListOfBlocks()
std::optional< double > simul_start_wallclock_time_
std::mutex simul_time_mtx_
std::map< std::string, mrpt::math::TTwist2D > copy_of_objects_dynstate_twist_
void register_tag_parser(const std::string &xmlTagName, const xml_tag_parser_function_t &f)
std::list< WorldElementBase::Ptr > WorldElementList
WorldElementList worldElements_
void mark_as_pending_running_sensors_on_3D_scene()
mvsim::Client & commsClient()
TGUIKeyEvent lastKeyEvent_
void headless(bool setHeadless)
std::set< std::string > reset_collision_flags_
double get_gravity() const
std::vector< std::function< void(void)> > guiUserPendingTasks_
SimulableList & getListOfSimulableObjects()
Always lock/unlock getListOfSimulableObjectsMtx() before using this:
std::mutex simulableObjectsMtx_
void enqueue_task_to_run_in_gui_thread(const std::function< void(void)> &f)