16 #ifndef NAV2_MPPI_CONTROLLER__MOTION_MODELS_HPP_
17 #define NAV2_MPPI_CONTROLLER__MOTION_MODELS_HPP_
19 #include <Eigen/Dense>
26 #include "nav2_mppi_controller/models/control_sequence.hpp"
27 #include "nav2_mppi_controller/models/state.hpp"
28 #include "nav2_mppi_controller/models/constraints.hpp"
30 #include "nav2_mppi_controller/tools/parameters_handler.hpp"
69 float model_delay_vx,
float model_delay_vy,
float model_delay_wz,
bool clamp_raw_controls)
71 control_constraints_ = control_constraints;
73 model_delay_vx_ = model_delay_vx;
74 model_delay_vy_ = model_delay_vy;
75 model_delay_wz_ = model_delay_wz;
76 clamp_raw_controls_ = clamp_raw_controls;
78 cmd_history_vx_.resize(
offsetSteps(model_delay_vx_), 0.0f);
79 cmd_history_vy_.resize(
offsetSteps(model_delay_vy_), 0.0f);
80 cmd_history_wz_.resize(
offsetSteps(model_delay_wz_), 0.0f);
99 std::fill(cmd_history_vx_.begin(), cmd_history_vx_.end(), 0.0f);
100 std::fill(cmd_history_vy_.begin(), cmd_history_vy_.end(), 0.0f);
101 std::fill(cmd_history_wz_.begin(), cmd_history_wz_.end(), 0.0f);
111 float max_delta_vx = model_dt_ * control_constraints_.ax_max;
112 float min_delta_vx = model_dt_ * control_constraints_.ax_min;
113 float max_delta_vy = model_dt_ * control_constraints_.ay_max;
114 float min_delta_vy = model_dt_ * control_constraints_.ay_min;
115 float max_delta_wz = model_dt_ * control_constraints_.az_max;
116 unsigned int n_cols = state.vx.cols();
119 for (
unsigned int i = 1; i < n_cols; i++) {
120 auto lower_bound_vx = (state.vx.col(i - 1) >
122 state.vx.col(i - 1) + min_delta_vx,
123 state.vx.col(i - 1) - max_delta_vx);
124 auto upper_bound_vx = (state.vx.col(i - 1) >
126 state.vx.col(i - 1) + max_delta_vx,
127 state.vx.col(i - 1) - min_delta_vx);
128 state.vx.col(i) = state.cvx.col(i - 1)
129 .cwiseMax(lower_bound_vx)
130 .cwiseMin(upper_bound_vx);
131 if (clamp_raw_controls_) {
132 state.cvx.col(i - 1) = state.vx.col(i);
135 state.wz.col(i) = state.cwz.col(i - 1)
136 .cwiseMax(state.wz.col(i - 1) - max_delta_wz)
137 .cwiseMin(state.wz.col(i - 1) + max_delta_wz);
138 if (clamp_raw_controls_) {
139 state.cwz.col(i - 1) = state.wz.col(i);
143 auto lower_bound_vy = (state.vy.col(i - 1) >
145 state.vy.col(i - 1) + min_delta_vy,
146 state.vy.col(i - 1) - max_delta_vy);
147 auto upper_bound_vy = (state.vy.col(i - 1) >
149 state.vy.col(i - 1) + max_delta_vy,
150 state.vy.col(i - 1) - min_delta_vy);
151 state.vy.col(i) = state.cvy.col(i - 1)
152 .cwiseMax(lower_bound_vy)
153 .cwiseMin(upper_bound_vy);
154 if (clamp_raw_controls_) {
155 state.cvy.col(i - 1) = state.vy.col(i);
160 const unsigned int offset_vx = std::floor((model_delay_vx_ / model_dt_) + 0.5);
161 const unsigned int offset_vy = std::floor((model_delay_vy_ / model_dt_) + 0.5);
162 const unsigned int offset_wz = std::floor((model_delay_wz_ / model_dt_) + 0.5);
164 if (offset_vx > 0u || offset_wz > 0u || (is_holo && offset_vy > 0u)) {
189 unsigned int offset_vx,
unsigned int offset_vy,
unsigned int offset_wz)
const
191 auto shift = [](Eigen::ArrayXXf & velocities,
unsigned int offset,
192 const std::vector<float> & history) {
193 const unsigned int cols =
static_cast<unsigned int>(velocities.cols());
194 if (offset == 0u || cols == 0u) {
199 for (
unsigned int k = (offset < cols) ? cols - offset : 0u; k > 0; --k) {
200 velocities.col(offset + k - 1) = velocities.col(k);
204 const unsigned int end = std::min(offset, cols);
205 for (
unsigned int j = 1; j < end; ++j) {
206 velocities.col(j).setConstant(history[j]);
210 shift(state.vx, offset_vx, cmd_history_vx_);
211 shift(state.wz, offset_wz, cmd_history_wz_);
214 shift(state.vy, offset_vy, cmd_history_vy_);
223 if (delay <= 0.0f || model_dt_ <= 0.0f) {
226 return static_cast<std::size_t
>(std::floor(delay / model_dt_ + 0.5f));
232 static void pushOne(std::vector<float> & buf,
float v)
234 if (buf.empty()) {
return;}
235 std::rotate(buf.begin(), buf.begin() + 1, buf.end());
239 float model_dt_{0.0};
240 float model_delay_vx_{0.0};
241 float model_delay_vy_{0.0};
242 float model_delay_wz_{0.0};
243 bool clamp_raw_controls_{
false};
246 std::vector<float> cmd_history_vx_;
247 std::vector<float> cmd_history_vy_;
248 std::vector<float> cmd_history_wz_;
250 models::ControlConstraints control_constraints_{0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
273 const std::string & plugin_name)
override
276 getParam(min_turning_r_,
"min_turning_r", 0.2f);
294 const auto wz_constrained = control_sequence.vx.abs() / min_turning_r_;
295 control_sequence.wz = control_sequence.wz
296 .max((-wz_constrained))
297 .min(wz_constrained);
306 float min_turning_r_{0.0f};
void initialize(ParametersHandler *param_handler, const std::string &plugin_name) override
Initialize motion model.
AckermannMotionModel()=default
Constructor for mppi::AckermannMotionModel.
bool isHolonomic() const override
Whether the motion model is holonomic, using Y axis.
float getMinTurningRadius() const
Get minimum turning radius of ackermann drive.
void applyConstraints(models::ControlSequence &control_sequence) override
Apply hard vehicle constraints to a control sequence.
Differential drive motion model.
bool isHolonomic() const override
Whether the motion model is holonomic, using Y axis.
DiffDriveMotionModel()=default
Constructor for mppi::DiffDriveMotionModel.
Abstract pluginlib class for modeling a vehicle.
void applyDelayShift(models::State &state, bool is_holo, unsigned int offset_vx, unsigned int offset_vy, unsigned int offset_wz) const
Apply the per-axis input-delay shift to velocity rollout.
virtual bool isHolonomic() const =0
Whether the motion model is holonomic, using Y axis.
virtual void initialize(ParametersHandler *, const std::string &)
Initialize motion model on bringup.
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.
void clearCommandHistory()
Zero the ring buffers.
void setConstraints(const models::ControlConstraints &control_constraints, float model_dt, float model_delay_vx, float model_delay_vy, float model_delay_wz, bool clamp_raw_controls)
Initialize motion model on bringup and set required variables.
std::size_t offsetSteps(float delay) const
Convert a delay in seconds to an offset in number of rollout steps, rounding to the nearest step.
MotionModel()=default
Constructor for mppi::MotionModel.
static void pushOne(std::vector< float > &buf, float v)
Push a value to the back of a ring buffer and rotate the elements.
virtual ~MotionModel()=default
Destructor for mppi::MotionModel.
void pushCommandHistory(float vx, float vy, float wz)
Push the most recently published command to the per-axis history ring buffers. Called once per contro...
Omnidirectional motion model.
OmniMotionModel()=default
Constructor for mppi::OmniMotionModel.
bool isHolonomic() const 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.
A control sequence over time (e.g. trajectory)
State information: velocities, controls, poses, speed.