00001 
00010 
00011 
00012 
00013 
00014 #include <pluginlib/class_list_macros.h>
00015 
00016 #include "kobuki_bumper2pc/kobuki_bumper2pc.hpp"
00017 
00018 namespace kobuki_bumper2pc
00019 {
00020 
00021 void Bumper2PcNodelet::coreSensorCB(const kobuki_msgs::SensorState::ConstPtr& msg)
00022 {
00023   if (pointcloud_pub_.getNumSubscribers() == 0)
00024     return;
00025 
00026   
00027   if (! msg->bumper && ! msg->cliff && ! prev_bumper && ! prev_cliff)
00028     return;
00029 
00030   prev_bumper = msg->bumper;
00031   prev_cliff  = msg->cliff;
00032 
00033   
00034   
00035   if ((msg->bumper & kobuki_msgs::SensorState::BUMPER_LEFT) ||
00036       (msg->cliff  & kobuki_msgs::SensorState::CLIFF_LEFT))
00037   {
00038     memcpy(&pointcloud_.data[0 * pointcloud_.point_step + pointcloud_.fields[0].offset], &p_side_x_, sizeof(float));
00039     memcpy(&pointcloud_.data[0 * pointcloud_.point_step + pointcloud_.fields[1].offset], &p_side_y_, sizeof(float));
00040   }
00041   else
00042   {
00043     memcpy(&pointcloud_.data[0 * pointcloud_.point_step + pointcloud_.fields[0].offset], &P_INF_X, sizeof(float));
00044     memcpy(&pointcloud_.data[0 * pointcloud_.point_step + pointcloud_.fields[1].offset], &P_INF_Y, sizeof(float));
00045   }
00046 
00047   if ((msg->bumper & kobuki_msgs::SensorState::BUMPER_CENTRE) ||
00048       (msg->cliff  & kobuki_msgs::SensorState::CLIFF_CENTRE))
00049   {
00050     memcpy(&pointcloud_.data[1 * pointcloud_.point_step + pointcloud_.fields[0].offset], &pc_radius_, sizeof(float));
00051   }
00052   else
00053   {
00054     memcpy(&pointcloud_.data[1 * pointcloud_.point_step + pointcloud_.fields[0].offset], &P_INF_X, sizeof(float));
00055   }
00056 
00057   if ((msg->bumper & kobuki_msgs::SensorState::BUMPER_RIGHT) ||
00058       (msg->cliff  & kobuki_msgs::SensorState::CLIFF_RIGHT))
00059   {
00060     memcpy(&pointcloud_.data[2 * pointcloud_.point_step + pointcloud_.fields[0].offset], &p_side_x_, sizeof(float));
00061     memcpy(&pointcloud_.data[2 * pointcloud_.point_step + pointcloud_.fields[1].offset], &n_side_y_, sizeof(float));
00062   }
00063   else
00064   {
00065     memcpy(&pointcloud_.data[2 * pointcloud_.point_step + pointcloud_.fields[0].offset], &P_INF_X, sizeof(float));
00066     memcpy(&pointcloud_.data[2 * pointcloud_.point_step + pointcloud_.fields[1].offset], &N_INF_Y, sizeof(float));
00067   }
00068 
00069   pointcloud_.header.stamp = msg->header.stamp;
00070   pointcloud_pub_.publish(pointcloud_);
00071 }
00072 
00073 void Bumper2PcNodelet::onInit()
00074 {
00075   ros::NodeHandle nh = this->getPrivateNodeHandle();
00076 
00077   
00078   
00079   
00080   
00081   
00082   std::string base_link_frame;
00083   double r, h, angle;
00084   nh.param("pointcloud_radius", r, 0.25); pc_radius_ = r;
00085   nh.param("pointcloud_height", h, 0.04); pc_height_ = h;
00086   nh.param("side_point_angle", angle, 0.34906585); 
00087   nh.param<std::string>("base_link_frame", base_link_frame, "/base_link");
00088 
00089   
00090   p_side_x_ = + pc_radius_*sin(angle); 
00091   p_side_y_ = + pc_radius_*cos(angle); 
00092   n_side_y_ = - pc_radius_*cos(angle); 
00093 
00094   
00095   pointcloud_.header.frame_id = base_link_frame;
00096   pointcloud_.width  = 3;
00097   pointcloud_.height = 1;
00098   pointcloud_.fields.resize(3);
00099 
00100   
00101   pointcloud_.fields[0].name = "x";
00102   pointcloud_.fields[1].name = "y";
00103   pointcloud_.fields[2].name = "z";
00104 
00105   int offset = 0;
00106   
00107   for (size_t d = 0; d < pointcloud_.fields.size(); ++d, offset += 4)
00108   {
00109     pointcloud_.fields[d].count    = 1;
00110     pointcloud_.fields[d].offset   = offset;
00111     pointcloud_.fields[d].datatype = sensor_msgs::PointField::FLOAT32;
00112   }
00113 
00114   pointcloud_.point_step = offset;
00115   pointcloud_.row_step   = pointcloud_.point_step * pointcloud_.width;
00116 
00117   pointcloud_.data.resize(3 * pointcloud_.point_step);
00118   pointcloud_.is_bigendian = false;
00119   pointcloud_.is_dense     = true;
00120 
00121   
00122 
00123   
00124   memcpy(&pointcloud_.data[1 * pointcloud_.point_step + pointcloud_.fields[1].offset], &ZERO, sizeof(float));
00125 
00126   
00127   memcpy(&pointcloud_.data[0 * pointcloud_.point_step + pointcloud_.fields[2].offset], &pc_height_, sizeof(float));
00128   memcpy(&pointcloud_.data[1 * pointcloud_.point_step + pointcloud_.fields[2].offset], &pc_height_, sizeof(float));
00129   memcpy(&pointcloud_.data[2 * pointcloud_.point_step + pointcloud_.fields[2].offset], &pc_height_, sizeof(float));
00130 
00131   pointcloud_pub_  = nh.advertise <sensor_msgs::PointCloud2> ("pointcloud", 10);
00132   core_sensor_sub_ = nh.subscribe("core_sensors", 10, &Bumper2PcNodelet::coreSensorCB, this);
00133 
00134   ROS_INFO("Bumper/cliff pointcloud configured at distance %f and height %f from base frame", pc_radius_, pc_height_);
00135 }
00136 
00137 } 
00138 
00139 
00140 PLUGINLIB_EXPORT_CLASS(kobuki_bumper2pc::Bumper2PcNodelet, nodelet::Nodelet);