kobuki_bumper2pc.cpp
Go to the documentation of this file.
00001 
00010 /*****************************************************************************
00011 ** Includes
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   // We publish just one "no events" pc (with all three points far away) and stop spamming when bumper/cliff conditions disappear
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   // We replicate the sensors order of bumper/cliff event messages: LEFT = 0, CENTER = 1 and RIGHT = 2
00034   // For any of {left/center/right} with no bumper/cliff event, we publish a faraway point that won't get used 
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   // Bumper/cliff pointcloud distance to base frame; should be something like the robot radius plus
00078   // costmap resolution plus an extra to cope with robot inertia. This is a bit tricky parameter: if
00079   // it's too low, costmap will ignore this pointcloud (the robot footprint runs over the hit obstacle),
00080   // but if it's too big, hit obstacles will be mapped too far from the robot and the navigation around
00081   // them will probably fail.
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   // Lateral points x/y coordinates; we need to store float values to memcopy later
00090   p_side_x_ = + pc_radius_*sin(angle); // angle degrees from vertical
00091   p_side_y_ = + pc_radius_*cos(angle); // angle degrees from vertical
00092   n_side_y_ = - pc_radius_*cos(angle); // angle degrees from vertical
00093 
00094   // Prepare constant parts of the pointcloud message to be  published
00095   pointcloud_.header.frame_id = base_link_frame;
00096   pointcloud_.width  = 3;
00097   pointcloud_.height = 1;
00098   pointcloud_.fields.resize(3);
00099 
00100   // Set x/y/z as the only fields
00101   pointcloud_.fields[0].name = "x";
00102   pointcloud_.fields[1].name = "y";
00103   pointcloud_.fields[2].name = "z";
00104 
00105   int offset = 0;
00106   // All offsets are *4, as all field data types are float32
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   // Bumper/cliff "points" fix coordinates (the others depend on sensor activation/deactivation)
00122 
00123   // y: always 0 for central bumper
00124   memcpy(&pointcloud_.data[1 * pointcloud_.point_step + pointcloud_.fields[1].offset], &ZERO, sizeof(float));
00125 
00126   // z: constant elevation from base frame
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 } // namespace kobuki_bumper2pc
00138 
00139 
00140 PLUGINLIB_EXPORT_CLASS(kobuki_bumper2pc::Bumper2PcNodelet, nodelet::Nodelet);


kobuki_bumper2pc
Author(s): Jorge Santos Simon
autogenerated on Thu Jun 6 2019 17:37:40