38 #ifndef ERGODIC_CONTROL_HPP
39 #define ERGODIC_CONTROL_HPP
45 #include <nav_msgs/Path.h>
65 inline vec
rhodot(
const vec& rho,
const vec& gdx,
const vec& dbar,
const mat& fdx)
67 return -gdx - dbar - fdx.t() * rho;
72 template <
class ModelT>
91 double horizon,
double resolution,
double exploration_weight,
92 unsigned int num_basis,
unsigned int buffer_size,
93 unsigned int batch_size,
const mat& Rinv,
const vec& umin,
112 nav_msgs::Path
path(
const std::string& map_frame_id)
const;
187 template <
class ModelT>
189 double dt,
double horizon,
double resolution,
190 double exploration_weight,
unsigned int num_basis,
191 unsigned int buffer_size,
unsigned int batch_size,
192 const mat& Rinv,
const vec& umin,
const vec& umax)
194 , collision_(collision)
197 , resolution_(resolution)
198 , expl_weight_(exploration_weight)
199 , steps_(static_cast<unsigned int>(
std::abs(horizon / dt)))
201 , ut_(3, steps_, arma::fill::zeros)
202 , phik_(num_basis * num_basis)
203 , rhoT_(model.state_space, arma::fill::zeros)
204 , map_pos_(2, arma::fill::zeros)
207 , pose_(model.state_space, arma::fill::zeros)
208 , basis_(0.0, 0.0, num_basis)
209 , buffer_(buffer_size, batch_size)
214 throw std::invalid_argument(
"Need at least two steps in forward simulation. \
215 Increase the horizon or decrease the time step.");
220 rhodot_ = std::bind(
rhodot, std::placeholders::_1, std::placeholders::_2,
221 std::placeholders::_3, std::placeholders::_4);
224 template <
class ModelT>
233 ut_.cols(0, ut_.n_cols - 2) = ut_.cols(1, ut_.n_cols - 1);
234 ut_.col(ut_.n_cols - 1).fill(0.0);
237 const mat traj = rk4_.solve(model_, pose_, ut_, horizon_);
240 mat xt_total = buffer_.sampleMemory(traj);
243 xt_total.row(0) -= map_pos_(0);
244 xt_total.row(1) -= map_pos_(1);
264 const mat xt = xt_total.cols(xt_total.n_cols - steps_, xt_total.n_cols - 1);
267 const vec ck = basis_.trajCoeff(xt_total);
270 const mat edx = gradErgodicMetric(ck, xt);
273 const mat bdx = gradBarrier(xt);
277 const mat rhot = rk4_.solve(rhodot_, model_, rhoT_, xt, ut_, edx, bdx, horizon_);
305 updateControl(xt, rhot);
313 template <
class ModelT>
316 return rk4_.solve(model_, pose_, ut_, horizon_);
319 template <
class ModelT>
323 path.header.frame_id = map_frame_id;
324 path.poses.resize(steps_);
326 const mat opt_traj = rk4_.solve(model_, pose_, ut_, horizon_);
327 for (
unsigned int i = 0; i < opt_traj.n_cols; i++)
329 path.poses.at(i).pose.position.x = opt_traj(0, i);
330 path.poses.at(i).pose.position.y = opt_traj(1, i);
335 path.poses.at(i).pose.orientation.x = quat.x();
336 path.poses.at(i).pose.orientation.y = quat.y();
337 path.poses.at(i).pose.orientation.z = quat.z();
338 path.poses.at(i).pose.orientation.w = quat.w();
344 template <
class ModelT>
350 template <
class ModelT>
356 template <
class ModelT>
362 template <
class ModelT>
366 map_pos_(0) = grid.
xmin();
367 map_pos_(1) = grid.
ymin();
370 const auto mx = grid.
xmax() - grid.
xmin();
371 const auto my = grid.
ymax() - grid.
ymin();
379 std::cout <<
"Updating target distribution grid... ";
387 const auto nx =
axis_length(0.0, basis_.lx_, resolution_) + 1;
388 const auto ny =
axis_length(0.0, basis_.ly_, resolution_) + 1;
391 mat phi_grid(2, nx * ny);
393 unsigned int col = 0;
395 for (
unsigned int i = 0; i < ny; i++)
398 for (
unsigned int j = 0; j < nx; j++)
400 phi_grid(0, col) = x;
401 phi_grid(1, col) = y;
411 const vec phi_vals = target_.fill(map_pos_, phi_grid);
413 phik_ = basis_.spatialCoeff(phi_vals, phi_grid);
415 std::cout <<
"done" << std::endl;
418 template <
class ModelT>
422 const vec fourier_diff = basis_.lamdak_ % (ck - phik_);
424 mat edx(model_.state_space, steps_);
425 for (
unsigned int i = 0; i < steps_; i++)
427 edx(span(0, 1), span(i, i)) = basis_.gradFourierBasis(xt.col(i)) * fourier_diff;
433 edx.rows(0, 1) *= expl_weight_;
438 template <
class ModelT>
441 for (
unsigned int i = 0; i < xt.n_cols; i++)
444 ut_.col(i) = -Rinv_ * model_.fdu(xt.col(i)).t() * rhot.col(i);
447 ut_(0, i) = std::clamp(ut_(0, i), umin_(0), umax_(0));
448 ut_(1, i) = std::clamp(ut_(1, i), umin_(1), umax_(1));
449 ut_(2, i) = std::clamp(ut_(2, i), umin_(2), umax_(2));
453 template <
class ModelT>
457 const auto weight = 25.0;
458 const auto eps = 0.05;
461 mat bdx(model_.state_space, steps_, arma::fill::zeros);
462 for (
unsigned int i = 0; i < steps_; i++)
464 bdx(0, i) += 2.0 * (xt(0, i) > basis_.lx_ - eps) * (xt(0, i) - (basis_.lx_ - eps));
465 bdx(1, i) += 2.0 * (xt(1, i) > basis_.ly_ - eps) * (xt(1, i) - (basis_.ly_ - eps));
467 bdx(0, i) += 2.0 * (xt(0, i) < eps) * (xt(0, i) - eps);
468 bdx(1, i) += 2.0 * (xt(1, i) < eps) * (xt(1, i) - eps);
471 bdx.rows(0, 1) *= weight;