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);
00061 private_nh_.param<double>("ult_length", ult_length_, 0.1);
00062 private_nh_.param<double>("psd_length", PSD_length_, 0.1);
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
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
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
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
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 {
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 ) {
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 ¢er, 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
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 }