diff --git a/nav2_mppi_controller/include/nav2_mppi_controller/models/optimizer_settings.hpp b/nav2_mppi_controller/include/nav2_mppi_controller/models/optimizer_settings.hpp index 5892dfe687e..419975180b5 100644 --- a/nav2_mppi_controller/include/nav2_mppi_controller/models/optimizer_settings.hpp +++ b/nav2_mppi_controller/include/nav2_mppi_controller/models/optimizer_settings.hpp @@ -31,6 +31,7 @@ struct OptimizerSettings models::ControlConstraints constraints{0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}; models::SamplingStd sampling_std{0.0f, 0.0f, 0.0f}; float model_dt{0.0f}; + float model_delay{0.0f}; float temperature{0.0f}; float gamma{0.0f}; unsigned int batch_size{0u}; diff --git a/nav2_mppi_controller/include/nav2_mppi_controller/motion_models.hpp b/nav2_mppi_controller/include/nav2_mppi_controller/motion_models.hpp index 5741313a213..dafdd612f9e 100644 --- a/nav2_mppi_controller/include/nav2_mppi_controller/motion_models.hpp +++ b/nav2_mppi_controller/include/nav2_mppi_controller/motion_models.hpp @@ -60,10 +60,12 @@ class MotionModel * @param control_constraints Constraints on control * @param model_dt duration of a time step */ - void initialize(const models::ControlConstraints & control_constraints, float model_dt) + void initialize(const models::ControlConstraints & control_constraints, float model_dt, + float model_delay) { control_constraints_ = control_constraints; model_dt_ = model_dt; + model_delay_ = model_delay; } /** @@ -116,6 +118,25 @@ class MotionModel state.vy.col(i) = state.cvy.col(i - 1); } } + + // Apply model delay + if(model_delay_ == 0.0) {return;} + unsigned int offset = std::floor((model_delay_ / model_dt_) + 0.5); + auto state_copy = state; + for (unsigned int i = 0; i != state.vx.shape(0); i++) { + for (unsigned int j = 1; j != state.vx.shape(1); j++) { + // Keep the first value before delay (because we cannot do better) + if (j < offset) { + state.vx(i, j) = state_copy.vx(i, 0); + state.wz(i, j) = state_copy.wz(i, 0); + if (is_holo) {state.vy(i, j) = state_copy.vy(i, 0);} + } else { // move the command to express delay + state.vx(i, j) = state_copy.vx(i, j - offset); + state.wz(i, j) = state_copy.wz(i, j - offset); + if (is_holo) {state.vy(i, j) = state_copy.vy(i, j - offset);} + } + } + } } /** @@ -132,6 +153,7 @@ class MotionModel protected: float model_dt_{0.0}; + float model_delay_{0.0}; models::ControlConstraints control_constraints_{0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}; }; diff --git a/nav2_mppi_controller/src/optimizer.cpp b/nav2_mppi_controller/src/optimizer.cpp index c16c953d90d..f19d79a5ff5 100644 --- a/nav2_mppi_controller/src/optimizer.cpp +++ b/nav2_mppi_controller/src/optimizer.cpp @@ -102,6 +102,7 @@ void Optimizer::getParams() } getParam(s.model_dt, "model_dt", 0.05f); + getParam(s.model_delay, "model_delay", 0.0f); getParam(s.time_steps, "time_steps", 56); getParam(s.batch_size, "batch_size", 1000); getParam(s.iteration_count, "iteration_count", 1); @@ -192,7 +193,7 @@ void Optimizer::reset(bool reset_dynamic_speed_limits) generated_trajectories_.reset(settings_.batch_size, settings_.time_steps); noise_generator_.reset(settings_, isHolonomic()); - motion_model_->initialize(settings_.constraints, settings_.model_dt); + motion_model_->initialize(settings_.constraints, settings_.model_dt, settings_.model_delay); trajectory_validator_->initialize( parent_, name_ + ".TrajectoryValidator", costmap_ros_, parameters_handler_, tf_buffer_, settings_); @@ -590,7 +591,7 @@ void Optimizer::setMotionModel(const std::string & model) "Model " + model + " is not valid! Valid options are DiffDrive, Omni, " "or Ackermann")); } - motion_model_->initialize(settings_.constraints, settings_.model_dt); + motion_model_->initialize(settings_.constraints, settings_.model_dt, settings_.model_delay); } void Optimizer::setSpeedLimit(double speed_limit, bool percentage)