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 #include <srs_env_model/but_server/plugins/map2d_plugin.h>
00029 #include <srs_env_model/topics_list.h>
00030
00031 #include <pcl_ros/transforms.h>
00032
00033
00034 srs_env_model::CMap2DPlugin::CMap2DPlugin(const std::string & name)
00035 : srs_env_model::CServerPluginBase(name)
00036 , m_publishMap2D(true)
00037 , m_map2DPublisherName(MAP2D_PUBLISHER_NAME)
00038 , m_latchedTopics(false)
00039 , m_map2DFrameId(MAP2D_FRAME_ID)
00040 , m_minSizeX(0.0)
00041 , m_minSizeY(0.0)
00042 {
00043 assert( m_data != 0 );
00044 }
00045
00046
00047
00048 srs_env_model::CMap2DPlugin::~CMap2DPlugin()
00049 {
00050 }
00051
00052
00053
00054 bool srs_env_model::CMap2DPlugin::shouldPublish()
00055 {
00056 return( m_publishMap2D && m_map2DPublisher.getNumSubscribers() > 0 );
00057 }
00058
00059
00060
00061 void srs_env_model::CMap2DPlugin::init(ros::NodeHandle & node_handle)
00062 {
00063 node_handle.param("collision_object_publisher", m_map2DPublisherName, MAP2D_PUBLISHER_NAME );
00064 node_handle.param("collision_object_frame_id", m_map2DFrameId, MAP2D_FRAME_ID );
00065 node_handle.param("min_x_size", m_minSizeX, m_minSizeX);
00066 node_handle.param("min_y_size", m_minSizeY, m_minSizeY);
00067
00068
00069 m_map2DPublisher = node_handle.advertise<nav_msgs::OccupancyGrid> (m_map2DPublisherName, 5, m_latchedTopics);
00070 }
00071
00072
00073
00074 void srs_env_model::CMap2DPlugin::publishInternal(const ros::Time & timestamp)
00075 {
00076 if( shouldPublish() )
00077 m_map2DPublisher.publish(*m_data);
00078 }
00079
00080
00081
00082 void srs_env_model::CMap2DPlugin::newMapDataCB(SMapWithParameters & par)
00083 {
00084 m_data->header.frame_id = m_map2DFrameId;
00085 m_data->header.stamp = par.currentTime;
00086 m_data->info.resolution = par.resolution;
00087
00088 m_ocFrameId = par.frameId;
00089 ros::Time timestamp( par.currentTime );
00090
00091 tf::StampedTransform ocToMap2DTf;
00092
00093 m_bConvert = m_ocFrameId != m_map2DFrameId;
00094
00095
00096 try {
00097
00098 m_tfListener.waitForTransform(m_map2DFrameId, m_ocFrameId,
00099 timestamp, ros::Duration(5));
00100
00101 m_tfListener.lookupTransform(m_map2DFrameId, m_ocFrameId,
00102 timestamp, ocToMap2DTf);
00103
00104 } catch (tf::TransformException& ex) {
00105 ROS_ERROR_STREAM("Transform error: " << ex.what() << ", quitting callback");
00106 PERROR( "Transform error.");
00107 return;
00108 }
00109
00110
00111 Eigen::Matrix4f ocToMap2DTM;
00112
00113
00114 pcl_ros::transformAsMatrix(ocToMap2DTf, ocToMap2DTM);
00115
00116 const tButServerOcMap &map(*par.map);
00117
00118
00119 m_ocToMap2DRot = ocToMap2DTM.block<3, 3> (0, 0);
00120 m_ocToMap2DTrans = ocToMap2DTM.block<3, 1> (0, 3);
00121
00122 double minX, minY, minZ, maxX, maxY, maxZ;
00123 map.getTree().getMetricMin(minX, minY, minZ);
00124 map.getTree().getMetricMax(maxX, maxY, maxZ);
00125
00126 octomap::point3d minPt(minX, minY, minZ);
00127 octomap::point3d maxPt(maxX, maxY, maxZ);
00128
00129 octomap::OcTreeKey minKey, maxKey, curKey;
00130
00131
00132 if (!map.getTree().genKey(minPt, minKey)) {
00133 ROS_ERROR("Could not create min OcTree key at %f %f %f", minPt.x(), minPt.y(), minPt.z());
00134 return;
00135 }
00136
00137 if (!map.getTree().genKey(maxPt, maxKey)) {
00138 ROS_ERROR("Could not create max OcTree key at %f %f %f", maxPt.x(), maxPt.y(), maxPt.z());
00139 return;
00140 }
00141
00142 ROS_DEBUG("MinKey: %d %d %d / MaxKey: %d %d %d", minKey[0], minKey[1], minKey[2], maxKey[0], maxKey[1], maxKey[2]);
00143
00144
00145 double halfPaddedX = 0.5 * m_minSizeX;
00146 double halfPaddedY = 0.5 * m_minSizeY;
00147
00148 minX = std::min(minX, -halfPaddedX);
00149 maxX = std::max(maxX, halfPaddedX);
00150
00151 minY = std::min(minY, -halfPaddedY);
00152 maxY = std::max(maxY, halfPaddedY);
00153
00154 minPt = octomap::point3d(minX, minY, minZ);
00155 maxPt = octomap::point3d(maxX, maxY, maxZ);
00156
00157 octomap::OcTreeKey paddedMaxKey;
00158
00159 if (!map.getTree().genKey(minPt, m_paddedMinKey)) {
00160 ROS_ERROR("Could not create padded min OcTree key at %f %f %f", minPt.x(), minPt.y(), minPt.z());
00161 return;
00162 }
00163
00164 if (!map.getTree().genKey(maxPt, paddedMaxKey)) {
00165 ROS_ERROR("Could not create padded max OcTree key at %f %f %f", maxPt.x(), maxPt.y(), maxPt.z());
00166 return;
00167 }
00168
00169 ROS_DEBUG("Padded MinKey: %d %d %d / padded MaxKey: %d %d %d", m_paddedMinKey[0], m_paddedMinKey[1],
00170 m_paddedMinKey[2], paddedMaxKey[0], paddedMaxKey[1], paddedMaxKey[2]);
00171
00172 assert(paddedMaxKey[0] >= maxKey[0] && paddedMaxKey[1] >= maxKey[1]);
00173
00174 m_data->info.width = paddedMaxKey[0] - m_paddedMinKey[0] + 1;
00175 m_data->info.height = paddedMaxKey[1] - m_paddedMinKey[1] + 1;
00176
00177 int mapOriginX = minKey[0] - m_paddedMinKey[0];
00178 int mapOriginY = minKey[1] - m_paddedMinKey[1];
00179
00180 assert(mapOriginX >= 0 && mapOriginY >= 0);
00181
00182
00183 octomap::point3d origin;
00184 map.getTree().genCoords(m_paddedMinKey, par.treeDepth, origin);
00185
00186 m_data->info.origin.position.x = origin.x() - par.resolution* 0.5;
00187 m_data->info.origin.position.y = origin.y() - par.resolution * 0.5;
00188
00189
00190 m_data->data.resize(m_data->info.width * m_data->info.height, -1);
00191
00192 tButServerOcTree & tree( par.map->getTree() );
00193 srs_env_model::tButServerOcTree::leaf_iterator it, itEnd( tree.end_leafs() );
00194
00195
00196 for ( it = tree.begin_leafs(m_crawlDepth); it != itEnd; ++it)
00197 {
00198
00199 if (tree.isNodeOccupied(*it))
00200 {
00201 handleOccupiedNode(it, par);
00202 }
00203 else
00204 {
00205 handleFreeNode( it, par );
00206 }
00207
00208 }
00209
00210 invalidate();
00211 }
00212
00216 void srs_env_model::CMap2DPlugin::handleOccupiedNode(srs_env_model::tButServerOcTree::iterator & it, const SMapWithParameters & mp)
00217 {
00218 if (it.getDepth() == mp.treeDepth)
00219 {
00220
00221 octomap::OcTreeKey nKey = it.getKey();
00222 int i = nKey[0] - m_paddedMinKey[0];
00223 int j = nKey[1] - m_paddedMinKey[1];
00224 m_data->data[m_data->info.width * j + i] = 100;
00225
00226 } else {
00227
00228 int intSize = 1 << (mp.treeDepth - it.getDepth());
00229 octomap::OcTreeKey minKey = it.getIndexKey();
00230 for (int dx = 0; dx < intSize; dx++) {
00231 int i = minKey[0] + dx - m_paddedMinKey[0];
00232 for (int dy = 0; dy < intSize; dy++) {
00233 int j = minKey[1] + dy - m_paddedMinKey[1];
00234 m_data->data[m_data->info.width * j + i] = 100;
00235 }
00236 }
00237 }
00238 }
00239
00243 void srs_env_model::CMap2DPlugin::handleFreeNode(srs_env_model::tButServerOcTree::iterator & it, const SMapWithParameters & mp )
00244 {
00245 if (it.getDepth() == mp.treeDepth) {
00246 octomap::OcTreeKey nKey = it.getKey();
00247 int i = nKey[0] - m_paddedMinKey[0];
00248 int j = nKey[1] - m_paddedMinKey[1];
00249 if (m_data->data[m_data->info.width * j + i] == -1) {
00250 m_data->data[m_data->info.width * j + i] = 0;
00251 }
00252 } else {
00253 int intSize = 1 << (mp.treeDepth - it.getDepth());
00254 octomap::OcTreeKey minKey = it.getIndexKey();
00255 for (int dx = 0; dx < intSize; dx++) {
00256 int i = minKey[0] + dx - m_paddedMinKey[0];
00257 for (int dy = 0; dy < intSize; dy++) {
00258 int j = minKey[1] + dy - m_paddedMinKey[1];
00259 if (m_data->data[m_data->info.width * j + i] == -1) {
00260 m_data->data[m_data->info.width * j + i] = 0;
00261 }
00262 }
00263 }
00264 }
00265 }
00266
00270 void srs_env_model::CMap2DPlugin::pause( bool bPause, ros::NodeHandle & node_handle )
00271 {
00272 if( bPause )
00273 {
00274 m_map2DPublisher.shutdown();
00275 }
00276 else
00277 {
00278
00279 m_map2DPublisher = node_handle.advertise<nav_msgs::OccupancyGrid> (m_map2DPublisherName, 5, m_latchedTopics);
00280 }
00281 }