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;
}
void StaticLayer::updateBounds(double robot_x, double robot_y, double robot_yaw, double* min_x, double* min_y,
                               double* max_x, double* max_y)
{
  if (!map_received_ || !(has_updated_data_ || has_extra_bounds_))
    return;

  useExtraBounds(min_x, min_y, max_x, max_y);

  double wx, wy;

  mapToWorld(x_, y_, wx, wy);
  *min_x = std::min(wx, *min_x);
  *min_y = std::min(wy, *min_y);

  mapToWorld(x_ + width_, y_ + height_, wx, wy);
  *max_x = std::max(wx, *max_x);
  *max_y = std::max(wy, *max_y);

  has_updated_data_ = false;
}
Example #3
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.
	}
}
gm::Polygon cellPolygon (const nm::MapMetaData& info, const Cell& c)
{
  const float dx[4] = {0.0, 0.0, 1.0, 1.0};
  const float dy[4] = {0.0, 1.0, 1.0, 0.0};
  
  const tf::Transform trans = mapToWorld(info);
  gm::Polygon p;
  p.points.resize(4);
  for (unsigned i=0; i<4; i++) {
    tf::Point pt((c.x+dx[i])*info.resolution, (c.y+dy[i])*info.resolution, 0.0);
    tf::Point transformed = trans*pt;
    p.points[i].x = transformed.x();
    p.points[i].y = transformed.y();
    p.points[i].z = transformed.z();
  }
  return p;
}
Example #5
0
bool GlobalPlanner::getPlanFromPotential(double start_x, double start_y, double goal_x, double goal_y,
                                      const geometry_msgs::PoseStamped& goal,
                                       std::vector<geometry_msgs::PoseStamped>& plan) {
    if (!initialized_) {
        ROS_ERROR(
                "This planner has not been initialized yet, but it is being used, please call initialize() before use");
        return false;
    }

    std::string global_frame = frame_id_;

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

    std::vector<std::pair<float, float> > path;

    if (!path_maker_->getPath(potential_array_, start_x, start_y, goal_x, goal_y, path)) {
        ROS_ERROR("NO PATH!");
        return false;
    }

    ros::Time plan_time = ros::Time::now();
    for (int i = path.size() -1; i>=0; i--) {
        std::pair<float, float> point = path[i];
        //convert the plan to world coordinates
        double world_x, world_y;
        mapToWorld(point.first, point.second, world_x, world_y);

        geometry_msgs::PoseStamped pose;
        pose.header.stamp = plan_time;
        pose.header.frame_id = global_frame;
        pose.pose.position.x = world_x;
        pose.pose.position.y = world_y;
        pose.pose.position.z = 0.0;
        pose.pose.orientation.x = 0.0;
        pose.pose.orientation.y = 0.0;
        pose.pose.orientation.z = 0.0;
        pose.pose.orientation.w = 1.0;
        plan.push_back(pose);
    }
    if(old_navfn_behavior_){
            plan.push_back(goal);
    }
    return !plan.empty();
}
gm::Polygon gridPolygon (const nm::MapMetaData& info)
{
  const float x[4] = {0.0, 0.0, 1.0, 1.0};
  const float y[4] = {0.0, 1.0, 1.0, 0.0};

  const tf::Transform trans = mapToWorld(info);
  gm::Polygon p;
  p.points.resize(4);

  for (unsigned i=0; i<4; i++) {
    tf::Point pt(x[i]*info.resolution*info.width, y[i]*info.resolution*info.height, 0.0);
    tf::Point transformed=trans*pt;
    p.points[i].x = transformed.x();
    p.points[i].y = transformed.y();
    p.points[i].z = transformed.z();
  }
  return p;
}
Example #7
0
bool DynamicEDTOctomap::checkConsistency() const {

	for(octomap::KeyBoolMap::const_iterator it = octree->changedKeysBegin(), end=octree->changedKeysEnd(); it!=end; ++it){
		//std::cerr<<"Cannot check consistency, you must execute the update() method first."<<std::endl;
		return false;
	}

	for(int x=0; x<sizeX; x++){
		for(int y=0; y<sizeY; y++){
			for(int z=0; z<sizeZ; z++){

				octomap::point3d point;
				mapToWorld(x,y,z,point);
				octomap::OcTreeNode* node = octree->search(point);

				bool mapOccupied = isOccupied(x,y,z);
				bool treeOccupied = false;
				if(node){
					treeOccupied = octree->isNodeOccupied(node);
				} else {
					if(unknownOccupied)
						treeOccupied = true;
				}

				if(mapOccupied != treeOccupied){
					//std::cerr<<"OCCUPANCY MISMATCH BETWEEN TREE AND MAP at "<<x<<","<<y<<","<<z<<std::endl;
					//std::cerr<<"Tree "<<treeOccupied<<std::endl;
					//std::cerr<<"Map "<<mapOccupied<<std::endl;
					return false;
				}
			}
		}
	}

	return true;
}
  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);

  }
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;
}
Example #10
0
bool VoronoiPlanner::computePlan(costmap_2d::Costmap2D* costmap_, DynamicVoronoi * voronoi_,
                const geometry_msgs::PoseStamped& start,
                const geometry_msgs::PoseStamped& goal, double tolerance,
                std::vector<geometry_msgs::PoseStamped>& plan) {

        //Sure that plan is clear
        plan.clear();

        ros::NodeHandle n;

        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;
        }
        worldToMap(costmap_, 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;
        }
        worldToMap(costmap_, wx, wy, goal_x, goal_y);

        clearRobotCell(costmap_, start_x_i, start_y_i);
	bool ** map;
        computeVoronoi(voronoi_, costmap_, map);

        ros::Time t_b = ros::Time::now();
        ros::Time t = ros::Time::now();

        std::vector<std::pair<float, float> > path1;
        std::vector<std::pair<float, float> > path2;
        std::vector<std::pair<float, float> > path3;

	ROS_INFO("start_x %f, start_y %f", start_x, start_y);

        bool res1 = false, res2 = false, res3 = false;

	// If goal not are in cell of the vornoi diagram, we have that best findPath of goal to voronoi diagram without have a cell occupancie
	if (!voronoi_->isVoronoi(goal_x, goal_y)) {
                res3 = computePath(&path3, goal_x, goal_y, start_x, start_y, voronoi_, 0,
                                1);
                std::cout << "computePath goal to VD " << res3 << std::endl;
                goal_x = std::get < 0 > (path3[path3.size() - 1]);
                goal_y = std::get < 1 > (path3[path3.size() - 1]);

		ROS_INFO("Is voronoi goal compute %d", voronoi_->isVoronoi(goal_x, goal_y));		

                std::reverse(path3.begin(), path3.end());
        }

        if (!voronoi_->isVoronoi(start_x, start_y)) {
                res1 = computePath(&path1, start_x, start_y, goal_x, goal_y, voronoi_, 0,
                                1);
                std::cout << "computePath start to VD " << res1 << std::endl;
                start_x = std::get < 0 > (path1[path1.size() - 1]);
                start_y = std::get < 1 > (path1[path1.size() - 1]);

		ROS_INFO("Is voronoi start compute %d", voronoi_->isVoronoi(start_x, start_y));		
        }
	
	res2 = computePath(&path2, start_x, start_y, goal_x, goal_y, voronoi_, 1, 0);
        ROS_INFO("computePath %d", res2);

        if (!(res1 && res2 && res3)) {
                ROS_INFO("Failed to compute full path");
        }

        path1.insert(path1.end(), path2.begin(), path2.end());
        path1.insert(path1.end(), path3.begin(), path3.end());

        /*for (int i = 0; i < path1.size(); i++) {
                int x = std::get < 0 > (path1[i]);
                int y = std::get < 1 > (path1[i]);

                if (x > 0 && y > 0)
                        map[x][y] = 1;
        }*/

	smoothPath(&path1);

        for (int i = 0; i < path1.size(); i++) {

                geometry_msgs::PoseStamped new_goal = goal;
                tf::Quaternion goal_quat = tf::createQuaternionFromYaw(1.54);

                new_goal.pose.position.x = std::get < 0 > (path1[i]);
                new_goal.pose.position.y = std::get < 1 > (path1[i]);

                mapToWorld(costmap_, new_goal.pose.position.x, new_goal.pose.position.y,
                                new_goal.pose.position.x, new_goal.pose.position.y);

                new_goal.pose.orientation.x = goal_quat.x();
                new_goal.pose.orientation.y = goal_quat.y();
                new_goal.pose.orientation.z = goal_quat.z();
                new_goal.pose.orientation.w = goal_quat.w();
                plan.push_back(new_goal);
        }

        ROS_INFO("\nTime to get plan: %f sec\n", (ros::Time::now() - t_b).toSec());

        return !plan.empty();
}
Example #11
0
bool EpicNavCorePlugin::makePlan(const geometry_msgs::PoseStamped &start,
        const geometry_msgs::PoseStamped &goal,
        std::vector<geometry_msgs::PoseStamped> &plan)
{
    if (!initialized) {
        ROS_ERROR("Error[EpicNavCorePlugin::makePlan]: EpicNavCorePlugin has not been initialized yet.");
        return false;
    }

    // Set the goal location on the potential map.
    unsigned int x_coord = 0;
    unsigned int y_coord = 0;

    if (!costmap->worldToMap(goal.pose.position.x, goal.pose.position.y, x_coord, y_coord)) {
        ROS_WARN("Warning[EpicNavCorePlugin::makePlan]: Could not convert goal to cost map location.");
        x_coord = 0;
        y_coord = 0;
    }

    setGoal(x_coord, y_coord);

    ROS_INFO("Information[EpicNavCorePlugin::makePlan]: Solving harmonic function...");
    int result = harmonic_complete_gpu(&harmonic, NUM_THREADS_GPU);

    if (result != EPIC_SUCCESS) {
        ROS_WARN("Warning[EpicNavCorePlugin::makePlan]: Could not execute GPU version of 'epic' library.");
        ROS_WARN("Warning[EpicNavCorePlugin::makePlan]: Trying CPU fallback...");

        result = harmonic_complete_cpu(&harmonic);
    }

    if (result == EPIC_SUCCESS) {
        ROS_INFO("Information[EpicNavCorePlugin::makePlan]: Successfully solved harmonic function!");
    } else {
        ROS_ERROR("Error[EpicNavCorePlugin::makePlan]: Failed to solve harmonic function.");
        return false;
    }

    //pub_potential.publish(harmonic.u);

    plan.clear();
    plan.push_back(start);

    /*
    if (!costmap->worldToMap(start.pose.position.x, start.pose.position.y, xCoord, yCoord)) {
        ROS_WARN("Warning[EpicNavCorePlugin::makePlan]: Could not convert start to cost map location.");
        xCoord = 0;
        yCoord = 0;
    }
    */

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

    float step_size = 0.05f;
    float cd_precision = 0.5f;
    unsigned int max_length = harmonic.m[0] * harmonic.m[1] / step_size;

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

    result = harmonic_compute_path_2d_cpu(&harmonic, x, y, step_size, cd_precision, max_length, k, raw_plan);

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

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

        return false;
    }

    geometry_msgs::PoseStamped new_goal = goal;

    for (unsigned int i = 1; i < k; i++) {
        float x = raw_plan[2 * i + 0];
        float y = raw_plan[2 * i + 1];

        float plan_theta = std::atan2(y - raw_plan[2 * (i - 1) + 1], x - raw_plan[2 * (i - 1) + 0]);

        float plan_x = 0.0f;
        float plan_y = 0.0f;

        mapToWorld(x, y, plan_x, plan_y);

        new_goal.pose.position.x = plan_x;
        new_goal.pose.position.y = plan_y;
        new_goal.pose.orientation = tf::createQuaternionMsgFromYaw(plan_theta);

        plan.push_back(new_goal);
    }

    delete [] raw_plan;
    raw_plan = nullptr;

    plan.push_back(goal);

    publishPlan(plan);

    return true;
}