Nav2 Navigation Stack - kilted  kilted
ROS 2 Navigation Stack
optimizer.cpp
1 // Copyright (c) 2022 Samsung Research America, @artofnothingness Alexey Budyakov
2 // Copyright (c) 2025 Open Navigation LLC
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 
16 #include "nav2_mppi_controller/optimizer.hpp"
17 
18 #include <limits>
19 #include <memory>
20 #include <stdexcept>
21 #include <string>
22 #include <vector>
23 #include <cmath>
24 #include <chrono>
25 
26 #include "nav2_core/controller_exceptions.hpp"
27 #include "nav2_costmap_2d/costmap_filters/filter_values.hpp"
28 
29 namespace mppi
30 {
31 
33  rclcpp_lifecycle::LifecycleNode::WeakPtr parent, const std::string & name,
34  std::shared_ptr<nav2_costmap_2d::Costmap2DROS> costmap_ros,
35  ParametersHandler * param_handler)
36 {
37  parent_ = parent;
38  name_ = name;
39  costmap_ros_ = costmap_ros;
40  costmap_ = costmap_ros_->getCostmap();
41  parameters_handler_ = param_handler;
42 
43  auto node = parent_.lock();
44  logger_ = node->get_logger();
45 
46  getParams();
47 
48  critic_manager_.on_configure(parent_, name_, costmap_ros_, parameters_handler_);
49  noise_generator_.initialize(settings_, isHolonomic(), name_, parameters_handler_);
50 
51  reset();
52 }
53 
55 {
56  noise_generator_.shutdown();
57 }
58 
60 {
61  std::string motion_model_name;
62 
63  auto & s = settings_;
64  auto getParam = parameters_handler_->getParamGetter(name_);
65  auto getParentParam = parameters_handler_->getParamGetter("");
66  getParam(s.model_dt, "model_dt", 0.05f);
67  getParam(s.time_steps, "time_steps", 56);
68  getParam(s.batch_size, "batch_size", 1000);
69  getParam(s.iteration_count, "iteration_count", 1);
70  getParam(s.temperature, "temperature", 0.3f);
71  getParam(s.gamma, "gamma", 0.015f);
72  getParam(s.base_constraints.vx_max, "vx_max", 0.5f);
73  getParam(s.base_constraints.vx_min, "vx_min", -0.35f);
74  getParam(s.base_constraints.vy, "vy_max", 0.5f);
75  getParam(s.base_constraints.wz, "wz_max", 1.9f);
76  getParam(s.base_constraints.ax_max, "ax_max", 3.0f);
77  getParam(s.base_constraints.ax_min, "ax_min", -3.0f);
78  getParam(s.base_constraints.ay_max, "ay_max", 3.0f);
79  getParam(s.base_constraints.ay_min, "ay_min", -3.0f);
80  getParam(s.base_constraints.az_max, "az_max", 3.5f);
81  getParam(s.sampling_std.vx, "vx_std", 0.2f);
82  getParam(s.sampling_std.vy, "vy_std", 0.2f);
83  getParam(s.sampling_std.wz, "wz_std", 0.4f);
84  getParam(s.retry_attempt_limit, "retry_attempt_limit", 1);
85 
86  s.base_constraints.ax_max = fabs(s.base_constraints.ax_max);
87  if (s.base_constraints.ax_min > 0.0) {
88  s.base_constraints.ax_min = -1.0 * s.base_constraints.ax_min;
89  RCLCPP_WARN(
90  logger_,
91  "Sign of the parameter ax_min is incorrect, consider setting it negative.");
92  }
93 
94  if (s.base_constraints.ay_min > 0.0) {
95  s.base_constraints.ay_min = -1.0 * s.base_constraints.ay_min;
96  RCLCPP_WARN(
97  logger_,
98  "Sign of the parameter ay_min is incorrect, consider setting it negative.");
99  }
100 
101 
102  getParam(motion_model_name, "motion_model", std::string("DiffDrive"));
103 
104  s.constraints = s.base_constraints;
105 
106  setMotionModel(motion_model_name);
107  parameters_handler_->addPostCallback([this]() {reset();});
108 
109  double controller_frequency;
110  getParentParam(controller_frequency, "controller_frequency", 0.0, ParameterType::Static);
111  setOffset(controller_frequency);
112 }
113 
114 void Optimizer::setOffset(double controller_frequency)
115 {
116  const double controller_period = 1.0 / controller_frequency;
117  constexpr double eps = 1e-6;
118 
119  if ((controller_period + eps) < settings_.model_dt) {
120  RCLCPP_WARN(
121  logger_,
122  "Controller period is less then model dt, consider setting it equal");
123  } else if (abs(controller_period - settings_.model_dt) < eps) {
124  RCLCPP_INFO(
125  logger_,
126  "Controller period is equal to model dt. Control sequence "
127  "shifting is ON");
128  settings_.shift_control_sequence = true;
129  } else {
131  "Controller period more then model dt, set it equal to model dt");
132  }
133 }
134 
135 void Optimizer::reset(bool reset_dynamic_speed_limits)
136 {
137  state_.reset(settings_.batch_size, settings_.time_steps);
138  control_sequence_.reset(settings_.time_steps);
139  control_history_[0] = {0.0f, 0.0f, 0.0f};
140  control_history_[1] = {0.0f, 0.0f, 0.0f};
141  control_history_[2] = {0.0f, 0.0f, 0.0f};
142  control_history_[3] = {0.0f, 0.0f, 0.0f};
143 
144  if (reset_dynamic_speed_limits) {
145  settings_.constraints = settings_.base_constraints;
146  }
147 
148  costs_.setZero(settings_.batch_size);
149  generated_trajectories_.reset(settings_.batch_size, settings_.time_steps);
150 
151  noise_generator_.reset(settings_, isHolonomic());
152  motion_model_->initialize(settings_.constraints, settings_.model_dt);
153 
154  RCLCPP_INFO(logger_, "Optimizer reset");
155 }
156 
158 {
159  return motion_model_->isHolonomic();
160 }
161 
162 geometry_msgs::msg::TwistStamped Optimizer::evalControl(
163  const geometry_msgs::msg::PoseStamped & robot_pose,
164  const geometry_msgs::msg::Twist & robot_speed,
165  const nav_msgs::msg::Path & plan,
166  const geometry_msgs::msg::Pose & goal,
167  nav2_core::GoalChecker * goal_checker)
168 {
169  prepare(robot_pose, robot_speed, plan, goal, goal_checker);
170 
171  do {
172  optimize();
173  } while (fallback(critics_data_.fail_flag));
174 
175  utils::savitskyGolayFilter(control_sequence_, control_history_, settings_);
176  auto control = getControlFromSequenceAsTwist(plan.header.stamp);
177 
178  if (settings_.shift_control_sequence) {
180  }
181 
182  return control;
183 }
184 
186 {
187  for (size_t i = 0; i < settings_.iteration_count; ++i) {
189  critic_manager_.evalTrajectoriesScores(critics_data_);
191  }
192 }
193 
194 bool Optimizer::fallback(bool fail)
195 {
196  static size_t counter = 0;
197 
198  if (!fail) {
199  counter = 0;
200  return false;
201  }
202 
203  reset();
204 
205  if (++counter > settings_.retry_attempt_limit) {
206  counter = 0;
207  throw nav2_core::NoValidControl("Optimizer fail to compute path");
208  }
209 
210  return true;
211 }
212 
214  const geometry_msgs::msg::PoseStamped & robot_pose,
215  const geometry_msgs::msg::Twist & robot_speed,
216  const nav_msgs::msg::Path & plan,
217  const geometry_msgs::msg::Pose & goal,
218  nav2_core::GoalChecker * goal_checker)
219 {
220  state_.pose = robot_pose;
221  state_.speed = robot_speed;
222  path_ = utils::toTensor(plan);
223  costs_.setZero();
224  goal_ = goal;
225 
226  critics_data_.fail_flag = false;
227  critics_data_.goal_checker = goal_checker;
228  critics_data_.motion_model = motion_model_;
229  critics_data_.furthest_reached_path_point.reset();
230  critics_data_.path_pts_valid.reset();
231 }
232 
234 {
235  auto size = control_sequence_.vx.size();
236  utils::shiftColumnsByOnePlace(control_sequence_.vx, -1);
237  utils::shiftColumnsByOnePlace(control_sequence_.wz, -1);
238  control_sequence_.vx(size - 1) = control_sequence_.vx(size - 2);
239  control_sequence_.wz(size - 1) = control_sequence_.wz(size - 2);
240 
241  if (isHolonomic()) {
242  utils::shiftColumnsByOnePlace(control_sequence_.vy, -1);
243  control_sequence_.vy(size - 1) = control_sequence_.vy(size - 2);
244  }
245 }
246 
248 {
249  noise_generator_.setNoisedControls(state_, control_sequence_);
250  noise_generator_.generateNextNoises();
251  updateStateVelocities(state_);
252  integrateStateVelocities(generated_trajectories_, state_);
253 }
254 
256 {
257  auto & s = settings_;
258 
259  float max_delta_vx = s.model_dt * s.constraints.ax_max;
260  float min_delta_vx = s.model_dt * s.constraints.ax_min;
261  float max_delta_vy = s.model_dt * s.constraints.ay_max;
262  float min_delta_vy = s.model_dt * s.constraints.ay_min;
263  float max_delta_wz = s.model_dt * s.constraints.az_max;
264  float vx_last = utils::clamp(s.constraints.vx_min, s.constraints.vx_max, control_sequence_.vx(0));
265  float wz_last = utils::clamp(-s.constraints.wz, s.constraints.wz, control_sequence_.wz(0));
266  control_sequence_.vx(0) = vx_last;
267  control_sequence_.wz(0) = wz_last;
268  float vy_last = 0;
269  if (isHolonomic()) {
270  vy_last = utils::clamp(-s.constraints.vy, s.constraints.vy, control_sequence_.vy(0));
271  control_sequence_.vy(0) = vy_last;
272  }
273 
274  for (unsigned int i = 1; i != control_sequence_.vx.size(); i++) {
275  float & vx_curr = control_sequence_.vx(i);
276  vx_curr = utils::clamp(s.constraints.vx_min, s.constraints.vx_max, vx_curr);
277  if(vx_last > 0) {
278  vx_curr = utils::clamp(vx_last + min_delta_vx, vx_last + max_delta_vx, vx_curr);
279  } else {
280  vx_curr = utils::clamp(vx_last - max_delta_vx, vx_last - min_delta_vx, vx_curr);
281  }
282  vx_last = vx_curr;
283 
284  float & wz_curr = control_sequence_.wz(i);
285  wz_curr = utils::clamp(-s.constraints.wz, s.constraints.wz, wz_curr);
286  wz_curr = utils::clamp(wz_last - max_delta_wz, wz_last + max_delta_wz, wz_curr);
287  wz_last = wz_curr;
288 
289  if (isHolonomic()) {
290  float & vy_curr = control_sequence_.vy(i);
291  vy_curr = utils::clamp(-s.constraints.vy, s.constraints.vy, vy_curr);
292  if(vy_last > 0) {
293  vy_curr = utils::clamp(vy_last + min_delta_vy, vy_last + max_delta_vy, vy_curr);
294  } else {
295  vy_curr = utils::clamp(vy_last - max_delta_vy, vy_last - min_delta_vy, vy_curr);
296  }
297  vy_last = vy_curr;
298  }
299  }
300 
301  motion_model_->applyConstraints(control_sequence_);
302 }
303 
305  models::State & state) const
306 {
309 }
310 
312  models::State & state) const
313 {
314  state.vx.col(0) = static_cast<float>(state.speed.linear.x);
315  state.wz.col(0) = static_cast<float>(state.speed.angular.z);
316 
317  if (isHolonomic()) {
318  state.vy.col(0) = static_cast<float>(state.speed.linear.y);
319  }
320 }
321 
323  models::State & state) const
324 {
325  motion_model_->predict(state);
326 }
327 
329  Eigen::Array<float, Eigen::Dynamic, 3> & trajectory,
330  const Eigen::ArrayXXf & sequence) const
331 {
332  float initial_yaw = static_cast<float>(tf2::getYaw(state_.pose.pose.orientation));
333 
334  const auto vx = sequence.col(0);
335  const auto wz = sequence.col(1);
336 
337  auto traj_x = trajectory.col(0);
338  auto traj_y = trajectory.col(1);
339  auto traj_yaws = trajectory.col(2);
340 
341  const size_t n_size = traj_yaws.size();
342  if (n_size == 0) {
343  return;
344  }
345 
346  float last_yaw = initial_yaw;
347  for(size_t i = 0; i != n_size; i++) {
348  last_yaw += wz(i) * settings_.model_dt;
349  traj_yaws(i) = last_yaw;
350  }
351 
352  Eigen::ArrayXf yaw_cos = traj_yaws.cos();
353  Eigen::ArrayXf yaw_sin = traj_yaws.sin();
354  utils::shiftColumnsByOnePlace(yaw_cos, 1);
355  utils::shiftColumnsByOnePlace(yaw_sin, 1);
356  yaw_cos(0) = cosf(initial_yaw);
357  yaw_sin(0) = sinf(initial_yaw);
358 
359  auto dx = (vx * yaw_cos).eval();
360  auto dy = (vx * yaw_sin).eval();
361 
362  if (isHolonomic()) {
363  auto vy = sequence.col(2);
364  dx = (dx - vy * yaw_sin).eval();
365  dy = (dy + vy * yaw_cos).eval();
366  }
367 
368  float last_x = state_.pose.pose.position.x;
369  float last_y = state_.pose.pose.position.y;
370  for(size_t i = 0; i != n_size; i++) {
371  last_x += dx(i) * settings_.model_dt;
372  last_y += dy(i) * settings_.model_dt;
373  traj_x(i) = last_x;
374  traj_y(i) = last_y;
375  }
376 }
377 
379  models::Trajectories & trajectories,
380  const models::State & state) const
381 {
382  auto initial_yaw = static_cast<float>(tf2::getYaw(state.pose.pose.orientation));
383  const size_t n_cols = trajectories.yaws.cols();
384 
385  Eigen::ArrayXf last_yaws = Eigen::ArrayXf::Constant(trajectories.yaws.rows(), initial_yaw);
386  for (size_t i = 0; i != n_cols; i++) {
387  last_yaws += state.wz.col(i) * settings_.model_dt;
388  trajectories.yaws.col(i) = last_yaws;
389  }
390 
391  Eigen::ArrayXXf yaw_cos = trajectories.yaws.cos();
392  Eigen::ArrayXXf yaw_sin = trajectories.yaws.sin();
393  utils::shiftColumnsByOnePlace(yaw_cos, 1);
394  utils::shiftColumnsByOnePlace(yaw_sin, 1);
395  yaw_cos.col(0) = cosf(initial_yaw);
396  yaw_sin.col(0) = sinf(initial_yaw);
397 
398  auto dx = (state.vx * yaw_cos).eval();
399  auto dy = (state.vx * yaw_sin).eval();
400 
401  if (isHolonomic()) {
402  dx -= state.vy * yaw_sin;
403  dy += state.vy * yaw_cos;
404  }
405 
406  Eigen::ArrayXf last_x = Eigen::ArrayXf::Constant(trajectories.x.rows(),
407  state.pose.pose.position.x);
408  Eigen::ArrayXf last_y = Eigen::ArrayXf::Constant(trajectories.y.rows(),
409  state.pose.pose.position.y);
410 
411  for (size_t i = 0; i != n_cols; i++) {
412  last_x += dx.col(i) * settings_.model_dt;
413  last_y += dy.col(i) * settings_.model_dt;
414  trajectories.x.col(i) = last_x;
415  trajectories.y.col(i) = last_y;
416  }
417 }
418 
420 {
421  const bool is_holo = isHolonomic();
422  Eigen::ArrayXXf sequence = Eigen::ArrayXXf(settings_.time_steps, is_holo ? 3 : 2);
423  Eigen::Array<float, Eigen::Dynamic, 3> trajectories =
424  Eigen::Array<float, Eigen::Dynamic, 3>(settings_.time_steps, 3);
425 
426  sequence.col(0) = control_sequence_.vx;
427  sequence.col(1) = control_sequence_.wz;
428 
429  if (is_holo) {
430  sequence.col(2) = control_sequence_.vy;
431  }
432 
433  integrateStateVelocities(trajectories, sequence);
434  return trajectories;
435 }
436 
438 {
439  return control_sequence_;
440 }
441 
443 {
444  const bool is_holo = isHolonomic();
445  auto & s = settings_;
446 
447  auto vx_T = control_sequence_.vx.transpose();
448  auto bounded_noises_vx = state_.cvx.rowwise() - vx_T;
449  const float gamma_vx = s.gamma / (s.sampling_std.vx * s.sampling_std.vx);
450  costs_ += (gamma_vx * (bounded_noises_vx.rowwise() * vx_T).rowwise().sum()).eval();
451 
452  if (s.sampling_std.wz > 0.0f) {
453  auto wz_T = control_sequence_.wz.transpose();
454  auto bounded_noises_wz = state_.cwz.rowwise() - wz_T;
455  const float gamma_wz = s.gamma / (s.sampling_std.wz * s.sampling_std.wz);
456  costs_ += (gamma_wz * (bounded_noises_wz.rowwise() * wz_T).rowwise().sum()).eval();
457  }
458 
459  if (is_holo) {
460  auto vy_T = control_sequence_.vy.transpose();
461  auto bounded_noises_vy = state_.cvy.rowwise() - vy_T;
462  const float gamma_vy = s.gamma / (s.sampling_std.vy * s.sampling_std.vy);
463  costs_ += (gamma_vy * (bounded_noises_vy.rowwise() * vy_T).rowwise().sum()).eval();
464  }
465 
466  auto costs_normalized = costs_ - costs_.minCoeff();
467  const float inv_temp = 1.0f / s.temperature;
468  auto softmaxes = (-inv_temp * costs_normalized).exp().eval();
469  softmaxes /= softmaxes.sum();
470 
471  auto softmax_mat = softmaxes.matrix();
472  control_sequence_.vx = state_.cvx.transpose().matrix() * softmax_mat;
473  control_sequence_.wz = state_.cwz.transpose().matrix() * softmax_mat;
474 
475  if (is_holo) {
476  control_sequence_.vy = state_.cvy.transpose().matrix() * softmax_mat;
477  }
478 
480 }
481 
482 geometry_msgs::msg::TwistStamped Optimizer::getControlFromSequenceAsTwist(
483  const builtin_interfaces::msg::Time & stamp)
484 {
485  unsigned int offset = settings_.shift_control_sequence ? 1 : 0;
486 
487  auto vx = control_sequence_.vx(offset);
488  auto wz = control_sequence_.wz(offset);
489 
490  if (isHolonomic()) {
491  auto vy = control_sequence_.vy(offset);
492  return utils::toTwistStamped(vx, vy, wz, stamp, costmap_ros_->getBaseFrameID());
493  }
494 
495  return utils::toTwistStamped(vx, wz, stamp, costmap_ros_->getBaseFrameID());
496 }
497 
498 void Optimizer::setMotionModel(const std::string & model)
499 {
500  if (model == "DiffDrive") {
501  motion_model_ = std::make_shared<DiffDriveMotionModel>();
502  } else if (model == "Omni") {
503  motion_model_ = std::make_shared<OmniMotionModel>();
504  } else if (model == "Ackermann") {
505  motion_model_ = std::make_shared<AckermannMotionModel>(parameters_handler_, name_);
506  } else {
508  std::string(
509  "Model " + model + " is not valid! Valid options are DiffDrive, Omni, "
510  "or Ackermann"));
511  }
512  motion_model_->initialize(settings_.constraints, settings_.model_dt);
513 }
514 
515 void Optimizer::setSpeedLimit(double speed_limit, bool percentage)
516 {
517  auto & s = settings_;
518  if (speed_limit == nav2_costmap_2d::NO_SPEED_LIMIT) {
519  s.constraints.vx_max = s.base_constraints.vx_max;
520  s.constraints.vx_min = s.base_constraints.vx_min;
521  s.constraints.vy = s.base_constraints.vy;
522  s.constraints.wz = s.base_constraints.wz;
523  } else {
524  if (percentage) {
525  // Speed limit is expressed in % from maximum speed of robot
526  double ratio = speed_limit / 100.0;
527  s.constraints.vx_max = s.base_constraints.vx_max * ratio;
528  s.constraints.vx_min = s.base_constraints.vx_min * ratio;
529  s.constraints.vy = s.base_constraints.vy * ratio;
530  s.constraints.wz = s.base_constraints.wz * ratio;
531  } else {
532  // Speed limit is expressed in absolute value
533  double ratio = speed_limit / s.base_constraints.vx_max;
534  s.constraints.vx_max = s.base_constraints.vx_max * ratio;
535  s.constraints.vx_min = s.base_constraints.vx_min * ratio;
536  s.constraints.vy = s.base_constraints.vy * ratio;
537  s.constraints.wz = s.base_constraints.wz * ratio;
538  }
539  }
540 }
541 
543 {
544  return generated_trajectories_;
545 }
546 
547 } // namespace mppi
void on_configure(rclcpp_lifecycle::LifecycleNode::WeakPtr parent, const std::string &name, std::shared_ptr< nav2_costmap_2d::Costmap2DROS >, ParametersHandler *)
Configure critic manager on bringup and load plugins.
void evalTrajectoriesScores(CriticData &data) const
Score trajectories by the set of loaded critic functions.
void reset(mppi::models::OptimizerSettings &settings, bool is_holonomic)
Reset noise generator with settings and model types.
void initialize(mppi::models::OptimizerSettings &settings, bool is_holonomic, const std::string &name, ParametersHandler *param_handler)
Initialize noise generator with settings and model types.
void setNoisedControls(models::State &state, const models::ControlSequence &control_sequence)
set noised control_sequence to state controls
void shutdown()
Shutdown noise generator thread.
void generateNextNoises()
Signal to the noise thread the controller is ready to generate a new noised control for the next iter...
geometry_msgs::msg::TwistStamped 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:162
void updateStateVelocities(models::State &state) const
Update velocities in state.
Definition: optimizer.cpp:304
const models::ControlSequence & getOptimalControlSequence()
Get the optimal control sequence for a cycle for visualization.
Definition: optimizer.cpp:437
void setMotionModel(const std::string &model)
Set the motion model of the vehicle platform.
Definition: optimizer.cpp:498
void setOffset(double controller_frequency)
Using control frequencies and time step size, determine if trajectory offset should be used to popula...
Definition: optimizer.cpp:114
Eigen::ArrayXXf getOptimizedTrajectory()
Get the optimal trajectory for a cycle for visualization.
Definition: optimizer.cpp:419
void reset(bool reset_dynamic_speed_limits=true)
Reset the optimization problem to initial conditions.
Definition: optimizer.cpp:135
rclcpp::Logger logger_
Caution, keep references.
Definition: optimizer.hpp:279
void prepare(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)
Prepare state information on new request for trajectory rollouts.
Definition: optimizer.cpp:213
void integrateStateVelocities(models::Trajectories &trajectories, const models::State &state) const
Rollout velocities in state to poses.
Definition: optimizer.cpp:378
void updateControlSequence()
Update control sequence with state controls weighted by costs using softmax function.
Definition: optimizer.cpp:442
void generateNoisedTrajectories()
updates generated trajectories with noised trajectories from the last cycle's optimal control
Definition: optimizer.cpp:247
bool fallback(bool fail)
Perform fallback behavior to try to recover from a set of trajectories in collision.
Definition: optimizer.cpp:194
bool isHolonomic() const
Whether the motion model is holonomic.
Definition: optimizer.cpp:157
models::Trajectories & getGeneratedTrajectories()
Get the trajectories generated in a cycle for visualization.
Definition: optimizer.cpp:542
void updateInitialStateVelocities(models::State &state) const
Update initial velocity in state.
Definition: optimizer.cpp:311
void shutdown()
Shutdown for optimizer at process end.
Definition: optimizer.cpp:54
void optimize()
Main function to generate, score, and return trajectories.
Definition: optimizer.cpp:185
void setSpeedLimit(double speed_limit, bool percentage)
Set the maximum speed based on the speed limits callback.
Definition: optimizer.cpp:515
void shiftControlSequence()
Shift the optimal control sequence after processing for next iterations initial conditions after exec...
Definition: optimizer.cpp:233
void applyControlSequenceConstraints()
Apply hard vehicle constraints on control sequence.
Definition: optimizer.cpp:255
void getParams()
Obtain the main controller's parameters.
Definition: optimizer.cpp:59
void propagateStateVelocitiesFromInitials(models::State &state) const
predict velocities in state using model for time horizon equal to timesteps
Definition: optimizer.cpp:322
void initialize(rclcpp_lifecycle::LifecycleNode::WeakPtr parent, const std::string &name, std::shared_ptr< nav2_costmap_2d::Costmap2DROS > costmap_ros, ParametersHandler *dynamic_parameters_handler)
Initializes optimizer on startup.
Definition: optimizer.cpp:32
geometry_msgs::msg::TwistStamped getControlFromSequenceAsTwist(const builtin_interfaces::msg::Time &stamp)
Convert control sequence to a twist command.
Definition: optimizer.cpp:482
Handles getting parameters and dynamic parameter changes.
void addPostCallback(T &&callback)
Set a callback to process after parameter changes.
auto getParamGetter(const std::string &ns)
Get an object to retrieve parameters.
Function-object for checking whether a goal has been reached.
A control sequence over time (e.g. trajectory)
State information: velocities, controls, poses, speed.
Definition: state.hpp:32
void reset(unsigned int batch_size, unsigned int time_steps)
Reset state data.
Definition: state.hpp:47
Candidate Trajectories.
void reset(unsigned int batch_size, unsigned int time_steps)
Reset state data.