Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include <ros/ros.h>
00031 #include <nav_msgs/OccupancyGrid.h>
00032 #include <tf2_geometry_msgs/tf2_geometry_msgs.h>
00033 #include <tf2_ros/transform_listener.h>
00034
00035 #include <string>
00036 #include <neonavigation_common/compatibility.h>
00037
00038 class LargeMapToMapNode
00039 {
00040 private:
00041 ros::NodeHandle pnh_;
00042 ros::NodeHandle nh_;
00043 ros::Publisher pub_map_;
00044 ros::Subscriber sub_largemap_;
00045 ros::Timer timer_;
00046
00047 nav_msgs::OccupancyGrid::ConstPtr large_map_;
00048 tf2_ros::Buffer tfbuf_;
00049 tf2_ros::TransformListener tfl_;
00050
00051 std::string robot_frame_;
00052
00053 int width_;
00054
00055 public:
00056 LargeMapToMapNode()
00057 : pnh_("~")
00058 , nh_()
00059 , tfl_(tfbuf_)
00060 {
00061 neonavigation_common::compat::checkCompatMode();
00062 pnh_.param("robot_frame", robot_frame_, std::string("base_link"));
00063
00064 pub_map_ = neonavigation_common::compat::advertise<nav_msgs::OccupancyGrid>(
00065 nh_, "map_local",
00066 pnh_, "map", 1, true);
00067 sub_largemap_ = nh_.subscribe("map", 2, &LargeMapToMapNode::cbLargeMap, this);
00068
00069 pnh_.param("width", width_, 30);
00070
00071 double hz;
00072 pnh_.param("hz", hz, 1.0);
00073 timer_ = nh_.createTimer(ros::Duration(1.0 / hz), &LargeMapToMapNode::cbTimer, this);
00074 }
00075
00076 private:
00077 void cbTimer(const ros::TimerEvent& event)
00078 {
00079 publishMap();
00080 }
00081 void cbLargeMap(const nav_msgs::OccupancyGrid::ConstPtr& msg)
00082 {
00083 large_map_ = msg;
00084 }
00085 void publishMap()
00086 {
00087 if (!large_map_)
00088 return;
00089 tf2::Stamped<tf2::Transform> trans;
00090 try
00091 {
00092 tf2::fromMsg(tfbuf_.lookupTransform(large_map_->header.frame_id, robot_frame_, ros::Time(0)), trans);
00093 }
00094 catch (tf2::TransformException& e)
00095 {
00096 return;
00097 }
00098
00099 nav_msgs::OccupancyGrid map;
00100 map.header.frame_id = large_map_->header.frame_id;
00101 map.header.stamp = ros::Time::now();
00102 map.info = large_map_->info;
00103 map.info.width = width_;
00104 map.info.height = width_;
00105
00106 const auto pos = trans.getOrigin();
00107 const float x = static_cast<int>(pos.x() / map.info.resolution) * map.info.resolution;
00108 const float y = static_cast<int>(pos.y() / map.info.resolution) * map.info.resolution;
00109 map.info.origin.position.x = x - map.info.width * map.info.resolution * 0.5;
00110 map.info.origin.position.y = y - map.info.height * map.info.resolution * 0.5;
00111 map.info.origin.position.z = 0.0;
00112 map.info.origin.orientation.w = 1.0;
00113 map.data.resize(width_ * width_);
00114
00115 const int gx =
00116 lroundf((map.info.origin.position.x - large_map_->info.origin.position.x) / map.info.resolution);
00117 const int gy =
00118 lroundf((map.info.origin.position.y - large_map_->info.origin.position.y) / map.info.resolution);
00119
00120 for (int y = gy; y < gy + width_; ++y)
00121 {
00122 for (int x = gx; x < gx + width_; ++x)
00123 {
00124 const size_t addr = (y - gy) * width_ + (x - gx);
00125 const size_t addr_large = y * large_map_->info.width + x;
00126 if (x < 0 || y < 0 ||
00127 x >= static_cast<int>(large_map_->info.width) ||
00128 y >= static_cast<int>(large_map_->info.height))
00129 {
00130 map.data[addr] = -1;
00131 }
00132 else
00133 {
00134 map.data[addr] = large_map_->data[addr_large];
00135 }
00136 }
00137 }
00138
00139 pub_map_.publish(map);
00140 }
00141 };
00142
00143 int main(int argc, char** argv)
00144 {
00145 ros::init(argc, argv, "largemap_to_map");
00146
00147 LargeMapToMapNode conv;
00148 ros::spin();
00149
00150 return 0;
00151 }