Esempio n. 1
0
void VirtualWallLayer::onWallMessageCallback(const WallPtr& msg) {

    WallInfo wi;

    if(worldToMap(msg->from.x, msg->from.y, wi.x1, wi.y1) && worldToMap(msg->to.x, msg->to.y, wi.x2, wi.y2)) {
        walls[msg->identifier] = wi;
        updateWalls();
    } else {
        walls.erase(msg->identifier);
    }

}
Esempio n. 2
0
void VoxelLayer::clearNonLethal(double wx, double wy, double w_size_x, double w_size_y, bool clear_no_info)
{
  //get the cell coordinates of the center point of the window
  unsigned int mx, my;
  if (!worldToMap(wx, wy, mx, my))
    return;

  //compute the bounds of the window
  double start_x = wx - w_size_x / 2;
  double start_y = wy - w_size_y / 2;
  double end_x = start_x + w_size_x;
  double end_y = start_y + w_size_y;

  //scale the window based on the bounds of the costmap
  start_x = std::max(origin_x_, start_x);
  start_y = std::max(origin_y_, start_y);

  end_x = std::min(origin_x_ + getSizeInMetersX(), end_x);
  end_y = std::min(origin_y_ + getSizeInMetersY(), end_y);

  //get the map coordinates of the bounds of the window
  unsigned int map_sx, map_sy, map_ex, map_ey;

  //check for legality just in case
  if (!worldToMap(start_x, start_y, map_sx, map_sy) || !worldToMap(end_x, end_y, map_ex, map_ey))
    return;

  //we know that we want to clear all non-lethal obstacles in this window to get it ready for inflation
  unsigned int index = getIndex(map_sx, map_sy);
  unsigned char* current = &costmap_[index];
  for (unsigned int j = map_sy; j <= map_ey; ++j)
  {
    for (unsigned int i = map_sx; i <= map_ex; ++i)
    {
      //if the cell is a lethal obstacle... we'll keep it and queue it, otherwise... we'll clear it
      if (*current != LETHAL_OBSTACLE)
      {
        if (clear_no_info || *current != NO_INFORMATION)
        {
          *current = FREE_SPACE;
          voxel_grid_.clearVoxelColumn(index);
        }
      }
      current++;
      index++;
    }
    current += size_x_ - (map_ex - map_sx) - 1;
    index += size_x_ - (map_ex - map_sx) - 1;
  }
}
bool EpicNavigationNodeOMPL::srvRemoveGoals(epic::ModifyGoals::Request &req, epic::ModifyGoals::Response &res)
{
    if (occupancy_grid == nullptr) {
        ROS_WARN("Warning[EpicNavigationNodeOMPL::srvRemoveGoals]: Occupancy grid was not initialized.");
        res.success = false;
        return false;
    }

    if (req.goals.size() != 1) {
        ROS_ERROR("Warning[EpicNavigationNodeOMPL::srvRemoveGoals]: Invalid number of goal locations.");
        res.success = false;
        return false;
    }

    float x = 0.0f;
    float y = 0.0f;

    worldToMap(req.goals[0].pose.position.x, req.goals[0].pose.position.y, x, y);

    // If the goal location is not a goal, then we can just return without changing anything.
    if (!isCellGoal((unsigned int)(x + 0.5f), (unsigned int)(y + 0.5f))) {
        return ;
    }

    occupancy_grid[(unsigned int)(y + 0.5f) * width + (unsigned int)(x + 0.5f)] = EPIC_CELL_TYPE_FREE;
    goal_assigned = false;

    // Try to create the planner algorithm now.
    initAlg();

    res.success = true;

    return true;
}
bool EpicNavigationNodeHarmonic::srvRemoveGoals(epic::ModifyGoals::Request &req, epic::ModifyGoals::Response &res)
{
    if (!init_alg) {
        ROS_WARN("Warning[EpicNavigationNodeHarmonic::srvRemoveGoals]: Algorithm was not initialized.");
        res.success = false;
        return false;
    }

    std::vector<unsigned int> v;
    std::vector<unsigned int> types;

    // Note: Removing goals turns them into free space. Recall, however, that goals can
    // only be added on free space (above).
    for (unsigned int i = 0; i < req.goals.size(); i++) {
        float x = 0.0f;
        float y = 0.0f;

        if (!worldToMap(req.goals[i].pose.position.x, req.goals[i].pose.position.y, x, y)) {
            continue;
        }

        v.push_back((unsigned int) x);
        v.push_back((unsigned int) y);
        types.push_back(EPIC_CELL_TYPE_FREE);
    }

    setCells(v, types);

    v.clear();
    types.clear();

    res.success = true;

    return true;
}
bool GridMap2D::isOccupiedAt(double wx, double wy) const{
	unsigned mx, my;
	if (worldToMap(wx, wy, mx, my))
		return isOccupiedAtCell(mx, my);
	else
		return true;
}
bool EpicNavigationNodeOMPL::srvComputePath(epic::ComputePath::Request &req, epic::ComputePath::Response &res)
{
    // First, determine and assign the starting location.
    float x = 0.0f;
    float y = 0.0f;

    if (!worldToMap(req.start.pose.position.x, req.start.pose.position.y, x, y)) {
        ROS_WARN("Warning[EpicNavigationNodeOMPL::srvComputePath]: Could not convert start to floating point map location.");
    }

    start_location.first = x;
    start_location.second = y;
    start_assigned = true;

    // Try to create the planner algorithm now that we have an initial starting state.
    initAlg();

    if (!init_alg) {
        ROS_WARN("Warning[EpicNavigationNodeOMPL::srvComputePath]: Algorithm was not initialized.");
        return false;
    }

    unsigned int k = 0;
    float *raw_path = nullptr;

    if ((bool)ompl_planner_status) {
        // TODO: If an approximate or exact solution was found, then populate raw_path. Otherwise, leave it empty.
        //k = ???
        //raw_path = new float[2 * k];
        //for (...
        // ompl_planner.get_path...???
    }

    res.path.header.frame_id = req.start.header.frame_id;
    res.path.header.stamp = req.start.header.stamp;

    res.path.poses.resize(k);
    res.path.poses[0] = req.start;

    for (unsigned int i = 1; i < k; i++) {
        x = raw_path[2 * i + 0];
        y = raw_path[2 * i + 1];
        float path_theta = std::atan2(y - raw_path[2 * (i - 1) + 1], x - raw_path[2 * (i - 1) + 0]);

        float path_x = 0.0f;
        float path_y = 0.0f;
        mapToWorld(x, y, path_x, path_y);

        res.path.poses[i] = req.start;
        res.path.poses[i].pose.position.x = path_x;
        res.path.poses[i].pose.position.y = path_y;
        res.path.poses[i].pose.orientation = tf::createQuaternionMsgFromYaw(path_theta);
    }

    delete [] raw_path;
    raw_path = nullptr;

    return true;
}
uchar GridMap2D::binaryMapAt(double wx, double wy) const{
	unsigned mx, my;

	if (worldToMap(wx, wy, mx, my))
		return m_binaryMap.at<uchar>(mx, my);
	else
		return 0;
}
float GridMap2D::distanceMapAt(double wx, double wy) const{
	unsigned mx, my;

	if (worldToMap(wx, wy, mx, my))
		return m_distMap.at<float>(mx, my);
	else
		return -1.0f;
}
  void Costmap2D::resetInflationWindow(double wx, double wy, double w_size_x, double w_size_y,
      priority_queue<CellData>& inflation_queue, bool clear){
    //get the cell coordinates of the center point of the window
    unsigned int mx, my;
    if(!worldToMap(wx, wy, mx, my))
      return;

    //compute the bounds of the window
    double start_x = wx - w_size_x / 2;
    double start_y = wy - w_size_y / 2;
    double end_x = start_x + w_size_x;
    double end_y = start_y + w_size_y;

    //scale the window based on the bounds of the costmap
    start_x = max(origin_x_, start_x);
    start_y = max(origin_y_, start_y);

    end_x = min(origin_x_ + getSizeInMetersX(), end_x);
    end_y = min(origin_y_ + getSizeInMetersY(), end_y);

    //get the map coordinates of the bounds of the window
    unsigned int map_sx, map_sy, map_ex, map_ey;

    //check for legality just in case
    if(!worldToMap(start_x, start_y, map_sx, map_sy) || !worldToMap(end_x, end_y, map_ex, map_ey)){
      ROS_ERROR("Bounds not legal for reset window. Doing nothing.");
      return;
    }

    //we know that we want to clear all non-lethal obstacles in this window to get it ready for inflation
    unsigned int index = getIndex(map_sx, map_sy);
    unsigned char* current = &costmap_[index];
    for(unsigned int j = map_sy; j <= map_ey; ++j){
      for(unsigned int i = map_sx; i <= map_ex; ++i){
        //if the cell is a lethal obstacle... we'll keep it and queue it, otherwise... we'll clear it
        if(*current == LETHAL_OBSTACLE)
          enqueue(index, i, j, i, j, inflation_queue);
        else if(clear && *current != NO_INFORMATION)
          *current = FREE_SPACE;
        current++;
        index++;
      }
      current += size_x_ - (map_ex - map_sx) - 1;
      index += size_x_ - (map_ex - map_sx) - 1;
    }
  }
Esempio n. 10
0
float DynamicEDTOctomap::getDistance(const octomap::point3d& p) const {
  int x,y,z;
  worldToMap(p, x, y, z);
  if(x>=0 && x<sizeX && y>=0 && y<sizeY && z>=0 && z<sizeZ){
      return data[x][y][z].dist*treeResolution;
  } else {
      return distanceValue_Error;
  }
}
Esempio n. 11
0
int DynamicEDTOctomap::getSquaredDistanceInCells(const octomap::point3d& p) const {
  int x,y,z;
  worldToMap(p, x, y, z);
  if(x>=0 && x<sizeX && y>=0 && y<sizeY && z>=0 && z<sizeZ){
    return data[x][y][z].sqdist;
  } else {
    return distanceInCellsValue_Error;
  }
}
Esempio n. 12
0
float cartman_mpd_t::get_level(float x, float y)
{
    float zdone = 0.0f;
    if (x < 0.0f || x >= info.edgex) return zdone;
    if (y < 0.0f || y >= info.edgey) return zdone;
    int mapx, mapy;
    worldToMap(x, y, mapx, mapy);
    return get_level(mapx, mapy);
}
  void Costmap2D::resetMapOutsideWindow(double wx, double wy, double w_size_x, double w_size_y){
    ROS_ASSERT_MSG(w_size_x >= 0 && w_size_y >= 0, "You cannot specify a negative size window");

    double start_point_x = wx - w_size_x / 2;
    double start_point_y = wy - w_size_y / 2;
    double end_point_x = start_point_x + w_size_x;
    double end_point_y = start_point_y + w_size_y;

    //check start bounds
    start_point_x = max(origin_x_, start_point_x);
    start_point_y = max(origin_y_, start_point_y);

    //check end bounds
    end_point_x = min(origin_x_ + getSizeInMetersX(), end_point_x);
    end_point_y = min(origin_y_ + getSizeInMetersY(), end_point_y);

    unsigned int start_x, start_y, end_x, end_y;

    //check for legality just in case
    if(!worldToMap(start_point_x, start_point_y, start_x, start_y) || !worldToMap(end_point_x, end_point_y, end_x, end_y))
      return;

    ROS_ASSERT(end_x >= start_x && end_y >= start_y);
    unsigned int cell_size_x = end_x - start_x;
    unsigned int cell_size_y = end_y - start_y;

    //we need a map to store the obstacles in the window temporarily
    unsigned char* local_map = new unsigned char[cell_size_x * cell_size_y];

    //copy the local window in the costmap to the local map
    copyMapRegion(costmap_, start_x, start_y, size_x_, local_map, 0, 0, cell_size_x, cell_size_x, cell_size_y);

    //now we'll reset the costmap to the static map
    memcpy(costmap_, static_map_, size_x_ * size_y_ * sizeof(unsigned char));

    //now we want to copy the local map back into the costmap
    copyMapRegion(local_map, 0, 0, cell_size_x, costmap_, start_x, start_y, size_x_, cell_size_x, cell_size_y);

    //clean up
    delete[] local_map;
  }
Esempio n. 14
0
void DynamicEDTOctomap::getDistanceAndClosestObstacle_unsafe(const octomap::point3d& p, float &distance, octomap::point3d& closestObstacle) const {
	int x,y,z;
	worldToMap(p, x, y, z);

	dataCell c= data[x][y][z];

	distance = c.dist*treeResolution;
	if(c.obstX != invalidObstData){
		mapToWorld(c.obstX, c.obstY, c.obstZ, closestObstacle);
	} else {
		//If we are at maxDist, it can very well be that there is no valid closest obstacle data for this cell, this is not an error.
	}
}
void StaticLayer::updateCosts(costmap_2d::Costmap2D& master_grid, int min_i, int min_j, int max_i, int max_j)
{
  if (!map_received_)
    return;

  if (!layered_costmap_->isRolling())
  {
    // if not rolling, the layered costmap (master_grid) has same coordinates as this layer
    if (!use_maximum_)
      updateWithTrueOverwrite(master_grid, min_i, min_j, max_i, max_j);
    else
      updateWithMax(master_grid, min_i, min_j, max_i, max_j);
  }
  else
  {
    // If rolling window, the master_grid is unlikely to have same coordinates as this layer
    unsigned int mx, my;
    double wx, wy;
    // Might even be in a different frame
    tf::StampedTransform transform;
    try
    {
      tf_->lookupTransform(map_frame_, global_frame_, ros::Time(0), transform);
    }
    catch (tf::TransformException ex)
    {
      ROS_ERROR("%s", ex.what());
      return;
    }
    // Copy map data given proper transformations
    for (unsigned int i = min_i; i < max_i; ++i)
    {
      for (unsigned int j = min_j; j < max_j; ++j)
      {
        // Convert master_grid coordinates (i,j) into global_frame_(wx,wy) coordinates
        layered_costmap_->getCostmap()->mapToWorld(i, j, wx, wy);
        // Transform from global_frame_ to map_frame_
        tf::Point p(wx, wy, 0);
        p = transform(p);
        // Set master_grid with cell from map
        if (worldToMap(p.x(), p.y(), mx, my))
        {
          if (!use_maximum_)
            master_grid.setCost(i, j, getCost(mx, my));
          else
            master_grid.setCost(i, j, std::max(getCost(mx, my), master_grid.getCost(i, j)));
        }
      }
    }
  }
}
  void Costmap2D::reshapeStaticMap(double win_origin_x, double win_origin_y,
                                 unsigned int data_size_x, unsigned int data_size_y, const std::vector<unsigned char>& static_data){
    int m_ox, m_oy;
    worldToMapNoBounds(win_origin_x, win_origin_y, m_ox, m_oy);

    //compute the bounds for the size of our new map
    int bl_x = std::min(m_ox, 0);
    int bl_y = std::min(m_oy, 0);
    int ur_x = std::max(m_ox + data_size_x, size_x_);
    int ur_y = std::max(m_oy + data_size_y, size_y_);

    //create a temporary map to hold our static data and copy the old static map into it
    unsigned char* static_map_copy = new unsigned char[size_x_ * size_y_];
    memcpy(static_map_copy, static_map_, size_x_ * size_y_ * sizeof(unsigned char));

    //delete our old maps... the user will lose any 
    //cost information not stored in the static map when reshaping a map
    deleteMaps();

    //update the origin and sizes, and cache data we'll need
    double old_origin_x = origin_x_;
    double old_origin_y = origin_y_;
    unsigned int old_size_x = size_x_;
    unsigned int old_size_y = size_y_;

    size_x_ = ur_x - bl_x;
    size_y_ = ur_y - bl_y;
    origin_x_ = std::min(origin_x_, win_origin_x);
    origin_y_ = std::min(origin_y_, win_origin_y);

    //initialize our various maps
    initMaps(size_x_, size_y_);

    //reset our maps to be full of unknown space if appropriate
    resetMaps();

    //now, copy the old static map into the new costmap
    unsigned int start_x, start_y;
    worldToMap(old_origin_x, old_origin_y, start_x, start_y);
    copyMapRegion(static_map_copy, 0, 0, old_size_x, costmap_, start_x, start_y, size_x_, old_size_x, old_size_y);

    delete[] static_map_copy;

    //now we want to update the map with the new static map data
    replaceStaticMapWindow(win_origin_x, win_origin_y, data_size_x, data_size_y, static_data);
  }
Esempio n. 17
0
void GridLayer::updateBounds(double origin_x, double origin_y, double origin_yaw, double* min_x,
                                           double* min_y, double* max_x, double* max_y)
{
  if (!enabled_)
    return;

  double mark_x = origin_x + cos(origin_yaw), mark_y = origin_y + sin(origin_yaw);
  unsigned int mx;
  unsigned int my;
  if(worldToMap(mark_x, mark_y, mx, my)){
    setCost(mx, my, LETHAL_OBSTACLE);
  }
  
  *min_x = std::min(*min_x, mark_x);
  *min_y = std::min(*min_y, mark_y);
  *max_x = std::max(*max_x, mark_x);
  *max_y = std::max(*max_y, mark_y);
}
bool EpicNavigationNodeHarmonic::srvAddGoals(epic::ModifyGoals::Request &req, epic::ModifyGoals::Response &res)
{
    if (!init_alg) {
        ROS_WARN("Warning[EpicNavigationNodeHarmonic::srvAddGoals]: Algorithm was not initialized.");
        res.success = false;
        return false;
    }

    std::vector<unsigned int> v;
    std::vector<unsigned int> types;

    for (unsigned int i = 0; i < req.goals.size(); i++) {
        float x = 0.0f;
        float y = 0.0f;

        worldToMap(req.goals[i].pose.position.x, req.goals[i].pose.position.y, x, y);

        // If the goal location is an obstacle, then do not let it add a goal here.
        if (isCellObstacle((unsigned int)(x + 0.5f), (unsigned int)(y + 0.5f))) {
            continue;
        }

        v.push_back((unsigned int) x);
        v.push_back((unsigned int) y);
        types.push_back(EPIC_CELL_TYPE_GOAL);
    }

    if (v.size() == 0) {
        ROS_WARN("Warning[EpicNavigationNodeHarmonic::srvAddGoals]: Attempted to add goal(s) inside obstacles. No goals added.");
        res.success = false;
        return false;
    }

    setCells(v, types);

    v.clear();
    types.clear();

    res.success = true;

    return true;
}
  void Costmap2D::updateObstacles(const vector<Observation>& observations, priority_queue<CellData>& inflation_queue){
    //place the new obstacles into a priority queue... each with a priority of zero to begin with
    for(vector<Observation>::const_iterator it = observations.begin(); it != observations.end(); ++it){
      const Observation& obs = *it;

      const sensor_msgs::PointCloud& cloud =obs.cloud_;

      double sq_obstacle_range = obs.obstacle_range_ * obs.obstacle_range_;


      for(unsigned int i = 0; i < cloud.points.size(); ++i){
        //if the obstacle is too high or too far away from the robot we won't add it
        if(cloud.points[i].z > max_obstacle_height_){
          ROS_DEBUG("The point is too high");
          continue;
        }

        //compute the squared distance from the hitpoint to the pointcloud's origin
        double sq_dist = (cloud.points[i].x - obs.origin_.x) * (cloud.points[i].x - obs.origin_.x)
          + (cloud.points[i].y - obs.origin_.y) * (cloud.points[i].y - obs.origin_.y)
          + (cloud.points[i].z - obs.origin_.z) * (cloud.points[i].z - obs.origin_.z);

        //if the point is far enough away... we won't consider it
        if(sq_dist >= sq_obstacle_range){
          ROS_DEBUG("The point is too far away");
          continue;
        }

        //now we need to compute the map coordinates for the observation
        unsigned int mx, my;
        if(!worldToMap(cloud.points[i].x, cloud.points[i].y, mx, my)){
          ROS_DEBUG("Computing map coords failed");
          continue;
        }

        unsigned int index = getIndex(mx, my);

        //push the relevant cell index back onto the inflation queue
        enqueue(index, mx, my, mx, my, inflation_queue);
      }
    }
  }
Esempio n. 20
0
bool EpicNavigationNodeOMPL::srvAddGoals(epic::ModifyGoals::Request &req, epic::ModifyGoals::Response &res)
{
    if (occupancy_grid == nullptr) {
        ROS_WARN("Warning[EpicNavigationNodeOMPL::srvAddGoals]: Occupancy grid was not initialized.");
        res.success = false;
        return false;
    }

    if (req.goals.size() != 1) {
        ROS_ERROR("Warning[EpicNavigationNodeOMPL::srvAddGoals]: Invalid number of goal locations.");
        res.success = false;
        return false;
    }

    float x = 0.0f;
    float y = 0.0f;

    worldToMap(req.goals[0].pose.position.x, req.goals[0].pose.position.y, x, y);

    // If the goal location is an obstacle, then do not let it add a goal here.
    if (isCellObstacle((unsigned int)(x + 0.5f), (unsigned int)(y + 0.5f))) {
        ROS_WARN("Warning[EpicNavigationNodeOMPL::srvAddGoals]: Attempted to add a goal at an obstacle.");
        res.success = false;
        return false;
    }

    goal_location.first = x;
    goal_location.second = y;
    goal_assigned = true;

    occupancy_grid[(unsigned int)(y + 0.5f) * width + (unsigned int)(x + 0.5f)] = EPIC_CELL_TYPE_OBSTACLE;

    // Try to create the planner algorithm now.
    initAlg();

    res.success = true;

    return true;
}
  void BallPickerLayer::updateBounds(double origin_x, double origin_y, double origin_yaw, double* min_x, double* min_y, double* max_x, double* max_y)
  {
    if (!enabled_) 
      return;
    
    if (layered_costmap_->isRolling())
      updateOrigin(origin_x - getSizeInMetersX() / 2, origin_y - getSizeInMetersY() / 2);

    double mark_x, mark_y;
    unsigned int mx, my;
    unsigned int index;

    if (clear_flag)
    {
      *min_x = *min_x - getSizeInMetersX()/2;
      *min_y = *min_y - getSizeInMetersY()/2;
      *max_x = *max_x + getSizeInMetersX()/2;
      *max_y = *max_y + getSizeInMetersY()/2;
    }

    for (std::vector<ball_picker::PointOfInterest>::iterator iter = obstacle_buffer.begin() ; iter != obstacle_buffer.end(); iter++)
    {
      mark_x = iter->x;
      mark_y = iter->y;

      if(worldToMap(mark_x, mark_y, mx, my))
      {
        index = getIndex(mx, my);
        costmap_[index] = LETHAL_OBSTACLE;      
      }
  
      *min_x = std::min(*min_x, mark_x);
      *min_y = std::min(*min_y, mark_y);
      *max_x = std::max(*max_x, mark_x);
      *max_y = std::max(*max_y, mark_y);

    }

  }
  bool Costmap2D::setConvexPolygonCost(const std::vector<geometry_msgs::Point>& polygon, unsigned char cost_value) {
    //we assume the polygon is given in the global_frame... we need to transform it to map coordinates
    std::vector<MapLocation> map_polygon;
    for(unsigned int i = 0; i < polygon.size(); ++i){
      MapLocation loc;
      if(!worldToMap(polygon[i].x, polygon[i].y, loc.x, loc.y)){
        ROS_DEBUG("Polygon lies outside map bounds, so we can't fill it");
        return false;
      }
      map_polygon.push_back(loc);
    }

    std::vector<MapLocation> polygon_cells;

    //get the cells that fill the polygon
    convexFillCells(map_polygon, polygon_cells);

    //set the cost of those cells
    for(unsigned int i = 0; i < polygon_cells.size(); ++i){
      unsigned int index = getIndex(polygon_cells[i].x, polygon_cells[i].y);
      costmap_[index] = cost_value;
    }
    return true;
  }
bool GridMap2D::inMapBounds(double wx, double wy) const{
	unsigned mx, my;
	return worldToMap(wx,wy,mx,my);
}
Esempio n. 24
0
int DynamicEDTOctomap::getSquaredDistanceInCells_unsafe(const octomap::point3d& p) const {
  int x,y,z;
  worldToMap(p, x, y, z);
  return data[x][y][z].sqdist;
}
bool EpicNavigationNodeHarmonic::srvComputePath(epic::ComputePath::Request &req, epic::ComputePath::Response &res)
{
    if (!init_alg) {
        ROS_WARN("Warning[EpicNavigationNodeHarmonic::srvComputePath]: Algorithm was not initialized.");
        return false;
    }

    if (gpu) {
        if (harmonic_get_potential_values_gpu(&harmonic) != EPIC_SUCCESS) {
            ROS_WARN("Error[EpicNavigationNodeHarmonic::srvComputePath]: Failed to get the potential values from the GPU.");
            return false;
        }
    }

    float x = 0.0f;
    float y = 0.0f;
    if (!worldToMap(req.start.pose.position.x, req.start.pose.position.y, x, y)) {
        ROS_WARN("Warning[EpicNavigationNodeHarmonic::srvComputePath]: Could not convert start to floating point map location.");
    }

    unsigned int k = 0;
    float *raw_path = nullptr;

    int result = harmonic_compute_path_2d_cpu(&harmonic, x, y, req.step_size, req.precision, req.max_length, k, raw_path);

    if (result != EPIC_SUCCESS) {
        ROS_ERROR("Error[EpicNavigationNodeHarmonic::srvComputePath]: Failed to compute the path.");

        if (raw_path != nullptr) {
            delete [] raw_path;
        }

        return false;
    }

    res.path.header.frame_id = req.start.header.frame_id;
    res.path.header.stamp = req.start.header.stamp;

    res.path.poses.resize(k);
    res.path.poses[0] = req.start;

    for (unsigned int i = 1; i < k; i++) {
        x = raw_path[2 * i + 0];
        y = raw_path[2 * i + 1];
        float path_theta = std::atan2(y - raw_path[2 * (i - 1) + 1], x - raw_path[2 * (i - 1) + 0]);

        float path_x = 0.0f;
        float path_y = 0.0f;
        mapToWorld(x, y, path_x, path_y);

        res.path.poses[i] = req.start;
        res.path.poses[i].pose.position.x = path_x;
        res.path.poses[i].pose.position.y = path_y;
        res.path.poses[i].pose.orientation = tf::createQuaternionMsgFromYaw(path_theta);
    }

    delete [] raw_path;
    raw_path = nullptr;

    return true;
}
Esempio n. 26
0
float DynamicEDTOctomap::getDistance_unsafe(const octomap::point3d& p) const {
  int x,y,z;
  worldToMap(p, x, y, z);
  return data[x][y][z].dist*treeResolution;
}
  void Costmap2D::replaceStaticMapWindow(double win_origin_x, double win_origin_y, 
                                         unsigned int data_size_x, unsigned int data_size_y, 
                                         const std::vector<unsigned char>& static_data){
    unsigned int start_x, start_y;
    if(!worldToMap(win_origin_x, win_origin_y, start_x, start_y) || (start_x + data_size_x) > size_x_ || (start_y + data_size_y) > size_y_){
      ROS_ERROR("You must call replaceStaticMapWindow with a window origin and size that is contained within the map");
      return;
    }

    //we need to compute the region of the costmap that could change from inflation of new obstacles
    unsigned int max_inflation_change = 2 * cell_inflation_radius_;

    //make sure that we don't go out of map bounds
    unsigned int copy_sx = std::min(std::max(0, (int)start_x - (int)max_inflation_change), (int)size_x_);
    unsigned int copy_sy = std::min(std::max(0, (int)start_y - (int)max_inflation_change), (int)size_x_);
    unsigned int copy_ex = std::max(std::min((int)size_x_, (int)start_x + (int)data_size_x + (int)max_inflation_change), 0);
    unsigned int copy_ey = std::max(std::min((int)size_y_, (int)start_y + (int)data_size_y + (int)max_inflation_change), 0);

    unsigned int copy_size_x = copy_ex - copy_sx;
    unsigned int copy_size_y = copy_ey - copy_sy;

    //now... we have to compute the window
    double ll_x, ll_y, ur_x, ur_y;
    mapToWorld(copy_sx, copy_sy, ll_x, ll_y);
    mapToWorld(copy_ex, copy_ey, ur_x, ur_y);
    double mid_x = (ll_x + ur_x) / 2;
    double mid_y = (ll_y + ur_y) / 2;
    double size_x = ur_x - ll_x;
    double size_y = ur_y - ll_y;

    //finally... we'll clear all non-lethal costs in the area that could be affected by the map update
    //we'll reinflate after the map update is complete
    clearNonLethal(mid_x, mid_y, size_x, size_y);

    //copy static data into the costmap
    unsigned int start_index = start_y * size_x_ + start_x;
    unsigned char* costmap_index = costmap_ + start_index;
    std::vector<unsigned char>::const_iterator static_data_index =  static_data.begin();
    for(unsigned int i = 0; i < data_size_y; ++i){
      for(unsigned int j = 0; j < data_size_x; ++j){
        //check if the static value is above the unknown or lethal thresholds
        if(track_unknown_space_ && unknown_cost_value_ > 0 && *static_data_index == unknown_cost_value_)
          *costmap_index = NO_INFORMATION;
        else if(*static_data_index >= lethal_threshold_)
          *costmap_index = LETHAL_OBSTACLE;
        else
          *costmap_index = FREE_SPACE;

        ++costmap_index;
        ++static_data_index;
      }
      costmap_index += size_x_ - data_size_x;
    }

    //now, we're ready to reinflate obstacles in the window that has been updated
    //we won't clear all non-lethal obstacles first because the static map update
    //may have included non-lethal costs
    reinflateWindow(mid_x, mid_y, size_x, size_y, false);


    //we also want to keep a copy of the current costmap as the static map... we'll only need to write the region that has changed
    copyMapRegion(costmap_, copy_sx, copy_sy, size_x_, static_map_, copy_sx, copy_sy, size_x_, copy_size_x, copy_size_y);

  }
  void Costmap2D::raytraceFreespace(const Observation& clearing_observation){
    //create the functor that we'll use to clear cells from the costmap
    ClearCell clearer(costmap_);

    double ox = clearing_observation.origin_.x;
    double oy = clearing_observation.origin_.y;
    sensor_msgs::PointCloud cloud = clearing_observation.cloud_;

    //get the map coordinates of the origin of the sensor 
    unsigned int x0, y0;
    if(!worldToMap(ox, oy, x0, y0)){
      ROS_WARN("The origin for the sensor at (%.2f, %.2f) is out of map bounds. So, the costmap cannot raytrace for it.", ox, oy);
      return;
    }

    //we can pre-compute the enpoints of the map outside of the inner loop... we'll need these later
    double map_end_x = origin_x_ + getSizeInMetersX();
    double map_end_y = origin_y_ + getSizeInMetersY();

    //for each point in the cloud, we want to trace a line from the origin and clear obstacles along it
    for(unsigned int i = 0; i < cloud.points.size(); ++i){
      double wx = cloud.points[i].x;
      double wy = cloud.points[i].y;

      //now we also need to make sure that the enpoint we're raytracing 
      //to isn't off the costmap and scale if necessary
      double a = wx - ox;
      double b = wy - oy;

      //the minimum value to raytrace from is the origin
      if(wx < origin_x_){
        double t = (origin_x_ - ox) / a;
        wx = origin_x_;
        wy = oy + b * t;
      }
      if(wy < origin_y_){
        double t = (origin_y_ - oy) / b;
        wx = ox + a * t;
        wy = origin_y_;
      }

      //the maximum value to raytrace to is the end of the map
      if(wx > map_end_x){
        double t = (map_end_x - ox) / a;
        wx = map_end_x;
        wy = oy + b * t;
      }
      if(wy > map_end_y){
        double t = (map_end_y - oy) / b;
        wx = ox + a * t;
        wy = map_end_y;
      }

      //now that the vector is scaled correctly... we'll get the map coordinates of its endpoint
      unsigned int x1, y1;

      //check for legality just in case
      if(!worldToMap(wx, wy, x1, y1))
        continue;

      unsigned int cell_raytrace_range = cellDistance(clearing_observation.raytrace_range_);

      //and finally... we can execute our trace to clear obstacles along that line
      raytraceLine(clearer, x0, y0, x1, y1, cell_raytrace_range);
    }
  }
Esempio n. 29
0
bool GlobalPlanner::makePlan(const geometry_msgs::PoseStamped& start, const geometry_msgs::PoseStamped& goal,
                           double tolerance, std::vector<geometry_msgs::PoseStamped>& plan) {
    boost::mutex::scoped_lock lock(mutex_);
    if (!initialized_) {
        ROS_ERROR(
                "This planner has not been initialized yet, but it is being used, please call initialize() before use");
        return false;
    }

    //clear the plan, just in case
    plan.clear();

    ros::NodeHandle n;
    std::string global_frame = frame_id_;

    //until tf can handle transforming things that are way in the past... we'll require the goal to be in our global frame
    if (tf::resolve(tf_prefix_, goal.header.frame_id) != tf::resolve(tf_prefix_, global_frame)) {
        ROS_ERROR(
                "The goal pose passed to this planner must be in the %s frame.  It is instead in the %s frame.", tf::resolve(tf_prefix_, global_frame).c_str(), tf::resolve(tf_prefix_, goal.header.frame_id).c_str());
        return false;
    }

    if (tf::resolve(tf_prefix_, start.header.frame_id) != tf::resolve(tf_prefix_, global_frame)) {
        ROS_ERROR(
                "The start pose passed to this planner must be in the %s frame.  It is instead in the %s frame.", tf::resolve(tf_prefix_, global_frame).c_str(), tf::resolve(tf_prefix_, start.header.frame_id).c_str());
        return false;
    }

    double wx = start.pose.position.x;
    double wy = start.pose.position.y;

    unsigned int start_x_i, start_y_i, goal_x_i, goal_y_i;
    double start_x, start_y, goal_x, goal_y;

    if (!costmap_->worldToMap(wx, wy, start_x_i, start_y_i)) {
        ROS_WARN(
                "The robot's start position is off the global costmap. Planning will always fail, are you sure the robot has been properly localized?");
        return false;
    }
    if(old_navfn_behavior_){
        start_x = start_x_i;
        start_y = start_y_i;
    }else{
        worldToMap(wx, wy, start_x, start_y);
    }

    wx = goal.pose.position.x;
    wy = goal.pose.position.y;

    if (!costmap_->worldToMap(wx, wy, goal_x_i, goal_y_i)) {
        ROS_WARN_THROTTLE(1.0,
                "The goal sent to the global planner is off the global costmap. Planning will always fail to this goal.");
        return false;
    }
    if(old_navfn_behavior_){
        goal_x = goal_x_i;
        goal_y = goal_y_i;
    }else{
        worldToMap(wx, wy, goal_x, goal_y);
    }

    //clear the starting cell within the costmap because we know it can't be an obstacle
    tf::Stamped<tf::Pose> start_pose;
    tf::poseStampedMsgToTF(start, start_pose);
    clearRobotCell(start_pose, start_x_i, start_y_i);

    int nx = costmap_->getSizeInCellsX(), ny = costmap_->getSizeInCellsY();

    //make sure to resize the underlying array that Navfn uses
    p_calc_->setSize(nx, ny);
    planner_->setSize(nx, ny);
    path_maker_->setSize(nx, ny);
    potential_array_ = new float[nx * ny];

    outlineMap(costmap_->getCharMap(), nx, ny, costmap_2d::LETHAL_OBSTACLE);

    bool found_legal = planner_->calculatePotentials(costmap_->getCharMap(), start_x, start_y, goal_x, goal_y,
                                                    nx * ny * 2, potential_array_);

    if(!old_navfn_behavior_)
        planner_->clearEndpoint(costmap_->getCharMap(), potential_array_, goal_x_i, goal_y_i, 2);
    if(publish_potential_)
        publishPotential(potential_array_);

    if (found_legal) {
        //extract the plan
        if (getPlanFromPotential(start_x, start_y, goal_x, goal_y, goal, plan)) {
            //make sure the goal we push on has the same timestamp as the rest of the plan
            geometry_msgs::PoseStamped goal_copy = goal;
            goal_copy.header.stamp = ros::Time::now();
            plan.push_back(goal_copy);
        } else {
            ROS_ERROR("Failed to get a plan from potential when a legal potential was found. This shouldn't happen.");
        }
    }else{
        ROS_ERROR("Failed to get a plan.");
    }

    // add orientations if needed
    orientation_filter_->processPath(start, plan);
    
    //publish the plan for visualization purposes
    publishPlan(plan);
    delete potential_array_;
    return !plan.empty();
}
bool GlobalPlanner::makePlan(const geometry_msgs::PoseStamped& start, const geometry_msgs::PoseStamped& goal,
                           double tolerance, std::vector<geometry_msgs::PoseStamped>& plan) {
    boost::mutex::scoped_lock lock(mutex_);
    if (!initialized_) {
        ROS_ERROR(
                "This planner has not been initialized yet, but it is being used, please call initialize() before use");
        return false;
    }

    //clear the plan, just in case
    plan.clear();

    ros::NodeHandle n;
    std::string global_frame = frame_id_;

    //until tf can handle transforming things that are way in the past... we'll require the goal to be in our global frame
    if (tf::resolve(tf_prefix_, goal.header.frame_id) != tf::resolve(tf_prefix_, global_frame)) {
        ROS_ERROR(
                "The goal pose passed to this planner must be in the %s frame.  It is instead in the %s frame.", tf::resolve(tf_prefix_, global_frame).c_str(), tf::resolve(tf_prefix_, goal.header.frame_id).c_str());
        return false;
    }

    if (tf::resolve(tf_prefix_, start.header.frame_id) != tf::resolve(tf_prefix_, global_frame)) {
        ROS_ERROR(
                "The start pose passed to this planner must be in the %s frame.  It is instead in the %s frame.", tf::resolve(tf_prefix_, global_frame).c_str(), tf::resolve(tf_prefix_, start.header.frame_id).c_str());
        return false;
    }

    double wx = start.pose.position.x;
    double wy = start.pose.position.y;

    unsigned int start_x_i, start_y_i, goal_x_i, goal_y_i;
    double start_x, start_y, goal_x, goal_y;

    if (!costmap_->worldToMap(wx, wy, start_x_i, start_y_i)) {
        ROS_WARN(
                "The robot's start position is off the global costmap. Planning will always fail, are you sure the robot has been properly localized?");
        return false;
    }
    if(old_navfn_behavior_){
        start_x = start_x_i;
        start_y = start_y_i;
    }else{
        worldToMap(wx, wy, start_x, start_y);
    }

    wx = goal.pose.position.x;
    wy = goal.pose.position.y;

    if (!costmap_->worldToMap(wx, wy, goal_x_i, goal_y_i)) {
        ROS_WARN(
                "The goal sent to the navfn planner is off the global costmap. Planning will always fail to this goal.");
        return false;
    }
    if(old_navfn_behavior_){
        goal_x = goal_x_i;
        goal_y = goal_y_i;
    }else{
        worldToMap(wx, wy, goal_x, goal_y);
    }

    //clear the starting cell within the costmap because we know it can't be an obstacle
    tf::Stamped<tf::Pose> start_pose;
    tf::poseStampedMsgToTF(start, start_pose);
    clearRobotCell(start_pose, start_x_i, start_y_i);

    int nx = costmap_->getSizeInCellsX(), ny = costmap_->getSizeInCellsY();

    //make sure to resize the underlying array that Navfn uses
    p_calc_->setSize(nx, ny);
    planner_->setSize(nx, ny);
    path_maker_->setSize(nx, ny);
    potential_array_ = new float[nx * ny];

    outlineMap(costmap_->getCharMap(), nx, ny, costmap_2d::LETHAL_OBSTACLE);
    
    
     timespec time1, time2;
    /* take current time here */
    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time1);

    bool found_legal = planner_->calculatePotentials(costmap_->getCharMap(), start_x, start_y, goal_x, goal_y,
                                                    nx * ny * 2, potential_array_);

    if(!old_navfn_behavior_)
        planner_->clearEndpoint(costmap_->getCharMap(), potential_array_, goal_x_i, goal_y_i, 2);
    if(publish_potential_)
        publishPotential(potential_array_);

    if (found_legal) {
        //extract the plan
        if (getPlanFromPotential(start_x, start_y, goal_x, goal_y, goal, plan)) {
            //make sure the goal we push on has the same timestamp as the rest of the plan
            geometry_msgs::PoseStamped goal_copy = goal;
            goal_copy.header.stamp = ros::Time::now();
            plan.push_back(goal_copy);
        } else {
            ROS_ERROR("Failed to get a plan from potential when a legal potential was found. This shouldn't happen.");
        }
    }else{
        ROS_ERROR("Failed to get a plan.");
    }

    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time2);
    std::cout<<"time to generate best global path time = " << (diff(time1,time2).tv_sec)*1e3 + (diff(time1,time2).tv_nsec)*1e-6 << " microseconds" <<"\n";
    
    //data<<"["<< (diff(time1,time2).tv_sec)*1e3 + (diff(time1,time2).tv_nsec)*1e-6 ;

    // add orientations if needed
    orientation_filter_->processPath(start, plan);
    
    float path_length = 0.0;
	
	std::vector<geometry_msgs::PoseStamped>::iterator it = plan.begin();
	
	geometry_msgs::PoseStamped last_pose;
	last_pose = *it;
	it++;
	for (; it!=plan.end(); ++it) {

        std::cout<<"路径位姿点:("<<(*it).pose.position.x<<","<<(*it).pose.position.y<<")"<<"\n";
	   path_length += hypot(  (*it).pose.position.x - last_pose.pose.position.x, 
		                 (*it).pose.position.y - last_pose.pose.position.y );
	   last_pose = *it;
	}
	std::cout <<"------The global path length: "<< path_length<< " meters------"<<"\n";
    //data <<"["<< path_length<< ",";
    
    //data<< (diff(time1,time2).tv_sec)*1e3 + (diff(time1,time2).tv_nsec)*1e-6<<"]"<<"\n" ;

    std::cout <<"["<< path_length<< ",";
    
    std::cout<< (diff(time1,time2).tv_sec)*1e3 + (diff(time1,time2).tv_nsec)*1e-6<<"]"<<"\n" ;
    
    //publish the plan for visualization purposes
    publishPlan(plan);
    delete potential_array_;
    return !plan.empty();
}