ViSP  2.9.0
vpServo.cpp
1 /****************************************************************************
2  *
3  * $Id: vpServo.cpp 4674 2014-02-17 15:34:41Z fspindle $
4  *
5  * This file is part of the ViSP software.
6  * Copyright (C) 2005 - 2014 by INRIA. All rights reserved.
7  *
8  * This software is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * ("GPL") version 2 as published by the Free Software Foundation.
11  * See the file LICENSE.txt at the root directory of this source
12  * distribution for additional information about the GNU GPL.
13  *
14  * For using ViSP with software that can not be combined with the GNU
15  * GPL, please contact INRIA about acquiring a ViSP Professional
16  * Edition License.
17  *
18  * See http://www.irisa.fr/lagadic/visp/visp.html for more information.
19  *
20  * This software was developed at:
21  * INRIA Rennes - Bretagne Atlantique
22  * Campus Universitaire de Beaulieu
23  * 35042 Rennes Cedex
24  * France
25  * http://www.irisa.fr/lagadic
26  *
27  * If you have questions regarding the use of this file, please contact
28  * INRIA at visp@inria.fr
29  *
30  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
31  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
32  *
33  *
34  * Description:
35  * Visual servoing control law.
36  *
37  * Authors:
38  * Eric Marchand
39  * Nicolas Mansard
40  * Fabien Spindler
41  *
42  *****************************************************************************/
43 
44 
45 #include <visp/vpServo.h>
46 
47 // Exception
48 #include <visp/vpException.h>
49 #include <visp/vpMatrixException.h>
50 
51 // Debug trace
52 #include <visp/vpDebug.h>
53 
72  : L(), error(), J1(), J1p(), s(), sStar(), e1(), e(), q_dot(), v(), servoType(vpServo::NONE),
73  rankJ1(0), featureList(), desiredFeatureList(), featureSelectionList(), lambda(), signInteractionMatrix(1),
74  interactionMatrixType(DESIRED), inversionType(PSEUDO_INVERSE), cVe(), init_cVe(false),
75  cVf(), init_cVf(false), fVe(), init_fVe(false), eJe(), init_eJe(false), fJe(), init_fJe(false),
76  errorComputed(false), interactionMatrixComputed(false), dim_task(0), taskWasKilled(false),
77  forceInteractionMatrixComputation(false), WpW(), I_WpW(), sv(), mu(4.)
78 {
79 }
94  : L(), error(), J1(), J1p(), s(), sStar(), e1(), e(), q_dot(), v(), servoType(servo_type),
95  rankJ1(0), featureList(), desiredFeatureList(), featureSelectionList(), lambda(), signInteractionMatrix(1),
96  interactionMatrixType(DESIRED), inversionType(PSEUDO_INVERSE), cVe(), init_cVe(false),
97  cVf(), init_cVf(false), fVe(), init_fVe(false), eJe(), init_eJe(false), fJe(), init_fJe(false),
98  errorComputed(false), interactionMatrixComputed(false), dim_task(0), taskWasKilled(false),
99  forceInteractionMatrixComputation(false), WpW(), I_WpW(), sv(), mu(4)
100 {
101 }
102 
111 // \exception vpServoException::notKilledProperly : Task was not killed
112 // properly. That means that you should explitly call kill().
113 
115 {
116  if (taskWasKilled == false) {
117  vpTRACE("--- Begin Warning Warning Warning Warning Warning ---");
118  vpTRACE("--- You should explicitly call vpServo.kill()... ---");
119  vpTRACE("--- End Warning Warning Warning Warning Warning ---");
120  // throw(vpServoException(vpServoException::notKilledProperly,
121  // "Task was not killed properly"));
122  }
123 }
124 
125 
140 {
141  // type of visual servoing
143 
144  // Twist transformation matrix
145  init_cVe = false ;
146  init_cVf = false ;
147  init_fVe = false ;
148  // Jacobians
149  init_eJe = false ;
150  init_fJe = false ;
151 
152  dim_task = 0 ;
153 
154  featureList.clear() ;
155  desiredFeatureList.clear() ;
156  featureSelectionList.clear();
157 
159 
162 
163  interactionMatrixComputed = false ;
164  errorComputed = false ;
165 
166  taskWasKilled = false;
167 
169 
170  rankJ1 = 0;
171 }
172 
190 {
191  if (taskWasKilled == false) {
192  // kill the current and desired feature lists
193 
194  // current list
195  for(std::list<vpBasicFeature *>::iterator it = featureList.begin(); it != featureList.end(); ++it) {
196  if ((*it)->getDeallocate() == vpBasicFeature::vpServo) {
197  delete (*it) ;
198  (*it) = NULL ;
199  }
200  }
201  //desired list
202  for(std::list<vpBasicFeature *>::iterator it = desiredFeatureList.begin(); it != desiredFeatureList.end(); ++it) {
203  if ((*it)->getDeallocate() == vpBasicFeature::vpServo) {
204  delete (*it) ;
205  (*it) = NULL ;
206  }
207  }
208 
209  featureList.clear() ;
210  desiredFeatureList.clear() ;
211  taskWasKilled = true;
212  }
213 }
214 
220 void vpServo::setServo(const vpServoType &servo_type)
221 {
222  this->servoType = servo_type ;
223 
226  else
227  signInteractionMatrix = -1 ;
228 
229  // when the control is directly compute in the camera frame
230  // we relieve the end-user to initialize cVa and aJe
232  {
233  vpVelocityTwistMatrix _cVe ; set_cVe(_cVe) ;
234 
235  vpMatrix _eJe ;
236  _eJe.eye(6) ;
237  set_eJe(_eJe) ;
238  };
239 }
240 
241 
250 void
251  vpServo::print(const vpServo::vpServoPrintType displayLevel, std::ostream &os)
252 {
253  switch (displayLevel)
254  {
255  case vpServo::ALL:
256  {
257  os << "Visual servoing task: " <<std::endl ;
258 
259  os << "Type of control law " <<std::endl ;
260  switch( servoType )
261  {
262  case NONE :
263  os << "Type of task have not been chosen yet ! " << std::endl ;
264  break ;
265  case EYEINHAND_CAMERA :
266  os << "Eye-in-hand configuration " << std::endl ;
267  os << "Control in the camera frame " << std::endl ;
268  break ;
269  case EYEINHAND_L_cVe_eJe :
270  os << "Eye-in-hand configuration " << std::endl ;
271  os << "Control in the articular frame " << std::endl ;
272  break ;
273  case EYETOHAND_L_cVe_eJe :
274  os << "Eye-to-hand configuration " << std::endl ;
275  os << "s_dot = _L_cVe_eJe q_dot " << std::endl ;
276  break ;
278  os << "Eye-to-hand configuration " << std::endl ;
279  os << "s_dot = _L_cVe_fVe_eJe q_dot " << std::endl ;
280  break ;
281  case EYETOHAND_L_cVf_fJe :
282  os << "Eye-to-hand configuration " << std::endl ;
283  os << "s_dot = _L_cVf_fJe q_dot " << std::endl ;
284  break ;
285  }
286 
287  os << "List of visual features : s" <<std::endl ;
288  std::list<vpBasicFeature *>::const_iterator it_s;
289  std::list<vpBasicFeature *>::const_iterator it_s_star;
290  std::list<unsigned int>::const_iterator it_select;
291 
292  for (it_s = featureList.begin(), it_select = featureSelectionList.begin(); it_s != featureList.end(); ++it_s, ++it_select)
293  {
294  os << "" ;
295  (*it_s)->print( (*it_select) ) ;
296  }
297 
298  os << "List of desired visual features : s*" <<std::endl ;
299  for (it_s_star = desiredFeatureList.begin(), it_select = featureSelectionList.begin(); it_s_star != desiredFeatureList.end(); ++it_s_star, ++it_select)
300  {
301  os << "" ;
302  (*it_s_star)->print( (*it_select) ) ;
303  }
304 
305  os <<"Interaction Matrix Ls "<<std::endl ;
307  {
308  os << L << std::endl;
309  }
310  else
311  {
312  os << "not yet computed "<<std::endl ;
313  }
314 
315  os <<"Error vector (s-s*) "<<std::endl ;
316  if (errorComputed)
317  {
318  os << error.t() << std::endl;
319  }
320  else
321  {
322  os << "not yet computed "<<std::endl ;
323  }
324 
325  os << "Gain : " << lambda <<std::endl ;
326 
327  break;
328  }
329 
330  case vpServo::CONTROLLER:
331  {
332  os << "Type of control law " <<std::endl ;
333  switch( servoType )
334  {
335  case NONE :
336  os << "Type of task have not been chosen yet ! " << std::endl ;
337  break ;
338  case EYEINHAND_CAMERA :
339  os << "Eye-in-hand configuration " << std::endl ;
340  os << "Control in the camera frame " << std::endl ;
341  break ;
342  case EYEINHAND_L_cVe_eJe :
343  os << "Eye-in-hand configuration " << std::endl ;
344  os << "Control in the articular frame " << std::endl ;
345  break ;
346  case EYETOHAND_L_cVe_eJe :
347  os << "Eye-to-hand configuration " << std::endl ;
348  os << "s_dot = _L_cVe_eJe q_dot " << std::endl ;
349  break ;
351  os << "Eye-to-hand configuration " << std::endl ;
352  os << "s_dot = _L_cVe_fVe_eJe q_dot " << std::endl ;
353  break ;
354  case EYETOHAND_L_cVf_fJe :
355  os << "Eye-to-hand configuration " << std::endl ;
356  os << "s_dot = _L_cVf_fJe q_dot " << std::endl ;
357  break ;
358  }
359  break;
360  }
361 
363  {
364  os << "List of visual features : s" <<std::endl ;
365 
366  std::list<vpBasicFeature *>::const_iterator it_s;
367  std::list<unsigned int>::const_iterator it_select;
368 
369  for (it_s = featureList.begin(), it_select = featureSelectionList.begin(); it_s != featureList.end(); ++it_s, ++it_select)
370  {
371  os << "" ;
372  (*it_s)->print( (*it_select) ) ;
373  }
374  break;
375  }
377  {
378  os << "List of desired visual features : s*" <<std::endl ;
379 
380  std::list<vpBasicFeature *>::const_iterator it_s_star;
381  std::list<unsigned int>::const_iterator it_select;
382 
383  for (it_s_star = desiredFeatureList.begin(), it_select = featureSelectionList.begin(); it_s_star != desiredFeatureList.end(); ++it_s_star, ++it_select)
384  {
385  os << "" ;
386  (*it_s_star)->print( (*it_select) ) ;
387  }
388  break;
389  }
390  case vpServo::GAIN:
391  {
392  os << "Gain : " << lambda <<std::endl ;
393  break;
394  }
396  {
397  os <<"Interaction Matrix Ls "<<std::endl ;
399  os << L << std::endl;
400  }
401  else {
402  os << "not yet computed "<<std::endl ;
403  }
404  break;
405  }
406 
408  case vpServo::MINIMUM:
409 
410  {
411  os <<"Error vector (s-s*) "<<std::endl ;
412  if (errorComputed) {
413  os << error.t() << std::endl;
414  }
415  else {
416  os << "not yet computed "<<std::endl ;
417  }
418 
419  break;
420  }
421  }
422 }
423 
449 void vpServo::addFeature(vpBasicFeature& s_cur, vpBasicFeature &s_star, unsigned int select)
450 {
451  featureList.push_back( &s_cur );
452  desiredFeatureList.push_back( &s_star );
453  featureSelectionList.push_back( select );
454 }
455 
479 void vpServo::addFeature(vpBasicFeature& s_cur, unsigned int select)
480 {
481  featureList.push_back( &s_cur );
482 
483  // in fact we have a problem with s_star that is not defined
484  // by the end user.
485 
486  // If the same user want to compute the interaction at the desired position
487  // this "virtual feature" must exist
488 
489  // a solution is then to duplicate the current feature (s* = s)
490  // and reinitialized s* to 0
491 
492  // it remains the deallocation issue therefore a flag that stipulates that
493  // the feature has been allocated in vpServo is set
494 
495  // vpServo must deallocate the memory (see ~vpServo and kill() )
496 
497  vpBasicFeature *s_star ;
498  s_star = s_cur.duplicate() ;
499 
500  s_star->init() ;
502 
503  desiredFeatureList.push_back( s_star );
504  featureSelectionList.push_back( select );
505 }
506 
508 unsigned int vpServo::getDimension() const
509 {
510  unsigned int dim = 0 ;
511  std::list<vpBasicFeature *>::const_iterator it_s;
512  std::list<unsigned int>::const_iterator it_select;
513 
514  for (it_s = featureList.begin(), it_select = featureSelectionList.begin(); it_s != featureList.end(); ++it_s, ++it_select)
515  {
516  dim += (*it_s)->getDimension(*it_select) ;
517  }
518 
519  return dim;
520 }
521 
523  const vpServoInversionType &interactionMatrixInversion)
524 {
525  this->interactionMatrixType = interactionMatrix_type ;
526  this->inversionType = interactionMatrixInversion ;
527 }
528 
529 
530 static void computeInteractionMatrixFromList (const std::list<vpBasicFeature *> & featureList,
531  const std::list<unsigned int> & featureSelectionList,
532  vpMatrix & L)
533 {
534  if (featureList.empty())
535  {
536  vpERROR_TRACE("feature list empty, cannot compute Ls") ;
538  "feature list empty, cannot compute Ls")) ;
539  }
540 
541  /* The matrix dimension is not known before the affectation loop.
542  * It thus should be allocated on the flight, in the loop.
543  * The first assumption is that the size has not changed. A double
544  * reallocation (realloc(dim*2)) is done if necessary. In particular,
545  * [log_2(dim)+1] reallocations are done for the first matrix computation.
546  * If the allocated size is too large, a correction is done after the loop.
547  * The algorithmic cost is linear in affectation, logarithmic in allocation
548  * numbers and linear in allocation size.
549  */
550 
551  /* First assumption: matrix dimensions have not changed. If 0, they are
552  * initialized to dim 1.*/
553  unsigned int rowL = L.getRows();
554  const unsigned int colL = 6;
555  if (0 == rowL) {
556  rowL = 1;
557  L .resize(rowL, colL);
558  }
559 
560  /* vectTmp is used to store the return values of functions get_s() and
561  * error(). */
562  vpMatrix matrixTmp;
563  unsigned int rowMatrixTmp, colMatrixTmp;
564 
565  /* The cursor are the number of the next case of the vector array to
566  * be affected. A memory reallocation should be done when cursor
567  * is out of the vector-array range.*/
568  unsigned int cursorL = 0;
569 
570  std::list<vpBasicFeature *>::const_iterator it;
571  std::list<unsigned int>::const_iterator it_select;
572 
573  for (it = featureList.begin(), it_select = featureSelectionList.begin(); it != featureList.end(); ++it, ++it_select)
574  {
575  /* Get s. */
576  matrixTmp = (*it)->interaction( *it_select );
577  rowMatrixTmp = matrixTmp .getRows();
578  colMatrixTmp = matrixTmp .getCols();
579 
580  /* Check the matrix L size, and realloc if needed. */
581  while (rowMatrixTmp + cursorL > rowL) {
582  rowL *= 2;
583  L.resize (rowL,colL,false);
584  vpDEBUG_TRACE(15,"Realloc!");
585  }
586 
587  /* Copy the temporarily matrix into L. */
588  for (unsigned int k = 0; k < rowMatrixTmp; ++k, ++cursorL) {
589  for (unsigned int j = 0; j < colMatrixTmp; ++j) {
590  L[cursorL][j] = matrixTmp[k][j];
591  }
592  }
593  }
594 
595  L.resize (cursorL,colL,false);
596 
597  return ;
598 }
599 
600 
608 {
609  try {
610 
611  switch (interactionMatrixType)
612  {
613  case CURRENT:
614  {
615  try
616  {
617  computeInteractionMatrixFromList(this ->featureList,
618  this ->featureSelectionList,
619  L);
620  dim_task = L.getRows() ;
622  }
623 
624  catch(vpException me)
625  {
626  vpERROR_TRACE("Error caught") ;
627  throw ;
628  }
629  }
630  break ;
631  case DESIRED:
632  {
633  try
634  {
636  {
637  computeInteractionMatrixFromList(this ->desiredFeatureList,
638  this ->featureSelectionList, L);
639 
640  dim_task = L.getRows() ;
642  }
643 
644  }
645  catch(vpException me)
646  {
647  vpERROR_TRACE("Error caught") ;
648  throw ;
649  }
650  }
651  break ;
652  case MEAN:
653  {
654  vpMatrix Lstar (L.getRows(), L.getCols());
655  try
656  {
657  computeInteractionMatrixFromList(this ->featureList,
658  this ->featureSelectionList, L);
659  computeInteractionMatrixFromList(this ->desiredFeatureList,
660  this ->featureSelectionList, Lstar);
661  }
662  catch(vpException me)
663  {
664  vpERROR_TRACE("Error caught") ;
665  throw ;
666  }
667  L = (L+Lstar)/2;
668 
669  dim_task = L.getRows() ;
671  }
672  break ;
673  case USER_DEFINED:
674  // dim_task = L.getRows() ;
675  interactionMatrixComputed = false ;
676  break;
677  }
678 
679  }
680  catch(vpException me)
681  {
682  vpERROR_TRACE("Error caught") ;
683  throw ;
684  }
685  return L ;
686 }
687 
697 {
698  if (featureList.empty())
699  {
700  vpERROR_TRACE("feature list empty, cannot compute Ls") ;
702  "feature list empty, cannot compute Ls")) ;
703  }
704  if (desiredFeatureList.empty())
705  {
706  vpERROR_TRACE("feature list empty, cannot compute Ls") ;
708  "feature list empty, cannot compute Ls")) ;
709  }
710 
711  try {
712  vpBasicFeature *current_s ;
713  vpBasicFeature *desired_s ;
714 
715  /* The vector dimensions are not known before the affectation loop.
716  * They thus should be allocated on the flight, in the loop.
717  * The first assumption is that the size has not changed. A double
718  * reallocation (realloc(dim*2)) is done if necessary. In particular,
719  * [log_2(dim)+1] reallocations are done for the first error computation.
720  * If the allocated size is too large, a correction is done after the loop.
721  * The algorithmic cost is linear in affectation, logarithmic in allocation
722  * numbers and linear in allocation size.
723  * No assumptions are made concerning size of each vector: they are
724  * not said equal, and could be different.
725  */
726 
727  /* First assumption: vector dimensions have not changed. If 0, they are
728  * initialized to dim 1.*/
729  unsigned int dimError = error .getRows();
730  unsigned int dimS = s .getRows();
731  unsigned int dimSStar = sStar .getRows();
732  if (0 == dimError) { dimError = 1; error .resize(dimError);}
733  if (0 == dimS) { dimS = 1; s .resize(dimS);}
734  if (0 == dimSStar) { dimSStar = 1; sStar .resize(dimSStar);}
735 
736  /* vectTmp is used to store the return values of functions get_s() and
737  * error(). */
738  vpColVector vectTmp;
739  unsigned int dimVectTmp;
740 
741  /* The cursor are the number of the next case of the vector array to
742  * be affected. A memory reallocation should be done when cursor
743  * is out of the vector-array range.*/
744  unsigned int cursorS = 0;
745  unsigned int cursorSStar = 0;
746  unsigned int cursorError = 0;
747 
748  /* For each cell of the list, copy value of s, s_star and error. */
749  std::list<vpBasicFeature *>::const_iterator it_s;
750  std::list<vpBasicFeature *>::const_iterator it_s_star;
751  std::list<unsigned int>::const_iterator it_select;
752 
753  for (it_s = featureList.begin(), it_s_star = desiredFeatureList.begin(), it_select = featureSelectionList.begin();
754  it_s != featureList.end();
755  ++it_s, ++it_s_star, ++it_select)
756  {
757  current_s = (*it_s);
758  desired_s = (*it_s_star);
759  unsigned int select = (*it_select);
760 
761  /* Get s, and store it in the s vector. */
762  vectTmp = current_s->get_s(select);
763  dimVectTmp = vectTmp .getRows();
764  while (dimVectTmp + cursorS > dimS)
765  { dimS *= 2; s .resize (dimS,false); vpDEBUG_TRACE(15,"Realloc!"); }
766  for (unsigned int k = 0; k < dimVectTmp; ++k) { s[cursorS++] = vectTmp[k]; }
767 
768  /* Get s_star, and store it in the s vector. */
769  vectTmp = desired_s->get_s(select);
770  dimVectTmp = vectTmp .getRows();
771  while (dimVectTmp + cursorSStar > dimSStar) {
772  dimSStar *= 2;
773  sStar.resize (dimSStar,false);
774  }
775  for (unsigned int k = 0; k < dimVectTmp; ++k) {
776  sStar[cursorSStar++] = vectTmp[k];
777  }
778 
779  /* Get error, and store it in the s vector. */
780  vectTmp = current_s->error(*desired_s, select) ;
781  dimVectTmp = vectTmp .getRows();
782  while (dimVectTmp + cursorError > dimError) {
783  dimError *= 2;
784  error.resize (dimError,false);
785  }
786  for (unsigned int k = 0; k < dimVectTmp; ++k) {
787  error[cursorError++] = vectTmp[k];
788  }
789  }
790 
791  /* If too much memory has been allocated, realloc. */
792  s .resize(cursorS,false);
793  sStar .resize(cursorSStar,false);
794  error .resize(cursorError,false);
795 
796  /* Final modifications. */
797  dim_task = error.getRows() ;
798  errorComputed = true ;
799  }
800  catch(vpException me)
801  {
802  vpERROR_TRACE("Error caught") ;
803  throw ;
804  }
805  catch(...)
806  {
807  throw ;
808  }
809  return error ;
810 }
811 
813 {
814  switch (servoType)
815  {
816  case NONE:
817  vpERROR_TRACE("No control law have been yet defined") ;
819  "No control law have been yet defined")) ;
820  break ;
821  case EYEINHAND_CAMERA:
822  return true ;
823  break ;
824  case EYEINHAND_L_cVe_eJe:
825  case EYETOHAND_L_cVe_eJe:
826  if (!init_cVe) vpERROR_TRACE("cVe not initialized") ;
827  if (!init_eJe) vpERROR_TRACE("eJe not initialized") ;
828  return (init_cVe && init_eJe) ;
829  break ;
831  if (!init_cVf) vpERROR_TRACE("cVf not initialized") ;
832  if (!init_fJe) vpERROR_TRACE("fVe not initialized") ;
833  if (!init_eJe) vpERROR_TRACE("eJe not initialized") ;
834  return (init_cVf && init_fVe && init_eJe) ;
835  break ;
836 
837  case EYETOHAND_L_cVf_fJe :
838  if (!init_cVf) vpERROR_TRACE("cVf not initialized") ;
839  if (!init_fJe) vpERROR_TRACE("fJe not initialized") ;
840  return (init_cVf && init_fJe) ;
841  break ;
842  }
843 
844  return false ;
845 }
847 {
848  switch (servoType)
849  {
850  case NONE:
851  vpERROR_TRACE("No control law have been yet defined") ;
853  "No control law have been yet defined")) ;
854  break ;
855  case EYEINHAND_CAMERA:
856  return true ;
857  case EYEINHAND_L_cVe_eJe:
858  if (!init_eJe) vpERROR_TRACE("eJe not updated") ;
859  return (init_eJe) ;
860  break ;
861  case EYETOHAND_L_cVe_eJe:
862  if (!init_cVe) vpERROR_TRACE("cVe not updated") ;
863  if (!init_eJe) vpERROR_TRACE("eJe not updated") ;
864  return (init_cVe && init_eJe) ;
865  break ;
867  if (!init_fVe) vpERROR_TRACE("fVe not updated") ;
868  if (!init_eJe) vpERROR_TRACE("eJe not updated") ;
869  return (init_fVe && init_eJe) ;
870  break ;
871 
872  case EYETOHAND_L_cVf_fJe :
873  if (!init_fJe) vpERROR_TRACE("fJe not updated") ;
874  return (init_fJe) ;
875  break ;
876  }
877 
878  return false ;
879 }
903 {
904  static int iteration =0;
905 
906  try
907  {
908  vpVelocityTwistMatrix cVa ; // Twist transformation matrix
909  vpMatrix aJe ; // Jacobian
910 
911  if (iteration==0)
912  {
913  if (testInitialization() == false) {
914  vpERROR_TRACE("All the matrices are not correctly initialized") ;
916  "Cannot compute control law "
917  "All the matrices are not correctly"
918  "initialized")) ;
919  }
920  }
921  if (testUpdated() == false) {
922  vpERROR_TRACE("All the matrices are not correctly updated") ;
923  }
924 
925  // test if all the required initialization have been done
926  switch (servoType)
927  {
928  case NONE :
929  vpERROR_TRACE("No control law have been yet defined") ;
931  "No control law have been yet defined")) ;
932  break ;
933  case EYEINHAND_CAMERA:
934  case EYEINHAND_L_cVe_eJe:
935  case EYETOHAND_L_cVe_eJe:
936 
937  cVa = cVe ;
938  aJe = eJe ;
939 
940  init_cVe = false ;
941  init_eJe = false ;
942  break ;
944  cVa = cVf*fVe ;
945  aJe = eJe ;
946  init_fVe = false ;
947  init_eJe = false ;
948  break ;
949  case EYETOHAND_L_cVf_fJe :
950  cVa = cVf ;
951  aJe = fJe ;
952  init_fJe = false ;
953  break ;
954  }
955 
957  computeError() ;
958 
959  // compute task Jacobian
960  J1 = L*cVa*aJe ;
961 
962  // handle the eye-in-hand eye-to-hand case
964 
965  // pseudo inverse of the task Jacobian
966  // and rank of the task Jacobian
967  // the image of J1 is also computed to allows the computation
968  // of the projection operator
969  vpMatrix imJ1t, imJ1 ;
970  bool imageComputed = false ;
971 
973  {
974  rankJ1 = J1.pseudoInverse(J1p, sv, 1e-6, imJ1, imJ1t) ;
975 
976  imageComputed = true ;
977  }
978  else
979  J1p = J1.t() ;
980 
981  if (rankJ1 == L.getCols())
982  {
983  /* if no degrees of freedom remains (rank J1 = ndof)
984  WpW = I, multiply by WpW is useless
985  */
986  e1 = J1p*error ;// primary task
987 
988  WpW.resize(J1.getCols(), J1.getCols()) ;
989  WpW.setIdentity() ;
990  }
991  else
992  {
993  if (imageComputed!=true)
994  {
995  vpMatrix Jtmp ;
996  // image of J1 is computed to allows the computation
997  // of the projection operator
998  rankJ1 = J1.pseudoInverse(Jtmp, sv, 1e-6, imJ1, imJ1t) ;
999  imageComputed = true ;
1000  }
1001  WpW = imJ1t*imJ1t.t() ;
1002 
1003 #ifdef DEBUG
1004  std::cout << "rank J1 " << rankJ1 <<std::endl ;
1005  std::cout << "imJ1t"<<std::endl << imJ1t ;
1006  std::cout << "imJ1"<<std::endl << imJ1 ;
1007 
1008  std::cout << "WpW" <<std::endl <<WpW ;
1009  std::cout << "J1" <<std::endl <<J1 ;
1010  std::cout << "J1p" <<std::endl <<J1p ;
1011 #endif
1012  e1 = WpW*J1p*error ;
1013  }
1014  e = - lambda(e1) * e1 ;
1015 
1016  vpMatrix I ;
1017 
1018  I.resize(J1.getCols(),J1.getCols()) ;
1019  I.setIdentity() ;
1020 
1021  I_WpW = (I - WpW) ;
1022  }
1023  catch(vpMatrixException me)
1024  {
1025  vpERROR_TRACE("Caught a matrix related error") ;
1026  std::cout << me << std::endl ;
1027  throw me;
1028  }
1029  catch(vpException me)
1030  {
1031  vpERROR_TRACE("Error caught") ;
1032  std::cout << me << std::endl ;
1033  throw me ;
1034  }
1035 
1036  iteration++ ;
1037  return e ;
1038 }
1039 
1069 {
1070  static int iteration =0;
1071  static vpColVector e1_initial;
1072 
1073  try
1074  {
1075  vpVelocityTwistMatrix cVa ; // Twist transformation matrix
1076  vpMatrix aJe ; // Jacobian
1077 
1078  if (iteration==0)
1079  {
1080  if (testInitialization() == false) {
1081  vpERROR_TRACE("All the matrices are not correctly initialized") ;
1083  "Cannot compute control law "
1084  "All the matrices are not correctly"
1085  "initialized")) ;
1086  }
1087  }
1088  if (testUpdated() == false) {
1089  vpERROR_TRACE("All the matrices are not correctly updated") ;
1090  }
1091 
1092  // test if all the required initialization have been done
1093  switch (servoType)
1094  {
1095  case NONE :
1096  vpERROR_TRACE("No control law have been yet defined") ;
1098  "No control law have been yet defined")) ;
1099  break ;
1100  case EYEINHAND_CAMERA:
1101  case EYEINHAND_L_cVe_eJe:
1102  case EYETOHAND_L_cVe_eJe:
1103 
1104  cVa = cVe ;
1105  aJe = eJe ;
1106 
1107  init_cVe = false ;
1108  init_eJe = false ;
1109  break ;
1111  cVa = cVf*fVe ;
1112  aJe = eJe ;
1113  init_fVe = false ;
1114  init_eJe = false ;
1115  break ;
1116  case EYETOHAND_L_cVf_fJe :
1117  cVa = cVf ;
1118  aJe = fJe ;
1119  init_fJe = false ;
1120  break ;
1121  }
1122 
1124  computeError() ;
1125 
1126  // compute task Jacobian
1127  J1 = L*cVa*aJe ;
1128 
1129  // handle the eye-in-hand eye-to-hand case
1131 
1132  // pseudo inverse of the task Jacobian
1133  // and rank of the task Jacobian
1134  // the image of J1 is also computed to allows the computation
1135  // of the projection operator
1136  vpMatrix imJ1t, imJ1 ;
1137  bool imageComputed = false ;
1138 
1140  {
1141  rankJ1 = J1.pseudoInverse(J1p, sv, 1e-6, imJ1, imJ1t) ;
1142 
1143  imageComputed = true ;
1144  }
1145  else
1146  J1p = J1.t() ;
1147 
1148  if (rankJ1 == L.getCols())
1149  {
1150  /* if no degrees of freedom remains (rank J1 = ndof)
1151  WpW = I, multiply by WpW is useless
1152  */
1153  e1 = J1p*error ;// primary task
1154 
1155  WpW.resize(J1.getCols(), J1.getCols()) ;
1156  WpW.setIdentity() ;
1157  }
1158  else
1159  {
1160  if (imageComputed!=true)
1161  {
1162  vpMatrix Jtmp ;
1163  // image of J1 is computed to allows the computation
1164  // of the projection operator
1165  rankJ1 = J1.pseudoInverse(Jtmp, sv, 1e-6, imJ1, imJ1t) ;
1166  imageComputed = true ;
1167  }
1168  WpW = imJ1t*imJ1t.t() ;
1169 
1170 #ifdef DEBUG
1171  std::cout << "rank J1 " << rankJ1 <<std::endl ;
1172  std::cout << "imJ1t"<<std::endl << imJ1t ;
1173  std::cout << "imJ1"<<std::endl << imJ1 ;
1174 
1175  std::cout << "WpW" <<std::endl <<WpW ;
1176  std::cout << "J1" <<std::endl <<J1 ;
1177  std::cout << "J1p" <<std::endl <<J1p ;
1178 #endif
1179  e1 = WpW*J1p*error ;
1180  }
1181 
1182  // memorize the initial e1 value if the function is called the first time or if the time given as parameter is equal to 0.
1183  if (iteration==0 || std::fabs(t) < std::numeric_limits<double>::epsilon()) {
1184  e1_initial = e1;
1185  }
1186 
1187  e = - lambda(e1) * e1 + lambda(e1) * e1_initial*exp(-mu*t);
1188 
1189  vpMatrix I ;
1190 
1191  I.resize(J1.getCols(), J1.getCols()) ;
1192  I.setIdentity() ;
1193 
1194  I_WpW = (I - WpW) ;
1195  }
1196  catch(vpMatrixException me)
1197  {
1198  vpERROR_TRACE("Caught a matrix related error") ;
1199  std::cout << me << std::endl ;
1200  throw me;
1201  }
1202  catch(vpException me)
1203  {
1204  vpERROR_TRACE("Error caught") ;
1205  std::cout << me << std::endl ;
1206  throw me ;
1207  }
1208 
1209  iteration++ ;
1210  return e ;
1211 }
1212 
1242 {
1243  static int iteration =0;
1244  static vpColVector e1_initial;
1245 
1246  try
1247  {
1248  vpVelocityTwistMatrix cVa ; // Twist transformation matrix
1249  vpMatrix aJe ; // Jacobian
1250 
1251  if (iteration==0)
1252  {
1253  if (testInitialization() == false) {
1254  vpERROR_TRACE("All the matrices are not correctly initialized") ;
1256  "Cannot compute control law "
1257  "All the matrices are not correctly"
1258  "initialized")) ;
1259  }
1260  }
1261  if (testUpdated() == false) {
1262  vpERROR_TRACE("All the matrices are not correctly updated") ;
1263  }
1264 
1265  // test if all the required initialization have been done
1266  switch (servoType)
1267  {
1268  case NONE :
1269  vpERROR_TRACE("No control law have been yet defined") ;
1271  "No control law have been yet defined")) ;
1272  break ;
1273  case EYEINHAND_CAMERA:
1274  case EYEINHAND_L_cVe_eJe:
1275  case EYETOHAND_L_cVe_eJe:
1276 
1277  cVa = cVe ;
1278  aJe = eJe ;
1279 
1280  init_cVe = false ;
1281  init_eJe = false ;
1282  break ;
1284  cVa = cVf*fVe ;
1285  aJe = eJe ;
1286  init_fVe = false ;
1287  init_eJe = false ;
1288  break ;
1289  case EYETOHAND_L_cVf_fJe :
1290  cVa = cVf ;
1291  aJe = fJe ;
1292  init_fJe = false ;
1293  break ;
1294  }
1295 
1297  computeError() ;
1298 
1299  // compute task Jacobian
1300  J1 = L*cVa*aJe ;
1301 
1302  // handle the eye-in-hand eye-to-hand case
1304 
1305  // pseudo inverse of the task Jacobian
1306  // and rank of the task Jacobian
1307  // the image of J1 is also computed to allows the computation
1308  // of the projection operator
1309  vpMatrix imJ1t, imJ1 ;
1310  bool imageComputed = false ;
1311 
1313  {
1314  rankJ1 = J1.pseudoInverse(J1p, sv, 1e-6, imJ1, imJ1t) ;
1315 
1316  imageComputed = true ;
1317  }
1318  else
1319  J1p = J1.t() ;
1320 
1321  if (rankJ1 == L.getCols())
1322  {
1323  /* if no degrees of freedom remains (rank J1 = ndof)
1324  WpW = I, multiply by WpW is useless
1325  */
1326  e1 = J1p*error ;// primary task
1327 
1328  WpW.resize(J1.getCols(), J1.getCols()) ;
1329  WpW.setIdentity() ;
1330  }
1331  else
1332  {
1333  if (imageComputed!=true)
1334  {
1335  vpMatrix Jtmp ;
1336  // image of J1 is computed to allows the computation
1337  // of the projection operator
1338  rankJ1 = J1.pseudoInverse(Jtmp, sv, 1e-6, imJ1, imJ1t) ;
1339  imageComputed = true ;
1340  }
1341  WpW = imJ1t*imJ1t.t() ;
1342 
1343 #ifdef DEBUG
1344  std::cout << "rank J1 " << rankJ1 <<std::endl ;
1345  std::cout << "imJ1t"<<std::endl << imJ1t ;
1346  std::cout << "imJ1"<<std::endl << imJ1 ;
1347 
1348  std::cout << "WpW" <<std::endl <<WpW ;
1349  std::cout << "J1" <<std::endl <<J1 ;
1350  std::cout << "J1p" <<std::endl <<J1p ;
1351 #endif
1352  e1 = WpW*J1p*error ;
1353  }
1354 
1355  // memorize the initial e1 value if the function is called the first time or if the time given as parameter is equal to 0.
1356  if (iteration==0 || std::fabs(t) < std::numeric_limits<double>::epsilon()) {
1357  e1_initial = e1;
1358  }
1359 
1360  e = - lambda(e1) * e1 + (e_dot_init + lambda(e1) * e1_initial)*exp(-mu*t);
1361 
1362  vpMatrix I ;
1363 
1364  I.resize(J1.getCols(), J1.getCols()) ;
1365  I.setIdentity() ;
1366 
1367  I_WpW = (I - WpW) ;
1368  }
1369  catch(vpMatrixException me)
1370  {
1371  vpERROR_TRACE("Caught a matrix related error") ;
1372  std::cout << me << std::endl ;
1373  throw me;
1374  }
1375  catch(vpException me)
1376  {
1377  vpERROR_TRACE("Error caught") ;
1378  std::cout << me << std::endl ;
1379  throw me ;
1380  }
1381 
1382  iteration++ ;
1383  return e ;
1384 }
1385 
1386 
1417 {
1418  if (rankJ1 == L.getCols())
1419  {
1420  vpERROR_TRACE("no degree of freedom is free, cannot use secondary task") ;
1422  "no degree of freedom is free, cannot use secondary task")) ;
1423  }
1424  else
1425  {
1426  vpColVector sec ;
1427 #if 0
1428  // computed in computeControlLaw()
1429  vpMatrix I ;
1430 
1431  I.resize(J1.getCols(),J1.getCols()) ;
1432  I.setIdentity() ;
1433  I_WpW = (I - WpW) ;
1434 #endif
1435  // std::cout << "I-WpW" << std::endl << I_WpW <<std::endl ;
1436  sec = I_WpW*de2dt ;
1437 
1438  return sec ;
1439  }
1440 }
1441 
1475 {
1476  if (rankJ1 == L.getCols())
1477  {
1478  vpERROR_TRACE("no degree of freedom is free, cannot use secondary task") ;
1480  "no degree of freedom is free, cannot use secondary task")) ;
1481  }
1482  else
1483  {
1484  vpColVector sec ;
1485 #if 0
1486  // computed in computeControlLaw()
1487  vpMatrix I ;
1488 
1489  I.resize(J1.getCols(),J1.getCols()) ;
1490  I.setIdentity() ;
1491 
1492  I_WpW = (I - WpW) ;
1493 #endif
1494 
1495  // To be coherent with the primary task the gain must be the same between
1496  // primary and secondary task.
1497  sec = -lambda(e1) *I_WpW*e2 + I_WpW *de2dt ;
1498 
1499  return sec ;
1500  }
1501 }
1502 
1516 {
1517  return I_WpW;
1518 }
1519 
1533 {
1534  return J1;
1535 }
1554 {
1555  return J1p;
1556 }
1567 unsigned int vpServo::getTaskRank() const
1568 {
1569  return rankJ1;
1570 }
1571 
1588 {
1589  return WpW;
1590 }
#define vpDEBUG_TRACE
Definition: vpDebug.h:482
Definition of the vpMatrix class.
Definition: vpMatrix.h:98
unsigned int getDimension() const
Return the task dimension.
Definition: vpServo.cpp:508
void resize(const unsigned int nrows, const unsigned int ncols, const bool nullify=true)
Definition: vpMatrix.cpp:183
vpServoType servoType
Chosen visual servoing control law.
Definition: vpServo.h:488
void setDeallocate(vpBasicFeatureDeallocatorType d)
bool interactionMatrixComputed
true if the interaction matrix has been computed.
Definition: vpServo.h:546
bool taskWasKilled
Flag to indicate if the task was killed.
Definition: vpServo.h:550
vpMatrix getTaskJacobian() const
Definition: vpServo.cpp:1532
unsigned int rankJ1
Rank of the task Jacobian.
Definition: vpServo.h:491
vpVelocityTwistMatrix cVf
Twist transformation matrix between Rf and Rc.
Definition: vpServo.h:522
#define vpERROR_TRACE
Definition: vpDebug.h:395
#define vpTRACE
Definition: vpDebug.h:418
bool init_cVf
Definition: vpServo.h:523
vpVelocityTwistMatrix fVe
Twist transformation matrix between Re and Rf.
Definition: vpServo.h:525
vpColVector sv
Singular values from the pseudo inverse.
Definition: vpServo.h:560
vpServoType
Definition: vpServo.h:161
vpColVector e1
Primary task .
Definition: vpServo.h:478
bool init_cVe
Definition: vpServo.h:520
void set_eJe(const vpMatrix &eJe_)
Definition: vpServo.h:439
Error that can be emited by the vpServo class and its derivates.
void addFeature(vpBasicFeature &s, vpBasicFeature &s_star, const unsigned int select=vpBasicFeature::FEATURE_ALL)
Definition: vpServo.cpp:449
error that can be emited by ViSP classes.
Definition: vpException.h:76
vpServoInversionType
Definition: vpServo.h:199
vpMatrix fJe
Jacobian expressed in the robot reference frame.
Definition: vpServo.h:536
virtual vpColVector error(const vpBasicFeature &s_star, const unsigned int select=FEATURE_ALL)
Compute the error between two visual features from a subset of the possible features.
vpMatrix getI_WpW() const
Definition: vpServo.cpp:1515
unsigned int dim_task
Dimension of the task updated during computeControlLaw().
Definition: vpServo.h:548
vpServoInversionType inversionType
Definition: vpServo.h:511
vpColVector secondaryTask(const vpColVector &de2dt)
Definition: vpServo.cpp:1416
class that defines what is a visual feature
double mu
Definition: vpServo.h:562
vpMatrix computeInteractionMatrix()
Definition: vpServo.cpp:607
std::list< unsigned int > featureSelectionList
Definition: vpServo.h:499
void kill()
Definition: vpServo.cpp:189
void setIdentity(const double &val=1.0)
Definition: vpMatrix.cpp:1159
bool testInitialization()
Definition: vpServo.cpp:812
vpColVector computeError()
Definition: vpServo.cpp:696
int signInteractionMatrix
Definition: vpServo.h:506
vpColVector computeControlLaw()
Definition: vpServo.cpp:902
vpMatrix J1
Task Jacobian .
Definition: vpServo.h:466
vpMatrix L
Interaction matrix.
Definition: vpServo.h:460
vpRowVector t() const
transpose of Vector
bool init_fVe
Definition: vpServo.h:526
bool forceInteractionMatrixComputation
Force the interaction matrix computation even if it is already done.
Definition: vpServo.h:552
vpAdaptiveGain lambda
Gain used in the control law.
Definition: vpServo.h:502
vpVelocityTwistMatrix cVe
Twist transformation matrix between Re and Rc.
Definition: vpServo.h:519
Class that consider the particular case of twist transformation matrix that allows to transform a vel...
vpColVector s
Definition: vpServo.h:472
vpServoIteractionMatrixType
Definition: vpServo.h:187
virtual void init()=0
vpServo()
Definition: vpServo.cpp:71
void setInteractionMatrixType(const vpServoIteractionMatrixType &interactionMatrixType, const vpServoInversionType &interactionMatrixInversion=PSEUDO_INVERSE)
Definition: vpServo.cpp:522
vpColVector e
Task .
Definition: vpServo.h:480
void eye(unsigned int n)
Definition: vpMatrix.cpp:1181
vpMatrix getTaskJacobianPseudoInverse() const
Definition: vpServo.cpp:1553
vpMatrix t() const
Definition: vpMatrix.cpp:1225
std::list< vpBasicFeature * > desiredFeatureList
List of desired visual features .
Definition: vpServo.h:496
Class that provides a data structure for the column vectors as well as a set of operations on these v...
Definition: vpColVector.h:72
virtual ~vpServo()
Definition: vpServo.cpp:114
void set_cVe(const vpVelocityTwistMatrix &cVe_)
Definition: vpServo.h:414
unsigned int getCols() const
Return the number of columns of the matrix.
Definition: vpMatrix.h:163
bool init_fJe
Definition: vpServo.h:537
error that can be emited by the vpMatrix class and its derivates
No degree of freedom is available to achieve the secondary task.
void print(const vpServo::vpServoPrintType display_level=ALL, std::ostream &os=std::cout)
Definition: vpServo.cpp:251
vpMatrix I_WpW
Projection operators .
Definition: vpServo.h:557
vpColVector sStar
Definition: vpServo.h:475
bool testUpdated()
Definition: vpServo.cpp:846
vpMatrix pseudoInverse(double svThreshold=1e-6) const
Compute the pseudo inverse of the matrix using the SVD.
Definition: vpMatrix.cpp:1861
virtual vpBasicFeature * duplicate() const =0
bool errorComputed
true if the error has been computed.
Definition: vpServo.h:544
vpMatrix WpW
Projection operators .
Definition: vpServo.h:555
bool init_eJe
Definition: vpServo.h:534
vpMatrix J1p
Pseudo inverse of the task Jacobian.
Definition: vpServo.h:468
vpMatrix getWpW() const
Definition: vpServo.cpp:1587
unsigned int getRows() const
Return the number of rows of the matrix.
Definition: vpMatrix.h:161
vpColVector get_s(unsigned int select=FEATURE_ALL) const
Get the feature vector .
std::list< vpBasicFeature * > featureList
List of current visual features .
Definition: vpServo.h:494
void setServo(const vpServoType &servo_type)
Definition: vpServo.cpp:220
vpServoPrintType
Definition: vpServo.h:205
vpColVector error
Definition: vpServo.h:464
void init()
Basic initialization.
Definition: vpServo.cpp:139
unsigned int getTaskRank() const
Definition: vpServo.cpp:1567
vpServoIteractionMatrixType interactionMatrixType
Type of the interaction matrox (current, mean, desired, user)
Definition: vpServo.h:508
vpMatrix eJe
Jacobian expressed in the end-effector frame.
Definition: vpServo.h:533
Current or desired feature list is empty.
void resize(const unsigned int i, const bool flagNullify=true)
Definition: vpColVector.h:94