slot_callbacks.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2012, Yujin Robot.
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  *     * Redistributions of source code must retain the above copyright
00009  *       notice, this list of conditions and the following disclaimer.
00010  *     * Redistributions in binary form must reproduce the above copyright
00011  *       notice, this list of conditions and the following disclaimer in the
00012  *       documentation and/or other materials provided with the distribution.
00013  *     * Neither the name of Yujin Robot nor the names of its
00014  *       contributors may be used to endorse or promote products derived from
00015  *       this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027  * POSSIBILITY OF SUCH DAMAGE.
00028  */
00036 /*****************************************************************************
00037 ** Includes
00038 *****************************************************************************/
00039 
00040 #include "kobuki_node/kobuki_ros.hpp"
00041 
00042 /*****************************************************************************
00043  ** Namespaces
00044  *****************************************************************************/
00045 
00046 namespace kobuki
00047 {
00048 
00049 void KobukiRos::processStreamData() {
00050   publishWheelState();
00051   publishSensorState();
00052   publishDockIRData();
00053   publishInertia();
00054   publishRawInertia();
00055 }
00056 
00057 /*****************************************************************************
00058 ** Publish Sensor Stream Workers
00059 *****************************************************************************/
00060 
00061 void KobukiRos::publishSensorState()
00062 {
00063   if ( ros::ok() ) {
00064     if (sensor_state_publisher.getNumSubscribers() > 0) {
00065       kobuki_msgs::SensorState state;
00066       CoreSensors::Data data = kobuki.getCoreSensorData();
00067       state.header.stamp = ros::Time::now();
00068       state.time_stamp = data.time_stamp; // firmware time stamp
00069       state.bumper = data.bumper;
00070       state.wheel_drop = data.wheel_drop;
00071       state.cliff = data.cliff;
00072       state.left_encoder = data.left_encoder;
00073       state.right_encoder = data.right_encoder;
00074       state.left_pwm = data.left_pwm;
00075       state.right_pwm = data.right_pwm;
00076       state.buttons = data.buttons;
00077       state.charger = data.charger;
00078       state.battery = data.battery;
00079       state.over_current = data.over_current;
00080 
00081       Cliff::Data cliff_data = kobuki.getCliffData();
00082       state.bottom = cliff_data.bottom;
00083 
00084       Current::Data current_data = kobuki.getCurrentData();
00085       state.current = current_data.current;
00086 
00087       GpInput::Data gp_input_data = kobuki.getGpInputData();
00088       state.digital_input = gp_input_data.digital_input;
00089       for ( unsigned int i = 0; i < gp_input_data.analog_input.size(); ++i ) {
00090         state.analog_input.push_back(gp_input_data.analog_input[i]);
00091       }
00092 
00093       sensor_state_publisher.publish(state);
00094     }
00095   }
00096 }
00097 
00098 void KobukiRos::publishWheelState()
00099 {
00100   // Take latest encoders and gyro data
00101   ecl::Pose2D<double> pose_update;
00102   ecl::linear_algebra::Vector3d pose_update_rates;
00103   kobuki.updateOdometry(pose_update, pose_update_rates);
00104   kobuki.getWheelJointStates(joint_states.position[0], joint_states.velocity[0],   // left wheel
00105                              joint_states.position[1], joint_states.velocity[1]);  // right wheel
00106 
00107   // Update and publish odometry and joint states
00108   odometry.update(pose_update, pose_update_rates, kobuki.getHeading(), kobuki.getAngularVelocity());
00109 
00110   if (ros::ok())
00111   {
00112     joint_states.header.stamp = ros::Time::now();
00113     joint_state_publisher.publish(joint_states);
00114   }
00115 }
00116 
00117 void KobukiRos::publishInertia()
00118 {
00119   if (ros::ok())
00120   {
00121     if (imu_data_publisher.getNumSubscribers() > 0)
00122     {
00123       // Publish as shared pointer to leverage the nodelets' zero-copy pub/sub feature
00124       sensor_msgs::ImuPtr msg(new sensor_msgs::Imu);
00125 
00126       msg->header.frame_id = "gyro_link";
00127       msg->header.stamp = ros::Time::now();
00128 
00129       msg->orientation = tf::createQuaternionMsgFromRollPitchYaw(0.0, 0.0, kobuki.getHeading());
00130 
00131       // set a non-zero covariance on unused dimensions (pitch and roll); this is a requirement of robot_pose_ekf
00132       // set yaw covariance as very low, to make it dominate over the odometry heading when combined
00133       // 1: fill once, as its always the same;  2: using an invented value; cannot we get a realistic estimation?
00134       msg->orientation_covariance[0] = DBL_MAX;
00135       msg->orientation_covariance[4] = DBL_MAX;
00136       msg->orientation_covariance[8] = 0.05;
00137 
00138       // fill angular velocity; we ignore acceleration for now
00139       msg->angular_velocity.z = kobuki.getAngularVelocity();
00140 
00141       // angular velocity covariance; useless by now, but robot_pose_ekf's
00142       // roadmap claims that it will compute velocities in the future
00143       msg->angular_velocity_covariance[0] = DBL_MAX;
00144       msg->angular_velocity_covariance[4] = DBL_MAX;
00145       msg->angular_velocity_covariance[8] = 0.05;
00146 
00147       imu_data_publisher.publish(msg);
00148     }
00149   }
00150 }
00151 
00152 void KobukiRos::publishRawInertia()
00153 {
00154   if ( ros::ok() && (raw_imu_data_publisher.getNumSubscribers() > 0) )
00155   {
00156     // Publish as shared pointer to leverage the nodelets' zero-copy pub/sub feature
00157     sensor_msgs::ImuPtr msg(new sensor_msgs::Imu);
00158     ThreeAxisGyro::Data data = kobuki.getRawInertiaData();
00159 
00160     ros::Time now = ros::Time::now();
00161     ros::Duration interval(0.01); // Time interval between each sensor reading.
00162     const double digit_to_dps = 0.00875; // digit to deg/s ratio, comes from datasheet of 3d gyro[L3G4200D].
00163     unsigned int length = data.followed_data_length/3;
00164     for( unsigned int i=0; i<length; i++) {
00165       // Each sensor reading has id, that circulate 0 to 255.
00166       //msg->header.frame_id = std::string("gyro_link_" + boost::lexical_cast<std::string>((unsigned int)data.frame_id+i));
00167       msg->header.frame_id = "gyro_link";
00168 
00169       // Update rate of 3d gyro sensor is 100 Hz, but robot's update rate is 50 Hz.
00170       // So, here is some compensation.
00171       // See also https://github.com/yujinrobot/kobuki/issues/216
00172       msg->header.stamp = now - interval * (length-i-1);
00173 
00174       // Sensing axis of 3d gyro is not match with robot. It is rotated 90 degree counterclockwise about z-axis.
00175       msg->angular_velocity.x = angles::from_degrees( -digit_to_dps * (short)data.data[i*3+1] );
00176       msg->angular_velocity.y = angles::from_degrees(  digit_to_dps * (short)data.data[i*3+0] );
00177       msg->angular_velocity.z = angles::from_degrees(  digit_to_dps * (short)data.data[i*3+2] );
00178 
00179       raw_imu_data_publisher.publish(msg);
00180     }
00181   }
00182 }
00183 
00184 void KobukiRos::publishDockIRData()
00185 {
00186   if (ros::ok())
00187   {
00188     if (dock_ir_publisher.getNumSubscribers() > 0)
00189     {
00190       DockIR::Data data = kobuki.getDockIRData();
00191 
00192       // Publish as shared pointer to leverage the nodelets' zero-copy pub/sub feature
00193       kobuki_msgs::DockInfraRedPtr msg(new kobuki_msgs::DockInfraRed);
00194 
00195       msg->header.frame_id = "dock_ir_link";
00196       msg->header.stamp = ros::Time::now();
00197 
00198       msg->data.push_back( data.docking[0] );
00199       msg->data.push_back( data.docking[1] );
00200       msg->data.push_back( data.docking[2] );
00201 
00202       dock_ir_publisher.publish(msg);
00203     }
00204   }
00205 }
00206 
00207 /*****************************************************************************
00208 ** Non Default Stream Packets
00209 *****************************************************************************/
00216 void KobukiRos::publishVersionInfo(const VersionInfo &version_info)
00217 {
00218   if (ros::ok())
00219   {
00220     kobuki_msgs::VersionInfoPtr msg(new kobuki_msgs::VersionInfo);
00221 
00222     msg->firmware = VersionInfo::toString(version_info.firmware);
00223     msg->hardware = VersionInfo::toString(version_info.hardware);
00224     msg->software = VersionInfo::getSoftwareVersion();
00225 
00226     msg->udid.resize(3);
00227     msg->udid[0] = version_info.udid0;
00228     msg->udid[1] = version_info.udid1;
00229     msg->udid[2] = version_info.udid2;
00230 
00231     // Set available features mask depending on firmware and driver versions
00232     if (version_info.firmware > 65536)  // 1.0.0
00233     {
00234       msg->features |= kobuki_msgs::VersionInfo::SMOOTH_MOVE_START;
00235       msg->features |= kobuki_msgs::VersionInfo::GYROSCOPE_3D_DATA;
00236     }
00237     if (version_info.firmware > 65792)  // 1.1.0
00238     {
00239       // msg->features |= kobuki_msgs::VersionInfo::SOMETHING_JINCHA_FANCY;
00240     }
00241     // if (msg->firmware > ...
00242 
00243     version_info_publisher.publish(msg);
00244   }
00245 }
00246 
00247 void KobukiRos::publishControllerInfo()
00248 {
00249   if (ros::ok())
00250   {
00251     kobuki_msgs::ControllerInfoPtr msg(new kobuki_msgs::ControllerInfo);
00252     ControllerInfo::Data data = kobuki.getControllerInfoData();
00253 
00254     msg->type = data.type;
00255     msg->p_gain = static_cast<float>(data.p_gain) * 0.001f;;
00256     msg->i_gain = static_cast<float>(data.i_gain) * 0.001f;;
00257     msg->d_gain = static_cast<float>(data.d_gain) * 0.001f;;
00258 
00259     controller_info_publisher.publish(msg);
00260   }
00261 }
00262 
00263 /*****************************************************************************
00264 ** Events
00265 *****************************************************************************/
00266 
00267 void KobukiRos::publishButtonEvent(const ButtonEvent &event)
00268 {
00269   if (ros::ok())
00270   {
00271     kobuki_msgs::ButtonEventPtr msg(new kobuki_msgs::ButtonEvent);
00272     switch(event.state) {
00273       case(ButtonEvent::Pressed)  : { msg->state = kobuki_msgs::ButtonEvent::PRESSED;  break; }
00274       case(ButtonEvent::Released) : { msg->state = kobuki_msgs::ButtonEvent::RELEASED; break; }
00275       default: break;
00276     }
00277     switch(event.button) {
00278       case(ButtonEvent::Button0) : { msg->button = kobuki_msgs::ButtonEvent::Button0; break; }
00279       case(ButtonEvent::Button1) : { msg->button = kobuki_msgs::ButtonEvent::Button1; break; }
00280       case(ButtonEvent::Button2) : { msg->button = kobuki_msgs::ButtonEvent::Button2; break; }
00281       default: break;
00282     }
00283     button_event_publisher.publish(msg);
00284   }
00285 }
00286 
00287 void KobukiRos::publishBumperEvent(const BumperEvent &event)
00288 {
00289   if (ros::ok())
00290   {
00291     kobuki_msgs::BumperEventPtr msg(new kobuki_msgs::BumperEvent);
00292     switch(event.state) {
00293       case(BumperEvent::Pressed)  : { msg->state = kobuki_msgs::BumperEvent::PRESSED;  break; }
00294       case(BumperEvent::Released) : { msg->state = kobuki_msgs::BumperEvent::RELEASED; break; }
00295       default: break;
00296     }
00297     switch(event.bumper) {
00298       case(BumperEvent::Left)   : { msg->bumper = kobuki_msgs::BumperEvent::LEFT;   break; }
00299       case(BumperEvent::Center) : { msg->bumper = kobuki_msgs::BumperEvent::CENTER; break; }
00300       case(BumperEvent::Right)  : { msg->bumper = kobuki_msgs::BumperEvent::RIGHT;  break; }
00301       default: break;
00302     }
00303     bumper_event_publisher.publish(msg);
00304   }
00305 }
00306 
00307 void KobukiRos::publishCliffEvent(const CliffEvent &event)
00308 {
00309   if (ros::ok())
00310   {
00311     kobuki_msgs::CliffEventPtr msg(new kobuki_msgs::CliffEvent);
00312     switch(event.state) {
00313       case(CliffEvent::Floor) : { msg->state = kobuki_msgs::CliffEvent::FLOOR; break; }
00314       case(CliffEvent::Cliff) : { msg->state = kobuki_msgs::CliffEvent::CLIFF; break; }
00315       default: break;
00316     }
00317     switch(event.sensor) {
00318       case(CliffEvent::Left)   : { msg->sensor = kobuki_msgs::CliffEvent::LEFT;   break; }
00319       case(CliffEvent::Center) : { msg->sensor = kobuki_msgs::CliffEvent::CENTER; break; }
00320       case(CliffEvent::Right)  : { msg->sensor = kobuki_msgs::CliffEvent::RIGHT;  break; }
00321       default: break;
00322     }
00323     msg->bottom = event.bottom;
00324     cliff_event_publisher.publish(msg);
00325   }
00326 }
00327 
00328 void KobukiRos::publishWheelEvent(const WheelEvent &event)
00329 {
00330   if (ros::ok())
00331   {
00332     kobuki_msgs::WheelDropEventPtr msg(new kobuki_msgs::WheelDropEvent);
00333     switch(event.state) {
00334       case(WheelEvent::Dropped) : { msg->state = kobuki_msgs::WheelDropEvent::DROPPED; break; }
00335       case(WheelEvent::Raised)  : { msg->state = kobuki_msgs::WheelDropEvent::RAISED;  break; }
00336       default: break;
00337     }
00338     switch(event.wheel) {
00339       case(WheelEvent::Left)  : { msg->wheel = kobuki_msgs::WheelDropEvent::LEFT;  break; }
00340       case(WheelEvent::Right) : { msg->wheel = kobuki_msgs::WheelDropEvent::RIGHT; break; }
00341       default: break;
00342     }
00343     wheel_event_publisher.publish(msg);
00344   }
00345 }
00346 
00347 void KobukiRos::publishPowerEvent(const PowerEvent &event)
00348 {
00349   if (ros::ok())
00350   {
00351     kobuki_msgs::PowerSystemEventPtr msg(new kobuki_msgs::PowerSystemEvent);
00352     switch(event.event) {
00353       case(PowerEvent::Unplugged) :
00354         { msg->event = kobuki_msgs::PowerSystemEvent::UNPLUGGED; break; }
00355       case(PowerEvent::PluggedToAdapter) :
00356         { msg->event = kobuki_msgs::PowerSystemEvent::PLUGGED_TO_ADAPTER;  break; }
00357       case(PowerEvent::PluggedToDockbase) :
00358         { msg->event = kobuki_msgs::PowerSystemEvent::PLUGGED_TO_DOCKBASE; break; }
00359       case(PowerEvent::ChargeCompleted)  :
00360         { msg->event = kobuki_msgs::PowerSystemEvent::CHARGE_COMPLETED;  break; }
00361       case(PowerEvent::BatteryLow) :
00362         { msg->event = kobuki_msgs::PowerSystemEvent::BATTERY_LOW; break; }
00363       case(PowerEvent::BatteryCritical) :
00364         { msg->event = kobuki_msgs::PowerSystemEvent::BATTERY_CRITICAL;  break; }
00365       default: break;
00366     }
00367     power_event_publisher.publish(msg);
00368   }
00369 }
00370 
00371 void KobukiRos::publishInputEvent(const InputEvent &event)
00372 {
00373   if (ros::ok())
00374   {
00375     kobuki_msgs::DigitalInputEventPtr msg(new kobuki_msgs::DigitalInputEvent);
00376     for (unsigned int i = 0; i < msg->values.size(); i++)
00377       msg->values[i] = event.values[i];
00378     input_event_publisher.publish(msg);
00379   }
00380 }
00381 
00382 void KobukiRos::publishRobotEvent(const RobotEvent &event)
00383 {
00384   if (ros::ok())
00385   {
00386     kobuki_msgs::RobotStateEventPtr msg(new kobuki_msgs::RobotStateEvent);
00387     switch(event.state) {
00388       case(RobotEvent::Online)  : { msg->state = kobuki_msgs::RobotStateEvent::ONLINE;  break; }
00389       case(RobotEvent::Offline) : { msg->state = kobuki_msgs::RobotStateEvent::OFFLINE; break; }
00390       default: break;
00391     }
00392 
00393     robot_event_publisher.publish(msg);
00394   }
00395 }
00396 
00410 void KobukiRos::publishRawDataCommand(Command::Buffer &buffer)
00411 {
00412   if ( raw_data_command_publisher.getNumSubscribers() > 0 ) { // do not do string processing if there is no-one listening.
00413     std::ostringstream ostream;
00414     Command::Buffer::Formatter format;
00415     ostream << format(buffer); // convert to an easily readable hex string.
00416     std_msgs::String s;
00417     s.data = ostream.str();
00418     if (ros::ok())
00419     {
00420       raw_data_command_publisher.publish(s);
00421     }
00422   }
00423 }
00437 void KobukiRos::publishRawDataStream(PacketFinder::BufferType &buffer)
00438 {
00439   if ( raw_data_stream_publisher.getNumSubscribers() > 0 ) { // do not do string processing if there is no-one listening.
00440     /*std::cout << "size: [" << buffer.size() << "], asize: [" << buffer.asize() << "]" << std::endl;
00441     std::cout << "leader: " << buffer.leader << ", follower: " << buffer.follower  << std::endl;
00442     {
00443       std::ostringstream ostream;
00444       PacketFinder::BufferType::Formatter format;
00445       ostream << format(buffer); // convert to an easily readable hex string.
00446       //std::cout << ostream.str() << std::endl;
00447       std_msgs::String s;
00448       s.data = ostream.str();
00449       if (ros::ok())
00450       {
00451         raw_data_stream_publisher.publish(s);
00452       }
00453     }*/
00454     {
00455       std::ostringstream ostream;
00456       ostream << "{ " ;
00457       ostream << std::setfill('0') << std::uppercase;
00458       for (unsigned int i=0; i < buffer.size(); i++)
00459           ostream << std::hex << std::setw(2) << static_cast<unsigned int>(buffer[i]) << " " << std::dec;
00460       ostream << "}";
00461       //std::cout << ostream.str() << std::endl;
00462       std_msgs::StringPtr msg(new std_msgs::String);
00463       msg->data = ostream.str();
00464       if (ros::ok())
00465       {
00466         raw_data_stream_publisher.publish(msg);
00467       }
00468     }
00469   }
00470 }
00471 
00472 void KobukiRos::publishRawControlCommand(const std::vector<short> &velocity_commands)
00473 {
00474   if ( raw_control_command_publisher.getNumSubscribers() > 0 ) {
00475     std_msgs::Int16MultiArrayPtr msg(new std_msgs::Int16MultiArray);
00476     msg->data = velocity_commands;
00477     if (ros::ok())
00478     {
00479       raw_control_command_publisher.publish(msg);
00480     }
00481   }
00482   return;
00483 }
00484 
00485 } // namespace kobuki


kobuki_node
Author(s): Daniel Stonier , Younghun Ju , Jorge Santos Simon
autogenerated on Wed Sep 16 2015 04:35:38