proximity_sensor_driver.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002  *
00003  * Software License Agreement (BSD License)
00004  *
00005  *  Copyright (c) 2011, Robert Bosch LLC.
00006  *  All rights reserved.
00007  *
00008  *  Redistribution and use in source and binary forms, with or without
00009  *  modification, are permitted provided that the following conditions
00010  *  are met:
00011  *
00012  *   * Redistributions of source code must retain the above copyright
00013  *     notice, this list of conditions and the following disclaimer.
00014  *   * Redistributions in binary form must reproduce the above
00015  *     copyright notice, this list of conditions and the following
00016  *     disclaimer in the documentation and/or other materials provided
00017  *     with the distribution.
00018  *   * Neither the name of the Robert Bosch nor the names of its
00019  *     contributors may be used to endorse or promote products derived
00020  *     from this software without specific prior written permission.
00021  *
00022  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00023  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00024  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00025  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00026  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00027  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00028  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00029  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00030  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00032  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00033  *  POSSIBILITY OF SUCH DAMAGE.
00034  *
00035  *********************************************************************/
00036 
00037 //\Author Philip Roan and Joerg Wagner, Bosch LLC
00038 
00039 //Common Headers
00040 #include <iostream>
00041 #include <sstream>
00042 #include <string.h>
00043 #include <cmath>
00044 
00045 //ROS Headers
00046 #include <ros/ros.h>
00047 #include <ros/time.h>
00048 
00049 #include "proximity_sensor_driver.h"
00050 
00051 //TODO:
00052 //  - implement a useful application with dynamic reconfigure or delete the code belonging to dynamic reconfigure
00053 //      - change the software to handle 192 instead of 191 sensors
00054 //      - bug-fix: After the execution of command "Ram to Flash" the dynamic threshold is changed to zero.
00055 //        In the most cases the dynamic threshold could be reset to the old value by restarting the ECU (or several restarts).
00056 //      - Increase the I2C-BUS speed of the ECU (Must be changed in the assembler code of the ECU)
00057 //                      *An increased I2C-BUS speed could slow down the evaluation software of the sensor skin
00058 //      - Implementation of error handling routines
00059 
00060 ProxSensor::ProxSensor( const ros::NodeHandle& nh ):  // Initialization List Follows
00061   skin_connected_( false ),
00062   serialNumber_( "         " ),
00063   i2c_frequency_( 100000 ),
00064   cell_count_( 0 )
00065 {
00066   int noise = -1;
00067   int threshold = -1;
00068   int dynamic_threshold = -1;
00069 
00070   // Getting parameters from .launch file
00071   nh.getParam( "/prox_sensor_driver/sensor_count", cell_count_ );
00072   nh.getParam( "/prox_sensor_driver/noise_threshold", noise );
00073   nh.getParam( "/prox_sensor_driver/static_threshold", threshold );
00074   nh.getParam( "/prox_sensor_driver/dynamic_threshold", dynamic_threshold );
00075 
00076   if( noise < 0 || noise > 255 )
00077   {
00078     noise_ = 0;
00079   }
00080   else
00081   {
00082     noise_ = (uint8_t)noise;
00083   }
00084   if( threshold < 0 || threshold > 255 )
00085   {
00086     threshold_ = THRESHOLD_DEFAULT;
00087   }
00088   else
00089   {
00090     threshold_ = (uint8_t)threshold;
00091   }
00092   if( dynamic_threshold < 0 || dynamic_threshold > 255 )
00093   {
00094     dynamic_threshold_ = THRESHOLD_DEFAULT;
00095   }
00096   else
00097   {
00098     dynamic_threshold_ = (uint8_t)dynamic_threshold;
00099   }
00100 
00101   //ROS_INFO("Retrieved parameters: %d %d %d", sensor_count_, noise_, threshold_);
00102 }
00103 
00104 ProxSensor::~ProxSensor()
00105 {
00106   if( skin_connected_ == true )
00107   {
00108     // Close SUB20-Device device
00109     sub_close( handle_ );
00110     //Reset status
00111     skin_connected_ = false;
00112   }
00113   ROS_DEBUG( "Sub20 closed." );
00114 }
00115 
00116 bool ProxSensor::init( void )
00117 {
00118 
00119   int error_code = 0; //Error code for Sub20 API
00120   bool device_found = false; 
00121 
00122   subdev_ = sub_find_devices( NULL ); // start a new search for Sub20 devices
00123   while( subdev_ != NULL )
00124   {
00125     handle_ = sub_open( subdev_ ); // open found subdevice
00126     
00127     if( handle_ == 0 ) // on success, sub_open returns non-zero handle
00128     {
00129       //sub_open was not successful
00130       ROS_ERROR( "sub_open: %s", sub_strerror(sub_errno) );
00131       return false;
00132     }
00133   
00134     // Subdevice successfully opened
00135     ROS_DEBUG( "Device Handle: %ld", (long)handle_ );
00136     // Read Serial number of subdevice
00137     if( sub_get_serial_number( handle_, const_cast<char*>(serialNumber_.c_str() ), serialNumber_.size() ) >= 0 )
00138     {
00139       ROS_DEBUG( "Serial Number: %s", serialNumber_.c_str() );
00140     }
00141 
00142     ROS_DEBUG( "Initializing I2C interface to %d Hz.", i2c_frequency_ );
00143     error_code = sub_i2c_freq( handle_, &i2c_frequency_ ); // Set I2C frequency
00144     if( error_code != 0 )
00145     {
00146       ROS_ERROR( "Sub20 I2C configuration failed. Status: 0x%02x.", sub_i2c_status );
00147       sub_close( handle_ );
00148       return false;
00149     }
00150     else
00151     {
00152       ROS_DEBUG( "I2C initialized. Communicating at %d Hz.", i2c_frequency_ );
00153     }
00154 
00155     // Scan for I2C slave devices
00156     ROS_DEBUG( "Scanning for I2C devices." );
00157     int num_i2c_devices;        // number of i2c slave devices attached to this Sub20
00158     char device_addresses[112]; // i2c has a max of 112 devices per bus
00159     
00160     error_code = sub_i2c_scan( handle_, &num_i2c_devices, device_addresses ); //scan for devices
00161     if( error_code != 0 )
00162     {
00163       ROS_ERROR( "No I2C devices connected to Sub20." );
00164       sub_close( handle_ );
00165       return false;
00166     }
00167     ROS_DEBUG( "Number of I2C slaves detected: %d", num_i2c_devices );
00168     for( int i = 0; i < num_i2c_devices; i++ )
00169     {
00170       ROS_DEBUG( "%d. Slave address: 0x%02x", i+1, int(device_addresses[i]) ); // display found devices
00171       
00172       //verify that an I2C device exists at the skin ECU address
00173       if( PROX_SENSOR_I2C_ADR == (int)device_addresses[i] )
00174       {
00175         device_found = true;
00176         ROS_DEBUG( "I2C device at skin ECU address (0x%02x) exists.", PROX_SENSOR_I2C_ADR );
00177       }
00178     }
00179     if( device_found == false )
00180     {
00181       ROS_ERROR( "No I2C device at address 0x%02x.", PROX_SENSOR_I2C_ADR );
00182       sub_close( handle_ );
00183       return false;
00184     }
00185 
00186           
00187     char buffer[8] = {0};
00188     char adr[2];
00189     uint16_t next_address = 0;
00190     int adr_length = 0;
00191 
00192     adr[0] = DATA_ADR_HI;
00193     adr[1] = DATA_ADR_LO;
00194     adr_length = 2;
00195     error_code = sub_i2c_write( handle_, PROX_SENSOR_I2C_ADR, 0x00, SKIP_MEM_ADR_WRITE, adr, adr_length ); //Memory Address Write
00196     ros::Duration(0.05).sleep(); //sleep for 0.05 seconds
00197           
00198     error_code += sub_i2c_read( handle_, PROX_SENSOR_I2C_ADR, 0x00, SKIP_MEM_ADR_WRITE, buffer, 8 );//read data (8 bytes)
00199     ROS_DEBUG( "Status read from I2C device: %d", sub_i2c_status );
00200     
00201     if( error_code == 0 && ( ((int)buffer[0] & 0xFF) < 64 ) ) //condition for sensor skin: value stat < 64
00202     {
00203       ROS_DEBUG( "Connected device is a sensor skin." );
00204       skin_connected_ = true;
00205     }
00206     else
00207     {
00208       ROS_ERROR( "Found sensor is not a sensor skin." );
00209       sub_close( handle_ );
00210       return false;
00211     }
00212 
00213     // determine number of sensor elements
00214     // test each sensor until END_OF_CHAIN_MARKER is found 
00215     ROS_INFO("Determining the number of skin cells. We need at most %d I2C transmissions, with %d sensors per I2C transmission.", MAX_SENSORS / SENSORS_PER_I2C, SENSORS_PER_I2C );
00216     for( int i = 0; i < MAX_SENSORS / SENSORS_PER_I2C; i++ ) //read sensor values in blocks
00217     {
00218       next_address = ( i * SENSORS_PER_I2C * sizeof(struct skin_cell) ) + ( (uint16_t)DATA_ADR_HI << 8 | (uint16_t)DATA_ADR_LO );
00219       adr[1] = (char)next_address;
00220       adr[0] = (char)(next_address >> 8);
00221       adr_length = 2;
00222       error_code = sub_i2c_write( handle_, PROX_SENSOR_I2C_ADR, 0x00, SKIP_MEM_ADR_WRITE, adr, adr_length ); //Memory Address Write
00223       ros::Duration(0.05).sleep(); //sleep for 0.05 seconds
00224       error_code += sub_i2c_read( handle_, PROX_SENSOR_I2C_ADR, 0x00, SKIP_MEM_ADR_WRITE, (char*)&cells_[i*SENSORS_PER_I2C], MAX_BYTES_PER_I2C );//read data
00225       if( error_code != 0 )
00226       {
00227         ROS_ERROR("Cannot read data from ECU to determine number of cells.");
00228         sub_close( handle_ );
00229         return false;
00230       }
00231       for( int  k = i*SENSORS_PER_I2C; k < (i+1)*SENSORS_PER_I2C; k++ )
00232       {
00233         //ROS_DEBUG( "cell:%d\tstatus:%02x value:%03d offset:%03d limit:%03d V1:%03d V2:%03d V3:%03d dynamic:%d", k, cells_[k].status, cells_[k].value, cells_[k].offset, cells_[k].limit, cells_[k].U1, cells_[k].U2, cells_[k].U3, cells_[k].dynamic );
00234         if( cells_[k].limit == END_OF_CHAIN_MARKER || k >= MAX_SENSORS ) //|| (cells_[k].U1 == 0 && cells_[k].U2 == 0 && cells_[k].U3 == 0) ) // true for last skin cell
00235         {
00236           if( k != cell_count_ )
00237           {
00238             ROS_WARN( "Number of proximity sensors detected(%d) does not match the number specified(%d).", k, cell_count_ );
00239           }
00240           else
00241           {
00242             ROS_DEBUG( "Found %d attached proximity sensors.", k );
00243 
00244             // write the number of sensors to RAM of device ?
00245             // reinit ?
00246           }
00247           
00248           // initialize proximity sensor
00249           //sendToECU( INITIALIZE, 0, 0 );
00250           return true;
00251         }
00252       }
00253     }
00254 
00255     // search for the next Sub20 device and loop
00256     subdev_ = sub_find_devices( subdev_ );
00257   }
00258 
00259 
00260   ROS_ERROR("No Sub20 device found.");
00261   return false;
00262 }
00263 
00264 
00265 
00266 bool ProxSensor::getMeasurement( void )
00267 {
00268   int  error_code;
00269   char skin_status[2] = {0};
00270   char adr[2] = {0};
00271   int adr_length = 0;
00272 
00273   //only execute if SubDevice is configured and I2C device found
00274   if( skin_connected_ )
00275   {
00276     error_code = 0;
00277    
00278     // Read 2-byte status
00279     // send: Start|Slave Adr.|write|Mem. Adr. MSB/Hi|Mem. Adr. LSB/Lo|Stop
00280     adr[0] = STATUS_ADDRESS_HIGH;
00281     adr[1] = STATUS_ADDRESS_LOW;
00282     adr_length = 2;
00283     error_code += sub_i2c_write( handle_, PROX_SENSOR_I2C_ADR, 0x00, SKIP_MEM_ADR_WRITE, adr, adr_length );
00284     ros::Duration(0.05).sleep();//sleeps for 0.05 seconds (50msec sleep time required for ECU|uC of ECU is to slow to handle a I2C communication without sleep time)
00285 
00286     // Receive data from ECU (Start|Slave Adr.|Data[0]|...|Stop)
00287     error_code += sub_i2c_read( handle_, PROX_SENSOR_I2C_ADR, 0x00, SKIP_MEM_ADR_WRITE, skin_status, STATUS_LENGTH );//read data (2 bytes)
00288 
00289     // Extract data
00290     dynamic_threshold_ = (uint8_t)( (skin_status[1]) & 0xFF ); //Dynamic threshold initialized
00291     //Status byte contains Go/NoGo (Bit0) and Err/NoErr (Bit1)
00292     status_go_  = ( (skin_status[0] & 0x01) == 0 ) ? true : false;
00293     status_err_ = ( (skin_status[0] & 0x02) == 0 ) ? true : false;
00294     //ROS_DEBUG( "Go/NoGo: %d, Err: %d", status_go_, status_err_ );
00295     
00296     // Read sensor data
00297     //int old_read_loops = (int)ceil( sizeof(struct skin_cell) * cell_count_ / (double)MAX_BYTES_PER_I2C );
00298     int read_loops = cell_count_ / SENSORS_PER_I2C;
00299     uint16_t next_address = 0;
00300     //ROS_INFO("old: %d, new: %d", old_read_loops, read_loops);
00301     for( int k = 0; k < read_loops; k++ )
00302     {
00303       //send: Start|Slave Adr.|write|Mem. Adr. MSB/Hi|Mem. Adr. LSB/Lo|Stop
00304       next_address = ( k * SENSORS_PER_I2C * sizeof(struct skin_cell) ) + ( (uint16_t)DATA_ADR_HI << 8 | (uint16_t)DATA_ADR_LO );
00305       adr[1] = (uint8_t)next_address;
00306       adr[0] = (uint8_t)(next_address >> 8);
00307       adr_length = 2;
00308       ROS_DEBUG("Reading %d sensors (%d bytes). ECU start address: 0x%02x%02x to memory address start 0x%x", SENSORS_PER_I2C, SENSORS_PER_I2C * sizeof(struct skin_cell), adr[0], (uint8_t)adr[1], &cells_[k*SENSORS_PER_I2C] );
00309       adr_length = 2;
00310       error_code += sub_i2c_write( handle_, PROX_SENSOR_I2C_ADR, 0x00, SKIP_MEM_ADR_WRITE, adr, adr_length ); //Memory Address Write
00311       //ROS_DEBUG( "sub_i2c_write status: %d", sub_i2c_status );
00312       ros::Duration(0.05).sleep();//sleeps for 0.05 seconds (50msec sleep time required for ECU|uC of ECU is to slow to handle a I2C communication without sleep time)
00313 
00314       //receive data from ECU (Start|Slave Adr.|Data[0]|...|Stop)
00315       error_code += sub_i2c_read( handle_, PROX_SENSOR_I2C_ADR, 0x00, SKIP_MEM_ADR_WRITE, (char*)&cells_[k*SENSORS_PER_I2C], MAX_BYTES_PER_I2C );//read data
00316       //ROS_DEBUG( "sub_i2c_read status: %d", sub_i2c_status );
00317       //ros::Duration(0.05).sleep();//sleeps for 0.05 seconds (50msec sleep time required for ECU|uC of ECU is to slow to handle a I2C communication without sleep time)
00318     }
00319     if( cell_count_ % SENSORS_PER_I2C != 0 ) //read data of remaining sensors
00320     {
00321       //send: Start|Slave Adr.|write|Mem. Adr. MSB/Hi|Mem. Adr. LSB/Lo|Stop
00322       next_address = ( read_loops * SENSORS_PER_I2C * sizeof(struct skin_cell) ) + ( (uint16_t)DATA_ADR_HI << 8 | (uint16_t)DATA_ADR_LO );
00323       adr[1] = (char)next_address;
00324       adr[0] = (char)(next_address >> 8);
00325       adr_length = 2;
00326       ROS_DEBUG("Reading %d sensors (%d bytes). ECU start address: 0x%02x%02x to memory address start 0x%x", cell_count_ % SENSORS_PER_I2C, cell_count_ % SENSORS_PER_I2C * sizeof(struct skin_cell), adr[0], (uint8_t)adr[1], &cells_[read_loops*SENSORS_PER_I2C] );
00327       adr_length = 2;
00328       error_code += sub_i2c_write( handle_, PROX_SENSOR_I2C_ADR, 0x00, SKIP_MEM_ADR_WRITE, adr, adr_length ); //Memory Address Write
00329       //ROS_DEBUG( "sub_i2c_write status: %d", sub_i2c_status );
00330       ros::Duration(0.05).sleep();//sleeps for 0.05 seconds (50msec sleep time required for ECU|uC of ECU is to slow to handle a I2C communication without sleep time)
00331       
00332       //receive data from ECU (Start|Slave Adr.|Data[0]|...|Stop)
00333       error_code += sub_i2c_read( handle_, PROX_SENSOR_I2C_ADR, 0x00, SKIP_MEM_ADR_WRITE, (char*)&cells_[read_loops*SENSORS_PER_I2C], cell_count_ % SENSORS_PER_I2C * sizeof(struct skin_cell) );
00334       //ROS_DEBUG( "sub_i2c_read status: %d", sub_i2c_status );
00335       //ros::Duration(0.05).sleep();//sleeps for 0.05 seconds (50msec sleep time required for ECU|uC of ECU is to slow to handle a I2C communication without sleep time)
00336     }
00337    
00338     
00339     if( error_code != 0 )
00340     {
00341       ROS_WARN("getMeasurement(): master read transaction failed. Error code %d. Status %d", error_code, sub_i2c_status);
00342       return false;
00343     }
00344     else
00345     {
00346       ROS_DEBUG("Measurement available: %d\tStatus %02x\tOffset %d\tLimit %d", cells_[0].value, cells_[0].status, cells_[0].offset, cells_[0].limit);
00347     }
00348   }
00349   else
00350   {
00351     ROS_WARN("Measurement was not retrieved.");
00352     return false;
00353   }
00354 
00355   return true;
00356 }
00357 
00358 
00359 void ProxSensor::checkConnection( void )
00360 {
00361   skin_connected_ = false;
00362   sub_close( handle_ );
00363 }
00364 
00365 
00366 
00367 
00368 // Document me!
00369 bool ProxSensor::sendToECU( ECU_command command, uint8_t sensor_number, uint8_t value )
00370 {
00371   int error_code = 0;
00372   int sensor_address = 0;
00373   char data = 0;
00374   char adr[2] = {0};
00375   int adr_length = 0;
00376 
00377   if( skin_connected_ )
00378   {
00379     switch( command )
00380     {
00381     case INITIALIZE:
00382       data = 1;
00383       error_code = sub_i2c_write( handle_, PROX_SENSOR_I2C_ADR, (int)COMMAND_ADR, RAM_ADR_LENGTH, &data, RAM_WRITE_LENGTH );
00384       break;
00385     case WRITE_TO_FLASH:
00386       data = 4;
00387       
00388       adr[1] = (uint8_t)COMMAND_ADR;
00389       adr[0] = (uint8_t)(COMMAND_ADR >> 8);
00390       adr_length = 2;
00391       //error_code = sub_i2c_write( handle_, PROX_SENSOR_I2C_ADR, 
00392       error_code = sub_i2c_write( handle_, PROX_SENSOR_I2C_ADR, 0x00, SKIP_MEM_ADR_WRITE, adr, adr_length ); //Memory Address Write
00393       ros::Duration(0.05).sleep();//sleeps for 0.05 seconds (50msec sleep time required for ECU|uC of ECU is to slow to handle a I2C communication without sleep time)
00394       error_code += sub_i2c_write( handle_, PROX_SENSOR_I2C_ADR, 0x00, SKIP_MEM_ADR_WRITE, &data, RAM_WRITE_LENGTH );
00395       //error_code = sub_i2c_write( handle_, PROX_SENSOR_I2C_ADR, (int)COMMAND_ADR, RAM_ADR_LENGTH, &data, RAM_WRITE_LENGTH );
00396       break;
00397     case SET_DYNAMIC_THRESHOLD:
00398       data = value;
00399       error_code = sub_i2c_write( handle_, PROX_SENSOR_I2C_ADR, (int)DYNAMIC_THRESHOLD_ADR, RAM_ADR_LENGTH, &data, RAM_WRITE_LENGTH );
00400       break;
00401     case SET_STATIC_THRESHOLD:
00402       data = value;
00403       sensor_address = (int)( STATIC_THRESHOLD_ADR + (sensor_number)*sizeof(struct skin_cell) );
00404       error_code = sub_i2c_write( handle_, PROX_SENSOR_I2C_ADR, sensor_address, RAM_ADR_LENGTH, &data, RAM_WRITE_LENGTH );
00405       break;
00406     case SET_END_OF_CHAIN:
00407       // clear old END_OF_CHAIN_MARKER, where 'value' contains the sensor number of the old end of chain
00408       data = (char)threshold_;
00409       sensor_address = (int)( STATIC_THRESHOLD_ADR + value*sizeof(struct skin_cell) );
00410       error_code = sub_i2c_write( handle_, PROX_SENSOR_I2C_ADR, sensor_address, RAM_ADR_LENGTH, &data, RAM_WRITE_LENGTH );
00411       ros::Duration(0.05).sleep();
00412       
00413       data = END_OF_CHAIN_MARKER;
00414       sensor_address = (int)( STATIC_THRESHOLD_ADR + sensor_number*sizeof(struct skin_cell) );
00415       error_code += sub_i2c_write( handle_, PROX_SENSOR_I2C_ADR, sensor_address, RAM_ADR_LENGTH, &data, RAM_WRITE_LENGTH );
00416       ros::Duration(0.05).sleep();
00417       
00418       sendToECU(ACTIVATE_SENSOR, value, 0);
00419       ros::Duration(0.05).sleep();
00420       sendToECU(DEACTIVATE_SENSOR, sensor_number, 0);
00421       break;
00422     case ACTIVATE_SENSOR:
00423       data = ACTIVE;
00424       sensor_address = (int)( ACTIVATE_ADR + (sensor_number)*sizeof(struct skin_cell) );
00425       error_code += sub_i2c_write( handle_, PROX_SENSOR_I2C_ADR, sensor_address, RAM_ADR_LENGTH, &data, RAM_WRITE_LENGTH);
00426       break;
00427     case DEACTIVATE_SENSOR:
00428       data = INACTIVE;
00429       sensor_address = (int)( ACTIVATE_ADR + (sensor_number)*sizeof(struct skin_cell) );
00430       error_code += sub_i2c_write( handle_, PROX_SENSOR_I2C_ADR, sensor_address, RAM_ADR_LENGTH, &data, RAM_WRITE_LENGTH);
00431       break;
00432     default:
00433       ROS_WARN("Received unknown command for proximity sensor ECU: %d", command);
00434       return false;
00435     }
00436 
00437     if( error_code != 0 )
00438     {
00439       ROS_ERROR("Command not sent to ECU. Command: %d. Error code: %d. I2C Status: %d.", command, error_code, sub_i2c_status);
00440       return false;
00441     }
00442     else
00443     {
00444       ROS_DEBUG("Command (%d) sent to ECU.", command);
00445       return true;
00446     }
00447   }
00448 
00449   ROS_ERROR("Command was not sent because proximity sensor was not connected."); 
00450   return false;
00451 }
00452 
00453 
00454 
00455 //dynamic reconfigure routine
00456 void ProxSensor::reconfigure_callback(proximity_sensor_driver::ProximitySensorConfig &config, uint32_t level)
00457 {
00458 
00459   ROS_DEBUG("Reconfigure request, update?: %s", config.apply_changes?"yes":"no");
00460   
00461 
00462   if( config.apply_changes == true )
00463   {
00464     // update number of sensors
00465     if( config.sensor_count != cell_count_ )
00466     {
00467       if( sendToECU( SET_END_OF_CHAIN, (uint8_t)config.sensor_count, cell_count_ ) != true )
00468         ROS_ERROR("Attemped to change the number of sensors, but failure in sendToECU");
00469 
00470       cell_count_ = (uint8_t)config.sensor_count;
00471     }
00472 
00473     // update noise threshold
00474     if( config.noise_threshold != noise_ )
00475     {
00476       noise_ = (uint8_t)config.noise_threshold;
00477     }
00478     
00479     // update static thresholds
00480     if( config.change_static_threshold == true )
00481     {
00482       if( sendToECU( SET_STATIC_THRESHOLD, (uint8_t)config.static_threshold_sensor-1, (uint8_t)config.static_threshold ) != true )
00483         ROS_ERROR("Attemped to set the static threshold of sensor %d, but failure in sendToECU", config.static_threshold_sensor);
00484     }
00485     
00486     // update dynamic threshold
00487     if( config.dynamic_threshold != dynamic_threshold_ )
00488     {
00489       dynamic_threshold_ = (uint8_t)config.dynamic_threshold;
00490 
00491       if( sendToECU( SET_DYNAMIC_THRESHOLD, 0, dynamic_threshold_ ) != true )
00492         ROS_ERROR("Attemped to set the dynamic threshold, but failure in sendToECU");
00493     }
00494     
00495     // activate sensor
00496     if( config.activate_sensor == true )
00497     {
00498       if( sendToECU( ACTIVATE_SENSOR, (uint8_t)config.activate_sensor_number-1, 0 ) != true )
00499         ROS_ERROR("Attemped to activate sensor %d, but failure in sendToECU", config.activate_sensor_number);
00500     }
00501 
00502     // deactivate sensor
00503     if( config.deactivate_sensor == true )
00504     {
00505       if( sendToECU( DEACTIVATE_SENSOR, (uint8_t)config.deactivate_sensor_number-1, 0 ) != true )
00506         ROS_ERROR("Attemped to deactivate sensor %d, but failure in sendToECU", config.deactivate_sensor_number);
00507     }
00508 
00509     // write changes to flash memory
00510     if( config.write_to_flash == true )
00511     {
00512       ros::Duration(0.05).sleep();
00513       if( sendToECU( WRITE_TO_FLASH, 0, 0 ) != true )
00514         ROS_ERROR("Attemped to write to flash, but failure in sendToECU");
00515     }
00516 
00517     // reinitialize ECU
00518     if( config.initialize == true )
00519     {
00520       ros::Duration(0.05).sleep();
00521       if( sendToECU( INITIALIZE, 0, 0 ) != true )
00522         ROS_ERROR("Attemped to reinitialize, but failure in sendToECU");
00523     }
00524   }
00525 }
00526 
00527 //reinitialize service callback
00528 bool ProxSensor::reinitialize_callback(proximity_sensor_driver::reinitialize_proximity_sensor::Request &req,
00529                                  proximity_sensor_driver::reinitialize_proximity_sensor::Response &res)
00530 {
00531   if( sendToECU( INITIALIZE, 0, 0 ) != true )
00532   {
00533     ROS_ERROR("Attemped to reinitialize, but failure in sendToECU");
00534     return false;
00535   }
00536   return true;
00537 }
00538 
00539 
00540 // ----------
00541 // -- MAIN --
00542 // ----------
00543 int main(int argc, char **argv)
00544 {
00545   // ros init
00546   ros::init(argc, argv, "proximity_data_publisher");
00547   ros::NodeHandle nh;
00548   
00549   // create a skin class
00550   ProxSensor pr2_prox_sensor_arm(nh);
00551 
00552   proximity_sensor_driver::prox_sensor_measurement prox_msg;//ROS message
00553   proximity_sensor_driver::proximity_sensor_measurement proximity_msg; //ROS message
00554   
00555   ros::Publisher prox_pub = nh.advertise<proximity_sensor_driver::prox_sensor_measurement> ("prox_sensor_data", 20);
00556   ros::Publisher proximity_pub = nh.advertise<proximity_sensor_driver::proximity_sensor_measurement> ("proximity_sensor_data", 20);
00557   
00558   //dynamic reconfigure
00559   dynamic_reconfigure::Server<proximity_sensor_driver::ProximitySensorConfig> reconfigure_serv;
00560   dynamic_reconfigure::Server<proximity_sensor_driver::ProximitySensorConfig>::CallbackType dr = boost::bind( &ProxSensor::reconfigure_callback, &pr2_prox_sensor_arm, _1, _2 );
00561   reconfigure_serv.setCallback(dr);
00562 
00563   ros::ServiceServer prox_serv = nh.advertiseService( "reinitialize_proximity_sensor", &ProxSensor::reinitialize_callback, &pr2_prox_sensor_arm );
00564   
00565 
00566   int temporary_counter = 0;
00567 
00568   while( nh.ok() )
00569   {
00570     // Wait for sensor skin to be attached and configured (1 Hz loop rate)
00571     {
00572       ros::Rate loop_rate(1);
00573       while( nh.ok() && (pr2_prox_sensor_arm.init() == false) )
00574       {
00575         prox_msg.is_connected = false;
00576         prox_msg.cell_count = 0;
00577         prox_msg.header.stamp = ros::Time::now();
00578         prox_pub.publish( prox_msg );
00579 
00580         proximity_msg.is_connected = false;
00581         proximity_msg.cell_count = 0;
00582         proximity_msg.value.clear();
00583         proximity_msg.offset.clear();
00584         proximity_msg.limit.clear();
00585         proximity_msg.header.stamp = ros::Time::now();
00586         proximity_pub.publish( proximity_msg );
00587         
00588         ros::spinOnce();
00589         loop_rate.sleep();
00590       }
00591     }
00592 
00593     // If sensor skin is configured, publish readings (5 Hz loop rate);
00594     {
00595       ros::Rate loop_rate(5);
00596       while( nh.ok() && pr2_prox_sensor_arm.skin_connected_ )
00597       {
00598         //Publish if measurement was successful
00599         if( pr2_prox_sensor_arm.getMeasurement() == true )
00600         {
00601           prox_msg.is_connected = true;
00602           prox_msg.cell_count = pr2_prox_sensor_arm.cell_count_;
00603 
00604           proximity_msg.is_connected = true;
00605           proximity_msg.cell_count = pr2_prox_sensor_arm.cell_count_;
00606           proximity_msg.value.clear();
00607           proximity_msg.offset.clear();
00608           proximity_msg.limit.clear();
00609 
00610 
00611 
00612           // !!!!! NEXT 2 LINES CORRESPOND TO THE DIRTY HACK !!!!!
00613           bool bool_publish = true;
00614           int int_strange_readings = 0;
00615 
00616           for( int i = 0; i < pr2_prox_sensor_arm.cell_count_; i++ )
00617             //for( int i = 0; i < 192; i++ )
00618           {
00619             prox_msg.value[i] = pr2_prox_sensor_arm.cells_[i].value;
00620             prox_msg.offset[i] = pr2_prox_sensor_arm.cells_[i].offset;
00621             prox_msg.limit[i] = pr2_prox_sensor_arm.cells_[i].limit;
00622 
00623             
00624             proximity_msg.value.push_back( pr2_prox_sensor_arm.cells_[i].value );
00625             proximity_msg.offset.push_back( pr2_prox_sensor_arm.cells_[i].offset );
00626             proximity_msg.limit.push_back( pr2_prox_sensor_arm.cells_[i].limit );
00627 
00628             
00629             prox_msg.debug_voltage1[i] = pr2_prox_sensor_arm.cells_[i].U1;
00630             prox_msg.debug_voltage2[i] = pr2_prox_sensor_arm.cells_[i].U2;
00631             prox_msg.debug_voltage3[i] = pr2_prox_sensor_arm.cells_[i].U3;
00632             //prox_msg.status[i] = pr2_prox_sensor_arm.cells_[i].status;
00633 
00634             // !!!!! THIS IS A DIRTY HACK, BECAUSE THE PROX_SENSOR SOMETIMES GIVES WRONG READINGS !!!!!
00635             //if( abs(prox_msg.value[i] - prox_msg.offset[i]) > 20 || prox_msg.value[i] < 15)
00636             //{
00637             //  int_strange_readings++;
00638             //  if(int_strange_readings > 10)
00639             //  {
00640             //    bool_publish = false;
00641             //  }
00642             //}
00643             //if(prox_msg.value[i] == 0)
00644             //{
00645             //  // !!!!! SETS PATCHES THAT GIVE ZERO READINGS TO THEIR INIT !!!!!
00646             //  prox_msg.value[i] = prox_msg.offset[i];
00647             //}
00648 
00649 
00650 
00651 
00652             //if( temporary_counter % 5 == 0 )
00653             //  ROS_DEBUG("cell:%d\tstatus:%02x value:%03d offset:%03d limit:%03d\tV1:%03d V2:%03d V3:%03d dynamic:%d", i, pr2_prox_sensor_arm.cells_[i].status, pr2_prox_sensor_arm.cells_[i].value, pr2_prox_sensor_arm.cells_[i].offset, pr2_prox_sensor_arm.cells_[i].limit, pr2_prox_sensor_arm.cells_[i].U1, pr2_prox_sensor_arm.cells_[i].U2, pr2_prox_sensor_arm.cells_[i].U3, pr2_prox_sensor_arm.cells_[i].dynamic);
00654 
00655           }
00656           prox_msg.header.stamp = ros::Time::now();
00657           prox_msg.status_go = pr2_prox_sensor_arm.status_go_;
00658           prox_msg.status_err = pr2_prox_sensor_arm.status_err_;
00659           
00660           proximity_msg.header.stamp = ros::Time::now();
00661           proximity_msg.status_go = pr2_prox_sensor_arm.status_go_;
00662           proximity_msg.status_err = pr2_prox_sensor_arm.status_err_;
00663 
00664           if( bool_publish )
00665           {
00666             prox_pub.publish( prox_msg );
00667             proximity_pub.publish( proximity_msg );
00668           }
00669         }
00670         else // check if skin is still connected
00671         {
00672           ROS_WARN("Proximity sensors have been disconnected.");
00673           pr2_prox_sensor_arm.checkConnection();
00674 
00675           prox_msg.is_connected = false;
00676           prox_msg.cell_count = 0;
00677           prox_msg.header.stamp = ros::Time::now();
00678           prox_pub.publish( prox_msg );
00679 
00680           proximity_msg.is_connected = false;
00681           proximity_msg.cell_count = 0;
00682           proximity_msg.header.stamp = ros::Time::now();
00683           proximity_pub.publish( proximity_msg );
00684         }
00685 
00686 
00687         ++temporary_counter;
00688 
00689         ros::spinOnce();
00690         loop_rate.sleep();
00691       }
00692     }
00693   }
00694   return 0;
00695 }


proximity_sensor_driver
Author(s): Philip Roan, Joerg Wagner (Maintained by Philip Roan)
autogenerated on Fri Jan 3 2014 11:08:48