10 #include <mrpt/core/lock_helper.h>
11 #include <mrpt/system/filesystem.h>
12 #include <mrpt/system/os.h>
13 #include <mrpt/version.h>
19 #if MRPT_VERSION >= 0x020b04 // >=2.11.4?
20 #define HAVE_POINTS_XYZIRT
23 #if defined(HAVE_POINTS_XYZIRT)
24 #include <mrpt/maps/CPointsMapXYZIRT.h>
27 #if PACKAGE_ROS_VERSION == 1
31 #include <mrpt/ros1bridge/image.h>
32 #include <mrpt/ros1bridge/imu.h>
33 #include <mrpt/ros1bridge/laser_scan.h>
34 #include <mrpt/ros1bridge/map.h>
35 #include <mrpt/ros1bridge/point_cloud2.h>
36 #include <mrpt/ros1bridge/pose.h>
37 #include <sensor_msgs/Image.h>
38 #include <sensor_msgs/Imu.h>
39 #include <sensor_msgs/LaserScan.h>
40 #include <sensor_msgs/NavSatFix.h>
41 #include <sensor_msgs/PointCloud2.h>
49 using Msg_Pose = geometry_msgs::Pose;
52 using Msg_GPS = sensor_msgs::NavSatFix;
54 using Msg_Imu = sensor_msgs::Imu;
63 #include <mrpt/ros2bridge/image.h>
64 #include <mrpt/ros2bridge/imu.h>
65 #include <mrpt/ros2bridge/laser_scan.h>
66 #include <mrpt/ros2bridge/map.h>
67 #include <mrpt/ros2bridge/point_cloud2.h>
68 #include <mrpt/ros2bridge/pose.h>
70 #include <sensor_msgs/msg/image.hpp>
71 #include <sensor_msgs/msg/imu.hpp>
72 #include <sensor_msgs/msg/laser_scan.hpp>
73 #include <sensor_msgs/msg/nav_sat_fix.hpp>
74 #include <sensor_msgs/msg/point_cloud2.hpp>
77 #if defined(MVSIM_HAS_TF2_GEOMETRY_MSGS_HPP)
78 #include <tf2_geometry_msgs/tf2_geometry_msgs.hpp>
83 #include <tf2_ros/qos.hpp>
93 using Msg_GPS = sensor_msgs::msg::NavSatFix;
102 #if PACKAGE_ROS_VERSION == 1
103 namespace mrpt2ros = mrpt::ros1bridge;
105 namespace mrpt2ros = mrpt::ros2bridge;
108 #if PACKAGE_ROS_VERSION == 1
109 #define ROS12_INFO(...) ROS_INFO(__VA_ARGS__)
110 #define ROS12_WARN_THROTTLE(...) ROS_WARN_THROTTLE(__VA_ARGS__)
111 #define ROS12_WARN_STREAM_THROTTLE(...) ROS_WARN_STREAM_THROTTLE(__VA_ARGS__)
112 #define ROS12_ERROR(...) ROS_ERROR(__VA_ARGS__)
114 #define ROS12_INFO(...) RCLCPP_INFO(n_->get_logger(), __VA_ARGS__)
115 #define ROS12_WARN_THROTTLE(...) RCLCPP_WARN_THROTTLE(n_->get_logger(), *clock_, __VA_ARGS__)
116 #define ROS12_WARN_STREAM_THROTTLE(...) \
117 RCLCPP_WARN_STREAM_THROTTLE(n_->get_logger(), *clock_, __VA_ARGS__)
118 #define ROS12_ERROR(...) RCLCPP_ERROR(n_->get_logger(), __VA_ARGS__)
127 #if PACKAGE_ROS_VERSION == 1
135 #if PACKAGE_ROS_VERSION == 1
137 if (!localn_.getParam(
"base_watchdog_timeout",
t))
t = 0.2;
138 base_watchdog_timeout_.fromSec(
t);
139 localn_.param(
"realtime_factor", realtime_factor_, 1.0);
140 localn_.param(
"gui_refresh_period", gui_refresh_period_ms_, gui_refresh_period_ms_);
141 localn_.param(
"headless", headless_, headless_);
142 localn_.param(
"period_ms_publish_tf", period_ms_publish_tf_, period_ms_publish_tf_);
143 localn_.param(
"do_fake_localization", do_fake_localization_, do_fake_localization_);
144 localn_.param(
"publish_tf_odom2baselink", publish_tf_odom2baselink_, publish_tf_odom2baselink_);
146 "force_publish_vehicle_namespace", force_publish_vehicle_namespace_,
147 force_publish_vehicle_namespace_);
152 if (
true == localn_.param(
"use_sim_time",
false))
154 THROW_EXCEPTION(
"At present, MVSIM can only work with use_sim_time=false");
157 clock_ = n_->get_clock();
158 ts_.attachClock(clock_);
161 n_->declare_parameter<std::string>(
"world_file",
"default.world.xml");
162 n_->declare_parameter<
double>(
"simul_rate", 100);
163 n_->declare_parameter<
double>(
"base_watchdog_timeout", 0.2);
166 base_watchdog_timeout_ =
167 std::chrono::milliseconds(1000 * n_->get_parameter_or(
"base_watchdog_timeout",
t, 0.2));
170 realtime_factor_ = n_->declare_parameter<
double>(
"realtime_factor", realtime_factor_);
172 gui_refresh_period_ms_ =
173 n_->declare_parameter<
double>(
"gui_refresh_period", gui_refresh_period_ms_);
175 headless_ = n_->declare_parameter<
bool>(
"headless", headless_);
177 period_ms_publish_tf_ =
178 n_->declare_parameter<
double>(
"period_ms_publish_tf", period_ms_publish_tf_);
180 do_fake_localization_ =
181 n_->declare_parameter<
bool>(
"do_fake_localization", do_fake_localization_);
183 publish_tf_odom2baselink_ =
184 n_->declare_parameter<
bool>(
"publish_tf_odom2baselink", publish_tf_odom2baselink_);
186 publisher_history_len_ =
187 n_->declare_parameter<
int>(
"publisher_history_len", publisher_history_len_);
189 force_publish_vehicle_namespace_ = n_->declare_parameter<
bool>(
190 "force_publish_vehicle_namespace", force_publish_vehicle_namespace_);
193 if (
true == n_->get_parameter_or(
"use_sim_time",
false))
195 THROW_EXCEPTION(
"At present, MVSIM can only work with use_sim_time=false");
200 thread_params_.obj =
this;
204 #if PACKAGE_ROS_VERSION == 1
210 #if PACKAGE_ROS_VERSION == 1
212 base_last_cmd_.fromSec(0.0);
215 base_last_cmd_ = rclcpp::Time(0);
218 mvsim_world_->registerCallbackOnObservation(
219 [
this](
const mvsim::Simulable& veh,
const mrpt::obs::CObservation::Ptr& obs)
223 mrpt::system::CTimeLoggerEntry tle(profiler_,
"lambda_onNewObservation");
226 const mrpt::obs::CObservation::Ptr obsCopy = obs;
227 const auto fut = ros_publisher_workers_.enqueue(
228 [
this, vehPtr, obsCopy]()
232 onNewObservation(*vehPtr, obsCopy);
234 catch (
const std::exception& e)
237 "[MVSimNode] Error processing observation with "
240 obsCopy ? obsCopy->sensorLabel.c_str() :
"(nullptr)", e.what());
248 ROS12_INFO(
"[MVSimNode] launch_mvsim_server()");
249 #if defined(MVSIM_HAS_ZMQ) && defined(MVSIM_HAS_PROTOBUF)
251 ASSERT_(!mvsim_server_);
254 mvsim_server_ = mvsim_node::make_shared<mvsim::Server>();
256 mvsim_server_->start();
262 ROS12_INFO(
"[MVSimNode] Loading world file: %s", world_xml_file.c_str());
264 ASSERT_FILE_EXISTS_(world_xml_file);
270 ROS12_INFO(
"[MVSimNode] World file load done.");
297 std::cout <<
"[MVSimNode::terminateSimulation] All done." << std::endl;
300 #if PACKAGE_ROS_VERSION == 1
305 void MVSimNode::configCallback(mvsim::mvsimNodeConfig& config, [[maybe_unused]] uint32_t level)
310 ROS12_INFO(
"MVSimNode::configCallback() called.");
319 using namespace mvsim;
320 using namespace std::string_literals;
333 if (incr_time < mvsim_world_->get_simul_timestep())
return;
353 std::string txt2gui_tmp;
371 txt2gui_tmp += mrpt::format(
372 "Selected vehicle: %u/%u\n",
static_cast<unsigned>(
teleop_idx_veh_ + 1),
373 static_cast<unsigned>(vehs.size()));
377 auto it_veh = vehs.begin();
381 txt2gui_tmp +=
"gt. vel: "s + it_veh->second->getVelocityLocal().asString();
385 "\nodo vel: "s + it_veh->second->getVelocityLocalOdoEstimate().asString();
390 auto* controller = it_veh->second->getControllerInterface();
395 controller->teleop_interface(teleop_in, teleop_out);
410 std::set<mvsim::VehicleBase*> toRemove;
415 auto* controller = veh->getControllerInterface();
417 controller->setTwistCommand({0, 0, 0});
418 toRemove.insert(veh);
421 for (
auto* veh : toRemove)
452 obj->
mvsim_world_->internalGraphicsLoopTasksForSimulation();
454 std::this_thread::sleep_for(std::chrono::microseconds(
455 static_cast<size_t>(obj->
mvsim_world_->get_simul_timestep() * 1000000)));
463 catch (
const std::exception& e)
465 std::cerr <<
"[MVSimNode::thread_update_GUI] Exception:\n" << e.what();
484 mrpt2ros::toROS(grid->getOccGrid(), ros_map);
486 #if PACKAGE_ROS_VERSION == 1
487 static size_t loop_count = 0;
488 ros_map.header.seq = loop_count++;
490 ros_map.header.frame_id =
"map";
492 ros_map.header.stamp =
myNow();
512 for (
auto it = vehs.begin(); it != vehs.end(); ++it, ++idx)
522 #if PACKAGE_ROS_VERSION == 1
532 auto qosLatched = rclcpp::QoS(rclcpp::KeepLast(1)).transient_local().reliable();
546 #if PACKAGE_ROS_VERSION == 1
555 #if PACKAGE_ROS_VERSION == 1
558 return clock_->now().nanoseconds() * 1e-9;
567 #if PACKAGE_ROS_VERSION == 1
577 #if PACKAGE_ROS_VERSION == 1
579 pubsubs.
pub_odom = mvsim_node::make_shared<ros::Publisher>(
587 pubsubs.
pub_collision = mvsim_node::make_shared<ros::Publisher>(
591 pubsubs.
pub_tf = mvsim_node::make_shared<ros::Publisher>(
593 pubsubs.
pub_tf_static = mvsim_node::make_shared<ros::Publisher>(
609 const auto qos = tf2_ros::DynamicBroadcasterQoS();
610 const auto qos_static = tf2_ros::StaticBroadcasterQoS();
619 #if PACKAGE_ROS_VERSION == 1
623 rclcpp::QoS qosLatched5(rclcpp::KeepLast(5));
624 qosLatched5.durability(
625 rmw_qos_durability_policy_t::RMW_QOS_POLICY_DURABILITY_TRANSIENT_LOCAL);
637 auto& chassis_shape_msg = msg_shapes.markers[0];
639 chassis_shape_msg.pose = mrpt2ros::toROS_Pose(mrpt::poses::CPose3D::Identity());
641 chassis_shape_msg.action = Msg_Marker::MODIFY;
642 chassis_shape_msg.type = Msg_Marker::LINE_STRIP;
644 chassis_shape_msg.header.frame_id =
"base_link";
645 chassis_shape_msg.ns =
"mvsim.chassis_shape";
647 chassis_shape_msg.scale.x = 0.05;
648 chassis_shape_msg.scale.y = 0.05;
649 chassis_shape_msg.scale.z = 0.02;
650 chassis_shape_msg.points.resize(poly.size() + 1);
651 for (
size_t i = 0; i <= poly.size(); i++)
653 size_t k = i % poly.size();
654 chassis_shape_msg.points[i].x = poly[k].x;
655 chassis_shape_msg.points[i].y = poly[k].y;
656 chassis_shape_msg.points[i].z = 0;
658 chassis_shape_msg.color.a = 0.9;
659 chassis_shape_msg.color.r = 0.9;
660 chassis_shape_msg.color.g = 0.9;
661 chassis_shape_msg.color.b = 0.9;
662 chassis_shape_msg.frame_locked =
true;
667 auto& wheel_shape_msg = msg_shapes.markers[1 + i];
670 const double lx = w.
diameter * 0.5, ly = w.width * 0.5;
673 wheel_shape_msg = msg_shapes.markers[0];
676 mrpt::format(
"mvsim.chassis_shape.wheel%u",
static_cast<unsigned int>(i));
677 wheel_shape_msg.points.resize(5);
678 wheel_shape_msg.points[0].x = lx;
679 wheel_shape_msg.points[0].y = ly;
680 wheel_shape_msg.points[0].z = 0;
681 wheel_shape_msg.points[1].x = lx;
682 wheel_shape_msg.points[1].y = -ly;
683 wheel_shape_msg.points[1].z = 0;
684 wheel_shape_msg.points[2].x = -lx;
685 wheel_shape_msg.points[2].y = -ly;
686 wheel_shape_msg.points[2].z = 0;
687 wheel_shape_msg.points[3].x = -lx;
688 wheel_shape_msg.points[3].y = ly;
689 wheel_shape_msg.points[3].z = 0;
690 wheel_shape_msg.points[4] = wheel_shape_msg.points[0];
692 wheel_shape_msg.color.r = w.color.R / 255.0f;
693 wheel_shape_msg.color.g = w.color.G / 255.0f;
694 wheel_shape_msg.color.b = w.color.B / 255.0f;
695 wheel_shape_msg.color.a = 1.0f;
698 wheel_shape_msg.pose = mrpt2ros::toROS_Pose(w.pose());
707 #if PACKAGE_ROS_VERSION == 1
711 rclcpp::QoS qosLatched1(rclcpp::KeepLast(1));
712 qosLatched1.durability(
713 rmw_qos_durability_policy_t::RMW_QOS_POLICY_DURABILITY_TRANSIENT_LOCAL);
722 poly_msg.points.resize(poly.size());
723 for (
size_t i = 0; i < poly.size(); i++)
725 poly_msg.points[i].x = poly[i].x;
726 poly_msg.points[i].y = poly[i].y;
727 poly_msg.points[i].z = 0;
734 #if PACKAGE_ROS_VERSION == 1
743 rclcpp::QoS qosLatched1(rclcpp::KeepLast(1));
744 qosLatched1.durability(
745 rmw_qos_durability_policy_t::RMW_QOS_POLICY_DURABILITY_TRANSIENT_LOCAL);
758 tx.header.frame_id =
"base_link";
759 tx.child_frame_id =
"base_footprint";
760 tx.header.stamp =
myNow();
764 tfMsg.transforms.push_back(tx);
775 const bool ctrlAcceptTwist =
776 controller->setTwistCommand({
cmd->linear.x,
cmd->linear.y,
cmd->angular.z});
778 if (!ctrlAcceptTwist)
781 1.0,
"*Warning* Vehicle's controller ['%s'] refuses Twist commands!",
798 #if PACKAGE_ROS_VERSION == 1
816 for (
auto it = vehs.begin(); it != vehs.end(); ++it, ++i)
818 const auto& veh = it->second;
823 const mrpt::math::TPose3D& gh_veh_pose = veh->getPose();
825 const auto& gh_veh_vel = veh->getTwist();
829 gtOdoMsg.pose.pose = mrpt2ros::toROS_Pose(gh_veh_pose);
831 gtOdoMsg.twist.twist.linear.x = gh_veh_vel.vx;
832 gtOdoMsg.twist.twist.linear.y = gh_veh_vel.vy;
833 gtOdoMsg.twist.twist.linear.z = 0;
834 gtOdoMsg.twist.twist.angular.z = gh_veh_vel.omega;
836 gtOdoMsg.header.stamp =
myNow();
837 gtOdoMsg.header.frame_id =
"odom";
838 gtOdoMsg.child_frame_id =
"base_link";
840 pubs.pub_ground_truth->publish(gtOdoMsg);
849 particleCloud.header.stamp =
myNow();
850 particleCloud.header.frame_id =
"map";
851 particleCloud.poses.resize(1);
852 particleCloud.poses[0] = gtOdoMsg.pose.pose;
853 pubs.pub_particlecloud->publish(particleCloud);
858 currentPos.header = gtOdoMsg.header;
859 currentPos.pose.pose = gtOdoMsg.pose.pose;
860 pubs.pub_amcl_pose->publish(currentPos);
866 tx.header.frame_id =
"map";
867 tx.child_frame_id =
"odom";
868 tx.header.stamp =
myNow();
872 tfMsg.transforms.push_back(tx);
873 pubs.pub_tf->publish(tfMsg);
883 auto& msg_shapes = pubs.chassis_shape_msg;
884 ASSERT_EQUAL_(msg_shapes.markers.size(), (1 + veh->getNumWheels()));
888 for (
size_t j = 0; j < veh->getNumWheels(); j++)
891 auto& wheel_shape_msg = msg_shapes.markers[1 + j];
892 const auto& w = veh->getWheelInfo(j);
895 wheel_shape_msg.pose = mrpt2ros::toROS_Pose(w.pose());
900 pubs.pub_chassis_markers->publish(msg_shapes);
906 const mrpt::math::TPose3D odo_pose = gh_veh_pose;
912 tx.header.frame_id =
"odom";
913 tx.child_frame_id =
"base_link";
914 tx.header.stamp =
myNow();
915 tx.transform =
tf2::toMsg(mrpt2ros::toROS_tfTransform(odo_pose));
918 tfMsg.transforms.push_back(tx);
919 pubs.pub_tf->publish(tfMsg);
925 odoMsg.pose.pose = mrpt2ros::toROS_Pose(odo_pose);
928 odoMsg.header.stamp =
myNow();
929 odoMsg.header.frame_id =
"odom";
930 odoMsg.child_frame_id =
"base_link";
933 pubs.pub_odom->publish(odoMsg);
939 const bool col = veh->hadCollision();
940 veh->resetCollisionFlag();
946 pubs.pub_collision->publish(colMsg);
958 mrpt::system::CTimeLoggerEntry tle(
profiler_,
"onNewObservation");
964 ASSERT_(!obs->sensorLabel.empty());
968 const auto& veh = *vehPtr;
973 if (
const auto* o2DLidar =
dynamic_cast<const mrpt::obs::CObservation2DRangeScan*
>(obs.get());
978 else if (
const auto* oImage =
dynamic_cast<const mrpt::obs::CObservationImage*
>(obs.get());
983 else if (
const auto* oRGBD =
dynamic_cast<const mrpt::obs::CObservation3DRangeScan*
>(obs.get());
988 else if (
const auto* oPC =
dynamic_cast<const mrpt::obs::CObservationPointCloud*
>(obs.get());
993 else if (
const auto* oIMU =
dynamic_cast<const mrpt::obs::CObservationIMU*
>(obs.get()); oIMU)
997 else if (
const auto* oGPS =
dynamic_cast<const mrpt::obs::CObservationGPS*
>(obs.get()); oGPS)
1005 1.0,
"Do not know how to publish this observation to ROS: '"
1006 << obs->sensorLabel <<
"', class: " << obs->GetRuntimeClass()->className);
1021 return veh.
getName() + std::string(
"/") + sVarName;
1032 const bool is_1st_pub = pubs.pub_sensors.find(obs.sensorLabel) == pubs.pub_sensors.end();
1033 auto& pub = pubs.pub_sensors[obs.sensorLabel];
1037 #if PACKAGE_ROS_VERSION == 1
1038 pub = mvsim_node::make_shared<ros::Publisher>(
1041 pub = mvsim_node::make_shared<PublisherWrapper<Msg_LaserScan>>(
1048 mrpt::poses::CPose3D sensorPose = obs.sensorPose;
1049 auto transform = mrpt2ros::toROS_tfTransform(sensorPose);
1053 tfStmp.header.frame_id =
"base_link";
1054 tfStmp.child_frame_id = obs.sensorLabel;
1055 tfStmp.header.stamp =
myNow();
1058 tfMsg.transforms.push_back(tfStmp);
1059 pubs.pub_tf->publish(tfMsg);
1067 msg_laser.header.stamp =
myNow();
1068 msg_laser.header.frame_id = obs.sensorLabel;
1069 mrpt2ros::toROS(obs, msg_laser, msg_pose_laser);
1070 pub->publish(mvsim_node::make_shared<Msg_LaserScan>(msg_laser));
1080 const bool is_1st_pub = pubs.pub_sensors.find(obs.sensorLabel) == pubs.pub_sensors.end();
1081 auto& pub = pubs.pub_sensors[obs.sensorLabel];
1085 #if PACKAGE_ROS_VERSION == 1
1086 pub = mvsim_node::make_shared<ros::Publisher>(
1089 pub = mvsim_node::make_shared<PublisherWrapper<Msg_Imu>>(
1096 mrpt::poses::CPose3D sensorPose = obs.sensorPose;
1097 auto transform = mrpt2ros::toROS_tfTransform(sensorPose);
1101 tfStmp.header.frame_id =
"base_link";
1102 tfStmp.child_frame_id = obs.sensorLabel;
1103 tfStmp.header.stamp =
myNow();
1106 tfMsg.transforms.push_back(tfStmp);
1107 pubs.pub_tf->publish(tfMsg);
1115 msg_header.stamp =
myNow();
1116 msg_header.frame_id = obs.sensorLabel;
1117 mrpt2ros::toROS(obs, msg_header, msg_imu);
1118 pub->publish(mvsim_node::make_shared<Msg_Imu>(msg_imu));
1124 if (!obs.has_GGA_datum())
1134 const bool is_1st_pub = pubs.pub_sensors.find(obs.sensorLabel) == pubs.pub_sensors.end();
1135 auto& pub = pubs.pub_sensors[obs.sensorLabel];
1139 #if PACKAGE_ROS_VERSION == 1
1140 pub = mvsim_node::make_shared<ros::Publisher>(
1143 pub = mvsim_node::make_shared<PublisherWrapper<Msg_GPS>>(
1150 mrpt::poses::CPose3D sensorPose = obs.sensorPose;
1151 auto transform = mrpt2ros::toROS_tfTransform(sensorPose);
1155 tfStmp.header.frame_id =
"base_link";
1156 tfStmp.child_frame_id = obs.sensorLabel;
1157 tfStmp.header.stamp =
myNow();
1160 tfMsg.transforms.push_back(tfStmp);
1161 pubs.pub_tf->publish(tfMsg);
1166 auto msg = mvsim_node::make_shared<Msg_GPS>();
1167 msg->header.stamp =
myNow();
1168 msg->header.frame_id = obs.sensorLabel;
1170 const auto& o = obs.getMsgByClass<mrpt::obs::gnss::Message_NMEA_GGA>();
1172 msg->latitude = o.fields.latitude_degrees;
1173 msg->longitude = o.fields.longitude_degrees;
1174 msg->altitude = o.fields.altitude_meters;
1176 if (
auto& c = obs.covariance_enu; c.has_value())
1178 #if PACKAGE_ROS_VERSION == 1
1179 msg->position_covariance_type = sensor_msgs::NavSatFix::COVARIANCE_TYPE_DIAGONAL_KNOWN;
1181 msg->position_covariance_type =
1182 sensor_msgs::msg::NavSatFix::COVARIANCE_TYPE_DIAGONAL_KNOWN;
1185 msg->position_covariance.fill(0.0);
1186 msg->position_covariance[0] = (*c)(0, 0);
1187 msg->position_covariance[4] = (*c)(1, 1);
1188 msg->position_covariance[8] = (*c)(2, 2);
1203 ci.height = c.nrows;
1206 #if PACKAGE_ROS_VERSION == 1
1216 switch (c.distortion)
1218 case mrpt::img::DistortionModel::kannala_brandt:
1219 ci.distortion_model =
"kannala_brandt";
1227 case mrpt::img::DistortionModel::plumb_bob:
1228 ci.distortion_model =
"plumb_bob";
1230 for (
size_t i = 0; i < dist.size(); i++) dist[i] = c.dist[i];
1233 case mrpt::img::DistortionModel::none:
1234 ci.distortion_model =
"plumb_bob";
1236 for (
size_t i = 0; i < dist.size(); i++) dist[i] = 0;
1240 THROW_EXCEPTION(
"Unexpected distortion model!");
1261 using namespace std::string_literals;
1266 const std::string img_topic = obs.sensorLabel +
"/image_raw"s;
1267 const std::string camInfo_topic = obs.sensorLabel +
"/camera_info"s;
1270 const bool is_1st_pub = pubs.pub_sensors.find(img_topic) == pubs.pub_sensors.end();
1271 auto& pubImg = pubs.pub_sensors[img_topic];
1272 auto& pubCamInfo = pubs.pub_sensors[camInfo_topic];
1276 #if PACKAGE_ROS_VERSION == 1
1277 pubImg = mvsim_node::make_shared<ros::Publisher>(
1279 pubCamInfo = mvsim_node::make_shared<ros::Publisher>(
1282 pubImg = mvsim_node::make_shared<PublisherWrapper<Msg_Image>>(
1284 pubCamInfo = mvsim_node::make_shared<PublisherWrapper<Msg_CameraInfo>>(
1291 mrpt::poses::CPose3D sensorPose;
1292 obs.getSensorPose(sensorPose);
1293 auto transform = mrpt2ros::toROS_tfTransform(sensorPose);
1297 tfStmp.header.frame_id =
"base_link";
1298 tfStmp.child_frame_id = obs.sensorLabel;
1299 tfStmp.header.stamp =
myNow();
1302 tfMsg.transforms.push_back(tfStmp);
1303 pubs.pub_tf->publish(tfMsg);
1307 msg_header.stamp =
myNow();
1308 msg_header.frame_id = obs.sensorLabel;
1313 msg_img = mrpt2ros::toROS(obs.image, msg_header);
1314 pubImg->publish(mvsim_node::make_shared<Msg_Image>(msg_img));
1319 camInfo.header = msg_header;
1320 pubCamInfo->publish(mvsim_node::make_shared<Msg_CameraInfo>(camInfo));
1327 using namespace std::string_literals;
1332 const auto lbPoints = obs.sensorLabel +
"_points"s;
1333 const auto lbImage = obs.sensorLabel +
"_image"s;
1336 const bool is_1st_pub = pubs.pub_sensors.find(lbPoints) == pubs.pub_sensors.end();
1338 auto& pubPts = pubs.pub_sensors[lbPoints];
1339 auto& pubImg = pubs.pub_sensors[lbImage];
1343 #if PACKAGE_ROS_VERSION == 1
1344 pubImg = mvsim_node::make_shared<ros::Publisher>(
1346 pubPts = mvsim_node::make_shared<ros::Publisher>(
1349 pubImg = mvsim_node::make_shared<PublisherWrapper<Msg_Image>>(
1351 pubPts = mvsim_node::make_shared<PublisherWrapper<Msg_PointCloud2>>(
1357 const auto now =
myNow();
1361 if (obs.hasIntensityImage)
1364 mrpt::poses::CPose3D sensorPose = obs.sensorPose + obs.relativePoseIntensityWRTDepth;
1365 auto transform = mrpt2ros::toROS_tfTransform(sensorPose);
1369 tfStmp.header.frame_id =
"base_link";
1370 tfStmp.child_frame_id = lbImage;
1371 tfStmp.header.stamp = now;
1374 tfMsg.transforms.push_back(tfStmp);
1375 pubs.pub_tf->publish(tfMsg);
1382 msg_header.stamp = now;
1383 msg_header.frame_id = lbImage;
1384 msg_img = mrpt2ros::toROS(obs.intensityImage, msg_header);
1385 pubImg->publish(mvsim_node::make_shared<Msg_Image>(msg_img));
1391 if (obs.hasRangeImage)
1394 mrpt::poses::CPose3D sensorPose = obs.sensorPose;
1395 auto transform = mrpt2ros::toROS_tfTransform(sensorPose);
1399 tfStmp.header.frame_id =
"base_link";
1400 tfStmp.child_frame_id = lbPoints;
1401 tfStmp.header.stamp = now;
1404 tfMsg.transforms.push_back(tfStmp);
1405 pubs.pub_tf->publish(tfMsg);
1412 msg_header.stamp = now;
1413 msg_header.frame_id = lbPoints;
1415 mrpt::obs::T3DPointsProjectionParams pp;
1416 pp.takeIntoAccountSensorPoseOnRobot =
false;
1418 mrpt::maps::CSimplePointsMap pts;
1419 const_cast<mrpt::obs::CObservation3DRangeScan&
>(obs).unprojectInto(pts, pp);
1420 mrpt2ros::toROS(pts, msg_header, msg_pts);
1421 pubPts->publish(mvsim_node::make_shared<Msg_PointCloud2>(msg_pts));
1429 using namespace std::string_literals;
1434 const auto lbPoints = obs.sensorLabel +
"_points"s;
1437 const bool is_1st_pub = pubs.pub_sensors.find(lbPoints) == pubs.pub_sensors.end();
1439 auto& pubPts = pubs.pub_sensors[lbPoints];
1443 #if PACKAGE_ROS_VERSION == 1
1444 pubPts = mvsim_node::make_shared<ros::Publisher>(
1447 pubPts = mvsim_node::make_shared<PublisherWrapper<Msg_PointCloud2>>(
1453 const auto now =
myNow();
1459 mrpt::poses::CPose3D sensorPose = obs.sensorPose;
1460 auto transform = mrpt2ros::toROS_tfTransform(sensorPose);
1464 tfStmp.header.frame_id =
"base_link";
1465 tfStmp.child_frame_id = lbPoints;
1466 tfStmp.header.stamp = now;
1469 tfMsg.transforms.push_back(tfStmp);
1470 pubs.pub_tf->publish(tfMsg);
1477 msg_header.stamp = now;
1478 msg_header.frame_id = lbPoints;
1480 #if defined(HAVE_POINTS_XYZIRT)
1481 if (
auto* xyzirt =
dynamic_cast<const mrpt::maps::CPointsMapXYZIRT*
>(obs.pointcloud.get());
1484 mrpt2ros::toROS(*xyzirt, msg_header, msg_pts);
1488 if (
auto* xyzi =
dynamic_cast<const mrpt::maps::CPointsMapXYZI*
>(obs.pointcloud.get());
1491 mrpt2ros::toROS(*xyzi, msg_header, msg_pts);
1493 else if (
auto* sPts =
1494 dynamic_cast<const mrpt::maps::CSimplePointsMap*
>(obs.pointcloud.get());
1497 mrpt2ros::toROS(*sPts, msg_header, msg_pts);
1501 THROW_EXCEPTION(
"Do not know how to handle this variant of CPointsMap");
1504 pubPts->publish(mvsim_node::make_shared<Msg_PointCloud2>(msg_pts));