Skip to content

Commit

Permalink
Merge branch 'main' into mppi_opt
Browse files Browse the repository at this point in the history
Signed-off-by: Steve Macenski <[email protected]>
  • Loading branch information
SteveMacenski authored Mar 22, 2024
2 parents 80d459e + 1ef462e commit d0fea59
Show file tree
Hide file tree
Showing 26 changed files with 289 additions and 56 deletions.
11 changes: 11 additions & 0 deletions nav2_amcl/include/nav2_amcl/amcl_node.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "nav2_amcl/sensors/laser/laser.hpp"
#include "nav2_msgs/msg/particle.hpp"
#include "nav2_msgs/msg/particle_cloud.hpp"
#include "nav2_msgs/srv/set_initial_pose.hpp"
#include "nav_msgs/srv/set_map.hpp"
#include "sensor_msgs/msg/laser_scan.hpp"
#include "std_srvs/srv/empty.hpp"
Expand Down Expand Up @@ -210,6 +211,16 @@ class AmclNode : public nav2_util::LifecycleNode
const std::shared_ptr<std_srvs::srv::Empty::Request> request,
std::shared_ptr<std_srvs::srv::Empty::Response> response);

// service server for providing an initial pose guess
rclcpp::Service<nav2_msgs::srv::SetInitialPose>::SharedPtr initial_guess_srv_;
/*
* @brief Service callback for an initial pose guess request
*/
void initialPoseReceivedSrv(
const std::shared_ptr<rmw_request_id_t> request_header,
const std::shared_ptr<nav2_msgs::srv::SetInitialPose::Request> request,
std::shared_ptr<nav2_msgs::srv::SetInitialPose::Response> response);

// Let amcl update samples without requiring motion
rclcpp::Service<std_srvs::srv::Empty>::SharedPtr nomotion_update_srv_;
/*
Expand Down
23 changes: 19 additions & 4 deletions nav2_amcl/src/amcl_node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,9 @@ AmclNode::on_cleanup(const rclcpp_lifecycle::State & /*state*/)
// Get rid of the inputs first (services and message filter input), so we
// don't continue to process incoming messages
global_loc_srv_.reset();
initial_guess_srv_.reset();
nomotion_update_srv_.reset();
executor_thread_.reset(); // to make sure initial_pose_sub_ completely exit
initial_pose_sub_.reset();
laser_scan_connection_.disconnect();
tf_listener_.reset(); // listener may access lase_scan_filter_, so it should be reset earlier
Expand Down Expand Up @@ -494,6 +496,15 @@ AmclNode::globalLocalizationCallback(
pf_init_ = false;
}

void
AmclNode::initialPoseReceivedSrv(
const std::shared_ptr<rmw_request_id_t>/*request_header*/,
const std::shared_ptr<nav2_msgs::srv::SetInitialPose::Request> req,
std::shared_ptr<nav2_msgs::srv::SetInitialPose::Response>/*res*/)
{
initialPoseReceived(std::make_shared<geometry_msgs::msg::PoseWithCovarianceStamped>(req->pose));
}

// force nomotion updates (amcl updating without requiring motion)
void
AmclNode::nomotionUpdateCallback(
Expand Down Expand Up @@ -1103,20 +1114,20 @@ AmclNode::initParameters()
// Semantic checks
if (laser_likelihood_max_dist_ < 0) {
RCLCPP_WARN(
get_logger(), "You've set laser_likelihood_max_dist to be negtive,"
get_logger(), "You've set laser_likelihood_max_dist to be negative,"
" this isn't allowed so it will be set to default value 2.0.");
laser_likelihood_max_dist_ = 2.0;
}
if (max_particles_ < 0) {
RCLCPP_WARN(
get_logger(), "You've set max_particles to be negtive,"
get_logger(), "You've set max_particles to be negative,"
" this isn't allowed so it will be set to default value 2000.");
max_particles_ = 2000;
}

if (min_particles_ < 0) {
RCLCPP_WARN(
get_logger(), "You've set min_particles to be negtive,"
get_logger(), "You've set min_particles to be negative,"
" this isn't allowed so it will be set to default value 500.");
min_particles_ = 500;
}
Expand All @@ -1130,7 +1141,7 @@ AmclNode::initParameters()

if (resample_interval_ <= 0) {
RCLCPP_WARN(
get_logger(), "You've set resample_interval to be zero or negtive,"
get_logger(), "You've set resample_interval to be zero or negative,"
" this isn't allowed so it will be set to default value to 1.");
resample_interval_ = 1;
}
Expand Down Expand Up @@ -1543,6 +1554,10 @@ AmclNode::initServices()
"reinitialize_global_localization",
std::bind(&AmclNode::globalLocalizationCallback, this, _1, _2, _3));

initial_guess_srv_ = create_service<nav2_msgs::srv::SetInitialPose>(
"set_initial_pose",
std::bind(&AmclNode::initialPoseReceivedSrv, this, _1, _2, _3));

nomotion_update_srv_ = create_service<std_srvs::srv::Empty>(
"request_nomotion_update",
std::bind(&AmclNode::nomotionUpdateCallback, this, _1, _2, _3));
Expand Down
22 changes: 11 additions & 11 deletions nav2_amcl/src/sensors/laser/likelihood_field_model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,17 @@ LikelihoodFieldModel::sensorFunction(LaserData * data, pf_sample_set_t * set)

self = reinterpret_cast<LikelihoodFieldModel *>(data->laser);

// Pre-compute a couple of things
double z_hit_denom = 2 * self->sigma_hit_ * self->sigma_hit_;
double z_rand_mult = 1.0 / data->range_max;

step = (data->range_count - 1) / (self->max_beams_ - 1);

// Step size must be at least 1
if (step < 1) {
step = 1;
}

total_weight = 0.0;

// Compute the sample weights
Expand All @@ -65,17 +76,6 @@ LikelihoodFieldModel::sensorFunction(LaserData * data, pf_sample_set_t * set)

p = 1.0;

// Pre-compute a couple of things
double z_hit_denom = 2 * self->sigma_hit_ * self->sigma_hit_;
double z_rand_mult = 1.0 / data->range_max;

step = (data->range_count - 1) / (self->max_beams_ - 1);

// Step size must be at least 1
if (step < 1) {
step = 1;
}

for (i = 0; i < data->range_count; i += step) {
obs_range = data->ranges[i][0];
obs_bearing = data->ranges[i][1];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,9 @@ class BtActionNode : public BT::ActionNodeBase
RCLCPP_DEBUG(node_->get_logger(), "Waiting for \"%s\" action server", action_name.c_str());
if (!action_client_->wait_for_action_server(wait_for_service_timeout_)) {
RCLCPP_ERROR(
node_->get_logger(), "\"%s\" action server not available after waiting for 1 s",
action_name.c_str());
node_->get_logger(), "\"%s\" action server not available after waiting for %f s",
action_name.c_str(),
wait_for_service_timeout_.count() / 1000.0);
throw std::runtime_error(
std::string("Action server ") + action_name +
std::string(" not available"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ BtActionServer<ActionT>::BtActionServer(
if (!node->has_parameter("action_server_result_timeout")) {
node->declare_parameter("action_server_result_timeout", 900.0);
}
if (!node->has_parameter("wait_for_service_timeout")) {
node->declare_parameter("wait_for_service_timeout", 1000);
}

std::vector<std::string> error_code_names = {
"follow_path_error_code",
Expand Down
7 changes: 5 additions & 2 deletions nav2_controller/src/controller_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,7 @@ void ControllerServer::computeControl()
{
std::lock_guard<std::mutex> lock(dynamic_params_lock_);

auto start_time = this->now();
RCLCPP_INFO(get_logger(), "Received a goal, begin computing control effort.");

try {
Expand Down Expand Up @@ -479,10 +480,12 @@ void ControllerServer::computeControl()
break;
}

auto cycle_duration = this->now() - start_time;
if (!loop_rate.sleep()) {
RCLCPP_WARN(
get_logger(), "Control loop missed its desired rate of %.4fHz",
controller_frequency_);
get_logger(),
"Control loop missed its desired rate of %.4f Hz. Current loop rate is %.4f Hz.",
controller_frequency_, 1 / cycle_duration.seconds());
}
}
} catch (nav2_core::InvalidController & e) {
Expand Down
1 change: 1 addition & 0 deletions nav2_msgs/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ rosidl_generate_interfaces(${PROJECT_NAME}
"srv/ManageLifecycleNodes.srv"
"srv/LoadMap.srv"
"srv/SaveMap.srv"
"srv/SetInitialPose.srv"
"action/AssistedTeleop.action"
"action/BackUp.action"
"action/ComputePathToPose.action"
Expand Down
3 changes: 3 additions & 0 deletions nav2_msgs/srv/SetInitialPose.srv
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
geometry_msgs/PoseWithCovarianceStamped pose
---

2 changes: 2 additions & 0 deletions nav2_regulated_pure_pursuit_controller/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 3.5)
project(nav2_regulated_pure_pursuit_controller)

find_package(ament_cmake REQUIRED)
find_package(nav2_amcl REQUIRED)
find_package(nav2_common REQUIRED)
find_package(nav2_core REQUIRED)
find_package(nav2_costmap_2d REQUIRED)
Expand All @@ -26,6 +27,7 @@ set(dependencies
nav2_costmap_2d
pluginlib
nav_msgs
nav2_amcl
nav2_util
nav2_core
tf2
Expand Down
2 changes: 2 additions & 0 deletions nav2_regulated_pure_pursuit_controller/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ Note: The maximum allowed time to collision is thresholded by the lookahead poin
| `rotate_to_heading_min_angle` | The difference in the path orientation and the starting robot orientation to trigger a rotate in place, if `use_rotate_to_heading` is enabled. |
| `max_angular_accel` | Maximum allowable angular acceleration while rotating to heading, if enabled |
| `max_robot_pose_search_dist` | Maximum integrated distance along the path to bound the search for the closest pose to the robot. This is set by default to the maximum costmap extent, so it shouldn't be set manually unless there are loops within the local costmap. |
| `interpolate_curvature_after_goal` | Needs use_fixed_curvature_lookahead to be true. Interpolate a carrot after the goal dedicated to the curvate calculation (to avoid oscilaltions at the end of the path) |

Example fully-described XML with default parameter values:

Expand Down Expand Up @@ -137,6 +138,7 @@ controller_server:
rotate_to_heading_min_angle: 0.785
max_angular_accel: 3.2
max_robot_pose_search_dist: 10.0
interpolate_curvature_after_goal: false
cost_scaling_dist: 0.3
cost_scaling_gain: 1.0
inflation_cost_scaling_factor: 3.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ struct Parameters
double rotate_to_heading_min_angle;
bool allow_reversing;
double max_robot_pose_search_dist;
bool interpolate_curvature_after_goal;
bool use_collision_detection;
double transform_tolerance;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,12 @@ class PathHandler
* - Outside the local_costmap (collision avoidance cannot be assured)
* @param pose pose to transform
* @param max_robot_pose_search_dist Distance to search for matching nearest path point
* @param reject_unit_path If true, fail if path has only one pose
* @return Path in new frame
*/
nav_msgs::msg::Path transformGlobalPlan(
const geometry_msgs::msg::PoseStamped & pose,
double max_robot_pose_search_dist);
double max_robot_pose_search_dist, bool reject_unit_path = false);

/**
* @brief Transform a pose to another frame.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,12 @@ class RegulatedPurePursuitController : public nav2_core::Controller
* @brief Whether robot should rotate to rough path heading
* @param carrot_pose current lookahead point
* @param angle_to_path Angle of robot output relatie to carrot marker
* @param x_vel_sign Velocoty sign (forward or backward)
* @return Whether should rotate to path heading
*/
bool shouldRotateToPath(
const geometry_msgs::msg::PoseStamped & carrot_pose, double & angle_to_path);
const geometry_msgs::msg::PoseStamped & carrot_pose, double & angle_to_path,
double & x_vel_sign);

/**
* @brief Whether robot should rotate to final goal orientation
Expand Down Expand Up @@ -185,9 +187,13 @@ class RegulatedPurePursuitController : public nav2_core::Controller
* @brief Get lookahead point
* @param lookahead_dist Optimal lookahead distance
* @param path Current global path
* @param interpolate_after_goal If true, interpolate the lookahead point after the goal based
* on the orientation given by the position of the last two pose of the path
* @return Lookahead point
*/
geometry_msgs::msg::PoseStamped getLookAheadPoint(const double &, const nav_msgs::msg::Path &);
geometry_msgs::msg::PoseStamped getLookAheadPoint(
const double &, const nav_msgs::msg::Path &,
bool interpolate_after_goal = false);

/**
* @brief checks for the cusp position
Expand All @@ -210,6 +216,8 @@ class RegulatedPurePursuitController : public nav2_core::Controller
std::shared_ptr<rclcpp_lifecycle::LifecyclePublisher<nav_msgs::msg::Path>> global_path_pub_;
std::shared_ptr<rclcpp_lifecycle::LifecyclePublisher<geometry_msgs::msg::PointStamped>>
carrot_pub_;
std::shared_ptr<rclcpp_lifecycle::LifecyclePublisher<geometry_msgs::msg::PointStamped>>
curvature_carrot_pub_;
std::shared_ptr<rclcpp_lifecycle::LifecyclePublisher<nav_msgs::msg::Path>> carrot_arc_pub_;
std::unique_ptr<nav2_regulated_pure_pursuit_controller::PathHandler> path_handler_;
std::unique_ptr<nav2_regulated_pure_pursuit_controller::ParameterHandler> param_handler_;
Expand Down
1 change: 1 addition & 0 deletions nav2_regulated_pure_pursuit_controller/package.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

<buildtool_depend>ament_cmake</buildtool_depend>

<depend>nav2_amcl</depend>
<depend>nav2_common</depend>
<depend>nav2_core</depend>
<depend>nav2_util</depend>
Expand Down
28 changes: 12 additions & 16 deletions nav2_regulated_pure_pursuit_controller/src/parameter_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ ParameterHandler::ParameterHandler(
declare_parameter_if_not_declared(
node, plugin_name_ + ".max_robot_pose_search_dist",
rclcpp::ParameterValue(costmap_size_x / 2.0));
declare_parameter_if_not_declared(
node, plugin_name_ + ".interpolate_curvature_after_goal",
rclcpp::ParameterValue(false));
declare_parameter_if_not_declared(
node, plugin_name_ + ".use_collision_detection",
rclcpp::ParameterValue(true));
Expand Down Expand Up @@ -159,6 +162,15 @@ ParameterHandler::ParameterHandler(
params_.max_robot_pose_search_dist = std::numeric_limits<double>::max();
}

node->get_parameter(
plugin_name_ + ".interpolate_curvature_after_goal",
params_.interpolate_curvature_after_goal);
if (!params_.use_fixed_curvature_lookahead && params_.interpolate_curvature_after_goal) {
RCLCPP_WARN(
logger_, "For interpolate_curvature_after_goal to be set to true, "
"use_fixed_curvature_lookahead should be true, it is currently set to false. Disabling.");
params_.interpolate_curvature_after_goal = false;
}
node->get_parameter(
plugin_name_ + ".use_collision_detection",
params_.use_collision_detection);
Expand All @@ -170,16 +182,6 @@ ParameterHandler::ParameterHandler(
params_.use_cost_regulated_linear_velocity_scaling = false;
}

/** Possible to drive in reverse direction if and only if
"use_rotate_to_heading" parameter is set to false **/

if (params_.use_rotate_to_heading && params_.allow_reversing) {
RCLCPP_WARN(
logger_, "Disabling reversing. Both use_rotate_to_heading and allow_reversing "
"parameter cannot be set to true. By default setting use_rotate_to_heading true");
params_.allow_reversing = false;
}

dyn_params_handler_ = node->add_on_set_parameters_callback(
std::bind(
&ParameterHandler::dynamicParametersCallback,
Expand Down Expand Up @@ -250,12 +252,6 @@ ParameterHandler::dynamicParametersCallback(
} else if (name == plugin_name_ + ".use_collision_detection") {
params_.use_collision_detection = parameter.as_bool();
} else if (name == plugin_name_ + ".use_rotate_to_heading") {
if (parameter.as_bool() && params_.allow_reversing) {
RCLCPP_WARN(
logger_, "Both use_rotate_to_heading and allow_reversing "
"parameter cannot be set to true. Rejecting parameter update.");
continue;
}
params_.use_rotate_to_heading = parameter.as_bool();
} else if (name == plugin_name_ + ".allow_reversing") {
if (params_.use_rotate_to_heading && parameter.as_bool()) {
Expand Down
16 changes: 15 additions & 1 deletion nav2_regulated_pure_pursuit_controller/src/path_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,17 @@ double PathHandler::getCostmapMaxExtent() const

nav_msgs::msg::Path PathHandler::transformGlobalPlan(
const geometry_msgs::msg::PoseStamped & pose,
double max_robot_pose_search_dist)
double max_robot_pose_search_dist,
bool reject_unit_path)
{
if (global_plan_.poses.empty()) {
throw nav2_core::InvalidPath("Received plan with zero length");
}

if (reject_unit_path && global_plan_.poses.size() == 1) {
throw nav2_core::InvalidPath("Received plan with length of one");
}

// let's get the pose of the robot in the frame of the plan
geometry_msgs::msg::PoseStamped robot_pose;
if (!transformPose(global_plan_.header.frame_id, pose, robot_pose)) {
Expand All @@ -73,6 +78,15 @@ nav_msgs::msg::Path PathHandler::transformGlobalPlan(
return euclidean_distance(robot_pose, ps);
});

// Make sure we always have at least 2 points on the transformed plan and that we don't prune
// the global plan below 2 points in order to have always enough point to interpolate the
// end of path direction
if (global_plan_.poses.begin() != closest_pose_upper_bound && global_plan_.poses.size() > 1 &&
transformation_begin == std::prev(closest_pose_upper_bound))
{
transformation_begin = std::prev(std::prev(closest_pose_upper_bound));
}

// We'll discard points on the plan that are outside the local costmap
const double max_costmap_extent = getCostmapMaxExtent();
auto transformation_end = std::find_if(
Expand Down
Loading

0 comments on commit d0fea59

Please sign in to comment.