Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
vpViper.cpp
1/*
2 * ViSP, open source Visual Servoing Platform software.
3 * Copyright (C) 2005 - 2025 by Inria. All rights reserved.
4 *
5 * This software is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 * See the file LICENSE.txt at the root directory of this source
10 * distribution for additional information about the GNU GPL.
11 *
12 * For using ViSP with software that can not be combined with the GNU
13 * GPL, please contact Inria about acquiring a ViSP Professional
14 * Edition License.
15 *
16 * See https://visp.inria.fr for more information.
17 *
18 * This software was developed at:
19 * Inria Rennes - Bretagne Atlantique
20 * Campus Universitaire de Beaulieu
21 * 35042 Rennes Cedex
22 * France
23 *
24 * If you have questions regarding the use of this file, please contact
25 * Inria at visp@inria.fr
26 *
27 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29 *
30 * Description:
31 * Interface for a generic ADEPT Viper (either 650 or 850) robot.
32 */
33
39
40#include <cmath> // std::fabs
41#include <limits> // numeric_limits
42#include <visp3/core/vpCameraParameters.h>
43#include <visp3/core/vpDebug.h>
44#include <visp3/core/vpRotationMatrix.h>
45#include <visp3/core/vpRxyzVector.h>
46#include <visp3/core/vpTranslationVector.h>
47#include <visp3/core/vpVelocityTwistMatrix.h>
48#include <visp3/robot/vpRobotException.h>
49#include <visp3/robot/vpViper.h>
50
52const unsigned int vpViper::njoint = 6;
53
58 : eMc(), etc(), erc(), a1(0), d1(0), a2(), a3(), d4(0), d6(0), d7(0), c56(0), joint_max(), joint_min()
59{
60 // Default values are initialized
61
62 // Denavit-Hartenberg parameters
63 a1 = 0.075;
64 a2 = 0.365;
65 a3 = 0.090;
66 d1 = 0.335;
67 d4 = 0.405;
68 d6 = 0.080;
69 d7 = 0.0666;
70 c56 = -341.33 / 9102.22;
71
72 // Software joint limits in radians
73 joint_min.resize(njoint);
74 joint_min[0] = vpMath::rad(-170);
75 joint_min[1] = vpMath::rad(-190);
76 joint_min[2] = vpMath::rad(-29);
77 joint_min[3] = vpMath::rad(-190);
78 joint_min[4] = vpMath::rad(-120);
79 joint_min[5] = vpMath::rad(-360);
80 joint_max.resize(njoint);
81 joint_max[0] = vpMath::rad(170);
82 joint_max[1] = vpMath::rad(45);
83 joint_max[2] = vpMath::rad(256);
84 joint_max[3] = vpMath::rad(190);
85 joint_max[4] = vpMath::rad(120);
86 joint_max[5] = vpMath::rad(360);
87
88 // End effector to camera transformation
89 eMc.eye();
90}
91
96{
97 *this = viper;
98}
99
104{
105 eMc = viper.eMc;
106 etc = viper.etc;
107 erc = viper.erc;
108 a1 = viper.a1;
109 d1 = viper.d1;
110 a2 = viper.a2;
111 a3 = viper.a3;
112 d4 = viper.d4;
113 d6 = viper.d6;
114 d7 = viper.d7;
115 c56 = viper.c56;
116 joint_max = viper.joint_max;
117 joint_min = viper.joint_min;
118 return *this;
119}
120
141{
143 fMc = get_fMc(q);
144
145 return fMc;
146}
147
162bool vpViper::convertJointPositionInLimits(unsigned int joint, const double &q, double &q_mod,
163 const bool &verbose) const
164{
165 double eps = 0.01;
166 if (q >= joint_min[joint] - eps && q <= joint_max[joint] + eps) {
167 q_mod = q;
168 return true;
169 }
170
171 q_mod = q + 2 * M_PI;
172 if (q_mod >= joint_min[joint] - eps && q_mod <= joint_max[joint] + eps) {
173 return true;
174 }
175
176 q_mod = q - 2 * M_PI;
177 if (q_mod >= joint_min[joint] - eps && q_mod <= joint_max[joint] + eps) {
178 return true;
179 }
180
181 if (verbose) {
182 std::cout << "Joint " << joint << " not in limits: " << this->joint_min[joint] << " < " << q << " < "
183 << this->joint_max[joint] << std::endl;
184 }
185
186 return false;
187}
188
242 const bool &verbose) const
243{
244 vpColVector q_sol[8];
245
246 for (unsigned int i = 0; i < 8; i++)
247 q_sol[i].resize(6);
248
249 double c1[8] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
250 double s1[8] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
251 double c3[8] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
252 double s3[8] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
253 double c23[8] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
254 double s23[8] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
255 double c4[8] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
256 double s4[8] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
257 double c5[8] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
258 double s5[8] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
259 double c6[8] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
260 double s6[8] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
261
262 bool ok[8];
263
264 if (q.getRows() != njoint)
265 q.resize(6);
266
267 for (unsigned int i = 0; i < 8; i++)
268 ok[i] = true;
269
270 double px = fMw[0][3]; // a*c1
271 double py = fMw[1][3]; // a*s1
272 double pz = fMw[2][3];
273
274 // Compute q1
275 double a_2 = px * px + py * py;
276 // if (a_2 == 0) {// singularity
277 if (std::fabs(a_2) <= std::numeric_limits<double>::epsilon()) { // singularity
278 c1[0] = cos(q[0]);
279 s1[0] = sin(q[0]);
280 c1[4] = cos(q[0] + M_PI);
281 s1[4] = sin(q[0] + M_PI);
282 }
283 else {
284 double a = sqrt(a_2);
285 c1[0] = px / a;
286 s1[0] = py / a;
287 c1[4] = -px / a;
288 s1[4] = -py / a;
289 }
290
291 double q1_mod;
292 for (unsigned int i = 0; i < 8; i += 4) {
293 q_sol[i][0] = atan2(s1[i], c1[i]);
294 if (convertJointPositionInLimits(0, q_sol[i][0], q1_mod, verbose) == true) {
295 q_sol[i][0] = q1_mod;
296 for (unsigned int j = 1; j < 4; j++) {
297 c1[i + j] = c1[i];
298 s1[i + j] = s1[i];
299 q_sol[i + j][0] = q_sol[i][0];
300 }
301 }
302 else {
303 for (unsigned int j = 1; j < 4; j++)
304 ok[i + j] = false;
305 }
306 }
307
308 // Compute q3
309 double K, q3_mod;
310 for (unsigned int i = 0; i < 8; i += 4) {
311 if (ok[i] == true) {
312 K = (px * px + py * py + pz * pz + a1 * a1 - a2 * a2 - a3 * a3 + d1 * d1 - d4 * d4 -
313 2 * (a1 * c1[i] * px + a1 * s1[i] * py + d1 * pz)) /
314 (2 * a2);
315 double d4_a3_K = d4 * d4 + a3 * a3 - K * K;
316
317 q_sol[i][2] = atan2(a3, d4) + atan2(K, sqrt(d4_a3_K));
318 q_sol[i + 2][2] = atan2(a3, d4) + atan2(K, -sqrt(d4_a3_K));
319
320 for (unsigned int j = 0; j < 4; j += 2) {
321 if (d4_a3_K < 0) {
322 for (unsigned int k = 0; k < 2; k++)
323 ok[i + j + k] = false;
324 }
325 else {
326 if (convertJointPositionInLimits(2, q_sol[i + j][2], q3_mod, verbose) == true) {
327 for (unsigned int k = 0; k < 2; k++) {
328 q_sol[i + j + k][2] = q3_mod;
329 c3[i + j + k] = cos(q3_mod);
330 s3[i + j + k] = sin(q3_mod);
331 }
332 }
333 else {
334 for (unsigned int k = 0; k < 2; k++)
335 ok[i + j + k] = false;
336 }
337 }
338 }
339 }
340 }
341 // std::cout << "ok apres q3: ";
342 // for (unsigned int i=0; i< 8; i++)
343 // std::cout << ok[i] << " ";
344 // std::cout << std::endl;
345
346 // Compute q2
347 double q23[8], q2_mod;
348 for (unsigned int i = 0; i < 8; i += 2) {
349 if (ok[i] == true) {
350 // Compute q23 = q2+q3
351 c23[i] = (-(a3 - a2 * c3[i]) * (c1[i] * px + s1[i] * py - a1) - (d1 - pz) * (d4 + a2 * s3[i])) /
352 ((c1[i] * px + s1[i] * py - a1) * (c1[i] * px + s1[i] * py - a1) + (d1 - pz) * (d1 - pz));
353 s23[i] = ((d4 + a2 * s3[i]) * (c1[i] * px + s1[i] * py - a1) - (d1 - pz) * (a3 - a2 * c3[i])) /
354 ((c1[i] * px + s1[i] * py - a1) * (c1[i] * px + s1[i] * py - a1) + (d1 - pz) * (d1 - pz));
355 q23[i] = atan2(s23[i], c23[i]);
356 // std::cout << i << " c23 = " << c23[i] << " s23 = " << s23[i] <<
357 // std::endl;
358 // q2 = q23 - q3
359 q_sol[i][1] = q23[i] - q_sol[i][2];
360
361 if (convertJointPositionInLimits(1, q_sol[i][1], q2_mod, verbose) == true) {
362 for (unsigned int j = 0; j < 2; j++) {
363 q_sol[i + j][1] = q2_mod;
364 c23[i + j] = c23[i];
365 s23[i + j] = s23[i];
366 }
367 }
368 else {
369 for (unsigned int j = 0; j < 2; j++)
370 ok[i + j] = false;
371 }
372 }
373 }
374 // std::cout << "ok apres q2: ";
375 // for (unsigned int i=0; i< 8; i++)
376 // std::cout << ok[i] << " ";
377 // std::cout << std::endl;
378
379 // Compute q4 as long as s5 != 0
380 double r13 = fMw[0][2];
381 double r23 = fMw[1][2];
382 double r33 = fMw[2][2];
383 double s4s5, c4s5, q4_mod, q5_mod;
384 for (unsigned int i = 0; i < 8; i += 2) {
385 if (ok[i] == true) {
386 s4s5 = -s1[i] * r13 + c1[i] * r23;
387 c4s5 = c1[i] * c23[i] * r13 + s1[i] * c23[i] * r23 - s23[i] * r33;
388 if (fabs(s4s5) < vpMath::rad(0.5) && fabs(c4s5) < vpMath::rad(0.5)) {
389 // s5 = 0
390 c5[i] = c1[i] * s23[i] * r13 + s1[i] * s23[i] * r23 + c23[i] * r33;
391 // std::cout << "Singularity: s5 near 0: ";
392 if (c5[i] > 0.)
393 q_sol[i][4] = 0.0;
394 else
395 q_sol[i][4] = M_PI;
396
397 if (convertJointPositionInLimits(4, q_sol[i][4], q5_mod, verbose) == true) {
398 for (unsigned int j = 0; j < 2; j++) {
399 q_sol[i + j][3] = q[3]; // keep current q4
400 q_sol[i + j][4] = q5_mod;
401 c4[i] = cos(q_sol[i + j][3]);
402 s4[i] = sin(q_sol[i + j][3]);
403 }
404 }
405 else {
406 for (unsigned int j = 0; j < 2; j++)
407 ok[i + j] = false;
408 }
409 }
410 else {
411// s5 != 0
412#if 0 // Modified 2016/03/10 since if and else are the same
413 // if (c4s5 == 0) {
414 if (std::fabs(c4s5) <= std::numeric_limits<double>::epsilon()) {
415 // c4 = 0
416 // vpTRACE("c4 = 0");
417 // q_sol[i][3] = q[3]; // keep current position
418 q_sol[i][3] = atan2(s4s5, c4s5);
419 }
420 else {
421 q_sol[i][3] = atan2(s4s5, c4s5);
422 }
423#else
424 q_sol[i][3] = atan2(s4s5, c4s5);
425#endif
426 if (convertJointPositionInLimits(3, q_sol[i][3], q4_mod, verbose) == true) {
427 q_sol[i][3] = q4_mod;
428 c4[i] = cos(q4_mod);
429 s4[i] = sin(q4_mod);
430 }
431 else {
432 ok[i] = false;
433 }
434 if (q_sol[i][3] > 0.)
435 q_sol[i + 1][3] = q_sol[i][3] + M_PI;
436 else
437 q_sol[i + 1][3] = q_sol[i][3] - M_PI;
438 if (convertJointPositionInLimits(3, q_sol[i + 1][3], q4_mod, verbose) == true) {
439 q_sol[i + 1][3] = q4_mod;
440 c4[i + 1] = cos(q4_mod);
441 s4[i + 1] = sin(q4_mod);
442 }
443 else {
444 ok[i + 1] = false;
445 }
446
447 // Compute q5
448 for (unsigned int j = 0; j < 2; j++) {
449 if (ok[i + j] == true) {
450 c5[i + j] = c1[i + j] * s23[i + j] * r13 + s1[i + j] * s23[i + j] * r23 + c23[i + j] * r33;
451 s5[i + j] = (c1[i + j] * c23[i + j] * c4[i + j] - s1[i + j] * s4[i + j]) * r13 +
452 (s1[i + j] * c23[i + j] * c4[i + j] + c1[i + j] * s4[i + j]) * r23 -
453 s23[i + j] * c4[i + j] * r33;
454
455 q_sol[i + j][4] = atan2(s5[i + j], c5[i + j]);
456 if (convertJointPositionInLimits(4, q_sol[i + j][4], q5_mod, verbose) == true) {
457 q_sol[i + j][4] = q5_mod;
458 }
459 else {
460
461 ok[i + j] = false;
462 }
463 }
464 }
465 }
466 }
467 }
468
469 // Compute q6
470 // 4 solutions for q6 and 4 more solutions by flipping the wrist (see below)
471 double r12 = fMw[0][1];
472 double r22 = fMw[1][1];
473 double r32 = fMw[2][1];
474 double q6_mod;
475 for (unsigned int i = 0; i < 8; i++) {
476 c6[i] = -(c1[i] * c23[i] * s4[i] + s1[i] * c4[i]) * r12 + (c1[i] * c4[i] - s1[i] * c23[i] * s4[i]) * r22 +
477 s23[i] * s4[i] * r32;
478 s6[i] = -(c1[i] * c23[i] * c4[i] * c5[i] - c1[i] * s23[i] * s5[i] - s1[i] * s4[i] * c5[i]) * r12 -
479 (s1[i] * c23[i] * c4[i] * c5[i] - s1[i] * s23[i] * s5[i] + c1[i] * s4[i] * c5[i]) * r22 +
480 (c23[i] * s5[i] + s23[i] * c4[i] * c5[i]) * r32;
481
482 q_sol[i][5] = atan2(s6[i], c6[i]);
483 if (convertJointPositionInLimits(5, q_sol[i][5], q6_mod, verbose) == true) {
484 q_sol[i][5] = q6_mod;
485 }
486 else {
487 ok[i] = false;
488 }
489 }
490
491 // Select the best config in terms of distance from the current position
492 unsigned int nbsol = 0;
493 unsigned int sol = 0;
494 vpColVector dist(8);
495 for (unsigned int i = 0; i < 8; i++) {
496 if (ok[i] == true) {
497 nbsol++;
498 sol = i;
499 vpColVector weight(6);
500 weight = 1;
501 weight[0] = 8;
502 weight[1] = weight[2] = 4;
503 dist[i] = 0;
504 for (unsigned int j = 0; j < 6; j++) {
505 double rought_dist = q[j] - q_sol[i][j];
506 double modulo_dist = rought_dist;
507 if (rought_dist > 0) {
508 if (fabs(rought_dist - 2 * M_PI) < fabs(rought_dist))
509 modulo_dist = rought_dist - 2 * M_PI;
510 }
511 else {
512 if (fabs(rought_dist + 2 * M_PI) < fabs(rought_dist))
513 modulo_dist = rought_dist + 2 * M_PI;
514 }
515
516 dist[i] += weight[j] * vpMath::sqr(modulo_dist);
517 }
518 }
519
520 }
521 // std::cout << "dist: " << dist.t() << std::endl;
522 if (nbsol) {
523 for (unsigned int i = 0; i < 8; i++) {
524 if (ok[i] == true)
525 if (dist[i] < dist[sol])
526 sol = i;
527 }
528 // Update the inverse kinematics solution
529 q = q_sol[sol];
530
531 }
532 return nbsol;
533}
534
589unsigned int vpViper::getInverseKinematics(const vpHomogeneousMatrix &fMc, vpColVector &q, const bool &verbose) const
590{
594 this->get_wMe(wMe);
595 this->get_eMc(eMc_);
596 fMw = fMc * eMc_.inverse() * wMe.inverse();
597
598 return (getInverseKinematicsWrist(fMw, q, verbose));
599}
600
627{
629 get_fMc(q, fMc);
630
631 return fMc;
632}
633
656{
657
658 // Compute the direct geometric model: fMe = transformation between
659 // fix and end effector frame.
661
662 get_fMe(q, fMe);
663
664 fMc = fMe * this->eMc;
665
666 return;
667}
668
746{
747 double q1 = q[0];
748 double q2 = q[1];
749 double q3 = q[2];
750 double q4 = q[3];
751 double q5 = q[4];
752 double q6 = q[5];
753 // We turn off the coupling since the measured positions are joint position
754 // taking into account the coupling factor. The coupling factor is relevant
755 // if positions are motor position.
756 // double q6 = q[5] + c56 * q[4];
757
758 double c1 = cos(q1);
759 double s1 = sin(q1);
760 double c2 = cos(q2);
761 double s2 = sin(q2);
762 // double c3 = cos(q3);
763 // double s3 = sin(q3);
764 double c4 = cos(q4);
765 double s4 = sin(q4);
766 double c5 = cos(q5);
767 double s5 = sin(q5);
768 double c6 = cos(q6);
769 double s6 = sin(q6);
770 double c23 = cos(q2 + q3);
771 double s23 = sin(q2 + q3);
772
773 fMe[0][0] = c1 * (c23 * (c4 * c5 * c6 - s4 * s6) - s23 * s5 * c6) - s1 * (s4 * c5 * c6 + c4 * s6);
774 fMe[1][0] = -s1 * (c23 * (-c4 * c5 * c6 + s4 * s6) + s23 * s5 * c6) + c1 * (s4 * c5 * c6 + c4 * s6);
775 fMe[2][0] = s23 * (s4 * s6 - c4 * c5 * c6) - c23 * s5 * c6;
776
777 fMe[0][1] = -c1 * (c23 * (c4 * c5 * s6 + s4 * c6) - s23 * s5 * s6) + s1 * (s4 * c5 * s6 - c4 * c6);
778 fMe[1][1] = -s1 * (c23 * (c4 * c5 * s6 + s4 * c6) - s23 * s5 * s6) - c1 * (s4 * c5 * s6 - c4 * c6);
779 fMe[2][1] = s23 * (c4 * c5 * s6 + s4 * c6) + c23 * s5 * s6;
780
781 fMe[0][2] = c1 * (c23 * c4 * s5 + s23 * c5) - s1 * s4 * s5;
782 fMe[1][2] = s1 * (c23 * c4 * s5 + s23 * c5) + c1 * s4 * s5;
783 fMe[2][2] = -s23 * c4 * s5 + c23 * c5;
784
785 fMe[0][3] = c1 * (c23 * (c4 * s5 * d6 - a3) + s23 * (c5 * d6 + d4) + a1 + a2 * c2) - s1 * s4 * s5 * d6;
786 fMe[1][3] = s1 * (c23 * (c4 * s5 * d6 - a3) + s23 * (c5 * d6 + d4) + a1 + a2 * c2) + c1 * s4 * s5 * d6;
787 fMe[2][3] = s23 * (a3 - c4 * s5 * d6) + c23 * (c5 * d6 + d4) - a2 * s2 + d1;
788
789 // std::cout << "Effector position fMe: " << std::endl << fMe;
790
791 return;
792}
793
836{
837 double q1 = q[0];
838 double q2 = q[1];
839 double q3 = q[2];
840 double q4 = q[3];
841 double q5 = q[4];
842 double q6 = q[5];
843 // We turn off the coupling since the measured positions are joint position
844 // taking into account the coupling factor. The coupling factor is relevant
845 // if positions are motor position.
846 // double q6 = q[5] + c56 * q[4];
847
848 double c1 = cos(q1);
849 double s1 = sin(q1);
850 double c2 = cos(q2);
851 double s2 = sin(q2);
852 // double c3 = cos(q3);
853 // double s3 = sin(q3);
854 double c4 = cos(q4);
855 double s4 = sin(q4);
856 double c5 = cos(q5);
857 double s5 = sin(q5);
858 double c6 = cos(q6);
859 double s6 = sin(q6);
860 double c23 = cos(q2 + q3);
861 double s23 = sin(q2 + q3);
862
863 fMw[0][0] = c1 * (c23 * (c4 * c5 * c6 - s4 * s6) - s23 * s5 * c6) - s1 * (s4 * c5 * c6 + c4 * s6);
864 fMw[1][0] = -s1 * (c23 * (-c4 * c5 * c6 + s4 * s6) + s23 * s5 * c6) + c1 * (s4 * c5 * c6 + c4 * s6);
865 fMw[2][0] = s23 * (s4 * s6 - c4 * c5 * c6) - c23 * s5 * c6;
866
867 fMw[0][1] = -c1 * (c23 * (c4 * c5 * s6 + s4 * c6) - s23 * s5 * s6) + s1 * (s4 * c5 * s6 - c4 * c6);
868 fMw[1][1] = -s1 * (c23 * (c4 * c5 * s6 + s4 * c6) - s23 * s5 * s6) - c1 * (s4 * c5 * s6 - c4 * c6);
869 fMw[2][1] = s23 * (c4 * c5 * s6 + s4 * c6) + c23 * s5 * s6;
870
871 fMw[0][2] = c1 * (c23 * c4 * s5 + s23 * c5) - s1 * s4 * s5;
872 fMw[1][2] = s1 * (c23 * c4 * s5 + s23 * c5) + c1 * s4 * s5;
873 fMw[2][2] = -s23 * c4 * s5 + c23 * c5;
874
875 fMw[0][3] = c1 * (-c23 * a3 + s23 * d4 + a1 + a2 * c2);
876 fMw[1][3] = s1 * (-c23 * a3 + s23 * d4 + a1 + a2 * c2);
877 fMw[2][3] = s23 * a3 + c23 * d4 - a2 * s2 + d1;
878
879 // std::cout << "Wrist position fMw: " << std::endl << fMw;
880
881 return;
882}
883
895{
896 // Set the rotation as identity
897 wMe.eye();
898
899 // Set the translation
900 wMe[2][3] = d6;
901}
902
914void vpViper::get_eMc(vpHomogeneousMatrix &eMc_) const { eMc_ = this->eMc; }
915
926{
927 eMs.eye();
928 eMs[2][3] = -d7; // tz = -d7
929}
930
942void vpViper::get_cMe(vpHomogeneousMatrix &cMe) const { cMe = this->eMc.inverse(); }
943
959{
961 get_cMe(cMe);
962
963 cVe.buildFrom(cMe);
964
965 return;
966}
967
990void vpViper::get_eJe(const vpColVector &q, vpMatrix &eJe) const
991{
992 vpMatrix V(6, 6);
993 V = 0;
994 // Compute the first and last block of V
996 get_fMw(q, fMw);
998 fMw.extract(fRw);
1000 wRf = fRw.inverse();
1001 for (unsigned int i = 0; i < 3; i++) {
1002 for (unsigned int j = 0; j < 3; j++) {
1003 V[i][j] = V[i + 3][j + 3] = wRf[i][j];
1004 }
1005 }
1006 // Compute the second block of V
1008 get_wMe(wMe);
1010 eMw = wMe.inverse();
1012 eMw.extract(etw);
1013 vpMatrix block2 = etw.skew() * wRf;
1014 for (unsigned int i = 0; i < 3; i++) {
1015 for (unsigned int j = 0; j < 3; j++) {
1016 V[i][j + 3] = block2[i][j];
1017 }
1018 }
1019 // Compute eJe
1020 vpMatrix fJw;
1021 get_fJw(q, fJw);
1022 eJe = V * fJw;
1023
1024 return;
1025}
1026
1073
1074void vpViper::get_fJw(const vpColVector &q, vpMatrix &fJw) const
1075{
1076 double q1 = q[0];
1077 double q2 = q[1];
1078 double q3 = q[2];
1079 double q4 = q[3];
1080 double q5 = q[4];
1081
1082 double c1 = cos(q1);
1083 double s1 = sin(q1);
1084 double c2 = cos(q2);
1085 double s2 = sin(q2);
1086 double c3 = cos(q3);
1087 double s3 = sin(q3);
1088 double c4 = cos(q4);
1089 double s4 = sin(q4);
1090 double c5 = cos(q5);
1091 double s5 = sin(q5);
1092 double c23 = cos(q2 + q3);
1093 double s23 = sin(q2 + q3);
1094
1095 vpColVector J1(6);
1096 vpColVector J2(6);
1097 vpColVector J3(6);
1098 vpColVector J4(6);
1099 vpColVector J5(6);
1100 vpColVector J6(6);
1101
1102 // Jacobian when d6 is set to zero
1103 J1[0] = -s1 * (-c23 * a3 + s23 * d4 + a1 + a2 * c2);
1104 J1[1] = c1 * (-c23 * a3 + s23 * d4 + a1 + a2 * c2);
1105 J1[2] = 0;
1106 J1[3] = 0;
1107 J1[4] = 0;
1108 J1[5] = 1;
1109
1110 J2[0] = c1 * (s23 * a3 + c23 * d4 - a2 * s2);
1111 J2[1] = s1 * (s23 * a3 + c23 * d4 - a2 * s2);
1112 J2[2] = c23 * a3 - s23 * d4 - a2 * c2;
1113 J2[3] = -s1;
1114 J2[4] = c1;
1115 J2[5] = 0;
1116
1117 J3[0] = c1 * (a3 * (s2 * c3 + c2 * s3) + (-s2 * s3 + c2 * c3) * d4);
1118 J3[1] = s1 * (a3 * (s2 * c3 + c2 * s3) + (-s2 * s3 + c2 * c3) * d4);
1119 J3[2] = -a3 * (s2 * s3 - c2 * c3) - d4 * (s2 * c3 + c2 * s3);
1120 J3[3] = -s1;
1121 J3[4] = c1;
1122 J3[5] = 0;
1123
1124 J4[0] = 0;
1125 J4[1] = 0;
1126 J4[2] = 0;
1127 J4[3] = c1 * s23;
1128 J4[4] = s1 * s23;
1129 J4[5] = c23;
1130
1131 J5[0] = 0;
1132 J5[1] = 0;
1133 J5[2] = 0;
1134 J5[3] = -c23 * c1 * s4 - s1 * c4;
1135 J5[4] = c1 * c4 - c23 * s1 * s4;
1136 J5[5] = s23 * s4;
1137
1138 J6[0] = 0;
1139 J6[1] = 0;
1140 J6[2] = 0;
1141 J6[3] = (c1 * c23 * c4 - s1 * s4) * s5 + c1 * s23 * c5;
1142 J6[4] = (s1 * c23 * c4 + c1 * s4) * s5 + s1 * s23 * c5;
1143 J6[5] = -s23 * c4 * s5 + c23 * c5;
1144
1145 fJw.resize(6, 6);
1146 for (unsigned int i = 0; i < 6; i++) {
1147 fJw[i][0] = J1[i];
1148 fJw[i][1] = J2[i];
1149 fJw[i][2] = J3[i];
1150 fJw[i][3] = J4[i];
1151 fJw[i][4] = J5[i];
1152 fJw[i][5] = J6[i];
1153 }
1154 return;
1155}
1156
1179void vpViper::get_fJe(const vpColVector &q, vpMatrix &fJe) const
1180{
1181 vpMatrix V(6, 6);
1182 V = 0;
1183 // Set the first and last block to identity
1184 for (unsigned int i = 0; i < 6; i++)
1185 V[i][i] = 1;
1186
1187 // Compute the second block of V
1189 get_fMw(q, fMw);
1190 vpRotationMatrix fRw;
1191 fMw.extract(fRw);
1193 get_wMe(wMe);
1195 eMw = wMe.inverse();
1197 eMw.extract(etw);
1198 vpMatrix block2 = (fRw * etw).skew();
1199 // Set the second block
1200 for (unsigned int i = 0; i < 3; i++)
1201 for (unsigned int j = 0; j < 3; j++)
1202 V[i][j + 3] = block2[i][j];
1203
1204 // Compute fJe
1205 vpMatrix fJw;
1206 get_fJw(q, fJw);
1207 fJe = V * fJw;
1208
1209 return;
1210}
1211
1220
1229
1240double vpViper::getCoupl56() const { return c56; }
1241
1251{
1252 this->eMc = eMc_;
1253 this->eMc.extract(etc);
1254 vpRotationMatrix R(this->eMc);
1255 this->erc.buildFrom(R);
1256}
1257
1269{
1270 this->etc = etc_;
1271 this->erc = erc_;
1272 vpRotationMatrix eRc(erc);
1273 this->eMc.buildFrom(etc, eRc);
1274}
1275
1285VISP_EXPORT std::ostream &operator<<(std::ostream &os, const vpViper &viper)
1286{
1287 vpRotationMatrix eRc;
1288 viper.eMc.extract(eRc);
1289 vpRxyzVector rxyz(eRc);
1290
1291 // Convert joint limits in degrees
1292 vpColVector jmax = viper.joint_max;
1293 vpColVector jmin = viper.joint_min;
1294 jmax.rad2deg();
1295 jmin.rad2deg();
1296
1297 os << "Joint Max (deg):" << std::endl
1298 << "\t" << jmax.t() << std::endl
1299
1300 << "Joint Min (deg): " << std::endl
1301 << "\t" << jmin.t() << std::endl
1302
1303 << "Coupling 5-6:" << std::endl
1304 << "\t" << viper.c56 << std::endl
1305
1306 << "eMc: " << std::endl
1307 << "\tTranslation (m): " << viper.eMc[0][3] << " " << viper.eMc[1][3] << " " << viper.eMc[2][3] << "\t"
1308 << std::endl
1309 << "\tRotation Rxyz (rad) : " << rxyz[0] << " " << rxyz[1] << " " << rxyz[2] << "\t" << std::endl
1310 << "\tRotation Rxyz (deg) : " << vpMath::deg(rxyz[0]) << " " << vpMath::deg(rxyz[1]) << " " << vpMath::deg(rxyz[2])
1311 << "\t" << std::endl;
1312
1313 return os;
1314}
1315END_VISP_NAMESPACE
void resize(unsigned int nrows, unsigned int ncols, bool flagNullify=true, bool recopy_=true)
Definition vpArray2D.h:448
unsigned int getRows() const
Definition vpArray2D.h:433
Implementation of column vector and the associated operations.
vpColVector & rad2deg()
vpRowVector t() const
void resize(unsigned int i, bool flagNullify=true)
Implementation of an homogeneous matrix and operations on such kind of matrices.
vpHomogeneousMatrix inverse() const
void extract(vpRotationMatrix &R) const
static double rad(double deg)
Definition vpMath.h:129
static double sqr(double x)
Definition vpMath.h:203
static double deg(double rad)
Definition vpMath.h:119
Implementation of a matrix and operations on matrices.
Definition vpMatrix.h:175
Implementation of a rotation matrix and operations on such kind of matrices.
vpRotationMatrix inverse() const
Implementation of a rotation vector as Euler angle minimal representation.
Class that consider the case of a translation vector.
vpVelocityTwistMatrix & buildFrom(const vpTranslationVector &t, const vpRotationMatrix &R)
double getCoupl56() const
Definition vpViper.cpp:1240
void get_fJw(const vpColVector &q, vpMatrix &fJw) const
Definition vpViper.cpp:1074
virtual void set_eMc(const vpHomogeneousMatrix &eMc_)
Definition vpViper.cpp:1250
vpHomogeneousMatrix getForwardKinematics(const vpColVector &q) const
Definition vpViper.cpp:140
void get_fMw(const vpColVector &q, vpHomogeneousMatrix &fMw) const
Definition vpViper.cpp:835
vpTranslationVector etc
Definition vpViper.h:158
double d6
for joint 6
Definition vpViper.h:166
double a3
for joint 3
Definition vpViper.h:164
static const unsigned int njoint
Number of joint.
Definition vpViper.h:153
void get_cMe(vpHomogeneousMatrix &cMe) const
Definition vpViper.cpp:942
double d4
for joint 4
Definition vpViper.h:165
void get_fJe(const vpColVector &q, vpMatrix &fJe) const
Definition vpViper.cpp:1179
vpColVector joint_max
Definition vpViper.h:171
unsigned int getInverseKinematics(const vpHomogeneousMatrix &fMc, vpColVector &q, const bool &verbose=false) const
Definition vpViper.cpp:589
double c56
Mechanical coupling between joint 5 and joint 6.
Definition vpViper.h:168
vpColVector getJointMin() const
Definition vpViper.cpp:1219
void get_eMc(vpHomogeneousMatrix &eMc) const
Definition vpViper.cpp:914
vpHomogeneousMatrix eMc
End effector to camera transformation.
Definition vpViper.h:156
vpViper & operator=(const vpViper &viper)
Definition vpViper.cpp:103
double a1
Definition vpViper.h:162
vpRxyzVector erc
Definition vpViper.h:159
vpColVector getJointMax() const
Definition vpViper.cpp:1228
vpColVector joint_min
Definition vpViper.h:172
void get_eMs(vpHomogeneousMatrix &eMs) const
Definition vpViper.cpp:925
double a2
for joint 2
Definition vpViper.h:163
vpViper()
Definition vpViper.cpp:57
void get_wMe(vpHomogeneousMatrix &wMe) const
Definition vpViper.cpp:894
friend VISP_EXPORT std::ostream & operator<<(std::ostream &os, const vpViper &viper)
Definition vpViper.cpp:1285
unsigned int getInverseKinematicsWrist(const vpHomogeneousMatrix &fMw, vpColVector &q, const bool &verbose=false) const
Definition vpViper.cpp:241
void get_eJe(const vpColVector &q, vpMatrix &eJe) const
Definition vpViper.cpp:990
double d1
for joint 1
Definition vpViper.h:162
void get_fMe(const vpColVector &q, vpHomogeneousMatrix &fMe) const
Definition vpViper.cpp:745
void get_cVe(vpVelocityTwistMatrix &cVe) const
Definition vpViper.cpp:958
double d7
for force/torque location
Definition vpViper.h:167
vpHomogeneousMatrix get_fMc(const vpColVector &q) const
Definition vpViper.cpp:626