roch_sensorpc.cpp
Go to the documentation of this file.
00001 
00012 /*****************************************************************************
00013 ** Includes
00014 *****************************************************************************/
00015 
00016 #include <pluginlib/class_list_macros.h>   
00017 #include <ros/console.h>
00018 
00019 #include "roch_sensorpc/roch_sensorpc.hpp"
00020 
00021 #include <ros/ros.h>
00022 
00023 namespace roch_sensorpc
00024 {
00025 
00026 void SensorPcNodelet::coreSensorCB(const roch_msgs::SensorState::ConstPtr& msg)
00027 {
00028   if (pointcloud_pub_.getNumSubscribers() == 0)
00029     return;
00030 
00031   // We publish just one "no events" pc (with all three points far away) and stop spamming when bumper/cliff conditions disappear
00032   if (! msg->leftcliff  && ! prev_leftcliff && ! msg->rightcliff  && ! prev_rightcliff && 
00033       ! msg->leftult    && ! prev_leftult && ! msg->centerult  && ! prev_centerult && ! msg->rightult  && ! prev_rightult &&
00034       ! msg->leftpsd    && ! prev_leftpsd && ! msg->centerpsd  && ! prev_centerpsd && ! msg->rightpsd  && ! prev_rightpsd)
00035     return;
00036 
00037    prev_leftcliff  = msg->leftcliff;
00038    prev_rightcliff  = msg->rightcliff;
00039    prev_leftult  = msg->leftult;
00040    prev_centerult  = msg->centerult;
00041    prev_rightult  = msg->rightult;
00042    prev_leftpsd  = msg->leftpsd;
00043    prev_centerpsd  = msg->centerpsd;
00044    prev_rightpsd  = msg->rightpsd;
00045    
00046  
00047   // We replicate the sensors order of bumper/cliff event messages: LEFT = 0, CENTER = 1 and RIGHT = 2
00048   // For any of {left/center/right} with no bumper/cliff event, we publish a faraway point that won't get used 
00049   if ((cliff_enable_ && (msg->leftcliff & roch_msgs::SensorState::CLIFF )) || 
00050       (ult_enable_ && (msg->leftult  & roch_msgs::SensorState::NEAR)) || 
00051       (psd_enable_ && (msg->leftpsd  & roch_msgs::SensorState::NEAR)))
00052   {
00053     memcpy(&pointcloud_.data[0 * pointcloud_.point_step + pointcloud_.fields[0].offset], &p_side_x_, sizeof(float));
00054     memcpy(&pointcloud_.data[0 * pointcloud_.point_step + pointcloud_.fields[1].offset], &p_side_y_, sizeof(float));
00055     ROS_INFO_STREAM("Enter left interrupt: cliff_enable:" << cliff_enable_ << "  ult_enable:"<<ult_enable_<<"  psd_enable:"<<psd_enable_<<".");
00056   }
00057   else
00058   {
00059     memcpy(&pointcloud_.data[0 * pointcloud_.point_step + pointcloud_.fields[0].offset], &P_INF_X, sizeof(float));
00060     memcpy(&pointcloud_.data[0 * pointcloud_.point_step + pointcloud_.fields[1].offset], &P_INF_Y, sizeof(float));
00061   }
00062 
00063   if ((ult_enable_ && (msg->centerult & roch_msgs::SensorState::NEAR )) ||  
00064       (psd_enable_ && (msg->centerpsd & roch_msgs::SensorState::NEAR)))
00065   {
00066     memcpy(&pointcloud_.data[1 * pointcloud_.point_step + pointcloud_.fields[0].offset], &pc_radius_, sizeof(float));
00067     
00068     ROS_INFO_STREAM("Enter center interrupt: ult_enable:"<<ult_enable_<<" psd_enable:"<<psd_enable_<<".");
00069    }
00070   else
00071   {
00072     memcpy(&pointcloud_.data[1 * pointcloud_.point_step + pointcloud_.fields[0].offset], &P_INF_X, sizeof(float));
00073   }
00074 
00075   if ((cliff_enable_ && (msg->rightcliff  & roch_msgs::SensorState::CLIFF)) ||
00076       (ult_enable_ && (msg->rightult & roch_msgs::SensorState::NEAR )) ||       
00077       (psd_enable_ && (msg->rightpsd  & roch_msgs::SensorState::NEAR)))
00078   {
00079     memcpy(&pointcloud_.data[2 * pointcloud_.point_step + pointcloud_.fields[0].offset], &p_side_x_, sizeof(float));
00080     memcpy(&pointcloud_.data[2 * pointcloud_.point_step + pointcloud_.fields[1].offset], &n_side_y_, sizeof(float));
00081     ROS_INFO_STREAM("Enter right interrupt: cliff_enable:" << cliff_enable_ << "  ult_enable:"<<ult_enable_<<"  psd_enable:"<<psd_enable_<<".");
00082   }
00083   else
00084   {
00085     memcpy(&pointcloud_.data[2 * pointcloud_.point_step + pointcloud_.fields[0].offset], &P_INF_X, sizeof(float));
00086     memcpy(&pointcloud_.data[2 * pointcloud_.point_step + pointcloud_.fields[1].offset], &N_INF_Y, sizeof(float));
00087   }
00088 
00089   pointcloud_.header.stamp = msg->header.stamp;
00090   pointcloud_pub_.publish(pointcloud_);
00091 }
00092 
00093 void SensorPcNodelet::onInit()
00094 {
00095 
00096   // Bumper/cliff pointcloud distance to base frame; should be something like the robot radius plus
00097   // costmap resolution plus an extra to cope with robot inertia. This is a bit tricky parameter: if
00098   // it's too low, costmap will ignore this pointcloud (the robot footprint runs over the hit obstacle),
00099   // but if it's too big, hit obstacles will be mapped too far from the robot and the navigation around
00100   // them will probably fail.
00101   std::string base_link_frame;
00102   double r, h, angle;
00103   bool ult_en,psd_en,cliff_en;
00104   private_nh_.param("pointcloud_radius", r, 0.25); pc_radius_ = r;
00105   private_nh_.param("pointcloud_height", h, 0.04); pc_height_ = h;
00106   private_nh_.param("side_point_angle", angle, 0.34906585); 
00107   private_nh_.param<std::string>("base_link_frame", base_link_frame, "/base_link");
00108   private_nh_.param<bool>("ult_enable", ult_enable_, true); 
00109   private_nh_.param<bool>("psd_enable", psd_enable_, true);  
00110   private_nh_.param<bool>("cliff_enable", cliff_enable_, true); 
00111 
00112   // Lateral points x/y coordinates; we need to store float values to memcopy later
00113   p_side_x_ = + pc_radius_*sin(angle); // angle degrees from vertical
00114   p_side_y_ = + pc_radius_*cos(angle); // angle degrees from vertical
00115   n_side_y_ = - pc_radius_*cos(angle); // angle degrees from vertical
00116 
00117   // Prepare constant parts of the pointcloud message to be  published
00118   pointcloud_.header.frame_id = base_link_frame;
00119   pointcloud_.width  = 3;
00120   pointcloud_.height = 1;
00121   pointcloud_.fields.resize(3);
00122 
00123   // Set x/y/z as the only fields
00124   pointcloud_.fields[0].name = "x";
00125   pointcloud_.fields[1].name = "y";
00126   pointcloud_.fields[2].name = "z";
00127 
00128   int offset = 0;
00129   // All offsets are *4, as all field data types are float32
00130   for (size_t d = 0; d < pointcloud_.fields.size(); ++d, offset += 4)
00131   {
00132     pointcloud_.fields[d].count    = 1;
00133     pointcloud_.fields[d].offset   = offset;
00134     pointcloud_.fields[d].datatype = sensor_msgs::PointField::FLOAT32;
00135   }
00136 
00137   pointcloud_.point_step = offset;
00138   pointcloud_.row_step   = pointcloud_.point_step * pointcloud_.width;
00139 
00140   pointcloud_.data.resize(3 * pointcloud_.point_step);
00141   pointcloud_.is_bigendian = false;
00142   pointcloud_.is_dense     = true;
00143 
00144   // Bumper/cliff "points" fix coordinates (the others depend on sensor activation/deactivation)
00145 
00146   // y: always 0 for central bumper
00147   memcpy(&pointcloud_.data[1 * pointcloud_.point_step + pointcloud_.fields[1].offset], &ZERO, sizeof(float));
00148 
00149   // z: constant elevation from base frame
00150   memcpy(&pointcloud_.data[0 * pointcloud_.point_step + pointcloud_.fields[2].offset], &pc_height_, sizeof(float));
00151   memcpy(&pointcloud_.data[1 * pointcloud_.point_step + pointcloud_.fields[2].offset], &pc_height_, sizeof(float));
00152   memcpy(&pointcloud_.data[2 * pointcloud_.point_step + pointcloud_.fields[2].offset], &pc_height_, sizeof(float));
00153 
00154   pointcloud_pub_  = nh.advertise <sensor_msgs::PointCloud2> ("pointcloud", 10);
00155   core_sensor_sub_ = nh.subscribe("core_sensors", 10, &SensorPcNodelet::coreSensorCB, this);
00156   ROS_INFO("init params: cliff_enable:%d  ult_enable:%d  psd_enable:%d.",cliff_enable_, ult_enable_, psd_enable_);
00157 
00158   ROS_INFO("Ult/psd/cliff pointcloud configured at distance %f and height %f from base frame", pc_radius_, pc_height_);
00159 }
00160 
00161 } // namespace roch_sensorpc
00162 
00163 int main(int argc, char** argv){
00164   ros::init(argc,argv,"roch_sensorpc_nodelet");
00165   ros::NodeHandle nh, private_nh("~");
00166   roch_sensorpc::SensorPcNodelet sensorpc(nh,private_nh);
00167    
00168   ros::spin();
00169   
00170   return 0;
00171 }


roch_sensorpc
Author(s): Carl , Jorge Santos Simon
autogenerated on Sat Jun 8 2019 20:32:48