Nav2 Navigation Stack - jazzy  jazzy
ROS 2 Navigation Stack
trajectory_visualizer.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 <memory>
16 #include "nav2_mppi_controller/tools/trajectory_visualizer.hpp"
17 
18 namespace mppi
19 {
20 
22  rclcpp_lifecycle::LifecycleNode::WeakPtr parent, const std::string & name,
23  const std::string & frame_id, ParametersHandler * parameters_handler)
24 {
25  auto node = parent.lock();
26  logger_ = node->get_logger();
27  frame_id_ = frame_id;
28  trajectories_publisher_ =
29  node->create_publisher<visualization_msgs::msg::MarkerArray>("/trajectories", 1);
30  transformed_path_pub_ = node->create_publisher<nav_msgs::msg::Path>("transformed_global_plan", 1);
31  optimal_path_pub_ = node->create_publisher<nav_msgs::msg::Path>("optimal_trajectory", 1);
32  parameters_handler_ = parameters_handler;
33 
34  auto getParam = parameters_handler->getParamGetter(name + ".TrajectoryVisualizer");
35 
36  getParam(trajectory_step_, "trajectory_step", 5);
37  getParam(time_step_, "time_step", 3);
38 
39  reset();
40 }
41 
43 {
44  trajectories_publisher_.reset();
45  transformed_path_pub_.reset();
46  optimal_path_pub_.reset();
47 }
48 
50 {
51  trajectories_publisher_->on_activate();
52  transformed_path_pub_->on_activate();
53  optimal_path_pub_->on_activate();
54 }
55 
57 {
58  trajectories_publisher_->on_deactivate();
59  transformed_path_pub_->on_deactivate();
60  optimal_path_pub_->on_deactivate();
61 }
62 
64  const xt::xtensor<float, 2> & trajectory,
65  const std::string & marker_namespace,
66  const builtin_interfaces::msg::Time & cmd_stamp)
67 {
68  if (optimal_path_pub_->get_subscription_count() == 0 &&
69  trajectories_publisher_->get_subscription_count() == 0)
70  {
71  return;
72  }
73 
74  auto & size = trajectory.shape()[0];
75  if (!size) {
76  return;
77  }
78 
79  auto add_marker = [&](auto i) {
80  float component = static_cast<float>(i) / static_cast<float>(size);
81 
82  auto pose = utils::createPose(trajectory(i, 0), trajectory(i, 1), 0.06);
83  auto scale =
84  i != size - 1 ?
85  utils::createScale(0.03, 0.03, 0.07) :
86  utils::createScale(0.07, 0.07, 0.09);
87  auto color = utils::createColor(0, component, component, 1);
88  auto marker = utils::createMarker(
89  marker_id_++, pose, scale, color, frame_id_, marker_namespace);
90  points_->markers.push_back(marker);
91 
92  // populate optimal path
93  geometry_msgs::msg::PoseStamped pose_stamped;
94  pose_stamped.header.frame_id = frame_id_;
95  pose_stamped.pose = pose;
96 
97  tf2::Quaternion quaternion_tf2;
98  quaternion_tf2.setRPY(0., 0., trajectory(i, 2));
99  pose_stamped.pose.orientation = tf2::toMsg(quaternion_tf2);
100 
101  optimal_path_->poses.push_back(pose_stamped);
102  };
103 
104  optimal_path_->header.stamp = cmd_stamp;
105  optimal_path_->header.frame_id = frame_id_;
106  for (size_t i = 0; i < size; i++) {
107  add_marker(i);
108  }
109 }
110 
112  const models::Trajectories & trajectories, const std::string & marker_namespace)
113 {
114  if (trajectories_publisher_->get_subscription_count() == 0) {
115  return;
116  }
117 
118  auto & shape = trajectories.x.shape();
119  const float shape_1 = static_cast<float>(shape[1]);
120  points_->markers.reserve(floor(shape[0] / trajectory_step_) * floor(shape[1] * time_step_));
121 
122  for (size_t i = 0; i < shape[0]; i += trajectory_step_) {
123  for (size_t j = 0; j < shape[1]; j += time_step_) {
124  const float j_flt = static_cast<float>(j);
125  float blue_component = 1.0f - j_flt / shape_1;
126  float green_component = j_flt / shape_1;
127 
128  auto pose = utils::createPose(trajectories.x(i, j), trajectories.y(i, j), 0.03);
129  auto scale = utils::createScale(0.03, 0.03, 0.03);
130  auto color = utils::createColor(0, green_component, blue_component, 1);
131  auto marker = utils::createMarker(
132  marker_id_++, pose, scale, color, frame_id_, marker_namespace);
133 
134  points_->markers.push_back(marker);
135  }
136  }
137 }
138 
140 {
141  marker_id_ = 0;
142  points_ = std::make_unique<visualization_msgs::msg::MarkerArray>();
143  optimal_path_ = std::make_unique<nav_msgs::msg::Path>();
144 }
145 
146 void TrajectoryVisualizer::visualize(const nav_msgs::msg::Path & plan)
147 {
148  if (trajectories_publisher_->get_subscription_count() > 0) {
149  trajectories_publisher_->publish(std::move(points_));
150  }
151 
152  if (optimal_path_pub_->get_subscription_count() > 0) {
153  optimal_path_pub_->publish(std::move(optimal_path_));
154  }
155 
156  reset();
157 
158  if (transformed_path_pub_->get_subscription_count() > 0) {
159  auto plan_ptr = std::make_unique<nav_msgs::msg::Path>(plan);
160  transformed_path_pub_->publish(std::move(plan_ptr));
161  }
162 }
163 
164 } // namespace mppi
Handles getting parameters and dynamic parmaeter changes.
auto getParamGetter(const std::string &ns)
Get an object to retreive parameters.
void visualize(const nav_msgs::msg::Path &plan)
Visualize the plan.
void on_deactivate()
Deactivate object.
void on_configure(rclcpp_lifecycle::LifecycleNode::WeakPtr parent, const std::string &name, const std::string &frame_id, ParametersHandler *parameters_handler)
Configure trajectory visualizer.
void on_activate()
Activate object.
void add(const xt::xtensor< float, 2 > &trajectory, const std::string &marker_namespace, const builtin_interfaces::msg::Time &cmd_stamp)
Add an optimal trajectory to visualize.
void on_cleanup()
Cleanup object on shutdown.
Candidate Trajectories.