|
6 | 6 | #include <tsid/solvers/solver-HQP-factory.hxx> |
7 | 7 | #include <tsid/solvers/utils.hpp> |
8 | 8 | #include <tsid/tasks/task-actuation-bounds.hpp> |
9 | | -#include <tsid/tasks/task-joint-bounds.hpp> |
10 | 9 | #include <tsid/tasks/task-joint-posVelAcc-bounds.hpp> |
11 | 10 | #include <tsid/tasks/task-joint-posture.hpp> |
12 | 11 | #include <tsid/tasks/task-se3-equality.hpp> |
13 | | -#include <tsid/trajectories/trajectory-euclidian.hpp> |
| 12 | +#include <tsid/trajectories/trajectory-base.hpp> |
14 | 13 |
|
15 | 14 | // Allow to define a field, it's default value and its convenient chainable setter in one keyword. |
16 | 15 | #define DEFINE_FIELD(type, name, value) \ |
@@ -53,165 +52,22 @@ namespace simple_mpc |
53 | 52 | DEFINE_FIELD(double, w_contact_force, -1.) // Disabled by default |
54 | 53 | }; |
55 | 54 |
|
56 | | - KinodynamicsID(const simple_mpc::RobotModelHandler & model_handler, double control_dt, const Settings settings) |
57 | | - : settings_(settings) |
58 | | - , model_handler_(model_handler) |
59 | | - , data_handler_(model_handler_) |
60 | | - , robot_(model_handler_.getModel()) |
61 | | - , formulation_("tsid", robot_) |
62 | | - { |
63 | | - const pinocchio::Model & model = model_handler.getModel(); |
64 | | - const size_t nq = model.nq; |
65 | | - const size_t nq_actuated = robot_.nq_actuated(); |
66 | | - const size_t nv = model.nv; |
67 | | - const size_t nu = nv - 6; |
68 | | - |
69 | | - // Prepare contact point task |
70 | | - const size_t n_contacts = model_handler_.getFeetNames().size(); |
71 | | - const Eigen::Vector3d normal{0, 0, 1}; |
72 | | - const double weight = model_handler_.getMass() * 9.81; |
73 | | - const double max_f = settings_.contact_weight_ratio_max * weight; |
74 | | - const double min_f = settings_.contact_weight_ratio_min * weight; |
75 | | - for (int i = 0; i < n_contacts; i++) |
76 | | - { |
77 | | - const std::string frame_name = model_handler.getFootName(i); |
78 | | - // Create contact point |
79 | | - tsid::contacts::ContactPoint & contact_point = tsid_contacts.emplace_back( |
80 | | - frame_name, robot_, frame_name, normal, settings_.friction_coefficient, min_f, max_f); |
81 | | - // Set contact parameters |
82 | | - contact_point.Kp(settings_.kp_contact * Eigen::VectorXd::Ones(3)); |
83 | | - contact_point.Kd(2.0 * contact_point.Kp().cwiseSqrt()); |
84 | | - contact_point.useLocalFrame(false); |
85 | | - // By default contact is not active (will be by setTarget) |
86 | | - active_tsid_contacts_.push_back(false); |
87 | | - } |
88 | | - |
89 | | - // Add the posture task |
90 | | - postureTask_ = std::make_shared<tsid::tasks::TaskJointPosture>("task-posture", robot_); |
91 | | - postureTask_->Kp(settings_.kp_posture * Eigen::VectorXd::Ones(nu)); |
92 | | - postureTask_->Kd(2.0 * postureTask_->Kp().cwiseSqrt()); |
93 | | - if (settings_.w_posture > 0.) |
94 | | - formulation_.addMotionTask(*postureTask_, settings_.w_posture, 1); |
95 | | - |
96 | | - samplePosture_ = tsid::trajectories::TrajectorySample(nq_actuated, nu); |
97 | | - |
98 | | - // Add the base task |
99 | | - baseTask_ = |
100 | | - std::make_shared<tsid::tasks::TaskSE3Equality>("task-base", robot_, model_handler_.getBaseFrameName()); |
101 | | - baseTask_->Kp(settings_.kp_base * Eigen::VectorXd::Ones(6)); |
102 | | - baseTask_->Kd(2.0 * baseTask_->Kp().cwiseSqrt()); |
103 | | - if (settings_.w_base > 0.) |
104 | | - formulation_.addMotionTask(*baseTask_, settings_.w_base, 1); |
105 | | - |
106 | | - sampleBase_ = tsid::trajectories::TrajectorySample(12, 6); |
107 | | - |
108 | | - // Add joint limit task |
109 | | - boundsTask_ = std::make_shared<tsid::tasks::TaskJointPosVelAccBounds>("task-joint-limits", robot_, control_dt); |
110 | | - boundsTask_->setPositionBounds( |
111 | | - model_handler_.getModel().lowerPositionLimit.tail(nq_actuated), |
112 | | - model_handler_.getModel().upperPositionLimit.tail(nq_actuated)); |
113 | | - boundsTask_->setVelocityBounds(model_handler_.getModel().upperVelocityLimit.tail(nu)); |
114 | | - boundsTask_->setImposeBounds( |
115 | | - true, true, true, false); // For now do not impose acceleration bound as it is not provided in URDF |
116 | | - formulation_.addMotionTask(*boundsTask_, 1.0, 0); // No weight needed as it is set as constraint |
117 | | - |
118 | | - // Add actuation limit task |
119 | | - actuationTask_ = std::make_shared<tsid::tasks::TaskActuationBounds>("actuation-limits", robot_); |
120 | | - actuationTask_->setBounds( |
121 | | - model_handler_.getModel().lowerEffortLimit.tail(nu), model_handler_.getModel().upperEffortLimit.tail(nu)); |
122 | | - formulation_.addActuationTask(*actuationTask_, 1.0, 0); // No weight needed as it is set as constraint |
123 | | - |
124 | | - // Create an HQP solver |
125 | | - solver_ = tsid::solvers::SolverHQPFactory::createNewSolver(tsid::solvers::SOLVER_HQP_PROXQP, "solver-proxqp"); |
126 | | - solver_->resize(formulation_.nVar(), formulation_.nEq(), formulation_.nIn()); |
127 | | - |
128 | | - // Dry run to initialize solver data & output |
129 | | - const Eigen::VectorXd q_ref = model_handler.getReferenceState().head(nq); |
130 | | - const Eigen::VectorXd v_ref = model_handler.getReferenceState().tail(nv); |
131 | | - std::vector<bool> c_ref(n_contacts); |
132 | | - Eigen::VectorXd f_ref = Eigen::VectorXd::Zero(3 * n_contacts); |
133 | | - for (int i = 0; i < n_contacts; i++) |
134 | | - { |
135 | | - c_ref[i] = true; |
136 | | - f_ref[2 + 3 * i] = weight / n_contacts; |
137 | | - } |
138 | | - setTarget(q_ref, v_ref, v_ref, c_ref, f_ref); |
139 | | - const tsid::solvers::HQPData & solver_data = formulation_.computeProblemData(0, q_ref, v_ref); |
140 | | - last_solution_ = solver_->solve(solver_data); |
141 | | - } |
| 55 | + KinodynamicsID(const simple_mpc::RobotModelHandler & model_handler, double control_dt, const Settings settings); |
142 | 56 |
|
143 | 57 | void setTarget( |
144 | 58 | const Eigen::Ref<const Eigen::VectorXd> & q_target, |
145 | 59 | const Eigen::Ref<const Eigen::VectorXd> & v_target, |
146 | 60 | const Eigen::Ref<const Eigen::VectorXd> & a_target, |
147 | 61 | const std::vector<bool> & contact_state_target, |
148 | | - const Eigen::Ref<const Eigen::VectorXd> & f_target) |
149 | | - { |
150 | | - data_handler_.updateInternalData(q_target, v_target, false); |
151 | | - |
152 | | - // Posture task |
153 | | - samplePosture_.setValue(q_target.tail(robot_.nq_actuated())); |
154 | | - samplePosture_.setDerivative(v_target.tail(robot_.na())); |
155 | | - samplePosture_.setSecondDerivative(a_target.tail(robot_.na())); |
156 | | - postureTask_->setReference(samplePosture_); |
157 | | - |
158 | | - // Base task |
159 | | - tsid::math::SE3ToVector(data_handler_.getBaseFramePose(), sampleBase_.pos); |
160 | | - sampleBase_.setDerivative(v_target.head<6>()); |
161 | | - sampleBase_.setSecondDerivative(a_target.head<6>()); |
162 | | - baseTask_->setReference(sampleBase_); |
163 | | - |
164 | | - // Foot contacts |
165 | | - for (std::size_t i = 0; i < model_handler_.getFeetNames().size(); i++) |
166 | | - { |
167 | | - const std::string name = model_handler_.getFeetNames()[i]; |
168 | | - if (contact_state_target[i]) |
169 | | - { |
170 | | - if (!active_tsid_contacts_[i]) |
171 | | - { |
172 | | - formulation_.addRigidContact(tsid_contacts[i], settings_.w_contact_force, settings_.w_contact_motion, 1); |
173 | | - } |
174 | | - tsid_contacts[i].setForceReference(f_target.segment(i * 3, 3)); |
175 | | - active_tsid_contacts_[i] = true; |
176 | | - } |
177 | | - else |
178 | | - { |
179 | | - if (active_tsid_contacts_[i]) |
180 | | - { |
181 | | - formulation_.removeRigidContact(name, 0); |
182 | | - active_tsid_contacts_[i] = false; |
183 | | - } |
184 | | - } |
185 | | - } |
186 | | - solver_->resize(formulation_.nVar(), formulation_.nEq(), formulation_.nIn()); |
187 | | - } |
| 62 | + const Eigen::Ref<const Eigen::VectorXd> & f_target); |
188 | 63 |
|
189 | 64 | void solve( |
190 | 65 | const double t, |
191 | 66 | const Eigen::Ref<const Eigen::VectorXd> & q_meas, |
192 | 67 | const Eigen::Ref<const Eigen::VectorXd> & v_meas, |
193 | | - Eigen::Ref<Eigen::VectorXd> tau_res) |
194 | | - { |
195 | | - // Update contact position based on the real robot foot placement |
196 | | - data_handler_.updateInternalData(q_meas, v_meas, false); |
197 | | - for (std::size_t i = 0; i < active_tsid_contacts_.size(); i++) |
198 | | - { |
199 | | - if (active_tsid_contacts_[i]) |
200 | | - { |
201 | | - tsid_contacts[i].setReference(data_handler_.getFootPose(i)); |
202 | | - } |
203 | | - } |
| 68 | + Eigen::Ref<Eigen::VectorXd> tau_res); |
204 | 69 |
|
205 | | - const tsid::solvers::HQPData & solver_data = formulation_.computeProblemData(t, q_meas, v_meas); |
206 | | - last_solution_ = solver_->solve(solver_data); |
207 | | - assert(last_solution_.status == tsid::solvers::HQPStatus::HQP_STATUS_OPTIMAL); |
208 | | - tau_res = formulation_.getActuatorForces(last_solution_); |
209 | | - } |
210 | | - |
211 | | - const Eigen::VectorXd & getAccelerations() |
212 | | - { |
213 | | - return formulation_.getAccelerations(last_solution_); |
214 | | - } |
| 70 | + const Eigen::VectorXd & getAccelerations(); |
215 | 71 |
|
216 | 72 | private: |
217 | 73 | // Order matters to be instanciated in the right order |
|
0 commit comments