Austin Schuh | 7400da0 | 2018-01-28 19:54:58 -0800 | [diff] [blame^] | 1 | /********************************************************************************************************************** |
| 2 | This file is part of the Control Toolbox (https://adrlab.bitbucket.io/ct), copyright by ETH Zurich, Google Inc. |
| 3 | Authors: Michael Neunert, Markus Giftthaler, Markus Stäuble, Diego Pardo, Farbod Farshidian |
| 4 | Licensed under Apache2 license (see LICENSE file in main directory) |
| 5 | **********************************************************************************************************************/ |
| 6 | |
| 7 | #include <ct/optcon/optcon.h> |
| 8 | #include <ct/rbd/rbd.h> |
| 9 | #include "../exampleDir.h" |
| 10 | |
| 11 | #include <ct/models/InvertedPendulum/InvertedPendulum.h> |
| 12 | |
| 13 | using namespace ct::rbd; |
| 14 | |
| 15 | const size_t njoints = ct::rbd::InvertedPendulum::Kinematics::NJOINTS; |
| 16 | const size_t actuator_state_dim = 1; |
| 17 | |
| 18 | typedef ct::rbd::InvertedPendulum::tpl::Dynamics<double> IPDynamics; |
| 19 | typedef ct::rbd::FixBaseFDSystem<IPDynamics, actuator_state_dim, false> IPSystem; |
| 20 | |
| 21 | typedef ct::core::LinearSystem<IPSystem::STATE_DIM, IPSystem::CONTROL_DIM, double> LinearSystem; |
| 22 | |
| 23 | using InvertedPendulumNLOC = FixBaseNLOC<IPSystem, actuator_state_dim, double>; |
| 24 | |
| 25 | class MPCSimulator : public ct::core::ControlSimulator<IPSystem> |
| 26 | { |
| 27 | public: |
| 28 | MPCSimulator(ct::core::Time sim_dt, |
| 29 | ct::core::Time control_dt, |
| 30 | const ct::core::StateVector<STATE_DIM>& x0, |
| 31 | std::shared_ptr<IPSystem> ip_system, |
| 32 | ct::optcon::MPC<ct::optcon::NLOptConSolver<STATE_DIM, CONTROL_DIM>>& mpc) |
| 33 | : ct::core::ControlSimulator<IPSystem>(sim_dt, control_dt, x0, ip_system), mpc_(mpc) |
| 34 | { |
| 35 | controller_.reset(new ct::core::StateFeedbackController<STATE_DIM, CONTROL_DIM>); |
| 36 | } |
| 37 | |
| 38 | void finishSystemIteration(ct::core::Time sim_time) override |
| 39 | { |
| 40 | control_mtx_.lock(); |
| 41 | system_->setController(controller_); |
| 42 | control_mtx_.unlock(); |
| 43 | } |
| 44 | |
| 45 | void prepareControllerIteration(ct::core::Time sim_time) override |
| 46 | { |
| 47 | mpc_.prepareIteration(sim_time); |
| 48 | } |
| 49 | |
| 50 | void finishControllerIteration(ct::core::Time sim_time) override |
| 51 | { |
| 52 | state_mtx_.lock(); |
| 53 | ct::core::StateVector<STATE_DIM> x_temp = x_; |
| 54 | state_mtx_.unlock(); |
| 55 | |
| 56 | std::shared_ptr<ct::core::StateFeedbackController<STATE_DIM, CONTROL_DIM>> new_controller( |
| 57 | new ct::core::StateFeedbackController<STATE_DIM, CONTROL_DIM>); |
| 58 | bool success = mpc_.finishIteration(x_temp, sim_time, *new_controller, controller_ts_); |
| 59 | if (!success) throw std::runtime_error("Failed to finish iteration."); |
| 60 | |
| 61 | control_mtx_.lock(); |
| 62 | controller_ = new_controller; |
| 63 | control_mtx_.unlock(); |
| 64 | } |
| 65 | |
| 66 | private: |
| 67 | ct::optcon::MPC<ct::optcon::NLOptConSolver<STATE_DIM, CONTROL_DIM>>& mpc_; |
| 68 | ct::core::Time controller_ts_; |
| 69 | }; |
| 70 | |
| 71 | int main(int argc, char* argv[]) |
| 72 | { |
| 73 | const bool verbose = true; |
| 74 | try |
| 75 | { |
| 76 | std::string workingDirectory = ct::models::exampleDir + "/InvertedPendulum"; |
| 77 | |
| 78 | std::string configFile = workingDirectory + "/solver.info"; |
| 79 | std::string costFunctionFile = workingDirectory + "/cost.info"; |
| 80 | |
| 81 | std::shared_ptr<ct::rbd::SEADynamicsFirstOrder<njoints, double>> actuatorDynamics( |
| 82 | new ct::rbd::SEADynamicsFirstOrder<njoints, double>(160.0)); |
| 83 | std::shared_ptr<IPSystem> ipSystem(new IPSystem(actuatorDynamics)); |
| 84 | |
| 85 | // NLOC settings |
| 86 | ct::optcon::NLOptConSettings nloc_settings; |
| 87 | nloc_settings.load(configFile, verbose, "ilqr"); |
| 88 | |
| 89 | std::shared_ptr<ct::optcon::TermQuadratic<IPSystem::STATE_DIM, IPSystem::CONTROL_DIM, double, double>> |
| 90 | termQuadInterm(new ct::optcon::TermQuadratic<IPSystem::STATE_DIM, IPSystem::CONTROL_DIM, double, double>); |
| 91 | termQuadInterm->loadConfigFile(costFunctionFile, "term0", verbose); |
| 92 | |
| 93 | std::shared_ptr<ct::optcon::TermQuadratic<IPSystem::STATE_DIM, IPSystem::CONTROL_DIM, double, double>> |
| 94 | termQuadFinal(new ct::optcon::TermQuadratic<IPSystem::STATE_DIM, IPSystem::CONTROL_DIM, double, double>); |
| 95 | termQuadFinal->loadConfigFile(costFunctionFile, "term1", verbose); |
| 96 | |
| 97 | std::shared_ptr<ct::optcon::CostFunctionAnalytical<IPSystem::STATE_DIM, IPSystem::CONTROL_DIM>> newCost( |
| 98 | new ct::optcon::CostFunctionAnalytical<IPSystem::STATE_DIM, IPSystem::CONTROL_DIM>); |
| 99 | size_t intTermID = newCost->addIntermediateTerm(termQuadInterm); |
| 100 | size_t finalTermID = newCost->addFinalTerm(termQuadFinal); |
| 101 | |
| 102 | ct::core::Time timeHorizon; |
| 103 | InvertedPendulumNLOC::FeedbackArray::value_type fbD; |
| 104 | ct::rbd::tpl::JointState<njoints, double> x0; |
| 105 | ct::rbd::tpl::JointState<njoints, double> xf; |
| 106 | |
| 107 | ct::core::loadScalar(configFile, "timeHorizon", timeHorizon); |
| 108 | ct::core::loadMatrix(costFunctionFile, "K_init", fbD); |
| 109 | ct::core::loadMatrix(costFunctionFile, "x_0", x0.toImplementation()); |
| 110 | ct::core::loadMatrix(costFunctionFile, "term1.weights.x_des", xf.toImplementation()); |
| 111 | ct::core::StateVector<IPSystem::STATE_DIM> x0full = IPSystem::toFullState(x0.toImplementation()); |
| 112 | |
| 113 | std::shared_ptr<LinearSystem> linSystem = nullptr; |
| 114 | ct::optcon::OptConProblem<IPSystem::STATE_DIM, IPSystem::CONTROL_DIM> optConProblem( |
| 115 | timeHorizon, x0full, ipSystem, newCost, linSystem); |
| 116 | InvertedPendulumNLOC nloc_solver(newCost, nloc_settings, ipSystem, verbose, linSystem); |
| 117 | |
| 118 | int K = nloc_solver.getSettings().computeK(timeHorizon); |
| 119 | |
| 120 | InvertedPendulumNLOC::StateVectorArray stateRefTraj(K + 1, x0full); |
| 121 | InvertedPendulumNLOC::FeedbackArray fbTrajectory(K, -fbD); |
| 122 | InvertedPendulumNLOC::ControlVectorArray ffTrajectory(K, InvertedPendulumNLOC::ControlVector::Zero()); |
| 123 | |
| 124 | int initType = 0; |
| 125 | ct::core::loadScalar(configFile, "initType", initType); |
| 126 | |
| 127 | switch (initType) |
| 128 | { |
| 129 | case 0: // steady state |
| 130 | { |
| 131 | ct::core::ControlVector<IPSystem::CONTROL_DIM> uff_ref; |
| 132 | nloc_solver.initializeSteadyPose(x0, timeHorizon, K, uff_ref, -fbD); |
| 133 | |
| 134 | std::vector< |
| 135 | std::shared_ptr<ct::optcon::CostFunctionQuadratic<IPSystem::STATE_DIM, IPSystem::CONTROL_DIM>>>& |
| 136 | inst1 = nloc_solver.getSolver()->getCostFunctionInstances(); |
| 137 | |
| 138 | for (size_t i = 0; i < inst1.size(); i++) |
| 139 | { |
| 140 | inst1[i]->getIntermediateTermById(intTermID)->updateReferenceControl(uff_ref); |
| 141 | } |
| 142 | break; |
| 143 | } |
| 144 | case 1: // linear interpolation |
| 145 | { |
| 146 | nloc_solver.initializeDirectInterpolation(x0, xf, timeHorizon, K, -fbD); |
| 147 | break; |
| 148 | } |
| 149 | default: |
| 150 | { |
| 151 | throw std::runtime_error("illegal init type"); |
| 152 | break; |
| 153 | } |
| 154 | } |
| 155 | |
| 156 | std::cout << "waiting 1 second for begin" << std::endl; |
| 157 | std::this_thread::sleep_for(std::chrono::seconds(1)); |
| 158 | |
| 159 | nloc_solver.solve(); |
| 160 | ct::core::StateFeedbackController<IPSystem::STATE_DIM, IPSystem::CONTROL_DIM> initialSolution = |
| 161 | nloc_solver.getSolution(); |
| 162 | InvertedPendulumNLOC::StateVectorArray x_nloc = initialSolution.x_ref(); |
| 163 | |
| 164 | // nloc_solver.retrieveLastRollout(); |
| 165 | |
| 166 | ct::optcon::NLOptConSettings ilqr_settings_mpc(nloc_solver.getSettings()); |
| 167 | ilqr_settings_mpc.max_iterations = 1; |
| 168 | ilqr_settings_mpc.printSummary = false; |
| 169 | |
| 170 | ct::optcon::mpc_settings mpc_settings; |
| 171 | mpc_settings.stateForwardIntegration_ = false; |
| 172 | mpc_settings.postTruncation_ = false; |
| 173 | mpc_settings.measureDelay_ = false; |
| 174 | mpc_settings.delayMeasurementMultiplier_ = 1.0; |
| 175 | mpc_settings.mpc_mode = ct::optcon::MPC_MODE::CONSTANT_RECEDING_HORIZON; |
| 176 | mpc_settings.coldStart_ = false; |
| 177 | mpc_settings.minimumTimeHorizonMpc_ = 3.0; |
| 178 | |
| 179 | ct::optcon::MPC<ct::optcon::NLOptConSolver<IPSystem::STATE_DIM, IPSystem::CONTROL_DIM>> ilqr_mpc( |
| 180 | optConProblem, ilqr_settings_mpc, mpc_settings); |
| 181 | ilqr_mpc.setInitialGuess(initialSolution); |
| 182 | |
| 183 | MPCSimulator mpc_sim(1e-3, 1e-2, x0full, ipSystem, ilqr_mpc); |
| 184 | std::cout << "simulating 3 seconds" << std::endl; |
| 185 | mpc_sim.simulate(3); |
| 186 | mpc_sim.finish(); |
| 187 | |
| 188 | ilqr_mpc.printMpcSummary(); |
| 189 | |
| 190 | } catch (std::runtime_error& e) |
| 191 | { |
| 192 | std::cout << "Exception caught: " << e.what() << std::endl; |
| 193 | } |
| 194 | } |