Ask Your Question

Navigating a robot using same path every time

asked 2016-04-29 06:03:47 -0600

murdock gravatar image

updated 2016-05-09 13:19:30 -0600


I am not sure if I am clear here with my question. What I want to do is create a map with couple of obstacles in it and to make the robot drive around them, making an 8 shape. Something similar to the picture. Just imagine that in those 2 loops, there would be an obstacle. I am probably using wrong terms to find a similar example. I want the robot to be always driving that shape too (this is necessary for tests). Which tutorials could provide me with some samples? Right now I am using teb_local_planner. One of the requirements for the robot is that it also has to localize itself while doing this.

image description

Thank you!

EDIT So I have tried running samples of teb_local_planner following the Global Plan (Via-Points), however it didnt work for me.

I couldnt git clone the newest version of teb_local_planner because I already had it in my ~/catkin_ws directory (or at least I got git FATAL error), however I ran the rosdep install in the same folder and it didnt complain. How do I know that it didnt work in the end? I could never see neither the global_plan_viapoint_sep parameter nor weight_viapoint when I ran the roslaunch teb_local_planner test_optim_node.launch. Heres proof:

I tried setting it just in rqt config file, but to no avail.

edit retag flag offensive close merge delete


According to your new edit: the issue is not related to your original question, but it is much more concerned with: how to compile a package from source. If you cannot see the parameter, you do not have Version 0.4 properly installed. Of course, you shouldn't have two copies of the package at once.

croesmann gravatar image croesmann  ( 2016-05-09 13:43:32 -0600 )edit

Here is a similar question to the missing version. It still takes some time until new packages are synchronized in ROS.

croesmann gravatar image croesmann  ( 2016-05-09 13:44:37 -0600 )edit

You can find information on how to compile from source here. Delete any duplicate teb_local_planner package first! If you want to be 100% sure, also invoke sudo apt-get remove ros-indigo-teb-local-planner first.

croesmann gravatar image croesmann  ( 2016-05-09 13:46:53 -0600 )edit

2 Answers

Sort by ยป oldest newest most voted

answered 2016-04-29 06:55:36 -0600

croesmann gravatar image

updated 2016-04-29 07:08:44 -0600

To my knowledge, move_base is currently not intended to provide / follow a global plan endlessly, since it switches between three states: Planning (globally), Controlling (locally, determining velocity commands) and Clearing. Obviously, you require a goal point for the global plan.

You can try the following:

First, we follow the 2 loops once:

Write your own global planner that computes your "predefined" plan of the 8-shape. Create your two loops by choosing an appropriate discretization (maybe every 0.2/0.3 cm, or better with a parameter). Of course, you should generate your intermediate points computer-aided. Writing a global planner is not hard. You must implement the required interface and export your compiled library as plugin. A tutorial can be found here: Writing A Global Path Planner As Plugin in ROS. You can also check out the carrot_planner example (click here for indigo source).

Then try which of your local planners performs best. Version 0.4 of the teb_local_planner provides a path following mode which could be really helpful here!

After configuring your planners for move_base, you must invoke move_base by sending a navigation goal in order to switch the state machine to the Planning state.

Multiple loops:

  • If you want to follow the path endlessly, you can write a small node that renews the navigation goal, if the robot has reached its goal. But here you will always have a deceleration and acceleration phase each time.
  • Maybe you can renew your global plan more often causing the state machine to switch between states planning and controlling. But this shouldn't be a problem since this is common practice with the default GlobalPlanner (parameter planning_frequency). This way it should be possible to follow the path endlessly without the decelaration and acceleration phase. But you might need to adjust your predefined path (incl goal) according to the current robot position.
  • If you just want to repeat a few times, you could replicate your global plan in the global planner multiple times (e.g. with a parameter).
edit flag offensive delete link more


Correct me if I am wrong, but from what I gathered I may just be able to use teb_local_planner's path following mode and that would solve my problem?

P.S. As always, thank you for your answers.

murdock gravatar image murdock  ( 2016-04-30 16:00:27 -0600 )edit

yeah, but in conjunction with a global planner which provides your predefined path. You can built upon the source code posted by Steven_Daniluk.

croesmann gravatar image croesmann  ( 2016-05-02 01:54:17 -0600 )edit

answered 2016-05-01 09:30:00 -0600

Steven_Daniluk gravatar image

I've actually wrote a planner that does something similar, so I'll post the code for the initialize and makePlan methods for you, or anyone that is interested. It's nothing too sophisticated, but it works for just following a loop. By following the tutorial for writing a global planner you should be able to fill in the header file and create the plugin.

The initialize method loads a tab delineated text file with X and Y coordinates for the path you want to follow, and stores this as the path.

The parameters that get loaded are for setting the filename of the text file with coordinates, the package it resides in, and also how far apart points are spaced in your text file, and how far ahead you want to generate the plan. If planning_distance_ is negative, then it will generate a plan for the entire loop (minus 0.5m, otherwise move_base will think its reached its goal).

    void LoopPlanner::initialize(std::string name, costmap_2d::Costmap2DROS* costmap_ros){
      costmap_ros_ = costmap_ros;

      ros::NodeHandle private_nh("~/" + name);

      // Get parameters
      private_nh.param("pt_spacing", pt_spacing_, 0.01);
      private_nh.param("planning_distance", planning_distance_, 2.0);
      if (!private_nh.getParam("path_filename", path_filename_)){
        ROS_ERROR("Failed to get param 'path_filename'. A text file with coordinates is necessary for this planner to run.");
      }// end if
      if (!private_nh.getParam("path_package", path_package_)){
        ROS_ERROR("Failed to get param 'path_package'. This is necessary in order to find the path file.");
      }// end if

      // Set inputted file name and path
      std::string full_file = ros::package::getPath(path_package_) + "/" + path_filename_;

      // Load file
      std::ifstream is(full_file.c_str());
      std::istream_iterator<double> start(is), end;
      std::vector<double> data(start, end);

      // Resize vectors appropriately
      int columns = 2;
      num_pts_ = data.size()/columns;

      // Sort data columns into vectors
      for (int i =0 ; i < num_pts_ ; i++){
        path_x_[i] = data[columns*i];
        path_y_[i] =*i+1);
       }// end for

      initialized_ = true;

      ROS_INFO("Created global_planner loop_planner");
      ROS_INFO("Loaded path file");
      ROS_WARN("This planner has already been initialized... doing nothing");
  }// end initialize

Then in the makePlan method it finds the closest point on the path to the starting point, then builds the plan from there. It doesn't check if any of the points are valid in the costmap, since for my use I always knew they were valid.

    bool LoopPlanner::makePlan(const geometry_msgs::PoseStamped& start, 
    const geometry_msgs::PoseStamped& goal, std::vector<geometry_msgs::PoseStamped>& plan){

    // Check the initialization
      ROS_ERROR("The planner has not been initialized, please call initialize() to use the planner");
      return false;
    }// end if

    // Make sure the plan vector is empty

    // Check if goal and costmap frame ID's match
    if(goal.header.frame_id != costmap_ros_->getGlobalFrameID()){
      ROS_ERROR("This planner as configured will only accept goals in the %s frame, but a goal was sent in the %s frame.", 
          costmap_ros_->getGlobalFrameID().c_str(), goal.header.frame_id.c_str());
      return false;
    }// end if

    ROS_DEBUG("Starting path generation");
    ROS_DEBUG("Finding closest point on path");

    // Create vectors to hold the difference to each point
    std::vector ...
edit flag offensive delete link more


hello, could you provide an example of the text file with coordinates? Id like to see the correct format

aarontan gravatar image aarontan  ( 2018-06-29 13:17:20 -0600 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools



Asked: 2016-04-29 06:03:47 -0600

Seen: 1,985 times

Last updated: May 09 '16