00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 #include <biotac_sensors/biotac_hand_class.h>
00039 #include <stdio.h>
00040 #include <iostream>
00041 
00042 
00043 
00044 
00045 
00046 static const unsigned char parity_values[] = \
00047                 { 0x01, 0x02, 0x04, 0x07, 0x08, 0x0B, 0x0D, 0x0E, \
00048                   0x10, 0x13, 0x15, 0x16, 0x19, 0x1A, 0x1C, 0x1F, \
00049                   0x20, 0x23, 0x25, 0x26, 0x29, 0x2A, 0x2C, 0x2F, \
00050                   0x31, 0x32, 0x34, 0x37, 0x38, 0x3B, 0x3D, 0x3E, \
00051                   0x40, 0x43, 0x45, 0x46, 0x49, 0x4A, 0x4C, 0x4F, \
00052                   0x51, 0x52, 0x54, 0x57, 0x58, 0x5B, 0x5D, 0x5E, \
00053                   0x61, 0x62, 0x64, 0x67, 0x68, 0x6B, 0x6D, 0x6E, \
00054                   0x70, 0x73, 0x75, 0x76, 0x79, 0x7A, 0x7C, 0x7F, \
00055                   0x80, 0x83, 0x85, 0x86, 0x89, 0x8A, 0x8C, 0x8F, \
00056                   0x91, 0x92, 0x94, 0x97, 0x98, 0x9B, 0x9D, 0x9E, \
00057                   0xA1, 0xA2, 0xA4, 0xA7, 0xA8, 0xAB, 0xAD, 0xAE, \
00058                   0xB0, 0xB3, 0xB5, 0xB6, 0xB9, 0xBA, 0xBC, 0xBF, \
00059                   0xC1, 0xC2, 0xC4, 0xC7, 0xC8, 0xCB, 0xCD, 0xCE, \
00060                   0xD0, 0xD3, 0xD5, 0xD6, 0xD9, 0xDA, 0xDC, 0xDF, \
00061                   0xE0, 0xE3, 0xE5, 0xE6, 0xE9, 0xEA, 0xEC, 0xEF, \
00062                   0xF1, 0xF2, 0xF4, 0xF7, 0xF8, 0xFB, 0xFD, 0xFE};
00063 
00064 using namespace biotac;
00065 
00066 
00067 
00068 
00069 BioTacHandClass::BioTacHandClass(string hand_id)
00070 {
00071   hand_id_ = hand_id;
00072   biotac_.spi_clock_speed = BT_SPI_BITRATE_KHZ_DEFAULT;
00073   biotac_.number_of_biotacs = 0;
00074   biotac_.sample_rate_Hz = BT_SAMPLE_RATE_HZ_DEFAULT;
00075   
00076   biotac_.frame.frame_type = 0;
00077   
00078   biotac_.batch.batch_frame_count = 1;
00079   
00080   biotac_.batch.batch_ms = 10;
00081 
00082   
00083   double length_of_data_in_second = 0.01;
00084   number_of_samples_ = (int)(BT_SAMPLE_RATE_HZ_DEFAULT * length_of_data_in_second);
00085 
00086   
00087   if (MAX_BIOTACS_PER_CHEETAH != 3 && MAX_BIOTACS_PER_CHEETAH != 5)
00088   {
00089     BioTac bt_err_code = BT_WRONG_MAX_BIOTAC_NUMBER;
00090     displayErrors(bt_err_code);
00091   }
00092 
00093 }
00094 
00095 
00096 
00097 
00098 BioTacHandClass::~BioTacHandClass()
00099 {
00100   bt_cheetah_close(ch_handle_);
00101 }
00102 
00103 
00104 
00105 
00106 
00107 
00108 void BioTacHandClass::initBioTacSensors()
00109 {
00110   BioTac bt_err_code = BT_NO_CHEETAH_DETECTED;
00111   ros::Rate loop_rate_cheetah(1);
00112   
00113   while( bt_err_code < BT_OK && ros::ok())
00114   {
00115     bt_err_code = bt_cheetah_initialize(&biotac_, &ch_handle_);
00116     if(bt_err_code < BT_OK)
00117     {
00118       displayErrors(bt_err_code);
00119       ROS_INFO("Attempting to initialize the Cheetah again in 1 second...");
00120       loop_rate_cheetah.sleep();
00121     }
00122   }
00123 
00124   bt_err_code = BT_NO_BIOTAC_DETECTED;
00125   ros::Rate loop_rate_biotac_connect(1);
00126   
00127   while( bt_err_code < BT_OK && ros::ok())
00128   { 
00129     bt_err_code = getBioTacProperties();
00130     if(bt_err_code < BT_OK)
00131     {
00132       displayErrors(bt_err_code);
00133       ROS_INFO("Attempting to connect to BioTac sensors again in 1 second...");
00134       loop_rate_biotac_connect.sleep();
00135     }
00136   }
00137 
00138   bt_err_code = BT_DATA_SIZE_TOO_SMALL;
00139   ros::Rate loop_rate_biotac_configure(1);
00140   
00141   while( bt_err_code < BT_OK && ros::ok())
00142   { 
00143     bt_err_code = configureBatch();
00144     if(bt_err_code < BT_OK)
00145     {
00146       displayErrors(bt_err_code);
00147       ROS_INFO("Configuring the BioTac SPI batch again, this time using default parameters.");
00148       ROS_INFO("Attempting to configure the BioTac SPI batch again in 1 second...");
00149       
00150       biotac_.spi_clock_speed = BT_SPI_BITRATE_KHZ_DEFAULT;
00151       biotac_.number_of_biotacs = 0;
00152       biotac_.sample_rate_Hz = BT_SAMPLE_RATE_HZ_DEFAULT;
00153       
00154       biotac_.frame.frame_type = 0;
00155       
00156       biotac_.batch.batch_frame_count = 1;
00157       
00158       biotac_.batch.batch_ms = 10;
00159       
00160       double length_of_data_in_second = 0.01;
00161       number_of_samples_ = (int)(BT_SAMPLE_RATE_HZ_DEFAULT * length_of_data_in_second);
00162       
00163       loop_rate_biotac_configure.sleep();
00164     }
00165   }
00166 
00167   
00168   biotac_sensors::BioTacData one_finger;
00169   for(int i = 0; i < biotac_.number_of_biotacs; i++)
00170   {
00171     bt_hand_msg_.bt_data.push_back(one_finger);
00172   }
00173   if(bt_err_code == BT_OK)
00174   {
00175     ROS_INFO("Configuring of Cheetah SPI and BioTac sensors complete.");
00176     ROS_INFO("Reading BioTac data...");
00177   }
00178 }
00179 
00180 
00181 
00182 
00183 BioTac BioTacHandClass::getBioTacProperties()
00184 {
00185   biotac_.number_of_biotacs = 0;
00186   bt_property biotac_property[MAX_BIOTACS_PER_CHEETAH];
00187   BioTac bt_err_code;
00188   for (int i = 0; i < MAX_BIOTACS_PER_CHEETAH; i++)
00189   {
00190     bt_err_code = bt_cheetah_get_properties(ch_handle_, i+1, &(biotac_property[i]));
00191     if (bt_err_code)
00192     {
00193       return bt_err_code;
00194     }
00195 
00196     if (biotac_property[i].bt_connected == YES)
00197     {
00198       (biotac_.number_of_biotacs)++;
00199       
00200       finger_info new_finger;
00201       char serial_char_array [25];
00202       sprintf(serial_char_array, "%c%c-%c%c-%c%c.%c.%c-%c-%c%c-%c-%c%c%c%c", \
00203                     biotac_property[i].serial_number[0], biotac_property[i].serial_number[1], \
00204                     biotac_property[i].serial_number[2], biotac_property[i].serial_number[3], \
00205                     biotac_property[i].serial_number[4], biotac_property[i].serial_number[5], \
00206                     biotac_property[i].serial_number[6], biotac_property[i].serial_number[7], \
00207                     biotac_property[i].serial_number[8], biotac_property[i].serial_number[9], \
00208                     biotac_property[i].serial_number[10], biotac_property[i].serial_number[11], \
00209                     biotac_property[i].serial_number[12], biotac_property[i].serial_number[13], \
00210                     biotac_property[i].serial_number[14], biotac_property[i].serial_number[15]);
00211       new_finger.finger_serial = string(serial_char_array);
00212       
00213       new_finger.finger_position = i+1;
00214       biotac_serial_no_info_.push_back(new_finger);
00215       ROS_INFO("Detected a BioTac at board position %d with serial number %s", \
00216                 new_finger.finger_position, serial_char_array+'\0');
00217     }
00218 
00219   }
00220   
00221   
00222   if (biotac_.number_of_biotacs == 0)
00223   {
00224     bt_err_code = BT_NO_BIOTAC_DETECTED;
00225     return bt_err_code;
00226   }
00227   
00228   ROS_INFO("%d BioTac(s) detected.", biotac_.number_of_biotacs);
00229   
00230   bt_err_code = BT_OK;
00231   return bt_err_code;
00232 }
00233 
00234 
00235 
00236 
00237 BioTac BioTacHandClass::configureBatch()
00238 {
00239   BioTac bt_err_code;
00240 
00241   bt_err_code = bt_cheetah_configure_batch(ch_handle_, &biotac_, number_of_samples_);
00242 
00243   if(bt_err_code == BT_OK)
00244   {
00245     ROS_INFO("Configured the Cheetah batch.");
00246     ros::Time frame_start_time_ = ros::Time::now();
00247   }
00248 
00249   return bt_err_code;
00250 }
00251 
00252 
00253 
00254 
00255 biotac_sensors::BioTacHand BioTacHandClass::collectBatch()
00256 {
00257   int i, j;
00258   int byte_shift = 2 + MAX_BIOTACS_PER_CHEETAH*2;  
00259   int spi_data_len;
00260   int number_of_samples_in_batch;
00261   static u08 *bt_raw_data;
00262   unsigned int channel_id;
00263   int finger_vector_pos;
00264 
00265   
00266   spi_data_len = ch_spi_batch_length(ch_handle_);
00267   bt_raw_data = (u08*) malloc(spi_data_len * sizeof *bt_raw_data);
00268   ch_spi_async_collect(ch_handle_, spi_data_len, bt_raw_data);
00269   ros::Time frame_end_time = ros::Time::now();
00270   ch_spi_async_submit(ch_handle_);
00271 
00272   number_of_samples_in_batch = spi_data_len/byte_shift;
00273 
00274   
00275   bt_hand_msg_.hand_id = hand_id_;
00276   
00277   bt_hand_msg_.header.stamp = frame_end_time;
00278   bt_hand_msg_.bt_time.frame_start_time = frame_start_time_;
00279   bt_hand_msg_.bt_time.frame_end_time = frame_end_time;
00280   double sample_total_time = (frame_end_time.sec + (double)frame_end_time.nsec/1000000) - \
00281                              (frame_start_time_.sec + (double)frame_start_time_.nsec/1000000);
00282   unsigned int time_step = (unsigned int)((sample_total_time / number_of_samples_in_batch) * 1000000.0);
00283   frame_start_time_ = frame_end_time;
00284 
00285   
00286   for(unsigned int k = 0; k < biotac_serial_no_info_.size(); k++)
00287   {
00288     bt_hand_msg_.bt_data[k].bt_position = biotac_serial_no_info_[k].finger_position;
00289     bt_hand_msg_.bt_data[k].bt_serial = biotac_serial_no_info_[k].finger_serial;
00290   }
00291 
00292   unsigned int ns_offset = 0;
00293   unsigned int pac_index = 0;
00294   unsigned int electrode_index = 0;
00295   unsigned int spi_data;
00296   for(i = 0; i < number_of_samples_in_batch; i++)
00297   {
00298     channel_id = (biotac_.frame.frame_structure[i%(biotac_.frame.frame_size)] & 0x7E) >> 1;
00299     finger_vector_pos = 0;
00300     for(j = 0; j < MAX_BIOTACS_PER_CHEETAH; j++)
00301     {
00302       spi_data = (unsigned int) (bt_raw_data[i*byte_shift + j*2 + 2] >> 1) * 32 + (bt_raw_data[i*byte_shift + j*2 + 3] >> 3);
00303 
00304       if((parity_values[bt_raw_data[i*byte_shift + j*2 + 2] >> 1] == bt_raw_data[i*byte_shift + j*2 + 2]) && \
00305           (parity_values[bt_raw_data[i*byte_shift + j*2 + 3] >> 1] == bt_raw_data[i*byte_shift + j*2 + 3]))
00306       {
00307         
00308         switch (channel_id)
00309         {
00310            case TDC:
00311               
00312               bt_hand_msg_.bt_data[finger_vector_pos].tdc_data = spi_data;
00313               bt_hand_msg_.bt_time.tdc_ns_offset = ns_offset;
00314               break;
00315            case TAC:
00316               
00317               bt_hand_msg_.bt_data[finger_vector_pos].tac_data = spi_data;
00318               bt_hand_msg_.bt_time.tac_ns_offset = ns_offset;
00319               break;
00320            case PDC:
00321               
00322               bt_hand_msg_.bt_data[finger_vector_pos].pdc_data = spi_data;
00323               bt_hand_msg_.bt_time.pdc_ns_offset = ns_offset;
00324               break;
00325            case PAC:
00326               
00327               bt_hand_msg_.bt_data[finger_vector_pos].pac_data[pac_index] = spi_data;
00328               bt_hand_msg_.bt_time.pac_ns_offset[pac_index] = ns_offset;
00329               break;
00330            default:
00331               
00332               if(channel_id >= ELEC_LO && channel_id <= ELEC_HI)
00333               {
00334                 electrode_index = channel_id - ELEC_LO;
00335                 bt_hand_msg_.bt_data[finger_vector_pos].electrode_data[electrode_index] = spi_data;
00336                 bt_hand_msg_.bt_time.electrode_ns_offset[electrode_index] = ns_offset;
00337               }
00338               else
00339               {
00340               }
00341         }  
00342 
00343         if( finger_vector_pos < (int)bt_hand_msg_.bt_data.size()-1 )
00344         {
00345           finger_vector_pos++;
00346         }
00347       }
00348       
00349       
00350       
00351       
00352 
00353      }
00354 
00355     
00356      if(channel_id == PAC)
00357      {
00358        pac_index++;
00359      }
00360      
00361      ns_offset += time_step;
00362 
00363   }
00364   free(bt_raw_data);
00365   return bt_hand_msg_;
00366 }
00367 
00368 
00369 
00370 
00371 
00372 void BioTacHandClass::displayErrors(BioTac bt_err_code)
00373 {
00374 
00375   switch(bt_err_code)
00376   {
00377   case BT_OK:
00378     
00379     break;
00380   case BT_WRONG_NUMBER_ASSIGNED:
00381     ROS_WARN("Wrong BioTac number assigned!");
00382     break;
00383   case BT_NO_BIOTAC_DETECTED:
00384     ROS_ERROR("No BioTacs are detected!");
00385     break;
00386   case BT_WRONG_MAX_BIOTAC_NUMBER:
00387     ROS_WARN("Wrong maximum number of BioTacs assigned (should be 3 or 5)!");
00388     break;
00389   case BT_DATA_SIZE_TOO_SMALL:
00390     ROS_WARN("The number of samples is too small! Using default sample size of ____.");
00391     break;
00392   case BT_NO_CHEETAH_DETECTED:
00393     ROS_ERROR("No Cheetah device detected!");
00394     break;
00395   case BT_UNABLE_TO_OPEN_CHEETAH:
00396     ROS_ERROR("Unable to open Cheetah device on current port.");
00397     break;
00398   case BT_UNABLE_TO_OPEN_FILE:
00399     ROS_ERROR("Cannot open output file.");
00400     break;
00401   default:
00402     ROS_ERROR("Unrecognized Biotac error encountered.");
00403     break;
00404   }
00405 
00406 }