38 void ControlLimitedDDPSolver::Instantiate(
const ControlLimitedDDPSolverInitializer& init)
41 base_parameters_ = AbstractDDPSolverInitializer(ControlLimitedDDPSolverInitializer(parameters_));
44 void ControlLimitedDDPSolver::BackwardPass()
46 const Eigen::MatrixXd& control_limits = dynamics_solver_->get_control_limits();
48 Vx_.back().noalias() = prob_->GetStateCostJacobian(T_ - 1);
49 Vxx_.back().noalias() = prob_->GetStateCostHessian(T_ - 1);
53 Eigen::array<Eigen::IndexPair<int>, 1> dims = {Eigen::IndexPair<int>(1, 0)};
55 Eigen::VectorXd
x(NX_), u(NU_);
56 for (
int t = T_ - 2; t >= 0; t--)
61 dynamics_solver_->ComputeDerivatives(
x, u);
62 fx_[t].noalias() = dynamics_solver_->get_Fx();
63 fu_[t].noalias() = dynamics_solver_->get_Fu();
65 Qx_[t].noalias() = dt_ * prob_->GetStateCostJacobian(t) + fx_[t].transpose() * Vx_[t + 1];
66 Qu_[t].noalias() = dt_ * prob_->GetControlCostJacobian(t) + fu_[t].transpose() * Vx_[t + 1];
69 Vxx_[t + 1].diagonal().array() += lambda_;
71 Qxx_[t].noalias() = dt_ * prob_->GetStateCostHessian(t) + fx_[t].transpose() * Vxx_[t + 1] * fx_[t];
72 Quu_[t].noalias() = dt_ * prob_->GetControlCostHessian(t) + fu_[t].transpose() * Vxx_[t + 1] * fu_[t];
74 Qux_[t].noalias() = fu_[t].transpose() * Vxx_[t + 1] * fx_[t];
76 if (parameters_.UseSecondOrderDynamics && dynamics_solver_->get_has_second_order_derivatives())
78 Eigen::Tensor<double, 1> Vx_tensor = Eigen::TensorMap<Eigen::Tensor<double, 1>>(Vx_[t + 1].data(), NDX_);
79 Qxx_[t].noalias() +=
Eigen::TensorToMatrix((Eigen::Tensor<double, 2>)dynamics_solver_->fxx(
x, u).contract(Vx_tensor, dims), NDX_, NDX_) * dt_;
80 Quu_[t].noalias() +=
Eigen::TensorToMatrix((Eigen::Tensor<double, 2>)dynamics_solver_->fuu(
x, u).contract(Vx_tensor, dims), NU_, NU_) * dt_;
81 Qux_[t].noalias() +=
Eigen::TensorToMatrix((Eigen::Tensor<double, 2>)dynamics_solver_->fxu(
x, u).contract(Vx_tensor, dims), NU_, NDX_) * dt_;
84 Eigen::VectorXd low_limit = control_limits.col(0) - u,
85 high_limit = control_limits.col(1) - u;
89 if (parameters_.UseNewBoxQP)
91 boxqp_sol =
BoxQP(Quu_[t], Qu_[t], low_limit, high_limit, u, 0.1, 100, 1e-5, lambda_, parameters_.BoxQPUsePolynomialLinesearch, parameters_.BoxQPUseCholeskyFactorization);
95 boxqp_sol =
ExoticaBoxQP(Quu_[t], Qu_[t], low_limit, high_limit, u, 0.1, 100, 1e-5, lambda_, parameters_.BoxQPUsePolynomialLinesearch, parameters_.BoxQPUseCholeskyFactorization);
98 Quu_inv_[t].setZero();
100 for (std::size_t i = 0; i < boxqp_sol.
free_idx.size(); ++i)
101 for (std::size_t j = 0; j < boxqp_sol.
free_idx.size(); ++j)
105 K_[t].noalias() = -Quu_inv_[t] * Qux_[t];
106 k_[t].noalias() = boxqp_sol.
x;
110 for (std::size_t i = 0; i < boxqp_sol.
clamped_idx.size(); ++i)
113 Vx_[t].noalias() = Qx_[t] + K_[t].transpose() * Quu_[t] * k_[t] + K_[t].transpose() * Qu_[t] + Qux_[t].transpose() * k_[t];
114 Vxx_[t].noalias() = Qxx_[t] + K_[t].transpose() * Quu_[t] * K_[t] + K_[t].transpose() * Qux_[t] + Qux_[t].transpose() * K_[t];
115 Vxx_[t] = 0.5 * (Vxx_[t] + Vxx_[t].transpose()).eval();
#define REGISTER_MOTIONSOLVER_TYPE(TYPE, DERIV)
std::vector< size_t > clamped_idx
std::vector< size_t > free_idx
MatrixType< Scalar > TensorToMatrix(const Eigen::Tensor< Scalar, rank > &tensor, const sizeType rows, const sizeType cols)
BoxQPSolution ExoticaBoxQP(const Eigen::MatrixXd &H, const Eigen::VectorXd &q, const Eigen::VectorXd &b_low, const Eigen::VectorXd &b_high, const Eigen::VectorXd &x_init, const double gamma, const int max_iterations, const double epsilon, const double lambda, bool use_polynomial_linesearch=false, bool use_cholesky_factorization=false)
BoxQPSolution BoxQP(const Eigen::MatrixXd &H, const Eigen::VectorXd &q, const Eigen::VectorXd &b_low, const Eigen::VectorXd &b_high, const Eigen::VectorXd &x_init, const double th_acceptstep, const int max_iterations, const double th_gradient_tolerance, const double lambda, bool use_polynomial_linesearch=true, bool use_cholesky_factorization=true)