8 #include <mrpt/system/os.h>       9 #include <mrpt/system/filesystem.h>    11 #include <mrpt_bridge/laser_scan.h>    12 #include <mrpt_bridge/map.h>    13 #include <mrpt_bridge/pose.h>    15 #include <nav_msgs/MapMetaData.h>    16 #include <nav_msgs/GetMap.h>    17 #include <geometry_msgs/PoseWithCovarianceStamped.h>    18 #include <geometry_msgs/PoseArray.h>    19 #include <geometry_msgs/Polygon.h>    20 #include <sensor_msgs/LaserScan.h>    22 #include <nav_msgs/Odometry.h>    30         : mvsim_world_(*this),
    31           realtime_factor_(1.0),
    32           gui_refresh_period_ms_(75),
    34           m_do_fake_localization(true),
    35           m_transform_tolerance(0.1),
    39           m_tfIdentity(
tf::createIdentityQuaternion(), 
tf::
Point(0, 0, 0)),
    41           world_init_ok_(false),
    42           m_period_ms_publish_tf(20),
    43           m_period_ms_teleop_refresh(100),
    55                 "simul_map", 1 , 
true );
    57                 "simul_map_metadata", 1 , 
true );
    82         ROS_INFO(
"[MVSimNode] Loading world file: %s", world_xml_file.c_str());
    84                 mrpt::system::fileExists(world_xml_file),
    85                 "[MVSimNode::loadWorldModel] File does not exist!: '%s'",
    86                 world_xml_file.c_str());
    92         ROS_INFO(
"[MVSimNode] World file load done.");
   118         ROS_INFO(
"MVSimNode::configCallback() called.");
   127         using namespace mvsim;
   160                 std::string txt2gui_tmp;
   178                         txt2gui_tmp += mrpt::format(
   179                                 "Selected vehicle: %u/%u\n",
   181                                 static_cast<unsigned>(vehs.size()));
   185                                 World::TListVehicles::const_iterator it_veh = vehs.begin();
   190                                         const vec3& vel = it_veh->second->getVelocityLocal();
   191                                         txt2gui_tmp += mrpt::format(
   192                                                 "gt. vel: lx=%7.03f, ly=%7.03f, w= %7.03fdeg/s\n",
   194                                             RAD2DEG(vel.
vals[2]));
   199                                                 it_veh->second->getVelocityLocalOdoEstimate();
   200                                         txt2gui_tmp += mrpt::format(
   201                                                 "odo vel: lx=%7.03f, ly=%7.03f, w= %7.03fdeg/s\n",
   203                                             RAD2DEG(vel.
vals[2]));
   210                                                 it_veh->second->getControllerInterface();
   233         using namespace mvsim;
   250                 std::this_thread::sleep_for(
   268         if (dynamic_cast<mvsim::OccupancyGridMap*>(obj))
   273                 nav_msgs::OccupancyGrid ros_map;
   274                 mrpt_bridge::convert(grid->
getOccGrid(), ros_map);
   276                 static size_t loop_count = 0;
   278                 ros_map.header.seq = loop_count++;
   280                 m_parent.m_pub_map_ros.publish(ros_map);
   281                 m_parent.m_pub_map_metadata.publish(ros_map.info);
   301         for (mvsim::World::TListVehicles::iterator it = vehs.begin();
   302                  it != vehs.end(); ++it, ++idx)
   313         const std::string& frame_id, 
const std::string& child_frame_id,
   316         geometry_msgs::TransformStamped tx;
   317         tx.header.frame_id = frame_id;
   318         tx.child_frame_id = child_frame_id;
   319         tx.header.stamp = stamp;
   339                 vehVarName(
"base_pose_ground_truth", veh), 10);
   345                                 vehVarName(
"chassis_markers", veh), 5, 
true );
   353                 visualization_msgs::Marker& chassis_shape_msg = msg_shapes.markers[0];
   355                 chassis_shape_msg.action = visualization_msgs::Marker::MODIFY;
   356                 chassis_shape_msg.type = visualization_msgs::Marker::LINE_STRIP;
   357                 chassis_shape_msg.header.frame_id = 
vehVarName(
"base_link", veh);
   358                 chassis_shape_msg.ns = 
"mvsim.chassis_shape";
   360                 chassis_shape_msg.scale.x = 0.05;
   361                 chassis_shape_msg.scale.y = 0.05;
   362                 chassis_shape_msg.scale.z = 0.02;
   363                 chassis_shape_msg.points.resize(poly.size() + 1);
   364                 for (
size_t i = 0; i <= poly.size(); i++)
   366                         size_t k = i % poly.size();
   367                         chassis_shape_msg.points[i].x = poly[k].x;
   368                         chassis_shape_msg.points[i].y = poly[k].y;
   369                         chassis_shape_msg.points[i].z = 0;
   371                 chassis_shape_msg.color.a = 0.9;
   372                 chassis_shape_msg.color.r = 0.9;
   373                 chassis_shape_msg.color.g = 0.9;
   374                 chassis_shape_msg.color.b = 0.9;
   375                 chassis_shape_msg.frame_locked = 
true;
   380                         visualization_msgs::Marker& wheel_shape_msg =
   381                                 msg_shapes.markers[1 + i];
   385                         wheel_shape_msg = chassis_shape_msg;  
   386                         chassis_shape_msg.ns = mrpt::format(
   387                                 "mvsim.chassis_shape.wheel%u", static_cast<unsigned int>(i));
   388                         wheel_shape_msg.points.resize(5);
   389                         wheel_shape_msg.points[0].x = lx;
   390                         wheel_shape_msg.points[0].y = ly;
   391                         wheel_shape_msg.points[0].z = 0;
   392                         wheel_shape_msg.points[1].x = lx;
   393                         wheel_shape_msg.points[1].y = -ly;
   394                         wheel_shape_msg.points[1].z = 0;
   395                         wheel_shape_msg.points[2].x = -lx;
   396                         wheel_shape_msg.points[2].y = -ly;
   397                         wheel_shape_msg.points[2].z = 0;
   398                         wheel_shape_msg.points[3].x = -lx;
   399                         wheel_shape_msg.points[3].y = ly;
   400                         wheel_shape_msg.points[3].z = 0;
   401                         wheel_shape_msg.points[4] = wheel_shape_msg.points[0];
   403                         wheel_shape_msg.color.r = w.
color.R / 255.0;
   404                         wheel_shape_msg.color.g = w.
color.G / 255.0;
   405                         wheel_shape_msg.color.b = w.
color.B / 255.0;
   412                                 wheel_shape_msg.pose);
   422                         vehVarName(
"chassis_polygon", veh), 1, 
true );
   425                 geometry_msgs::Polygon poly_msg;
   427                 poly_msg.points.resize(poly.size());
   428                 for (
size_t i = 0; i < poly.size(); i++)
   430                         poly_msg.points[i].x = poly[i].x;
   431                         poly_msg.points[i].y = poly[i].y;
   432                         poly_msg.points[i].z = 0;
   441                         m_n.
advertise<geometry_msgs::PoseWithCovarianceStamped>(
   459         const bool ctrlAcceptTwist =
   462         if (!ctrlAcceptTwist)
   466                         "*Warning* Vehicle's controller ['%s'] refuses Twist commands!",
   474         using namespace mvsim;
   492                 for (World::TListVehicles::const_iterator it = vehs.begin();
   493                          it != vehs.end(); ++it, ++i)
   497                         const std::string sOdomName = 
vehVarName(
"odom", veh);
   498                         const std::string sBaseLinkFrame = 
vehVarName(
"base_link", veh);
   502                         const mrpt::math::TPose3D& gh_veh_pose = veh->
getPose();
   507                                 nav_msgs::Odometry gtOdoMsg;
   509                                 gtOdoMsg.pose.pose.position.x = gh_veh_pose.x;
   510                                 gtOdoMsg.pose.pose.position.y = gh_veh_pose.y;
   511                                 gtOdoMsg.pose.pose.position.z = gh_veh_pose.z;
   515                                         gh_veh_pose.roll, gh_veh_pose.pitch, gh_veh_pose.yaw);
   517                                 gtOdoMsg.pose.pose.orientation.x = quat.x();
   518                                 gtOdoMsg.pose.pose.orientation.y = quat.y();
   519                                 gtOdoMsg.pose.pose.orientation.z = quat.z();
   520                                 gtOdoMsg.pose.pose.orientation.w = quat.w();
   521                                 gtOdoMsg.twist.twist.linear.x = gh_veh_vel.
vals[0];
   522                                 gtOdoMsg.twist.twist.linear.y = gh_veh_vel.
vals[1];
   523                                 gtOdoMsg.twist.twist.linear.z = 0;
   524                                 gtOdoMsg.twist.twist.angular.z = gh_veh_vel.
vals[2];
   527                                 gtOdoMsg.header.frame_id = sOdomName;
   528                                 gtOdoMsg.child_frame_id = sBaseLinkFrame;
   534                                         geometry_msgs::PoseWithCovarianceStamped currentPos;
   535                                         geometry_msgs::PoseArray particleCloud;
   539                                                         .pub_particlecloud.getNumSubscribers() > 0)
   542                                                 particleCloud.header.frame_id = 
"/map";
   543                                                 particleCloud.poses.resize(1);
   544                                                 particleCloud.poses[0] = gtOdoMsg.pose.pose;
   553                                                 currentPos.header = gtOdoMsg.header;
   554                                                 currentPos.pose.pose = gtOdoMsg.pose.pose;
   561                                                         "Save initial pose for each vehicle, set odometry "   579                                 visualization_msgs::MarkerArray& msg_shapes =
   582                                         msg_shapes.markers.size() == (1 + veh->
getNumWheels()));
   588                                         visualization_msgs::Marker& wheel_shape_msg =
   589                                                 msg_shapes.markers[1 + j];
   597                                                 wheel_shape_msg.pose);
   607                                 const mrpt::math::TPose3D odo_pose = gh_veh_pose;
   612                                                 odo_pose.yaw, odo_pose.pitch, odo_pose.roll);
   614                                                 rot, 
tf::Vector3(odo_pose.x, odo_pose.y, odo_pose.z));
   624                                         nav_msgs::Odometry odoMsg;
   626                                         odoMsg.pose.pose.position.x = odo_pose.x;
   627                                         odoMsg.pose.pose.position.y = odo_pose.y;
   628                                         odoMsg.pose.pose.position.z = odo_pose.z;
   631                                         quat.
setEuler(odo_pose.roll, odo_pose.pitch, odo_pose.yaw);
   633                                         odoMsg.pose.pose.orientation.x = quat.x();
   634                                         odoMsg.pose.pose.orientation.y = quat.y();
   635                                         odoMsg.pose.pose.orientation.z = quat.z();
   636                                         odoMsg.pose.pose.orientation.w = quat.w();
   640                                         odoMsg.header.frame_id = sOdomName;
   641                                         odoMsg.child_frame_id = sBaseLinkFrame;
   656 #
if MRPT_VERSION >= 0x130
   657         const mrpt::obs::CObservation* obs
   659         const mrpt::slam::CObservation* obs
   669         const bool is_1st_pub =
   670                 pubs.
pub_sensors.find(obs->sensorLabel) == pubs.pub_sensors.end();
   675         if (dynamic_cast<const CObservation2DRangeScan*>(obs))
   678                         pub = m_parent.m_n.advertise<sensor_msgs::LaserScan>(
   679                                 m_parent.vehVarName(obs->sensorLabel, &veh), 10);
   681                 const CObservation2DRangeScan* o =
   682                         dynamic_cast<const CObservation2DRangeScan*
>(obs);
   683                 const std::string sSensorFrameId =
   684                         m_parent.vehVarName(obs->sensorLabel, &veh);
   687                 mrpt::poses::CPose3D pose_laser;
   689                 o->getSensorPose(pose_laser);
   690                 mrpt_bridge::convert(pose_laser, transform);
   692                 m_parent.m_tf_br.sendTransform(
   694                                 transform, m_parent.m_sim_time,
   695                                 m_parent.vehVarName(
"base_link", &veh),  
   702                         geometry_msgs::Pose msg_pose_laser;
   703                         sensor_msgs::LaserScan msg_laser;
   704                         mrpt_bridge::convert(*o, msg_laser, msg_pose_laser);
   707                         msg_laser.header.stamp = m_parent.m_sim_time;
   708                         msg_laser.header.frame_id = sSensorFrameId;
   727                 return std::string(
"/") + sVarName;
   731                 return std::string(
"/") + veh->
getName() + std::string(
"/") + sVarName;
 
ros::Publisher pub_ground_truth
Publisher of "base_pose_ground_truth" topic. 
ros::Publisher pub_amcl_pose
static void thread_update_GUI(TThreadParams &thread_params)
mrpt::utils::CTicTac m_tim_publish_tf
TF transforms & /*/odom topics (In ms) 
std::string vehVarName(const std::string &sVarName, const mvsim::VehicleBase *veh) const 
double width
Length(diameter) and width of the wheel rectangle [m]. 
void visit(mvsim::VehicleBase *obj)
double m_period_ms_teleop_refresh
void publish(const boost::shared_ptr< M > &message) const 
Represents data loaded from a file. 
void update_GUI(TUpdateGUIParams *params=NULL)
ros::Subscriber sub_cmd_vel
Subscribers for each vehicle's "cmd_vel" topic. 
virtual void teleop_interface(const TeleopInput &in, TeleopOutput &out)
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
void runVisitorOnWorldElements(WorldElementVisitorBase &v)
const std::string & getName() const 
std::multimap< std::string, VehicleBase * > TListVehicles
ros::Time m_base_last_cmd
Last time we received a vel_cmd (for watchdog) 
ros::Publisher m_pub_map_ros
void setEulerYPR(tfScalar eulerZ, tfScalar eulerY, tfScalar eulerX)
TColor color
constructor and at loadFromXML(), but can be overrided. 
virtual void onNewObservation(const mvsim::VehicleBase &veh, const CObservation *obs)
rosgraph_msgs::Clock m_clockMsg
static tf::Quaternion createIdentityQuaternion()
mvsim::World::TGUIKeyEvent m_gui_key_events
"focused" vehicle) 
const mrpt::math::TPolygon2D & getChassisShape() const 
ros::Duration m_base_watchdog_timeout
TGUIKeyEvent keyevent
Keystrokes in the window are returned here. 
const tf::Transform m_tfIdentity
Unit transform (const, created only once) 
double get_simul_timestep() const 
Simulation fixed-time interval for numerical integration. 
void onROSMsgCmdVel(const geometry_msgs::Twist::ConstPtr &cmd, mvsim::VehicleBase *veh)
tf::TransformBroadcaster m_tf_br
Use to send data to TF. 
size_t getNumWheels() const 
void loadWorldModel(const std::string &world_xml_file)
void spin()
Process pending msgs, run real-time simulation, etc. 
void configCallback(mvsim::mvsimNodeConfig &config, uint32_t level)
int gui_refresh_period_ms_
Default:25. 
bool is_GUI_open() const 
Forces closing the GUI window, if any. 
Duration & fromSec(double t)
tf2_ros::StaticTransformBroadcaster m_static_tf_br
For sending STATIC tf. 
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const 
size_t getVehicleIndex() const 
#define ROS_ASSERT_MSG(cond,...)
mrpt::utils::CTicTac realtime_tictac_
double m_period_ms_publish_tf
loadWorldModel() 
std::string msg_lines
Messages to show. 
double diameter
[m,rad] (in local coords) 
virtual ControllerBaseInterface * getControllerInterface()=0
ros::Publisher pub_chassis_shape
"<VEH>/chassis_shape" 
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
ros::NodeHandle & m_n
published TFs 
const Wheel & getWheelInfo(const size_t idx) const 
void sendStaticTF(const std::string &frame_id, const std::string &child_frame_id, const tf::Transform &tx, const ros::Time &stamp)
void load_from_XML(const std::string &xml_text, const std::string &fileNameForPath=std::string("."))
ros::Publisher pub_chassis_markers
"<VEH>/chassis_markers" 
TThreadParams thread_params_
void setEuler(const tfScalar &yaw, const tfScalar &pitch, const tfScalar &roll)
virtual bool setTwistCommand(const double vx, const double wz)
const mrpt::math::TPose3D & getPose() const 
ros::Publisher pub_particlecloud
Publishers for "fake_localization" topics. 
const COccupancyGridMap2D & getOccGrid() const 
ros::Publisher pub_odom
Publisher of "odom" topic. 
TFSIMD_FORCE_INLINE const tfScalar & w() const 
mrpt::utils::CTicTac m_tim_teleop_refresh
uint32_t getNumSubscribers() const 
static void poseTFToMsg(const Pose &bt, geometry_msgs::Pose &msg)
void initPubSubs(TPubSubPerVehicle &out_pubsubs, mvsim::VehicleBase *veh)
bool getParam(const std::string &key, std::string &s) const 
ros::Publisher m_pub_clock
std::vector< TPubSubPerVehicle > m_pubsub_vehicles
const TListVehicles & getListOfVehicles() const 
std::string append_gui_lines
MVSimNode(ros::NodeHandle &n)
void runVisitorOnVehicles(VehicleVisitorBase &v)
std::map< std::string, ros::Publisher > pub_sensors
Map <sensor_label> => publisher. 
void run_simulation(double dt)
void notifyROSWorldIsUpdated()
bool m_show_gui
Default= true. 
ros::Time m_sim_time
Current simulation time. 
bool m_do_fake_localization
double get_simul_time() const 
Simulation wall-clock time. 
void setParam(const std::string &key, const XmlRpc::XmlRpcValue &v) const 
#define ROS_DEBUG_THROTTLE(period,...)
visualization_msgs::MarkerArray chassis_shape_msg
static void transformTFToMsg(const Transform &bt, geometry_msgs::Transform &msg)
const vec3 & getVelocity() const 
int keycode
0=no Key. Otherwise, ASCII code. 
double realtime_factor_
everything: vehicles, obstacles, etc.) 
void close_GUI()
a previous call to update_GUI() 
ros::Publisher m_pub_map_metadata
used for simul_map publication