Rigid Body Dynamics Library
Kinematics.cc
Go to the documentation of this file.
1/*
2 * RBDL - Rigid Body Dynamics Library
3 * Copyright (c) 2011-2018 Martin Felis <martin@fysx.org>
4 *
5 * Licensed under the zlib license. See LICENSE for more details.
6 */
7
8#include <iostream>
9#include <limits>
10#include <cstring>
11#include <assert.h>
12
13#include "rbdl/rbdl_mathutils.h"
14#include "rbdl/Logging.h"
15
16#include "rbdl/Model.h"
17#include "rbdl/Kinematics.h"
18
19#include "rbdl/rbdl_utils.h"
20
21namespace RigidBodyDynamics {
22
23using namespace Math;
24
25RBDL_DLLAPI void UpdateKinematics(
26 Model &model,
27 const VectorNd &Q,
28 const VectorNd &QDot,
29 const VectorNd &QDDot) {
30 LOG << "-------- " << __func__ << " --------" << std::endl;
31
32 unsigned int i;
33
34 model.a[0].setZero();
35
36 for (i = 1; i < model.mBodies.size(); i++) {
37 unsigned int q_index = model.mJoints[i].q_index;
38 unsigned int lambda = model.lambda[i];
39
40 jcalc (model, i, Q, QDot);
41
42 if (lambda != 0) {
43 model.X_base[i] = model.X_lambda[i] * model.X_base[lambda];
44 model.v[i] = model.X_lambda[i].apply(model.v[lambda]) + model.v_J[i];
45 } else {
46 model.X_base[i] = model.X_lambda[i];
47 model.v[i] = model.v_J[i];
48 }
49
50 model.c[i] = model.c_J[i] + crossm(model.v[i],model.v_J[i]);
51 model.a[i] = model.X_lambda[i].apply(model.a[lambda]) + model.c[i];
52
53 if(model.mJoints[i].mJointType != JointTypeCustom){
54 if (model.mJoints[i].mDoFCount == 1) {
55 model.a[i] = model.a[i] + model.S[i] * QDDot[q_index];
56 } else if (model.mJoints[i].mDoFCount == 3) {
57 Vector3d omegadot_temp (QDDot[q_index],
58 QDDot[q_index + 1],
59 QDDot[q_index + 2]);
60 model.a[i] = model.a[i] + model.multdof3_S[i] * omegadot_temp;
61 }
62 } else {
63 unsigned int custom_index = model.mJoints[i].custom_joint_index;
64 const CustomJoint* custom_joint = model.mCustomJoints[custom_index];
65 unsigned int joint_dof_count = custom_joint->mDoFCount;
66
67 model.a[i] = model.a[i]
68 + ( model.mCustomJoints[custom_index]->S
69 * QDDot.block(q_index, 0, joint_dof_count, 1));
70 }
71 }
72
73 for (i = 1; i < model.mBodies.size(); i++) {
74 LOG << "a[" << i << "] = " << model.a[i].transpose() << std::endl;
75 }
76}
77
78RBDL_DLLAPI void UpdateKinematicsCustom(
79 Model &model,
80 const VectorNd *Q,
81 const VectorNd *QDot,
82 const VectorNd *QDDot) {
83 LOG << "-------- " << __func__ << " --------" << std::endl;
84
85 unsigned int i;
86
87 if (Q) {
88 for (i = 1; i < model.mBodies.size(); i++) {
89 unsigned int lambda = model.lambda[i];
90
91 VectorNd QDot_zero (VectorNd::Zero (model.q_size));
92
93 jcalc (model, i, (*Q), QDot_zero);
94
95 if (lambda != 0) {
96 model.X_base[i] = model.X_lambda[i] * model.X_base[lambda];
97 } else {
98 model.X_base[i] = model.X_lambda[i];
99 }
100 }
101 }
102
103 if (QDot) {
104 for (i = 1; i < model.mBodies.size(); i++) {
105 unsigned int lambda = model.lambda[i];
106
107 jcalc (model, i, *Q, *QDot);
108
109 if (lambda != 0) {
110 model.v[i] = model.X_lambda[i].apply(model.v[lambda]) + model.v_J[i];
111 model.c[i] = model.c_J[i] + crossm(model.v[i],model.v_J[i]);
112 } else {
113 model.v[i] = model.v_J[i];
114 model.c[i] = model.c_J[i] + crossm(model.v[i],model.v_J[i]);
115 }
116 // LOG << "v[" << i << "] = " << model.v[i].transpose() << std::endl;
117 }
118 }
119
120 // FIXME?: Changing QDot can alter body accelerations via c[] - update to QDot but not QDDot can result in incorrect a[]
121 if (QDDot) {
122 for (i = 1; i < model.mBodies.size(); i++) {
123 unsigned int q_index = model.mJoints[i].q_index;
124
125 unsigned int lambda = model.lambda[i];
126
127 if (lambda != 0) {
128 model.a[i] = model.X_lambda[i].apply(model.a[lambda]) + model.c[i];
129 } else {
130 model.a[i] = model.c[i];
131 }
132
133 if( model.mJoints[i].mJointType != JointTypeCustom){
134 if (model.mJoints[i].mDoFCount == 1) {
135 model.a[i] = model.a[i] + model.S[i] * (*QDDot)[q_index];
136 } else if (model.mJoints[i].mDoFCount == 3) {
137 Vector3d omegadot_temp ((*QDDot)[q_index],
138 (*QDDot)[q_index + 1],
139 (*QDDot)[q_index + 2]);
140 model.a[i] = model.a[i]
141 + model.multdof3_S[i] * omegadot_temp;
142 }
143 } else {
144 unsigned int k = model.mJoints[i].custom_joint_index;
145
146 const CustomJoint* custom_joint = model.mCustomJoints[k];
147 unsigned int joint_dof_count = custom_joint->mDoFCount;
148
149 model.a[i] = model.a[i]
150 + ( (model.mCustomJoints[k]->S)
151 *(QDDot->block(q_index, 0, joint_dof_count, 1)));
152 }
153 }
154 }
155}
156
158 Model &model,
159 const VectorNd &Q,
160 unsigned int body_id,
161 const Vector3d &point_body_coordinates,
162 bool update_kinematics) {
163 // update the Kinematics if necessary
164 if (update_kinematics) {
165 UpdateKinematicsCustom (model, &Q, NULL, NULL);
166 }
167
168 if (body_id >= model.fixed_body_discriminator) {
169 unsigned int fbody_id = body_id - model.fixed_body_discriminator;
170 unsigned int parent_id = model.mFixedBodies[fbody_id].mMovableParent;
171
172 Matrix3d fixed_rotation =
173 model.mFixedBodies[fbody_id].mParentTransform.E.transpose();
174 Vector3d fixed_position = model.mFixedBodies[fbody_id].mParentTransform.r;
175
176 Matrix3d parent_body_rotation = model.X_base[parent_id].E.transpose();
177 Vector3d parent_body_position = model.X_base[parent_id].r;
178
179 return (parent_body_position
180 + (parent_body_rotation
181 * (fixed_position + fixed_rotation * (point_body_coordinates))) );
182 }
183
184 Matrix3d body_rotation = model.X_base[body_id].E.transpose();
185 Vector3d body_position = model.X_base[body_id].r;
186
187 return body_position + body_rotation * point_body_coordinates;
188}
189
191 Model &model,
192 const VectorNd &Q,
193 unsigned int body_id,
194 const Vector3d &point_base_coordinates,
195 bool update_kinematics) {
196 if (update_kinematics) {
197 UpdateKinematicsCustom (model, &Q, NULL, NULL);
198 }
199
200 if (body_id >= model.fixed_body_discriminator) {
201 unsigned int fbody_id = body_id - model.fixed_body_discriminator;
202 unsigned int parent_id = model.mFixedBodies[fbody_id].mMovableParent;
203
204 Matrix3d fixed_rotation = model.mFixedBodies[fbody_id].mParentTransform.E;
205 Vector3d fixed_position = model.mFixedBodies[fbody_id].mParentTransform.r;
206
207 Matrix3d parent_body_rotation = model.X_base[parent_id].E;
208 Vector3d parent_body_position = model.X_base[parent_id].r;
209
210 return (fixed_rotation
211 * ( - fixed_position
212 - parent_body_rotation
213 * (parent_body_position - point_base_coordinates)));
214 }
215
216 Matrix3d body_rotation = model.X_base[body_id].E;
217 Vector3d body_position = model.X_base[body_id].r;
218
219 return body_rotation * (point_base_coordinates - body_position);
220}
221
223 Model &model,
224 const VectorNd &Q,
225 const unsigned int body_id,
226 bool update_kinematics) {
227 // update the Kinematics if necessary
228 if (update_kinematics) {
229 UpdateKinematicsCustom (model, &Q, NULL, NULL);
230 }
231
232 if (body_id >= model.fixed_body_discriminator) {
233 unsigned int fbody_id = body_id - model.fixed_body_discriminator;
234 model.mFixedBodies[fbody_id].mBaseTransform =
235 model.mFixedBodies[fbody_id].mParentTransform
236 * model.X_base[model.mFixedBodies[fbody_id].mMovableParent];
237
238 return model.mFixedBodies[fbody_id].mBaseTransform.E;
239 }
240
241 return model.X_base[body_id].E;
242}
243
244RBDL_DLLAPI void CalcPointJacobian (
245 Model &model,
246 const VectorNd &Q,
247 unsigned int body_id,
248 const Vector3d &point_position,
249 MatrixNd &G,
250 bool update_kinematics) {
251 LOG << "-------- " << __func__ << " --------" << std::endl;
252
253 // update the Kinematics if necessary
254 if (update_kinematics) {
255 UpdateKinematicsCustom (model, &Q, NULL, NULL);
256 }
257
258 SpatialTransform point_trans =
259 SpatialTransform (Matrix3d::Identity(),
261 Q,
262 body_id,
263 point_position,
264 false));
265
266 assert (G.rows() == 3 && G.cols() == model.qdot_size );
267
268 unsigned int reference_body_id = body_id;
269
270 if (model.IsFixedBodyId(body_id)) {
271 unsigned int fbody_id = body_id - model.fixed_body_discriminator;
272 reference_body_id = model.mFixedBodies[fbody_id].mMovableParent;
273 }
274
275 unsigned int j = reference_body_id;
276
277 // e[j] is set to 1 if joint j contributes to the jacobian that we are
278 // computing. For all other joints the column will be zero.
279 while (j != 0) {
280 unsigned int q_index = model.mJoints[j].q_index;
281
282 if(model.mJoints[j].mJointType != JointTypeCustom){
283 if (model.mJoints[j].mDoFCount == 1) {
284 G.block(0,q_index, 3, 1) =
285 point_trans.apply(
286 model.X_base[j].inverse().apply(
287 model.S[j])).block<3, 1>(3,0);
288 } else if (model.mJoints[j].mDoFCount == 3) {
289 G.block(0, q_index, 3, 3) =
290 ((point_trans
291 * model.X_base[j].inverse()).toMatrix()
292 * model.multdof3_S[j]).block<3, 3>(3,0);
293 }
294 } else {
295 unsigned int k = model.mJoints[j].custom_joint_index;
296
297 G.block(0, q_index, 3, model.mCustomJoints[k]->mDoFCount) =
298 ((point_trans
299 * model.X_base[j].inverse()).toMatrix()
300 * model.mCustomJoints[k]->S).block(
301 3,0,3,model.mCustomJoints[k]->mDoFCount);
302 }
303
304 j = model.lambda[j];
305 }
306}
307
308RBDL_DLLAPI void CalcPointJacobian6D (
309 Model &model,
310 const VectorNd &Q,
311 unsigned int body_id,
312 const Vector3d &point_position,
313 MatrixNd &G,
314 bool update_kinematics) {
315 LOG << "-------- " << __func__ << " --------" << std::endl;
316
317 // update the Kinematics if necessary
318 if (update_kinematics) {
319 UpdateKinematicsCustom (model, &Q, NULL, NULL);
320 }
321
322 SpatialTransform point_trans =
323 SpatialTransform (Matrix3d::Identity(),
325 Q,
326 body_id,
327 point_position,
328 false));
329
330 assert (G.rows() == 6 && G.cols() == model.qdot_size );
331
332 unsigned int reference_body_id = body_id;
333
334 if (model.IsFixedBodyId(body_id)) {
335 unsigned int fbody_id = body_id - model.fixed_body_discriminator;
336 reference_body_id = model.mFixedBodies[fbody_id].mMovableParent;
337 }
338
339 unsigned int j = reference_body_id;
340
341 while (j != 0) {
342 unsigned int q_index = model.mJoints[j].q_index;
343
344 if(model.mJoints[j].mJointType != JointTypeCustom){
345 if (model.mJoints[j].mDoFCount == 1) {
346 G.block(0,q_index, 6, 1)
347 = point_trans.apply(
348 model.X_base[j].inverse().apply(
349 model.S[j])).block<6, 1>(0,0);
350 } else if (model.mJoints[j].mDoFCount == 3) {
351 G.block(0, q_index, 6, 3)
352 = ((point_trans
353 * model.X_base[j].inverse()).toMatrix()
354 * model.multdof3_S[j]).block<6, 3>(0,0);
355 }
356 } else {
357 unsigned int k = model.mJoints[j].custom_joint_index;
358
359 G.block(0, q_index, 6, model.mCustomJoints[k]->mDoFCount)
360 = ((point_trans
361 * model.X_base[j].inverse()).toMatrix()
362 * model.mCustomJoints[k]->S).block(
363 0,0,6,model.mCustomJoints[k]->mDoFCount);
364 }
365
366 j = model.lambda[j];
367 }
368}
369
370RBDL_DLLAPI void CalcBodySpatialJacobian (
371 Model &model,
372 const VectorNd &Q,
373 unsigned int body_id,
374 MatrixNd &G,
375 bool update_kinematics) {
376 LOG << "-------- " << __func__ << " --------" << std::endl;
377
378 // update the Kinematics if necessary
379 if (update_kinematics) {
380 UpdateKinematicsCustom (model, &Q, NULL, NULL);
381 }
382
383 assert (G.rows() == 6 && G.cols() == model.qdot_size );
384
385 unsigned int reference_body_id = body_id;
386
387 SpatialTransform base_to_body;
388
389 if (model.IsFixedBodyId(body_id)) {
390 unsigned int fbody_id = body_id
391 - model.fixed_body_discriminator;
392
393 reference_body_id = model
394 .mFixedBodies[fbody_id]
395 .mMovableParent;
396
397 base_to_body = model.mFixedBodies[fbody_id]
398 .mParentTransform
399 * model.X_base[reference_body_id];
400 } else {
401 base_to_body = model.X_base[reference_body_id];
402 }
403
404 unsigned int j = reference_body_id;
405
406 while (j != 0) {
407 unsigned int q_index = model.mJoints[j].q_index;
408
409 if(model.mJoints[j].mJointType != JointTypeCustom){
410 if (model.mJoints[j].mDoFCount == 1) {
411 G.block(0,q_index,6,1) =
412 base_to_body.apply(
413 model.X_base[j]
414 .inverse()
415 .apply(model.S[j])
416 );
417 } else if (model.mJoints[j].mDoFCount == 3) {
418 G.block(0,q_index,6,3) =
419 (base_to_body * model.X_base[j].inverse()
420 ).toMatrix() * model.multdof3_S[j];
421 }
422 }else if(model.mJoints[j].mJointType == JointTypeCustom) {
423 unsigned int k = model.mJoints[j].custom_joint_index;
424
425 G.block(0,q_index,6,model.mCustomJoints[k]->mDoFCount ) =
426 (base_to_body * model.X_base[j].inverse()
427 ).toMatrix() * model.mCustomJoints[k]->S;
428 }
429
430 j = model.lambda[j];
431 }
432}
433
435 Model &model,
436 const VectorNd &Q,
437 const VectorNd &QDot,
438 unsigned int body_id,
439 const Vector3d &point_position,
440 bool update_kinematics) {
441 LOG << "-------- " << __func__ << " --------" << std::endl;
442 assert (model.IsBodyId(body_id) || body_id == 0);
443 assert (model.q_size == Q.size());
444 assert (model.qdot_size == QDot.size());
445
446 // Reset the velocity of the root body
447 model.v[0].setZero();
448
449 // update the Kinematics with zero acceleration
450 if (update_kinematics) {
451 UpdateKinematicsCustom (model, &Q, &QDot, NULL);
452 }
453
454 unsigned int reference_body_id = body_id;
455 Vector3d reference_point = point_position;
456
457 if (model.IsFixedBodyId(body_id)) {
458 unsigned int fbody_id = body_id - model.fixed_body_discriminator;
459 reference_body_id = model.mFixedBodies[fbody_id].mMovableParent;
460 Vector3d base_coords =
461 CalcBodyToBaseCoordinates(model, Q, body_id, point_position, false);
462 reference_point =
463 CalcBaseToBodyCoordinates(model, Q, reference_body_id, base_coords,false);
464 }
465
466 SpatialVector point_spatial_velocity =
468 CalcBodyWorldOrientation (model, Q, reference_body_id, false).transpose(),
469 reference_point).apply(model.v[reference_body_id]);
470
471 return Vector3d (
472 point_spatial_velocity[3],
473 point_spatial_velocity[4],
474 point_spatial_velocity[5]
475 );
476}
477
479 Model &model,
480 const Math::VectorNd &Q,
481 const Math::VectorNd &QDot,
482 unsigned int body_id,
483 const Math::Vector3d &point_position,
484 bool update_kinematics) {
485 LOG << "-------- " << __func__ << " --------" << std::endl;
486 assert (model.IsBodyId(body_id) || body_id == 0);
487 assert (model.q_size == Q.size());
488 assert (model.qdot_size == QDot.size());
489
490 // Reset the velocity of the root body
491 model.v[0].setZero();
492
493 // update the Kinematics with zero acceleration
494 if (update_kinematics) {
495 UpdateKinematicsCustom (model, &Q, &QDot, NULL);
496 }
497
498 unsigned int reference_body_id = body_id;
499 Vector3d reference_point = point_position;
500
501 if (model.IsFixedBodyId(body_id)) {
502 unsigned int fbody_id = body_id - model.fixed_body_discriminator;
503 reference_body_id = model.mFixedBodies[fbody_id].mMovableParent;
504 Vector3d base_coords =
505 CalcBodyToBaseCoordinates(model, Q, body_id, point_position, false);
506 reference_point =
507 CalcBaseToBodyCoordinates(model, Q, reference_body_id, base_coords,false);
508 }
509
510 return SpatialTransform (
511 CalcBodyWorldOrientation (model, Q, reference_body_id, false).transpose(),
512 reference_point).apply(model.v[reference_body_id]);
513}
514
516 Model &model,
517 const VectorNd &Q,
518 const VectorNd &QDot,
519 const VectorNd &QDDot,
520 unsigned int body_id,
521 const Vector3d &point_position,
522 bool update_kinematics) {
523 LOG << "-------- " << __func__ << " --------" << std::endl;
524
525 // Reset the velocity of the root body
526 model.v[0].setZero();
527 model.a[0].setZero();
528
529 if (update_kinematics)
530 UpdateKinematics (model, Q, QDot, QDDot);
531
532 LOG << std::endl;
533
534 unsigned int reference_body_id = body_id;
535 Vector3d reference_point = point_position;
536
537 if (model.IsFixedBodyId(body_id)) {
538 unsigned int fbody_id = body_id - model.fixed_body_discriminator;
539 reference_body_id = model.mFixedBodies[fbody_id].mMovableParent;
540 Vector3d base_coords =
541 CalcBodyToBaseCoordinates (model, Q, body_id, point_position, false);
542 reference_point =
543 CalcBaseToBodyCoordinates (model, Q, reference_body_id,base_coords,false);
544 }
545
546 SpatialTransform p_X_i (
547 CalcBodyWorldOrientation (model, Q, reference_body_id, false).transpose(),
548 reference_point);
549
550 SpatialVector p_v_i = p_X_i.apply(model.v[reference_body_id]);
551 Vector3d a_dash = Vector3d (p_v_i[0], p_v_i[1], p_v_i[2]
552 ).cross(Vector3d (p_v_i[3], p_v_i[4], p_v_i[5]));
553 SpatialVector p_a_i = p_X_i.apply(model.a[reference_body_id]);
554
555 return Vector3d (
556 p_a_i[3] + a_dash[0],
557 p_a_i[4] + a_dash[1],
558 p_a_i[5] + a_dash[2]
559 );
560}
561
563 Model &model,
564 const VectorNd &Q,
565 const VectorNd &QDot,
566 const VectorNd &QDDot,
567 unsigned int body_id,
568 const Vector3d &point_position,
569 bool update_kinematics) {
570 LOG << "-------- " << __func__ << " --------" << std::endl;
571
572 // Reset the velocity of the root body
573 model.v[0].setZero();
574 model.a[0].setZero();
575
576 if (update_kinematics)
577 UpdateKinematics (model, Q, QDot, QDDot);
578
579 LOG << std::endl;
580
581 unsigned int reference_body_id = body_id;
582 Vector3d reference_point = point_position;
583
584 if (model.IsFixedBodyId(body_id)) {
585 unsigned int fbody_id = body_id - model.fixed_body_discriminator;
586 reference_body_id = model.mFixedBodies[fbody_id].mMovableParent;
587 Vector3d base_coords =
588 CalcBodyToBaseCoordinates (model, Q, body_id, point_position, false);
589 reference_point =
590 CalcBaseToBodyCoordinates (model, Q, reference_body_id,base_coords,false);
591 }
592
593 SpatialTransform p_X_i (
594 CalcBodyWorldOrientation (model, Q, reference_body_id, false).transpose(),
595 reference_point);
596
597 SpatialVector p_v_i = p_X_i.apply(model.v[reference_body_id]);
598 Vector3d a_dash = Vector3d (p_v_i[0], p_v_i[1], p_v_i[2]
599 ).cross(Vector3d (p_v_i[3], p_v_i[4], p_v_i[5]));
600 return (p_X_i.apply(model.a[reference_body_id])
601 + SpatialVector (0, 0, 0, a_dash[0], a_dash[1], a_dash[2]));
602}
603
604#ifndef RBDL_USE_CASADI_MATH
605RBDL_DLLAPI bool InverseKinematics (
606 Model &model,
607 const VectorNd &Qinit,
608 const std::vector<unsigned int>& body_id,
609 const std::vector<Vector3d>& body_point,
610 const std::vector<Vector3d>& target_pos,
611 VectorNd &Qres,
612 double step_tol,
613 double lambda,
614 unsigned int max_iter) {
615 assert (Qinit.size() == model.q_size);
616 assert (body_id.size() == body_point.size());
617 assert (body_id.size() == target_pos.size());
618
619 MatrixNd J = MatrixNd::Zero(3 * body_id.size(), model.qdot_size);
620 VectorNd e = VectorNd::Zero(3 * body_id.size());
621
622 Qres = Qinit;
623
624 for (unsigned int ik_iter = 0; ik_iter < max_iter; ik_iter++) {
625 UpdateKinematicsCustom (model, &Qres, NULL, NULL);
626
627 for (unsigned int k = 0; k < body_id.size(); k++) {
628 MatrixNd G (MatrixNd::Zero(3, model.qdot_size));
629 CalcPointJacobian (model, Qres, body_id[k], body_point[k], G, false);
630 Vector3d point_base =
631 CalcBodyToBaseCoordinates (model, Qres, body_id[k], body_point[k], false);
632 LOG << "current_pos = " << point_base.transpose() << std::endl;
633
634 for (unsigned int i = 0; i < 3; i++) {
635 for (unsigned int j = 0; j < model.qdot_size; j++) {
636 unsigned int row = k * 3 + i;
637 LOG << "i = " << i << " j = " << j << " k = " << k << " row = "
638 << row << " col = " << j << std::endl;
639 J(row, j) = G (i,j);
640 }
641
642 e[k * 3 + i] = target_pos[k][i] - point_base[i];
643 }
644 }
645
646 LOG << "J = " << J << std::endl;
647 LOG << "e = " << e.transpose() << std::endl;
648
649 // abort if we are getting "close"
650 if (e.norm() < step_tol) {
651 LOG << "Reached target close enough after " << ik_iter << " steps" << std::endl;
652 return true;
653 }
654
655 MatrixNd JJTe_lambda2_I =
656 J * J.transpose()
657 + lambda*lambda * MatrixNd::Identity(e.size(), e.size());
658
659 VectorNd z (body_id.size() * 3);
660
661 bool solve_successful = LinSolveGaussElimPivot (JJTe_lambda2_I, e, z);
662 assert (solve_successful);
663
664 LOG << "z = " << z << std::endl;
665
666 VectorNd delta_theta = J.transpose() * z;
667 LOG << "change = " << delta_theta << std::endl;
668
669 Qres = Qres + delta_theta;
670 LOG << "Qres = " << Qres.transpose() << std::endl;
671
672 if (delta_theta.norm() < step_tol) {
673 LOG << "reached convergence after " << ik_iter << " steps" << std::endl;
674 return true;
675 }
676
677 VectorNd test_1 (z.size());
678 VectorNd test_res (z.size());
679
680 test_1.setZero();
681
682 for (unsigned int i = 0; i < z.size(); i++) {
683 test_1[i] = 1.;
684
685 VectorNd test_delta = J.transpose() * test_1;
686
687 test_res[i] = test_delta.squaredNorm();
688
689 test_1[i] = 0.;
690 }
691
692 LOG << "test_res = " << test_res.transpose() << std::endl;
693 }
694
695 return false;
696}
697
698RBDL_DLLAPI
700 const Matrix3d &RotMat
701 ) {
702 double tol = 1e-12;
703
704 Vector3d l = Vector3d (RotMat(2,1) - RotMat(1,2), RotMat(0,2) - RotMat(2,0), RotMat(1,0) - RotMat(0,1));
705 if(l.norm() > tol){
706 double preFactor = atan2(l.norm(),(RotMat.trace() - 1.0))/l.norm();
707 return preFactor*l;
708 }
709 else if((RotMat(0,0)>0 && RotMat(1,1)>0 && RotMat(2,2) > 0) || l.norm() < tol){
710 return Vector3dZero;
711 }
712 else{
713 double PI = atan(1)*4.0;
714 return Vector3d (PI/2*(RotMat(0,0) + 1.0),PI/2*(RotMat(1,1) + 1.0),PI/2*(RotMat(2,2) + 1.0));
715 }
716}
717
718RBDL_DLLAPI
720 lambda = 1e-9;
721 num_steps = 0;
722 max_steps = 300;
723 step_tol = 1e-12;
724 constraint_tol = 1e-12;
725 num_constraints = 0;
726}
727
728RBDL_DLLAPI
730 unsigned int body_id,
731 const Vector3d& body_point,
732 const Vector3d& target_pos,
733 float weight
734 ) {
736 body_ids.push_back(body_id);
737 body_points.push_back(body_point);
738 target_positions.push_back(target_pos);
739 target_orientations.push_back(Matrix3d::Zero());
740 constraint_weight.push_back(weight);
743 return constraint_type.size() - 1;
744}
745
746
748 unsigned int body_id,
749 const Vector3d& body_point,
750 const Vector3d& target_pos,
751 float weight
752 ) {
754 body_ids.push_back(body_id);
755 body_points.push_back(body_point);
756 target_positions.push_back(target_pos);
757 target_orientations.push_back(Matrix3d::Zero());
758 constraint_weight.push_back(weight);
761 return constraint_type.size() - 1;
762}
763
764
766 unsigned int body_id,
767 const Vector3d& body_point,
768 const Vector3d& target_pos,
769 float weight
770 ) {
772 body_ids.push_back(body_id);
773 body_points.push_back(body_point);
774 target_positions.push_back(target_pos);
775 target_orientations.push_back(Matrix3d::Zero());
776 constraint_weight.push_back(weight);
779 return constraint_type.size() - 1;
780}
781
783 unsigned int body_id,
784 //const Vector3d& body_point,
785 const Vector3d& target_pos,
786 float weight
787 ) {
789 body_ids.push_back(body_id);
790 body_points.push_back(Vector3d::Zero());
791 target_positions.push_back(target_pos);
792 target_orientations.push_back(Matrix3d::Zero());
793 constraint_weight.push_back(weight);
796 return constraint_type.size() - 1;
797}
798
799
800RBDL_DLLAPI
802 unsigned int body_id,
803 const Matrix3d& target_orientation,
804 float weight
805 ) {
807 body_ids.push_back(body_id);
808 body_points.push_back(Vector3d::Zero());
809 target_positions.push_back(Vector3d::Zero());
810 target_orientations.push_back(target_orientation);
812 constraint_weight.push_back(weight);
814 return constraint_type.size() - 1;
815}
816
817RBDL_DLLAPI
819 unsigned int body_id,
820 const Vector3d& body_point,
821 const Vector3d& target_pos,
822 const Matrix3d& target_orientation,
823 float weight
824 ) {
826 body_ids.push_back(body_id);
827 body_points.push_back(body_point);
828 target_positions.push_back(target_pos);
829 target_orientations.push_back(target_orientation);
831 constraint_weight.push_back(weight);
833 return constraint_type.size() - 1;
834}
835
836RBDL_DLLAPI
838{
839 unsigned int size = constraint_type.size();
840 for (unsigned int i = 0; i < size; i++){
841 constraint_type.pop_back();
842 body_ids.pop_back();
843 body_points.pop_back();
844 target_positions.pop_back();
845 target_orientations.pop_back();
846 constraint_row_index.pop_back();
847 constraint_weight.pop_back();
848 }
849 num_constraints = 0;
850 return constraint_type.size();
851}
852
853
854RBDL_DLLAPI
856 Model &model,
857 const Math::VectorNd &Qinit,
859 Math::VectorNd &Qres
860 ) {
861 assert (Qinit.size() == model.q_size);
862 assert (Qres.size() == Qinit.size());
863
864 CS.J = MatrixNd::Zero(CS.num_constraints, model.qdot_size);
866 double mass;
867
868 Qres = Qinit;
869
870 for (CS.num_steps = 0; CS.num_steps < CS.max_steps; CS.num_steps++) {
871 UpdateKinematicsCustom (model, &Qres, NULL, NULL);
872
873 for (unsigned int k = 0; k < CS.body_ids.size(); k++) {
874 CS.G = MatrixNd::Zero(6, model.qdot_size);
875 CalcPointJacobian6D (model, Qres, CS.body_ids[k], CS.body_points[k], CS.G, false);
876 Vector3d point_base = CalcBodyToBaseCoordinates (model, Qres, CS.body_ids[k], CS.body_points[k], false);
877 Matrix3d R = CalcBodyWorldOrientation(model, Qres, CS.body_ids[k], false);
878 Vector3d angular_velocity = R.transpose()*CalcAngularVelocityfromMatrix(R*CS.target_orientations[k].transpose());
879
880 //assign offsets and Jacobians
882 for (unsigned int i = 0; i < 3; i++){
883 unsigned int row = CS.constraint_row_index[k] + i;
884 CS.e[row + 3] = CS.constraint_weight.at(k)*(CS.target_positions[k][i] - point_base[i]);
885 CS.e[row] = CS.constraint_weight.at(k)*angular_velocity[i];
886 for (unsigned int j = 0; j < model.qdot_size; j++) {
887 CS.J(row + 3, j) = CS.constraint_weight.at(k)*CS.G (i + 3,j);
888 CS.J(row, j) = CS.constraint_weight.at(k)*CS.G (i,j);
889 }
890 }
891 }
893 for (unsigned int i = 0; i < 3; i++){
894 unsigned int row = CS.constraint_row_index[k] + i;
895 CS.e[row] = CS.constraint_weight.at(k)*angular_velocity[i];
896 for (unsigned int j = 0; j < model.qdot_size; j++) {
897 CS.J(row, j) = CS.constraint_weight.at(k)*CS.G (i,j);
898 }
899 }
900 }
902 for (unsigned int i = 0; i < 3; i++){
903 unsigned int row = CS.constraint_row_index[k] + i;
904 CS.e[row] = CS.constraint_weight.at(k)*(CS.target_positions[k][i] - point_base[i]);
905 for (unsigned int j = 0; j < model.qdot_size; j++) {
906 CS.J(row, j) = CS.constraint_weight.at(k)*CS.G (i + 3,j);
907 }
908 }
909 }
911 for (unsigned int i = 0; i < 2; i++){
912 unsigned int row = CS.constraint_row_index[k] + i;
913 CS.e[row] = CS.constraint_weight.at(k)*(CS.target_positions[k][i] - point_base[i]);
914 for (unsigned int j = 0; j < model.qdot_size; j++) {
915 CS.J(row, j) = CS.constraint_weight.at(k)*CS.G (i + 3,j);
916 }
917 }
918 }
920
921 unsigned int row = CS.constraint_row_index[k];
922 CS.e[row] = CS.constraint_weight.at(k)*(CS.target_positions[k][2] - point_base[2]);
923 for (unsigned int j = 0; j < model.qdot_size; j++) {
924 CS.J(row, j) = CS.constraint_weight.at(k)*CS.G (2 + 3,j);
925 }
926
927 }
929 Utils::CalcCenterOfMass (model, Qres, Qres, NULL, mass, point_base, NULL, NULL, NULL, NULL, false);
930 CalcPointJacobian6D (model, Qres, CS.body_ids[k], point_base, CS.G, false);
931
932 for (unsigned int i = 0; i < 2; i++){
933 unsigned int row = CS.constraint_row_index[k] + i;
934 CS.e[row] = CS.constraint_weight.at(k)*(CS.target_positions[k][i] - point_base[i]);
935 for (unsigned int j = 0; j < model.qdot_size; j++) {
936 CS.J(row, j) = CS.constraint_weight.at(k)*CS.G (i + 3,j);
937 }
938 }
939 }
940 else {
941 assert (false && !"Invalid inverse kinematics constraint");
942 }
943 }
944
945 LOG << "J = " << CS.J << std::endl;
946 LOG << "e = " << CS.e.transpose() << std::endl;
947 CS.error_norm = CS.e.norm();
948
949 // abort if we are getting "close"
950 if (CS.error_norm < CS.step_tol) {
951 LOG << "Reached target close enough after " << CS.num_steps << " steps" << std::endl;
952 return true;
953 }
954
955 // // "task space" from puppeteer
956 // MatrixNd Ek = MatrixNd::Zero (CS.e.size(), CS.e.size());
957 //
958 // for (size_t ei = 0; ei < CS.e.size(); ei ++) {
959 // // Ek(ei,ei) = CS.error_norm * CS.error_norm * 0.5 + CS.lambda;
960 // Ek(ei,ei) = CS.e[ei]*CS.e[ei] * 0.5 + CS.lambda;
961 // }
962 //
963 // MatrixNd JJT_Ek_wnI = CS.J * CS.J.transpose() + Ek;
964 //
965 // VectorNd delta_theta = CS.J.transpose() * JJT_Ek_wnI.colPivHouseholderQr().solve (CS.e);
966 //
967 // LOG << "change = " << delta_theta << std::endl;
968
969
970 // "joint space" from puppeteer
971
972 double Ek = 0.;
973
974 for (size_t ei = 0; ei < CS.e.size(); ei ++) {
975 Ek += CS.e[ei] * CS.e[ei] * 0.5;
976 }
977
978 VectorNd ek = CS.J.transpose() * CS.e;
979 MatrixNd Wn = MatrixNd::Zero (Qres.size(), Qres.size());
980
981 assert (ek.size() == Qres.size());
982
983 for (size_t wi = 0; wi < Qres.size(); wi++) {
984 Wn(wi, wi) = ek[wi] * ek[wi] * 0.5 + CS.lambda;
985 // Wn(wi, wi) = Ek + 1.0e-3;
986 }
987
988 MatrixNd A = CS.J.transpose() * CS.J + Wn;
989 VectorNd delta_theta = A.colPivHouseholderQr().solve(CS.J.transpose() * CS.e);
990
991 Qres = Qres + delta_theta;
992 CS.delta_q_norm = delta_theta.norm();
993 if (CS.delta_q_norm < CS.step_tol) {
994 LOG << "reached convergence after " << CS.num_steps << " steps" << std::endl;
995 return true;
996 }
997 }
998
999 return false;
1000}
1001#endif
1002}
MX_Xd_dynamic transpose() const
unsigned int rows() const
Definition: MX_Xd_dynamic.h:95
unsigned int cols() const
Definition: MX_Xd_dynamic.h:99
MX_Xd_dynamic squaredNorm() const
MX_Xd_dynamic norm() const
unsigned int size() const
static MX_Xd_dynamic Identity(unsigned int size, unsigned int ignoredSize=0)
Definition: MX_Xd_dynamic.h:68
static MX_Xd_dynamic Zero(unsigned int nrows, unsigned int ncols=1)
Definition: MX_Xd_dynamic.h:52
MX_Xd_SubMatrix block(unsigned int row_start, unsigned int col_start)
RBDL_DLLAPI Matrix3d CalcBodyWorldOrientation(Model &model, const VectorNd &Q, const unsigned int body_id, bool update_kinematics)
Returns the orientation of a given body as 3x3 matrix.
Definition: Kinematics.cc:222
RBDL_DLLAPI void UpdateKinematics(Model &model, const VectorNd &Q, const VectorNd &QDot, const VectorNd &QDDot)
Updates and computes velocities and accelerations of the bodies.
Definition: Kinematics.cc:25
RBDL_DLLAPI Vector3d CalcAngularVelocityfromMatrix(const Matrix3d &RotMat)
Definition: Kinematics.cc:699
RBDL_DLLAPI void CalcBodySpatialJacobian(Model &model, const VectorNd &Q, unsigned int body_id, MatrixNd &G, bool update_kinematics)
Computes the spatial jacobian for a body.
Definition: Kinematics.cc:370
RBDL_DLLAPI void CalcPointJacobian6D(Model &model, const VectorNd &Q, unsigned int body_id, const Vector3d &point_position, MatrixNd &G, bool update_kinematics)
Computes a 6-D Jacobian for a point on a body.
Definition: Kinematics.cc:308
RBDL_DLLAPI Vector3d CalcBodyToBaseCoordinates(Model &model, const VectorNd &Q, unsigned int body_id, const Vector3d &point_body_coordinates, bool update_kinematics)
Returns the base coordinates of a point given in body coordinates.
Definition: Kinematics.cc:157
RBDL_DLLAPI SpatialVector CalcPointAcceleration6D(Model &model, const VectorNd &Q, const VectorNd &QDot, const VectorNd &QDDot, unsigned int body_id, const Vector3d &point_position, bool update_kinematics)
Computes linear and angular acceleration of a point on a body.
Definition: Kinematics.cc:562
RBDL_DLLAPI void UpdateKinematicsCustom(Model &model, const VectorNd *Q, const VectorNd *QDot, const VectorNd *QDDot)
Selectively updates model internal states of body positions, velocities and/or accelerations.
Definition: Kinematics.cc:78
RBDL_DLLAPI void CalcPointJacobian(Model &model, const VectorNd &Q, unsigned int body_id, const Vector3d &point_position, MatrixNd &G, bool update_kinematics)
Computes the point jacobian for a point on a body.
Definition: Kinematics.cc:244
RBDL_DLLAPI Vector3d CalcBaseToBodyCoordinates(Model &model, const VectorNd &Q, unsigned int body_id, const Vector3d &point_base_coordinates, bool update_kinematics)
Returns the body coordinates of a point given in base coordinates.
Definition: Kinematics.cc:190
RBDL_DLLAPI Vector3d CalcPointVelocity(Model &model, const VectorNd &Q, const VectorNd &QDot, unsigned int body_id, const Vector3d &point_position, bool update_kinematics)
Computes the velocity of a point on a body.
Definition: Kinematics.cc:434
RBDL_DLLAPI bool InverseKinematics(Model &model, const VectorNd &Qinit, const std::vector< unsigned int > &body_id, const std::vector< Vector3d > &body_point, const std::vector< Vector3d > &target_pos, VectorNd &Qres, double step_tol, double lambda, unsigned int max_iter)
Computes the inverse kinematics iteratively using a damped Levenberg-Marquardt method (also known as ...
Definition: Kinematics.cc:605
RBDL_DLLAPI Math::SpatialVector CalcPointVelocity6D(Model &model, const Math::VectorNd &Q, const Math::VectorNd &QDot, unsigned int body_id, const Math::Vector3d &point_position, bool update_kinematics)
Computes angular and linear velocity of a point that is fixed on a body.
Definition: Kinematics.cc:478
RBDL_DLLAPI Vector3d CalcPointAcceleration(Model &model, const VectorNd &Q, const VectorNd &QDot, const VectorNd &QDDot, unsigned int body_id, const Vector3d &point_position, bool update_kinematics)
Computes the linear acceleration of a point on a body.
Definition: Kinematics.cc:515
SpatialMatrix crossm(const SpatialVector &v)
RBDL_DLLAPI bool LinSolveGaussElimPivot(MatrixNd A, VectorNd b, VectorNd &x)
Solves a linear system using gaussian elimination with pivoting.
RBDL_DLLAPI Vector3d Vector3dZero
RBDL_DLLAPI void CalcCenterOfMass(Model &model, const Math::VectorNd &q, const Math::VectorNd &qdot, const Math::VectorNd *qddot, Scalar &mass, Math::Vector3d &com, Math::Vector3d *com_velocity, Math::Vector3d *com_acceleration, Math::Vector3d *angular_momentum, Math::Vector3d *change_of_angular_momentum, bool update_kinematics)
Computes the Center of Mass (COM) and optionally its linear velocity.
Definition: rbdl_utils.cc:190
RBDL_DLLAPI void jcalc(Model &model, unsigned int joint_id, const VectorNd &q, const VectorNd &qdot)
Definition: Joint.cc:49
MX_Xd_scalar atan2(const MX_Xd_scalar &x, const MX_Xd_scalar &y)
Definition: MX_Xd_utils.h:360
unsigned int AddOrientationConstraint(unsigned int body_id, const Math::Matrix3d &target_orientation, float weight=1.)
Definition: Kinematics.cc:801
std::vector< Math::Vector3d > target_positions
Definition: Kinematics.h:391
Math::MatrixNd G
the Jacobian of all constraints
Definition: Kinematics.h:375
unsigned int num_constraints
Vector with all the constraint residuals.
Definition: Kinematics.h:378
std::vector< Math::Vector3d > body_points
Definition: Kinematics.h:390
unsigned int AddPointConstraintCoMXY(unsigned int body_id, const Math::Vector3d &target_pos, float weight=1.)
Definition: Kinematics.cc:782
unsigned int num_steps
Damping factor, the default value of 1.0e-6 is reasonable for most problems.
Definition: Kinematics.h:380
unsigned int AddPointConstraint(unsigned int body_id, const Math::Vector3d &body_point, const Math::Vector3d &target_pos, float weight=1.)
Definition: Kinematics.cc:729
std::vector< unsigned int > constraint_row_index
Definition: Kinematics.h:393
unsigned int AddPointConstraintZ(unsigned int body_id, const Math::Vector3d &body_point, const Math::Vector3d &target_pos, float weight=1.)
Definition: Kinematics.cc:765
std::vector< Math::Matrix3d > target_orientations
Definition: Kinematics.h:392
unsigned int AddPointConstraintXY(unsigned int body_id, const Math::Vector3d &body_point, const Math::Vector3d &target_pos, float weight=1.)
Definition: Kinematics.cc:747
Math::VectorNd e
temporary storage of a single body Jacobian
Definition: Kinematics.h:376
unsigned int AddFullConstraint(unsigned int body_id, const Math::Vector3d &body_point, const Math::Vector3d &target_pos, const Math::Matrix3d &target_orientation, float weight=1.)
Definition: Kinematics.cc:818
std::vector< ConstraintType > constraint_type
Definition: Kinematics.h:388
Compact representation of spatial transformations.
SpatialVector apply(const SpatialVector &v_sp)