ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange |
1 | initial version |
Ok. First off, I'll answer the question about turning at a really low angular speed. This is just a bug which should be fixed in the next patch release of navigation. There's a ticket to track it here: https://kforge.ros.org/navigation/trac/ticket/2.
As for the broader question of how to tune the navigation stack, I'll do my best below to outline how I typically go about things. With that said, its a bit different for every robot. So, with no further ado, basic navigation tuning:
This guide seeks to give some standard advice on how to tune the ROS Navigation Stack on a robot. This guide is in no way comprehensive, but should give some insight into the process. I'd also encourage folks to make sure they've read the ROS Navigation Tutorial before this post as it gives a good overview on setting the navigation stack up on a robot wheras this guide just gives advice on the process.
The large majority of the problems I run into when tuning the navigation stack on a new robot lie in areas outside of tuning parameters on the local planner. Things are often wrong with the odometry of the robot, localization, sensors, and other pre-requisites for running navigation effectively. So, the first thing I do is to make sure that the robot itself is navigation ready. This consists of three component checks: range sensors, odometry, and localization.
If the robot isn't getting information from its range sensors, such as lasers, then nothing with navigation will work. I'll make sure that I can view sensor information in rviz, that it looks relatively correct, and that its coming in at the expected rate.
Often, I'll have a lot of trouble getting a robot to localize correctly. It will constantly get lost and I'll spend a lot of time mucking with the parameters for AMCL only to find that the real culprit is the robot's odometry. As such, I always run two sanity checks to make sure that I believe the odometry of a robot.
The first test checks how reasonable the odometry is for rotation. I open up rviz, set the frame to "odom," display the laser scan the robot provides, set the decay time on that topic high (something like 20 seconds), and perform an in-place rotation. Then, I look at how closely the scans match each other on subsequent rotations. Ideally, the scans will fall right on top of each other, but some rotational drift is expected, so I just make sure that the scans aren't off by more than a degree or two.
The next test is a sanity check on odometry for translation. I'll set up rviz the same way with the robot a few meters away from a wall. Then, I'll drive the robot straight at the wall and look at the thickness of the wall as reported by the aggregated laser scans in rviz. Ideally, the wall should look like a single scan but I just make sure that it doesn't have a thickness of more than a few centimeters. If you drive a meter towards a wall and get scans spread out over half a meter though, something is likely wrong with the odometry.
Assuming that both odometry and a laser scanner are performing reasonably, making a map and tuning AMCL normally isn't too bad. First, I'll run either gmapping or karto and joystick the robot around to generate a map. Then, I'll use that map with AMCL and make sure that the robot stays localized. If the odometry for the robot that I'm running on isn't very good, I'll play around a bit with the odometry model parameters for AMCL. A good test for the whole system is to make sure that laser scans and the map can be visualized in the "map" frame in rviz and that the laser scans match up well with the map of the enviroment.
Once I'm satisfied that the robot satisfies the prerequisites for navigation, I like to make sure that the costmap is setup and configured properly. I'll leave details on how to configure things for the costmap to the ROS Navigation Tutorial and costmap_2d documentation, but I'll give some tips on the things that I often do. Some things that I find useful for tuning the costmap:
expected_update_rate
parameter for each observation source based on the rate at which the sensor actually publishes. I normally give a fair amount of tolerance here, putting the period for the check at twice what I'd expect, but its nice to receive warnings from navigation when a sensor falls way below its expected rate.transform_tolerance
parameter appropriately for the system. Its nice to check what the expected latency is for a transform from the "base_link" frame to the "map" frame using tf. I typically use tf_monitor to look at the delay for the system and set the parameter conservatively off of that. Also, if the delay reported by tf_monitor is sufficiently large, I might poke around a bit to see what's causing the latency. This sometimes leads me to find issues with how transforms are being published for a given robot.
map_update_rate
parameter. When doing this, however, I take into account the fact that this will cause a delay in how quickly sensor data makes it into the costmap which, in turn, slows the speed at which the robot reacts to obstacles.
publish_frequency
parameter is useful for visualizing the costmap in rviz. However, especially for large global maps, the parameter can cause things to run slowly. In production systems, I consider turning down the rate at which the costmap is published and when I need to visualize very large maps, I make sure to set the rate really low.voxel_grid
or costmap
model for the costmap depends largely on the sensor suite that the robot has. Tuning the costmap for a 3D-based costmap is more involved as considerations about unknown space really come into play. If the robot I'm using just has a planar laser, I always use the costmap
model for the map.local_costmap_params.yaml
file over my global_costmap_params.yaml
file and change the the width
and height
of the map to be something more like 10 meters. This is a really easy way to get things up and running if you want to tune navigation independent of localization performance.voxel_grid
model for the costmap, I make sure to look at the unknown space visualization to see that unknown space is being cleared out in a reasonable way. A good check I do to see if obstacles are being cleared out correctly from the costmap is to simply walk in front of the robot and see if it both successfully sees me and clears me out. For details on the topics published by the costmap to rviz, check out the navigation with rviz tutorial.
move_base
node, but not sending it a goal and looking at load. If the computer is bogged down at this point, I know I need to make some CPU saving parameter tweaks if I want any chance of running the planners.
If I'm satisfied that things up through the costmap are behaving satisfactorily, I'll move on to tuning parameters for the local planner. On robots that have reasonable acceleration limits, I typically use the dwa_local_planner, on those that have lower acceleration limits and would benefit from a rollout that takes acceleration limits into account at every step, I'll use the base_local_planner . Tuning the dwa_local_planner is more pleasant than tuning the base_local_planner because its parameters are dynamically_reconfigurable, though adding dynamic_reconfigure across the board for the navigation stack is on the roadmap. Ok, on to tips for the planners:
dwa
set to false. After setting dwa
to true
, I'll also make sure to update the vx_samples
parameter to something between 8 and 15 depending on the processing power available. This will allow for non-circular curves to be generated in the rollout.
sim_granularity
parameter a bit to save some cycles.path_distance_bias
and goal_distance_bias
parameters on the planners very much. When I do, its normally because I'm trying to restrict the freedom of the local planner to leave the planned path to work with a global planner other than NavFn. Turning the path_distance_bias
parameter up, will make the robot follow the path more closely at the expense of moving towards the goal quickly. If this weight is set too high, the robot will refuse to move because the cost of moving is greater than staying at its location on the path. meter_scoring
parameter to true. This makes it so distances in the cost function are in meters instead of cells and also means that I can tune the cost function for one map resolution and expect reasonable behavior when I move to others. Furthermore, you can now visualize the cost function produced by the local planner in rviz by setting the publish_cost_grid
parameter to true
. (This somehow never made it into the docs, I'll get to that sometime soon). Given the cost function in meters, I can compute the tradeoff in cost of moving 1 meter towards the goal balanced against how far away I am from the planned path. This tends to give me a decent idea of how to tune things.
sim_time
parameter to different values can have a large affect on how the robot behaves. I normally set this parameter to between 1-2 seconds, where setting it higher can result in slightly smoother trajectories, making sure that the minimum velocity multiplied by the sim_period is less than twice my tolerance on a goal. Otherwise, the robot will prefer to rotate in place just outside of range of its target position rather than moving towards the goal.OK... that's basically what I've got off the top of my head. I might come back later and add to this, but, hopefully, this gives some insight into the nuances of tuning navigation.
2 | addressed a comment |
Ok. First off, I'll answer the question about turning at a really low angular speed. This is just a bug which should be fixed in the next patch release of navigation. There's a ticket to track it here: https://kforge.ros.org/navigation/trac/ticket/2.
As for the broader question of how to tune the navigation stack, I'll do my best below to outline how I typically go about things. With that said, its a bit different for every robot. So, with no further ado, basic navigation tuning:
This guide seeks to give some standard advice on how to tune the ROS Navigation Stack on a robot. This guide is in no way comprehensive, but should give some insight into the process. I'd also encourage folks to make sure they've read the ROS Navigation Tutorial before this post as it gives a good overview on setting the navigation stack up on a robot wheras this guide just gives advice on the process.
The large majority of the problems I run into when tuning the navigation stack on a new robot lie in areas outside of tuning parameters on the local planner. Things are often wrong with the odometry of the robot, localization, sensors, and other pre-requisites for running navigation effectively. So, the first thing I do is to make sure that the robot itself is navigation ready. This consists of three component checks: range sensors, odometry, and localization.
If the robot isn't getting information from its range sensors, such as lasers, then nothing with navigation will work. I'll make sure that I can view sensor information in rviz, that it looks relatively correct, and that its coming in at the expected rate.
Often, I'll have a lot of trouble getting a robot to localize correctly. It will constantly get lost and I'll spend a lot of time mucking with the parameters for AMCL only to find that the real culprit is the robot's odometry. As such, I always run two sanity checks to make sure that I believe the odometry of a robot.
The first test checks how reasonable the odometry is for rotation. I open up rviz, set the frame to "odom," display the laser scan the robot provides, set the decay time on that topic high (something like 20 seconds), and perform an in-place rotation. Then, I look at how closely the scans match each other on subsequent rotations. Ideally, the scans will fall right on top of each other, but some rotational drift is expected, so I just make sure that the scans aren't off by more than a degree or two.
The next test is a sanity check on odometry for translation. I'll set up rviz the same way with the robot a few meters away from a wall. Then, I'll drive the robot straight at the wall and look at the thickness of the wall as reported by the aggregated laser scans in rviz. Ideally, the wall should look like a single scan but I just make sure that it doesn't have a thickness of more than a few centimeters. If you drive a meter towards a wall and get scans spread out over half a meter though, something is likely wrong with the odometry.
Assuming that both odometry and a laser scanner are performing reasonably, making a map and tuning AMCL normally isn't too bad. First, I'll run either gmapping or karto and joystick the robot around to generate a map. Then, I'll use that map with AMCL and make sure that the robot stays localized. If the odometry for the robot that I'm running on isn't very good, I'll play around a bit with the odometry model parameters for AMCL. A good test for the whole system is to make sure that laser scans and the map can be visualized in the "map" frame in rviz and that the laser scans match up well with the map of the enviroment.
Once I'm satisfied that the robot satisfies the prerequisites for navigation, I like to make sure that the costmap is setup and configured properly. I'll leave details on how to configure things for the costmap to the ROS Navigation Tutorial and costmap_2d documentation, but I'll give some tips on the things that I often do. Some things that I find useful for tuning the costmap:
expected_update_rate
parameter for each observation source based on the rate at which the sensor actually publishes. I normally give a fair amount of tolerance here, putting the period for the check at twice what I'd expect, but its nice to receive warnings from navigation when a sensor falls way below its expected rate.transform_tolerance
parameter appropriately for the system. Its nice to check what the expected latency is for a transform from the "base_link" frame to the "map" frame using tf. I typically use tf_monitor to look at the delay for the system and set the parameter conservatively off of that. Also, if the delay reported by tf_monitor is sufficiently large, I might poke around a bit to see what's causing the latency. This sometimes leads me to find issues with how transforms are being published for a given robot.
map_update_rate
parameter. When doing this, however, I take into account the fact that this will cause a delay in how quickly sensor data makes it into the costmap which, in turn, slows the speed at which the robot reacts to obstacles.
publish_frequency
parameter is useful for visualizing the costmap in rviz. However, especially for large global maps, the parameter can cause things to run slowly. In production systems, I consider turning down the rate at which the costmap is published and when I need to visualize very large maps, I make sure to set the rate really low.voxel_grid
or costmap
model for the costmap depends largely on the sensor suite that the robot has. Tuning the costmap for a 3D-based costmap is more involved as considerations about unknown space really come into play. If the robot I'm using just has a planar laser, I always use the costmap
model for the map.local_costmap_params.yaml
file over my global_costmap_params.yaml
file and change the the width
and height
of the map to be something more like 10 meters. This is a really easy way to get things up and running if you want to tune navigation independent of localization performance.voxel_grid
model for the costmap, I make sure to look at the unknown space visualization to see that unknown space is being cleared out in a reasonable way. A good check I do to see if obstacles are being cleared out correctly from the costmap is to simply walk in front of the robot and see if it both successfully sees me and clears me out. For details on the topics published by the costmap to rviz, check out the navigation with rviz tutorial.
move_base
node, but not sending it a goal and looking at load. If the computer is bogged down at this point, I know I need to make some CPU saving parameter tweaks if I want any chance of running the planners.
If I'm satisfied that things up through the costmap are behaving satisfactorily, I'll move on to tuning parameters for the local planner. On robots that have reasonable acceleration limits, I typically use the dwa_local_planner, on those that have lower acceleration limits and would benefit from a rollout that takes acceleration limits into account at every step, I'll use the base_local_planner . Tuning the dwa_local_planner is more pleasant than tuning the base_local_planner because its parameters are dynamically_reconfigurable, though adding dynamic_reconfigure across the board for the navigation stack is on the roadmap. Ok, on to tips for the planners:
dwa
set to false. After setting dwa
to true
, I'll also make sure to update the vx_samples
parameter to something between 8 and 15 depending on the processing power available. This will allow for non-circular curves to be generated in the rollout.
sim_granularity
parameter a bit to save some cycles.path_distance_bias
and goal_distance_bias
parameters on the planners very much. When I do, its normally because I'm trying to restrict the freedom of the local planner to leave the planned path to work with a global planner other than NavFn. Turning the path_distance_bias
parameter up, will make the robot follow the path more closely at the expense of moving towards the goal quickly. If this weight is set too high, the robot will refuse to move because the cost of moving is greater than staying at its location on the path. meter_scoring
parameter to true. This makes it so distances in the cost function are in meters instead of cells and also means that I can tune the cost function for one map resolution and expect reasonable behavior when I move to others. Furthermore, you can now visualize the cost function produced by the local planner in rviz by setting the publish_cost_grid
parameter to true
. (This somehow never made it into the docs, I'll get to that sometime soon). Given the cost function in meters, I can compute the tradeoff in cost of moving 1 meter towards the goal balanced against how far away I am from the planned path. This tends to give me a decent idea of how to tune things.
sim_time
parameter to different values can have a large affect on how the robot behaves. I normally set this parameter to between 1-2 seconds, where setting it higher can result in slightly smoother trajectories, making sure that the minimum velocity multiplied by the sim_period is less than twice my tolerance on a goal. Otherwise, the robot will prefer to rotate in place just outside of range of its target position rather than moving towards the goal.OK... that's basically what I've got off the top of my head. I might come back later and add to this, but, hopefully, this gives some insight into the nuances of tuning navigation.
3 | linking to updated version of guide |
Note: As suggested, this guide has now moved to the ROS wiki. For an up-to-date version of the navigation tuning guide please see the Navigation Tuning Guide Tutorial.
Ok. First off, I'll answer the question about turning at a really low angular speed. This is just a bug which should be fixed in the next patch release of navigation. There's a ticket to track it here: https://kforge.ros.org/navigation/trac/ticket/2.
As for the broader question of how to tune the navigation stack, I'll do my best below to outline how I typically go about things. With that said, its a bit different for every robot. So, with no further ado, basic navigation tuning:
This guide seeks to give some standard advice on how to tune the ROS Navigation Stack on a robot. This guide is in no way comprehensive, but should give some insight into the process. I'd also encourage folks to make sure they've read the ROS Navigation Tutorial before this post as it gives a good overview on setting the navigation stack up on a robot wheras this guide just gives advice on the process.
The large majority of the problems I run into when tuning the navigation stack on a new robot lie in areas outside of tuning parameters on the local planner. Things are often wrong with the odometry of the robot, localization, sensors, and other pre-requisites for running navigation effectively. So, the first thing I do is to make sure that the robot itself is navigation ready. This consists of three component checks: range sensors, odometry, and localization.
If the robot isn't getting information from its range sensors, such as lasers, then nothing with navigation will work. I'll make sure that I can view sensor information in rviz, that it looks relatively correct, and that its coming in at the expected rate.
Often, I'll have a lot of trouble getting a robot to localize correctly. It will constantly get lost and I'll spend a lot of time mucking with the parameters for AMCL only to find that the real culprit is the robot's odometry. As such, I always run two sanity checks to make sure that I believe the odometry of a robot.
The first test checks how reasonable the odometry is for rotation. I open up rviz, set the frame to "odom," display the laser scan the robot provides, set the decay time on that topic high (something like 20 seconds), and perform an in-place rotation. Then, I look at how closely the scans match each other on subsequent rotations. Ideally, the scans will fall right on top of each other, but some rotational drift is expected, so I just make sure that the scans aren't off by more than a degree or two.
The next test is a sanity check on odometry for translation. I'll set up rviz the same way with the robot a few meters away from a wall. Then, I'll drive the robot straight at the wall and look at the thickness of the wall as reported by the aggregated laser scans in rviz. Ideally, the wall should look like a single scan but I just make sure that it doesn't have a thickness of more than a few centimeters. If you drive a meter towards a wall and get scans spread out over half a meter though, something is likely wrong with the odometry.
Assuming that both odometry and a laser scanner are performing reasonably, making a map and tuning AMCL normally isn't too bad. First, I'll run either gmapping or karto and joystick the robot around to generate a map. Then, I'll use that map with AMCL and make sure that the robot stays localized. If the odometry for the robot that I'm running on isn't very good, I'll play around a bit with the odometry model parameters for AMCL. A good test for the whole system is to make sure that laser scans and the map can be visualized in the "map" frame in rviz and that the laser scans match up well with the map of the enviroment.
Once I'm satisfied that the robot satisfies the prerequisites for navigation, I like to make sure that the costmap is setup and configured properly. I'll leave details on how to configure things for the costmap to the ROS Navigation Tutorial and costmap_2d documentation, but I'll give some tips on the things that I often do. Some things that I find useful for tuning the costmap:
expected_update_rate
parameter for each observation source based on the rate at which the sensor actually publishes. I normally give a fair amount of tolerance here, putting the period for the check at twice what I'd expect, but its nice to receive warnings from navigation when a sensor falls way below its expected rate.transform_tolerance
parameter appropriately for the system. Its nice to check what the expected latency is for a transform from the "base_link" frame to the "map" frame using tf. I typically use tf_monitor to look at the delay for the system and set the parameter conservatively off of that. Also, if the delay reported by tf_monitor is sufficiently large, I might poke around a bit to see what's causing the latency. This sometimes leads me to find issues with how transforms are being published for a given robot.
map_update_rate
parameter. When doing this, however, I take into account the fact that this will cause a delay in how quickly sensor data makes it into the costmap which, in turn, slows the speed at which the robot reacts to obstacles.
publish_frequency
parameter is useful for visualizing the costmap in rviz. However, especially for large global maps, the parameter can cause things to run slowly. In production systems, I consider turning down the rate at which the costmap is published and when I need to visualize very large maps, I make sure to set the rate really low.voxel_grid
or costmap
model for the costmap depends largely on the sensor suite that the robot has. Tuning the costmap for a 3D-based costmap is more involved as considerations about unknown space really come into play. If the robot I'm using just has a planar laser, I always use the costmap
model for the map.local_costmap_params.yaml
file over my global_costmap_params.yaml
file and change the the width
and height
of the map to be something more like 10 meters. This is a really easy way to get things up and running if you want to tune navigation independent of localization performance.voxel_grid
model for the costmap, I make sure to look at the unknown space visualization to see that unknown space is being cleared out in a reasonable way. A good check I do to see if obstacles are being cleared out correctly from the costmap is to simply walk in front of the robot and see if it both successfully sees me and clears me out. For details on the topics published by the costmap to rviz, check out the navigation with rviz tutorial.
move_base
node, but not sending it a goal and looking at load. If the computer is bogged down at this point, I know I need to make some CPU saving parameter tweaks if I want any chance of running the planners.
If I'm satisfied that things up through the costmap are behaving satisfactorily, I'll move on to tuning parameters for the local planner. On robots that have reasonable acceleration limits, I typically use the dwa_local_planner, on those that have lower acceleration limits and would benefit from a rollout that takes acceleration limits into account at every step, I'll use the base_local_planner . Tuning the dwa_local_planner is more pleasant than tuning the base_local_planner because its parameters are dynamically_reconfigurable, though adding dynamic_reconfigure across the board for the navigation stack is on the roadmap. Ok, on to tips for the planners:
dwa
set to false. After setting dwa
to true
, I'll also make sure to update the vx_samples
parameter to something between 8 and 15 depending on the processing power available. This will allow for non-circular curves to be generated in the rollout.
sim_granularity
parameter a bit to save some cycles.path_distance_bias
and goal_distance_bias
parameters on the planners very much. When I do, its normally because I'm trying to restrict the freedom of the local planner to leave the planned path to work with a global planner other than NavFn. Turning the path_distance_bias
parameter up, will make the robot follow the path more closely at the expense of moving towards the goal quickly. If this weight is set too high, the robot will refuse to move because the cost of moving is greater than staying at its location on the path. meter_scoring
parameter to true. This makes it so distances in the cost function are in meters instead of cells and also means that I can tune the cost function for one map resolution and expect reasonable behavior when I move to others. Furthermore, you can now visualize the cost function produced by the local planner in rviz by setting the publish_cost_grid
parameter to true
. (This somehow never made it into the docs, I'll get to that sometime soon). Given the cost function in meters, I can compute the tradeoff in cost of moving 1 meter towards the goal balanced against how far away I am from the planned path. This tends to give me a decent idea of how to tune things.
sim_time
parameter to different values can have a large affect on how the robot behaves. I normally set this parameter to between 1-2 seconds, where setting it higher can result in slightly smoother trajectories, making sure that the minimum velocity multiplied by the sim_period is less than twice my tolerance on a goal. Otherwise, the robot will prefer to rotate in place just outside of range of its target position rather than moving towards the goal.OK... that's basically what I've got off the top of my head. I might come back later and add to this, but, hopefully, this gives some insight into the nuances of tuning navigation.