12 #include <mrpt/ros1bridge/time.h> 13 #include <mrpt/ros1bridge/laser_scan.h> 14 #include <mrpt/ros1bridge/pose.h> 15 #include <mrpt/ros1bridge/map.h> 33 template <
class GRAPH_T>
36 template <
class GRAPH_T>
40 template <
class GRAPH_T>
42 mrpt::system::COutputLogger*
logger,
44 :
parent_t(logger, options_checker, false), m_nh(nh_in)
72 template <
class GRAPH_T>
77 template <
class GRAPH_T>
82 ASSERT_(!this->m_ini_fname.empty());
83 parent_t::readConfigFname(this->m_ini_fname);
86 template <
class GRAPH_T>
91 std::string ns =
"misc/";
94 bool m_disable_MRPT_visuals;
96 ns +
"disable_MRPT_visuals", m_disable_MRPT_visuals,
false);
97 this->m_enable_visuals = !m_disable_MRPT_visuals;
101 m_nh->
param<
int>(ns +
"verbosity", lvl,
static_cast<int>(LVL_INFO));
107 std::string ns =
"deciders_optimizers/";
114 std::string ns =
"files/";
117 std::string config_param_path = ns +
"config";
118 bool found_config =
m_nh->
getParam(ns +
"config", this->m_ini_fname);
120 found_config, mrpt::format(
121 "Configuration file was not set. Set %s and try " 122 "again.\nExiting...",
123 config_param_path.c_str()));
132 std::string ns =
"frame_IDs/";
143 this->m_options_checker->createDeciderOptimizerMappings();
144 this->m_options_checker->populateDeciderOptimizerProperties();
147 this->m_logger->logFmt(
148 LVL_DEBUG,
"Successfully read parameters from ROS Parameter Server");
151 if (this->m_enable_visuals)
153 this->initVisualization();
157 template <
class GRAPH_T>
162 template <
class GRAPH_T>
165 this->m_logger->logFmt(
166 LVL_WARN,
"Initializing CGraphSlamEngine_ROS instance...");
168 m_nh, this->m_ini_fname,
169 "", this->m_gt_fname, this->m_win_manager,
170 this->m_options_checker->node_regs_map[
m_node_reg](),
171 this->m_options_checker->edge_regs_map[
m_edge_reg](),
172 this->m_options_checker->optimizers_map[
m_optimizer]());
173 this->m_logger->logFmt(
174 LVL_WARN,
"Successfully initialized CGraphSlamEngine_ROS instance.");
177 template <
class GRAPH_T>
180 this->m_options_checker->node_regs_map[
m_node_reg]();
181 this->m_options_checker->edge_regs_map[
m_edge_reg]();
182 this->m_options_checker->optimizers_map[
m_optimizer]();
184 this->m_logger->logFmt(
185 LVL_WARN,
"Initializing CGraphSlamEngine_MR instance...");
187 m_nh, this->m_ini_fname,
188 "", this->m_gt_fname, this->m_win_manager,
189 this->m_options_checker->node_regs_map[
m_node_reg](),
190 this->m_options_checker->edge_regs_map[
m_edge_reg](),
191 this->m_options_checker->optimizers_map[
m_optimizer]());
192 this->m_logger->logFmt(
193 LVL_WARN,
"Successfully initialized CGraphSlamEngine_MR instance.");
196 template <
class GRAPH_T>
205 ss <<
"ROS Parameters: " << endl;
209 ss <<
"Deciders / Optimizers = " << endl;
211 ss <<
"Node Registration Decider = " <<
m_node_reg << endl;
212 ss <<
"Edge Registration Decider = " <<
m_edge_reg << endl;
213 ss <<
"GraphSLAM Optimizer = " <<
m_optimizer << endl;
216 ss <<
"Filenames: " << endl;
218 ss <<
"Configuration .ini file = " << this->m_ini_fname << endl;
219 ss <<
"Ground truth filename = " 220 << (!this->m_gt_fname.empty() ? this->m_gt_fname :
"NONE") << endl;
223 ss <<
"Miscellaneous: " << endl;
225 ss <<
"Enable MRPT visuals? = " 226 << (this->m_enable_visuals ?
"TRUE" :
"FALSE") << endl;
227 ss <<
"Logging verbosity Level = " 235 template <
class GRAPH_T>
241 std::string ros_params(
"");
243 std::string mrpt_params(
"");
244 parent_t::getParamsAsString(&mrpt_params);
246 *str_out += ros_params;
248 *str_out += mrpt_params;
253 template <
class GRAPH_T>
261 template <
class GRAPH_T>
265 parent_t::printParams();
269 template <
class GRAPH_T>
272 this->m_logger->logFmt(LVL_DEBUG,
"Verifying user input...");
275 bool node_success, edge_success, optimizer_success;
278 node_success = this->m_options_checker->checkRegistrationDeciderExists(
280 edge_success = this->m_options_checker->checkRegistrationDeciderExists(
283 this->m_options_checker->checkOptimizerExists(
m_optimizer);
287 this->m_logger->logFmt(
288 LVL_ERROR,
"\nNode Registration Decider \"%s\" is not available",
290 this->m_options_checker->dumpRegistrarsToConsole(
"node");
295 this->m_logger->logFmt(
296 LVL_ERROR,
"\nEdge Registration Decider \"%s\" is not available.",
298 this->m_options_checker->dumpRegistrarsToConsole(
"edge");
301 if (!optimizer_success)
303 this->m_logger->logFmt(
304 LVL_ERROR,
"\ngraphSLAM Optimizser \"%s\" is not available.",
306 this->m_options_checker->dumpOptimizersToConsole();
313 bool ini_exists = system::fileExists(this->m_ini_fname);
316 "\n.ini configuration file \"%s\"doesn't exist. " 317 "Please specify a valid pathname.\nExiting...\n",
318 this->m_ini_fname.c_str()));
320 if (!this->m_gt_fname.empty())
322 bool gt_exists = system::fileExists(this->m_gt_fname);
325 "\nGround truth file \"%s\"doesn't exist." 326 "Either unset the corresponding ROS parameter or " 327 "specify a valid pathname.\n" 329 this->m_gt_fname.c_str()));
334 template <
class GRAPH_T>
337 this->m_logger->logFmt(
339 "Setting up ROS-related subscribers, publishers, services...");
351 template <
class GRAPH_T>
354 this->m_logger->logFmt(LVL_INFO,
"Setting up the subscribers...");
357 std::string ns =
"input/";
378 template <
class GRAPH_T>
381 this->m_logger->logFmt(LVL_INFO,
"Setting up the publishers...");
384 std::string ns =
"feedback/";
422 template <
class GRAPH_T>
425 this->m_logger->logFmt(LVL_INFO,
"Setting up the services...");
431 template <
class GRAPH_T>
442 pose_t mrpt_pose = this->m_engine->getCurrentRobotPosEstimation();
448 geometry_msgs::TransformStamped anchor_base_link_transform;
454 anchor_base_link_transform.transform.translation.x = mrpt_pose.x();
455 anchor_base_link_transform.transform.translation.y = mrpt_pose.y();
456 anchor_base_link_transform.transform.translation.z = 0;
459 anchor_base_link_transform.transform.rotation =
477 geometry_msgs::PoseStamped geom_pose;
478 geom_pose.header.stamp = timestamp;
480 geom_pose.header.frame_id =
484 geom_pose.pose = mrpt::ros1bridge::toROS_Pose(mrpt_pose);
491 this->m_logger->logFmt(
492 LVL_DEBUG,
"Publishing the current robot trajectory");
493 typename GRAPH_T::global_poses_t graph_poses;
494 graph_poses = this->m_engine->getRobotEstimatedTrajectory();
499 path.header.stamp = timestamp;
507 geometry_msgs::PoseArray geom_poses;
508 geom_poses.header.stamp = timestamp;
511 for (
auto n_cit = graph_poses.begin(); n_cit != graph_poses.end();
514 geometry_msgs::PoseStamped geom_pose_stamped;
515 geometry_msgs::Pose geom_pose;
518 const pose_t& mrpt_pose = n_cit->second;
519 geom_pose = mrpt::ros1bridge::toROS_Pose(mrpt_pose);
520 geom_poses.poses.push_back(geom_pose);
521 geom_pose_stamped.pose = geom_pose;
524 geom_pose_stamped.header.stamp = timestamp;
525 geom_pose_stamped.header.seq =
m_pub_seq;
528 path.poses.push_back(geom_pose_stamped);
547 mrpt::system::TTimeStamp mrpt_time;
548 auto mrpt_gridmap = mrpt::maps::COccupancyGridMap2D::Create();
549 this->m_engine->getMap(mrpt_gridmap, &mrpt_time);
552 h.stamp = mrpt::ros1bridge::toROS(mrpt_time);
557 nav_msgs::OccupancyGrid nav_gridmap;
558 mrpt::ros1bridge::toROS(*mrpt_gridmap, nav_gridmap, h);
564 mrpt_msgs::GraphSlamStats stats;
567 map<string, int> node_stats;
568 map<string, int> edge_stats;
569 vector<double> def_energy_vec;
570 mrpt::system::TTimeStamp mrpt_time;
572 this->m_engine->getGraphSlamStats(&node_stats, &edge_stats, &mrpt_time);
575 stats.nodes_total = node_stats[
"nodes_total"];
576 stats.edges_total = edge_stats[
"edges_total"];
577 if (edge_stats.find(
"ICP2D") != edge_stats.end())
579 stats.edges_icp_2d = edge_stats[
"ICP2D"];
581 if (edge_stats.find(
"ICP3D") != edge_stats.end())
583 stats.edges_icp_3d = edge_stats[
"ICP3D"];
585 if (edge_stats.find(
"Odometry") != edge_stats.end())
587 stats.edges_odom = edge_stats[
"Odometry"];
589 stats.loop_closures = edge_stats[
"loop_closures"];
592 this->m_engine->getDeformationEnergyVector(
593 &stats.slam_evaluation_metric);
595 stats.header.stamp = mrpt::ros1bridge::toROS(mrpt_time);
604 if (this->m_enable_visuals)
606 ret_val = this->queryObserverForEvents();
613 template <
class GRAPH_T>
615 const sensor_msgs::LaserScan::ConstPtr& ros_laser_scan)
620 this->m_logger->logFmt(
622 "sniffLaserScan: Received a LaserScan msg. Converting it to MRPT " 627 mrpt::poses::CPose3D rel_pose;
631 CObservation::Ptr tmp =
636 template <
class GRAPH_T>
638 const nav_msgs::Odometry::ConstPtr& ros_odom)
644 this->m_logger->logFmt(
646 "sniffOdom: Received an odometry msg. Converting it to MRPT format...");
663 ros_odom->pose.pose.position.x;
665 ros_odom->pose.pose.position.y;
667 ros_odom->pose.pose.position.z;
671 ros_odom->pose.pose.orientation;
676 m_mrpt_odom->timestamp = mrpt::ros1bridge::fromROS(ros_odom->header.stamp);
678 mrpt::poses::CPose2D(mrpt::ros1bridge::fromROS(ros_odom->pose.pose));
692 geometry_msgs::PoseStamped pose_stamped;
693 pose_stamped.header = ros_odom->header;
696 pose_stamped.pose = mrpt::ros1bridge::toROS_Pose(
m_mrpt_odom->odometry);
702 ss <<
"Odometry - MRPT format:\t" <<
m_mrpt_odom->odometry << endl;
703 this->m_logger->logFmt(LVL_DEBUG,
"%s", ss.str().c_str());
706 CObservation::Ptr tmp =
707 mrpt::ptr_cast<mrpt::obs::CObservation>::from(
m_mrpt_odom);
711 template <
class GRAPH_T>
714 THROW_EXCEPTION(
"Method is not implemented yet.");
716 template <
class GRAPH_T>
719 THROW_EXCEPTION(
"Method is not implemented yet.");
721 template <
class GRAPH_T>
723 mrpt::obs::CObservation::Ptr& observ)
731 template <
class GRAPH_T>
733 mrpt::obs::CObservation::Ptr& observ)
738 if (!this->m_engine->isPaused())
745 template <
class GRAPH_T>
void readROSParameters()
read configuration parameters from the ROS parameter server.
void readParams()
Read the problem configuration parameters.
void verifyUserInput()
Verify that the parameters read are valid and can be used with the CGraphSlamEngine_ROS instance...
void setRPY(const tf2Scalar &roll, const tf2Scalar &pitch, const tf2Scalar &yaw)
tf2_ros::TransformBroadcaster m_broadcaster
pose_t m_input_odometry_offset
static auto createQuaternionMsgFromYaw(double yaw)
bool usePublishersBroadcasters()
Provide feedback about the SLAM operation using ROS publilshers, update the registered frames using t...
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
void initEngine_ROS()
Initialize the CGraphslamEngine_* object.
std::string getParamsAsString()
bool m_first_time_in_sniff_odom
Initial offset of the received odometry.
ros::Subscriber m_laser_scan_sub
static const std::string sep_subheader
std::string m_curr_robot_pos_topic
size_t m_measurement_cnt
Total counter of the processed measurements.
mrpt::obs::CObservation2DRangeScan::Ptr m_mrpt_laser_scan
GRAPH_T::constraint_t::type_value pose_t
type of underlying poses (2D/3D).
ros::Subscriber m_odom_sub
bool m_received_laser_scan
VerbosityLevel m_min_logging_level
Minimum logging level for the current class instance.
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const
void publish(const boost::shared_ptr< M > &message) const
ros::Publisher m_robot_tr_poses_pub
static const std::string sep_header
std::string m_base_link_frame_id
bool getParam(const std::string &key, std::string &s) const
geometry_msgs::TransformStamped m_anchor_odom_transform
ros::NodeHandle * m_nh
Pointer to the Ros NodeHanle instance.
void sniffOdom(const nav_msgs::Odometry::ConstPtr &ros_odom)
Callback method for handling incoming odometry measurements in a ROS topic.
std::string m_odom_frame_id
CGraphSlamHandler< GRAPH_T > parent_t
Handy parent type.
void _process(mrpt::obs::CObservation::Ptr &observ)
Low level wrapper for executing the CGraphSlamEngine_ROS::execGraphSlamStep method.
void sniffLaserScan(const sensor_msgs::LaserScan::ConstPtr &ros_laser_scan)
Callback method for handling incoming LaserScans objects in a ROS topic.
ros::Publisher m_odom_trajectory_pub
void setupComm()
Wrapper method around the protected setup* class methods.
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
void getROSParameters(std::string *str_out)
Fill in the given string with the parameters that have been read from the ROS parameter server...
size_t m_graph_nodes_last_size
std::string m_odom_trajectory_topic
ros::Publisher m_gridmap_pub
nav_msgs::Path m_odom_path
Odometry path of the robot. Handy mostly for visualization reasons.
std::string m_gridmap_topic
std::string m_anchor_frame_id
Frame that the robot starts from. In a single-robot SLAM setup this can be set to the world frame...
std::string m_laser_scan_topic
void printParams()
Print in a compact manner the overall problem configuration parameters.
int m_pub_seq
Times a messge has been published => usePublishersBroadcasters method is called.
ros::Publisher m_curr_robot_pos_pub
void resetReceivedFlags()
Reset the flags indicating whether we have received new data (odometry, laser scans etc...
ros::Publisher m_stats_pub
mrpt::obs::CObservationOdometry::Ptr m_mrpt_odom
Received laser scan - converted into MRPT CObservation* format.
void processObservation(mrpt::obs::CObservation::Ptr &observ)
Process an incoming measurement.
std::string m_robot_trajectory_topic
int m_queue_size
ROS topic publisher standard queue size.
mrpt::graphslam::CGraphSlamEngine derived class for executing multi-robot graphSLAM ...
ros::Publisher m_robot_trajectory_pub
std::string m_robot_tr_poses_topic
std::string m_stats_topic
CGraphSlamHandler_ROS(mrpt::system::COutputLogger *logger, TUserOptionsChecker< GRAPH_T > *options_checker, ros::NodeHandle *nh_in)
bool m_received_point_cloud