Tuning the Navigation Stack
The localizer is a critical part of the navigation stack, as knowing the position of the robot is crucial to navigate properly to the destination. Having a fast and accurate localization is therefore essential.
There are a couple of parameters that may require some tuning to optimize performance:
num_particles: Controls how many particles are used to track the position of the robot. Increasing the number of particles has a direct impact on the speed: double the number of particles and the localizer takes twice as long. However, there are situations where you might want to increase the number of particles: when the sensors are very noisy, the environment does not match the map accurately (for example, if there are a lot of moving objects, like chairs), or the odometry can’t be trusted.
initial_sigma: Adjust this parameter to match the uncertainty of the global localizer. The first two values represent the standard deviation in the X and Y direction. A good value matches the max of the pixel size and the sample_distance of the grid_search_localizer. The third and last value corresponds to the standard deviation of the heading. A good starting value is about the gap between two beams used in the grid_search_localizer: 2 x Pi / num_beams_gpu.
If you have very noisy sensors, consider increasing all of these values.
absolute_predict_sigma: Same as above. It contains 3 values corresponding to the standard deviation of random noise. This parameter is independent of the current motion of the robot. It is adjusted to match the expected noise of the localization in general. This is reflected in the accuracy of the sensors and the map.
relative_predict_sigma: Controls the noise of the motion/odometry. The more accurate the odometry, the smaller the value is. It also reflects the model of the robot: a differential base has more noise along the X direction than the Y direction.
graph_initialization_steps: Controls how many random samples are performed in the start function. This has a direct impact on the speed of the start function. If you want a graph with high coverage, increase this value. Unfortunately, there is no method to pick a good value. It depends on the size of the graph but also on the shape of the robot, the connectivity between valid pose, etc. Experiment with different values and look at the generated graph until you are satisfied with the result.
Note: If the map is going to be mostly static in future runs of the application, it is worthwhile to spend a bit longer to generate a good graph (by increasing this value). Save the graph into a file using the parameter graph_file_out. Afterwards, you can load the graph directly from the file using the parameter graph_file_in.
graph_in_tick_steps: In most use cases you build the graph in the start function or load it from a file and this parameter should be set to 0 (to not waste time during the tick function). However, when the map is constantly changing between runs (preventing loading from a file) and the application requires a fast startup, it might be worthwhile to decrease the value of the above parameter and set this parameter to a reasonable value (once again, there is no magic number so tune it to take about 10/20% of the allowed tick time) to build the graph little by little, improving it at each tick.
max_colliding_lookup: When you expect the robot to navigate very closely to obstacles or have a target destination close to an obstacle, use this parameter to allow the planner to pick an alternative starting/target position in a non-colliding state (from the perspective of the planner). The planner then tries to plan to/from these alternative positions. This parameter controls how far inside an obstacle the current/target position can be before the planner gives up and looks for a path.
model_max_translation_distance: Controls the maximum distance allowed between waypoints of the navigation graph. If you reduce this parameter, it generates a denser graph (requiring more random sampling). There is a compromise between having more waypoints (slows down looking for a path in the graph) and having far away waypoints, making the check of collision between two waypoints slower. The sweet spot seems to be around a couple times the size of the robot for an office space.
If your map is mostly open space, this value may be increased.
model_max_rotation_distance: Controls the maximum rotation allowed for two waypoints to be connected. Setting the value larger than Pi means there is no restriction and most of the time it is the reasonable choice. However, if your map is such that your robot can’t rotate much (rectangular shape in a map consisting of mostly of corridors), it might be worth limiting the rotation to speed up the collision checking along edges. This creates a denser graph in general.
The local planner is by far the trickiest one to tune as it depends on your robot, application, and personal preferences:
To control the speed of the robot, you can use different parameters: min_speed and ** max_speed** control the legal range of operation. Make sure this range includes zero. To limit the capacity of the robot to move backward, set the min_speed to 0.
Note that these parameters are not absolute limits on the range of the speed. There are penalities when leaving the range, so set the limit lower than the desired max speed (as it depends on other parameters, you may want to play a bit with it, but in general about 90% of the target max_speed is a good guess). It is also important to set the value low enough that the planner does not command a speed that the robot cannot reach.
You can also control the speed of the robot when it gets close to obstacles by adjusting the costs parameter of the DistanceQuadraticCostBuilder component. This parameter takes a list of triplets corresponding to the gain, target_distance, and gradient. If the gradient is set to 0, the robot does not adjust its speed when moving close to an obstacle. If the value is set to a non-zero value, the robot decreases its speed at the specified rate when approaching an obstacle. For example, if gradient is set to 0.5 and the robot is moving at 1 m/s at a distance of 1 m from an obstacle, if the robot was forced to move at a distance of 0.4 m from the obstacle, it would move around the speed of 1 m/s - 0.5 * (1 - 0.4) = 0.7 m/s.
Increasing gain_linear_acceleration may reduce the top speed or takes longer to reach it. Increasing gain_lat_acceleration forces the robot to slow down while turning.
To control the rotation speed, limit the max rotation using the parameter max_angular_speed. Similar to the linear speed, this is not a hard limit. Set this value at most to ~80% of the maximum rotation rate that the robot can perform. You can also use gain_steering to limit the angular velocity.
To control the distance to the obstacle, you can set two limits: target_distance is the distance the robot tries to keep when possible. When the robot is closer than this distance, it is penalized a bit. Use min_distance to set a hard limit on how close the robot can be (as for the speed, it’s not a real hard limit, but the penalty grows very quickly past this value).
use_pid_controller: Controls whether to use the pid controller to track the error. If this parameter is disabled, then the command is matched to the plan provided by the global planner. In that case, disable use_predicted_position of the local planner.