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 <ct/models/HyQ/HyQ.h> |
| 10 | #include <ct/models/CodegenOutputDirs.h> |
| 11 | |
| 12 | #include "helperFunctions.h" |
| 13 | |
| 14 | // shortcut for the auto-diff codegen scalar |
| 15 | typedef CppAD::AD<CppAD::cg::CG<double>> SCALAR; |
| 16 | typedef typename SCALAR::value_type AD_ValueType; |
| 17 | |
| 18 | // a floating base forward-dynamic system templated on scalar type |
| 19 | typedef ct::rbd::FloatingBaseFDSystem<ct::rbd::HyQ::tpl::Dynamics<SCALAR>, false> HyQSystemAD; |
| 20 | |
| 21 | // extract dimensions |
| 22 | const size_t state_dim = HyQSystemAD::STATE_DIM; |
| 23 | const size_t control_dim = HyQSystemAD::CONTROL_DIM; |
| 24 | |
| 25 | // shortcut for number of joints |
| 26 | const size_t njoints = HyQSystemAD::Kinematics::NJOINTS; |
| 27 | |
| 28 | |
| 29 | void generateInverseDynamics() |
| 30 | { |
| 31 | typedef ct::core::DerivativesCppadCG<state_dim + 18, control_dim + 6> JacCG; |
| 32 | typename JacCG::FUN_TYPE_CG f = ct::models::HyQ::hyqInverseDynamics<SCALAR>; |
| 33 | JacCG jacCG(f); |
| 34 | |
| 35 | try |
| 36 | { |
| 37 | std::cout << "Generating Jacobian of Inverse Dynamics wrt state using forward mode... " << std::endl; |
| 38 | jacCG.generateJacobianSource("HyQInverseDynJacForward", ct::models::HYQ_CODEGEN_OUTPUT_DIR, |
| 39 | ct::core::CODEGEN_TEMPLATE_DIR, "models", "HyQ", JacCG::Sparsity::Ones(), false); |
| 40 | |
| 41 | std::cout << "Generating Jacobian of Inverse Dynamics wrt state using reverse mode... " << std::endl; |
| 42 | jacCG.generateJacobianSource("HyQInverseDynJacReverse", ct::models::HYQ_CODEGEN_OUTPUT_DIR, |
| 43 | ct::core::CODEGEN_TEMPLATE_DIR, "models", "HyQ", JacCG::Sparsity::Ones(), true); |
| 44 | } catch (const std::runtime_error& e) |
| 45 | { |
| 46 | std::cout << "inverse dynamics code generation failed: " << e.what() << std::endl; |
| 47 | } |
| 48 | } |
| 49 | |
| 50 | void generateForwardKinematics() |
| 51 | { |
| 52 | typedef ct::core::DerivativesCppadCG<state_dim, 4 * 6> JacCG; |
| 53 | typename JacCG::FUN_TYPE_CG f = ct::models::HyQ::hyqForwardKinematics<SCALAR>; |
| 54 | JacCG jacCG(f); |
| 55 | |
| 56 | try |
| 57 | { |
| 58 | std::cout << "Generating Jacobian of Forward Kinematics wrt state using forward mode... " << std::endl; |
| 59 | jacCG.generateJacobianSource("HyQForwardKinJacForward", ct::models::HYQ_CODEGEN_OUTPUT_DIR, |
| 60 | ct::core::CODEGEN_TEMPLATE_DIR, "models", "HyQ", JacCG::Sparsity::Ones(), false); |
| 61 | |
| 62 | std::cout << "Generating Jacobian of Forward Kinematics wrt state using reverse mode... " << std::endl; |
| 63 | jacCG.generateJacobianSource("HyQForwardKinJacReverse", ct::models::HYQ_CODEGEN_OUTPUT_DIR, |
| 64 | ct::core::CODEGEN_TEMPLATE_DIR, "models", "HyQ", JacCG::Sparsity::Ones(), true); |
| 65 | } catch (const std::runtime_error& e) |
| 66 | { |
| 67 | std::cout << "forward kinematics code generation failed: " << e.what() << std::endl; |
| 68 | } |
| 69 | } |
| 70 | |
| 71 | void generateForwardZeroForwardDynamics() |
| 72 | { |
| 73 | typedef ct::core::DerivativesCppadCG<state_dim + control_dim + 1, state_dim> JacCG; |
| 74 | // Eigen::Matrix<SCALAR, state_dim + control_dim + 1, 1> testInput = Eigen::Matrix<SCALAR, state_dim + control_dim + 1, 1>::Random(); |
| 75 | // auto asd = ct::models::HyQ::hyqContactModelForwardDynamics<SCALAR>(testInput); |
| 76 | typename JacCG::FUN_TYPE_CG f = ct::models::HyQ::hyqContactModelForwardDynamics<SCALAR>; |
| 77 | JacCG jacCG(f); |
| 78 | |
| 79 | try |
| 80 | { |
| 81 | std::cout << "Generating Forward Zero Code... " << std::endl; |
| 82 | jacCG.generateForwardZeroSource("HyQForwardZero", ct::models::HYQ_CODEGEN_OUTPUT_DIR, |
| 83 | ct::core::CODEGEN_TEMPLATE_DIR, "models", "HyQ", false); |
| 84 | } catch (const std::runtime_error& e) |
| 85 | { |
| 86 | std::cout << "forward zero code generation failed: " << e.what() << std::endl; |
| 87 | } |
| 88 | } |
| 89 | |
| 90 | |
| 91 | void generateFDLinearization(int argc, char* argv[]) |
| 92 | { |
| 93 | std::cout << "Generating Jacobian of Forward Dynamics... " << std::endl; |
| 94 | |
| 95 | // a contact model (auto-diff'able) |
| 96 | typedef ct::rbd::EEContactModel<typename HyQSystemAD::Kinematics> ContactModel; |
| 97 | |
| 98 | std::shared_ptr<HyQSystemAD> adSystem = std::shared_ptr<HyQSystemAD>(new HyQSystemAD); |
| 99 | |
| 100 | // explicitely pass kinematics from the system such that both, contact model and system use |
| 101 | // the same instance to give the AD codegen the opportunity to fully optimize the code |
| 102 | std::shared_ptr<ContactModel> contactModel = |
| 103 | std::shared_ptr<ContactModel>(new ContactModel(SCALAR(5000.0), SCALAR(1000.0), SCALAR(100.0), SCALAR(100.0), |
| 104 | SCALAR(-0.02), ContactModel::VELOCITY_SMOOTHING::SIGMOID, adSystem->dynamics().kinematicsPtr())); |
| 105 | |
| 106 | bool useContactModel = (argc <= 2 || !std::string(argv[2]).compare("nocontact") == 0); |
| 107 | std::cout << std::boolalpha << "using contact model: " << useContactModel << std::endl; |
| 108 | |
| 109 | // asign the contact model |
| 110 | if (useContactModel) |
| 111 | adSystem->setContactModel(contactModel); |
| 112 | |
| 113 | // create the codegen linearizer |
| 114 | ct::core::ADCodegenLinearizer<state_dim, control_dim> adLinearizer(adSystem); |
| 115 | |
| 116 | std::string baseName; |
| 117 | if (useContactModel) |
| 118 | baseName = "HyQWithContactModelLinearized"; |
| 119 | else |
| 120 | baseName = "HyQBareModelLinearized"; |
| 121 | |
| 122 | try |
| 123 | { |
| 124 | std::cout << "generating code..." << std::endl; |
| 125 | if (argc > 1 && std::string(argv[1]).compare("reverse") == 0) |
| 126 | { |
| 127 | std::cout << "generating using reverse mode" << std::endl; |
| 128 | |
| 129 | adLinearizer.generateCode(baseName + "Reverse", ct::models::HYQ_CODEGEN_OUTPUT_DIR, |
| 130 | ct::core::CODEGEN_TEMPLATE_DIR, "models", "HyQ", true); |
| 131 | } |
| 132 | else |
| 133 | { |
| 134 | std::cout << "generating using forward mode" << std::endl; |
| 135 | |
| 136 | adLinearizer.generateCode(baseName + "Forward", ct::models::HYQ_CODEGEN_OUTPUT_DIR, |
| 137 | ct::core::CODEGEN_TEMPLATE_DIR, "models", "HyQ", false); |
| 138 | } |
| 139 | |
| 140 | std::cout << "... done!" << std::endl; |
| 141 | } catch (const std::runtime_error& e) |
| 142 | { |
| 143 | std::cout << "forward dynamics code generation failed: " << e.what() << std::endl; |
| 144 | } |
| 145 | } |
| 146 | |
| 147 | |
| 148 | int main(int argc, char* argv[]) |
| 149 | { |
| 150 | generateFDLinearization(argc, argv); |
| 151 | generateInverseDynamics(); |
| 152 | generateForwardKinematics(); |
| 153 | generateForwardZeroForwardDynamics(); |
| 154 | } |