34 #include <geometry_msgs/PoseArray.h> 35 #include <mrpt/obs/CObservationBeaconRanges.h> 36 #include <mrpt/obs/CObservationRobotPose.h> 37 #include <mrpt/ros1bridge/laser_scan.h> 38 #include <mrpt/ros1bridge/map.h> 39 #include <mrpt/ros1bridge/pose.h> 40 #include <mrpt/ros1bridge/time.h> 41 #include <mrpt/system/COutputLogger.h> 45 #include <boost/interprocess/sync/scoped_lock.hpp> 50 #include <mrpt/maps/COccupancyGridMap2D.h> 53 using mrpt::maps::COccupancyGridMap2D;
55 int main(
int argc,
char** argv)
69 first_map_received_(false),
88 auto init_pose = mrpt::poses::CPose2D(
param()->init_x,
param()->init_y,
param()->init_phi);
89 auto cov = mrpt::math::CMatrixDouble33::Zero();
90 cov(0,0) = cov(1,1) = mrpt::square(
param()->init_std_xy);
91 cov(2,2) = mrpt::square(
param()->init_std_phi);
92 initial_pose_ = mrpt::poses::CPosePDFGaussian(init_pose, cov);
103 std::vector<std::string> sources;
104 mrpt::system::tokenize(
param()->sensor_sources,
" ,\t\n", sources);
107 "*Fatal*: At least one sensor source must be provided in " 108 "~sensor_sources (e.g. \"scan\" or \"beacon\")");
110 for (
size_t i = 0; i < sources.size(); i++)
112 if (sources[i].find(
"scan") != std::string::npos)
117 else if (sources[i].find(
"beacon") != std::string::npos)
129 if (!
param()->map_file.empty())
131 if (
metric_map_->countMapsByClass<COccupancyGridMap2D>())
133 mrpt::ros1bridge::toROS(
138 nh_.
advertise<nav_msgs::MapMetaData>(
"map_metadata", 1,
true);
143 nh_.
advertise<geometry_msgs::PoseArray>(
"particlecloud", 1,
true);
146 "mrpt_pose", 2,
true);
157 (
metric_map_->countMapsByClass<COccupancyGridMap2D>()))
170 mrpt::poses::CPose3D& des,
const std::string& target_frame,
171 const std::string& source_frame,
const ros::Time& time,
174 geometry_msgs::TransformStamped transform;
178 target_frame, source_frame, time, timeout);
183 "Failed to get transform target_frame (%s) to source_frame (%s): " 185 target_frame.c_str(), source_frame.c_str(), e.what());
190 des = mrpt::ros1bridge::fromROS(tx);
202 auto laser = CObservation2DRangeScan::Create();
212 if (
param()->update_sensor_pose)
219 mrpt::ros1bridge::fromROS(
222 auto sf = CSensoryFrame::Create();
223 CObservationOdometry::Ptr odometry;
226 CObservation::Ptr obs = CObservation::Ptr(laser);
234 const mrpt_msgs::ObservationRangeBeacon& _msg)
242 auto beacon = CObservationBeaconRanges::Create();
251 if (
param()->update_sensor_pose)
261 auto sf = CSensoryFrame::Create();
262 CObservationOdometry::Ptr odometry;
265 CObservation::Ptr obs = CObservation::Ptr(beacon);
273 const geometry_msgs::PoseWithCovarianceStamped& _msg)
290 geometry_msgs::TransformStamped map_to_obs_tf_msg;
294 global_frame_id, _msg.header.frame_id,
ros::Time(0.0),
300 "Failed to get transform target_frame (%s) to source_frame (%s): " 302 global_frame_id.c_str(), _msg.header.frame_id.c_str(), e.what());
306 tf2::fromMsg(map_to_obs_tf_msg.transform, map_to_obs_tf);
312 geometry_msgs::Pose map_to_obs_pose;
315 geometry_msgs::PoseWithCovarianceStamped obs_pose_world;
316 obs_pose_world.header.stamp = _msg.header.stamp;
317 obs_pose_world.header.frame_id = global_frame_id;
321 for (
unsigned int i = 0; i < obs_pose_world.pose.covariance.size(); ++i)
323 if (i / 6 == i % 6 && obs_pose_world.pose.covariance[i] <= 0.0)
324 obs_pose_world.pose.covariance[i] =
325 std::numeric_limits<double>().infinity();
329 auto feature = CObservationRobotPose::Create();
331 feature->sensorLabel = _msg.header.frame_id;
332 feature->timestamp = mrpt::ros1bridge::fromROS(_msg.header.stamp);
333 feature->pose = mrpt::ros1bridge::fromROS(obs_pose_world.pose);
335 auto sf = CSensoryFrame::Create();
336 CObservationOdometry::Ptr odometry;
339 CObservation::Ptr obs = CObservation::Ptr(feature);
346 CObservationOdometry::Ptr& _odometry,
const std_msgs::Header& _msg_header)
350 mrpt::poses::CPose3D poseOdom;
352 poseOdom, odom_frame_id, base_frame_id, _msg_header.stamp,
355 _odometry = CObservationOdometry::Create();
356 _odometry->sensorLabel = odom_frame_id;
357 _odometry->hasEncodersInfo =
false;
358 _odometry->hasVelocities =
false;
359 _odometry->odometry.x() = poseOdom.x();
360 _odometry->odometry.y() = poseOdom.y();
361 _odometry->odometry.phi() = poseOdom.yaw();
367 int wait_counter = 0;
370 if (
param()->use_map_topic)
374 ROS_INFO(
"Subscribed to map topic.");
378 ROS_INFO(
"waiting for map callback..");
383 if (wait_counter != wait_limit)
391 nav_msgs::GetMap srv;
394 ROS_INFO(
"waiting for map service!");
399 if (wait_counter != wait_limit)
426 mrpt::poses::CPose3D pose;
430 geometry_msgs::TransformStamped transformStmp;
436 base_frame_id, _frame_id,
ros::Time(0), timeout);
441 "Failed to get transform target_frame (%s) to source_frame (%s): " 443 base_frame_id.c_str(), _frame_id.c_str(), e.what());
449 tf2::Vector3 translation = transform.
getOrigin();
451 pose.x() = translation.x();
452 pose.y() = translation.y();
453 pose.z() = translation.z();
455 mrpt::math::CMatrixDouble33 Rdes;
456 for (
int c = 0; c < 3; c++)
458 for (
int r = 0; r < 3; r++)
460 Rdes(r, c) = Rsrc.
getRow(r)[c];
464 pose.setRotationMatrix(Rdes);
470 const geometry_msgs::PoseWithCovarianceStamped& _msg)
472 const geometry_msgs::PoseWithCovariance& pose = _msg.pose;
476 mrpt::poses::CPosePDFGaussian(mrpt::ros1bridge::fromROS(pose));
488 bool moving = std::abs(_msg.twist.twist.linear.x) > 1e-3 ||
489 std::abs(_msg.twist.twist.linear.y) > 1e-3 ||
490 std::abs(_msg.twist.twist.linear.z) > 1e-3 ||
491 std::abs(_msg.twist.twist.angular.x) > 1e-3 ||
492 std::abs(_msg.twist.twist.angular.y) > 1e-3 ||
493 std::abs(_msg.twist.twist.angular.z) > 1e-3;
494 if (
param()->update_while_stopped || moving)
509 ASSERT_(
metric_map_->countMapsByClass<COccupancyGridMap2D>());
510 mrpt::ros1bridge::fromROS(
511 _msg, *
metric_map_->mapByClass<COccupancyGridMap2D>());
515 nav_msgs::GetMap::Request& req, nav_msgs::GetMap::Response& res)
517 ROS_INFO(
"mapCallback: service requested!\n");
541 geometry_msgs::PoseArray poseArray;
545 poseArray.poses.resize(
pdf_.particlesCount());
546 for (
size_t i = 0; i <
pdf_.particlesCount(); i++)
548 const auto p = mrpt::math::TPose3D(
pdf_.getParticlePose(i));
549 poseArray.poses[i] = mrpt::ros1bridge::toROS_Pose(p);
551 mrpt::poses::CPose2D p;
566 const mrpt::poses::CPose2D robotPoseFromPF = [
this]() {
567 return pdf_.getMeanVal();
571 tf2::fromMsg(mrpt::ros1bridge::toROS_Pose(robotPoseFromPF), baseOnMap_tf);
585 param()->no_update_tolerance)
588 param()->no_inputs_tolerance)
592 "No observations received for %.2fs (tolerance %.2fs); are " 593 "robot sensors working?",
595 param()->no_inputs_tolerance);
601 "No filter updates for %.2fs (tolerance %.2fs); probably " 602 "robot stopped for a while",
604 param()->no_update_tolerance);
614 geometry_msgs::TransformStamped transform;
618 base_frame_id, odom_frame_id, time_last_update,
625 "Failed to get transform target_frame (%s) to source_frame " 628 base_frame_id.c_str(), odom_frame_id.c_str(), e.what());
631 "Ensure that your mobile base driver is broadcasting %s -> %s " 633 odom_frame_id.c_str(), base_frame_id.c_str());
649 baseOnMap_tf * odomOnBase_tf, transform_expiration, global_frame_id);
651 geometry_msgs::TransformStamped tfGeom =
tf2::toMsg(tmp_tf_stamped);
652 tfGeom.child_frame_id = odom_frame_id;
663 const auto [cov, mean] =
pdf_.getCovarianceAndMean();
665 geometry_msgs::PoseWithCovarianceStamped p;
680 p.pose.pose = mrpt::ros1bridge::toROS_Pose(mean);
683 for (
int i = 0; i < 3; i++)
685 for (
int j = 0; j < 3; j++)
689 if (i == 2 || j == 2)
691 ros_i = i == 2 ? 5 : i;
692 ros_j = j == 2 ? 5 : j;
694 p.pose.covariance[ros_i * 6 + ros_j] = cov(i, j);
705 std::map<std::string, ros::console::levels::Level> loggers;
707 if (loggers.find(
"ros.roscpp") != loggers.end())
708 pdf_.setVerbosityLevel(
709 static_cast<VerbosityLevel>(loggers[
"ros.roscpp"]));
710 if (loggers.find(
"ros.mrpt_localization") != loggers.end())
711 pdf_.setVerbosityLevel(
712 static_cast<VerbosityLevel>(loggers[
"ros.mrpt_localization"]));
ServiceClient serviceClient(const std::string &service_name, bool persistent=false, const M_string &header_values=M_string())
void callbackRobotPose(const geometry_msgs::PoseWithCovarianceStamped &)
std::string base_frame_id
ros::ServiceClient client_map_
void publishTF()
Publish map -> odom tf; as the filter provides map -> base, we multiply it by base -> odom...
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
std::string global_frame_id
ros::Subscriber sub_init_pose_
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
bool call(MReq &req, MRes &res)
ROSCONSOLE_DECL bool get_loggers(std::map< std::string, levels::Level > &loggers)
virtual bool waitForMap()
ros::Time time_last_input_
ServiceServer advertiseService(const std::string &service, bool(T::*srv_func)(MReq &, MRes &), T *obj)
void publishPose()
Publish the current pose of the robot.
ros::Publisher pub_particles_
void observation(CSensoryFrame::Ptr _sf, CObservationOdometry::Ptr _odometry)
ros::Publisher pub_metadata_
tf2_ros::TransformBroadcaster tf_broadcaster_
void compose(const Pose &a, const Pose &b, Pose &out)
virtual geometry_msgs::TransformStamped lookupTransform(const std::string &target_frame, const std::string &source_frame, const ros::Time &time, const ros::Duration timeout) const
void publish(const boost::shared_ptr< M > &message) const
void updateSensorPose(std::string frame_id)
#define ROS_WARN_THROTTLE(period,...)
std::map< std::string, mrpt::poses::CPose3D > beacon_poses_
void odometryForCallback(CObservationOdometry::Ptr &, const std_msgs::Header &)
void callbackOdometry(const nav_msgs::Odometry &)
#define ROS_ASSERT_MSG(cond,...)
mrpt::slam::CMonteCarloLocalization2D pdf_
the filter
void fromMsg(const A &, B &b)
mrpt::poses::CPosePDFGaussian initial_pose_
initial posed used in initializeFilter()
bool waitForTransform(mrpt::poses::CPose3D &des, const std::string &target_frame, const std::string &source_frame, const ros::Time &time, const ros::Duration &timeout, const ros::Duration &polling_sleep_duration=ros::Duration(0.01))
tf2_ros::Buffer tf_buffer_
std::vector< ros::Subscriber > sub_sensors_
ros::Subscriber sub_odometry_
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
PFLocalizationNode(ros::NodeHandle &n)
#define ROS_WARN_STREAM(args)
void callbackLaser(const sensor_msgs::LaserScan &)
std::string odom_frame_id
void callbackBeacon(const mrpt_msgs::ObservationRangeBeacon &)
bool mapCallback(nav_msgs::GetMap::Request &req, nav_msgs::GetMap::Response &res)
TF2SIMD_FORCE_INLINE const Vector3 & getRow(int i) const
double transform_tolerance
unsigned long long loop_count_
#define ROS_INFO_STREAM(args)
int main(int argc, char **argv)
void show3DDebug(CSensoryFrame::Ptr _observations)
nav_msgs::GetMap::Response resp_
bool fromROS(const marker_msgs::MarkerDetection &_msg, const mrpt::poses::CPose3D &sensorPoseOnRobot, mrpt::obs::CObservationBearingRange &_obj)
void update(const unsigned long &loop_count)
ros::ServiceServer service_map_
virtual ~PFLocalizationNode()
std::map< std::string, mrpt::poses::CPose3D > laser_poses_
void updateMap(const nav_msgs::OccupancyGrid &)
mrpt::system::TTimeStamp time_last_update_
time of the last update
void callbackInitialpose(const geometry_msgs::PoseWithCovarianceStamped &)
uint32_t getNumSubscribers() const
ROSCPP_DECL void spinOnce()
CMultiMetricMap::Ptr metric_map_
map
void callbackMap(const nav_msgs::OccupancyGrid &)
#define ROS_DEBUG_THROTTLE(period,...)