roch_hardware.cpp
Go to the documentation of this file.
00001 
00032 #include "roch_base/roch_hardware.h"
00033 #include <boost/assign/list_of.hpp>
00034 #include <float.h>
00035 
00036 
00037 namespace
00038 {
00039   const uint8_t LEFT = 0, RIGHT = 1;
00040 };
00041 namespace roch_base
00042 {
00043 
00047   rochHardware::rochHardware(ros::NodeHandle nh, ros::NodeHandle private_nh, double target_control_freq)
00048     :
00049     nh_(nh),
00050     private_nh_(private_nh),
00051     system_status_task_(roch_status_msg_),
00052     power_status_task_(roch_status_msg_),
00053     safety_status_task_(roch_status_msg_),
00054     software_status_task_(roch_status_msg_, target_control_freq)
00055   {
00056     private_nh_.param<double>("wheel_diameter", wheel_diameter_, 0.095);
00057     private_nh_.param<double>("max_accel", max_accel_, 5.0);
00058     private_nh_.param<double>("max_speed", max_speed_, 0.45);
00059     private_nh_.param<double>("polling_timeout_", polling_timeout_, 20.0);
00060     private_nh_.param<double>("cliff_hegiht", cliff_height_, 0.1); //how tall can scan(meter)
00061     private_nh_.param<double>("ult_length", ult_length_, 0.1); //how far can scan(meter)
00062     private_nh_.param<double>("psd_length", PSD_length_, 0.1); //how far can scan(meter)
00063     private_nh_.param<std::string>("imu_link_frame", gyro_link_frame_, "imu_link");
00064 
00065     std::string port;
00066     private_nh_.param<std::string>("port", port, "/dev/ttyUSB0");
00067 
00068     core::connect(port);
00069     core::configureLimits(max_speed_, max_accel_);
00070     resetTravelOffset();
00071     initializeDiagnostics(); 
00072     registerControlInterfaces();
00073   }
00074 
00078   void rochHardware::resetTravelOffset()
00079   {
00080     core::Channel<sawyer::DataEncoders>::Ptr enc = core::Channel<sawyer::DataEncoders>::requestData(
00081       polling_timeout_);
00082       publishRawData();
00083     if (enc)
00084     {
00085                 for (int i = 0; i < 2; i++)
00086       {
00087         joints_[i].position_offset = linearToAngular(enc->getTravel(i % 2));
00088         ROS_DEBUG_STREAM("joints_["<<i<<"].position_offset:"<<joints_[i].position_offset<<" .");
00089       }
00090     }
00091     else
00092     {
00093       ROS_ERROR("Could not get encoder data to calibrate travel offset");
00094     }
00095     
00096     //add imu data from IMU
00097    core::Channel<sawyer::Data6AxisYaw>::Ptr imuRateData = core::Channel<sawyer::Data6AxisYaw>::requestData(
00098      polling_timeout_);
00099      publishRawData();
00100      if(imuRateData){
00101       ROS_DEBUG_STREAM("Received  imu rate data information (Angle:" << imuRateData->getAngle() << " Angle rate:" << imuRateData->getAngleRate() << ")");
00102       ROS_DEBUG_STREAM("Received  imu rate data information, angle_offset:"<<imuRateData->getAngle()<<" .");        
00103       sixGyro.angle_offset = imuRateData->getAngle();
00104     }
00105     else{
00106        ROS_ERROR("Could not get imu data to calibrate rate offset");
00107     }
00108     core::Channel<sawyer::DataPlatformAcceleration>::Ptr getPlatformAccData = 
00109       core::Channel<sawyer::DataPlatformAcceleration>::requestData(polling_timeout_);
00110     publishRawData();
00111     if(getPlatformAccData){
00112 
00113       ROS_DEBUG_STREAM("Received acc_x:"<<getPlatformAccData->getX()<<", acc_y:"<<getPlatformAccData->getY()<<", acc_z:"<<getPlatformAccData->getZ()<<".");
00114  
00115       sixGyro.acc.X_Offset = getPlatformAccData->getX();
00116       sixGyro.acc.Y_Offset = getPlatformAccData->getY();
00117       sixGyro.acc.Z_Offset = getPlatformAccData->getZ();
00118       
00119       linear_acceleration[0] = sixGyro.acc.X_Offset;
00120       linear_acceleration[1] = sixGyro.acc.Y_Offset;
00121       linear_acceleration[2] = sixGyro.acc.Z_Offset;
00122     }
00123     else{
00124        ROS_ERROR("Could not get Gyro data to calibrate Acceleration offset");
00125     }
00126   }
00127 
00128   void rochHardware::getRangefinderData()
00129   {
00130     core::Channel<sawyer::DataRangefinders>::Ptr rangefinderData = 
00131     core::Channel<sawyer::DataRangefinders>::requestData(polling_timeout_);
00132     publishRawData();
00133     if(rangefinderData){
00134       ROS_DEBUG_STREAM("Received rangefinder Data, counts:"<<(int)rangefinderData->getRangefinderCount()<<", data[0]:"<<rangefinderData->getDistance(0)<<" , data[1]:"<<rangefinderData->getDistance(1)<<", data[2]:"<<rangefinderData->getDistance(2)<<" , data[3]:"<<rangefinderData->getDistance(3)<<", data[4]:"<<rangefinderData->getDistance(4)<<".");
00135 
00136       publishCliffEvent(rangefinderData->getDistance(6),rangefinderData->getDistance(7));
00137       publishUltEvent(rangefinderData->getDistance(0),rangefinderData->getDistance(1),rangefinderData->getDistance(2));  
00138       publishPSDEvent(rangefinderData->getDistance(3),rangefinderData->getDistance(4),rangefinderData->getDistance(5));
00139     }
00140   
00141     core::Channel<sawyer::DataRangefinderTimings>::Ptr rangefinderDataAndTime = 
00142     core::Channel<sawyer::DataRangefinderTimings>::requestData(polling_timeout_);
00143     publishRawData();
00144     if(rangefinderDataAndTime){
00145       ROS_DEBUG_STREAM("Received rangefinder Data and time, counts:"<<(int)rangefinderDataAndTime->getRangefinderCount()<<
00146                      ", data[0]:"<<rangefinderDataAndTime->getDistance(0)<<", time[0]:"<<rangefinderDataAndTime->getAcquisitionTime(0)<<
00147                      ", data[1]:"<<rangefinderDataAndTime->getDistance(0)<<", time[1]:"<<rangefinderDataAndTime->getAcquisitionTime(0)<<
00148                      ", data[2]:"<<rangefinderDataAndTime->getDistance(0)<<", time[2]:"<<rangefinderDataAndTime->getAcquisitionTime(0)<<
00149                      ", data[3]:"<<rangefinderDataAndTime->getDistance(0)<<", time[3]:"<<rangefinderDataAndTime->getAcquisitionTime(0)<<
00150                      ", data[4]:"<<rangefinderDataAndTime->getDistance(0)<<", time[4]:"<<rangefinderDataAndTime->getAcquisitionTime(0)<<".");
00151     }
00152   }
00153 
00154   void rochHardware::getPlatAccData()
00155   {
00156 
00157     core::Channel<sawyer::DataPlatformAcceleration>::Ptr getPlatformAccData = 
00158     core::Channel<sawyer::DataPlatformAcceleration>::requestData(polling_timeout_);
00159     publishRawData();
00160     if(getPlatformAccData){
00161 
00162       ROS_DEBUG_STREAM("Received acc_x:"<<getPlatformAccData->getX()<<", acc_y:"<<getPlatformAccData->getY()<<", acc_z:"<<getPlatformAccData->getZ()<<".");
00163  
00164       sixGyro.acc.X = getPlatformAccData->getX() - sixGyro.acc.X_Offset;
00165       sixGyro.acc.Y = getPlatformAccData->getY() - sixGyro.acc.Y_Offset;
00166       sixGyro.acc.Z = getPlatformAccData->getZ() - sixGyro.acc.Z_Offset;
00167     
00168       linear_acceleration[0] = sixGyro.acc.X;
00169       linear_acceleration[1] = sixGyro.acc.Y;
00170       linear_acceleration[2] = sixGyro.acc.Z;
00171       imuMsgData.linear_acceleration = linear_acceleration;
00172     }
00173   
00174   }
00175 
00176   void rochHardware::getPlatformName()
00177   { 
00178     core::Channel<sawyer::DataPlatformName>::Ptr getPlatformName = 
00179     core::Channel<sawyer::DataPlatformName>::requestData(polling_timeout_);
00180     publishRawData();
00181  
00182     if(getPlatformName){
00183       ROS_DEBUG_STREAM("Received platform name:"<<getPlatformName->getName());   
00184     }
00185 
00186   }
00187 
00188   void rochHardware::getDifferentControlConstantData()
00189   {
00190 
00191     core::Channel<sawyer::DataDifferentialControl>::Ptr getDifferentControlConstantData = 
00192     core::Channel<sawyer::DataDifferentialControl>::requestData(polling_timeout_);
00193     publishRawData();
00194     if(getDifferentControlConstantData){
00195        ROS_DEBUG_STREAM("Received Data of Differential Control Data, Left_P:"<<getDifferentControlConstantData->getLeftP()<<", Left_I:"<<getDifferentControlConstantData->getLeftI()<<", Left_D:"<<getDifferentControlConstantData->getLeftD()<<
00196        ",right_P:"<<getDifferentControlConstantData->getRightP()<<", right_I:"<<getDifferentControlConstantData->getRightI()<<", right_D:"<<getDifferentControlConstantData->getRightD()<<".");
00197  
00198      }
00199     
00200    }
00201 
00202   
00206   void rochHardware::initializeDiagnostics()
00207   {
00208     core::Channel<sawyer::DataPlatformInfo>::Ptr info =
00209       core::Channel<sawyer::DataPlatformInfo>::requestData(polling_timeout_);
00210       if(info){
00211       std::ostringstream hardware_id_stream;
00212       hardware_id_stream << "roch " << info->getModel() << "-" << info->getSerial();
00213       diagnostic_updater_.setHardwareID(hardware_id_stream.str());
00214       diagnostic_updater_.add(system_status_task_);
00215       diagnostic_updater_.add(power_status_task_);
00216       diagnostic_updater_.add(safety_status_task_);
00217       diagnostic_updater_.add(software_status_task_);
00218     }
00219     diagnostic_publisher_ = nh_.advertise<roch_msgs::RochStatus>("status", 10);  
00220     raw_data_command_publisher_ = nh_.advertise<std_msgs::String>("debug/raw_data_command",100);
00221     
00222     //Obstacle detection publish
00223     cliff_event_publisher_ = nh_.advertise < roch_msgs::CliffEvent > ("events/cliff", 100);
00224     psd_event_publisher_ = nh_.advertise < roch_msgs::PSDEvent > ("events/psd", 100);
00225     ult_event_publisher_ = nh_.advertise < roch_msgs::UltEvent > ("events/ult", 100);
00226     sensor_state_publisher_ = nh_.advertise < roch_msgs::SensorState > ("core_sensors", 100);
00227   }
00228 
00229 
00233   void rochHardware::registerControlInterfaces()
00234   {    
00235          ros::V_string joint_names = boost::assign::list_of("front_left_wheel")
00236          ("front_right_wheel");
00237         imuMsgData.name="roch_sensor_controller/imu/data";
00238         imuMsgData.frame_id=gyro_link_frame_;
00239 
00240         orientation_covariance[0] =  0.001*0.001;
00241         orientation_covariance[1] =  0;
00242         orientation_covariance[2] =  0;
00243         orientation_covariance[3] =  0;
00244         orientation_covariance[4] =  0.001*0.001;
00245         orientation_covariance[5] =  0;
00246         orientation_covariance[6] =  0;
00247         orientation_covariance[7] =  0;
00248         orientation_covariance[8] =  0.001*0.001;
00249         
00250         angular_velocity_covariance[0] =  0.001*0.001;
00251         angular_velocity_covariance[1] =  0;
00252         angular_velocity_covariance[2] =  0;
00253         angular_velocity_covariance[3] =  0;
00254         angular_velocity_covariance[4] =  0.001*0.001;
00255         angular_velocity_covariance[5] =  0;
00256         angular_velocity_covariance[6] =  0;
00257         angular_velocity_covariance[7] =  0;
00258         angular_velocity_covariance[8] =  0.001*0.001;
00259         
00260         linear_acceleration_covariance[0] = 0.001*0.001;
00261         linear_acceleration_covariance[1] = 0;
00262         linear_acceleration_covariance[2] = 0;
00263         linear_acceleration_covariance[3] = 0;
00264         linear_acceleration_covariance[4] = 0.001*0.001;
00265         linear_acceleration_covariance[5] = 0;
00266         linear_acceleration_covariance[6] = 0;
00267         linear_acceleration_covariance[7] = 0;
00268         linear_acceleration_covariance[8] = 0.001*0.001;
00269 
00270         geometry_msgs::Quaternion orien =  tf::createQuaternionMsgFromRollPitchYaw(0.0, 0.0, sixGyro.angle);
00271         orientation[0] = orien.y;
00272         orientation[1] = orien.x;
00273         orientation[2] = orien.z;
00274         orientation[3] = orien.w;
00275         imuMsgData.orientation =  orientation;
00276         imuMsgData.orientation_covariance =  orientation_covariance;
00277         imuMsgData.angular_velocity_covariance = angular_velocity_covariance;
00278         imuMsgData.linear_acceleration_covariance = linear_acceleration_covariance;
00279         angular_velocity[0] = 0.0;
00280         angular_velocity[1] = 0.0;
00281         angular_velocity[2] = sixGyro.angle_rate;
00282         imuMsgData.angular_velocity = angular_velocity;
00283         
00284         linear_acceleration[0] = sixGyro.acc.Y;
00285         linear_acceleration[1] = sixGyro.acc.X;
00286         linear_acceleration[2] = -sixGyro.acc.Z;
00287         
00288         imuMsgData.linear_acceleration = linear_acceleration;
00289     for (unsigned int i = 0; i < joint_names.size(); i++)
00290     {
00291       hardware_interface::JointStateHandle joint_state_handle(joint_names[i],
00292                                                               &joints_[i].position, &joints_[i].velocity,
00293                                                               &joints_[i].effort);
00294       joint_state_interface_.registerHandle(joint_state_handle);
00295 
00296       hardware_interface::JointHandle joint_handle(
00297         joint_state_handle, &joints_[i].velocity_command);
00298       velocity_joint_interface_.registerHandle(joint_handle);
00299       std::cout<<"Received joint_names["<<i<<"]:"<<joint_names[i]<<std::endl;
00300       ROS_DEBUG_STREAM("Received joint["<<i<<"].position:"<<joints_[i].position<<", joint["<<i<<"].velocity:"<<joints_[i].velocity<<", joint["<<i<<"].effort:"<<joints_[i].effort<<"."); 
00301     }
00302     hardware_interface::ImuSensorHandle imu_sensor_handle(imuMsgData);
00303    
00304     imu_sensor_interface_.registerHandle(imu_sensor_handle);
00305     registerInterface(&joint_state_interface_);
00306     registerInterface(&velocity_joint_interface_);
00307     registerInterface(&imu_sensor_interface_);
00308   }
00309 
00313   void rochHardware::updateDiagnostics()
00314   {
00315     diagnostic_updater_.force_update();
00316     roch_status_msg_.header.stamp = ros::Time::now();
00317     diagnostic_publisher_.publish(roch_status_msg_);
00318   }
00319   
00320   
00324   void rochHardware::updateJointsFromHardware()
00325   {
00326 
00327     for(int i=0;i<2;i++){ 
00328        ROS_DEBUG_STREAM("Received joint["<<i<<"].position:"<<joints_[i].position<<", joint["<<i<<"].velocity:"<<joints_[i].velocity<<", joint["<<i<<"].effort:"<<joints_[i].effort<<"."); 
00329     } 
00330 
00331     core::Channel<sawyer::DataEncoders>::Ptr enc = core::Channel<sawyer::DataEncoders>::requestData(
00332       polling_timeout_);
00333       publishRawData();
00334  
00335     if (enc)
00336     { 
00337       ROS_DEBUG_STREAM("Received travel information (L:" << enc->getTravel(LEFT) << " R:" << enc->getTravel(RIGHT) << ")");
00338       for (int i = 0; i < 2; i++)
00339       {
00340         double delta = linearToAngular(enc->getTravel(i % 2)) - joints_[i].position - joints_[i].position_offset;
00341         // detect suspiciously large readings, possibly from encoder rollover
00342         if (std::abs(delta) < 2.0)
00343         {
00344           joints_[i].position += delta;
00345               ROS_DEBUG_STREAM("jiounts_["<<i<<"].postion:"<<joints_[i].position<<",delta:"<<delta<<".");
00346         }
00347         else
00348         {
00349           // suspicious! drop this measurement and update the offset for subsequent readings
00350           joints_[i].position_offset += delta;
00351               ROS_DEBUG_STREAM("jiounts_["<<i<<"].position_offset:"<<joints_[i].position_offset<<",delta:"<<delta<<".");
00352         }
00353       }
00354       
00355     }
00356     core::Channel<sawyer::DataDifferentialSpeed>::Ptr speed = core::Channel<sawyer::DataDifferentialSpeed>::requestData(
00357       polling_timeout_);
00358     publishRawData();
00359     if (speed)
00360     {
00361       ROS_DEBUG_STREAM("Received linear speed information (L:" << speed->getLeftSpeed() << " R:" << speed->getRightSpeed() << ")");
00362       for (int i = 0; i < 2; i++)
00363       {
00364         if (i % 2 == LEFT)
00365         {
00366           joints_[i].velocity = linearToAngular(speed->getLeftSpeed());
00367               ROS_DEBUG_STREAM("jiounts_["<<i<<"].velocity:"<<joints_[i].velocity<<".");
00368         }
00369         else
00370         { // assume RIGHT
00371               ROS_DEBUG_STREAM("jiounts_["<<i<<"].velocity:"<<joints_[i].velocity<<".");
00372           joints_[i].velocity = linearToAngular(speed->getRightSpeed());
00373         }
00374       }
00375     }
00376     core::Channel<sawyer::DataVelocity>::Ptr overallspeed = core::Channel<sawyer::DataVelocity>::requestData(
00377       polling_timeout_);
00378       publishRawData();
00379     if (overallspeed)
00380     {
00381       ROS_DEBUG_STREAM("Received  speed information (speed:" << overallspeed->getTranslational() << " Rotational:" << overallspeed->getRotational()<<" Acceleration:"<<overallspeed->getTransAccel() << ")");    
00382     }
00383     
00384     core::Channel<sawyer::Data6AxisYaw>::Ptr imuRateData = core::Channel<sawyer::Data6AxisYaw>::requestData(
00385      polling_timeout_);
00386     publishRawData();
00387     if(imuRateData){
00388       ROS_DEBUG_STREAM("Received  imu rate data information (Angle:" << imuRateData->getAngle() << " Angle rate:" << imuRateData->getAngleRate() << ")");
00389       sixGyro.angle = imuRateData->getAngle() - sixGyro.angle_offset;
00390       sixGyro.angle_rate = imuRateData->getAngleRate();
00391         
00392       geometry_msgs::Quaternion orien =  tf::createQuaternionMsgFromRollPitchYaw(0.0, 0.0, sixGyro.angle);
00393       orientation[0] = orien.x;
00394       orientation[1] = orien.y;
00395       orientation[2] = orien.z;
00396       orientation[3] = orien.w;
00397       imuMsgData.orientation = orientation;
00398       ROS_DEBUG_STREAM("Received imu msg data, orientation.x:"<<imuMsgData.orientation[0]<<", orientation.y:"<<imuMsgData.orientation[1]<<", orientation.z:"<<imuMsgData.orientation[2]<<", orientation.w:"<<imuMsgData.orientation[3]<<".");
00399 
00400       angular_velocity[0] = 0.0;
00401       angular_velocity[1] = 0.0;
00402       angular_velocity[2] = sixGyro.angle_rate;
00403       imuMsgData.angular_velocity = angular_velocity;
00404     } 
00405     getPlatAccData();
00406     getRangefinderData();
00407     getDifferentControlConstantData();
00408     getPlatformName();
00409   }
00410 
00414   void rochHardware::writeCommandsToHardware()
00415   {
00416     double diff_speed_left = angularToLinear(joints_[LEFT].velocity_command);
00417     double diff_speed_right = angularToLinear(joints_[RIGHT].velocity_command);
00418 
00419     ROS_DEBUG_STREAM("diff_speed_left:"<<diff_speed_left<<",joints_[LEFT].velocity_command:"<<joints_[LEFT].velocity_command<<".");
00420     ROS_DEBUG_STREAM("diff_speed_right:"<<diff_speed_left<<",joints_[RIGHT].velocity_command:"<<joints_[RIGHT].velocity_command<<".");
00421 
00422     limitDifferentialSpeed(diff_speed_left, diff_speed_right);
00423     core::controlSpeed(diff_speed_left, diff_speed_right, max_accel_, max_accel_);
00424     publishRawData();
00425     
00426     publishSensorState();
00427   }
00428 
00432   void rochHardware::writeOverallSpeedCommandsToHardware()
00433   {    
00434     double diff_speed_left = angularToLinear(joints_[LEFT].velocity_command);
00435     double diff_speed_right = angularToLinear(joints_[RIGHT].velocity_command);
00436     limitDifferentialSpeed(diff_speed_left, diff_speed_right);
00437     publishRawData();
00438     core::controloverallSpeed(diff_speed_left, diff_speed_right, max_accel_, max_accel_);   
00439     publishRawData();
00440   }
00441   
00442   void rochHardware::publishRawData()
00443   {
00444     if ( raw_data_command_publisher_.getNumSubscribers() > 0 ) { // do not do string processing if there is no-one listening.
00445       std::ostringstream ostream;
00446       sawyer::base_data::RawData data =sawyer::Transport::instance().getdata();
00447       ostream << "{ " ;
00448       ostream << std::setfill('0') << std::uppercase;
00449       for (unsigned int i=0; i < data.length; i++)
00450           ostream << std::hex << std::setw(2) << static_cast<unsigned int>(data.data[i]) << " " << std::dec;
00451       ostream << "}";
00452       std_msgs::StringPtr msg(new std_msgs::String);
00453       msg->data = ostream.str();
00454       if (ros::ok())
00455       {
00456         raw_data_command_publisher_.publish(msg);
00457       }
00458     }
00459   }
00460 
00461   void rochHardware::publishCliffEvent(const double &left, const double &right)
00462   {
00463     leftcliffevent.sensor = CliffEvent::Left;    
00464     if(left>cliff_height_)
00465        leftcliffevent.state = CliffEvent::Cliff;
00466     else    
00467        leftcliffevent.state = CliffEvent::Floor;
00468     leftcliffevent.leftbottom = left;
00469   
00470     rightcliffevent.sensor = CliffEvent::Right;
00471     if(right>cliff_height_)
00472        rightcliffevent.state = CliffEvent::Cliff;
00473     else    
00474        rightcliffevent.state = CliffEvent::Floor;
00475     rightcliffevent.rightbottom = right;   
00476   
00477     if (cliff_event_publisher_.getNumSubscribers()>0)
00478     {
00479       roch_msgs::CliffEventPtr msg(new roch_msgs::CliffEvent);
00480       switch(leftcliffevent.state) {
00481         case(CliffEvent::Floor) : { msg->leftState = roch_msgs::CliffEvent::FLOOR; break; }
00482         case(CliffEvent::Cliff) : { msg->leftState = roch_msgs::CliffEvent::CLIFF; break; }
00483         default: break;
00484       }
00485       switch(rightcliffevent.state) {
00486         case(CliffEvent::Floor) : { msg->rightState = roch_msgs::CliffEvent::FLOOR; break; }
00487         case(CliffEvent::Cliff) : { msg->rightState = roch_msgs::CliffEvent::CLIFF; break; }
00488         default: break;
00489       }
00490       msg->leftSensor = roch_msgs::CliffEvent::LEFT;
00491       msg->rightSensor = roch_msgs::CliffEvent::RIGHT;
00492       msg->leftBottom = leftcliffevent.leftbottom;
00493       msg->rightBottom = rightcliffevent.rightbottom;
00494       cliff_event_publisher_.publish(msg);
00495     }
00496   }
00497 
00498   void rochHardware::publishUltEvent(const double &left, const double &center, const double &right){
00499   
00500     leftultevent.sensor = UltEvent::Left;    
00501     if(left<ult_length_)
00502        leftultevent.state = UltEvent::Near;
00503     else    
00504        leftultevent.state = UltEvent::Normal;
00505     leftultevent.leftbottom = left;
00506 
00507     centerultevent.sensor = UltEvent::Center;    
00508     if(center<ult_length_)
00509        centerultevent.state = UltEvent::Near;
00510     else    
00511        centerultevent.state = UltEvent::Normal;
00512     centerultevent.centerbottom = center;
00513   
00514     rightultevent.sensor = UltEvent::Right;
00515     if(right<ult_length_)
00516        rightultevent.state = UltEvent::Near;
00517     else    
00518        rightultevent.state = UltEvent::Normal;
00519     rightultevent.rightbottom = right;   
00520   
00521     if (ult_event_publisher_.getNumSubscribers()>0)
00522     {
00523       roch_msgs::UltEventPtr msg(new roch_msgs::UltEvent);
00524       switch(leftultevent.state) {
00525         case(UltEvent::Normal) : { msg->leftState = roch_msgs::UltEvent::NORMAL; break; }
00526         case(UltEvent::Near) : { msg->leftState = roch_msgs::UltEvent::NEAR; break; }
00527         default: break;
00528       }
00529       switch(centerultevent.state) {
00530         case(UltEvent::Normal) : { msg->centerState = roch_msgs::UltEvent::NORMAL; break; }
00531         case(UltEvent::Near) : { msg->centerState = roch_msgs::UltEvent::NEAR; break; }
00532         default: break;
00533       }
00534       switch(rightultevent.state) {
00535         case(UltEvent::Normal) : { msg->rightState = roch_msgs::UltEvent::NORMAL; break; }
00536         case(UltEvent::Near) : { msg->rightState = roch_msgs::UltEvent::NEAR; break; }
00537         default: break;
00538       }
00539       msg->leftSensor = roch_msgs::UltEvent::LEFT;
00540       msg->centerSensor = roch_msgs::UltEvent::CENTER;
00541       msg->rightSensor = roch_msgs::UltEvent::RIGHT;
00542       msg->leftBottom = leftultevent.leftbottom;
00543       msg->centerBottom = centerultevent.centerbottom;
00544       msg->rightBottom = rightultevent.rightbottom;
00545       ult_event_publisher_.publish(msg);
00546     }
00547   }
00548 
00549 
00550   /*****************************************************************************
00551   ** Publish Sensor Stream Workers
00552   *****************************************************************************/
00553   void rochHardware::publishSensorState()
00554   {
00555     if(sensor_state_publisher_.getNumSubscribers()>0){
00556       cliffbottom.clear();
00557       ultbottom.clear();
00558       psdbottom.clear();
00559       roch_msgs::SensorState statecore;
00560       statecore.header.stamp = ros::Time::now();
00561       statecore.leftcliff = leftcliffevent.state;
00562       statecore.rightcliff = rightcliffevent.state;
00563       statecore.leftult = leftultevent.state;
00564       statecore.centerult = centerultevent.state;
00565       statecore.rightult = rightultevent.state;
00566       statecore.leftpsd = leftpsdevent.state;
00567       statecore.centerpsd = centerpsdevent.state;
00568       statecore.rightpsd = rightpsdevent.state;
00569 
00570       cliffbottom.push_back(leftcliffevent.leftbottom);
00571       cliffbottom.push_back(rightcliffevent.rightbottom);
00572     
00573       ultbottom.push_back(leftultevent.leftbottom);
00574       ultbottom.push_back(centerultevent.centerbottom);
00575       ultbottom.push_back(rightultevent.rightbottom);
00576     
00577       psdbottom.push_back(leftpsdevent.leftbottom);
00578       psdbottom.push_back(centerpsdevent.centerbottom);
00579       psdbottom.push_back(rightpsdevent.rightbottom);
00580       statecore.cliffbottom = cliffbottom;
00581       statecore.ultbottom = ultbottom;
00582       statecore.psdbottom = psdbottom;
00583       sensor_state_publisher_.publish(statecore);  
00584     }
00585   }
00586 
00587   void rochHardware::publishPSDEvent(const double& left, const double& center, const double& right)
00588   {
00589   
00590     leftpsdevent.sensor = PSDEvent::Left;    
00591     if(left<PSD_length_)
00592        leftpsdevent.state = PSDEvent::Near;
00593     else    
00594        leftpsdevent.state = PSDEvent::Normal;
00595     leftpsdevent.leftbottom = left;
00596 
00597     centerpsdevent.sensor = PSDEvent::Center;    
00598     if(center<PSD_length_)
00599        centerpsdevent.state = PSDEvent::Near;
00600     else    
00601        centerpsdevent.state = PSDEvent::Normal;
00602     centerpsdevent.centerbottom = center;
00603   
00604     rightpsdevent.sensor = PSDEvent::Right;
00605     if(right<PSD_length_)
00606        rightpsdevent.state = PSDEvent::Near;
00607     else    
00608        rightpsdevent.state = PSDEvent::Normal;
00609     rightpsdevent.rightbottom = right;   
00610   
00611     if (psd_event_publisher_.getNumSubscribers()>0)
00612     {
00613       roch_msgs::PSDEventPtr msg(new roch_msgs::PSDEvent);
00614       switch(leftpsdevent.state) {
00615         case(PSDEvent::Normal) : { msg->leftState = roch_msgs::PSDEvent::NORMAL; break; }
00616         case(PSDEvent::Near) : { msg->leftState = roch_msgs::PSDEvent::NEAR; break; }
00617         default: break;
00618       }
00619       switch(centerpsdevent.state) {
00620         case(PSDEvent::Normal) : { msg->centerState = roch_msgs::PSDEvent::NORMAL; break; }
00621         case(PSDEvent::Near) : { msg->centerState = roch_msgs::PSDEvent::NEAR; break; }
00622         default: break;
00623       }
00624       switch(rightpsdevent.state) {
00625         case(PSDEvent::Normal) : { msg->rightState = roch_msgs::PSDEvent::NORMAL; break; }
00626         case(PSDEvent::Near) : { msg->rightState = roch_msgs::PSDEvent::NEAR; break; }
00627         default: break;
00628       }
00629       msg->leftSensor = roch_msgs::PSDEvent::LEFT;
00630       msg->centerSensor = roch_msgs::PSDEvent::CENTER;
00631       msg->rightSensor = roch_msgs::PSDEvent::RIGHT;
00632       msg->leftBottom = leftpsdevent.leftbottom;
00633       msg->centerBottom = centerpsdevent.centerbottom;
00634       msg->rightBottom = rightpsdevent.rightbottom;
00635       psd_event_publisher_.publish(msg);
00636     }
00637   }
00638 
00642   void rochHardware::reportLoopDuration(const ros::Duration &duration)
00643   {
00644     software_status_task_.updateControlFrequency(1 / duration.toSec());
00645   }
00646 
00650   void rochHardware::limitDifferentialSpeed(double &diff_speed_left, double &diff_speed_right)
00651   {
00652     double large_speed = std::max(std::abs(diff_speed_left), std::abs(diff_speed_right));
00653 
00654     if (large_speed > max_speed_)
00655     {
00656       diff_speed_left *= max_speed_ / large_speed;
00657       diff_speed_right *= max_speed_ / large_speed;
00658     }
00659   }
00660 
00664   double rochHardware::linearToAngular(const double &travel) const
00665   {
00666     return travel / wheel_diameter_ * 2;
00667   }
00668 
00672   double rochHardware::angularToLinear(const double &angle) const
00673   {
00674     return angle * wheel_diameter_ / 2;
00675   }
00676 
00677 
00678 }  // namespace roch_base


roch_base
Author(s): Mike Purvis , Paul Bovbel , Carl
autogenerated on Sat Jun 8 2019 20:32:33