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 }