Visual Servoing Platform  version 3.0.0
vpRobotAfma4.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 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/robot/vpRobotAfma4.h>
53 
54 /* ---------------------------------------------------------------------- */
55 /* --- STATIC ----------------------------------------------------------- */
56 /* ---------------------------------------------------------------------- */
57 
58 bool vpRobotAfma4::robotAlreadyCreated = false;
59 
68 
69 
70 /* ---------------------------------------------------------------------- */
71 /* --- EMERGENCY STOP --------------------------------------------------- */
72 /* ---------------------------------------------------------------------- */
73 
81 void emergencyStopAfma4(int signo)
82 {
83  std::cout << "Stop the Afma4 application by signal ("
84  << signo << "): " << (char)7 ;
85  switch(signo)
86  {
87  case SIGINT:
88  std::cout << "SIGINT (stop by ^C) " << std::endl ; break ;
89  case SIGBUS:
90  std::cout <<"SIGBUS (stop due to a bus error) " << std::endl ; break ;
91  case SIGSEGV:
92  std::cout <<"SIGSEGV (stop due to a segmentation fault) " << std::endl ; break ;
93  case SIGKILL:
94  std::cout <<"SIGKILL (stop by CTRL \\) " << std::endl ; break ;
95  case SIGQUIT:
96  std::cout <<"SIGQUIT " << std::endl ; break ;
97  default :
98  std::cout << signo << std::endl ;
99  }
100  // std::cout << "Emergency stop called\n";
101  // PrimitiveESTOP_Afma4();
102  PrimitiveSTOP_Afma4();
103  std::cout << "Robot was stopped\n";
104 
105  // Free allocated resources
106  // ShutDownConnection(); // Some times cannot exit here when Ctrl-C
107 
108  fprintf(stdout, "Application ");
109  fflush(stdout);
110  kill(getpid(), SIGKILL);
111  exit(1) ;
112 }
113 
114 
115 /* ---------------------------------------------------------------------- */
116 /* --- CONSTRUCTOR ------------------------------------------------------ */
117 /* ---------------------------------------------------------------------- */
118 
130 vpRobotAfma4::vpRobotAfma4 (bool verbose)
131  :
132  vpAfma4 (),
133  vpRobot ()
134 {
135 
136  /*
137  #define SIGHUP 1 // hangup
138  #define SIGINT 2 // interrupt (rubout)
139  #define SIGQUIT 3 // quit (ASCII FS)
140  #define SIGILL 4 // illegal instruction (not reset when caught)
141  #define SIGTRAP 5 // trace trap (not reset when caught)
142  #define SIGIOT 6 // IOT instruction
143  #define SIGABRT 6 // used by abort, replace SIGIOT in the future
144  #define SIGEMT 7 // EMT instruction
145  #define SIGFPE 8 // floating point exception
146  #define SIGKILL 9 // kill (cannot be caught or ignored)
147  #define SIGBUS 10 // bus error
148  #define SIGSEGV 11 // segmentation violation
149  #define SIGSYS 12 // bad argument to system call
150  #define SIGPIPE 13 // write on a pipe with no one to read it
151  #define SIGALRM 14 // alarm clock
152  #define SIGTERM 15 // software termination signal from kill
153  */
154 
155  signal(SIGINT, emergencyStopAfma4);
156  signal(SIGBUS, emergencyStopAfma4) ;
157  signal(SIGSEGV, emergencyStopAfma4) ;
158  signal(SIGKILL, emergencyStopAfma4);
159  signal(SIGQUIT, emergencyStopAfma4);
160 
161  setVerbose(verbose);
162  if (verbose_)
163  std::cout << "Open communication with MotionBlox.\n";
164  try {
165  this->init();
167  }
168  catch(...) {
169  // vpERROR_TRACE("Error caught") ;
170  throw ;
171  }
172  positioningVelocity = defaultPositioningVelocity ;
173 
174  vpRobotAfma4::robotAlreadyCreated = true;
175 
176  return ;
177 }
178 
179 
180 /* ------------------------------------------------------------------------ */
181 /* --- INITIALISATION ----------------------------------------------------- */
182 /* ------------------------------------------------------------------------ */
183 
192 void
194 {
195  int stt;
196  InitTry;
197 
198  // Initialise private variables used to compute the measured velocities
199  q_prev_getvel.resize(4);
200  q_prev_getvel = 0;
201  time_prev_getvel = 0;
202  first_time_getvel = true;
203 
204  // Initialise private variables used to compute the measured displacement
205  q_prev_getdis.resize(4);
206  q_prev_getdis = 0;
207  first_time_getdis = true;
208 
209  // Initialize the firewire connection
210  Try( stt = InitializeConnection(verbose_) );
211 
212  if (stt != SUCCESS) {
213  vpERROR_TRACE ("Cannot open connexion with the motionblox.");
215  "Cannot open connexion with the motionblox");
216  }
217 
218  // Connect to the servoboard using the servo board GUID
219  Try( stt = InitializeNode_Afma4() );
220 
221  if (stt != SUCCESS) {
222  vpERROR_TRACE ("Cannot open connexion with the motionblox.");
224  "Cannot open connexion with the motionblox");
225  }
226  Try( PrimitiveRESET_Afma4() );
227 
228  // Look if the power is on or off
229  UInt32 HIPowerStatus;
230  UInt32 EStopStatus;
231  Try( PrimitiveSTATUS_Afma4(NULL, NULL, &EStopStatus, NULL, NULL, NULL,
232  &HIPowerStatus));
233  CAL_Wait(0.1);
234 
235  // Print the robot status
236  if (verbose_) {
237  std::cout << "Robot status: ";
238  switch(EStopStatus) {
239  case ESTOP_AUTO:
240  case ESTOP_MANUAL:
241  if (HIPowerStatus == 0)
242  std::cout << "Power is OFF" << std::endl;
243  else
244  std::cout << "Power is ON" << std::endl;
245  break;
246  case ESTOP_ACTIVATED:
247  std::cout << "Emergency stop is activated" << std::endl;
248  break;
249  default:
250  std::cout << "Sorry there is an error on the emergency chain." << std::endl;
251  std::cout << "You have to call Adept for maintenance..." << std::endl;
252  // Free allocated resources
253  }
254  std::cout << std::endl;
255  }
256  // get real joint min/max from the MotionBlox
257  Try( PrimitiveJOINT_MINMAX_Afma4(_joint_min, _joint_max) );
258 // for (unsigned int i=0; i < njoint; i++) {
259 // printf("axis %d: joint min %lf, max %lf\n", i, _joint_min[i], _joint_max[i]);
260 // }
261 
262  // If an error occur in the low level controller, goto here
263  // CatchPrint();
264  Catch();
265 
266  // Test if an error occurs
267  if (TryStt == -20001)
268  printf("No connection detected. Check if the robot is powered on \n"
269  "and if the firewire link exist between the MotionBlox and this computer.\n");
270  else if (TryStt == -675)
271  printf(" Timeout enabling power...\n");
272 
273  if (TryStt < 0) {
274  // Power off the robot
275  PrimitivePOWEROFF_Afma4();
276  // Free allocated resources
277  ShutDownConnection();
278 
279  std::cout << "Cannot open connexion with the motionblox..." << std::endl;
281  "Cannot open connexion with the motionblox");
282  }
283  return ;
284 }
285 
286 
287 /* ------------------------------------------------------------------------ */
288 /* --- DESTRUCTOR --------------------------------------------------------- */
289 /* ------------------------------------------------------------------------ */
290 
298 {
299  InitTry;
300 
302 
303  // Look if the power is on or off
304  UInt32 HIPowerStatus;
305  Try( PrimitiveSTATUS_Afma4(NULL, NULL, NULL, NULL, NULL, NULL,
306  &HIPowerStatus));
307  CAL_Wait(0.1);
308 
309 // if (HIPowerStatus == 1) {
310 // fprintf(stdout, "Power OFF the robot\n");
311 // fflush(stdout);
312 
313 // Try( PrimitivePOWEROFF_Afma4() );
314 // }
315 
316  // Free allocated resources
317  ShutDownConnection();
318 
319  vpRobotAfma4::robotAlreadyCreated = false;
320 
321  CatchPrint();
322  return;
323 }
324 
325 
326 
327 
328 
337 {
338  InitTry;
339 
340  switch (newState) {
341  case vpRobot::STATE_STOP: {
343  Try( PrimitiveSTOP_Afma4() );
344  }
345  break;
346  }
349  std::cout << "Change the control mode from velocity to position control.\n";
350  Try( PrimitiveSTOP_Afma4() );
351  }
352  else {
353  //std::cout << "Change the control mode from stop to position control.\n";
354  }
355  this->powerOn();
356  break;
357  }
360  std::cout << "Change the control mode from stop to velocity control.\n";
361  }
362  this->powerOn();
363  break;
364  }
365  default:
366  break ;
367  }
368 
369  CatchPrint();
370 
371  return vpRobot::setRobotState (newState);
372 }
373 
374 /* ------------------------------------------------------------------------ */
375 /* --- STOP --------------------------------------------------------------- */
376 /* ------------------------------------------------------------------------ */
377 
385 void
387 {
388  InitTry;
389  Try( PrimitiveSTOP_Afma4() );
391 
392  CatchPrint();
393  if (TryStt < 0) {
394  vpERROR_TRACE ("Cannot stop robot motion");
396  "Cannot stop robot motion.");
397  }
398 }
399 
400 
410 void
412 {
413  InitTry;
414 
415  // Look if the power is on or off
416  UInt32 HIPowerStatus;
417  UInt32 EStopStatus;
418  bool firsttime = true;
419  unsigned int nitermax = 10;
420 
421  for (unsigned int i=0; i<nitermax; i++) {
422  Try( PrimitiveSTATUS_Afma4(NULL, NULL, &EStopStatus, NULL, NULL, NULL,
423  &HIPowerStatus));
424  if (EStopStatus == ESTOP_AUTO) {
425  break; // exit for loop
426  }
427  else if (EStopStatus == ESTOP_MANUAL) {
428  break; // exit for loop
429  }
430  else if (EStopStatus == ESTOP_ACTIVATED) {
431  if (firsttime) {
432  std::cout << "Emergency stop is activated! \n"
433  << "Check the emergency stop button and push the yellow button before continuing." << std::endl;
434  firsttime = false;
435  }
436  fprintf(stdout, "Remaining time %ds \r", nitermax-i);
437  fflush(stdout);
438  CAL_Wait(1);
439  }
440  else {
441  std::cout << "Sorry there is an error on the emergency chain." << std::endl;
442  std::cout << "You have to call Adept for maintenance..." << std::endl;
443  // Free allocated resources
444  ShutDownConnection();
445  exit(0);
446  }
447  }
448 
449  if (EStopStatus == ESTOP_ACTIVATED)
450  std::cout << std::endl;
451 
452  if (EStopStatus == ESTOP_ACTIVATED) {
453  std::cout << "Sorry, cannot power on the robot." << std::endl;
455  "Cannot power on the robot.");
456  }
457 
458  if (HIPowerStatus == 0) {
459  fprintf(stdout, "Power ON the Afma4 robot\n");
460  fflush(stdout);
461 
462  Try( PrimitivePOWERON_Afma4() );
463  }
464 
465  CatchPrint();
466  if (TryStt < 0) {
467  vpERROR_TRACE ("Cannot power on the robot");
469  "Cannot power off the robot.");
470  }
471 }
472 
482 void
484 {
485  InitTry;
486 
487  // Look if the power is on or off
488  UInt32 HIPowerStatus;
489  Try( PrimitiveSTATUS_Afma4(NULL, NULL, NULL, NULL, NULL, NULL,
490  &HIPowerStatus));
491  CAL_Wait(0.1);
492 
493  if (HIPowerStatus == 1) {
494  fprintf(stdout, "Power OFF the Afma4 robot\n");
495  fflush(stdout);
496 
497  Try( PrimitivePOWEROFF_Afma4() );
498  }
499 
500  CatchPrint();
501  if (TryStt < 0) {
502  vpERROR_TRACE ("Cannot power off the robot");
504  "Cannot power off the robot.");
505  }
506 }
507 
519 bool
521 {
522  InitTry;
523  bool status = false;
524  // Look if the power is on or off
525  UInt32 HIPowerStatus;
526  Try( PrimitiveSTATUS_Afma4(NULL, NULL, NULL, NULL, NULL, NULL,
527  &HIPowerStatus));
528  CAL_Wait(0.1);
529 
530  if (HIPowerStatus == 1) {
531  status = true;
532  }
533 
534  CatchPrint();
535  if (TryStt < 0) {
536  vpERROR_TRACE ("Cannot get the power status");
538  "Cannot get the power status.");
539  }
540  return status;
541 }
542 
552 void
554 {
555  vpHomogeneousMatrix cMe ;
556  vpAfma4::get_cMe(cMe) ;
557 
558  cVe.buildFrom(cMe) ;
559 }
560 
570 void
572 {
573  double position[this->njoint];
574  double timestamp;
575 
576  InitTry;
577  Try( PrimitiveACQ_POS_Afma4(position, &timestamp) );
578  CatchPrint();
579 
580  vpColVector q(this->njoint);
581  for (unsigned int i=0; i < njoint; i++)
582  q[i] = position[i];
583 
584  try {
585  vpAfma4::get_cVf(q, cVf) ;
586  }
587  catch(...) {
588  vpERROR_TRACE("catch exception ") ;
589  throw ;
590  }}
591 
602 void
604 {
605  vpAfma4::get_cMe(cMe) ;
606 }
607 
620 void
622 {
623 
624  double position[this->njoint];
625  double timestamp;
626 
627  InitTry;
628  Try( PrimitiveACQ_POS_Afma4(position, &timestamp) );
629  CatchPrint();
630 
631  vpColVector q(this->njoint);
632  for (unsigned int i=0; i < njoint; i++)
633  q[i] = position[i];
634 
635  try {
636  vpAfma4::get_eJe(q, eJe) ;
637  }
638  catch(...) {
639  vpERROR_TRACE("catch exception ") ;
640  throw ;
641  }
642 }
643 
659 {
660  double position[6];
661  double timestamp;
662 
663  InitTry;
664  Try( PrimitiveACQ_POS_Afma4(position, &timestamp) );
665  CatchPrint();
666 
667  vpColVector q(6);
668  for (unsigned int i=0; i < njoint; i++)
669  q[i] = position[i];
670 
671  try {
672  vpAfma4::get_fJe(q, fJe) ;
673  }
674  catch(...) {
675  vpERROR_TRACE("Error caught");
676  throw ;
677  }
678 }
707 void
709 {
710  positioningVelocity = velocity;
711 }
712 
718 double
720 {
721  return positioningVelocity;
722 }
723 
724 
796 void
798  const vpColVector & position )
799 {
800 
802  vpERROR_TRACE ("Robot was not in position-based control\n"
803  "Modification of the robot state");
805  }
806 
807  int error = 0;
808 
809  switch(frame) {
811  vpERROR_TRACE ("Positionning error. Reference frame not implemented");
813  "Positionning error: "
814  "Reference frame not implemented.");
815  break ;
816  case vpRobot::CAMERA_FRAME :
817  vpERROR_TRACE ("Positionning error. Camera frame not implemented");
819  "Positionning error: "
820  "Camera frame not implemented.");
821  break ;
822  case vpRobot::MIXT_FRAME:
823  vpERROR_TRACE ("Positionning error. Mixt frame not implemented");
825  "Positionning error: "
826  "Mixt frame not implemented.");
827  break ;
828 
830  break ;
831 
832  }
833  }
834  if (position.getRows() != this->njoint) {
835  vpERROR_TRACE ("Positionning error: bad vector dimension.");
837  "Positionning error: bad vector dimension.");
838  }
839 
840  InitTry;
841 
842  Try( PrimitiveMOVE_Afma4(position.data, positioningVelocity) );
843  Try( WaitState_Afma4(ETAT_ATTENTE_AFMA4, 1000) );
844 
845  CatchPrint();
846  if (TryStt == InvalidPosition || TryStt == -1023)
847  std::cout << " : Position out of range.\n";
848  else if (TryStt < 0)
849  std::cout << " : Unknown error (see Fabien).\n";
850  else if (error == -1)
851  std::cout << "Position out of range.\n";
852 
853  if (TryStt < 0 || error < 0) {
854  vpERROR_TRACE ("Positionning error.");
856  "Position out of range.");
857  }
858 
859  return ;
860 }
861 
862 
914  const double q1,
915  const double q2,
916  const double q4,
917  const double q5)
918 {
919  try {
920  vpColVector position(this->njoint) ;
921  position[0] = q1 ;
922  position[1] = q2 ;
923  position[2] = q4 ;
924  position[3] = q5 ;
925 
926  setPosition(frame, position) ;
927  }
928  catch(...) {
929  vpERROR_TRACE("Error caught");
930  throw ;
931  }
932 }
933 
934 
935 
936 
966 void vpRobotAfma4::setPosition(const char *filename)
967 {
968  vpColVector q;
969  bool ret;
970 
971  ret = this->readPosFile(filename, q);
972 
973  if (ret == false) {
974  vpERROR_TRACE ("Bad position in \"%s\"", filename);
976  "Bad position in filename.");
977  }
980 }
981 
985 double vpRobotAfma4::getTime() const
986 {
987  double timestamp;
988  PrimitiveACQ_TIME_Afma4(&timestamp);
989  return timestamp;
990 }
991 
1051 void
1053  vpColVector & position, double &timestamp)
1054 {
1055 
1056  InitTry;
1057 
1058  position.resize (this->njoint);
1059 
1060  switch (frame) {
1061  case vpRobot::CAMERA_FRAME : {
1062  position = 0;
1063  return;
1064  }
1065  case vpRobot::ARTICULAR_FRAME : {
1066  double _q[njoint];
1067  Try( PrimitiveACQ_POS_Afma4(_q, &timestamp) );
1068  for (unsigned int i=0; i < this->njoint; i ++) {
1069  position[i] = _q[i];
1070  }
1071 
1072  return;
1073  }
1074  case vpRobot::REFERENCE_FRAME : {
1075  double _q[njoint];
1076  Try( PrimitiveACQ_POS_Afma4(_q, &timestamp) );
1077 
1078  vpColVector q(this->njoint);
1079  for (unsigned int i=0; i < this->njoint; i++)
1080  q[i] = _q[i];
1081 
1082  // Compute fMc
1083  vpHomogeneousMatrix fMc;
1084  vpAfma4::get_fMc(q, fMc);
1085 
1086  // From fMc extract the pose
1087  vpRotationMatrix fRc;
1088  fMc.extract(fRc);
1089  vpRxyzVector rxyz;
1090  rxyz.buildFrom(fRc);
1091 
1092  for (unsigned int i=0; i < 3; i++) {
1093  position[i] = fMc[i][3]; // translation x,y,z
1094  position[i+3] = rxyz[i]; // Euler rotation x,y,z
1095  }
1096  break ;
1097  }
1098  case vpRobot::MIXT_FRAME: {
1099  vpERROR_TRACE ("Cannot get position in mixt frame: not implemented");
1101  "Cannot get position in mixt frame: "
1102  "not implemented");
1103  break ;
1104  }
1105  }
1106 
1107  CatchPrint();
1108  if (TryStt < 0) {
1109  vpERROR_TRACE ("Cannot get position.");
1111  "Cannot get position.");
1112  }
1113 
1114  return;
1115 }
1116 
1127  vpColVector &position)
1128 {
1129  double timestamp;
1130  getPosition(frame, position, timestamp);
1131 }
1132 
1179 void
1181  const vpColVector & vel)
1182 {
1183 
1185  {
1186  vpERROR_TRACE ("Cannot send a velocity to the robot "
1187  "use setRobotState(vpRobot::STATE_VELOCITY_CONTROL) first) ");
1189  "Cannot send a velocity to the robot "
1190  "use setRobotState(vpRobot::STATE_VELOCITY_CONTROL) first) ");
1191  }
1192 
1193  // Check the dimension of the velocity vector to see if it is
1194  // compatible with the requested frame
1195  switch(frame) {
1196  case vpRobot::CAMERA_FRAME : {
1197  //if (vel.getRows() != 2) {
1198  if (vel.getRows() != 6) {
1199  vpERROR_TRACE ("Bad dimension of the velocity vector in camera frame");
1201  "Bad dimension of the velocity vector "
1202  "in camera frame");
1203  }
1204  break ;
1205  }
1206  case vpRobot::ARTICULAR_FRAME : {
1207  if (vel.getRows() != this->njoint) {
1208  vpERROR_TRACE ("Bad dimension of the articular velocity vector");
1210  "Bad dimension of the articular "
1211  "velocity vector ");
1212  }
1213  break ;
1214  }
1215  case vpRobot::REFERENCE_FRAME : {
1216  vpERROR_TRACE ("Cannot send a velocity to the robot "
1217  "in the reference frame: "
1218  "functionality not implemented");
1220  "Cannot send a velocity to the robot "
1221  "in the reference frame:"
1222  "functionality not implemented");
1223  break ;
1224  }
1225  case vpRobot::MIXT_FRAME : {
1226  vpERROR_TRACE ("Cannot send a velocity to the robot "
1227  "in the mixt frame: "
1228  "functionality not implemented");
1230  "Cannot send a velocity to the robot "
1231  "in the mixt frame:"
1232  "functionality not implemented");
1233  break ;
1234  }
1235  default: {
1236  vpERROR_TRACE ("Error in spec of vpRobot. "
1237  "Case not taken in account.");
1239  "Cannot send a velocity to the robot ");
1240  }
1241  }
1242 
1243 
1244  //
1245  // Velocities saturation with normalization
1246  //
1247  vpColVector joint_vel(this->njoint);
1248 
1249  // Case of the camera frame where we control only 2 dof
1250  if (frame == vpRobot::CAMERA_FRAME) {
1251  vpColVector vel_max(6);
1252 
1253  for (unsigned int i=0; i<3; i++) {
1254  vel_max[i] = getMaxTranslationVelocity();
1255  vel_max[i+3] = getMaxRotationVelocity();
1256  }
1257 
1258  vpColVector velocity = vpRobot::saturateVelocities(vel, vel_max, true);
1259 
1260 #if 0 // ok
1261  vpMatrix eJe(4,6);
1262  eJe = 0;
1263  eJe[2][4] = -1;
1264  eJe[3][3] = 1;
1265 
1266  joint_vel = eJe * velocity; // Compute the articular velocity
1267 #endif
1268  vpColVector q;
1270  vpMatrix fJe_inverse;
1271  get_fJe_inverse(q, fJe_inverse);
1272  vpHomogeneousMatrix fMe;
1273  get_fMe(q, fMe);
1275  t=0;
1276  vpRotationMatrix fRe;
1277  fMe.extract(fRe);
1278  vpVelocityTwistMatrix fVe(t, fRe);
1279  // compute the inverse jacobian in the end-effector frame
1280  vpMatrix eJe_inverse = fJe_inverse * fVe;
1281 
1282  // Transform the velocities from camera to end-effector frame
1284  eVc.buildFrom(this->_eMc);
1285  joint_vel = eJe_inverse * eVc * velocity;
1286 
1287  // printf("Vitesse art: %f %f %f %f\n", joint_vel[0], joint_vel[1],
1288  // joint_vel[2], joint_vel[3]);
1289  }
1290 
1291  // Case of the joint control where we control all the joints
1292  else if (frame == vpRobot::ARTICULAR_FRAME) {
1293 
1294  vpColVector vel_max(4);
1295 
1296  vel_max[0] = getMaxRotationVelocity();
1297  vel_max[1] = getMaxTranslationVelocity();
1298  vel_max[2] = getMaxRotationVelocity();
1299  vel_max[3] = getMaxRotationVelocity();
1300 
1301  joint_vel = vpRobot::saturateVelocities(vel, vel_max, true);
1302  }
1303 
1304  InitTry;
1305 
1306  // Send a joint velocity to the low level controller
1307  Try( PrimitiveMOVESPEED_Afma4(joint_vel.data) );
1308 
1309  Catch();
1310  if (TryStt < 0) {
1311  if (TryStt == VelStopOnJoint) {
1312  UInt32 axisInJoint[njoint];
1313  PrimitiveSTATUS_Afma4(NULL, NULL, NULL, NULL, NULL, axisInJoint, NULL);
1314  for (unsigned int i=0; i < njoint; i ++) {
1315  if (axisInJoint[i])
1316  std::cout << "\nWarning: Velocity control stopped: axis "
1317  << i+1 << " on joint limit!" <<std::endl;
1318  }
1319  }
1320  else {
1321  printf("\n%s(%d): Error %d", __FUNCTION__, TryLine, TryStt);
1322  if (TryString != NULL) {
1323  // The statement is in TryString, but we need to check the validity
1324  printf(" Error sentence %s\n", TryString); // Print the TryString
1325  }
1326  else {
1327  printf("\n");
1328  }
1329  }
1330  }
1331 
1332  return;
1333 }
1334 
1335 /* ------------------------------------------------------------------------ */
1336 /* --- GET ---------------------------------------------------------------- */
1337 /* ------------------------------------------------------------------------ */
1338 
1339 
1387 void
1389  vpColVector & velocity, double &timestamp)
1390 {
1391 
1392  switch (frame) {
1394  velocity.resize (this->njoint);
1395  default:
1396  velocity.resize (6);
1397  }
1398 
1399  velocity = 0;
1400 
1401  double q[4];
1402  vpColVector q_cur(4);
1403  vpHomogeneousMatrix fMc_cur;
1404  vpHomogeneousMatrix cMc; // camera displacement
1405  double time_cur;
1406 
1407  InitTry;
1408 
1409  // Get the current joint position
1410  Try( PrimitiveACQ_POS_Afma4(q, &timestamp) );
1411  time_cur = timestamp;
1412 
1413  for (unsigned int i=0; i < this->njoint; i ++) {
1414  q_cur[i] = q[i];
1415  }
1416 
1417  // Get the camera pose from the direct kinematics
1418  vpAfma4::get_fMc(q_cur, fMc_cur);
1419 
1420  if ( ! first_time_getvel ) {
1421 
1422  switch (frame) {
1423  case vpRobot::CAMERA_FRAME: {
1424  // Compute the displacement of the camera since the previous call
1425  cMc = fMc_prev_getvel.inverse() * fMc_cur;
1426 
1427  // Compute the velocity of the camera from this displacement
1428  velocity = vpExponentialMap::inverse(cMc, time_cur - time_prev_getvel);
1429 
1430  break ;
1431  }
1432 
1433  case vpRobot::ARTICULAR_FRAME: {
1434  velocity = (q_cur - q_prev_getvel) / (time_cur - time_prev_getvel);
1435  break ;
1436  }
1437 
1438  case vpRobot::REFERENCE_FRAME: {
1439  // Compute the displacement of the camera since the previous call
1440  cMc = fMc_prev_getvel.inverse() * fMc_cur;
1441 
1442  // Compute the velocity of the camera from this displacement
1443  vpColVector v;
1444  v = vpExponentialMap::inverse(cMc, time_cur - time_prev_getvel);
1445 
1446  // Express this velocity in the reference frame
1447  vpVelocityTwistMatrix fVc(fMc_cur);
1448  velocity = fVc * v;
1449 
1450  break ;
1451  }
1452 
1453  case vpRobot::MIXT_FRAME: {
1454  vpERROR_TRACE ("Cannot get a velocity in the mixt frame: "
1455  "functionality not implemented");
1457  "Cannot get a displacement in the mixt frame:"
1458  "functionality not implemented");
1459 
1460  break ;
1461  }
1462  }
1463  }
1464  else {
1465  first_time_getvel = false;
1466  }
1467 
1468  // Memorize the camera pose for the next call
1469  fMc_prev_getvel = fMc_cur;
1470 
1471  // Memorize the joint position for the next call
1472  q_prev_getvel = q_cur;
1473 
1474  // Memorize the time associated to the joint position for the next call
1475  time_prev_getvel = time_cur;
1476 
1477 
1478  CatchPrint();
1479  if (TryStt < 0) {
1480  vpERROR_TRACE ("Cannot get velocity.");
1482  "Cannot get velocity.");
1483  }
1484 }
1485 
1495  vpColVector & velocity)
1496 {
1497  double timestamp;
1498  getVelocity(frame, velocity, timestamp);
1499 }
1500 
1501 
1502 
1544 {
1545  vpColVector velocity;
1546  getVelocity (frame, velocity, timestamp);
1547 
1548  return velocity;
1549 }
1550 
1560 {
1561  vpColVector velocity;
1562  double timestamp;
1563  getVelocity (frame, velocity, timestamp);
1564 
1565  return velocity;
1566 }
1567 
1618 bool
1619 vpRobotAfma4::readPosFile(const char *filename, vpColVector &q)
1620 {
1621 
1622  FILE * fd ;
1623  fd = fopen(filename, "r") ;
1624  if (fd == NULL)
1625  return false;
1626 
1627  char line[FILENAME_MAX];
1628  char dummy[FILENAME_MAX];
1629  char head[] = "R:";
1630  bool sortie = false;
1631 
1632  do {
1633  // Saut des lignes commencant par #
1634  if (fgets (line, FILENAME_MAX, fd) != NULL) {
1635  if ( strncmp (line, "#", 1) != 0) {
1636  // La ligne n'est pas un commentaire
1637  if ( strncmp (line, head, sizeof(head)-1) == 0) {
1638  sortie = true; // Position robot trouvee.
1639  }
1640 // else
1641 // return (false); // fin fichier sans position robot.
1642  }
1643  }
1644  else {
1645  return (false); /* fin fichier */
1646  }
1647 
1648  }
1649  while ( sortie != true );
1650 
1651  // Lecture des positions
1652  q.resize(4);
1653  sscanf(line, "%s %lf %lf %lf %lf",
1654  dummy,
1655  &q[0], &q[1], &q[2], &q[3]);
1656 
1657  // converts rotations from degrees into radians
1658  q[0] = vpMath::rad(q[0]);
1659  q[2] = vpMath::rad(q[2]);
1660  q[3] = vpMath::rad(q[3]);
1661 
1662 
1663  fclose(fd) ;
1664  return (true);
1665 }
1666 
1690 bool
1691 vpRobotAfma4::savePosFile(const char *filename, const vpColVector &q)
1692 {
1693 
1694  FILE * fd ;
1695  fd = fopen(filename, "w") ;
1696  if (fd == NULL)
1697  return false;
1698 
1699  fprintf(fd, "\
1700 #AFMA4 - Position - Version 2.01\n\
1701 #\n\
1702 # R: X Y A B\n\
1703 # Joint position: X : rotation of the turret in degrees (joint 1)\n\
1704 # Y : vertical translation in meters (joint 2)\n\
1705 # A : pan rotation of the camera in degrees (joint 4)\n\
1706 # B : tilt rotation of the camera in degrees (joint 5)\n\
1707 #\n\n");
1708 
1709  // Save positions in mm and deg
1710  fprintf(fd, "R: %lf %lf %lf %lf\n",
1711  vpMath::deg(q[0]),
1712  q[1],
1713  vpMath::deg(q[2]),
1714  vpMath::deg(q[3]));
1715 
1716  fclose(fd) ;
1717  return (true);
1718 }
1719 
1730 void
1731 vpRobotAfma4::move(const char *filename)
1732 {
1733  vpColVector q;
1734 
1735  this->readPosFile(filename, q) ;
1737  this->setPositioningVelocity(10);
1739 }
1740 
1754 void
1755 vpRobotAfma4::getCameraDisplacement(vpColVector &displacement)
1756 {
1757  getDisplacement(vpRobot::CAMERA_FRAME, displacement);
1758 }
1770 void
1771 vpRobotAfma4::getArticularDisplacement(vpColVector &displacement)
1772 {
1774 }
1775 
1796 void
1798  vpColVector &displacement)
1799 {
1800  displacement.resize (6);
1801  displacement = 0;
1802 
1803  double q[6];
1804  vpColVector q_cur(6);
1805  double timestamp;
1806 
1807  InitTry;
1808 
1809  // Get the current joint position
1810  Try( PrimitiveACQ_POS_Afma4(q, &timestamp) );
1811  for (unsigned int i=0; i < njoint; i ++) {
1812  q_cur[i] = q[i];
1813  }
1814 
1815  if ( ! first_time_getdis ) {
1816  switch (frame) {
1817  case vpRobot::CAMERA_FRAME: {
1818  std::cout << "getDisplacement() CAMERA_FRAME not implemented\n";
1819  return;
1820  break ;
1821  }
1822 
1823  case vpRobot::ARTICULAR_FRAME: {
1824  displacement = q_cur - q_prev_getdis;
1825  break ;
1826  }
1827 
1828  case vpRobot::REFERENCE_FRAME: {
1829  std::cout << "getDisplacement() REFERENCE_FRAME not implemented\n";
1830  return;
1831  break ;
1832  }
1833 
1834  case vpRobot::MIXT_FRAME: {
1835  std::cout << "getDisplacement() MIXT_FRAME not implemented\n";
1836  return;
1837  break ;
1838  }
1839  }
1840  }
1841  else {
1842  first_time_getdis = false;
1843  }
1844 
1845  // Memorize the joint position for the next call
1846  q_prev_getdis = q_cur;
1847 
1848  CatchPrint();
1849  if (TryStt < 0) {
1850  vpERROR_TRACE ("Cannot get velocity.");
1852  "Cannot get velocity.");
1853  }
1854 }
1855 
1856 #elif !defined(VISP_BUILD_SHARED_LIBS)
1857 // Work arround to avoid warning: libvisp_robot.a(vpRobotAfma4.cpp.o) has no symbols
1858 void dummy_vpRobotAfma4() {};
1859 #endif
1860 
static vpColVector inverse(const vpHomogeneousMatrix &M)
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:92
vpRxyzVector buildFrom(const vpRotationMatrix &R)
vpHomogeneousMatrix get_fMc(const vpColVector &q) const
Definition: vpAfma4.cpp:186
Error that can be emited by the vpRobot class and its derivates.
void get_fMe(const vpColVector &q, vpHomogeneousMatrix &fMe) const
Definition: vpAfma4.cpp:269
void get_cMe(vpHomogeneousMatrix &cMe) const
Definition: vpAfma4.cpp:320
static bool savePosFile(const char *filename, const vpColVector &q)
Implementation of an homogeneous matrix and operations on such kind of matrices.
void setVerbose(bool verbose)
Definition: vpRobot.h:156
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:152
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:364
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:412
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:145
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:146
static const unsigned int njoint
Number of joint.
Definition: vpAfma4.h:138
Modelisation of Irisa's cylindrical robot named Afma4.
Definition: vpAfma4.h:108
void extract(vpRotationMatrix &R) const
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 double rad(double deg)
Definition: vpMath.h:104
void get_eJe(vpMatrix &eJe)
static bool readPosFile(const char *filename, vpColVector &q)
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:522
virtual vpRobotStateType getRobotState(void) const
Definition: vpRobot.h:138
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:466
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:217