create_driver.cpp
Go to the documentation of this file.
00001 #include <tf/transform_datatypes.h>
00002 #include "create_driver/create_driver.h"
00003 
00004 CreateDriver::CreateDriver(ros::NodeHandle& nh)
00005   : nh_(nh),
00006     priv_nh_("~"),
00007     diagnostics_(),
00008     model_(create::RobotModel::CREATE_2),
00009     is_running_slowly_(false)
00010 {
00011   bool create_one;
00012   std::string robot_model_name;
00013   priv_nh_.param<std::string>("dev", dev_, "/dev/ttyUSB0");
00014   priv_nh_.param<std::string>("robot_model", robot_model_name, "CREATE_2");
00015   priv_nh_.param<std::string>("base_frame", base_frame_, "base_footprint");
00016   priv_nh_.param<std::string>("odom_frame", odom_frame_, "odom");
00017   priv_nh_.param<double>("latch_cmd_duration", latch_duration_, 0.2);
00018   priv_nh_.param<double>("loop_hz", loop_hz_, 10.0);
00019   priv_nh_.param<bool>("publish_tf", publish_tf_, true);
00020 
00021   if (robot_model_name == "ROOMBA_400")
00022   {
00023     model_ = create::RobotModel::ROOMBA_400;
00024   }
00025   else if (robot_model_name == "CREATE_1")
00026   {
00027     model_ = create::RobotModel::CREATE_1;
00028   }
00029   else if (robot_model_name == "CREATE_2")
00030   {
00031     model_ = create::RobotModel::CREATE_2;
00032   }
00033   else
00034   {
00035     ROS_FATAL_STREAM("[CREATE] Robot model \"" + robot_model_name + "\" is not known.");
00036     ros::shutdown();
00037     return;
00038   }
00039 
00040   ROS_INFO_STREAM("[CREATE] \"" << robot_model_name << "\" selected");
00041 
00042   priv_nh_.param<int>("baud", baud_, model_.getBaud());
00043 
00044   robot_ = new create::Create(model_);
00045 
00046   if (!robot_->connect(dev_, baud_))
00047   {
00048     ROS_FATAL("[CREATE] Failed to establish serial connection with Create.");
00049     ros::shutdown();
00050   }
00051 
00052   ROS_INFO("[CREATE] Connection established.");
00053 
00054   // Start in full control mode
00055   robot_->setMode(create::MODE_FULL);
00056 
00057   // Show robot's battery level
00058   ROS_INFO("[CREATE] Battery level %.2f %%", (robot_->getBatteryCharge() / robot_->getBatteryCapacity()) * 100.0);
00059 
00060   // Set frame_id's
00061   mode_msg_.header.frame_id = base_frame_;
00062   bumper_msg_.header.frame_id = base_frame_;
00063   charging_state_msg_.header.frame_id = base_frame_;
00064   tf_odom_.header.frame_id = odom_frame_;
00065   tf_odom_.child_frame_id = base_frame_;
00066   odom_msg_.header.frame_id = odom_frame_;
00067   odom_msg_.child_frame_id = base_frame_;
00068   joint_state_msg_.name.resize(2);
00069   joint_state_msg_.position.resize(2);
00070   joint_state_msg_.velocity.resize(2);
00071   joint_state_msg_.effort.resize(2);
00072   joint_state_msg_.name[0] = "left_wheel_joint";
00073   joint_state_msg_.name[1] = "right_wheel_joint";
00074 
00075   // Populate intial covariances
00076   for (int i = 0; i < 36; i++)
00077   {
00078     odom_msg_.pose.covariance[i] = COVARIANCE[i];
00079     odom_msg_.twist.covariance[i] = COVARIANCE[i];
00080   }
00081 
00082   // Setup subscribers
00083   cmd_vel_sub_ = nh.subscribe("cmd_vel", 1, &CreateDriver::cmdVelCallback, this);
00084   debris_led_sub_ = nh.subscribe("debris_led", 10, &CreateDriver::debrisLEDCallback, this);
00085   spot_led_sub_ = nh.subscribe("spot_led", 10, &CreateDriver::spotLEDCallback, this);
00086   dock_led_sub_ = nh.subscribe("dock_led", 10, &CreateDriver::dockLEDCallback, this);
00087   check_led_sub_ = nh.subscribe("check_led", 10, &CreateDriver::checkLEDCallback, this);
00088   power_led_sub_ = nh.subscribe("power_led", 10, &CreateDriver::powerLEDCallback, this);
00089   set_ascii_sub_ = nh.subscribe("set_ascii", 10, &CreateDriver::setASCIICallback, this);
00090   dock_sub_ = nh.subscribe("dock", 10, &CreateDriver::dockCallback, this);
00091   undock_sub_ = nh.subscribe("undock", 10, &CreateDriver::undockCallback, this);
00092   define_song_sub_ = nh.subscribe("define_song", 10, &CreateDriver::defineSongCallback, this);
00093   play_song_sub_ = nh.subscribe("play_song", 10, &CreateDriver::playSongCallback, this);
00094 
00095   // Setup publishers
00096   odom_pub_ = nh.advertise<nav_msgs::Odometry>("odom", 30);
00097   clean_btn_pub_ = nh.advertise<std_msgs::Empty>("clean_button", 30);
00098   day_btn_pub_ = nh.advertise<std_msgs::Empty>("day_button", 30);
00099   hour_btn_pub_ = nh.advertise<std_msgs::Empty>("hour_button", 30);
00100   min_btn_pub_ = nh.advertise<std_msgs::Empty>("minute_button", 30);
00101   dock_btn_pub_ = nh.advertise<std_msgs::Empty>("dock_button", 30);
00102   spot_btn_pub_ = nh.advertise<std_msgs::Empty>("spot_button", 30);
00103   voltage_pub_ = nh.advertise<std_msgs::Float32>("battery/voltage", 30);
00104   current_pub_ = nh.advertise<std_msgs::Float32>("battery/current", 30);
00105   charge_pub_ = nh.advertise<std_msgs::Float32>("battery/charge", 30);
00106   charge_ratio_pub_ = nh.advertise<std_msgs::Float32>("battery/charge_ratio", 30);
00107   capacity_pub_ = nh.advertise<std_msgs::Float32>("battery/capacity", 30);
00108   temperature_pub_ = nh.advertise<std_msgs::Int16>("battery/temperature", 30);
00109   charging_state_pub_ = nh.advertise<ca_msgs::ChargingState>("battery/charging_state", 30);
00110   omni_char_pub_ = nh.advertise<std_msgs::UInt16>("ir_omni", 30);
00111   mode_pub_ = nh.advertise<ca_msgs::Mode>("mode", 30);
00112   bumper_pub_ = nh.advertise<ca_msgs::Bumper>("bumper", 30);
00113   wheeldrop_pub_ = nh.advertise<std_msgs::Empty>("wheeldrop", 30);
00114   wheel_joint_pub_ = nh.advertise<sensor_msgs::JointState>("joint_states", 10);
00115 
00116   // Setup diagnostics
00117   diagnostics_.add("Battery Status", this, &CreateDriver::updateBatteryDiagnostics);
00118   diagnostics_.add("Safety Status", this, &CreateDriver::updateSafetyDiagnostics);
00119   diagnostics_.add("Serial Status", this, &CreateDriver::updateSerialDiagnostics);
00120   diagnostics_.add("Base Mode", this, &CreateDriver::updateModeDiagnostics);
00121   diagnostics_.add("Driver Status", this, &CreateDriver::updateDriverDiagnostics);
00122 
00123   diagnostics_.setHardwareID(robot_model_name);
00124 
00125   ROS_INFO("[CREATE] Ready.");
00126 }
00127 
00128 CreateDriver::~CreateDriver()
00129 {
00130   ROS_INFO("[CREATE] Destruct sequence initiated.");
00131   robot_->disconnect();
00132   delete robot_;
00133 }
00134 
00135 void CreateDriver::cmdVelCallback(const geometry_msgs::TwistConstPtr& msg)
00136 {
00137   robot_->drive(msg->linear.x, msg->angular.z);
00138   last_cmd_vel_time_ = ros::Time::now();
00139 }
00140 
00141 void CreateDriver::debrisLEDCallback(const std_msgs::BoolConstPtr& msg)
00142 {
00143   robot_->enableDebrisLED(msg->data);
00144 }
00145 
00146 void CreateDriver::spotLEDCallback(const std_msgs::BoolConstPtr& msg)
00147 {
00148   robot_->enableSpotLED(msg->data);
00149 }
00150 
00151 void CreateDriver::dockLEDCallback(const std_msgs::BoolConstPtr& msg)
00152 {
00153   robot_->enableDockLED(msg->data);
00154 }
00155 
00156 void CreateDriver::checkLEDCallback(const std_msgs::BoolConstPtr& msg)
00157 {
00158   robot_->enableCheckRobotLED(msg->data);
00159 }
00160 
00161 void CreateDriver::powerLEDCallback(const std_msgs::UInt8MultiArrayConstPtr& msg)
00162 {
00163   if (msg->data.size() < 1)
00164   {
00165     ROS_ERROR("[CREATE] No values provided to set power LED");
00166   }
00167   else
00168   {
00169     if (msg->data.size() < 2)
00170     {
00171       robot_->setPowerLED(msg->data[0]);
00172     }
00173     else
00174     {
00175       robot_->setPowerLED(msg->data[0], msg->data[1]);
00176     }
00177   }
00178 }
00179 
00180 void CreateDriver::setASCIICallback(const std_msgs::UInt8MultiArrayConstPtr& msg)
00181 {
00182   bool result;
00183   if (msg->data.size() < 1)
00184   {
00185     ROS_ERROR("[CREATE] No ASCII digits provided");
00186   }
00187   else if (msg->data.size() < 2)
00188   {
00189     result = robot_->setDigitsASCII(msg->data[0], ' ', ' ', ' ');
00190   }
00191   else if (msg->data.size() < 3)
00192   {
00193     result = robot_->setDigitsASCII(msg->data[0], msg->data[1], ' ', ' ');
00194   }
00195   else if (msg->data.size() < 4)
00196   {
00197     result = robot_->setDigitsASCII(msg->data[0], msg->data[1], msg->data[2], ' ');
00198   }
00199   else
00200   {
00201     result = robot_->setDigitsASCII(msg->data[0], msg->data[1], msg->data[2], msg->data[3]);
00202   }
00203 
00204   if (!result)
00205   {
00206     ROS_ERROR("[CREATE] ASCII character out of range [32, 126]");
00207   }
00208 }
00209 
00210 void CreateDriver::dockCallback(const std_msgs::EmptyConstPtr& msg)
00211 {
00212   robot_->setMode(create::MODE_PASSIVE);
00213 
00214   if (model_.getVersion() <= create::V_2)
00215     usleep(1000000);  // Create 1 requires a delay (1 sec)
00216 
00217   // Call docking behaviour
00218   robot_->dock();
00219 }
00220 
00221 void CreateDriver::undockCallback(const std_msgs::EmptyConstPtr& msg)
00222 {
00223   // Switch robot back to FULL mode
00224   robot_->setMode(create::MODE_FULL);
00225 }
00226 
00227 void CreateDriver::defineSongCallback(const ca_msgs::DefineSongConstPtr& msg)
00228 {
00229   if (!robot_->defineSong(msg->song, msg->length, &(msg->notes.front()), &(msg->durations.front())))
00230   {
00231     ROS_ERROR_STREAM("[CREATE] Failed to define song " << msg->song << " of length " << msg->length);
00232   }
00233 }
00234 
00235 void CreateDriver::playSongCallback(const ca_msgs::PlaySongConstPtr& msg)
00236 {
00237   if (!robot_->playSong(msg->song))
00238   {
00239     ROS_ERROR_STREAM("[CREATE] Failed to play song " << msg->song);
00240   }
00241 }
00242 
00243 bool CreateDriver::update()
00244 {
00245   publishOdom();
00246   publishJointState();
00247   publishBatteryInfo();
00248   publishButtonPresses();
00249   publishOmniChar();
00250   publishMode();
00251   publishBumperInfo();
00252   publishWheeldrop();
00253 
00254   // If last velocity command was sent longer than latch duration, stop robot
00255   if (ros::Time::now() - last_cmd_vel_time_ >= ros::Duration(latch_duration_))
00256   {
00257     robot_->drive(0, 0);
00258   }
00259 
00260   return true;
00261 }
00262 
00263 void CreateDriver::updateBatteryDiagnostics(diagnostic_updater::DiagnosticStatusWrapper& stat)
00264 {
00265   const float charge = robot_->getBatteryCharge();
00266   const float capacity = robot_->getBatteryCapacity();
00267   const create::ChargingState charging_state = robot_->getChargingState();
00268   const float charge_ratio = charge / capacity;
00269 
00270   if (charging_state == create::CHARGE_FAULT)
00271   {
00272     stat.summary(diagnostic_msgs::DiagnosticStatus::ERROR, "Charging fault reported by base");
00273   }
00274   else if (charge_ratio == 0)
00275   {
00276     stat.summary(diagnostic_msgs::DiagnosticStatus::ERROR, "Battery reports no charge");
00277   }
00278   else if (charge_ratio < 0.1)
00279   {
00280     stat.summary(diagnostic_msgs::DiagnosticStatus::WARN, "Battery reports less than 10% charge");
00281   }
00282   else
00283   {
00284     stat.summary(diagnostic_msgs::DiagnosticStatus::OK, "Battery is OK");
00285   }
00286 
00287   stat.add("Charge (Ah)", charge);
00288   stat.add("Capacity (Ah)", capacity);
00289   stat.add("Temperature (Celsius)", robot_->getTemperature());
00290   stat.add("Current (A)", robot_->getCurrent());
00291   stat.add("Voltage (V)", robot_->getVoltage());
00292 
00293   switch (charging_state)
00294   {
00295     case create::CHARGE_NONE:
00296       stat.add("Charging state", "Not charging");
00297       break;
00298     case create::CHARGE_RECONDITION:
00299       stat.add("Charging state", "Reconditioning");
00300       break;
00301     case create::CHARGE_FULL:
00302       stat.add("Charging state", "Full charge");
00303       break;
00304     case create::CHARGE_TRICKLE:
00305       stat.add("Charging state", "Trickle charging");
00306       break;
00307     case create::CHARGE_WAITING:
00308       stat.add("Charging state", "Waiting");
00309       break;
00310     case create::CHARGE_FAULT:
00311       stat.add("Charging state", "Fault");
00312       break;
00313   }
00314 }
00315 
00316 void CreateDriver::updateSafetyDiagnostics(diagnostic_updater::DiagnosticStatusWrapper& stat)
00317 {
00318   const bool is_wheeldrop = robot_->isWheeldrop();
00319   const bool is_cliff = robot_->isCliff();
00320   if (is_wheeldrop)
00321   {
00322     stat.summary(diagnostic_msgs::DiagnosticStatus::WARN, "Wheeldrop detected");
00323   }
00324   else if (is_cliff)
00325   {
00326     stat.summary(diagnostic_msgs::DiagnosticStatus::WARN, "Cliff detected");
00327   }
00328   else
00329   {
00330     stat.summary(diagnostic_msgs::DiagnosticStatus::OK, "No safety issues detected");
00331   }
00332 
00333   stat.add("Wheeldrop", is_wheeldrop);
00334   stat.add("Cliff", is_cliff);
00335 }
00336 
00337 void CreateDriver::updateSerialDiagnostics(diagnostic_updater::DiagnosticStatusWrapper& stat)
00338 {
00339   const bool is_connected = robot_->connected();
00340   const uint64_t corrupt_packets = robot_->getNumCorruptPackets();
00341   const uint64_t total_packets = robot_->getTotalPackets();
00342 
00343   if (!is_connected)
00344   {
00345     stat.summary(diagnostic_msgs::DiagnosticStatus::ERROR, "Serial port to base not open");
00346   }
00347   else if (corrupt_packets)
00348   {
00349     stat.summary(diagnostic_msgs::DiagnosticStatus::WARN,
00350                  "Corrupt packets detected. If the number of corrupt packets is increasing, data may be unreliable");
00351   }
00352   else
00353   {
00354     stat.summary(diagnostic_msgs::DiagnosticStatus::OK, "Serial connection is good");
00355   }
00356 
00357   stat.add("Corrupt packets", corrupt_packets);
00358   stat.add("Total packets", total_packets);
00359 }
00360 
00361 void CreateDriver::updateModeDiagnostics(diagnostic_updater::DiagnosticStatusWrapper& stat)
00362 {
00363   const create::CreateMode mode = robot_->getMode();
00364   switch (mode)
00365   {
00366     case create::MODE_UNAVAILABLE:
00367       stat.summary(diagnostic_msgs::DiagnosticStatus::ERROR, "Unknown mode of operation");
00368       break;
00369     case create::MODE_OFF:
00370       stat.summary(diagnostic_msgs::DiagnosticStatus::WARN, "Mode is set to OFF");
00371       break;
00372     case create::MODE_PASSIVE:
00373       stat.summary(diagnostic_msgs::DiagnosticStatus::OK, "Mode is set to PASSIVE");
00374       break;
00375     case create::MODE_SAFE:
00376       stat.summary(diagnostic_msgs::DiagnosticStatus::OK, "Mode is set to SAFE");
00377       break;
00378     case create::MODE_FULL:
00379       stat.summary(diagnostic_msgs::DiagnosticStatus::OK, "Mode is set to FULL");
00380       break;
00381   }
00382 }
00383 
00384 void CreateDriver::updateDriverDiagnostics(diagnostic_updater::DiagnosticStatusWrapper& stat)
00385 {
00386   if (is_running_slowly_)
00387   {
00388     stat.summary(diagnostic_msgs::DiagnosticStatus::WARN, "Internal loop running slowly");
00389   }
00390   else
00391   {
00392     stat.summary(diagnostic_msgs::DiagnosticStatus::OK, "Maintaining loop frequency");
00393   }
00394 }
00395 
00396 void CreateDriver::publishOdom()
00397 {
00398   create::Pose pose = robot_->getPose();
00399   create::Vel vel = robot_->getVel();
00400 
00401   // Populate position info
00402   geometry_msgs::Quaternion quat = tf::createQuaternionMsgFromRollPitchYaw(0, 0, pose.yaw);
00403   odom_msg_.header.stamp = ros::Time::now();
00404   odom_msg_.pose.pose.position.x = pose.x;
00405   odom_msg_.pose.pose.position.y = pose.y;
00406   odom_msg_.pose.pose.orientation = quat;
00407 
00408   // Populate velocity info
00409   odom_msg_.twist.twist.linear.x = vel.x;
00410   odom_msg_.twist.twist.linear.y = vel.y;
00411   odom_msg_.twist.twist.angular.z = vel.yaw;
00412 
00413   // Update covariances
00414   odom_msg_.pose.covariance[0] = (double) pose.covariance[0];
00415   odom_msg_.pose.covariance[1] = pose.covariance[1];
00416   odom_msg_.pose.covariance[5] = pose.covariance[2];
00417   odom_msg_.pose.covariance[6] = pose.covariance[3];
00418   odom_msg_.pose.covariance[7] = pose.covariance[4];
00419   odom_msg_.pose.covariance[11] = pose.covariance[5];
00420   odom_msg_.pose.covariance[30] = pose.covariance[6];
00421   odom_msg_.pose.covariance[31] = pose.covariance[7];
00422   odom_msg_.pose.covariance[35] = pose.covariance[8];
00423   odom_msg_.twist.covariance[0] = vel.covariance[0];
00424   odom_msg_.twist.covariance[1] = vel.covariance[1];
00425   odom_msg_.twist.covariance[5] = vel.covariance[2];
00426   odom_msg_.twist.covariance[6] = vel.covariance[3];
00427   odom_msg_.twist.covariance[7] = vel.covariance[4];
00428   odom_msg_.twist.covariance[11] = vel.covariance[5];
00429   odom_msg_.twist.covariance[30] = vel.covariance[6];
00430   odom_msg_.twist.covariance[31] = vel.covariance[7];
00431   odom_msg_.twist.covariance[35] = vel.covariance[8];
00432 
00433   if (publish_tf_)
00434   {
00435     tf_odom_.header.stamp = ros::Time::now();
00436     tf_odom_.transform.translation.x = pose.x;
00437     tf_odom_.transform.translation.y = pose.y;
00438     tf_odom_.transform.rotation = quat;
00439     tf_broadcaster_.sendTransform(tf_odom_);
00440   }
00441 
00442   odom_pub_.publish(odom_msg_);
00443 }
00444 
00445 void CreateDriver::publishJointState() {
00446     // Publish joint states
00447     float wheelRadius = model_.getWheelDiameter() / 2.0;
00448 
00449     joint_state_msg_.header.stamp = ros::Time::now();
00450     joint_state_msg_.position[0] = robot_->getLeftWheelDistance() / wheelRadius;
00451     joint_state_msg_.position[1] = robot_->getRightWheelDistance() / wheelRadius;
00452     joint_state_msg_.velocity[0] = robot_->getRequestedLeftWheelVel() / wheelRadius;
00453     joint_state_msg_.velocity[1] = robot_->getRequestedRightWheelVel() / wheelRadius;
00454     wheel_joint_pub_.publish(joint_state_msg_);
00455 }
00456 
00457 void CreateDriver::publishBatteryInfo()
00458 {
00459   float32_msg_.data = robot_->getVoltage();
00460   voltage_pub_.publish(float32_msg_);
00461   float32_msg_.data = robot_->getCurrent();
00462   current_pub_.publish(float32_msg_);
00463   float32_msg_.data = robot_->getBatteryCharge();
00464   charge_pub_.publish(float32_msg_);
00465   float32_msg_.data = robot_->getBatteryCapacity();
00466   capacity_pub_.publish(float32_msg_);
00467   int16_msg_.data = robot_->getTemperature();
00468   temperature_pub_.publish(int16_msg_);
00469   float32_msg_.data = robot_->getBatteryCharge() / robot_->getBatteryCapacity();
00470   charge_ratio_pub_.publish(float32_msg_);
00471 
00472   const create::ChargingState charging_state = robot_->getChargingState();
00473   charging_state_msg_.header.stamp = ros::Time::now();
00474   switch (charging_state)
00475   {
00476     case create::CHARGE_NONE:
00477       charging_state_msg_.state = charging_state_msg_.CHARGE_NONE;
00478       break;
00479     case create::CHARGE_RECONDITION:
00480       charging_state_msg_.state = charging_state_msg_.CHARGE_RECONDITION;
00481       break;
00482 
00483     case create::CHARGE_FULL:
00484       charging_state_msg_.state = charging_state_msg_.CHARGE_FULL;
00485       break;
00486 
00487     case create::CHARGE_TRICKLE:
00488       charging_state_msg_.state = charging_state_msg_.CHARGE_TRICKLE;
00489       break;
00490 
00491     case create::CHARGE_WAITING:
00492       charging_state_msg_.state = charging_state_msg_.CHARGE_WAITING;
00493       break;
00494 
00495     case create::CHARGE_FAULT:
00496       charging_state_msg_.state = charging_state_msg_.CHARGE_FAULT;
00497       break;
00498   }
00499   charging_state_pub_.publish(charging_state_msg_);
00500 }
00501 
00502 void CreateDriver::publishButtonPresses() const
00503 {
00504   if (robot_->isCleanButtonPressed())
00505   {
00506     clean_btn_pub_.publish(empty_msg_);
00507   }
00508   if (robot_->isDayButtonPressed())
00509   {
00510     day_btn_pub_.publish(empty_msg_);
00511   }
00512   if (robot_->isHourButtonPressed())
00513   {
00514     hour_btn_pub_.publish(empty_msg_);
00515   }
00516   if (robot_->isMinButtonPressed())
00517   {
00518     min_btn_pub_.publish(empty_msg_);
00519   }
00520   if (robot_->isDockButtonPressed())
00521   {
00522     dock_btn_pub_.publish(empty_msg_);
00523   }
00524   if (robot_->isSpotButtonPressed())
00525   {
00526     spot_btn_pub_.publish(empty_msg_);
00527   }
00528 }
00529 
00530 void CreateDriver::publishOmniChar()
00531 {
00532   uint8_t ir_char = robot_->getIROmni();
00533   uint16_msg_.data = ir_char;
00534   omni_char_pub_.publish(uint16_msg_);
00535   // TODO: Publish info based on character, such as dock in sight
00536 }
00537 
00538 void CreateDriver::publishMode()
00539 {
00540   const create::CreateMode mode = robot_->getMode();
00541   mode_msg_.header.stamp = ros::Time::now();
00542   switch (mode)
00543   {
00544     case create::MODE_OFF:
00545       mode_msg_.mode = mode_msg_.MODE_OFF;
00546       break;
00547     case create::MODE_PASSIVE:
00548       mode_msg_.mode = mode_msg_.MODE_PASSIVE;
00549       break;
00550     case create::MODE_SAFE:
00551       mode_msg_.mode = mode_msg_.MODE_SAFE;
00552       break;
00553     case create::MODE_FULL:
00554       mode_msg_.mode = mode_msg_.MODE_FULL;
00555       break;
00556     default:
00557       ROS_ERROR("[CREATE] Unknown mode detected");
00558       break;
00559   }
00560   mode_pub_.publish(mode_msg_);
00561 }
00562 
00563 void CreateDriver::publishBumperInfo()
00564 {
00565   bumper_msg_.header.stamp = ros::Time::now();
00566   bumper_msg_.is_left_pressed = robot_->isLeftBumper();
00567   bumper_msg_.is_right_pressed = robot_->isRightBumper();
00568 
00569   if (model_.getVersion() >= create::V_3)
00570   {
00571     bumper_msg_.is_light_left = robot_->isLightBumperLeft();
00572     bumper_msg_.is_light_front_left = robot_->isLightBumperFrontLeft();
00573     bumper_msg_.is_light_center_left = robot_->isLightBumperCenterLeft();
00574     bumper_msg_.is_light_right = robot_->isLightBumperRight();
00575     bumper_msg_.is_light_front_right = robot_->isLightBumperFrontRight();
00576     bumper_msg_.is_light_center_right = robot_->isLightBumperCenterRight();
00577 
00578     bumper_msg_.light_signal_left = robot_->getLightSignalLeft();
00579     bumper_msg_.light_signal_front_left = robot_->getLightSignalFrontLeft();
00580     bumper_msg_.light_signal_center_left = robot_->getLightSignalCenterLeft();
00581     bumper_msg_.light_signal_right = robot_->getLightSignalRight();
00582     bumper_msg_.light_signal_front_right = robot_->getLightSignalFrontRight();
00583     bumper_msg_.light_signal_center_right = robot_->getLightSignalCenterRight();
00584   }
00585 
00586   bumper_pub_.publish(bumper_msg_);
00587 }
00588 
00589 void CreateDriver::publishWheeldrop()
00590 {
00591   if (robot_->isWheeldrop())
00592     wheeldrop_pub_.publish(empty_msg_);
00593 }
00594 
00595 void CreateDriver::spinOnce()
00596 {
00597   update();
00598   diagnostics_.update();
00599   ros::spinOnce();
00600 }
00601 
00602 void CreateDriver::spin()
00603 {
00604   ros::Rate rate(loop_hz_);
00605   while (ros::ok())
00606   {
00607     spinOnce();
00608 
00609     is_running_slowly_ = !rate.sleep();
00610     if (is_running_slowly_)
00611     {
00612       ROS_WARN("[CREATE] Loop running slowly.");
00613     }
00614   }
00615 }
00616 
00617 int main(int argc, char** argv)
00618 {
00619   ros::init(argc, argv, "ca_driver");
00620   ros::NodeHandle nh;
00621 
00622   CreateDriver create_driver(nh);
00623 
00624   try
00625   {
00626     create_driver.spin();
00627   }
00628   catch (std::runtime_error& ex)
00629   {
00630     ROS_FATAL_STREAM("[CREATE] Runtime error: " << ex.what());
00631     return 1;
00632   }
00633   return 0;
00634 }


ca_driver
Author(s): Jacob Perron
autogenerated on Thu Apr 20 2017 02:24:49