Control Libraries 7.4.0
Loading...
Searching...
No Matches
Model.cpp
1#include <iostream>
2#include <pinocchio/algorithm/frames.hpp>
3#include <pinocchio/algorithm/joint-configuration.hpp>
4#include "robot_model/Model.hpp"
5#include "robot_model/exceptions/FrameNotFoundException.hpp"
6#include "robot_model/exceptions/InverseKinematicsNotConvergingException.hpp"
7#include "robot_model/exceptions/InvalidJointStateSizeException.hpp"
8
9namespace robot_model {
10Model::Model(const std::string& robot_name, const std::string& urdf_path) :
11 robot_name_(std::make_shared<state_representation::Parameter<std::string>>("robot_name", robot_name)),
12 urdf_path_(std::make_shared<state_representation::Parameter<std::string>>("urdf_path", urdf_path)) {
13 this->init_model();
14}
15
16Model::Model(const Model& model) :
17 robot_name_(model.robot_name_),
18 urdf_path_(model.urdf_path_) {
19 this->init_model();
20}
21
22bool Model::create_urdf_from_string(const std::string& urdf_string, const std::string& desired_path) {
23 std::ofstream file(desired_path);
24 if (file.good() && file.is_open()) {
25 file << urdf_string;
26 file.close();
27 return true;
28 }
29 return false;
30}
31
32void Model::init_model() {
33 pinocchio::urdf::buildModel(this->get_urdf_path(), this->robot_model_);
34 this->robot_data_ = pinocchio::Data(this->robot_model_);
35 // get the frames
36 std::vector<std::string> frames;
37 for (auto& f : this->robot_model_.frames) {
38 frames.push_back(f.name);
39 }
40 // remove universe and root_joint frame added by Pinocchio
41 this->frames_ = std::vector<std::string>(frames.begin() + 2, frames.end());
42 this->init_qp_solver();
43}
44
45bool Model::init_qp_solver() {
46 // clear the solver
47 this->solver_.data()->clearHessianMatrix();
48 this->solver_.data()->clearLinearConstraintsMatrix();
49 this->solver_.clearSolver();
50
51 unsigned int nb_joints = this->get_number_of_joints();
52 // initialize the matrices
53 this->hessian_ = Eigen::SparseMatrix<double>(nb_joints + 1, nb_joints + 1);
54 this->gradient_ = Eigen::VectorXd::Zero(nb_joints + 1);
55 this->constraint_matrix_ = Eigen::SparseMatrix<double>(3 * nb_joints + 1 + 2, nb_joints + 1);
56 this->lower_bound_constraints_ = Eigen::VectorXd::Zero(3 * nb_joints + 1 + 2);
57 this->upper_bound_constraints_ = Eigen::VectorXd::Zero(3 * nb_joints + 1 + 2);
58
59 // reserve the size of the matrices
60 this->hessian_.reserve(nb_joints * nb_joints + 1);
61 this->constraint_matrix_.reserve(5 * nb_joints + 2 * (nb_joints * nb_joints + nb_joints) + 4 * nb_joints + 3);
62
63 Eigen::VectorXd lower_position_limit = this->robot_model_.lowerPositionLimit;
64 Eigen::VectorXd upper_position_limit = this->robot_model_.upperPositionLimit;
65 Eigen::VectorXd velocity_limit = this->robot_model_.velocityLimit;
66
67 // configure the QP problem
68 this->solver_.settings()->setVerbosity(false);
69 this->solver_.settings()->setWarmStart(true);
70
71 // joint dependent constraints
72 for (unsigned int n = 0; n < nb_joints; ++n) {
73 // joint limits
74 this->constraint_matrix_.coeffRef(n, n) = 1.0;
75 // joint velocity limits
76 this->constraint_matrix_.coeffRef(n + nb_joints, n) = 1.0;
77 this->constraint_matrix_.coeffRef(n + nb_joints, nb_joints) = velocity_limit(n);
78 this->upper_bound_constraints_(n + nb_joints) = std::numeric_limits<double>::infinity();
79 this->constraint_matrix_.coeffRef(n + 2 * nb_joints, n) = 1.0;
80 this->constraint_matrix_.coeffRef(n + 2 * nb_joints, nb_joints) = -velocity_limit(n);
81 this->lower_bound_constraints_(n + 2 * nb_joints) = -std::numeric_limits<double>::infinity();
82 }
83
84 // time constraint
85 this->constraint_matrix_.coeffRef(3 * nb_joints, nb_joints) = 1.0;
86 this->upper_bound_constraints_(3 * nb_joints) = std::numeric_limits<double>::infinity();
87 // cartesian velocity constraints
88 this->upper_bound_constraints_(3 * nb_joints + 1) = std::numeric_limits<double>::infinity();
89 this->upper_bound_constraints_(3 * nb_joints + 2) = std::numeric_limits<double>::infinity();
90
91 // set the initial data of the QP solver_
92 this->solver_.data()->setNumberOfVariables(static_cast<int>(nb_joints) + 1);
93 this->solver_.data()->setNumberOfConstraints(this->lower_bound_constraints_.size());
94 if (!this->solver_.data()->setHessianMatrix(this->hessian_)) { return false; }
95 if (!this->solver_.data()->setGradient(this->gradient_)) { return false; }
96 if (!this->solver_.data()->setLinearConstraintsMatrix(this->constraint_matrix_)) { return false; }
97 if (!this->solver_.data()->setLowerBound(this->lower_bound_constraints_)) { return false; }
98 if (!this->solver_.data()->setUpperBound(this->upper_bound_constraints_)) { return false; }
99 // instantiate the solver_
100 return this->solver_.initSolver();
101}
102
103std::vector<unsigned int> Model::get_frame_ids(const std::vector<std::string>& frames) {
104 std::vector<unsigned int> frame_ids;
105 frame_ids.reserve(frames.size());
106
107 for (auto& frame : frames) {
108 if (frame.empty()) {
109 // get last frame if none specified
110 frame_ids.push_back(this->robot_model_.frames.size() - 1);
111 } else {
112 // throw error if specified frame does not exist
113 if (!this->robot_model_.existFrame(frame)) {
114 throw (exceptions::FrameNotFoundException(frame));
115 }
116 frame_ids.push_back(this->robot_model_.getFrameId(frame));
117 }
118 }
119 return frame_ids;
120}
121
122unsigned int Model::get_frame_id(const std::string& frame) {
123 return get_frame_ids(std::vector<std::string>{frame}).back();
124}
125
126state_representation::Jacobian Model::compute_jacobian(const state_representation::JointPositions& joint_positions,
127 unsigned int frame_id) {
128 if (joint_positions.get_size() != this->get_number_of_joints()) {
129 throw (exceptions::InvalidJointStateSizeException(joint_positions.get_size(), this->get_number_of_joints()));
130 }
131 // compute the Jacobian from the joint state
132 pinocchio::Data::Matrix6x J(6, this->get_number_of_joints());
133 J.setZero();
134 pinocchio::computeFrameJacobian(this->robot_model_,
135 this->robot_data_,
136 joint_positions.data(),
137 frame_id,
138 pinocchio::LOCAL_WORLD_ALIGNED,
139 J);
140 // the model does not have any reference frame
142 this->get_joint_frames(),
143 this->robot_model_.frames[frame_id].name,
144 J,
145 this->get_base_frame());
146}
147
148state_representation::Jacobian Model::compute_jacobian(const state_representation::JointPositions& joint_positions,
149 const std::string& frame) {
150 auto frame_id = get_frame_id(frame);
151 return this->compute_jacobian(joint_positions, frame_id);
152}
153
154Eigen::MatrixXd Model::compute_jacobian_time_derivative(const state_representation::JointPositions& joint_positions,
155 const state_representation::JointVelocities& joint_velocities,
156 unsigned int frame_id) {
157 if (joint_positions.get_size() != this->get_number_of_joints()) {
158 throw (exceptions::InvalidJointStateSizeException(joint_positions.get_size(), this->get_number_of_joints()));
159 }
160 if (joint_velocities.get_size() != this->get_number_of_joints()) {
161 throw (exceptions::InvalidJointStateSizeException(joint_velocities.get_size(), this->get_number_of_joints()));
162 }
163 // compute the Jacobian from the joint state
164 pinocchio::Data::Matrix6x dJ = Eigen::MatrixXd::Zero(6, this->get_number_of_joints());
165 pinocchio::computeJointJacobiansTimeVariation(this->robot_model_,
166 this->robot_data_,
167 joint_positions.data(),
168 joint_velocities.data());
169 pinocchio::getFrameJacobianTimeVariation(this->robot_model_,
170 this->robot_data_,
171 frame_id,
172 pinocchio::LOCAL_WORLD_ALIGNED,
173 dJ);
174 // the model does not have any reference frame
175 return dJ;
176}
177
178Eigen::MatrixXd Model::compute_jacobian_time_derivative(const state_representation::JointPositions& joint_positions,
179 const state_representation::JointVelocities& joint_velocities,
180 const std::string& frame) {
181 auto frame_id = get_frame_id(frame);
182 return this->compute_jacobian_time_derivative(joint_positions, joint_velocities, frame_id);
183}
184
186 // compute only the upper part of the triangular inertia matrix stored in robot_data_.M
187 pinocchio::crba(this->robot_model_, this->robot_data_, joint_positions.data());
188 // copy the symmetric lower part
189 this->robot_data_.M.triangularView<Eigen::StrictlyLower>() =
190 this->robot_data_.M.transpose().triangularView<Eigen::StrictlyLower>();
191 return this->robot_data_.M;
192}
193
195 Eigen::MatrixXd inertia = this->compute_inertia_matrix(joint_state);
196 return state_representation::JointTorques(joint_state.get_name(),
197 joint_state.get_names(),
198 inertia * joint_state.get_accelerations());
199}
200
202 return pinocchio::computeCoriolisMatrix(this->robot_model_,
203 this->robot_data_,
204 joint_state.get_positions(),
205 joint_state.get_velocities());
206}
207
210 Eigen::MatrixXd coriolis_matrix = this->compute_coriolis_matrix(joint_state);
211 return state_representation::JointTorques(joint_state.get_name(),
212 joint_state.get_names(),
213 coriolis_matrix * joint_state.get_velocities());
214}
215
218 Eigen::VectorXd gravity_torque =
219 pinocchio::computeGeneralizedGravity(this->robot_model_, this->robot_data_, joint_positions.data());
220 return state_representation::JointTorques(joint_positions.get_name(), joint_positions.get_names(), gravity_torque);
221}
222
223state_representation::CartesianPose Model::forward_kinematics(const state_representation::JointPositions& joint_positions,
224 unsigned int frame_id) {
225 return this->forward_kinematics(joint_positions, std::vector<unsigned int>{frame_id}).front();
226}
227
228std::vector<state_representation::CartesianPose> Model::forward_kinematics(const state_representation::JointPositions& joint_positions,
229 const std::vector<unsigned int>& frame_ids) {
230 if (joint_positions.get_size() != this->get_number_of_joints()) {
231 throw (exceptions::InvalidJointStateSizeException(joint_positions.get_size(), this->get_number_of_joints()));
232 }
233 std::vector<state_representation::CartesianPose> pose_vector;
234 pinocchio::forwardKinematics(this->robot_model_, this->robot_data_, joint_positions.data());
235 for (unsigned int id : frame_ids) {
236 if (id >= static_cast<unsigned int>(this->robot_model_.nframes)) {
237 throw (exceptions::FrameNotFoundException(std::to_string(id)));
238 }
239 pinocchio::updateFramePlacement(this->robot_model_, this->robot_data_, id);
240 pinocchio::SE3 pose = this->robot_data_.oMf[id];
241 Eigen::Vector3d translation = pose.translation();
242 Eigen::Quaterniond quaternion;
243 pinocchio::quaternion::assignQuaternion(quaternion, pose.rotation());
244 state_representation::CartesianPose frame_pose(this->robot_model_.frames[id].name,
245 translation,
246 quaternion,
247 this->get_base_frame());
248 pose_vector.push_back(frame_pose);
249 }
250 return pose_vector;
251}
252
253state_representation::CartesianPose Model::forward_kinematics(const state_representation::JointPositions& joint_positions,
254 const std::string& frame) {
255 std::string actual_frame = frame.empty() ? this->robot_model_.frames.back().name : frame;
256 return this->forward_kinematics(joint_positions, std::vector<std::string>{actual_frame}).front();
257}
258
259std::vector<state_representation::CartesianPose> Model::forward_kinematics(const state_representation::JointPositions& joint_positions,
260 const std::vector<std::string>& frames) {
261 auto frame_ids = get_frame_ids(frames);
262 return this->forward_kinematics(joint_positions, frame_ids);
263}
264
265Eigen::MatrixXd Model::cwln_weighted_matrix(const state_representation::JointPositions& joint_positions,
266 const double margin) {
267 Eigen::MatrixXd W_b = Eigen::MatrixXd::Identity(this->robot_model_.nq, this->robot_model_.nq);
268 for (int n = 0; n < this->robot_model_.nq; ++n) {
269 double d = 1;
270 W_b(n, n) = 1;
271 if (joint_positions.data()[n] < this->robot_model_.lowerPositionLimit[n] + margin) {
272 if (joint_positions.data()[n] < this->robot_model_.lowerPositionLimit[n]) {
273 W_b(n, n) = 0;
274 } else {
275 d = (this->robot_model_.lowerPositionLimit[n] + margin - joint_positions.data()[n]) / margin;
276 W_b(n, n) = -2 * d * d * d + 3 * d * d;
277 }
278 } else if (this->robot_model_.upperPositionLimit[n] - margin < joint_positions.data()[n]) {
279 if (this->robot_model_.upperPositionLimit[n] < joint_positions.data()[n]) {
280 W_b(n, n) = 0;
281 } else {
282 d = (joint_positions.data()[n] - (this->robot_model_.upperPositionLimit[n] - margin)) / margin;
283 W_b(n, n) = -2 * d * d * d + 3 * d * d;
284 }
285 }
286 }
287 return W_b;
288}
289
290Eigen::VectorXd Model::cwln_repulsive_potential_field(const state_representation::JointPositions& joint_positions,
291 double margin) {
292 Eigen::VectorXd Psi(this->robot_model_.nq);
293 Eigen::VectorXd q = joint_positions.data();
294 for (int i = 0; i < this->robot_model_.nq; ++i) {
295 Psi[i] = 0;
296 if (q[i] < this->robot_model_.lowerPositionLimit[i] + margin) {
297 Psi[i] = this->robot_model_.upperPositionLimit[i] - margin
298 - std::max(q[i], this->robot_model_.lowerPositionLimit[i]);
299 } else if (this->robot_model_.upperPositionLimit[i] - margin < q[i]) {
300 Psi[i] = this->robot_model_.lowerPositionLimit[i] + margin
301 - std::min(q[i], this->robot_model_.upperPositionLimit[i]);
302 }
303 }
304 return Psi;
305}
306
309 const state_representation::JointPositions& joint_positions,
310 const InverseKinematicsParameters& parameters,
311 const std::string& frame) {
312 std::string actual_frame = frame.empty() ? this->robot_model_.frames.back().name : frame;
313 if (!this->robot_model_.existFrame(actual_frame)) {
314 throw (exceptions::FrameNotFoundException(actual_frame));
315 }
316 // 1 second for the Newton-Raphson method
317 const std::chrono::nanoseconds dt(static_cast<int>(1e9));
318 // initialization of the loop variables
319 state_representation::JointPositions q(joint_positions);
322 this->get_joint_frames(),
323 actual_frame,
324 this->get_base_frame());
325 Eigen::MatrixXd J_b = Eigen::MatrixXd::Zero(6, this->get_number_of_joints());
326 Eigen::MatrixXd JJt(6, 6);
327 Eigen::MatrixXd W_b = Eigen::MatrixXd::Identity(this->get_number_of_joints(), this->get_number_of_joints());
328 Eigen::MatrixXd W_c = Eigen::MatrixXd::Identity(this->get_number_of_joints(), this->get_number_of_joints());
329 Eigen::VectorXd psi(this->get_number_of_joints());
330 Eigen::VectorXd err(6);
331 for (unsigned int i = 0; i < parameters.max_number_of_iterations; ++i) {
332 err = ((cartesian_pose - this->forward_kinematics(q, actual_frame)) / dt).data();
333 // break in case of convergence
334 if (err.cwiseAbs().maxCoeff() < parameters.tolerance) {
335 return q;
336 }
337 J = this->compute_jacobian(q, actual_frame);
338 W_b = this->cwln_weighted_matrix(q, parameters.margin);
339 W_c = Eigen::MatrixXd::Identity(this->get_number_of_joints(), this->get_number_of_joints()) - W_b;
340 psi = parameters.gamma * this->cwln_repulsive_potential_field(q, parameters.margin);
341 J_b = J * W_b;
342 JJt.noalias() = J_b * J_b.transpose();
343 JJt.diagonal().array() += parameters.damp;
344 dq.set_velocities(W_c * psi + parameters.alpha * W_b * (J_b.transpose() * JJt.ldlt().solve(err - J * W_c * psi)));
345 q += dq * dt;
346 q = this->clamp_in_range(q);
347 }
348 throw (exceptions::InverseKinematicsNotConvergingException(parameters.max_number_of_iterations,
349 err.array().abs().maxCoeff()));
350}
351
354 const InverseKinematicsParameters& parameters,
355 const std::string& frame) {
356 Eigen::VectorXd q(pinocchio::neutral(this->robot_model_));
358 return this->inverse_kinematics(cartesian_pose, positions, parameters, frame);
359}
360
361std::vector<state_representation::CartesianTwist>
363 const std::vector<std::string>& frames) {
364 std::vector<state_representation::CartesianTwist> cartesian_twists(frames.size());
365 for (std::size_t i = 0; i < frames.size(); ++i) {
366 cartesian_twists.at(i) = this->compute_jacobian(joint_state, frames.at(i))
367 * static_cast<state_representation::JointVelocities>(joint_state);
368 }
369 return cartesian_twists;
370}
371
373 const std::string& frame) {
374 return this->forward_velocity(joint_state, std::vector<std::string>{frame}).front();
375}
376
377void Model::check_inverse_velocity_arguments(const std::vector<state_representation::CartesianTwist>& cartesian_twists,
378 const state_representation::JointPositions& joint_positions,
379 const std::vector<std::string>& frames) {
380 if (cartesian_twists.size() != frames.size()) {
381 throw (std::invalid_argument("The number of provided twists and frames does not match"));
382 }
383 if (joint_positions.get_size() != this->get_number_of_joints()) {
384 throw (exceptions::InvalidJointStateSizeException(joint_positions.get_size(), this->get_number_of_joints()));
385 }
386 for (auto& frame : frames) {
387 if (!this->robot_model_.existFrame(frame)) {
388 throw (exceptions::FrameNotFoundException(frame));
389 }
390 }
391}
392
394Model::inverse_velocity(const std::vector<state_representation::CartesianTwist>& cartesian_twists,
395 const state_representation::JointPositions& joint_positions,
396 const std::vector<std::string>& frames,
397 const double dls_lambda) {
398 // sanity check
399 this->check_inverse_velocity_arguments(cartesian_twists, joint_positions, frames);
400
401 const unsigned int nb_joints = this->get_number_of_joints();
402 // the velocity vector contains position of the intermediate frame and full pose of the end-effector
403 Eigen::VectorXd dX(3 * cartesian_twists.size() + 3);
404 Eigen::MatrixXd jacobian(3 * cartesian_twists.size() + 3, nb_joints);
405 for (unsigned int i = 0; i < cartesian_twists.size() - 1; ++i) {
406 // extract only the linear velocity for intermediate points
407 dX.segment<3>(3 * i) = cartesian_twists[i].get_linear_velocity();
408 jacobian.block(3 * i, 0, 3 * i + 3, nb_joints) =
409 this->compute_jacobian(joint_positions, frames.at(i)).data().block(0, 0, 3, nb_joints);
410 }
411 // full twist for the last provided frame
412 dX.tail(6) = cartesian_twists.back().data();
413 jacobian.bottomRows(6) = this->compute_jacobian(joint_positions, frames.back()).data();
414
415 if (dls_lambda == 0.0){
416 return state_representation::JointVelocities(joint_positions.get_name(),
417 joint_positions.get_names(),
418 jacobian.colPivHouseholderQr().solve(dX));
419 }
420
421 // add damped least square term
422 if (jacobian.rows() > jacobian.cols()){
423 Eigen::MatrixXd j_prime = jacobian.transpose() * jacobian +
424 dls_lambda * dls_lambda * Eigen::MatrixXd::Identity(jacobian.cols(), jacobian.cols());
425 return state_representation::JointVelocities(joint_positions.get_name(),
426 joint_positions.get_names(),
427 j_prime.colPivHouseholderQr().solve(jacobian.transpose() * dX));
428 } else {
429 Eigen::MatrixXd j_prime = jacobian * jacobian.transpose() +
430 dls_lambda * dls_lambda * Eigen::MatrixXd::Identity(jacobian.rows(), jacobian.rows());
431 return state_representation::JointVelocities(joint_positions.get_name(),
432 joint_positions.get_names(),
433 jacobian.transpose() * j_prime.colPivHouseholderQr().solve(dX));
434 }
435}
436
438 const state_representation::JointPositions& joint_positions,
439 const std::string& frame,
440 const double dls_lambda) {
441 std::string actual_frame = frame.empty() ? this->robot_model_.frames.back().name : frame;
442 return this->inverse_velocity(std::vector<state_representation::CartesianTwist>({cartesian_twist}),
443 joint_positions,
444 std::vector<std::string>({actual_frame}),
445 dls_lambda);
446}
447
449Model::inverse_velocity(const std::vector<state_representation::CartesianTwist>& cartesian_twists,
450 const state_representation::JointPositions& joint_positions,
451 const QPInverseVelocityParameters& parameters,
452 const std::vector<std::string>& frames) {
453 using namespace state_representation;
454 using namespace std::chrono;
455 // sanity check
456 this->check_inverse_velocity_arguments(cartesian_twists, joint_positions, frames);
457
458 const unsigned int nb_joints = this->get_number_of_joints();
459 // the velocity vector contains position of the intermediate frame and full pose of the end-effector
460 Eigen::VectorXd delta_r(3 * cartesian_twists.size() + 3);
461 Eigen::MatrixXd jacobian(3 * cartesian_twists.size() + 3, nb_joints);
462 for (unsigned int i = 0; i < cartesian_twists.size() - 1; ++i) {
463 // first convert the twist to a displacement
464 CartesianPose displacement = cartesian_twists[i];
465 // extract only the position for intermediate points
466 delta_r.segment<3>(3 * i) = displacement.get_position();
467 jacobian.block(3 * i, 0, 3 * i + 3, nb_joints) =
468 this->compute_jacobian(joint_positions, frames.at(i)).data().block(0, 0, 3, nb_joints);
469 }
470 // extract pose for the last provided frame
471 CartesianPose full_displacement = cartesian_twists.back();
472 delta_r.segment<3>(3 * (cartesian_twists.size() - 1)) = full_displacement.get_position();
473 delta_r.tail(3) = full_displacement.get_orientation().vec();
474 jacobian.bottomRows(6) = this->compute_jacobian(joint_positions, frames.back()).data();
475 // compute the Jacobian
476 Eigen::MatrixXd hessian_matrix = jacobian.transpose() * jacobian;
477 // set the hessian sparse matrix
478 std::vector<Eigen::Triplet<double>> coefficients;
479 for (unsigned int i = 0; i < nb_joints; ++i) {
480 for (unsigned int j = 0; j < nb_joints; ++j) {
481 coefficients.emplace_back(Eigen::Triplet<double>(i, j, hessian_matrix(i, j)));
482 }
483 }
484 coefficients.emplace_back(Eigen::Triplet<double>(nb_joints, nb_joints, parameters.alpha));
485 this->hessian_.setFromTriplets(coefficients.begin(), coefficients.end());
486 //set the gradient
487 this->gradient_.head(nb_joints) = -parameters.proportional_gain * delta_r.transpose() * jacobian;
488 // update minimal time as dt expressed in seconds
489 this->lower_bound_constraints_(3 * nb_joints) = duration_cast<duration<float>>(parameters.dt).count();
490 // update joint position constraints
491 Eigen::VectorXd lower_position_limit = this->robot_model_.lowerPositionLimit;
492 Eigen::VectorXd upper_position_limit = this->robot_model_.upperPositionLimit;
493 for (unsigned int n = 0; n < nb_joints; ++n) {
494 this->lower_bound_constraints_(n) = lower_position_limit(n) - joint_positions.data()(n);
495 this->upper_bound_constraints_(n) = upper_position_limit(n) - joint_positions.data()(n);
496 }
497 // update Cartesian velocity
498 this->constraint_matrix_.coeffRef(3 * nb_joints + 1, nb_joints) = parameters.linear_velocity_limit;
499 this->constraint_matrix_.coeffRef(3 * nb_joints + 2, nb_joints) = parameters.angular_velocity_limit;
500 this->lower_bound_constraints_(3 * nb_joints + 1) = full_displacement.get_position().norm();
501 this->lower_bound_constraints_(3 * nb_joints + 2) = full_displacement.get_orientation().vec().norm();
502
503 // update the constraints
504 this->solver_.updateHessianMatrix(this->hessian_);
505 this->solver_.updateGradient(this->gradient_);
506 this->solver_.updateBounds(this->lower_bound_constraints_, this->upper_bound_constraints_);
507 this->solver_.updateLinearConstraintsMatrix(this->constraint_matrix_);
508 // solve the QP problem
509 this->solver_.solve();
510 // extract the solution
511 JointPositions joint_displacement(joint_positions.get_name(),
512 joint_positions.get_names(),
513 this->solver_.getSolution().head(nb_joints));
514 double dt = this->solver_.getSolution().tail(1)(0);
515 return JointPositions(joint_displacement) / dt;
516}
517
519 const state_representation::JointPositions& joint_positions,
520 const QPInverseVelocityParameters& parameters,
521 const std::string& frame) {
522 std::string actual_frame = frame.empty() ? this->robot_model_.frames.back().name : frame;
523 return this->inverse_velocity(std::vector<state_representation::CartesianTwist>({cartesian_twist}),
524 joint_positions,
525 parameters,
526 std::vector<std::string>({actual_frame}));
527}
528
530 std::cout << "hessian:" << std::endl;
531 std::cout << this->hessian_ << std::endl;
532
533 std::cout << "gradient:" << std::endl;
534 std::cout << this->gradient_ << std::endl;
535
536 for (unsigned int i = 0; i < this->constraint_matrix_.rows(); ++i) {
537 std::cout << this->lower_bound_constraints_(i);
538 std::cout << " < | ";
539 for (unsigned int j = 0; j < this->constraint_matrix_.cols(); ++j) {
540 std::cout << this->constraint_matrix_.coeffRef(i, j) << " | ";
541 }
542 std::cout << " < ";
543 std::cout << this->upper_bound_constraints_(i) << std::endl;
544 }
545}
546
547bool Model::in_range(const Eigen::VectorXd& vector,
548 const Eigen::VectorXd& lower_limits,
549 const Eigen::VectorXd& upper_limits) {
550 return ((vector.array() >= lower_limits.array()).all() && (vector.array() <= upper_limits.array()).all());
551}
552
553bool Model::in_range(const state_representation::JointPositions& joint_positions) const {
554 return this->in_range(joint_positions.get_positions(),
555 this->robot_model_.lowerPositionLimit,
556 this->robot_model_.upperPositionLimit);
557}
558
559bool Model::in_range(const state_representation::JointVelocities& joint_velocities) const {
560 return this->in_range(joint_velocities.get_velocities(),
561 -this->robot_model_.velocityLimit,
562 this->robot_model_.velocityLimit);
563}
564
565bool Model::in_range(const state_representation::JointTorques& joint_torques) const {
566 return this->in_range(joint_torques.get_torques(), -this->robot_model_.effortLimit, this->robot_model_.effortLimit);
567}
568
569bool Model::in_range(const state_representation::JointState& joint_state) const {
570 return (this->in_range(static_cast<state_representation::JointPositions>(joint_state))
571 && this->in_range(static_cast<state_representation::JointVelocities>(joint_state))
572 && this->in_range(static_cast<state_representation::JointTorques>(joint_state)));
573}
574
575Eigen::VectorXd Model::clamp_in_range(const Eigen::VectorXd& vector,
576 const Eigen::VectorXd& lower_limits,
577 const Eigen::VectorXd& upper_limits) {
578 return lower_limits.cwiseMax(upper_limits.cwiseMin(vector));
579}
580
581state_representation::JointState Model::clamp_in_range(const state_representation::JointState& joint_state) const {
582 state_representation::JointState joint_state_clamped(joint_state);
583 joint_state_clamped.set_positions(this->clamp_in_range(joint_state.get_positions(),
584 this->robot_model_.lowerPositionLimit,
585 this->robot_model_.upperPositionLimit));
586 joint_state_clamped.set_velocities(this->clamp_in_range(joint_state.get_velocities(),
587 -this->robot_model_.velocityLimit,
588 this->robot_model_.velocityLimit));
589 joint_state_clamped.set_torques(this->clamp_in_range(joint_state.get_torques(),
590 -this->robot_model_.effortLimit,
591 this->robot_model_.effortLimit));
592 return joint_state_clamped;
593}
594}// namespace robot_model
The Model class is a wrapper around pinocchio dynamic computation library with state_representation e...
Definition Model.hpp:62
unsigned int get_number_of_joints() const
Getter of the number of joints.
Definition Model.hpp:533
std::vector< state_representation::CartesianTwist > forward_velocity(const state_representation::JointState &joint_state, const std::vector< std::string > &frames)
Compute the forward velocity kinematics, i.e. the twist of certain frames from the joint states.
Definition Model.cpp:362
Eigen::MatrixXd compute_coriolis_matrix(const state_representation::JointState &joint_state)
Compute the Coriolis matrix from a given joint state.
Definition Model.cpp:201
state_representation::JointTorques compute_inertia_torques(const state_representation::JointState &joint_state)
Compute the Inertia torques, i.e the inertia matrix multiplied by the joint accelerations....
Definition Model.cpp:194
state_representation::JointVelocities inverse_velocity(const std::vector< state_representation::CartesianTwist > &cartesian_twists, const state_representation::JointPositions &joint_positions, const std::vector< std::string > &frames, const double dls_lambda=0.0)
Compute the inverse velocity kinematics, i.e. joint velocities from the velocities of the frames in p...
Definition Model.cpp:394
const std::string & get_base_frame() const
Getter of the base frame of the robot.
Definition Model.hpp:543
state_representation::JointTorques compute_gravity_torques(const state_representation::JointPositions &joint_positions)
Compute the gravity torques.
Definition Model.cpp:217
Eigen::MatrixXd compute_inertia_matrix(const state_representation::JointPositions &joint_positions)
Compute the Inertia matrix from a given joint positions.
Definition Model.cpp:185
Model(const std::string &robot_name, const std::string &urdf_path)
Constructor with robot name and path to URDF file.
Definition Model.cpp:10
const std::string & get_urdf_path() const
Getter of the URDF path.
Definition Model.hpp:529
state_representation::JointPositions inverse_kinematics(const state_representation::CartesianPose &cartesian_pose, const InverseKinematicsParameters &parameters=InverseKinematicsParameters(), const std::string &frame="")
Compute the inverse kinematics, i.e. joint positions from the pose of the end-effector in an iterativ...
Definition Model.cpp:353
state_representation::JointTorques compute_coriolis_torques(const state_representation::JointState &joint_state)
Compute the Coriolis torques, i.e. the Coriolis matrix multiplied by the joint velocities and express...
Definition Model.cpp:209
void print_qp_problem()
Helper function to print the qp_problem (for debugging)
Definition Model.cpp:529
const std::string & get_robot_name() const
Getter of the robot name.
Definition Model.hpp:521
std::vector< std::string > get_joint_frames() const
Getter of the joint frames from the model.
Definition Model.hpp:537
static bool create_urdf_from_string(const std::string &urdf_string, const std::string &desired_path)
Creates a URDF file with desired path and name from a string (possibly the robot description string f...
Definition Model.cpp:22
Class to define Cartesian pose in Cartesian space as 3D position and quaternion based orientation.
const Eigen::Vector3d & get_position() const
Getter of the position attribute.
const Eigen::Quaterniond & get_orientation() const
Getter of the orientation attribute.
Class to define twist in Cartesian space as 3D linear and angular velocity vectors.
Class to define a robot Jacobian matrix.
Definition Jacobian.hpp:21
const Eigen::MatrixXd & data() const
Getter of the data attribute.
Definition Jacobian.cpp:113
Eigen::MatrixXd transpose() const
Return the transpose of the Jacobian matrix.
Definition Jacobian.cpp:261
Class to define positions of the joints.
Class to define a state in joint space.
void set_positions(const Eigen::VectorXd &positions)
Setter of the positions attribute.
void set_torques(const Eigen::VectorXd &torques)
Setter of the torques attribute.
const std::vector< std::string > & get_names() const
Getter of the names attribute.
void set_velocities(const Eigen::VectorXd &velocities)
Setter of the velocities attribute.
Class to define torques of the joints.
Class to define velocities of the joints.
Robot kinematics and dynamics.
Core state variables and objects.
parameters for the inverse kinematics function
Definition Model.hpp:32
parameters for the inverse velocity kinematics function
Definition Model.hpp:49