furniture_layer.cpp
Go to the documentation of this file.
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     //Determine whether the localization obstacle list needs to be expanded to include a previously-unseen obstacle
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     //Determine whether the navigation obstacle list needs to be expanded to include a previously-unseen obstacle
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   //update navigation obstacles
00108   if (!obs->navigationObstacles.empty())
00109   {
00110     //Determine whether the navigation obstacle list needs to be expanded to include a previously-unseen obstacle
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   //update localization obstacles
00129   if (!obs->localizationObstacles.empty())
00130   {
00131     //Determine whether the localization obstacle list needs to be expanded to include a previously-unseen obstacle
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   //clear furniture layer map
00172   resetMap(0, 0, getSizeInCellsX(), getSizeInCellsY());
00173 
00174   //add polygons from the localization obstacle polygon list and adjust bounds based on polygon vertices
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         //fill polygon, populate polygon outline to send to localization map
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   //add polygons from the navigation obstacle polygon list and adjust bounds based on polygon vertices
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         //fill polygon
00255         if (!setConvexPolygonCost(mapPolygon, LETHAL_OBSTACLE))
00256         {
00257           ROS_INFO("Failed to fill a navigation polygon");
00258         }
00259         else
00260         {
00261           //populate points for local map obstacles
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   //publish information needed for updating the localization map
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   //copy relevant information from this layer's costmap to the master costmap
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   //update navigation obstacles
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     //add some padding so the inflated portion of the obstacles gets cleared as well
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 } // end namespace


carl_navigation
Author(s): Russell Toris , David Kent
autogenerated on Sat Jun 8 2019 20:26:04