Skip to content

Commit 16f2295

Browse files
authored
Merge pull request ros-navigation#4 from botsandus/AUTO-572_update_mppic
AUTO-572 update mppic
2 parents d3b531d + b1ee78c commit 16f2295

File tree

18 files changed

+1147
-676
lines changed

18 files changed

+1147
-676
lines changed

nav2_mppi_controller/README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,8 @@ Visualization of the trajectories using `visualize` uses compute resources to ba
245245

246246
The most common parameters you might want to start off changing are the velocity profiles (`vx_max`, `vx_min`, `wz_max`, and `vy_max` if holonomic) and the `motion_model` to correspond to your vehicle. Its wise to consider the `prune_distance` of the path plan in proportion to your maximum velocity and prediction horizon. The only deeper parameter that will likely need to be adjusted for your particular settings is the Obstacle critics' `repulsion_weight` since the tuning of this is proprtional to your inflation layer's radius. Higher radii should correspond to reduced `repulsion_weight` due to the penalty formation (e.g. `inflation_radius - min_dist_to_obstacle`). If this penalty is too high, the robot will slow significantly when entering cost-space from non-cost space or jitter in narrow corridors. It is noteworthy, but likely not necessary to be changed, that the Obstacle critic may use the full footprint information if `consider_footprint = true`, though comes at an increased compute cost.
247247

248+
If you don't require path following behavior (e.g. just want to follow a goal pose and let the model predictive elements decide the best way to accomplish that), you may easily remove the PathAlign, PathFollow and PathAngle critics.
249+
248250
### Prediction Horizon, Costmap Sizing, and Offsets
249251

250252
As this is a predictive planner, there is some relationship between maximum speed, prediction times, and costmap size that users should keep in mind while tuning for their application. If a controller server costmap is set to 3.0m in size, that means that with the robot in the center, there is 1.5m of information on either side of the robot. When your prediction horizon (time_steps * model_dt) at maximum speed (vx_max) is larger than this, then your robot will be artifically limited in its maximum speeds and behavior by the costmap limitation. For example, if you predict forward 3 seconds (60 steps @ 0.05s per step) at 0.5m/s maximum speed, the **minimum** required costmap radius is 1.5m - or 3m total width.
@@ -255,7 +257,7 @@ The Path Follow critic cannot drive velocities greater than the projectable dist
255257

256258
### Obstacle, Inflation Layer, and Path Following
257259

258-
There also exists a relationship between the costmap configurations and the Obstacle critic configurations. If the Obstacle critic is not well tuned with the costmap parameters (inflation radius, scale) it can cause the robot to wobble significantly as it attempts to take finitely lower-cost trajectories with a slightly lower cost in exchange for jerky motion. It may also perform awkward maneuvors when in free-space to try to maximize time in a small pocket of 0-cost over a more natural motion which involves moving into some low-costed region. Finally, it may generally refuse to go into costed space at all when starting in a free 0-cost space if the gain is set disproportionately higher than the Path Follow scoring to encourage the robot to move along the path. This is due to the critic cost of staying in free space becoming more attractive than entering even lightly costed space in exchange for progression along the task.
260+
There also exists a relationship between the costmap configurations and the Obstacle critic configurations. If the Obstacle critic is not well tuned with the costmap parameters (inflation radius, scale) it can cause the robot to wobble significantly as it attempts to take finitely lower-cost trajectories with a slightly lower cost in exchange for jerky motion. The default behavior was tuned for small AMRs (e.g. turtlebots or similar), so if using a larger robot, you may want to reduce the `repulsion_weight` in kind. It may also perform awkward maneuvors when in free-space to try to maximize time in a small pocket of 0-cost over a more natural motion which involves moving into some low-costed region. Finally, it may generally refuse to go into costed space at all when starting in a free 0-cost space if the gain is set disproportionately higher than the Path Follow scoring to encourage the robot to move along the path. This is due to the critic cost of staying in free space becoming more attractive than entering even lightly costed space in exchange for progression along the task.
259261

260262
Thus, care should be taken to select weights of the obstacle critic in conjunction with the costmap inflation radius and scale so that a robot does not have such issues. How I (Steve, your friendly neighborhood navigator) tuned this was to first create the appropriate obstacle critic behavior desirable in conjunction with the inflation layer parameters. Its worth noting that the Obstacle critic converts the cost into a distance from obstacles, so the nature of the distribution of costs in the inflation isn't overly significant. However, the inflation radius and the scale will define the cost at the end of the distribution where free-space meets the lowest cost value within the radius. So testing for quality behavior when going over that threshold should be considered.
261263

nav2_mppi_controller/include/nav2_mppi_controller/optimizer.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
#include "nav2_costmap_2d/costmap_2d_ros.hpp"
2727
#include "nav2_core/goal_checker.hpp"
28+
#include "nav2_core/controller_exceptions.hpp"
2829

2930
#include "geometry_msgs/msg/twist.hpp"
3031
#include "geometry_msgs/msg/pose_stamped.hpp"

nav2_mppi_controller/include/nav2_mppi_controller/tools/path_handler.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "builtin_interfaces/msg/time.hpp"
2828
#include "nav2_costmap_2d/costmap_2d_ros.hpp"
2929
#include "nav2_util/geometry_utils.hpp"
30+
#include "nav2_core/controller_exceptions.hpp"
3031

3132
#include "nav2_mppi_controller/tools/parameters_handler.hpp"
3233

nav2_mppi_controller/src/optimizer.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ void Optimizer::setOffset(double controller_frequency)
108108
"shifting is ON");
109109
settings_.shift_control_sequence = true;
110110
} else {
111-
throw std::runtime_error(
111+
throw nav2_core::ControllerException(
112112
"Controller period more then model dt, set it equal to model dt");
113113
}
114114
}
@@ -170,7 +170,7 @@ bool Optimizer::fallback(bool fail)
170170

171171
if (++counter > settings_.retry_attempt_limit) {
172172
counter = 0;
173-
throw std::runtime_error("Optimizer fail to compute path");
173+
throw nav2_core::NoValidControl("Optimizer fail to compute path");
174174
}
175175

176176
return true;
@@ -407,7 +407,7 @@ void Optimizer::setMotionModel(const std::string & model)
407407
} else if (model == "Ackermann") {
408408
motion_model_ = std::make_shared<AckermannMotionModel>(parameters_handler_);
409409
} else {
410-
throw std::runtime_error(
410+
throw nav2_core::ControllerException(
411411
std::string(
412412
"Model " + model + " is not valid! Valid options are DiffDrive, Omni, "
413413
"or Ackermann"));

nav2_mppi_controller/src/path_handler.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,12 @@ geometry_msgs::msg::PoseStamped PathHandler::transformToGlobalPlanFrame(
7474
const geometry_msgs::msg::PoseStamped & pose)
7575
{
7676
if (global_plan_.poses.empty()) {
77-
throw std::runtime_error("Received plan with zero length");
77+
throw nav2_core::InvalidPath("Received plan with zero length");
7878
}
7979

8080
geometry_msgs::msg::PoseStamped robot_pose;
8181
if (!transformPose(global_plan_.header.frame_id, pose, robot_pose)) {
82-
throw std::runtime_error(
82+
throw nav2_core::ControllerTFError(
8383
"Unable to transform robot pose into global plan's frame");
8484
}
8585

@@ -102,7 +102,7 @@ nav_msgs::msg::Path PathHandler::transformPath(
102102
pruneGlobalPlan(lower_bound);
103103

104104
if (transformed_plan.poses.empty()) {
105-
throw std::runtime_error("Resulting plan has 0 poses in it.");
105+
throw nav2_core::InvalidPath("Resulting plan has 0 poses in it.");
106106
}
107107

108108
return transformed_plan;

nav2_mppi_controller/test/utils/factory.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ void setUpOptimizerParams(
5656
const std::vector<std::string> & critics,
5757
std::vector<rclcpp::Parameter> & params_, std::string node_name = std::string("dummy"))
5858
{
59-
constexpr double dummy_freq = 10.0;
59+
constexpr double dummy_freq = 50.0;
6060
params_.emplace_back(rclcpp::Parameter(node_name + ".iteration_count", s.iteration_count));
6161
params_.emplace_back(rclcpp::Parameter(node_name + ".batch_size", s.batch_size));
6262
params_.emplace_back(rclcpp::Parameter(node_name + ".time_steps", s.time_steps));
@@ -70,7 +70,7 @@ void setUpControllerParams(
7070
bool visualize, std::vector<rclcpp::Parameter> & params_,
7171
std::string node_name = std::string("dummy"))
7272
{
73-
double dummy_freq = 10.0;
73+
double dummy_freq = 50.0;
7474
params_.emplace_back(rclcpp::Parameter(node_name + ".visualize", visualize));
7575
params_.emplace_back(rclcpp::Parameter("controller_frequency", dummy_freq));
7676
}

nav2_regulated_pure_pursuit_controller/CMakeLists.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,10 @@ set(dependencies
3535
set(library_name nav2_regulated_pure_pursuit_controller)
3636

3737
add_library(${library_name} SHARED
38-
src/regulated_pure_pursuit_controller.cpp)
38+
src/regulated_pure_pursuit_controller.cpp
39+
src/collision_checker.cpp
40+
src/parameter_handler.cpp
41+
src/path_handler.cpp)
3942

4043
ament_target_dependencies(${library_name}
4144
${dependencies}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
// Copyright (c) 2022 Samsung Research America
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#ifndef NAV2_REGULATED_PURE_PURSUIT_CONTROLLER__COLLISION_CHECKER_HPP_
16+
#define NAV2_REGULATED_PURE_PURSUIT_CONTROLLER__COLLISION_CHECKER_HPP_
17+
18+
#include <string>
19+
#include <vector>
20+
#include <memory>
21+
#include <algorithm>
22+
#include <mutex>
23+
24+
#include "rclcpp/rclcpp.hpp"
25+
#include "nav2_costmap_2d/costmap_2d_ros.hpp"
26+
#include "nav2_costmap_2d/footprint_collision_checker.hpp"
27+
#include "nav2_util/odometry_utils.hpp"
28+
#include "geometry_msgs/msg/pose2_d.hpp"
29+
#include "nav2_regulated_pure_pursuit_controller/parameter_handler.hpp"
30+
31+
#include "nav2_core/controller_exceptions.hpp"
32+
#include "nav2_util/node_utils.hpp"
33+
#include "nav2_util/geometry_utils.hpp"
34+
#include "nav2_costmap_2d/costmap_filters/filter_values.hpp"
35+
36+
namespace nav2_regulated_pure_pursuit_controller
37+
{
38+
39+
/**
40+
* @class nav2_regulated_pure_pursuit_controller::CollisionChecker
41+
* @brief Checks for collision based on a RPP control command
42+
*/
43+
class CollisionChecker
44+
{
45+
public:
46+
/**
47+
* @brief Constructor for nav2_regulated_pure_pursuit_controller::CollisionChecker
48+
*/
49+
CollisionChecker(
50+
rclcpp_lifecycle::LifecycleNode::SharedPtr node,
51+
std::shared_ptr<nav2_costmap_2d::Costmap2DROS> costmap_ros, Parameters * params);
52+
53+
/**
54+
* @brief Destrructor for nav2_regulated_pure_pursuit_controller::CollisionChecker
55+
*/
56+
~CollisionChecker() = default;
57+
58+
/**
59+
* @brief Whether collision is imminent
60+
* @param robot_pose Pose of robot
61+
* @param carrot_pose Pose of carrot
62+
* @param linear_vel linear velocity to forward project
63+
* @param angular_vel angular velocity to forward project
64+
* @param carrot_dist Distance to the carrot for PP
65+
* @return Whether collision is imminent
66+
*/
67+
bool isCollisionImminent(
68+
const geometry_msgs::msg::PoseStamped &,
69+
const double &, const double &,
70+
const double &);
71+
72+
/**
73+
* @brief checks for collision at projected pose
74+
* @param x Pose of pose x
75+
* @param y Pose of pose y
76+
* @param theta orientation of Yaw
77+
* @return Whether in collision
78+
*/
79+
bool inCollision(
80+
const double & x,
81+
const double & y,
82+
const double & theta);
83+
84+
/**
85+
* @brief Cost at a point
86+
* @param x Pose of pose x
87+
* @param y Pose of pose y
88+
* @return Cost of pose in costmap
89+
*/
90+
double costAtPose(const double & x, const double & y);
91+
92+
protected:
93+
rclcpp::Logger logger_ {rclcpp::get_logger("RPPCollisionChecker")};
94+
std::shared_ptr<nav2_costmap_2d::Costmap2DROS> costmap_ros_;
95+
nav2_costmap_2d::Costmap2D * costmap_;
96+
std::unique_ptr<nav2_costmap_2d::FootprintCollisionChecker<nav2_costmap_2d::Costmap2D *>>
97+
footprint_collision_checker_;
98+
Parameters * params_;
99+
std::shared_ptr<rclcpp_lifecycle::LifecyclePublisher<nav_msgs::msg::Path>> carrot_arc_pub_;
100+
rclcpp::Clock::SharedPtr clock_;
101+
};
102+
103+
} // namespace nav2_regulated_pure_pursuit_controller
104+
105+
#endif // NAV2_REGULATED_PURE_PURSUIT_CONTROLLER__COLLISION_CHECKER_HPP_
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
// Copyright (c) 2022 Samsung Research America
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#ifndef NAV2_REGULATED_PURE_PURSUIT_CONTROLLER__PARAMETER_HANDLER_HPP_
16+
#define NAV2_REGULATED_PURE_PURSUIT_CONTROLLER__PARAMETER_HANDLER_HPP_
17+
18+
#include <string>
19+
#include <vector>
20+
#include <memory>
21+
#include <algorithm>
22+
#include <mutex>
23+
24+
#include "rclcpp/rclcpp.hpp"
25+
#include "rclcpp_lifecycle/lifecycle_node.hpp"
26+
#include "nav2_util/odometry_utils.hpp"
27+
#include "nav2_util/geometry_utils.hpp"
28+
#include "nav2_util/node_utils.hpp"
29+
30+
namespace nav2_regulated_pure_pursuit_controller
31+
{
32+
33+
struct Parameters
34+
{
35+
double desired_linear_vel, base_desired_linear_vel;
36+
double lookahead_dist;
37+
double rotate_to_heading_angular_vel;
38+
double max_lookahead_dist;
39+
double min_lookahead_dist;
40+
double lookahead_time;
41+
bool use_velocity_scaled_lookahead_dist;
42+
double min_approach_linear_velocity;
43+
double approach_velocity_scaling_dist;
44+
double max_allowed_time_to_collision_up_to_carrot;
45+
bool use_regulated_linear_velocity_scaling;
46+
bool use_cost_regulated_linear_velocity_scaling;
47+
double cost_scaling_dist;
48+
double cost_scaling_gain;
49+
double inflation_cost_scaling_factor;
50+
double regulated_linear_scaling_min_radius;
51+
double regulated_linear_scaling_min_speed;
52+
bool use_rotate_to_heading;
53+
double max_angular_accel;
54+
double rotate_to_heading_min_angle;
55+
bool allow_reversing;
56+
double max_robot_pose_search_dist;
57+
bool use_interpolation;
58+
bool use_collision_detection;
59+
double transform_tolerance;
60+
};
61+
62+
/**
63+
* @class nav2_regulated_pure_pursuit_controller::ParameterHandler
64+
* @brief Handles parameters and dynamic parameters for RPP
65+
*/
66+
class ParameterHandler
67+
{
68+
public:
69+
/**
70+
* @brief Constructor for nav2_regulated_pure_pursuit_controller::ParameterHandler
71+
*/
72+
ParameterHandler(
73+
rclcpp_lifecycle::LifecycleNode::SharedPtr node,
74+
std::string & plugin_name,
75+
rclcpp::Logger & logger, const double costmap_size_x);
76+
77+
/**
78+
* @brief Destrructor for nav2_regulated_pure_pursuit_controller::ParameterHandler
79+
*/
80+
~ParameterHandler() = default;
81+
82+
std::mutex & getMutex() {return mutex_;}
83+
84+
Parameters * getParams() {return &params_;}
85+
86+
protected:
87+
/**
88+
* @brief Callback executed when a parameter change is detected
89+
* @param event ParameterEvent message
90+
*/
91+
rcl_interfaces::msg::SetParametersResult
92+
dynamicParametersCallback(std::vector<rclcpp::Parameter> parameters);
93+
94+
// Dynamic parameters handler
95+
std::mutex mutex_;
96+
rclcpp::node_interfaces::OnSetParametersCallbackHandle::SharedPtr dyn_params_handler_;
97+
Parameters params_;
98+
std::string plugin_name_;
99+
rclcpp::Logger logger_ {rclcpp::get_logger("RegulatedPurePursuitController")};
100+
};
101+
102+
} // namespace nav2_regulated_pure_pursuit_controller
103+
104+
#endif // NAV2_REGULATED_PURE_PURSUIT_CONTROLLER__PARAMETER_HANDLER_HPP_

0 commit comments

Comments
 (0)