31 #ifndef INCLUDE_DTO_SNOPT_INTERFACE_HPP_ 
   32 #define INCLUDE_DTO_SNOPT_INTERFACE_HPP_ 
   34 #include <Eigen/Dense> 
   36 #include <snopt7/snoptProblem.hpp> 
   38 namespace DirectTrajectoryOptimization {
 
   41 template <
typename DIMENSIONS>
 
   42 class DTOMethodInterface;
 
   48 template <
class DIMENSIONS>
 
   54     EIGEN_MAKE_ALIGNED_OPERATOR_NEW
 
   56     typedef typename DIMENSIONS::state_vector_array_t state_vector_array_t;
 
   57     typedef typename DIMENSIONS::control_vector_array_t control_vector_array_t;
 
   67         bool snopt_verbose, 
bool feasible_point_only) :
 
   70     this->_verbose = snopt_verbose;
 
   73             minor_print_level_param = 0;
 
   74             major_print_level_param = 1;
 
   77         _feasible_point_only = feasible_point_only;
 
   84         if (use_computeJacobian) {
 
   97     std::shared_ptr<DTOMethodInterface<DIMENSIONS> > 
_method;                   
 
   99     snFunA spt_constraints_function = NULL;
 
  100     int status_output_flag = 0;
 
  101     bool use_computeJacobian = 
false;
 
  102     bool use_print_file = 
false;
 
  103     bool _feasible_point_only = 
false;
 
  106     static void NLP_function( 
int    *Status, 
int *n,    
double x[],
 
  107               int    *needF,  
int *neF,  
double F[],
 
  108               int    *needG,  
int *neG,  
double G[],
 
  109               char   *cu,     
int *lencu,
 
  110               int    iu[],    
int *leniu,
 
  111               double ru[],    
int *lenru );
 
  114             const std::string & problem_name,
 
  115             const std::string & output_file,
 
  116             const std::string & param_file = 
"",
 
  117             const bool & computeJacobian = 
false) 
override;
 
  118     void setupSNOPTvariables();
 
  119     void setupNLPsolver();
 
  120     void setupWarmStart();
 
  122     void estimateJacobianStructure();
 
  123     virtual void Solve(
bool warminit=
false) 
override;
 
  125     void setSparsityVariables();
 
  126     void setSnoptFLimits();
 
  128     void readParametersFromFile(
const std::string & param_file);
 
  131     void validateSNOPTStatus(
const int & status,
 
  132             const Eigen::Map<Eigen::VectorXd> & x, 
const Eigen::Map<Eigen::VectorXd> & F);
 
  135                 state_vector_array_t &yTraj,
 
  136                 control_vector_array_t &uTraj,
 
  137                 Eigen::VectorXd &hTraj) 
override;
 
  139             state_vector_array_t & y_trajectory,
 
  140             control_vector_array_t & u_trajectory,
 
  141             Eigen::VectorXd & h_trajectory,
 
  142             std::vector<int> & phaseId) 
override;
 
  145       state_vector_array_t &ydotTraj, control_vector_array_t & uTraj,
 
  146       Eigen::VectorXd &hTraj, std::vector<int> &phaseId) 
override;
 
  148     virtual void GetFVector(Eigen::VectorXd &fVec)
 override {fVec = F_vector;}
 
  151             Eigen::VectorXi & _x_state,
 
  152             Eigen::VectorXd & _x_mul,
 
  153             Eigen::VectorXi & _f_state,
 
  154             Eigen::VectorXd & _f_mul) 
override;
 
  157             const state_vector_array_t & y_sol,
 
  158             const control_vector_array_t & u_sol,
 
  159             const Eigen::VectorXd & h_sol) 
override;
 
  162             const Eigen::VectorXd & x_mul,
 
  163             const Eigen::VectorXi & f_state,
 
  164             const Eigen::VectorXd & f_mul) 
override;
 
  166     void SetVerifyLevel(
const int & level)
 override {
 
  167         if(level > -2 && level < 4)
 
  168             verify_level_param = level;
 
  170             std::cout << 
"incorrect verification level!" << std::endl;
 
  171             std::exit(EXIT_FAILURE);
 
  175     void UsePrintFile(
const bool & flag)
 override {
 
  176         use_print_file = flag;
 
  180     char* spt_name_of_problem = NULL;
 
  181     char* spt_name_of_output_file = NULL;
 
  182     char* spt_name_of_print_file=NULL;
 
  192     int original_size_G = 0;
 
  197     double * spt_A = NULL;
 
  199     int * spt_iGfun = NULL;
 
  200     int * spt_jGvar = NULL;
 
  202     int * spt_iAfun = NULL;
 
  203     int * spt_jAvar = NULL;
 
  205     double * spt_xlb = NULL;
 
  206     double * spt_xub = NULL;
 
  208     double * spt_Flb = NULL;
 
  209     double * spt_Fub = NULL;
 
  211     Eigen::VectorXd x_variables;
 
  212     Eigen::VectorXd x_variables_validation;
 
  213     Eigen::VectorXd x_multipliers;
 
  214     Eigen::VectorXi x_state;
 
  216     Eigen::VectorXd F_vector;
 
  217     Eigen::VectorXd F_vector_validation;
 
  218     Eigen::VectorXd F_multipliers;
 
  219     Eigen::VectorXi F_state;
 
  221     int snopt_warm_flag = 0;
 
  223     Eigen::VectorXd snopt_Flb_v;
 
  224     Eigen::VectorXd snopt_Fub_v;
 
  225     Eigen::VectorXi snopt_iGfun;
 
  226     Eigen::VectorXi snopt_jGvar;
 
  231     int derivative_option_param = 0;
 
  233     int scale_option_param = 1;
 
  234     int verify_level_param = -1;
 
  235     int major_iteration_limit_param = 80000;
 
  236     int minor_iteration_limit_param = 80000;
 
  237     int iteration_limit_param = 40000000;
 
  238     double major_optimality_tolerance_param = 1e-1;
 
  239     double major_feasibility_tolerance_param = 1e-6;
 
  240     double minor_feasibility_tolerance_param = 1e-6;
 
  241   int print_file_param = 0;
 
  242   int minor_print_level_param = 0;
 
  243   int major_print_level_param = 0;
 
  244   int backup_basis_file_param = 0;
 
  245   double line_search_tolerance_param = 0.9;
 
  247     std::string print_solution_param = 
"No";
 
  250 template<
class DIMENSIONS>
 
  251 std::shared_ptr<DTOSnoptInterface<DIMENSIONS> > DTOSnoptInterface<DIMENSIONS>::interface_pointer;
 
  253 template <
class DIMENSIONS>
 
  255         const std::string & output_file, 
const std::string & param_file ,
 
  256         const bool &computeJacobian) {
 
  258     use_computeJacobian = computeJacobian;
 
  261     _method->Initialize();
 
  263     std::string print_file_name = output_file;
 
  264     std::string real_output_file = output_file + 
".out";
 
  266     spt_name_of_problem = 
const_cast<char*
>(problem_name.c_str());
 
  267     spt_name_of_output_file = 
const_cast<char*
>(real_output_file.c_str());
 
  268     spt_name_of_print_file = 
const_cast<char*
>(print_file_name.c_str());
 
  271     setupSNOPTvariables();
 
  273     if (param_file!=
"") {
 
  274         readParametersFromFile(param_file);
 
  277     nlp_solver = std::shared_ptr<snoptProblemA>(
new snoptProblemA(spt_name_of_problem));
 
  280     SetupSolverParameters();
 
  283 template<
class DIMENSIONS>
 
  286     interface_pointer = std::enable_shared_from_this<DTOSnoptInterface<DIMENSIONS>>::shared_from_this();
 
  287     spt_constraints_function = &this->DTOSnoptInterface::NLP_function;
 
  290     spt_n_vars = _method->myNLP.GetNumVars();
 
  293     spt_lenF = _method->myNLP.GetNumF() + 1;
 
  294     spt_xlb = _method->myNLP.GetXlb_p();
 
  295     spt_xub = _method->myNLP.GetXub_p();
 
  297     x_variables.resize(spt_n_vars);
 
  298     x_variables_validation.resize(spt_n_vars);
 
  299     x_variables.setZero();
 
  300     x_multipliers.resize(spt_n_vars);
 
  301     x_state.resize(spt_n_vars);
 
  304     F_vector.resize(spt_lenF);
 
  305     F_vector_validation.resize(spt_lenF);
 
  306     F_multipliers.resize(spt_lenF);
 
  307     F_state.resize(spt_lenF);
 
  310     setSparsityVariables();
 
  313 template <
class DIMENSIONS>
 
  314 void DTOSnoptInterface<DIMENSIONS>::setSnoptFLimits() {
 
  316     Eigen::VectorXd local_Flb = _method->myNLP.GetFlb();
 
  317     Eigen::VectorXd local_Fub = _method->myNLP.GetFub();
 
  319     snopt_Flb_v.resize(spt_lenF);
 
  320     snopt_Fub_v.resize(spt_lenF);
 
  322     snopt_Flb_v(0) = -infy;
 
  323     snopt_Fub_v(0) = infy;
 
  325     snopt_Flb_v.segment(1,spt_lenF-1) = local_Flb;
 
  326     snopt_Fub_v.segment(1,spt_lenF-1) = local_Fub;
 
  328     spt_Flb = snopt_Flb_v.data();
 
  329     spt_Fub = snopt_Fub_v.data();
 
  331     if (this->_verbose) {
 
  332         std::cout << 
"[VERBOSE] spt_lenF  : " << spt_lenF << std::endl;
 
  333         std::cout << 
"[VERBOSE] snopt_Flb : " << snopt_Flb_v.transpose() << std::endl;
 
  334         std::cout << 
"[VERBOSE] snopt_Fub : " << snopt_Fub_v.transpose() << std::endl;
 
  339 template <
class DIMENSIONS>
 
  340 void DTOSnoptInterface<DIMENSIONS>::setSparsityVariables() {
 
  342     Eigen::VectorXi local_iGfun = _method->myNLP.GetiGfun();
 
  343     Eigen::VectorXi local_jGvar = _method->myNLP.GetjGvar();
 
  344     Eigen::VectorXi local_jGcost =_method->myNLP.GetjGvarCost();
 
  346     jgcost_size = local_jGcost.size();
 
  347     original_size_G = _method->myNLP.GetDimG();
 
  350         spt_lenA = spt_lenF*spt_n_vars;
 
  351         spt_iAfun = 
new int[spt_lenA];
 
  352         spt_jAvar = 
new int[spt_lenA];
 
  353         spt_A = 
new double[spt_lenA];
 
  355     if (use_computeJacobian) {
 
  357         spt_neG = spt_lenF*spt_n_vars;
 
  358         spt_iGfun = 
new int[spt_neG];
 
  359         spt_jGvar = 
new int[spt_neG];
 
  362         spt_neG = original_size_G + jgcost_size;
 
  363         snopt_iGfun.resize(spt_neG);
 
  364         snopt_jGvar.resize(spt_neG);
 
  366         snopt_iGfun.segment(0,jgcost_size) = Eigen::VectorXi::Zero(jgcost_size);
 
  367         snopt_iGfun.segment(jgcost_size,original_size_G) = local_iGfun + Eigen::VectorXi::Ones(local_iGfun.size());
 
  368         snopt_jGvar.segment(0,jgcost_size) = local_jGcost;
 
  369         snopt_jGvar.segment(jgcost_size,original_size_G) = local_jGvar;
 
  371         spt_iGfun = snopt_iGfun.data();
 
  372         spt_jGvar = snopt_jGvar.data();
 
  375     if (this->_verbose) {
 
  376         std::cout << 
"[VERBOSE] jgcost_size : " << jgcost_size << std::endl;
 
  377         std::cout << 
"[VERBOSE] spt_neG     : " << spt_neG << std::endl;
 
  379         std::cout << 
"[VERBOSE] snopt_iGfun : " << snopt_iGfun.transpose() << std::endl;
 
  381         std::cout << 
"[VERBOSE] snopt_jGvar : " << snopt_jGvar.transpose() << std::endl;
 
  386 template <
class DIMENSIONS>
 
  387 void DTOSnoptInterface<DIMENSIONS>::setupNLPsolver() {
 
  390     nlp_solver->setProblemSize( spt_n_vars , spt_lenF  );
 
  391     nlp_solver->setObjective  ( spt_obj_row , spt_obj_add );
 
  392     nlp_solver->setA              ( spt_lenA, spt_neA, spt_iAfun, spt_jAvar, spt_A);
 
  393     nlp_solver->setG          ( spt_neG, spt_neG, spt_iGfun, spt_jGvar );
 
  394     nlp_solver->setX          ( x_variables.data() , spt_xlb , spt_xub , x_multipliers.data() , x_state.data());
 
  395     nlp_solver->setF          ( F_vector.data(), spt_Flb , spt_Fub , F_multipliers.data(), F_state.data() );
 
  398     nlp_solver->setUserFun    (spt_constraints_function);
 
  401         nlp_solver->setPrintFile(spt_name_of_print_file);
 
  403     if (use_computeJacobian) {
 
  404         this->estimateJacobianStructure();
 
  408 template <
class DIMENSIONS>
 
  411     std::cout << std::endl << 
"setting parameters..." << std::endl;
 
  413     nlp_solver->setIntParameter(
"Scale option" , scale_option_param);
 
  418     if (use_computeJacobian)
 
  419         derivative_option_param = 0;
 
  421         derivative_option_param = 1;
 
  424     nlp_solver->setRealParameter(
"Major feasibility tolerance", major_feasibility_tolerance_param);
 
  427     nlp_solver->setRealParameter(
"Minor feasibility tolerance", minor_feasibility_tolerance_param);
 
  429     nlp_solver->setIntParameter(
"Derivative option", derivative_option_param);
 
  430     nlp_solver->setIntParameter(
"Verify level" , verify_level_param);
 
  431     nlp_solver->setIntParameter(
"Major iterations limit", major_iteration_limit_param);
 
  432     nlp_solver->setIntParameter(
"Minor iterations limit", minor_iteration_limit_param);
 
  433     nlp_solver->setIntParameter(
"Iterations limit", iteration_limit_param);
 
  434     nlp_solver->setRealParameter(
"Major optimality tolerance", major_optimality_tolerance_param);
 
  435     nlp_solver->setIntParameter(
"Minor print level", minor_print_level_param);
 
  436     nlp_solver->setIntParameter(
"Major print level", major_print_level_param);
 
  439     nlp_solver->setIntParameter(
"New basis file", this->new_basis_file_param);
 
  440     nlp_solver->setIntParameter(
"Old basis file", this->old_basis_file_param);
 
  441     nlp_solver->setIntParameter(
"Backup basis file", backup_basis_file_param);
 
  444     nlp_solver->setIntParameter(
"Save frequency",100000000);
 
  446     if(this->_totally_quiet_) {
 
  447         nlp_solver->setParameter(
"Solution No");
 
  448         nlp_solver->setIntParameter(
"Summary file",0);
 
  454     nlp_solver->setRealParameter(
"Linesearch tolerance", line_search_tolerance_param);
 
  458     if (_feasible_point_only) {
 
  459         nlp_solver->setIntParameter(
"Feasible point only",1);
 
  460       nlp_solver->setParameter(
"Feasible point");
 
  466 template <
class DIMENSIONS>
 
  469     nlp_solver->computeJac(spt_neA,spt_neG);
 
  472     std::cout << 
"Jacobian Structure has been estimated" << std::endl;
 
  473     std::cout << 
"please press [ENTER] if you want to continue with optimization" << std::endl;
 
  477 template <
class DIMENSIONS>
 
  479     std::cout << 
"Ready to solve... " << std::endl;
 
  487     nlp_solver->solve(snopt_warm_flag);
 
  489     if(this->x_variables_validation.size() < 1){
 
  490         std::cout << 
"Internal error!" << std::endl;
 
  494     double epsilon_e = 1e-5;
 
  495     for(
auto i = 0 ; i < this->spt_n_vars ; ++i) {
 
  496         if(std::fabs(this->x_variables(i) - this->x_variables_validation(i)) > epsilon_e) {
 
  497             std::cout << 
"SNOPT BUG! : X_variables are not the same!" << std::endl;
 
  498             std::cout << 
"x_variables("<< i <<
") : " << x_variables(i) << std::endl;
 
  499             std::cout << 
"x_validation("<< i <<
") : " << x_variables_validation(i) << std::endl;
 
  503     for(
auto i = 0 ; i < this->spt_lenF; ++i) {
 
  504         if(std::fabs(this->F_vector(i) - this->F_vector_validation(i)) > epsilon_e) {
 
  505             std::cout << 
"SNOPT BUG! : Constraints are not consistent" << std::endl;
 
  506       std::cout << 
"F_vector("<< i <<
") : " << F_vector(i) << std::endl;
 
  507       std::cout << 
"F_validation("<< i <<
") : " << F_vector_validation(i) << std::endl;
 
  508       std::cout << 
"F_lb("<< i <<
") : " << this->snopt_Flb_v(i) << std::endl;
 
  509       std::cout << 
"F_ub("<< i <<
") : " << this->snopt_Fub_v(i) << std::endl;
 
  577 template <
class DIMENSIONS>
 
  582 template <
class DIMENSIONS>
 
  583 void DTOSnoptInterface<DIMENSIONS>::validateSNOPTStatus(
const int & status,
 
  584         const Eigen::Map<Eigen::VectorXd> & X, 
const Eigen::Map<Eigen::VectorXd> & F) {
 
  595             message = 
"OPTIMAL SOLUTION FOUND!!!!";
 
  598             message = 
"Problem is Infeasible :-(";
 
  601             message = 
"---> Unbounded <---";
 
  604             message = 
"-> Iteration Limit <-";
 
  608     std::cout << message << std::endl;
 
  610     this->F_vector_validation = F;
 
  611     this->x_variables_validation = X;
 
  614 template <
class DIMENSIONS>
 
  616         Eigen::VectorXd & _x_mul, Eigen::VectorXi & _f_state, Eigen::VectorXd & _f_mul) {
 
  618     _x_state = this->x_state;
 
  619     _x_mul = this->x_multipliers;
 
  621     _f_state = this->F_state;
 
  622     _f_mul = this->F_multipliers;
 
  626 template <
class DIMENSIONS>
 
  628         const control_vector_array_t & u_sol, 
const Eigen::VectorXd &h_sol) {
 
  630     _method->SetDecisionVariablesFromStateControlIncrementsTrajectories(this->x_variables,y_sol,u_sol,h_sol);
 
  634 template <
class DIMENSIONS>
 
  636     const Eigen::VectorXd & p_x_mul, 
const Eigen::VectorXi & p_f_state,
 
  637     const Eigen::VectorXd & p_f_mul) {
 
  639     if(p_x_state.size() == spt_n_vars) {
 
  641         x_multipliers = p_x_mul;
 
  643         F_multipliers = p_f_mul;
 
  645         std::cout << 
"Error during SNOPT solver initialization" << std::endl;
 
  646         std::exit(EXIT_FAILURE);
 
  650 template <
class DIMENSIONS>
 
  652         control_vector_array_t & u_trajectory, Eigen::VectorXd & h_trajectory) {
 
  653     Eigen::Map<Eigen::VectorXd> x_vector(x_variables.data(),spt_n_vars);
 
  655     _method->getStateControlIncrementsTrajectoriesFromDecisionVariables(x_vector,y_trajectory,u_trajectory,h_trajectory);
 
  658 template <
class DIMENSIONS>
 
  660         control_vector_array_t & u_trajectory, Eigen::VectorXd & h_trajectory,
 
  661         std::vector<int> & phaseId) {
 
  663     this->GetDTOSolution(y_trajectory, u_trajectory, h_trajectory);
 
  665     phaseId = _method->node_to_phase_map;
 
  668 template <
class DIMENSIONS>
 
  670                     control_vector_array_t & uTraj, Eigen::VectorXd &hTraj, std::vector<int> &phaseId) {
 
  674   _method->UpdateDecisionVariables(x_variables.data());
 
  675   _method->getCompleteSolution(yTraj,ydotTraj,uTraj,hTraj,phaseId);
 
  679 template <
class DIMENSIONS>
 
  681           int    *needF,  
int *neF,  
double F[],
 
  682           int    *needG,  
int *neG,  
double G[],
 
  683           char   *cu,     
int *lencu,
 
  684           int    iu[],    
int *leniu,
 
  685           double ru[],    
int *lenru ) {
 
  707         DTOSnoptInterface<DIMENSIONS>::interface_pointer->_method->evalObjective(&F[0]);
 
  708         DTOSnoptInterface<DIMENSIONS>::interface_pointer->_method->evalConstraintFct(&F[1], *neF - 1);
 
  717         Eigen::Map<Eigen::VectorXd> F_b(F,*neF);
 
  718         Eigen::Map<Eigen::VectorXd> X_vector(x,*n);
 
  719         DTOSnoptInterface<DIMENSIONS>::interface_pointer->status_output_flag = *Status;
 
  720         DTOSnoptInterface<DIMENSIONS>::interface_pointer->validateSNOPTStatus(*Status,X_vector,F_b);
 
virtual void InitializeSolver(const std::string &problem_name, const std::string &output_file, const std::string ¶m_file="", const bool &computeJacobian=false) override
DTO initializes the solver using this method. 
Definition: snopt.hpp:254
 
This class serves as a base interface for inheriting classes. 
Definition: base_method_interface.hpp:60
 
virtual void GetDTOSolution(state_vector_array_t &yTraj, control_vector_array_t &uTraj, Eigen::VectorXd &hTraj) override
Method to get the current values of the solution. 
Definition: snopt.hpp:651
 
std::shared_ptr< DTOMethodInterface< DIMENSIONS > > _method
Definition: snopt.hpp:97
 
void InitializeDecisionVariablesFromTrajectory(const state_vector_array_t &y_sol, const control_vector_array_t &u_sol, const Eigen::VectorXd &h_sol) override
Initial solution point for the solver. 
Definition: snopt.hpp:627
 
void SetupSolverParameters() override
Setting up solver parameters. 
Definition: snopt.hpp:409
 
Base class for NLP Solvers interface. 
 
virtual void Solve(bool warminit=false) override
DTO request the solver to proceed with the NLP. 
Definition: snopt.hpp:478
 
This class serves as a base interface for inheriting classes. 
Definition: base_solver_interface.hpp:47
 
Class interfacing SNOPT NLP with DTO Problem. 
Definition: snopt.hpp:49
 
std::shared_ptr< snoptProblemA > nlp_solver
Definition: snopt.hpp:98
 
virtual void GetFVector(Eigen::VectorXd &fVec) override
Returns the vector of NLP-constraints. 
Definition: snopt.hpp:148
 
void GetSolverSolutionVariables(Eigen::VectorXi &_x_state, Eigen::VectorXd &_x_mul, Eigen::VectorXi &_f_state, Eigen::VectorXd &_f_mul) override
Method to get final values of internal solver variables. 
Definition: snopt.hpp:615
 
static std::shared_ptr< DTOSnoptInterface< DIMENSIONS > > interface_pointer
Definition: snopt.hpp:93
 
DTOSnoptInterface(std::shared_ptr< DTOMethodInterface< DIMENSIONS > > method, bool snopt_verbose, bool feasible_point_only)
Constructor. 
Definition: snopt.hpp:65
 
void WarmSolverInitialization(const Eigen::VectorXi &x_state, const Eigen::VectorXd &x_mul, const Eigen::VectorXi &f_state, const Eigen::VectorXd &f_mul) override
Warm Initialization of NLP Solver. 
Definition: snopt.hpp:635