FRICheck_legacy.cc
Go to the documentation of this file.
00001 #include "FRICheck_legacy.hh"
00002 
00003 #include <string.h>
00004 #include <math.h>
00005 
00006 #define DEG *M_PI/180.0
00007 #define RAD /M_PI*180.0
00008 
00009 
00010 
00011 // limits as of KRC/roboter/dlrrc/cfg/rsidef7.dat
00012 const float FRICheck_legacy::lim_low[7] = {-169.5 DEG, -119.5 DEG, -169.5 DEG, -119.5 DEG, -169.5 DEG, -119.5 DEG, -169.5 DEG};
00013 const float FRICheck_legacy::lim_high[7] = { 169.5 DEG,  119.5 DEG,  169.5 DEG,  119.5 DEG,  169.5 DEG,  119.5 DEG,  169.5 DEG};
00014 
00015 const float FRICheck_legacy::lim_vel[7] = {120 DEG, 120 DEG, 160 DEG, 160 DEG, 250 DEG, 220 DEG, 220 DEG};
00016 const float FRICheck_legacy::lim_acc[7] = {1200, 1200, 1600, 1600, 2500, 4400, 4400};
00017 
00018 
00019 void safety_check(float *vel, float *vel_old, float *pos, float rate);
00020 
00021 
00022 
00023 FRICheck_legacy::FRICheck_legacy() :
00024   j5_angles(0), j6_min(0), j6_max(0), length(0)
00025 {
00026   memset(pos_, 0, sizeof(float)*7);
00027   memset(vel_old_, 0, sizeof(float)*7);
00028 }
00029 
00030 
00031 void FRICheck_legacy::setPos(float* pos)
00032 {
00033   memcpy(pos_, pos, sizeof(float)*7);
00034 }
00035 
00036 
00037 
00038 void FRICheck_legacy::adjust(float *pos, float rate)
00039 {
00040   
00041   float vel[16];
00042   
00043   // compute increments
00044   for(int i=0; i < 7; i++)
00045     vel[i] = pos[i] - pos_[i];
00046   
00047   // limit increments
00048   safety_check(vel, vel_old_, pos_, rate);
00049     
00050   // convert position increments back to positions
00051   for(int i=0; i < 7; i++)
00052     pos[i] = pos_[i] + vel[i];
00053 
00054   // remember old positions and velocities
00055   memcpy(pos_, pos, sizeof(float)*7);
00056   memcpy(vel_old_, vel, sizeof(float)*7);
00057 }
00058 
00059 
00060 //This mapping of the limits was done choosing a value for j5, and then exploring the maximum and minimum value of j6.
00061 
00062 #include <stdio.h>
00063 #include <stdlib.h>
00064 
00065 
00066 double j5_angles_left[]={-120.0 DEG, -100 DEG, -80 DEG, -60 DEG, -40 DEG, -35 DEG, -30 DEG, -25 DEG, -20 DEG, -10 DEG, 0 DEG, 10 DEG, 20 DEG, 30 DEG, 40 DEG, 50 DEG, 60 DEG, 70 DEG, 80  DEG,100 DEG, 120 DEG};
00067 double j6_min_left[]={-170 DEG, -170 DEG, -170 DEG, -170 DEG,-170 DEG,-170 DEG,-170 DEG,-170 DEG,-170 DEG,-170 DEG,-170 DEG,-160 DEG,-150 DEG,-140 DEG,-105 DEG,-90 DEG,-85 DEG,-85 DEG,-80 DEG,-75 DEG,-75 DEG};
00068 double j6_max_left[]={-4 DEG, -4 DEG, 0 DEG, 0 DEG, 10 DEG, 30 DEG, 50 DEG, 60 DEG, 65 DEG, 70 DEG, 80 DEG, 80 DEG, 85 DEG, 90 DEG, 90 DEG, 90 DEG, 90 DEG, 90 DEG, 90 DEG, 90 DEG, 90 DEG};
00069 int length_left = 21;
00070 
00071 double j5_angles_right[] = {-120 DEG, -100 DEG, -80 DEG, -60 DEG, -40 DEG, -35 DEG, -30 DEG, -25 DEG, -20 DEG, -10 DEG, 0 DEG, 10 DEG, 20 DEG, 30 DEG, 40 DEG, 50 DEG, 60 DEG, 70 DEG, 80 DEG, 100 DEG, 120 DEG};
00072 double j6_max_right[] = { 84 DEG, 84 DEG, 90 DEG, 90 DEG, 100 DEG, 120 DEG, 140 DEG, 150 DEG, 155 DEG, 160 DEG, 170 DEG, 170 DEG, 170 DEG, 170 DEG, 170 DEG, 170 DEG, 170 DEG, 170 DEG, 170 DEG, 170 DEG, 170 DEG};
00073 double j6_min_right[] = {-80 DEG, -80 DEG, -80 DEG, -80 DEG, -80 DEG, -80 DEG, -80 DEG, -80 DEG, -80 DEG, -80 DEG, -80 DEG, -70 DEG, -60 DEG, -50 DEG, -15 DEG, 0 DEG, 5 DEG, 5 DEG, 10 DEG, 15 DEG, 15 DEG};
00074 int length_right = 21;
00075 
00076 // general limits (applying to both arms)
00077 double liml[7] = {-169.5 DEG, -119.5 DEG, -169.5 DEG, -119.5 DEG, -169.5 DEG, -119.5 DEG, -169.5 DEG};
00078 double limh[7] = { 169.5 DEG,  119.5 DEG,  169.5 DEG,  119.5 DEG,  169.5 DEG,  119.5 DEG,  169.5 DEG};
00079 
00080 
00081 //interpolate given two data points: x1,y1 and x2,y2
00082 double FRICheck_legacy::interpolate(double x, double x1, double y1, double x2, double y2)
00083 {
00084   double diff_y=y2 - y1;
00085   double diff_x=x2 - x1;
00086   double dx=x - x1;
00087   return(y1 + (diff_y/diff_x)*dx);
00088 }
00089 
00090 int FRICheck_legacy::find_index(float j5){
00091     //printf("Array length: %d\n",length);
00092     
00093     int i=0;
00094 
00095     // check for errors
00096     if ( (j5 < j5_angles[0]) || (j5 > j5_angles[length-1]) ){
00097       printf("%f not in [%f .. %f]: ", j5, j5_angles[0],j5_angles[length-1]);
00098       printf("Error, check the input value.\n");
00099       return(-1);
00100     }
00101 
00102     //The array must increase monotically
00103     //need the index where we interpolate
00104     int index=0;
00105     for (i=0; i<= length-1 ; i++){
00106         if ((j5 > j5_angles[i]) & (j5 <= j5_angles[i+1] )){
00107             index=i;
00108             break;
00109         }
00110     }
00111 
00112     return(index);
00113 }
00114 
00115 double FRICheck_legacy::min_j6(float j5, int index)
00116 {
00117   float min_lim = interpolate(j5,
00118                               j5_angles[index],  j6_min[index],
00119                               j5_angles[index+1],j6_min[index+1]);
00120   return(min_lim);
00121 }
00122 
00123 double FRICheck_legacy::max_j6(float j5, int index)
00124 {
00125   float max_lim = interpolate(j5,
00126                               j5_angles[index],  j6_max[index],
00127                               j5_angles[index+1],j6_max[index+1]);
00128   return(max_lim);
00129 }
00130 
00131 
00132 void FRICheck_legacy::safety_check(float *vel, float *vel_old, float *pos, float rate)
00133 {
00134   if(length == 0 || j5_angles == 0 || j6_min == 0 || j6_max == 0) {
00135     printf("arm side for safety limits checking not set, panicking...\n");
00136     exit(-1);
00137   }
00138 
00139   //The following values vel_max and acc_max are decided by us
00140   double vel_max = (100 DEG) * rate;
00141   double acc_max = (600 DEG) * rate * rate;
00142 
00143   //These are the hard acceleration limits defined in the RSI-Def7 file
00144   double acc_max_hard[7];
00145   acc_max_hard[0]=(1200 DEG) * rate * rate;
00146   acc_max_hard[1]=(1200 DEG) * rate * rate;
00147   acc_max_hard[2]=(1600 DEG) * rate * rate;
00148   acc_max_hard[3]=(1600 DEG) * rate * rate;
00149   acc_max_hard[4]=(2500 DEG) * rate * rate;
00150   acc_max_hard[5]=(4400 DEG) * rate * rate;
00151   acc_max_hard[6]=(4400 DEG) * rate * rate;
00152 
00153   //rate down the accel limits for safety
00154   for (unsigned int i=0; i <7 ; i++) {
00155     acc_max_hard[i]=acc_max_hard[i]*0.9;
00156   }
00157 
00158   // do a special check for the last two joints, they need to use the 2d map of their limits
00159   // check if we are inside the nice area, if not, stop!
00160   double newpos5=pos[5]+vel[5];
00161   int index = find_index(newpos5);
00162   double min_lim6=min_j6(newpos5,index);
00163   double max_lim6=max_j6(newpos5,index);
00164   int n_cycles=5;
00165 
00166   if(index == -1) {
00167     vel[5] = 0.0;
00168     vel[6] = 0.0;
00169   }
00170   
00171   //lower limit, speed negative
00172   if ( ( pos[6]+vel[6] < min_lim6 ) && (pos[6]+n_cycles*vel[6] < min_lim6 ) ) {
00173     vel[6] =  (0.0  > vel_old[6] + acc_max) ? vel_old[6] + acc_max : 0.0;
00174     //limit 5 also (both sides)
00175     vel[5] =  (0.0  > vel_old[5] + acc_max) ? vel_old[5] + acc_max : 0.0;
00176     vel[5] =  (0.0  < vel_old[5] - acc_max) ? vel_old[5] - acc_max : 0.0;
00177   }
00178 
00179   //upper limit, speed positive
00180   if (( pos[6]+vel[6] > max_lim6 ) && ( pos[6]+n_cycles*vel[6] > max_lim6  )  ) {
00181     vel[6] =  (0.0  < vel_old[6] - acc_max) ? vel_old[6] - acc_max : 0.0;
00182     //limit 5 also (both sides)
00183     vel[5] =  (0.0  > vel_old[5] + acc_max) ? vel_old[5] + acc_max : 0.0;
00184     vel[5] =  (0.0  < vel_old[5] - acc_max) ? vel_old[5] - acc_max : 0.0;
00185   }
00186 
00187 
00188   // final check on all the joints, avoiding to exceed their mechanical limits
00189   for(int i=0; i < 7; i++) {
00190 
00191     // handle velocity limits
00192     vel[i] = (vel[i] >  vel_max) ?  vel_max : vel[i];
00193     vel[i] = (vel[i] < -vel_max) ? -vel_max : vel[i];
00194 
00195     // handle normal acceleration limits
00196     vel[i] =  (vel[i]  > vel_old[i] + acc_max) ? vel_old[i] + acc_max : vel[i];
00197     vel[i] =  (vel[i]  < vel_old[i] - acc_max) ? vel_old[i] - acc_max : vel[i];
00198 
00199     //Limit handling in two stages:
00200     //Stage 1:
00201     // calculate the maximum speed now,
00202     // so that we could still stop in time for the limit, i.e.
00203     // | v(t) = a_max*t,  x(t) = Int(v(t)*dt) = .5*a_max*t^2
00204     // | ==> v(x) = sqrt(2*a_max*x)
00205     // | x: distance to limit
00206     // | v: velocity
00207     // | a_max: maximum allowed accelearation
00208 
00209     // BUT: We need to know the velocity that we mustn't exceed
00210     //      at the end of the NEXT timestep:
00211     // | [ x_next = x - v
00212     // | [ v = sqrt(2*a_max*x_next)
00213     // | ==> v(x) = -a + sqrt(a_max^2 + 2*a_max*x)
00214     if (vel[i] > 0.0) { // positive speed, worry about upper limit
00215         double dist_to_limit = limh[i] - pos[i];
00216         if (dist_to_limit > 0.0) { //only change vel[i] if we are before the limit
00217             double vel_max = -acc_max_hard[i] + sqrt(acc_max_hard[i]*(2*dist_to_limit+acc_max_hard[i]));
00218 
00219             vel[i] = ( vel[i] > vel_max ) ? vel_max : vel[i];
00220         }
00221     } else { //negative speed, worry about lower limit
00222         double dist_to_limit = pos[i] - liml[i];
00223         if (dist_to_limit > 0.0) {
00224             double vel_max = -acc_max_hard[i] + sqrt(acc_max_hard[i]*(2*dist_to_limit+acc_max_hard[i]));
00225 
00226             vel[i] = ( vel[i] < -vel_max ) ? -vel_max : vel[i];
00227         }
00228     }
00229 
00230     // Stage 2:
00231     // emergency braking taking advantage of the limit margin (0.5deg)
00232     if( ( (pos[i]) < liml[i] ) && ( vel[i] < 0.0 ) ) {  //negative velocity, hitting lower limit
00233       vel[i] =  (0.0  > vel_old[i] + acc_max_hard[i]) ? vel_old[i] + acc_max_hard[i] : 0.0;
00234     }
00235     if( ( (pos[i]) > limh[i] ) && ( vel[i] > 0.0 ) ){  //positive velocity, hitting upper limit
00236       vel[i] =  (0.0  < vel_old[i] - acc_max_hard[i]) ? vel_old[i] - acc_max_hard[i] : 0.0;
00237     }
00238   }
00239 }
00240 
00241 
00242 int FRICheck_legacy::safety_set_side(int side)
00243 {
00244   switch(side) {
00245   case SAFETY_LEFT:
00246     j5_angles = j5_angles_left;
00247     j6_min = j6_min_left;
00248     j6_max = j6_max_left;
00249     length = length_left;
00250     return 1;
00251   case SAFETY_RIGHT:
00252     j5_angles = j5_angles_right;
00253     j6_min = j6_min_right;
00254     j6_max = j6_max_right;
00255     length = length_right;
00256     return 1;
00257   default:
00258     return 0;
00259   }
00260 }


kuka_fri
Author(s): Ingo Kresse, Alexis Maldonado
autogenerated on Mon Oct 6 2014 09:27:39