Nav2 Navigation Stack - kilted  kilted
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.cvx.col(i - 1) = state.cvx.col(i - 1)
93  .cwiseMax(lower_bound_vx)
94  .cwiseMin(upper_bound_vx);
95  state.vx.col(i) = state.cvx.col(i - 1);
96 
97  state.cwz.col(i - 1) = state.cwz.col(i - 1)
98  .cwiseMax(state.wz.col(i - 1) - max_delta_wz)
99  .cwiseMin(state.wz.col(i - 1) + max_delta_wz);
100  state.wz.col(i) = state.cwz.col(i - 1);
101 
102  if (is_holo) {
103  auto lower_bound_vy = (state.vy.col(i - 1) >
104  0).select(state.vy.col(i - 1) + min_delta_vy,
105  state.vy.col(i - 1) - max_delta_vy);
106  auto upper_bound_vy = (state.vy.col(i - 1) >
107  0).select(state.vy.col(i - 1) + max_delta_vy,
108  state.vy.col(i - 1) - min_delta_vy);
109  state.cvy.col(i - 1) = state.cvy.col(i - 1)
110  .cwiseMax(lower_bound_vy)
111  .cwiseMin(upper_bound_vy);
112  state.vy.col(i) = state.cvy.col(i - 1);
113  }
114  }
115  }
116 
121  virtual bool isHolonomic() = 0;
122 
127  virtual void applyConstraints(models::ControlSequence & /*control_sequence*/) {}
128 
129 protected:
130  float model_dt_{0.0};
131  models::ControlConstraints control_constraints_{0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
132  0.0f, 0.0f};
133 };
134 
140 {
141 public:
145  explicit AckermannMotionModel(ParametersHandler * param_handler, const std::string & name)
146  {
147  auto getParam = param_handler->getParamGetter(name + ".AckermannConstraints");
148  getParam(min_turning_r_, "min_turning_r", 0.2);
149  }
150 
155  bool isHolonomic() override
156  {
157  return false;
158  }
159 
164  void applyConstraints(models::ControlSequence & control_sequence) override
165  {
166  const auto vx_ptr = control_sequence.vx.data();
167  auto wz_ptr = control_sequence.wz.data();
168  int steps = control_sequence.vx.size();
169  for(int i = 0; i < steps; i++) {
170  float wz_constrained = fabs(*(vx_ptr + i) / min_turning_r_);
171  float & wz_curr = *(wz_ptr + i);
172  wz_curr = utils::clamp(-1 * wz_constrained, wz_constrained, wz_curr);
173  }
174  }
175 
180  float getMinTurningRadius() {return min_turning_r_;}
181 
182 private:
183  float min_turning_r_{0};
184 };
185 
191 {
192 public:
196  DiffDriveMotionModel() = default;
197 
202  bool isHolonomic() override
203  {
204  return false;
205  }
206 };
207 
213 {
214 public:
218  OmniMotionModel() = default;
219 
224  bool isHolonomic() override
225  {
226  return true;
227  }
228 };
229 
230 } // namespace mppi
231 
232 #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