Visual Servoing Platform  version 3.0.1
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
vpRobotAfma4.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2017 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 Afma4 robot.
32  *
33  * Authors:
34  * Fabien Spindler
35  *
36  *****************************************************************************/
37 
38 #include <visp3/core/vpConfig.h>
39 
40 #ifdef VISP_HAVE_AFMA4
41 
42 #include <signal.h>
43 #include <stdlib.h>
44 #include <sys/types.h>
45 #include <unistd.h>
46 
47 #include <visp3/robot/vpRobotException.h>
48 #include <visp3/core/vpExponentialMap.h>
49 #include <visp3/core/vpDebug.h>
50 #include <visp3/core/vpVelocityTwistMatrix.h>
51 #include <visp3/core/vpThetaUVector.h>
52 #include <visp3/core/vpIoTools.h>
53 #include <visp3/robot/vpRobotAfma4.h>
54 
55 /* ---------------------------------------------------------------------- */
56 /* --- STATIC ----------------------------------------------------------- */
57 /* ---------------------------------------------------------------------- */
58 
59 bool vpRobotAfma4::robotAlreadyCreated = false;
60 
69 
70 
71 /* ---------------------------------------------------------------------- */
72 /* --- EMERGENCY STOP --------------------------------------------------- */
73 /* ---------------------------------------------------------------------- */
74 
82 void emergencyStopAfma4(int signo)
83 {
84  std::cout << "Stop the Afma4 application by signal ("
85  << signo << "): " << (char)7 ;
86  switch(signo)
87  {
88  case SIGINT:
89  std::cout << "SIGINT (stop by ^C) " << std::endl ; break ;
90  case SIGBUS:
91  std::cout <<"SIGBUS (stop due to a bus error) " << std::endl ; break ;
92  case SIGSEGV:
93  std::cout <<"SIGSEGV (stop due to a segmentation fault) " << std::endl ; break ;
94  case SIGKILL:
95  std::cout <<"SIGKILL (stop by CTRL \\) " << std::endl ; break ;
96  case SIGQUIT:
97  std::cout <<"SIGQUIT " << std::endl ; break ;
98  default :
99  std::cout << signo << std::endl ;
100  }
101  // std::cout << "Emergency stop called\n";
102  // PrimitiveESTOP_Afma4();
103  PrimitiveSTOP_Afma4();
104  std::cout << "Robot was stopped\n";
105 
106  // Free allocated resources
107  // ShutDownConnection(); // Some times cannot exit here when Ctrl-C
108 
109  fprintf(stdout, "Application ");
110  fflush(stdout);
111  kill(getpid(), SIGKILL);
112  exit(1) ;
113 }
114 
115 
116 /* ---------------------------------------------------------------------- */
117 /* --- CONSTRUCTOR ------------------------------------------------------ */
118 /* ---------------------------------------------------------------------- */
119 
131 vpRobotAfma4::vpRobotAfma4 (bool verbose)
132  :
133  vpAfma4 (),
134  vpRobot ()
135 {
136 
137  /*
138  #define SIGHUP 1 // hangup
139  #define SIGINT 2 // interrupt (rubout)
140  #define SIGQUIT 3 // quit (ASCII FS)
141  #define SIGILL 4 // illegal instruction (not reset when caught)
142  #define SIGTRAP 5 // trace trap (not reset when caught)
143  #define SIGIOT 6 // IOT instruction
144  #define SIGABRT 6 // used by abort, replace SIGIOT in the future
145  #define SIGEMT 7 // EMT instruction
146  #define SIGFPE 8 // floating point exception
147  #define SIGKILL 9 // kill (cannot be caught or ignored)
148  #define SIGBUS 10 // bus error
149  #define SIGSEGV 11 // segmentation violation
150  #define SIGSYS 12 // bad argument to system call
151  #define SIGPIPE 13 // write on a pipe with no one to read it
152  #define SIGALRM 14 // alarm clock
153  #define SIGTERM 15 // software termination signal from kill
154  */
155 
156  signal(SIGINT, emergencyStopAfma4);
157  signal(SIGBUS, emergencyStopAfma4) ;
158  signal(SIGSEGV, emergencyStopAfma4) ;
159  signal(SIGKILL, emergencyStopAfma4);
160  signal(SIGQUIT, emergencyStopAfma4);
161 
162  setVerbose(verbose);
163  if (verbose_)
164  std::cout << "Open communication with MotionBlox.\n";
165  try {
166  this->init();
168  }
169  catch(...) {
170  // vpERROR_TRACE("Error caught") ;
171  throw ;
172  }
173  positioningVelocity = defaultPositioningVelocity ;
174 
175  vpRobotAfma4::robotAlreadyCreated = true;
176 
177  return ;
178 }
179 
180 
181 /* ------------------------------------------------------------------------ */
182 /* --- INITIALISATION ----------------------------------------------------- */
183 /* ------------------------------------------------------------------------ */
184 
193 void
195 {
196  int stt;
197  InitTry;
198 
199  // Initialise private variables used to compute the measured velocities
200  q_prev_getvel.resize(4);
201  q_prev_getvel = 0;
202  time_prev_getvel = 0;
203  first_time_getvel = true;
204 
205  // Initialise private variables used to compute the measured displacement
206  q_prev_getdis.resize(4);
207  q_prev_getdis = 0;
208  first_time_getdis = true;
209 
210  // Initialize the firewire connection
211  Try( stt = InitializeConnection(verbose_) );
212 
213  if (stt != SUCCESS) {
214  vpERROR_TRACE ("Cannot open connection with the motionblox.");
216  "Cannot open connection with the motionblox");
217  }
218 
219  // Connect to the servoboard using the servo board GUID
220  Try( stt = InitializeNode_Afma4() );
221 
222  if (stt != SUCCESS) {
223  vpERROR_TRACE ("Cannot open connection with the motionblox.");
225  "Cannot open connection with the motionblox");
226  }
227  Try( PrimitiveRESET_Afma4() );
228 
229  // Look if the power is on or off
230  UInt32 HIPowerStatus;
231  UInt32 EStopStatus;
232  Try( PrimitiveSTATUS_Afma4(NULL, NULL, &EStopStatus, NULL, NULL, NULL,
233  &HIPowerStatus));
234  CAL_Wait(0.1);
235 
236  // Print the robot status
237  if (verbose_) {
238  std::cout << "Robot status: ";
239  switch(EStopStatus) {
240  case ESTOP_AUTO:
241  case ESTOP_MANUAL:
242  if (HIPowerStatus == 0)
243  std::cout << "Power is OFF" << std::endl;
244  else
245  std::cout << "Power is ON" << std::endl;
246  break;
247  case ESTOP_ACTIVATED:
248  std::cout << "Emergency stop is activated" << std::endl;
249  break;
250  default:
251  std::cout << "Sorry there is an error on the emergency chain." << std::endl;
252  std::cout << "You have to call Adept for maintenance..." << std::endl;
253  // Free allocated resources
254  }
255  std::cout << std::endl;
256  }
257  // get real joint min/max from the MotionBlox
258  Try( PrimitiveJOINT_MINMAX_Afma4(_joint_min, _joint_max) );
259 // for (unsigned int i=0; i < njoint; i++) {
260 // printf("axis %d: joint min %lf, max %lf\n", i, _joint_min[i], _joint_max[i]);
261 // }
262 
263  // If an error occur in the low level controller, goto here
264  // CatchPrint();
265  Catch();
266 
267  // Test if an error occurs
268  if (TryStt == -20001)
269  printf("No connection detected. Check if the robot is powered on \n"
270  "and if the firewire link exist between the MotionBlox and this computer.\n");
271  else if (TryStt == -675)
272  printf(" Timeout enabling power...\n");
273 
274  if (TryStt < 0) {
275  // Power off the robot
276  PrimitivePOWEROFF_Afma4();
277  // Free allocated resources
278  ShutDownConnection();
279 
280  std::cout << "Cannot open connection with the motionblox..." << std::endl;
282  "Cannot open connection with the motionblox");
283  }
284  return ;
285 }
286 
287 
288 /* ------------------------------------------------------------------------ */
289 /* --- DESTRUCTOR --------------------------------------------------------- */
290 /* ------------------------------------------------------------------------ */
291 
299 {
300  InitTry;
301 
303 
304  // Look if the power is on or off
305  UInt32 HIPowerStatus;
306  Try( PrimitiveSTATUS_Afma4(NULL, NULL, NULL, NULL, NULL, NULL,
307  &HIPowerStatus));
308  CAL_Wait(0.1);
309 
310 // if (HIPowerStatus == 1) {
311 // fprintf(stdout, "Power OFF the robot\n");
312 // fflush(stdout);
313 
314 // Try( PrimitivePOWEROFF_Afma4() );
315 // }
316 
317  // Free allocated resources
318  ShutDownConnection();
319 
320  vpRobotAfma4::robotAlreadyCreated = false;
321 
322  CatchPrint();
323  return;
324 }
325 
326 
327 
328 
329 
338 {
339  InitTry;
340 
341  switch (newState) {
342  case vpRobot::STATE_STOP: {
344  Try( PrimitiveSTOP_Afma4() );
345  }
346  break;
347  }
350  std::cout << "Change the control mode from velocity to position control.\n";
351  Try( PrimitiveSTOP_Afma4() );
352  }
353  else {
354  //std::cout << "Change the control mode from stop to position control.\n";
355  }
356  this->powerOn();
357  break;
358  }
361  std::cout << "Change the control mode from stop to velocity control.\n";
362  }
363  this->powerOn();
364  break;
365  }
366  default:
367  break ;
368  }
369 
370  CatchPrint();
371 
372  return vpRobot::setRobotState (newState);
373 }
374 
375 /* ------------------------------------------------------------------------ */
376 /* --- STOP --------------------------------------------------------------- */
377 /* ------------------------------------------------------------------------ */
378 
386 void
388 {
389  InitTry;
390  Try( PrimitiveSTOP_Afma4() );
392 
393  CatchPrint();
394  if (TryStt < 0) {
395  vpERROR_TRACE ("Cannot stop robot motion");
397  "Cannot stop robot motion.");
398  }
399 }
400 
401 
411 void
413 {
414  InitTry;
415 
416  // Look if the power is on or off
417  UInt32 HIPowerStatus;
418  UInt32 EStopStatus;
419  bool firsttime = true;
420  unsigned int nitermax = 10;
421 
422  for (unsigned int i=0; i<nitermax; i++) {
423  Try( PrimitiveSTATUS_Afma4(NULL, NULL, &EStopStatus, NULL, NULL, NULL,
424  &HIPowerStatus));
425  if (EStopStatus == ESTOP_AUTO) {
426  break; // exit for loop
427  }
428  else if (EStopStatus == ESTOP_MANUAL) {
429  break; // exit for loop
430  }
431  else if (EStopStatus == ESTOP_ACTIVATED) {
432  if (firsttime) {
433  std::cout << "Emergency stop is activated! \n"
434  << "Check the emergency stop button and push the yellow button before continuing." << std::endl;
435  firsttime = false;
436  }
437  fprintf(stdout, "Remaining time %us \r", nitermax-i);
438  fflush(stdout);
439  CAL_Wait(1);
440  }
441  else {
442  std::cout << "Sorry there is an error on the emergency chain." << std::endl;
443  std::cout << "You have to call Adept for maintenance..." << std::endl;
444  // Free allocated resources
445  ShutDownConnection();
446  exit(0);
447  }
448  }
449 
450  if (EStopStatus == ESTOP_ACTIVATED)
451  std::cout << std::endl;
452 
453  if (EStopStatus == ESTOP_ACTIVATED) {
454  std::cout << "Sorry, cannot power on the robot." << std::endl;
456  "Cannot power on the robot.");
457  }
458 
459  if (HIPowerStatus == 0) {
460  fprintf(stdout, "Power ON the Afma4 robot\n");
461  fflush(stdout);
462 
463  Try( PrimitivePOWERON_Afma4() );
464  }
465 
466  CatchPrint();
467  if (TryStt < 0) {
468  vpERROR_TRACE ("Cannot power on the robot");
470  "Cannot power off the robot.");
471  }
472 }
473 
483 void
485 {
486  InitTry;
487 
488  // Look if the power is on or off
489  UInt32 HIPowerStatus;
490  Try( PrimitiveSTATUS_Afma4(NULL, NULL, NULL, NULL, NULL, NULL,
491  &HIPowerStatus));
492  CAL_Wait(0.1);
493 
494  if (HIPowerStatus == 1) {
495  fprintf(stdout, "Power OFF the Afma4 robot\n");
496  fflush(stdout);
497 
498  Try( PrimitivePOWEROFF_Afma4() );
499  }
500 
501  CatchPrint();
502  if (TryStt < 0) {
503  vpERROR_TRACE ("Cannot power off the robot");
505  "Cannot power off the robot.");
506  }
507 }
508 
520 bool
522 {
523  InitTry;
524  bool status = false;
525  // Look if the power is on or off
526  UInt32 HIPowerStatus;
527  Try( PrimitiveSTATUS_Afma4(NULL, NULL, NULL, NULL, NULL, NULL,
528  &HIPowerStatus));
529  CAL_Wait(0.1);
530 
531  if (HIPowerStatus == 1) {
532  status = true;
533  }
534 
535  CatchPrint();
536  if (TryStt < 0) {
537  vpERROR_TRACE ("Cannot get the power status");
539  "Cannot get the power status.");
540  }
541  return status;
542 }
543 
553 void
555 {
556  vpHomogeneousMatrix cMe ;
557  vpAfma4::get_cMe(cMe) ;
558 
559  cVe.buildFrom(cMe) ;
560 }
561 
571 void
573 {
574  double position[this->njoint];
575  double timestamp;
576 
577  InitTry;
578  Try( PrimitiveACQ_POS_Afma4(position, &timestamp) );
579  CatchPrint();
580 
581  vpColVector q(this->njoint);
582  for (unsigned int i=0; i < njoint; i++)
583  q[i] = position[i];
584 
585  try {
586  vpAfma4::get_cVf(q, cVf) ;
587  }
588  catch(...) {
589  vpERROR_TRACE("catch exception ") ;
590  throw ;
591  }}
592 
603 void
605 {
606  vpAfma4::get_cMe(cMe) ;
607 }
608 
621 void
623 {
624 
625  double position[this->njoint];
626  double timestamp;
627 
628  InitTry;
629  Try( PrimitiveACQ_POS_Afma4(position, &timestamp) );
630  CatchPrint();
631 
632  vpColVector q(this->njoint);
633  for (unsigned int i=0; i < njoint; i++)
634  q[i] = position[i];
635 
636  try {
637  vpAfma4::get_eJe(q, eJe) ;
638  }
639  catch(...) {
640  vpERROR_TRACE("catch exception ") ;
641  throw ;
642  }
643 }
644 
660 {
661  double position[6];
662  double timestamp;
663 
664  InitTry;
665  Try( PrimitiveACQ_POS_Afma4(position, &timestamp) );
666  CatchPrint();
667 
668  vpColVector q(6);
669  for (unsigned int i=0; i < njoint; i++)
670  q[i] = position[i];
671 
672  try {
673  vpAfma4::get_fJe(q, fJe) ;
674  }
675  catch(...) {
676  vpERROR_TRACE("Error caught");
677  throw ;
678  }
679 }
708 void
710 {
711  positioningVelocity = velocity;
712 }
713 
719 double
721 {
722  return positioningVelocity;
723 }
724 
725 
797 void
799  const vpColVector & position )
800 {
801 
803  vpERROR_TRACE ("Robot was not in position-based control\n"
804  "Modification of the robot state");
806  }
807 
808  int error = 0;
809 
810  switch(frame) {
812  vpERROR_TRACE ("Positionning error. Reference frame not implemented");
814  "Positionning error: "
815  "Reference frame not implemented.");
816  break ;
817  case vpRobot::CAMERA_FRAME :
818  vpERROR_TRACE ("Positionning error. Camera frame not implemented");
820  "Positionning error: "
821  "Camera frame not implemented.");
822  break ;
823  case vpRobot::MIXT_FRAME:
824  vpERROR_TRACE ("Positionning error. Mixt frame not implemented");
826  "Positionning error: "
827  "Mixt frame not implemented.");
828  break ;
829 
831  break ;
832 
833  }
834  }
835  if (position.getRows() != this->njoint) {
836  vpERROR_TRACE ("Positionning error: bad vector dimension.");
838  "Positionning error: bad vector dimension.");
839  }
840 
841  InitTry;
842 
843  Try( PrimitiveMOVE_Afma4(position.data, positioningVelocity) );
844  Try( WaitState_Afma4(ETAT_ATTENTE_AFMA4, 1000) );
845 
846  CatchPrint();
847  if (TryStt == InvalidPosition || TryStt == -1023)
848  std::cout << " : Position out of range.\n";
849  else if (TryStt < 0)
850  std::cout << " : Unknown error (see Fabien).\n";
851  else if (error == -1)
852  std::cout << "Position out of range.\n";
853 
854  if (TryStt < 0 || error < 0) {
855  vpERROR_TRACE ("Positionning error.");
857  "Position out of range.");
858  }
859 
860  return ;
861 }
862 
863 
915  const double q1,
916  const double q2,
917  const double q4,
918  const double q5)
919 {
920  try {
921  vpColVector position(this->njoint) ;
922  position[0] = q1 ;
923  position[1] = q2 ;
924  position[2] = q4 ;
925  position[3] = q5 ;
926 
927  setPosition(frame, position) ;
928  }
929  catch(...) {
930  vpERROR_TRACE("Error caught");
931  throw ;
932  }
933 }
934 
964 void vpRobotAfma4::setPosition(const char *filename)
965 {
966  vpColVector q;
967  bool ret;
968 
969  ret = this->readPosFile(filename, q);
970 
971  if (ret == false) {
972  vpERROR_TRACE ("Bad position in \"%s\"", filename);
974  "Bad position in filename.");
975  }
978 }
979 
983 double vpRobotAfma4::getTime() const
984 {
985  double timestamp;
986  PrimitiveACQ_TIME_Afma4(&timestamp);
987  return timestamp;
988 }
989 
1049 void
1051  vpColVector & position, double &timestamp)
1052 {
1053 
1054  InitTry;
1055 
1056  position.resize (this->njoint);
1057 
1058  switch (frame) {
1059  case vpRobot::CAMERA_FRAME : {
1060  position = 0;
1061  return;
1062  }
1063  case vpRobot::ARTICULAR_FRAME : {
1064  double _q[njoint];
1065  Try( PrimitiveACQ_POS_Afma4(_q, &timestamp) );
1066  for (unsigned int i=0; i < this->njoint; i ++) {
1067  position[i] = _q[i];
1068  }
1069 
1070  return;
1071  }
1072  case vpRobot::REFERENCE_FRAME : {
1073  double _q[njoint];
1074  Try( PrimitiveACQ_POS_Afma4(_q, &timestamp) );
1075 
1076  vpColVector q(this->njoint);
1077  for (unsigned int i=0; i < this->njoint; i++)
1078  q[i] = _q[i];
1079 
1080  // Compute fMc
1081  vpHomogeneousMatrix fMc;
1082  vpAfma4::get_fMc(q, fMc);
1083 
1084  // From fMc extract the pose
1085  vpRotationMatrix fRc;
1086  fMc.extract(fRc);
1087  vpRxyzVector rxyz;
1088  rxyz.buildFrom(fRc);
1089 
1090  for (unsigned int i=0; i < 3; i++) {
1091  position[i] = fMc[i][3]; // translation x,y,z
1092  position[i+3] = rxyz[i]; // Euler rotation x,y,z
1093  }
1094  break ;
1095  }
1096  case vpRobot::MIXT_FRAME: {
1097  vpERROR_TRACE ("Cannot get position in mixt frame: not implemented");
1099  "Cannot get position in mixt frame: "
1100  "not implemented");
1101  }
1102  }
1103 
1104  CatchPrint();
1105  if (TryStt < 0) {
1106  vpERROR_TRACE ("Cannot get position.");
1108  "Cannot get position.");
1109  }
1110 
1111  return;
1112 }
1113 
1124  vpColVector &position)
1125 {
1126  double timestamp;
1127  getPosition(frame, position, timestamp);
1128 }
1129 
1176 void
1178  const vpColVector & vel)
1179 {
1180 
1182  {
1183  vpERROR_TRACE ("Cannot send a velocity to the robot "
1184  "use setRobotState(vpRobot::STATE_VELOCITY_CONTROL) first) ");
1186  "Cannot send a velocity to the robot "
1187  "use setRobotState(vpRobot::STATE_VELOCITY_CONTROL) first) ");
1188  }
1189 
1190  // Check the dimension of the velocity vector to see if it is
1191  // compatible with the requested frame
1192  switch(frame) {
1193  case vpRobot::CAMERA_FRAME : {
1194  //if (vel.getRows() != 2) {
1195  if (vel.getRows() != 6) {
1196  vpERROR_TRACE ("Bad dimension of the velocity vector in camera frame");
1198  "Bad dimension of the velocity vector "
1199  "in camera frame");
1200  }
1201  break ;
1202  }
1203  case vpRobot::ARTICULAR_FRAME : {
1204  if (vel.getRows() != this->njoint) {
1205  vpERROR_TRACE ("Bad dimension of the articular velocity vector");
1207  "Bad dimension of the articular "
1208  "velocity vector ");
1209  }
1210  break ;
1211  }
1212  case vpRobot::REFERENCE_FRAME : {
1213  vpERROR_TRACE ("Cannot send a velocity to the robot "
1214  "in the reference frame: "
1215  "functionality not implemented");
1217  "Cannot send a velocity to the robot "
1218  "in the reference frame:"
1219  "functionality not implemented");
1220  }
1221  case vpRobot::MIXT_FRAME : {
1222  vpERROR_TRACE ("Cannot send a velocity to the robot "
1223  "in the mixt frame: "
1224  "functionality not implemented");
1226  "Cannot send a velocity to the robot "
1227  "in the mixt frame:"
1228  "functionality not implemented");
1229  }
1230  default: {
1231  vpERROR_TRACE ("Error in spec of vpRobot. "
1232  "Case not taken in account.");
1234  "Cannot send a velocity to the robot ");
1235  }
1236  }
1237 
1238 
1239  //
1240  // Velocities saturation with normalization
1241  //
1242  vpColVector joint_vel(this->njoint);
1243 
1244  // Case of the camera frame where we control only 2 dof
1245  if (frame == vpRobot::CAMERA_FRAME) {
1246  vpColVector vel_max(6);
1247 
1248  for (unsigned int i=0; i<3; i++) {
1249  vel_max[i] = getMaxTranslationVelocity();
1250  vel_max[i+3] = getMaxRotationVelocity();
1251  }
1252 
1253  vpColVector velocity = vpRobot::saturateVelocities(vel, vel_max, true);
1254 
1255 #if 0 // ok
1256  vpMatrix eJe(4,6);
1257  eJe = 0;
1258  eJe[2][4] = -1;
1259  eJe[3][3] = 1;
1260 
1261  joint_vel = eJe * velocity; // Compute the articular velocity
1262 #endif
1263  vpColVector q;
1265  vpMatrix fJe_inverse;
1266  get_fJe_inverse(q, fJe_inverse);
1267  vpHomogeneousMatrix fMe;
1268  get_fMe(q, fMe);
1270  t=0;
1271  vpRotationMatrix fRe;
1272  fMe.extract(fRe);
1273  vpVelocityTwistMatrix fVe(t, fRe);
1274  // compute the inverse jacobian in the end-effector frame
1275  vpMatrix eJe_inverse = fJe_inverse * fVe;
1276 
1277  // Transform the velocities from camera to end-effector frame
1279  eVc.buildFrom(this->_eMc);
1280  joint_vel = eJe_inverse * eVc * velocity;
1281 
1282  // printf("Vitesse art: %f %f %f %f\n", joint_vel[0], joint_vel[1],
1283  // joint_vel[2], joint_vel[3]);
1284  }
1285 
1286  // Case of the joint control where we control all the joints
1287  else if (frame == vpRobot::ARTICULAR_FRAME) {
1288 
1289  vpColVector vel_max(4);
1290 
1291  vel_max[0] = getMaxRotationVelocity();
1292  vel_max[1] = getMaxTranslationVelocity();
1293  vel_max[2] = getMaxRotationVelocity();
1294  vel_max[3] = getMaxRotationVelocity();
1295 
1296  joint_vel = vpRobot::saturateVelocities(vel, vel_max, true);
1297  }
1298 
1299  InitTry;
1300 
1301  // Send a joint velocity to the low level controller
1302  Try( PrimitiveMOVESPEED_Afma4(joint_vel.data) );
1303 
1304  Catch();
1305  if (TryStt < 0) {
1306  if (TryStt == VelStopOnJoint) {
1307  UInt32 axisInJoint[njoint];
1308  PrimitiveSTATUS_Afma4(NULL, NULL, NULL, NULL, NULL, axisInJoint, NULL);
1309  for (unsigned int i=0; i < njoint; i ++) {
1310  if (axisInJoint[i])
1311  std::cout << "\nWarning: Velocity control stopped: axis "
1312  << i+1 << " on joint limit!" <<std::endl;
1313  }
1314  }
1315  else {
1316  printf("\n%s(%d): Error %d", __FUNCTION__, TryLine, TryStt);
1317  if (TryString != NULL) {
1318  // The statement is in TryString, but we need to check the validity
1319  printf(" Error sentence %s\n", TryString); // Print the TryString
1320  }
1321  else {
1322  printf("\n");
1323  }
1324  }
1325  }
1326 
1327  return;
1328 }
1329 
1330 /* ------------------------------------------------------------------------ */
1331 /* --- GET ---------------------------------------------------------------- */
1332 /* ------------------------------------------------------------------------ */
1333 
1334 
1382 void
1384  vpColVector & velocity, double &timestamp)
1385 {
1386 
1387  switch (frame) {
1389  velocity.resize (this->njoint);
1390  break;
1391  default:
1392  velocity.resize (6);
1393  }
1394 
1395  velocity = 0;
1396 
1397  double q[4];
1398  vpColVector q_cur(4);
1399  vpHomogeneousMatrix fMc_cur;
1400  vpHomogeneousMatrix cMc; // camera displacement
1401  double time_cur;
1402 
1403  InitTry;
1404 
1405  // Get the current joint position
1406  Try( PrimitiveACQ_POS_Afma4(q, &timestamp) );
1407  time_cur = timestamp;
1408 
1409  for (unsigned int i=0; i < this->njoint; i ++) {
1410  q_cur[i] = q[i];
1411  }
1412 
1413  // Get the camera pose from the direct kinematics
1414  vpAfma4::get_fMc(q_cur, fMc_cur);
1415 
1416  if ( ! first_time_getvel ) {
1417 
1418  switch (frame) {
1419  case vpRobot::CAMERA_FRAME: {
1420  // Compute the displacement of the camera since the previous call
1421  cMc = fMc_prev_getvel.inverse() * fMc_cur;
1422 
1423  // Compute the velocity of the camera from this displacement
1424  velocity = vpExponentialMap::inverse(cMc, time_cur - time_prev_getvel);
1425 
1426  break ;
1427  }
1428 
1429  case vpRobot::ARTICULAR_FRAME: {
1430  velocity = (q_cur - q_prev_getvel) / (time_cur - time_prev_getvel);
1431  break ;
1432  }
1433 
1434  case vpRobot::REFERENCE_FRAME: {
1435  // Compute the displacement of the camera since the previous call
1436  cMc = fMc_prev_getvel.inverse() * fMc_cur;
1437 
1438  // Compute the velocity of the camera from this displacement
1439  vpColVector v;
1440  v = vpExponentialMap::inverse(cMc, time_cur - time_prev_getvel);
1441 
1442  // Express this velocity in the reference frame
1443  vpVelocityTwistMatrix fVc(fMc_cur);
1444  velocity = fVc * v;
1445 
1446  break ;
1447  }
1448 
1449  case vpRobot::MIXT_FRAME: {
1450  vpERROR_TRACE ("Cannot get a velocity in the mixt frame: "
1451  "functionality not implemented");
1453  "Cannot get a displacement in the mixt frame:"
1454  "functionality not implemented");
1455 
1456  break ;
1457  }
1458  }
1459  }
1460  else {
1461  first_time_getvel = false;
1462  }
1463 
1464  // Memorize the camera pose for the next call
1465  fMc_prev_getvel = fMc_cur;
1466 
1467  // Memorize the joint position for the next call
1468  q_prev_getvel = q_cur;
1469 
1470  // Memorize the time associated to the joint position for the next call
1471  time_prev_getvel = time_cur;
1472 
1473 
1474  CatchPrint();
1475  if (TryStt < 0) {
1476  vpERROR_TRACE ("Cannot get velocity.");
1478  "Cannot get velocity.");
1479  }
1480 }
1481 
1491  vpColVector & velocity)
1492 {
1493  double timestamp;
1494  getVelocity(frame, velocity, timestamp);
1495 }
1496 
1497 
1498 
1540 {
1541  vpColVector velocity;
1542  getVelocity (frame, velocity, timestamp);
1543 
1544  return velocity;
1545 }
1546 
1556 {
1557  vpColVector velocity;
1558  double timestamp;
1559  getVelocity (frame, velocity, timestamp);
1560 
1561  return velocity;
1562 }
1563 
1614 bool
1615 vpRobotAfma4::readPosFile(const std::string &filename, vpColVector &q)
1616 {
1617  std::ifstream fd(filename.c_str(), std::ios::in);
1618 
1619  if(! fd.is_open()) {
1620  return false;
1621  }
1622 
1623  std::string line;
1624  std::string key("R:");
1625  std::string id("#AFMA4 - Position");
1626  bool pos_found = false;
1627  int lineNum = 0;
1628 
1629  q.resize(njoint);
1630 
1631  while(std::getline(fd, line)) {
1632  lineNum ++;
1633  if (lineNum == 1) {
1634  if(! (line.compare(0, id.size(), id) == 0)) { // check if Afma4 position file
1635  std::cout << "Error: this position file " << filename << " is not for Afma4 robot" << std::endl;
1636  return false;
1637  }
1638  }
1639  if((line.compare(0, 1, "#") == 0)) { // skip comment
1640  continue;
1641  }
1642  if((line.compare(0, key.size(), key) == 0)) { // decode position
1643  // check if there are at least njoint values in the line
1644  std::vector<std::string> chain = vpIoTools::splitChain(line, std::string(" "));
1645  if (chain.size() < njoint+1) // try to split with tab separator
1646  chain = vpIoTools::splitChain(line, std::string("\t"));
1647  if(chain.size() < njoint+1)
1648  continue;
1649 
1650  std::istringstream ss(line);
1651  std::string key_;
1652  ss >> key_;
1653  for (unsigned int i=0; i< njoint; i++)
1654  ss >> q[i];
1655  pos_found = true;
1656  break;
1657  }
1658  }
1659 
1660  // converts rotations from degrees into radians
1661  q[0] = vpMath::rad(q[0]);
1662  q[2] = vpMath::rad(q[2]);
1663  q[3] = vpMath::rad(q[3]);
1664 
1665  fd.close();
1666 
1667  if (!pos_found) {
1668  std::cout << "Error: unable to find a position for Afma4 robot in " << filename << std::endl;
1669  return false;
1670  }
1671 
1672  return true;
1673 }
1674 
1698 bool
1699 vpRobotAfma4::savePosFile(const std::string &filename, const vpColVector &q)
1700 {
1701 
1702  FILE * fd ;
1703  fd = fopen(filename.c_str(), "w") ;
1704  if (fd == NULL)
1705  return false;
1706 
1707  fprintf(fd, "\
1708 #AFMA4 - Position - Version 2.01\n\
1709 #\n\
1710 # R: X Y A B\n\
1711 # Joint position: X : rotation of the turret in degrees (joint 1)\n\
1712 # Y : vertical translation in meters (joint 2)\n\
1713 # A : pan rotation of the camera in degrees (joint 4)\n\
1714 # B : tilt rotation of the camera in degrees (joint 5)\n\
1715 #\n\n");
1716 
1717  // Save positions in mm and deg
1718  fprintf(fd, "R: %lf %lf %lf %lf\n",
1719  vpMath::deg(q[0]),
1720  q[1],
1721  vpMath::deg(q[2]),
1722  vpMath::deg(q[3]));
1723 
1724  fclose(fd) ;
1725  return (true);
1726 }
1727 
1738 void
1739 vpRobotAfma4::move(const char *filename)
1740 {
1741  vpColVector q;
1742 
1743  this->readPosFile(filename, q) ;
1745  this->setPositioningVelocity(10);
1747 }
1748 
1762 void
1763 vpRobotAfma4::getCameraDisplacement(vpColVector &displacement)
1764 {
1765  getDisplacement(vpRobot::CAMERA_FRAME, displacement);
1766 }
1778 void
1779 vpRobotAfma4::getArticularDisplacement(vpColVector &displacement)
1780 {
1782 }
1783 
1804 void
1806  vpColVector &displacement)
1807 {
1808  displacement.resize (6);
1809  displacement = 0;
1810 
1811  double q[6];
1812  vpColVector q_cur(6);
1813  double timestamp;
1814 
1815  InitTry;
1816 
1817  // Get the current joint position
1818  Try( PrimitiveACQ_POS_Afma4(q, &timestamp) );
1819  for (unsigned int i=0; i < njoint; i ++) {
1820  q_cur[i] = q[i];
1821  }
1822 
1823  if ( ! first_time_getdis ) {
1824  switch (frame) {
1825  case vpRobot::CAMERA_FRAME: {
1826  std::cout << "getDisplacement() CAMERA_FRAME not implemented\n";
1827  return;
1828  }
1829 
1830  case vpRobot::ARTICULAR_FRAME: {
1831  displacement = q_cur - q_prev_getdis;
1832  break ;
1833  }
1834 
1835  case vpRobot::REFERENCE_FRAME: {
1836  std::cout << "getDisplacement() REFERENCE_FRAME not implemented\n";
1837  return;
1838  }
1839 
1840  case vpRobot::MIXT_FRAME: {
1841  std::cout << "getDisplacement() MIXT_FRAME not implemented\n";
1842  return;
1843  }
1844  }
1845  }
1846  else {
1847  first_time_getdis = false;
1848  }
1849 
1850  // Memorize the joint position for the next call
1851  q_prev_getdis = q_cur;
1852 
1853  CatchPrint();
1854  if (TryStt < 0) {
1855  vpERROR_TRACE ("Cannot get velocity.");
1857  "Cannot get velocity.");
1858  }
1859 }
1860 
1861 #elif !defined(VISP_BUILD_SHARED_LIBS)
1862 // Work arround to avoid warning: libvisp_robot.a(vpRobotAfma4.cpp.o) has no symbols
1863 void dummy_vpRobotAfma4() {};
1864 #endif
1865 
static vpColVector inverse(const vpHomogeneousMatrix &M)
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:97
vpRxyzVector buildFrom(const vpRotationMatrix &R)
vpHomogeneousMatrix get_fMc(const vpColVector &q) const
Definition: vpAfma4.cpp:185
Error that can be emited by the vpRobot class and its derivates.
void get_fMe(const vpColVector &q, vpHomogeneousMatrix &fMe) const
Definition: vpAfma4.cpp:268
void get_cMe(vpHomogeneousMatrix &cMe) const
Definition: vpAfma4.cpp:319
Implementation of an homogeneous matrix and operations on such kind of matrices.
void setVerbose(bool verbose)
Definition: vpRobot.h:157
virtual ~vpRobotAfma4(void)
#define vpERROR_TRACE
Definition: vpDebug.h:391
void init(void)
void setVelocity(const vpRobot::vpControlFrameType frame, const vpColVector &velocity)
vpHomogeneousMatrix _eMc
Definition: vpAfma4.h:155
double getMaxTranslationVelocity(void) const
Definition: vpRobot.cpp:250
Initialize the position controller.
Definition: vpRobot.h:69
double getTime() const
Class that defines a generic virtual robot.
Definition: vpRobot.h:58
static vpColVector saturateVelocities(const vpColVector &v_in, const vpColVector &v_max, bool verbose=false)
Definition: vpRobot.cpp:163
Type * data
Address of the first element of the data array.
Definition: vpArray2D.h:84
vpControlFrameType
Definition: vpRobot.h:76
void get_cVf(const vpColVector &q, vpVelocityTwistMatrix &cVf) const
Definition: vpAfma4.cpp:363
double getMaxRotationVelocity(void) const
Definition: vpRobot.cpp:275
void move(const char *filename)
virtual vpRobotStateType setRobotState(const vpRobot::vpRobotStateType newState)
Definition: vpRobot.cpp:201
void get_eJe(const vpColVector &q, vpMatrix &eJe) const
Definition: vpAfma4.cpp:411
Implementation of a rotation matrix and operations on such kind of matrices.
void setPosition(const vpRobot::vpControlFrameType frame, const vpColVector &position)
void get_cMe(vpHomogeneousMatrix &cMe) const
double _joint_max[4]
Definition: vpAfma4.h:148
Initialize the velocity controller.
Definition: vpRobot.h:68
vpRobotStateType
Definition: vpRobot.h:64
bool verbose_
Definition: vpRobot.h:113
void getPosition(const vpRobot::vpControlFrameType frame, vpColVector &position)
void setPositioningVelocity(const double velocity)
vpVelocityTwistMatrix buildFrom(const vpTranslationVector &t, const vpRotationMatrix &R)
double _joint_min[4]
Definition: vpAfma4.h:149
static bool readPosFile(const std::string &filename, vpColVector &q)
static const unsigned int njoint
Number of joint.
Definition: vpAfma4.h:141
Modelisation of Irisa's cylindrical robot named Afma4.
Definition: vpAfma4.h:108
void extract(vpRotationMatrix &R) const
static std::vector< std::string > splitChain(const std::string &chain, const std::string &sep)
Definition: vpIoTools.cpp:1596
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
static bool savePosFile(const std::string &filename, const vpColVector &q)
static double rad(double deg)
Definition: vpMath.h:104
void get_eJe(vpMatrix &eJe)
vpRobot::vpRobotStateType setRobotState(vpRobot::vpRobotStateType newState)
static double deg(double rad)
Definition: vpMath.h:97
vpMatrix eJe
robot Jacobian expressed in the end-effector frame
Definition: vpRobot.h:101
void getDisplacement(vpRobot::vpControlFrameType frame, vpColVector &displacement)
Implementation of column vector and the associated operations.
Definition: vpColVector.h:72
vpHomogeneousMatrix inverse() const
void getVelocity(const vpRobot::vpControlFrameType frame, vpColVector &velocity)
void get_fJe_inverse(const vpColVector &q, vpMatrix &fJe_inverse) const
Definition: vpAfma4.cpp:521
virtual vpRobotStateType getRobotState(void) const
Definition: vpRobot.h:141
void get_fJe(vpMatrix &fJe)
Implementation of a rotation vector as Euler angle minimal representation.
Definition: vpRxyzVector.h:154
bool getPowerState()
void get_fJe(const vpColVector &q, vpMatrix &fJe) const
Definition: vpAfma4.cpp:465
double getPositioningVelocity(void)
void get_cVf(vpVelocityTwistMatrix &cVf) const
void get_cVe(vpVelocityTwistMatrix &cVe) const
static const double defaultPositioningVelocity
Definition: vpRobotAfma4.h:223
Class that consider the case of a translation vector.
void resize(const unsigned int i, const bool flagNullify=true)
Definition: vpColVector.h:225