Nav2 Navigation Stack - rolling  main
ROS 2 Navigation Stack
motion_models.hpp
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 #ifndef NAV2_MPPI_CONTROLLER__MOTION_MODELS_HPP_
17 #define NAV2_MPPI_CONTROLLER__MOTION_MODELS_HPP_
18 
19 #include <Eigen/Dense>
20 
21 #include <cstdint>
22 #include <string>
23 #include <algorithm>
24 
25 #include "nav2_mppi_controller/models/control_sequence.hpp"
26 #include "nav2_mppi_controller/models/state.hpp"
27 #include "nav2_mppi_controller/models/constraints.hpp"
28 
29 #include "nav2_mppi_controller/tools/parameters_handler.hpp"
30 
31 namespace mppi
32 {
33 
34 // Forward declaration of utils method, since utils.hpp can't be included here due
35 // to recursive inclusion.
36 namespace utils
37 {
38 float clamp(const float lower_bound, const float upper_bound, const float input);
39 }
40 
46 {
47 public:
51  MotionModel() = default;
52 
56  virtual ~MotionModel() = default;
57 
63  void initialize(const models::ControlConstraints & control_constraints, float model_dt)
64  {
65  control_constraints_ = control_constraints;
66  model_dt_ = model_dt;
67  }
68 
73  virtual void predict(models::State & state)
74  {
75  const bool is_holo = isHolonomic();
76  float max_delta_vx = model_dt_ * control_constraints_.ax_max;
77  float min_delta_vx = model_dt_ * control_constraints_.ax_min;
78  float max_delta_vy = model_dt_ * control_constraints_.ay_max;
79  float min_delta_vy = model_dt_ * control_constraints_.ay_min;
80  float max_delta_wz = model_dt_ * control_constraints_.az_max;
81 
82  unsigned int n_cols = state.vx.cols();
83 
84  for (unsigned int i = 1; i < n_cols; i++) {
85  auto lower_bound_vx = (state.vx.col(i - 1) >
86  0).select(state.vx.col(i - 1) + min_delta_vx,
87  state.vx.col(i - 1) - max_delta_vx);
88  auto upper_bound_vx = (state.vx.col(i - 1) >
89  0).select(state.vx.col(i - 1) + max_delta_vx,
90  state.vx.col(i - 1) - min_delta_vx);
91 
92  state.vx.col(i) = state.cvx.col(i - 1)
93  .cwiseMax(lower_bound_vx)
94  .cwiseMin(upper_bound_vx);
95 
96  state.wz.col(i) = state.cwz.col(i - 1)
97  .cwiseMax(state.wz.col(i - 1) - max_delta_wz)
98  .cwiseMin(state.wz.col(i - 1) + max_delta_wz);
99 
100  if (is_holo) {
101  auto lower_bound_vy = (state.vy.col(i - 1) >
102  0).select(state.vy.col(i - 1) + min_delta_vy,
103  state.vy.col(i - 1) - max_delta_vy);
104  auto upper_bound_vy = (state.vy.col(i - 1) >
105  0).select(state.vy.col(i - 1) + max_delta_vy,
106  state.vy.col(i - 1) - min_delta_vy);
107 
108  state.vy.col(i) = state.cvy.col(i - 1)
109  .cwiseMax(lower_bound_vy)
110  .cwiseMin(upper_bound_vy);
111  }
112  }
113  }
114 
119  virtual bool isHolonomic() = 0;
120 
125  virtual void applyConstraints(models::ControlSequence & /*control_sequence*/) {}
126 
127 protected:
128  float model_dt_{0.0};
129  models::ControlConstraints control_constraints_{0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
130  0.0f, 0.0f};
131 };
132 
138 {
139 public:
143  explicit AckermannMotionModel(ParametersHandler * param_handler, const std::string & name)
144  {
145  auto getParam = param_handler->getParamGetter(name + ".AckermannConstraints");
146  getParam(min_turning_r_, "min_turning_r", 0.2);
147  }
148 
153  bool isHolonomic() override
154  {
155  return false;
156  }
157 
162  void applyConstraints(models::ControlSequence & control_sequence) override
163  {
164  const auto vx_ptr = control_sequence.vx.data();
165  auto wz_ptr = control_sequence.wz.data();
166  int steps = control_sequence.vx.size();
167  for(int i = 0; i < steps; i++) {
168  float wz_constrained = fabs(*(vx_ptr + i) / min_turning_r_);
169  float & wz_curr = *(wz_ptr + i);
170  wz_curr = utils::clamp(-1 * wz_constrained, wz_constrained, wz_curr);
171  }
172  }
173 
178  float getMinTurningRadius() {return min_turning_r_;}
179 
180 private:
181  float min_turning_r_{0};
182 };
183 
189 {
190 public:
194  DiffDriveMotionModel() = default;
195 
200  bool isHolonomic() override
201  {
202  return false;
203  }
204 };
205 
211 {
212 public:
216  OmniMotionModel() = default;
217 
222  bool isHolonomic() override
223  {
224  return true;
225  }
226 };
227 
228 } // namespace mppi
229 
230 #endif // NAV2_MPPI_CONTROLLER__MOTION_MODELS_HPP_
Ackermann motion model.
float getMinTurningRadius()
Get minimum turning radius of ackermann drive.
void applyConstraints(models::ControlSequence &control_sequence) override
Apply hard vehicle constraints to a control sequence.
bool isHolonomic() override
Whether the motion model is holonomic, using Y axis.
AckermannMotionModel(ParametersHandler *param_handler, const std::string &name)
Constructor for mppi::AckermannMotionModel.
Differential drive motion model.
DiffDriveMotionModel()=default
Constructor for mppi::DiffDriveMotionModel.
bool isHolonomic() override
Whether the motion model is holonomic, using Y axis.
Abstract motion model for modeling a vehicle.
void initialize(const models::ControlConstraints &control_constraints, float model_dt)
Initialize motion model on bringup and set required variables.
virtual void predict(models::State &state)
With input velocities, find the vehicle's output velocities.
virtual void applyConstraints(models::ControlSequence &)
Apply hard vehicle constraints to a control sequence.
MotionModel()=default
Constructor for mppi::MotionModel.
virtual bool isHolonomic()=0
Whether the motion model is holonomic, using Y axis.
virtual ~MotionModel()=default
Destructor for mppi::MotionModel.
Omnidirectional motion model.
OmniMotionModel()=default
Constructor for mppi::OmniMotionModel.
bool isHolonomic() override
Whether the motion model is holonomic, using Y axis.
Handles getting parameters and dynamic parameter changes.
auto getParamGetter(const std::string &ns)
Get an object to retrieve parameters.
Constraints on control.
Definition: constraints.hpp:26
A control sequence over time (e.g. trajectory)
State information: velocities, controls, poses, speed.
Definition: state.hpp:32