00001
00012 #include <carl_navigation/furniture_layer.h>
00013 #include <pluginlib/class_list_macros.h>
00014
00015 PLUGINLIB_EXPORT_CLASS(furniture_layer_namespace::FurnitureLayer, costmap_2d::Layer)
00016 PLUGINLIB_EXPORT_CLASS(furniture_layer_namespace::FurnitureLayerLocal, costmap_2d::Layer)
00017
00018 using costmap_2d::LETHAL_OBSTACLE;
00019 using costmap_2d::NO_INFORMATION;
00020
00021 using namespace std;
00022
00023 namespace furniture_layer_namespace
00024 {
00025
00026 FurnitureLayer::FurnitureLayer() {}
00027
00028 void FurnitureLayer::onInitialize()
00029 {
00030 ros::NodeHandle nh("~/" + name_);
00031 current_ = true;
00032 default_value_ = NO_INFORMATION;
00033 matchSize();
00034
00035 dsrv_ = new dynamic_reconfigure::Server<costmap_2d::GenericPluginConfig>(nh);
00036 dynamic_reconfigure::Server<costmap_2d::GenericPluginConfig>::CallbackType cb = boost::bind(
00037 &FurnitureLayer::reconfigureCB, this, _1, _2);
00038 dsrv_->setCallback(cb);
00039
00040 updateReceived = false;
00041
00042 prevMaxX = std::numeric_limits<double>::min();
00043 prevMaxY = std::numeric_limits<double>::min();
00044 prevMinX = std::numeric_limits<double>::max();
00045 prevMinY = std::numeric_limits<double>::max();
00046
00047 localizationObstacles.clear();
00048 navigationObstacles.clear();
00049
00050 localizationGridPublisher = n.advertise<carl_navigation::BlockedCells>("furniture_layer/obstacle_grid", 1);
00051 localObstaclesPublisher = n.advertise<carl_navigation::BlockedCells>("furniture_layer/local_obstacle_grid", 1);
00052
00053 initialObstaclesClient = n.serviceClient<rail_ceiling::GetAllObstacles>("furniture_tracker/get_all_poses");
00054 initialObstaclesClient.waitForExistence();
00055 this->getInitialObstacles();
00056
00057 obstacleSubscriber = n.subscribe<rail_ceiling::Obstacles>("furniture_layer/update_obstacles", 1, &FurnitureLayer::updateFurnitureCallback, this);
00058 }
00059
00060 void FurnitureLayer::getInitialObstacles()
00061 {
00062 rail_ceiling::GetAllObstaclesRequest req;
00063 rail_ceiling::GetAllObstaclesResponse res;
00064 if (!initialObstaclesClient.call(req, res))
00065 {
00066 ROS_INFO("Failed to call initial obstacle pose client.");
00067 return;
00068 }
00069 if (!res.localizationObstacles.empty())
00070 {
00071
00072 int maxID = 0;
00073 for (unsigned int i = 0; i < res.localizationObstacles.size(); i ++)
00074 {
00075 if (res.localizationObstacles[i].id > maxID)
00076 maxID = res.localizationObstacles[i].id;
00077 }
00078 if (maxID >= localizationObstacles.size())
00079 localizationObstacles.resize(maxID + 1);
00080 for (unsigned int i = 0; i < res.localizationObstacles.size(); i ++)
00081 {
00082 localizationObstacles[res.localizationObstacles[i].id].polygons = res.localizationObstacles[i].polygons;
00083 }
00084 updateReceived = true;
00085 }
00086 if (!res.navigationObstacles.empty())
00087 {
00088
00089 int maxID = 0;
00090 for (unsigned int i = 0; i < res.navigationObstacles.size(); i++)
00091 {
00092 if (res.navigationObstacles[i].id > maxID)
00093 maxID = res.navigationObstacles[i].id;
00094 }
00095 if (maxID >= navigationObstacles.size())
00096 navigationObstacles.resize(maxID + 1);
00097 for (unsigned int i = 0; i < res.navigationObstacles.size(); i++)
00098 {
00099 navigationObstacles[res.navigationObstacles[i].id].polygons = res.navigationObstacles[i].polygons;
00100 }
00101 updateReceived = true;
00102 }
00103 }
00104
00105 void FurnitureLayer::updateFurnitureCallback(const rail_ceiling::Obstacles::ConstPtr &obs)
00106 {
00107
00108 if (!obs->navigationObstacles.empty())
00109 {
00110
00111 int maxID = 0;
00112 for (unsigned int i = 0; i < obs->navigationObstacles.size(); i++)
00113 {
00114 if (obs->navigationObstacles[i].id > maxID)
00115 maxID = obs->navigationObstacles[i].id;
00116 }
00117
00118 if (maxID >= navigationObstacles.size())
00119 navigationObstacles.resize(maxID + 1);
00120
00121 for (unsigned int i = 0; i < obs->navigationObstacles.size(); i++)
00122 {
00123 navigationObstacles[obs->navigationObstacles[i].id].polygons = obs->navigationObstacles[i].polygons;
00124 }
00125 updateReceived = true;
00126 }
00127
00128
00129 if (!obs->localizationObstacles.empty())
00130 {
00131
00132 int maxID = 0;
00133 for (unsigned int i = 0; i < obs->localizationObstacles.size(); i ++)
00134 {
00135 if (obs->localizationObstacles[i].id > maxID)
00136 maxID = obs->localizationObstacles[i].id;
00137 }
00138
00139 if (maxID >= localizationObstacles.size())
00140 localizationObstacles.resize(maxID + 1);
00141
00142 for (unsigned int i = 0; i < obs->localizationObstacles.size(); i ++)
00143 {
00144 localizationObstacles[obs->localizationObstacles[i].id].polygons = obs->localizationObstacles[i].polygons;
00145 }
00146
00147 updateReceived = true;
00148 }
00149 }
00150
00151 void FurnitureLayer::matchSize()
00152 {
00153 Costmap2D* master = layered_costmap_->getCostmap();
00154 resizeMap(master->getSizeInCellsX(), master->getSizeInCellsY(), master->getResolution(),
00155 master->getOriginX(), master->getOriginY());
00156 }
00157
00158 void FurnitureLayer::reconfigureCB(costmap_2d::GenericPluginConfig &config, uint32_t level)
00159 {
00160 enabled_ = config.enabled;
00161 }
00162
00163 void FurnitureLayer::updateBounds(double robot_x, double robot_y, double robot_yaw, double *min_x, double *min_y, double *max_x, double *max_y)
00164 {
00165 if (!enabled_)
00166 return;
00167
00168 if (!updateReceived)
00169 return;
00170
00171
00172 resetMap(0, 0, getSizeInCellsX(), getSizeInCellsY());
00173
00174
00175 vector<geometry_msgs::Point> filledPoints;
00176 vector<geometry_msgs::Point> edgePoints;
00177 vector<geometry_msgs::PointStamped> localObstacles;
00178 for (unsigned int i = 0; i < localizationObstacles.size(); i ++)
00179 {
00180 for (unsigned int j = 0; j < localizationObstacles[i].polygons.size(); j ++)
00181 {
00182 if (!localizationObstacles[i].polygons[j].points.empty())
00183 {
00184 vector<costmap_2d::MapLocation> vertices;
00185 vertices.resize(localizationObstacles[i].polygons[j].points.size());
00186 vector<geometry_msgs::Point> mapPolygon;
00187 mapPolygon.resize(localizationObstacles[i].polygons[j].points.size());
00188 for (unsigned int k = 0; k < mapPolygon.size(); k++)
00189 {
00190 mapPolygon[k].x = localizationObstacles[i].polygons[j].points[k].x;
00191 mapPolygon[k].y = localizationObstacles[i].polygons[j].points[k].y;
00192
00193 worldToMap(localizationObstacles[i].polygons[j].points[k].x, localizationObstacles[i].polygons[j].points[k].y, vertices[k].x, vertices[k].y);
00194
00195 *min_x = min(*min_x, mapPolygon[k].x);
00196 *min_y = min(*min_y, mapPolygon[k].y);
00197 *max_x = max(*max_x, mapPolygon[k].x);
00198 *max_y = max(*max_y, mapPolygon[k].y);
00199 }
00200
00201 if (!setConvexPolygonCost(mapPolygon, LETHAL_OBSTACLE))
00202 {
00203 ROS_INFO("Failed to fill a localization polygon");
00204 }
00205 else
00206 {
00207 vector<costmap_2d::MapLocation> polygonOutline;
00208 polygonOutlineCells(vertices, polygonOutline);
00209 for (unsigned int i = 0; i < polygonOutline.size(); i++)
00210 {
00211 geometry_msgs::Point p;
00212 p.x = polygonOutline[i].x;
00213 p.y = polygonOutline[i].y;
00214 edgePoints.push_back(p);
00215 }
00216
00217 vector<costmap_2d::MapLocation> filledCells;
00218 convexFillCells(vertices, filledCells);
00219 for (unsigned int k = 0; k < filledCells.size(); k++)
00220 {
00221 geometry_msgs::Point p;
00222 p.x = filledCells[k].x;
00223 p.y = filledCells[k].y;
00224 filledPoints.push_back(p);
00225 }
00226 }
00227 }
00228 }
00229 }
00230
00231
00232 for (unsigned int i = 0; i < navigationObstacles.size(); i ++)
00233 {
00234 for (unsigned int j = 0; j < navigationObstacles[i].polygons.size(); j ++)
00235 {
00236 if (!navigationObstacles[i].polygons[j].points.empty())
00237 {
00238 vector<costmap_2d::MapLocation> vertices;
00239 vertices.resize(navigationObstacles[i].polygons[j].points.size());
00240 vector<geometry_msgs::Point> mapPolygon;
00241 mapPolygon.resize(navigationObstacles[i].polygons[j].points.size());
00242 for (unsigned int k = 0; k < mapPolygon.size(); k ++)
00243 {
00244 mapPolygon[k].x = navigationObstacles[i].polygons[j].points[k].x;
00245 mapPolygon[k].y = navigationObstacles[i].polygons[j].points[k].y;
00246
00247 worldToMap(navigationObstacles[i].polygons[j].points[k].x, navigationObstacles[i].polygons[j].points[k].y, vertices[k].x, vertices[k].y);
00248
00249 *min_x = min(*min_x, mapPolygon[k].x);
00250 *min_y = min(*min_y, mapPolygon[k].y);
00251 *max_x = max(*max_x, mapPolygon[k].x);
00252 *max_y = max(*max_y, mapPolygon[k].y);
00253 }
00254
00255 if (!setConvexPolygonCost(mapPolygon, LETHAL_OBSTACLE))
00256 {
00257 ROS_INFO("Failed to fill a navigation polygon");
00258 }
00259 else
00260 {
00261
00262 vector<costmap_2d::MapLocation> filledCells;
00263 convexFillCells(vertices, filledCells);
00264 for (unsigned int k = 0; k < filledCells.size(); k++)
00265 {
00266 geometry_msgs::PointStamped point;
00267 point.header.frame_id = "map";
00268 mapToWorld((int)filledCells[k].x, (int)filledCells[k].y, point.point.x, point.point.y);
00269 localObstacles.push_back(point);
00270 }
00271 }
00272 }
00273 }
00274 }
00275
00276 prevMinX = min(*min_x, prevMinX);
00277 prevMinY = min(*min_y, prevMinY);
00278 prevMaxX = max(*max_x, prevMaxX);
00279 prevMaxY = max(*max_y, prevMaxY);
00280 *min_x = prevMinX;
00281 *min_y = prevMinY;
00282 *max_x = prevMaxX;
00283 *max_y = prevMaxY;
00284
00285
00286 carl_navigation::BlockedCells grid;
00287 grid.edgeCells = edgePoints;
00288 grid.blockedCells = filledPoints;
00289 if (localizationGridPublisher.getNumSubscribers() > 0)
00290 {
00291 localizationGridPublisher.publish(grid);
00292
00293 updateReceived = false;
00294 }
00295 else
00296 ROS_INFO("No subscribers for localizationGridPublisher yet, will republish obstacles shortly...");
00297
00298 if (localObstaclesPublisher.getNumSubscribers() > 0)
00299 {
00300 carl_navigation::BlockedCells localObstaclesMsg;
00301 localObstaclesMsg.blockedCells.resize(localObstacles.size());
00302
00303 for (unsigned int i = 0; i < localObstacles.size(); i ++)
00304 {
00305 localObstaclesMsg.blockedCells[i] = localObstacles[i].point;
00306 }
00307
00308 localObstaclesPublisher.publish(localObstaclesMsg);
00309 }
00310 else
00311 {
00312 ROS_INFO("No local map subscribing, will republish obstacles shortly...");
00313 updateReceived = true;
00314 }
00315
00316 }
00317
00318 void FurnitureLayer::updateCosts(costmap_2d::Costmap2D& master_grid, int min_i, int min_j, int max_i, int max_j)
00319 {
00320 if (!enabled_)
00321 return;
00322
00323
00324 for (int j = min_j; j < max_j; j++)
00325 {
00326 for (int i = min_i; i < max_i; i++)
00327 {
00328 int index = getIndex(i, j);
00329 if (costmap_[index] == NO_INFORMATION)
00330 continue;
00331 master_grid.setCost(i, j, costmap_[index]);
00332 }
00333 }
00334 }
00335
00336
00337
00338 FurnitureLayerLocal::FurnitureLayerLocal() {}
00339
00340 void FurnitureLayerLocal::onInitialize()
00341 {
00342 ros::NodeHandle nh("~/" + name_);
00343 current_ = true;
00344 default_value_ = NO_INFORMATION;
00345 matchSize();
00346
00347 dsrv_ = new dynamic_reconfigure::Server<costmap_2d::GenericPluginConfig>(nh);
00348 dynamic_reconfigure::Server<costmap_2d::GenericPluginConfig>::CallbackType cb = boost::bind(
00349 &FurnitureLayerLocal::reconfigureCB, this, _1, _2);
00350 dsrv_->setCallback(cb);
00351
00352 prevMaxX = std::numeric_limits<double>::min();
00353 prevMaxY = std::numeric_limits<double>::min();
00354 prevMinX = std::numeric_limits<double>::max();
00355 prevMinY = std::numeric_limits<double>::max();
00356
00357 obstaclePointsSubscriber = n.subscribe<carl_navigation::BlockedCells>("furniture_layer/local_obstacle_grid", 1, &FurnitureLayerLocal::updateObstaclePointsCallback, this);
00358 }
00359
00360 void FurnitureLayerLocal::updateObstaclePointsCallback(const carl_navigation::BlockedCells::ConstPtr &obs)
00361 {
00362
00363 if (!obs->blockedCells.empty())
00364 {
00365 obstaclePoints.clear();
00366 obstaclePoints = obs->blockedCells;
00367 }
00368 transformedPoints.clear();
00369 transformedPoints.resize(obstaclePoints.size());
00370 }
00371
00372 void FurnitureLayerLocal::matchSize()
00373 {
00374 Costmap2D* master = layered_costmap_->getCostmap();
00375 resizeMap(master->getSizeInCellsX(), master->getSizeInCellsY(), master->getResolution(),
00376 master->getOriginX(), master->getOriginY());
00377 }
00378
00379 void FurnitureLayerLocal::reconfigureCB(costmap_2d::GenericPluginConfig &config, uint32_t level)
00380 {
00381 enabled_ = config.enabled;
00382 }
00383
00384 void FurnitureLayerLocal::updateBounds(double robot_x, double robot_y, double robot_yaw, double *min_x, double *min_y, double *max_x, double *max_y)
00385 {
00386 if (!enabled_)
00387 return;
00388
00389 resetMap(0, 0, getSizeInCellsX(), getSizeInCellsY());
00390
00391 for (unsigned int i = 0; i < obstaclePoints.size(); i ++)
00392 {
00393 geometry_msgs::PointStamped inputPoint;
00394 inputPoint.header.frame_id = "map";
00395 inputPoint.point = obstaclePoints[i];
00396 geometry_msgs::PointStamped transformedPoint;
00397 tfListener.transformPoint("odom", inputPoint, transformedPoint);
00398 transformedPoints[i] = transformedPoint.point;
00399
00400 *min_x = min(*min_x, obstaclePoints[i].x - 1.0);
00401 *min_y = min(*min_y, obstaclePoints[i].y - 1.0);
00402 *max_x = max(*max_x, obstaclePoints[i].x + 1.0);
00403 *max_y = max(*max_y, obstaclePoints[i].y + 1.0);
00404 }
00405
00406 *min_x = std::min(std::min(*min_x, mark_x), prevMinX);
00407 *min_y = std::min(std::min(*min_y, mark_y), prevMinY);
00408 *max_x = std::max(std::max(*max_x, mark_x), prevMaxX);
00409 *max_y = std::max(std::max(*max_y, mark_y), prevMaxY);
00410 prevMinX = *min_x;
00411 prevMinY = *min_y;
00412 prevMaxX = *max_x;
00413 prevMaxY = *max_y;
00414 }
00415
00416
00417 void FurnitureLayerLocal::updateCosts(costmap_2d::Costmap2D& master_grid, int min_i, int min_j, int max_i, int max_j)
00418 {
00419 if (!enabled_)
00420 return;
00421
00422 for (unsigned int i = 0; i < transformedPoints.size(); i ++)
00423 {
00424 unsigned int mx, my;
00425 if (master_grid.worldToMap(transformedPoints[i].x, transformedPoints[i].y, mx, my))
00426 master_grid.setCost(mx, my, LETHAL_OBSTACLE);
00427 }
00428 }
00429
00430 }