Visual Servoing Platform  version 3.0.0
vpAfma6.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2015 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * ("GPL") version 2 as published by the Free Software Foundation.
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 http://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 the Irisa's Afma6 robot.
32  *
33  * Authors:
34  * Fabien Spindler
35  *
36  *****************************************************************************/
37 
47 #include <visp3/core/vpDebug.h>
48 #include <visp3/core/vpVelocityTwistMatrix.h>
49 #include <visp3/robot/vpRobotException.h>
50 #include <visp3/core/vpXmlParserCamera.h>
51 #include <visp3/core/vpCameraParameters.h>
52 #include <visp3/core/vpRxyzVector.h>
53 #include <visp3/core/vpTranslationVector.h>
54 #include <visp3/core/vpRotationMatrix.h>
55 #include <visp3/robot/vpAfma6.h>
56 
57 /* ----------------------------------------------------------------------- */
58 /* --- STATIC ------------------------------------------------------------ */
59 /* ---------------------------------------------------------------------- */
60 
61 #ifdef VISP_HAVE_ACCESS_TO_NAS
62 static const char *opt_Afma6[] = {"JOINT_MAX","JOINT_MIN","LONG_56","COUPL_56",
63  "CAMERA", "eMc_ROT_XYZ","eMc_TRANS_XYZ",
64  NULL};
65 
66 const char * const vpAfma6::CONST_AFMA6_FILENAME
67 #if defined(_WIN32)
68 = "Z:/robot/Afma6/current/include/const_Afma6.cnf";
69 #else
70 = "/udd/fspindle/robot/Afma6/current/include/const_Afma6.cnf";
71 #endif
72 
74 #if defined(_WIN32)
75 = "Z:/robot/Afma6/current/include/const_eMc_ccmop_without_distortion_Afma6.cnf";
76 #else
77 = "/udd/fspindle/robot/Afma6/current/include/const_eMc_ccmop_without_distortion_Afma6.cnf";
78 #endif
79 
81 #if defined(_WIN32)
82 = "Z:/robot/Afma6/current/include/const_eMc_ccmop_with_distortion_Afma6.cnf";
83 #else
84 = "/udd/fspindle/robot/Afma6/current/include/const_eMc_ccmop_with_distortion_Afma6.cnf";
85 #endif
86 
88 #if defined(_WIN32)
89 = "Z:/robot/Afma6/current/include/const_eMc_gripper_without_distortion_Afma6.cnf";
90 #else
91 = "/udd/fspindle/robot/Afma6/current/include/const_eMc_gripper_without_distortion_Afma6.cnf";
92 #endif
93 
95 #if defined(_WIN32)
96 = "Z:/robot/Afma6/current/include/const_eMc_gripper_with_distortion_Afma6.cnf";
97 #else
98 = "/udd/fspindle/robot/Afma6/current/include/const_eMc_gripper_with_distortion_Afma6.cnf";
99 #endif
100 
102 #if defined(_WIN32)
103 = "Z:/robot/Afma6/current/include/const_eMc_vacuum_without_distortion_Afma6.cnf";
104 #else
105 = "/udd/fspindle/robot/Afma6/current/include/const_eMc_vacuum_without_distortion_Afma6.cnf";
106 #endif
107 
109 #if defined(_WIN32)
110 = "Z:/robot/Afma6/current/include/const_eMc_vacuum_with_distortion_Afma6.cnf";
111 #else
112 = "/udd/fspindle/robot/Afma6/current/include/const_eMc_vacuum_with_distortion_Afma6.cnf";
113 #endif
114 
116 #if defined(_WIN32)
117 = "Z:/robot/Afma6/current/include/const_eMc_generic_without_distortion_Afma6.cnf";
118 #else
119 = "/udd/fspindle/robot/Afma6/current/include/const_eMc_generic_without_distortion_Afma6.cnf";
120 #endif
121 
123 #if defined(_WIN32)
124 = "Z:/robot/Afma6/current/include/const_eMc_generic_with_distortion_Afma6.cnf";
125 #else
126 = "/udd/fspindle/robot/Afma6/current/include/const_eMc_generic_with_distortion_Afma6.cnf";
127 #endif
128 
129 const char * const vpAfma6::CONST_CAMERA_AFMA6_FILENAME
130 #if defined(_WIN32)
131 = "Z:/robot/Afma6/current/include/const_camera_Afma6.xml";
132 #else
133 = "/udd/fspindle/robot/Afma6/current/include/const_camera_Afma6.xml";
134 #endif
135 
136 #endif // VISP_HAVE_ACCESS_TO_NAS
137 
138 const char * const vpAfma6::CONST_CCMOP_CAMERA_NAME = "Dragonfly2-8mm-ccmop";
139 const char * const vpAfma6::CONST_GRIPPER_CAMERA_NAME = "Dragonfly2-6mm-gripper";
140 const char * const vpAfma6::CONST_VACUUM_CAMERA_NAME = "Dragonfly2-6mm-vacuum";
141 const char * const vpAfma6::CONST_GENERIC_CAMERA_NAME = "Generic-camera";
142 
144 
145 const unsigned int vpAfma6::njoint = 6;
146 
153  : _coupl_56(0), _long_56(0), _etc(), _erc(), _eMc(),
154  tool_current(vpAfma6::defaultTool),
155  projModel(vpCameraParameters::perspectiveProjWithoutDistortion)
156 {
157  // Set the default parameters in case of the config files on the NAS
158  // at Inria are not available.
159 
160  //
161  // Geometric model constant parameters
162  //
163  // coupling between join 5 and 6
164  this->_coupl_56 = 0.009091;
165  // distance between join 5 and 6
166  this->_long_56 = -0.06924;
167  // Camera extrinsic parameters: effector to camera frame
168  this->_eMc.eye(); // Default values are initialized ...
169  // ... in init (vpAfma6::vpAfma6ToolType tool,
170  // vpCameraParameters::vpCameraParametersProjType projModel)
171  // Maximal value of the joints
172  this->_joint_max[0] = 0.7001;
173  this->_joint_max[1] = 0.5201;
174  this->_joint_max[2] = 0.4601;
175  this->_joint_max[3] = 2.7301;
176  this->_joint_max[4] = 2.4801;
177  this->_joint_max[5] = 1.5901;
178  // Minimal value of the joints
179  this->_joint_min[0] = -0.6501;
180  this->_joint_min[1] = -0.6001;
181  this->_joint_min[2] = -0.5001;
182  this->_joint_min[3] = -2.7301;
183  this->_joint_min[4] = -0.1001;
184  this->_joint_min[5] = -1.5901;
185 
186  init();
187 
188 }
189 
194 void
196 {
197  this->init ( vpAfma6::defaultTool);
198  return;
199 }
200 
215 #ifdef VISP_HAVE_ACCESS_TO_NAS
216 void
217 vpAfma6::init (const char * paramAfma6,
218  const char * paramCamera)
219 {
220  // vpTRACE ("Parsage fichier robot.");
221  this->parseConfigFile (paramAfma6);
222 
223  //vpTRACE ("Parsage fichier camera.");
224  this->parseConfigFile (paramCamera);
225 
226  return ;
227 }
228 #endif
229 
242 void
245 {
246 
247  this->projModel = proj_model;
248 
249 #ifdef VISP_HAVE_ACCESS_TO_NAS
250  // Read the robot parameters from files
251  char filename_eMc [FILENAME_MAX];
252  switch (tool) {
253  case vpAfma6::TOOL_CCMOP: {
254  switch(projModel) {
256 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
257  snprintf(filename_eMc, FILENAME_MAX, "%s",
259 #else // _WIN32
260  _snprintf(filename_eMc, FILENAME_MAX, "%s",
262 #endif
263  break;
265 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
266  snprintf(filename_eMc, FILENAME_MAX, "%s",
268 #else // _WIN32
269  _snprintf(filename_eMc, FILENAME_MAX, "%s",
271 #endif
272  break;
273  }
274  break;
275  }
276  case vpAfma6::TOOL_GRIPPER: {
277  switch(projModel) {
279 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
280  snprintf(filename_eMc, FILENAME_MAX, "%s",
282 #else // _WIN32
283  _snprintf(filename_eMc, FILENAME_MAX, "%s",
285 #endif
286  break;
288 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
289  snprintf(filename_eMc, FILENAME_MAX, "%s",
291 #else // _WIN32
292  _snprintf(filename_eMc, FILENAME_MAX, "%s",
294 #endif
295  break;
296  }
297  break;
298  }
299  case vpAfma6::TOOL_VACUUM: {
300  switch(projModel) {
302 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
303  snprintf(filename_eMc, FILENAME_MAX, "%s",
305 #else // _WIN32
306  _snprintf(filename_eMc, FILENAME_MAX, "%s",
308 #endif
309  break;
311 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
312  snprintf(filename_eMc, FILENAME_MAX, "%s",
314 #else // _WIN32
315  _snprintf(filename_eMc, FILENAME_MAX, "%s",
317 #endif
318  break;
319  }
320  break;
321  }
323  switch(projModel) {
325 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
326  snprintf(filename_eMc, FILENAME_MAX, "%s",
328 #else // _WIN32
329  _snprintf(filename_eMc, FILENAME_MAX, "%s",
331 #endif
332  break;
334 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
335  snprintf(filename_eMc, FILENAME_MAX, "%s",
337 #else // _WIN32
338  _snprintf(filename_eMc, FILENAME_MAX, "%s",
340 #endif
341  break;
342  }
343  break;
344  }
345  default: {
346  vpERROR_TRACE ("This error should not occur!");
347  // vpERROR_TRACE ("Si elle survient malgre tout, c'est sans doute "
348  // "que les specs de la classe ont ete modifiee, "
349  // "et que le code n'a pas ete mis a jour "
350  // "correctement.");
351  // vpERROR_TRACE ("Verifiez les valeurs possibles du type "
352  // "vpAfma6::vpAfma6ToolType, et controlez que "
353  // "tous les cas ont ete pris en compte dans la "
354  // "fonction init(camera).");
355  break;
356  }
357  }
358 
359  this->init (vpAfma6::CONST_AFMA6_FILENAME, filename_eMc);
360 
361 #else // VISP_HAVE_ACCESS_TO_NAS
362 
363  // Use here default values of the robot constant parameters.
364  switch (tool) {
365  case vpAfma6::TOOL_CCMOP: {
366  switch(projModel) {
368  _erc[0] = vpMath::rad(164.35); // rx
369  _erc[1] = vpMath::rad( 89.64); // ry
370  _erc[2] = vpMath::rad(-73.05); // rz
371  _etc[0] = 0.0117; // tx
372  _etc[1] = 0.0033; // ty
373  _etc[2] = 0.2272; // tz
374  break;
376  _erc[0] = vpMath::rad(33.54); // rx
377  _erc[1] = vpMath::rad(89.34); // ry
378  _erc[2] = vpMath::rad(57.83); // rz
379  _etc[0] = 0.0373; // tx
380  _etc[1] = 0.0024; // ty
381  _etc[2] = 0.2286; // tz
382  break;
383  }
384  break;
385  }
386  case vpAfma6::TOOL_GRIPPER: {
387  switch(projModel) {
389  _erc[0] = vpMath::rad( 88.33); // rx
390  _erc[1] = vpMath::rad( 72.07); // ry
391  _erc[2] = vpMath::rad( 2.53); // rz
392  _etc[0] = 0.0783; // tx
393  _etc[1] = 0.1234; // ty
394  _etc[2] = 0.1638; // tz
395  break;
397  _erc[0] = vpMath::rad(86.69); // rx
398  _erc[1] = vpMath::rad(71.93); // ry
399  _erc[2] = vpMath::rad( 4.17); // rz
400  _etc[0] = 0.1034; // tx
401  _etc[1] = 0.1142; // ty
402  _etc[2] = 0.1642; // tz
403  break;
404  }
405  break;
406  }
407  case vpAfma6::TOOL_VACUUM: {
408  switch(projModel) {
410  _erc[0] = vpMath::rad( 90.40); // rx
411  _erc[1] = vpMath::rad( 75.11); // ry
412  _erc[2] = vpMath::rad( 0.18); // rz
413  _etc[0] = 0.0038; // tx
414  _etc[1] = 0.1281; // ty
415  _etc[2] = 0.1658; // tz
416  break;
418  _erc[0] = vpMath::rad(91.61); // rx
419  _erc[1] = vpMath::rad(76.17); // ry
420  _erc[2] = vpMath::rad(-0.98); // rz
421  _etc[0] = 0.0815; // tx
422  _etc[1] = 0.1162; // ty
423  _etc[2] = 0.1658; // tz
424  break;
425  }
426  break;
427  }
429  switch(projModel) {
432  // set eMc to identity
433  _erc[0] = 0; // rx
434  _erc[1] = 0; // ry
435  _erc[2] = 0; // rz
436  _etc[0] = 0; // tx
437  _etc[1] = 0; // ty
438  _etc[2] = 0; // tz
439  break;
440  }
441  break;
442  }
443  }
444  vpRotationMatrix eRc(_erc);
445  this->_eMc.buildFrom(_etc, eRc);
446 #endif // VISP_HAVE_ACCESS_TO_NAS
447 
448  setToolType(tool);
449  return ;
450 }
451 
452 
479 {
481  fMc = get_fMc(q);
482 
483  return fMc;
484 }
485 
559 int
561  vpColVector & q, const bool &nearest, const bool &verbose) const
562 {
564  double q_[2][6],d[2],t;
565  int ok[2];
566  double cord[6];
567 
568  int nbsol = 0;
569 
570  if (q.getRows() != njoint)
571  q.resize(6);
572 
573 
574  // for(unsigned int i=0;i<3;i++) {
575  // fMe[i][3] = fMc[i][3];
576  // for(int j=0;j<3;j++) {
577  // fMe[i][j] = 0.0;
578  // for (int k=0;k<3;k++) fMe[i][j] += fMc[i][k]*rpi[j][k];
579  // fMe[i][3] -= fMe[i][j]*rpi[j][3];
580  // }
581  // }
582 
583  // std::cout << "\n\nfMc: " << fMc;
584  // std::cout << "\n\neMc: " << _eMc;
585 
586  fMe = fMc * this->_eMc.inverse();
587  // std::cout << "\n\nfMe: " << fMe;
588 
589  if (fMe[2][2] >= .99999f)
590  {
591  vpTRACE("singularity\n");
592  q_[0][4] = q_[1][4] = M_PI/2.f;
593  t = atan2(fMe[0][0],fMe[0][1]);
594  q_[1][3] = q_[0][3] = q[3];
595  q_[1][5] = q_[0][5] = t - q_[0][3];
596 
597  while ((q_[1][5]+vpMath::rad(2)) >= this->_joint_max[5])
598  /* -> a cause du couplage 4/5 */
599  {
600  q_[1][5] -= vpMath::rad(10);
601  q_[1][3] += vpMath::rad(10);
602  }
603  while (q_[1][5] <= this->_joint_min[5])
604  {
605  q_[1][5] += vpMath::rad(10);
606  q_[1][3] -= vpMath::rad(10);
607  }
608  }
609  else if (fMe[2][2] <= -.99999)
610  {
611  vpTRACE("singularity\n");
612  q_[0][4] = q_[1][4] = -M_PI/2;
613  t = atan2(fMe[1][1],fMe[1][0]);
614  q_[1][3] = q_[0][3] = q[3];
615  q_[1][5] = q_[0][5] = q_[0][3] - t;
616  while ((q_[1][5]+vpMath::rad(2)) >= this->_joint_max[5])
617  /* -> a cause du couplage 4/5 */
618  {
619  q_[1][5] -= vpMath::rad(10);
620  q_[1][3] -= vpMath::rad(10);
621  }
622  while (q_[1][5] <= this->_joint_min[5])
623  {
624  q_[1][5] += vpMath::rad(10);
625  q_[1][3] += vpMath::rad(10);
626  }
627  }
628  else
629  {
630  q_[0][3] = atan2(-fMe[0][2],fMe[1][2]);
631  if (q_[0][3] >= 0.0) q_[1][3] = q_[0][3] - M_PI;
632  else q_[1][3] = q_[0][3] + M_PI;
633 
634  q_[0][4] = asin(fMe[2][2]);
635  if (q_[0][4] >= 0.0) q_[1][4] = M_PI - q_[0][4];
636  else q_[1][4] = -M_PI - q_[0][4];
637 
638  q_[0][5] = atan2(-fMe[2][1],fMe[2][0]);
639  if (q_[0][5] >= 0.0) q_[1][5] = q_[0][5] - M_PI;
640  else q_[1][5] = q_[0][5] + M_PI;
641  }
642  q_[0][0] = fMe[0][3] - this->_long_56*cos(q_[0][3]);
643  q_[1][0] = fMe[0][3] - this->_long_56*cos(q_[1][3]);
644  q_[0][1] = fMe[1][3] - this->_long_56*sin(q_[0][3]);
645  q_[1][1] = fMe[1][3] - this->_long_56*sin(q_[1][3]);
646  q_[0][2] = q_[1][2] = fMe[2][3];
647 
648  /* prise en compte du couplage axes 5/6 */
649  q_[0][5] += this->_coupl_56*q_[0][4];
650  q_[1][5] += this->_coupl_56*q_[1][4];
651 
652  for (int j=0;j<2;j++)
653  {
654  ok[j] = 1;
655  // test is position is reachable
656  for (unsigned int i=0;i<6;i++) {
657  if (q_[j][i] < this->_joint_min[i] || q_[j][i] > this->_joint_max[i]) {
658  if (verbose) {
659  if (i < 3)
660  std::cout << "Joint " << i << " not in limits: " << this->_joint_min[i] << " < " << q_[j][i] << " < " << this->_joint_max[i] << std::endl;
661  else
662  std::cout << "Joint " << i << " not in limits: " << vpMath::deg(this->_joint_min[i]) << " < " << vpMath::deg(q_[j][i]) << " < " << vpMath::deg(this->_joint_max[i]) << std::endl;
663  }
664  ok[j] = 0;
665  }
666  }
667  }
668  if (ok[0] == 0)
669  {
670  if (ok[1] == 0) {
671  std::cout << "No solution..." << std::endl;
672  nbsol = 0;
673  return nbsol;
674  }
675  else if (ok[1] == 1) {
676  for (unsigned int i=0;i<6;i++) cord[i] = q_[1][i];
677  nbsol = 1;
678  }
679  }
680  else
681  {
682  if (ok[1] == 0) {
683  for (unsigned int i=0;i<6;i++) cord[i] = q_[0][i];
684  nbsol = 1;
685  }
686  else
687  {
688  nbsol = 2;
689  //vpTRACE("2 solutions\n");
690  for (int j=0;j<2;j++)
691  {
692  d[j] = 0.0;
693  for (unsigned int i=3;i<6;i++)
694  d[j] += (q_[j][i] - q[i]) * (q_[j][i] - q[i]);
695  }
696  if (nearest == true)
697  {
698  if (d[0] <= d[1])
699  for (unsigned int i=0;i<6;i++) cord[i] = q_[0][i];
700  else
701  for (unsigned int i=0;i<6;i++) cord[i] = q_[1][i];
702  }
703  else
704  {
705  if (d[0] <= d[1])
706  for (unsigned int i=0;i<6;i++) cord[i] = q_[1][i];
707  else
708  for (unsigned int i=0;i<6;i++) cord[i] = q_[0][i];
709  }
710  }
711  }
712  for(unsigned int i=0; i<6; i++)
713  q[i] = cord[i] ;
714 
715  return nbsol;
716 }
717 
741 vpAfma6::get_fMc (const vpColVector & q) const
742 {
744  get_fMc(q, fMc);
745 
746  return fMc;
747 }
748 
768 void
770 {
771 
772  // Compute the direct geometric model: fMe = transformation between
773  // fix and end effector frame.
775 
776  get_fMe(q, fMe);
777 
778  fMc = fMe * this->_eMc;
779 
780  return;
781 }
782 
802 void
804 {
805  double q0 = q[0]; // meter
806  double q1 = q[1]; // meter
807  double q2 = q[2]; // meter
808 
809  /* Decouplage liaisons 2 et 3. */
810  double q5 = q[5] - this->_coupl_56 * q[4];
811 
812  double c1 = cos(q[3]);
813  double s1 = sin(q[3]);
814  double c2 = cos(q[4]);
815  double s2 = sin(q[4]);
816  double c3 = cos(q5);
817  double s3 = sin(q5);
818 
819  // Compute the direct geometric model: fMe = transformation betwee
820  // fix and end effector frame.
821  fMe[0][0] = s1*s2*c3 + c1*s3;
822  fMe[0][1] = -s1*s2*s3 + c1*c3;
823  fMe[0][2] = -s1*c2;
824  fMe[0][3] = q0 + this->_long_56*c1;
825 
826  fMe[1][0] = -c1*s2*c3 + s1*s3;
827  fMe[1][1] = c1*s2*s3 + s1*c3;
828  fMe[1][2] = c1*c2;
829  fMe[1][3] = q1 + this->_long_56*s1;
830 
831  fMe[2][0] = c2*c3;
832  fMe[2][1] = -c2*s3;
833  fMe[2][2] = s2;
834  fMe[2][3] = q2;
835 
836  fMe[3][0] = 0;
837  fMe[3][1] = 0;
838  fMe[3][2] = 0;
839  fMe[3][3] = 1;
840 
841  // vpCTRACE << "Effector position fMe: " << std::endl << fMe;
842 
843  return;
844 }
845 
856 void
858 {
859  cMe = this->_eMc.inverse();
860 }
861 
871 void
873 {
874  vpHomogeneousMatrix cMe ;
875  get_cMe(cMe) ;
876 
877  cVe.buildFrom(cMe) ;
878 
879  return;
880 }
881 
894 void
895 vpAfma6::get_eJe(const vpColVector &q, vpMatrix &eJe) const
896 {
897 
898  eJe.resize(6,6) ;
899 
900  double s4,c4,s5,c5,s6,c6 ;
901 
902  s4=sin(q[3]); c4=cos(q[3]);
903  s5=sin(q[4]); c5=cos(q[4]);
904  s6=sin(q[5]-this->_coupl_56*q[4]); c6=cos(q[5]-this->_coupl_56*q[4]);
905 
906  eJe = 0;
907  eJe[0][0] = s4*s5*c6+c4*s6;
908  eJe[0][1] = -c4*s5*c6+s4*s6;
909  eJe[0][2] = c5*c6;
910  eJe[0][3] = - this->_long_56*s5*c6;
911 
912  eJe[1][0] = -s4*s5*s6+c4*c6;
913  eJe[1][1] = c4*s5*s6+s4*c6;
914  eJe[1][2] = -c5*s6;
915  eJe[1][3] = this->_long_56*s5*s6;
916 
917  eJe[2][0] = -s4*c5;
918  eJe[2][1] = c4*c5;
919  eJe[2][2] = s5;
920  eJe[2][3] = this->_long_56*c5;
921 
922  eJe[3][3] = c5*c6;
923  eJe[3][4] = s6;
924 
925  eJe[4][3] = -c5*s6;
926  eJe[4][4] = c6;
927 
928  eJe[5][3] = s5;
929  eJe[5][4] = -this->_coupl_56;
930  eJe[5][5] = 1;
931 
932  return;
933 }
934 
935 
963 void
964 vpAfma6::get_fJe(const vpColVector &q, vpMatrix &fJe) const
965 {
966 
967  fJe.resize(6,6) ;
968 
969  // block superieur gauche
970  fJe[0][0] = fJe[1][1] = fJe[2][2] = 1 ;
971 
972  double s4 = sin(q[3]) ;
973  double c4 = cos(q[3]) ;
974 
975 
976  // block superieur droit
977  fJe[0][3] = - this->_long_56*s4 ;
978  fJe[1][3] = this->_long_56*c4 ;
979 
980 
981  double s5 = sin(q[4]) ;
982  double c5 = cos(q[4]) ;
983  // block inferieur droit
984  fJe[3][4] = c4 ; fJe[3][5] = -s4*c5 ;
985  fJe[4][4] = s4 ; fJe[4][5] = c4*c5 ;
986  fJe[5][3] = 1 ; fJe[5][5] = s5 ;
987 
988  // coupling between joint 5 and 6
989  fJe[3][4] += this->_coupl_56*s4*c5;
990  fJe[4][4] += -this->_coupl_56*c4*c5;
991  fJe[5][4] += -this->_coupl_56*s5;
992 
993  return;
994 }
995 
996 
1007 {
1008  vpColVector qmin(6);
1009  for (unsigned int i=0; i < 6; i ++)
1010  qmin[i] = this->_joint_min[i];
1011  return qmin;
1012 }
1013 
1024 {
1025  vpColVector qmax(6);
1026  for (unsigned int i=0; i < 6; i ++)
1027  qmax[i] = this->_joint_max[i];
1028  return qmax;
1029 }
1030 
1037 double
1039 {
1040  return _coupl_56;
1041 }
1042 
1049 double
1051 {
1052  return _long_56;
1053 }
1054 
1055 
1068 #ifdef VISP_HAVE_ACCESS_TO_NAS
1069 void
1070 vpAfma6::parseConfigFile (const char * filename)
1071 {
1072  size_t dim;
1073  int code;
1074  char Ligne[FILENAME_MAX];
1075  char namoption[100];
1076  FILE * fdtask;
1077  int numLn = 0;
1078  double rot_eMc[3]; // rotation
1079  double trans_eMc[3]; // translation
1080  bool get_rot_eMc = false;
1081  bool get_trans_eMc = false;
1082 
1083  //vpTRACE("Read the config file for constant parameters %s.", filename);
1084  if ((fdtask = fopen(filename, "r" )) == NULL)
1085  {
1086  vpERROR_TRACE ("Impossible to read the config file %s.",
1087  filename);
1089  "Impossible to read the config file.");
1090  }
1091 
1092  while (fgets(Ligne, FILENAME_MAX, fdtask) != NULL) {
1093  numLn ++;
1094  if ('#' == Ligne[0]) { continue; }
1095  sscanf(Ligne, "%s", namoption);
1096  dim = strlen(namoption);
1097 
1098  for (code = 0;
1099  NULL != opt_Afma6[code];
1100  ++ code)
1101  {
1102  if (strncmp(opt_Afma6[code], namoption, dim) == 0)
1103  {
1104  break;
1105  }
1106  }
1107 
1108  switch(code)
1109  {
1110  case 0:
1111  sscanf(Ligne, "%s %lf %lf %lf %lf %lf %lf",
1112  namoption,
1113  &this->_joint_max[0], &this->_joint_max[1],
1114  &this->_joint_max[2], &this->_joint_max[3],
1115  &this->_joint_max[4], &this->_joint_max[5]);
1116  break;
1117 
1118  case 1:
1119  sscanf(Ligne, "%s %lf %lf %lf %lf %lf %lf", namoption,
1120  &this->_joint_min[0], &this->_joint_min[1],
1121  &this->_joint_min[2], &this->_joint_min[3],
1122  &this->_joint_min[4], &this->_joint_min[5]);
1123  break;
1124 
1125  case 2:
1126  sscanf(Ligne, "%s %lf", namoption, &this->_long_56);
1127  break;
1128 
1129  case 3:
1130  sscanf(Ligne, "%s %lf", namoption, &this->_coupl_56);
1131  break;
1132 
1133  case 4:
1134  break; // Nothing to do: camera name
1135 
1136  case 5:
1137  sscanf(Ligne, "%s %lf %lf %lf", namoption,
1138  &rot_eMc[0],
1139  &rot_eMc[1],
1140  &rot_eMc[2]);
1141 
1142  // Convert rotation from degrees to radians
1143  rot_eMc[0] *= M_PI / 180.0;
1144  rot_eMc[1] *= M_PI / 180.0;
1145  rot_eMc[2] *= M_PI / 180.0;
1146  get_rot_eMc = true;
1147  break;
1148 
1149  case 6:
1150  sscanf(Ligne, "%s %lf %lf %lf", namoption,
1151  &trans_eMc[0],
1152  &trans_eMc[1],
1153  &trans_eMc[2]);
1154  get_trans_eMc = true;
1155  break;
1156 
1157  default:
1158  vpERROR_TRACE ("Bad configuration file %s "
1159  "ligne #%d.", filename, numLn);
1160  } /* SWITCH */
1161  } /* WHILE */
1162 
1163  fclose (fdtask);
1164 
1165  // Compute the eMc matrix from the translations and rotations
1166  if (get_rot_eMc && get_trans_eMc) {
1167  for (unsigned int i=0; i < 3; i ++) {
1168  _erc[i] = rot_eMc[i];
1169  _etc[i] = trans_eMc[i];
1170  }
1171 
1172  vpRotationMatrix eRc(_erc);
1173  this->_eMc.buildFrom(_etc, eRc);
1174  }
1175 
1176  return;
1177 }
1178 #endif
1179 
1243 void
1245  const unsigned int &image_width,
1246  const unsigned int &image_height) const
1247 {
1248 #if defined(VISP_HAVE_XML2) && defined (VISP_HAVE_ACCESS_TO_NAS)
1249  vpXmlParserCamera parser;
1250  switch (getToolType()) {
1251  case vpAfma6::TOOL_CCMOP: {
1252  std::cout << "Get camera parameters for camera \""
1253  << vpAfma6::CONST_CCMOP_CAMERA_NAME << "\"" << std::endl
1254  << "from the XML file: \""
1255  << vpAfma6::CONST_CAMERA_AFMA6_FILENAME << "\""<< std::endl;
1256  if (parser.parse(cam,
1259  projModel,
1260  image_width, image_height) != vpXmlParserCamera::SEQUENCE_OK) {
1262  "Impossible to read the camera parameters.");
1263  }
1264  break;
1265  }
1266  case vpAfma6::TOOL_GRIPPER: {
1267  std::cout << "Get camera parameters for camera \""
1268  << vpAfma6::CONST_GRIPPER_CAMERA_NAME << "\"" << std::endl
1269  << "from the XML file: \""
1270  << vpAfma6::CONST_CAMERA_AFMA6_FILENAME << "\""<< std::endl;
1271  if (parser.parse(cam,
1274  projModel,
1275  image_width, image_height) != vpXmlParserCamera::SEQUENCE_OK) {
1277  "Impossible to read the camera parameters.");
1278  }
1279  break;
1280  }
1281  case vpAfma6::TOOL_VACUUM: {
1282  std::cout << "Get camera parameters for camera \""
1283  << vpAfma6::CONST_VACUUM_CAMERA_NAME << "\"" << std::endl
1284  << "from the XML file: \""
1285  << vpAfma6::CONST_CAMERA_AFMA6_FILENAME << "\""<< std::endl;
1286  if (parser.parse(cam,
1289  projModel,
1290  image_width, image_height) != vpXmlParserCamera::SEQUENCE_OK) {
1292  "Impossible to read the camera parameters.");
1293  }
1294  break;
1295  }
1297  std::cout << "Get camera parameters for camera \""
1298  << vpAfma6::CONST_GENERIC_CAMERA_NAME << "\"" << std::endl
1299  << "from the XML file: \""
1300  << vpAfma6::CONST_CAMERA_AFMA6_FILENAME << "\""<< std::endl;
1301  if (parser.parse(cam,
1304  projModel,
1305  image_width, image_height) != vpXmlParserCamera::SEQUENCE_OK) {
1307  "Impossible to read the camera parameters.");
1308  }
1309  break;
1310  }
1311  default: {
1312  vpERROR_TRACE ("This error should not occur!");
1313  // vpERROR_TRACE ("Si elle survient malgre tout, c'est sans doute "
1314  // "que les specs de la classe ont ete modifiee, "
1315  // "et que le code n'a pas ete mis a jour "
1316  // "correctement.");
1317  // vpERROR_TRACE ("Verifiez les valeurs possibles du type "
1318  // "vpAfma6::vpAfma6ToolType, et controlez que "
1319  // "tous les cas ont ete pris en compte dans la "
1320  // "fonction init(camera).");
1322  "Impossible to read the camera parameters.");
1323  break;
1324  }
1325  }
1326 #else
1327  // Set default parameters
1328  switch (getToolType()) {
1329  case vpAfma6::TOOL_CCMOP: {
1330  // Set default intrinsic camera parameters for 640x480 images
1331  if (image_width == 640 && image_height == 480) {
1332  std::cout << "Get default camera parameters for camera \""
1333  << vpAfma6::CONST_CCMOP_CAMERA_NAME << "\"" << std::endl;
1334  switch(this->projModel) {
1336  cam.initPersProjWithoutDistortion(1108.0, 1110.0, 314.5, 243.2);
1337  break;
1339  cam.initPersProjWithDistortion(1090.6, 1090.0, 310.1, 260.8, -0.2114, 0.2217);
1340  break;
1341  }
1342  }
1343  else {
1344  vpTRACE("Cannot get default intrinsic camera parameters for this image resolution");
1346  "Impossible to read the camera parameters.");
1347  }
1348  break;
1349  }
1350  case vpAfma6::TOOL_GRIPPER: {
1351  // Set default intrinsic camera parameters for 640x480 images
1352  if (image_width == 640 && image_height == 480) {
1353  std::cout << "Get default camera parameters for camera \""
1354  << vpAfma6::CONST_GRIPPER_CAMERA_NAME << "\"" << std::endl;
1355  switch(this->projModel) {
1357  cam.initPersProjWithoutDistortion(850.9, 853.0, 311.1, 243.6);
1358  break;
1360  cam.initPersProjWithDistortion(837.0, 837.5, 308.7, 251.6, -0.1455, 0.1511);
1361  break;
1362  }
1363  }
1364  else {
1365  vpTRACE("Cannot get default intrinsic camera parameters for this image resolution");
1367  "Impossible to read the camera parameters.");
1368  }
1369  break;
1370  }
1371  case vpAfma6::TOOL_VACUUM: {
1372  // Set default intrinsic camera parameters for 640x480 images
1373  if (image_width == 640 && image_height == 480) {
1374  std::cout << "Get default camera parameters for camera \""
1375  << vpAfma6::CONST_VACUUM_CAMERA_NAME << "\"" << std::endl;
1376  switch(this->projModel) {
1378  cam.initPersProjWithoutDistortion(853.5, 856.0, 307.8, 236.8);
1379  break;
1381  cam.initPersProjWithDistortion(828.5, 829.0, 322.5, 232.9, -0.1921, 0.2057);
1382  break;
1383  }
1384  }
1385  else {
1386  vpTRACE("Cannot get default intrinsic camera parameters for this image resolution");
1388  "Impossible to read the camera parameters.");
1389  }
1390  break;
1391  }
1393  // Set default intrinsic camera parameters for 640x480 images
1394  if (image_width == 640 && image_height == 480) {
1395  std::cout << "Get default camera parameters for camera \""
1396  << vpAfma6::CONST_GENERIC_CAMERA_NAME << "\"" << std::endl;
1397  switch(this->projModel) {
1399  cam.initPersProjWithoutDistortion(853.5, 856.0, 307.8, 236.8);
1400  break;
1402  cam.initPersProjWithDistortion(828.5, 829.0, 322.5, 232.9, -0.1921, 0.2057);
1403  break;
1404  }
1405  }
1406  else {
1407  vpTRACE("Cannot get default intrinsic camera parameters for this image resolution");
1409  "Impossible to read the camera parameters.");
1410  }
1411  break;
1412  }
1413  default:
1414  vpERROR_TRACE ("This error should not occur!");
1415  break;
1416  }
1417 #endif
1418  return;
1419 }
1420 
1462 void
1464  const vpImage<unsigned char> &I) const
1465 {
1466  getCameraParameters(cam,I.getWidth(),I.getHeight());
1467 }
1511 void
1513  const vpImage<vpRGBa> &I) const
1514 {
1515  getCameraParameters(cam,I.getWidth(),I.getHeight());
1516 }
1517 
1518 
1528 VISP_EXPORT std::ostream & operator << (std::ostream & os,
1529  const vpAfma6 & afma6)
1530 {
1531  vpRotationMatrix eRc;
1532  afma6._eMc.extract(eRc);
1533  vpRxyzVector rxyz(eRc);
1534 
1535  os
1536  << "Joint Max:" << std::endl
1537  << "\t" << afma6._joint_max[0]
1538  << "\t" << afma6._joint_max[1]
1539  << "\t" << afma6._joint_max[2]
1540  << "\t" << afma6._joint_max[3]
1541  << "\t" << afma6._joint_max[4]
1542  << "\t" << afma6._joint_max[5]
1543  << "\t" << std::endl
1544 
1545  << "Joint Min: " << std::endl
1546  << "\t" << afma6._joint_min[0]
1547  << "\t" << afma6._joint_min[1]
1548  << "\t" << afma6._joint_min[2]
1549  << "\t" << afma6._joint_min[3]
1550  << "\t" << afma6._joint_min[4]
1551  << "\t" << afma6._joint_min[5]
1552  << "\t" << std::endl
1553 
1554  << "Long 5-6: " << std::endl
1555  << "\t" << afma6._long_56
1556  << "\t" << std::endl
1557 
1558  << "Coupling 5-6:" << std::endl
1559  << "\t" << afma6._coupl_56
1560  << "\t" << std::endl
1561 
1562  << "eMc: "<< std::endl
1563  << "\tTranslation (m): "
1564  << afma6._eMc[0][3] << " "
1565  << afma6._eMc[1][3] << " "
1566  << afma6._eMc[2][3]
1567  << "\t" << std::endl
1568  << "\tRotation Rxyz (rad) : "
1569  << rxyz[0] << " "
1570  << rxyz[1] << " "
1571  << rxyz[2]
1572  << "\t" << std::endl
1573  << "\tRotation Rxyz (deg) : "
1574  << vpMath::deg(rxyz[0]) << " "
1575  << vpMath::deg(rxyz[1]) << " "
1576  << vpMath::deg(rxyz[2])
1577  << "\t" << std::endl;
1578 
1579  return os;
1580 }
1581 
Modelisation of Irisa's gantry robot named Afma6.
Definition: vpAfma6.h:65
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:92
vpRxyzVector _erc
Definition: vpAfma6.h:186
vpTranslationVector _etc
Definition: vpAfma6.h:185
void getCameraParameters(vpCameraParameters &cam, const unsigned int &image_width, const unsigned int &image_height) const
Definition: vpAfma6.cpp:1244
static const unsigned int njoint
Number of joint.
Definition: vpAfma6.h:172
void get_cVe(vpVelocityTwistMatrix &cVe) const
Definition: vpAfma6.cpp:872
Error that can be emited by the vpRobot class and its derivates.
static const char *const CONST_EMC_GRIPPER_WITHOUT_DISTORTION_FILENAME
Definition: vpAfma6.h:75
Perspective projection without distortion model.
static const char *const CONST_EMC_CCMOP_WITH_DISTORTION_FILENAME
Definition: vpAfma6.h:74
unsigned int getWidth() const
Definition: vpImage.h:161
void resize(const unsigned int nrows, const unsigned int ncols, const bool flagNullify=true)
Definition: vpArray2D.h:167
vpHomogeneousMatrix getForwardKinematics(const vpColVector &q) const
Definition: vpAfma6.cpp:478
int getInverseKinematics(const vpHomogeneousMatrix &fMc, vpColVector &q, const bool &nearest=true, const bool &verbose=false) const
Definition: vpAfma6.cpp:560
vpAfma6ToolType getToolType() const
Get the current tool type.
Definition: vpAfma6.h:146
Implementation of an homogeneous matrix and operations on such kind of matrices.
vpHomogeneousMatrix get_fMc(const vpColVector &q) const
Definition: vpAfma6.cpp:741
#define vpERROR_TRACE
Definition: vpDebug.h:391
double _coupl_56
Definition: vpAfma6.h:180
void get_eJe(const vpColVector &q, vpMatrix &eJe) const
Definition: vpAfma6.cpp:895
vpAfma6ToolType
List of possible tools that can be attached to the robot end-effector.
Definition: vpAfma6.h:104
vpCameraParameters::vpCameraParametersProjType projModel
Definition: vpAfma6.h:194
static const char *const CONST_EMC_VACUUM_WITH_DISTORTION_FILENAME
Definition: vpAfma6.h:78
XML parser to load and save intrinsic camera parameters.
void get_fMe(const vpColVector &q, vpHomogeneousMatrix &fMe) const
Definition: vpAfma6.cpp:803
void setToolType(vpAfma6::vpAfma6ToolType tool)
Set the current tool type.
Definition: vpAfma6.h:170
static const char *const CONST_EMC_VACUUM_WITHOUT_DISTORTION_FILENAME
Definition: vpAfma6.h:77
static const char *const CONST_GRIPPER_CAMERA_NAME
Definition: vpAfma6.h:91
Implementation of a rotation matrix and operations on such kind of matrices.
void initPersProjWithoutDistortion(const double px, const double py, const double u0, const double v0)
static const vpAfma6ToolType defaultTool
Default tool attached to the robot end effector.
Definition: vpAfma6.h:113
static const char *const CONST_EMC_CCMOP_WITHOUT_DISTORTION_FILENAME
Definition: vpAfma6.h:73
static const char *const CONST_EMC_GENERIC_WITHOUT_DISTORTION_FILENAME
Definition: vpAfma6.h:79
vpColVector getJointMin() const
Definition: vpAfma6.cpp:1006
vpVelocityTwistMatrix buildFrom(const vpTranslationVector &t, const vpRotationMatrix &R)
#define vpTRACE
Definition: vpDebug.h:414
static const char *const CONST_CAMERA_AFMA6_FILENAME
Definition: vpAfma6.h:81
void get_cMe(vpHomogeneousMatrix &cMe) const
Definition: vpAfma6.cpp:857
static const char *const CONST_AFMA6_FILENAME
Definition: vpAfma6.h:72
Generic class defining intrinsic camera parameters.
void parseConfigFile(const char *filename)
Definition: vpAfma6.cpp:1070
vpColVector getJointMax() const
Definition: vpAfma6.cpp:1023
void extract(vpRotationMatrix &R) const
friend std::ostream & operator<<(std::ostream &s, const vpArray2D< Type > &A)
Definition: vpArray2D.h:267
Implementation of a velocity twist matrix and operations on such kind of matrices.
unsigned int getRows() const
Return the number of rows of the 2D array.
Definition: vpArray2D.h:152
vpAfma6()
Definition: vpAfma6.cpp:152
Perspective projection with distortion model.
void buildFrom(const vpTranslationVector &t, const vpRotationMatrix &R)
static double rad(double deg)
Definition: vpMath.h:104
double getLong56() const
Definition: vpAfma6.cpp:1050
double _long_56
Definition: vpAfma6.h:181
static double deg(double rad)
Definition: vpMath.h:97
Implementation of column vector and the associated operations.
Definition: vpColVector.h:72
static const char *const CONST_EMC_GRIPPER_WITH_DISTORTION_FILENAME
Definition: vpAfma6.h:76
vpHomogeneousMatrix inverse() const
vpHomogeneousMatrix _eMc
Definition: vpAfma6.h:188
unsigned int getHeight() const
Definition: vpImage.h:152
Implementation of a rotation vector as Euler angle minimal representation.
Definition: vpRxyzVector.h:154
void init(void)
Definition: vpAfma6.cpp:195
double _joint_max[6]
Definition: vpAfma6.h:182
int parse(vpCameraParameters &cam, const std::string &filename, const std::string &camera_name, const vpCameraParameters::vpCameraParametersProjType &projModel, const unsigned int image_width=0, const unsigned int image_height=0)
static const char *const CONST_CCMOP_CAMERA_NAME
Definition: vpAfma6.h:86
void get_fJe(const vpColVector &q, vpMatrix &fJe) const
Definition: vpAfma6.cpp:964
static const char *const CONST_VACUUM_CAMERA_NAME
Definition: vpAfma6.h:96
void initPersProjWithDistortion(const double px, const double py, const double u0, const double v0, const double kud, const double kdu)
static const char *const CONST_EMC_GENERIC_WITH_DISTORTION_FILENAME
Definition: vpAfma6.h:80
double _joint_min[6]
Definition: vpAfma6.h:183
void resize(const unsigned int i, const bool flagNullify=true)
Definition: vpColVector.h:217
static const char *const CONST_GENERIC_CAMERA_NAME
Definition: vpAfma6.h:101
double getCoupl56() const
Definition: vpAfma6.cpp:1038