Nav2 Navigation Stack - lyrical  lyrical
ROS 2 Navigation Stack
controller.cpp
1 // Copyright (c) 2022 Samsung Research America, @artofnothingness Alexey Budyakov
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 #include <stdint.h>
16 #include <chrono>
17 #include "nav2_mppi_controller/controller.hpp"
18 #include "nav2_mppi_controller/tools/utils.hpp"
19 #include "nav2_ros_common/tf2_factories.hpp"
20 
21 // #define BENCHMARK_TESTING
22 
23 namespace nav2_mppi_controller
24 {
25 
27  const nav2::LifecycleNode::WeakPtr & parent,
28  std::string name, const nav2::TransformBuffer::SharedPtr tf,
29  const std::shared_ptr<nav2_costmap_2d::Costmap2DROS> costmap_ros)
30 {
31  parent_ = parent;
32  costmap_ros_ = costmap_ros;
33  tf_buffer_ = tf;
34  name_ = name;
35  parameters_handler_ = std::make_unique<ParametersHandler>(parent, name_);
36 
37  auto node = parent_.lock();
38  // Get high-level controller parameters
39  auto getParam = parameters_handler_->getParamGetter(name_);
40  getParam(visualize_, "visualize", false);
41  getParam(critic_index_to_visualize_, "critic_index_to_visualize", 0);
42 
43  getParam(publish_optimal_trajectory_, "publish_optimal_trajectory", false);
44 
45  // Configure composed objects
46  optimizer_.initialize(parent_, name_, costmap_ros_, tf_buffer_, parameters_handler_.get());
47  trajectory_visualizer_.on_configure(
48  parent_, name_,
49  costmap_ros_->getGlobalFrameID(), parameters_handler_.get());
50 
51  if (publish_optimal_trajectory_) {
52  opt_traj_pub_ = node->create_publisher<nav_msgs::msg::Trajectory>(
53  "~/optimal_trajectory");
54  }
55 
56  RCLCPP_INFO(logger_, "Configured MPPI Controller: %s", name_.c_str());
57 }
58 
60 {
61  optimizer_.shutdown();
62  trajectory_visualizer_.on_cleanup();
63  parameters_handler_.reset();
64  opt_traj_pub_.reset();
65  RCLCPP_INFO(logger_, "Cleaned up MPPI Controller: %s", name_.c_str());
66 }
67 
69 {
70  auto node = parent_.lock();
71  trajectory_visualizer_.on_activate();
72  parameters_handler_->start();
73  if (opt_traj_pub_) {
74  opt_traj_pub_->on_activate();
75  }
76  RCLCPP_INFO(logger_, "Activated MPPI Controller: %s", name_.c_str());
77 }
78 
80 {
81  trajectory_visualizer_.on_deactivate();
82  if (opt_traj_pub_) {
83  opt_traj_pub_->on_deactivate();
84  }
85  RCLCPP_INFO(logger_, "Deactivated MPPI Controller: %s", name_.c_str());
86 }
87 
89 {
90  optimizer_.reset(false /*Don't reset zone-based speed limits between requests*/);
91 }
92 
93 geometry_msgs::msg::TwistStamped MPPIController::computeVelocityCommands(
94  const geometry_msgs::msg::PoseStamped & robot_pose,
95  const geometry_msgs::msg::Twist & robot_speed,
96  nav2_core::GoalChecker * goal_checker,
97  const nav_msgs::msg::Path & transformed_global_plan,
98  const geometry_msgs::msg::PoseStamped & global_goal)
99 {
100 #ifdef BENCHMARK_TESTING
101  auto start = std::chrono::system_clock::now();
102 #endif
103 
104  std::lock_guard<std::mutex> param_lock(*parameters_handler_->getLock());
105 
106  nav2_costmap_2d::Costmap2D * costmap = costmap_ros_->getCostmap();
107  std::unique_lock<nav2_costmap_2d::Costmap2D::mutex_t> costmap_lock(*(costmap->getMutex()));
108 
109  auto [cmd, optimal_trajectory] =
110  optimizer_.evalControl(robot_pose, robot_speed, transformed_global_plan, global_goal.pose,
111  goal_checker);
112 
113 #ifdef BENCHMARK_TESTING
114  auto end = std::chrono::system_clock::now();
115  auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
116  RCLCPP_INFO(logger_, "Control loop execution time: %ld [ms]", duration);
117 #endif
118 
119  if (publish_optimal_trajectory_ && opt_traj_pub_ && opt_traj_pub_->get_subscription_count() > 0) {
120  std_msgs::msg::Header trajectory_header;
121  trajectory_header.stamp = cmd.header.stamp;
122  trajectory_header.frame_id = costmap_ros_->getGlobalFrameID();
123 
124  auto trajectory_msg = utils::toTrajectoryMsg(
125  optimal_trajectory,
126  optimizer_.getOptimalControlSequence(),
127  optimizer_.getSettings().model_dt,
128  trajectory_header);
129  opt_traj_pub_->publish(std::move(trajectory_msg));
130  }
131 
132  if (visualize_) {
133  visualize(cmd.header.stamp, optimal_trajectory);
134  }
135 
136  return cmd;
137 }
138 
140  const builtin_interfaces::msg::Time & cmd_stamp,
141  const Eigen::ArrayXXf & optimal_trajectory)
142 {
143  const auto & critic_costs = optimizer_.getCriticCosts();
144  const Eigen::ArrayXf & costs =
145  (critic_index_to_visualize_ <= 0 ||
146  critic_index_to_visualize_ > static_cast<int>(critic_costs.size())) ?
147  optimizer_.getCosts() :
148  critic_costs[critic_index_to_visualize_ - 1].second;
149 
150  trajectory_visualizer_.add(
151  optimizer_.getGeneratedTrajectories(),
152  costs,
153  optimizer_.getCollisionFlags(),
154  cmd_stamp);
155 
156  trajectory_visualizer_.add(optimal_trajectory, "Optimal Trajectory", cmd_stamp);
157  trajectory_visualizer_.visualize();
158 }
159 
160 void MPPIController::newPathReceived(const nav_msgs::msg::Path & /*raw_global_path*/)
161 {
162 }
163 
164 void MPPIController::setSpeedLimit(const double & speed_limit, const bool & percentage)
165 {
166  optimizer_.setSpeedLimit(speed_limit, percentage);
167 }
168 
169 } // namespace nav2_mppi_controller
170 
171 #include "pluginlib/class_list_macros.hpp"
const std::vector< std::pair< std::string, Eigen::ArrayXf > > & getCriticCosts() const
Get per-critic cost breakdown from last evaluation.
Definition: optimizer.hpp:134
const std::vector< bool > & getCollisionFlags() const
Get per-trajectory collision flags from last evaluation.
Definition: optimizer.hpp:143
const models::ControlSequence & getOptimalControlSequence()
Get the optimal control sequence for a cycle for visualization.
Definition: optimizer.cpp:600
void reset(bool reset_dynamic_speed_limits=true)
Reset the optimization problem to initial conditions.
Definition: optimizer.cpp:183
std::tuple< geometry_msgs::msg::TwistStamped, Eigen::ArrayXXf > evalControl(const geometry_msgs::msg::PoseStamped &robot_pose, const geometry_msgs::msg::Twist &robot_speed, const nav_msgs::msg::Path &plan, const geometry_msgs::msg::Pose &goal, nav2_core::GoalChecker *goal_checker)
Compute control using MPPI algorithm.
Definition: optimizer.cpp:230
const models::OptimizerSettings & getSettings() const
Get the motion model time step.
Definition: optimizer.hpp:171
models::Trajectories & getGeneratedTrajectories()
Get the trajectories generated in a cycle for visualization.
Definition: optimizer.cpp:721
void shutdown()
Shutdown for optimizer at process end.
Definition: optimizer.cpp:72
void setSpeedLimit(double speed_limit, bool percentage)
Set the maximum speed based on the speed limits callback.
Definition: optimizer.cpp:691
const Eigen::ArrayXf & getCosts() const
Get the aggregated trajectory costs from last evaluation.
Definition: optimizer.hpp:128
void initialize(nav2::LifecycleNode::WeakPtr parent, const std::string &name, std::shared_ptr< nav2_costmap_2d::Costmap2DROS > costmap_ros, nav2::TransformBuffer::SharedPtr tf_buffer, ParametersHandler *dynamic_parameters_handler)
Initializes optimizer on startup.
Definition: optimizer.cpp:34
void add(const Eigen::ArrayXXf &trajectory, const std::string &marker_namespace, const builtin_interfaces::msg::Time &cmd_stamp)
Add an optimal trajectory to visualize.
void on_deactivate()
Deactivate object.
void on_configure(nav2::LifecycleNode::WeakPtr parent, const std::string &name, const std::string &frame_id, ParametersHandler *parameters_handler)
Configure trajectory visualizer.
void visualize()
Visualize the plan.
void on_activate()
Activate object.
void on_cleanup()
Cleanup object on shutdown.
controller interface that acts as a virtual base class for all controller plugins
Definition: controller.hpp:60
Function-object for checking whether a goal has been reached.
A 2D costmap provides a mapping between points in the world and their associated "costs".
Definition: costmap_2d.hpp:69
void cleanup() override
Cleanup resources.
Definition: controller.cpp:59
void newPathReceived(const nav_msgs::msg::Path &raw_global_path) override
Receives a new plan from the Planner Server.
Definition: controller.cpp:160
void configure(const nav2::LifecycleNode::WeakPtr &parent, std::string name, const nav2::TransformBuffer::SharedPtr tf, const std::shared_ptr< nav2_costmap_2d::Costmap2DROS > costmap_ros) override
Configure controller on bringup.
Definition: controller.cpp:26
void visualize(const builtin_interfaces::msg::Time &cmd_stamp, const Eigen::ArrayXXf &optimal_trajectory)
Visualize trajectories.
Definition: controller.cpp:139
void setSpeedLimit(const double &speed_limit, const bool &percentage) override
Set new speed limit from callback.
Definition: controller.cpp:164
geometry_msgs::msg::TwistStamped computeVelocityCommands(const geometry_msgs::msg::PoseStamped &robot_pose, const geometry_msgs::msg::Twist &robot_speed, nav2_core::GoalChecker *goal_checker, const nav_msgs::msg::Path &transformed_global_plan, const geometry_msgs::msg::PoseStamped &global_goal) override
Main method to compute velocities using the optimizer.
Definition: controller.cpp:93
void activate() override
Activate controller.
Definition: controller.cpp:68
void reset() override
Reset the controller state between tasks.
Definition: controller.cpp:88
void deactivate() override
Deactivate controller.
Definition: controller.cpp:79