void pc_motion_filter::PcMotionFilter::cloud_in_cb(const sensor_msgs::PointCloud2::ConstPtr msg)
{
  update();
  ros::Time now = msg->header.stamp;
  ros::Time past = now;
  past.sec -= stillness_duration;
  geometry_msgs::TransformStamped difference_msg;
  btTransform difference;
  BOOST_FOREACH(std::string& frame_id, frame_ids){
    try{
      difference_msg = tf_buffer->lookupTransform(msg->header.frame_id, now, msg->header.frame_id, past, frame_id, ros::Duration(0.1));
      difference = tf2::transformToBullet(difference_msg);
      double linear_distance = difference.getOrigin().length();//sqrt(t.x*t.x+t.y*t.y+t.z*t.z);
      double angular_distance = difference.getRotation().getAngle();

      if (linear_distance > linear_throshold) {
        NODELET_DEBUG_STREAM("above linear threshold: "<<linear_distance<<" between "<<frame_id<<" and "<<msg->header.frame_id);
        return;
      }
      if (fabs(angular_distance) > angular_threshold) {
        NODELET_DEBUG_STREAM("above angular threshold: "<<angles::to_degrees(angular_distance)<<" between "<<frame_id<<" and "<<msg->header.frame_id);
        return;
      }
    } catch (tf2::TransformException &ex) {
      NODELET_WARN_STREAM_THROTTLE(1.0, "Could NOT transform "<<msg->header.frame_id<<" to "<<frame_id<<": "<< ex.what());
      //return;
    }
  }
  cloud_out_publisher.publish(msg);
}
 bool
 PrimitiveShapeClassifier::checkFrameId(const sensor_msgs::PointCloud2::ConstPtr& ros_cloud,
                                        const sensor_msgs::PointCloud2::ConstPtr& ros_normal,
                                        const jsk_recognition_msgs::ClusterPointIndices::ConstPtr& ros_indices,
                                        const jsk_recognition_msgs::PolygonArray::ConstPtr& ros_polygons)
 {
   std::string cloud_topic = ros::names::resolve(sub_cloud_.getTopic());
   std::string normal_topic = ros::names::resolve(sub_normal_.getTopic());
   std::string indices_topic = ros::names::resolve(sub_indices_.getTopic());
   std::string polygons_topic = ros::names::resolve(sub_polygons_.getTopic());
   if (!jsk_recognition_utils::isSameFrameId(ros_cloud->header, ros_normal->header)) {
     NODELET_ERROR_STREAM(cloud_topic << " and " << normal_topic << " must have same frame_id");
     return false;
   }
   if (!jsk_recognition_utils::isSameFrameId(ros_cloud->header, ros_indices->header)) {
     NODELET_ERROR_STREAM(cloud_topic << " and " << indices_topic << " must have same frame_id");
     return false;
   }
   if (!jsk_recognition_utils::isSameFrameId(ros_cloud->header, ros_polygons->header)) {
     NODELET_ERROR_STREAM(cloud_topic << " and " << polygons_topic << " must have same frame_id");
     return false;
   }
   NODELET_DEBUG_STREAM("Frame id is ok: " << ros_cloud->header.frame_id);
   return true;
 }
void pc_motion_filter::PcMotionFilter::update()
{
  ros::NodeHandle& nh_priv = getPrivateNodeHandle();
  nh_priv.getParamCached("linear_threshold", linear_throshold);
  nh_priv.getParamCached("degree_threshold", degree_threshold);
  nh_priv.getParamCached("stillness_duration", stillness_duration);
  nh_priv.getParamCached("frame_ids", frame_ids);
  angular_threshold = angles::from_degrees(degree_threshold);
  NODELET_DEBUG_STREAM("lin: "<<linear_throshold<<", ang: "<<angles::to_degrees(angular_threshold)<<", still: "<<stillness_duration);
}
  void BarcodeReaderNodelet::cleanCb()
  {
    for (boost::unordered_map<std::string, ros::Time>::iterator it = barcode_memory_.begin();
         it != barcode_memory_.end(); ++it)
    {
      if (ros::Time::now() > it->second)
      {
        NODELET_DEBUG_STREAM("Cleaned " << it->first << " from memory");
        barcode_memory_.erase(it);
      }
    }

  }
  // What we want to do here is to look at all the points that are *not* included in the indices list,
  // (i.e. these are the outliers, the points not on the floor) and determine which are the closest to the camera
  void cloudIndicesModelCallback(const sensor_msgs::PointCloud2ConstPtr& cloud_msg,
                                 const PointIndicesConstPtr& indices, const pcl::ModelCoefficientsConstPtr& model)
  {
    boost::mutex::scoped_lock lock (callback_mutex);
    NODELET_DEBUG_STREAM("Got cloud with timestamp " << cloud_msg->header.stamp << " + indices with timestamp "
        << indices->header.stamp << " + model with timestamp " << model->header.stamp);

    double dt;
    if (first)
    {
      first = false;
      dt = 0;
    }
    else
    {
      dt = (cloud_msg->header.stamp - prev_cloud_time).toSec();
      prev_cloud_time = cloud_msg->header.stamp;
    }
    if (model->values.size() > 0)
    {
      // Determine altitude:
      kinect_z = reject_outliers(-fabs(model->values[3])) - imu_to_kinect_offset;
      calcVelocity(kinect_z, dt, kinect_vz);
      // Detect obstacles:
      pcl::PointXYZ obstacle_location;
      bool obstacle_found = detectObstacle(cloud_msg, indices, model, obstacle_location);
      if (obstacle_found)
      {
        publishObstacleMarker(obstacle_location);
        NODELET_DEBUG("Detected obstacle at: [%f, %f, %f]", obstacle_location.x, obstacle_location.y,
                      obstacle_location.z);
      }
      publishObstacle(obstacle_found, obstacle_location);
    }
    else
    {
      NODELET_WARN("No planar model found -- cannot determine altitude or obstacles");
    }

    updateMask();

    if (not use_backup_estimator_alt)
    {
      publishOdom();
    }

    if (debug_throttle_rate > 0)
    {
      ros::Duration(1 / debug_throttle_rate).sleep();
    }
  }
 void ColorHistogramMatcher::feature(
     const sensor_msgs::PointCloud2::ConstPtr& input_cloud,
     const jsk_pcl_ros::ClusterPointIndices::ConstPtr& input_indices)
 {
   boost::mutex::scoped_lock(mutex_);
   if (!reference_set_) {
     NODELET_WARN("reference histogram is not available yet");
     return;
   }
   pcl::PointCloud<pcl::PointXYZRGB>::Ptr pcl_cloud (new pcl::PointCloud<pcl::PointXYZRGB>);
   pcl::fromROSMsg(*input_cloud, *pcl_cloud);
   pcl::PointCloud<pcl::PointXYZHSV>::Ptr hsv_cloud (new pcl::PointCloud<pcl::PointXYZHSV>);
   pcl::PointCloudXYZRGBtoXYZHSV(*pcl_cloud, *hsv_cloud);
   // compute histograms first
   std::vector<std::vector<float> > histograms;
   histograms.resize(input_indices->cluster_indices.size());
   
   pcl::ExtractIndices<pcl::PointXYZHSV> extract;
   extract.setInputCloud(hsv_cloud);
   // for debug
   jsk_pcl_ros::ColorHistogramArray histogram_array;
   histogram_array.header = input_cloud->header;
   for (size_t i = 0; i < input_indices->cluster_indices.size(); i++) {
     pcl::IndicesPtr indices (new std::vector<int>(input_indices->cluster_indices[i].indices));
     extract.setIndices(indices);
     pcl::PointCloud<pcl::PointXYZHSV> segmented_cloud;
     extract.filter(segmented_cloud);
     std::vector<float> histogram;
     computeHistogram(segmented_cloud, histogram, policy_);
     histograms[i] = histogram;
     ColorHistogram ros_histogram;
     ros_histogram.header = input_cloud->header;
     ros_histogram.histogram = histogram;
     histogram_array.histograms.push_back(ros_histogram);
   }
   all_histogram_pub_.publish(histogram_array);
   
   // compare histograms
   jsk_pcl_ros::ClusterPointIndices result;
   result.header = input_indices->header;
   for (size_t i = 0; i < input_indices->cluster_indices.size(); i++) {
     const double coefficient = bhattacharyyaCoefficient(histograms[i], reference_histogram_);
     NODELET_DEBUG_STREAM("coefficient: " << i << "::" << coefficient);
     if (coefficient > coefficient_thr_) {
       result.cluster_indices.push_back(input_indices->cluster_indices[i]);
     }
   }
   result_pub_.publish(result);
 }
 void NormalEstimationOMP::onInit()
 {
   pcl::console::setVerbosityLevel(pcl::console::L_ERROR);
   DiagnosticNodelet::onInit();
   pnh_->param("number_of_threads", num_of_threads_, 0);
   NODELET_DEBUG_STREAM("num_of_threads: " << num_of_threads_);
   srv_ = boost::make_shared <dynamic_reconfigure::Server<Config> > (*pnh_);
   typename dynamic_reconfigure::Server<Config>::CallbackType f =
     boost::bind (&NormalEstimationOMP::configCallback, this, _1, _2);
   srv_->setCallback (f);
   pub_ = advertise<sensor_msgs::PointCloud2>(*pnh_, "output", 1);
   pub_with_xyz_ = advertise<sensor_msgs::PointCloud2>(*pnh_, "output_with_xyz", 1);
   pub_latest_time_ = advertise<std_msgs::Float32>(
     *pnh_, "output/latest_time", 1);
   pub_average_time_ = advertise<std_msgs::Float32>(
     *pnh_, "output/average_time", 1);
   onInitPostProcess();
 }
Esempio n. 8
0
 ~SafetyControllerNodelet()
 {
   NODELET_DEBUG_STREAM("Waiting for update thread to finish.");
   shutdown_requested_ = true;
   update_thread_.join();
 }
  void GridSampler::sample(const sensor_msgs::PointCloud2::ConstPtr& msg)
  {
    boost::mutex::scoped_lock(mutex_);
    pcl::PointCloud<pcl::PointXYZRGB>::Ptr pcl_cloud(new pcl::PointCloud<pcl::PointXYZRGB>);
    pcl::fromROSMsg(*msg, *pcl_cloud);
    Eigen::Vector4f minpt, maxpt;
    pcl::getMinMax3D<pcl::PointXYZRGB>(*pcl_cloud, minpt, maxpt);
    int x_bin_num = ceil((maxpt[0] - minpt[0]) / grid_size_);
    int y_bin_num = ceil((maxpt[1] - minpt[1]) / grid_size_);
    int z_bin_num = ceil((maxpt[2] - minpt[2]) / grid_size_);

    //        x             y             z
    std::map<int, std::map<int, std::map<int, std::vector<size_t > > > > grid;
    for (size_t i = 0; i < pcl_cloud->points.size(); i++) {
      pcl::PointXYZRGB point = pcl_cloud->points[i];
      if (std::isnan(point.x) || std::isnan(point.y) || std::isnan(point.z)) {
        // skip nan
        continue;
      }
      int xbin = int((point.x - minpt[0]) / grid_size_);
      int ybin = int((point.y - minpt[1]) / grid_size_);
      int zbin = int((point.z - minpt[2]) / grid_size_);
      std::map<int, std::map<int, std::map<int, std::vector<size_t> > > >::iterator xit
        = grid.find(xbin);
      if (xit == grid.end()) {  // cannot find x bin
        NODELET_DEBUG_STREAM("no x bin" << xbin);
        std::map<int, std::vector<size_t> > new_z;
        std::vector<size_t> new_indices;
        new_indices.push_back(i);
        new_z[zbin] = new_indices;
        std::map<int, std::map<int, std::vector<size_t> > > new_y;
        new_y[ybin] = new_z;
        grid[xbin] = new_y;
      }
      else {
        NODELET_DEBUG_STREAM("found x bin" << xbin);
        std::map<int, std::map<int, std::vector<size_t> > > ybins = xit->second;
        std::map<int, std::map<int, std::vector<size_t> > >::iterator yit
          = ybins.find(ybin);
        if (yit == ybins.end()) { // cannot find y bin
          NODELET_DEBUG_STREAM("no y bin" << ybin);
          std::map<int, std::vector<size_t> > new_z;
          std::vector<size_t> new_indices;
          new_indices.push_back(i);
          new_z[zbin] = new_indices;
          xit->second[ybin] = new_z;
        }
        else {
          NODELET_DEBUG_STREAM("found y bin" << ybin);
          std::map<int, std::vector<size_t> > zbins = yit->second;
          std::map<int, std::vector<size_t> >::iterator zit
            = zbins.find(zbin);
          if (zit == zbins.end()) {
            NODELET_DEBUG_STREAM("no z bin" << zbin);
            std::vector<size_t> new_indices;
            new_indices.push_back(i);
            xit->second[ybin][zbin] = new_indices;
          }
          else {
            NODELET_DEBUG_STREAM("found z bin" << zbin);
            xit->second[ybin][zbin].push_back(i);
          }
        }
      }
    }
    // publish the result
    jsk_recognition_msgs::ClusterPointIndices output;
    output.header = msg->header;
    for (std::map<int, std::map<int, std::map<int, std::vector<size_t> > > >::iterator xit = grid.begin();
         xit != grid.end();
         xit++) {
      std::map<int, std::map<int, std::vector<size_t> > > ybins = xit->second;
      for (std::map<int, std::map<int, std::vector<size_t> > >::iterator yit = ybins.begin();
           yit != ybins.end();
           yit++) {
        std::map<int, std::vector<size_t> > zbins = yit->second;
        for (std::map<int, std::vector<size_t> >::iterator zit = zbins.begin();
             zit != zbins.end();
             zit++) {
          std::vector<size_t> indices = zit->second;
          NODELET_DEBUG_STREAM("size: " << indices.size());
          if (indices.size() > min_indices_) {
            PCLIndicesMsg ros_indices;
            ros_indices.header = msg->header;
            for (size_t j = 0; j < indices.size(); j++) {
              ros_indices.indices.push_back(indices[j]);
            }
            output.cluster_indices.push_back(ros_indices);
          }
        }
      }
    }
    pub_.publish(output);
  }
  bool
  PrimitiveShapeClassifier::estimate(const pcl::PointCloud<PointT>::Ptr& cloud,
                                     const pcl::PointCloud<pcl::Normal>::Ptr& normal,
                                     const pcl::ModelCoefficients::Ptr& plane,
                                     pcl::PointIndices::Ptr& boundary_indices,
                                     pcl::PointCloud<PointT>::Ptr& projected_cloud,
                                     float& circle_likelihood,
                                     float& box_likelihood)
  {
    // estimate boundaries
    pcl::PointCloud<pcl::Boundary>::Ptr boundaries(new pcl::PointCloud<pcl::Boundary>);
    pcl::BoundaryEstimation<PointT, pcl::Normal, pcl::Boundary> b;
    b.setInputCloud(cloud);
    b.setInputNormals(normal);
    b.setSearchMethod(typename pcl::search::KdTree<PointT>::Ptr(new pcl::search::KdTree<PointT>));
    b.setAngleThreshold(DEG2RAD(70));
    b.setRadiusSearch(0.03);
    b.compute(*boundaries);

    // set boundaries as indices
    for (size_t i = 0; i < boundaries->points.size(); ++i)
      if ((int)boundaries->points[i].boundary_point)
        boundary_indices->indices.push_back(i);

    // extract boundaries
    pcl::PointCloud<PointT>::Ptr boundary_cloud(new pcl::PointCloud<PointT>);
    pcl::ExtractIndices<PointT> ext;
    ext.setInputCloud(cloud);
    ext.setIndices(boundary_indices);
    ext.filter(*boundary_cloud);

    // thresholding with min points num
    if (boundary_indices->indices.size() < min_points_num_)
      return false;

    // project to supporting plane
    pcl::ProjectInliers<PointT> proj;
    proj.setModelType(pcl::SACMODEL_PLANE);
    proj.setInputCloud(boundary_cloud);
    proj.setModelCoefficients(plane);
    proj.filter(*projected_cloud);

    // estimate circles
    pcl::PointIndices::Ptr      circle_inliers(new pcl::PointIndices);
    pcl::ModelCoefficients::Ptr circle_coeffs(new pcl::ModelCoefficients);
    pcl::PointIndices::Ptr      line_inliers(new pcl::PointIndices);
    pcl::ModelCoefficients::Ptr line_coeffs(new pcl::ModelCoefficients);

    pcl::SACSegmentation<PointT> seg;
    seg.setInputCloud(projected_cloud);

    seg.setOptimizeCoefficients(true);
    seg.setMethodType(pcl::SAC_RANSAC);
    seg.setMaxIterations(sac_max_iterations_);
    seg.setModelType(pcl::SACMODEL_CIRCLE3D);
    seg.setDistanceThreshold(sac_distance_threshold_);
    seg.setRadiusLimits(sac_radius_limit_min_, sac_radius_limit_max_);
    seg.segment(*circle_inliers, *circle_coeffs);

    seg.setOptimizeCoefficients(true);
    seg.setMethodType(pcl::SAC_RANSAC);
    seg.setMaxIterations(sac_max_iterations_);
    seg.setModelType(pcl::SACMODEL_LINE);
    seg.setDistanceThreshold(sac_distance_threshold_);
    seg.segment(*line_inliers, *line_coeffs);

    // compute likelihood
    circle_likelihood =
      1.0f * circle_inliers->indices.size() / projected_cloud->points.size();
    box_likelihood =
      1.0f * line_inliers->indices.size() / projected_cloud->points.size();

    NODELET_DEBUG_STREAM("Projected cloud has " << projected_cloud->points.size() << " points");
    NODELET_DEBUG_STREAM(circle_inliers->indices.size() << " circle inliers found");
    NODELET_DEBUG_STREAM("circle confidence: " << circle_likelihood);
    NODELET_DEBUG_STREAM(line_inliers->indices.size() << " line inliers found");
    NODELET_DEBUG_STREAM("box confidence: " << box_likelihood);

    return true;
  }
  void
  PrimitiveShapeClassifier::process(const sensor_msgs::PointCloud2::ConstPtr& ros_cloud,
                                    const sensor_msgs::PointCloud2::ConstPtr& ros_normal,
                                    const jsk_recognition_msgs::ClusterPointIndices::ConstPtr& ros_indices,
                                    const jsk_recognition_msgs::PolygonArray::ConstPtr& ros_polygons)
  {
    boost::mutex::scoped_lock lock(mutex_);

    if (!checkFrameId(ros_cloud, ros_normal, ros_indices, ros_polygons)) return;

    pcl::PointCloud<PointT>::Ptr input(new pcl::PointCloud<PointT>);
    pcl::fromROSMsg(*ros_cloud, *input);

    pcl::PointCloud<pcl::Normal>::Ptr normal(new pcl::PointCloud<pcl::Normal>);
    pcl::fromROSMsg(*ros_normal, *normal);

    pcl::ExtractIndices<PointT> ext_input;
    ext_input.setInputCloud(input);
    pcl::ExtractIndices<pcl::Normal> ext_normal;
    ext_normal.setInputCloud(normal);

    std::vector<jsk_recognition_utils::Polygon::Ptr> polygons
      = jsk_recognition_utils::Polygon::fromROSMsg(*ros_polygons);

    jsk_recognition_msgs::ClassificationResult result;
    result.header = ros_cloud->header;
    result.classifier = "primitive_shape_classifier";
    result.target_names.push_back("box");
    result.target_names.push_back("circle");
    result.target_names.push_back("other");

    pcl::PointCloud<PointT>::Ptr projected_cloud(new pcl::PointCloud<PointT>);
    std::vector<pcl::PointIndices::Ptr> boundary_indices;

    NODELET_DEBUG_STREAM("Cluster num: " << ros_indices->cluster_indices.size());
    for (size_t i = 0; i < ros_indices->cluster_indices.size(); ++i)
    {
      pcl::PointIndices::Ptr indices(new pcl::PointIndices);
      indices->indices = ros_indices->cluster_indices[i].indices;
      NODELET_DEBUG_STREAM("Estimating cluster #" << i << " (" << indices->indices.size() << " points)");

      pcl::PointCloud<PointT>::Ptr cluster_cloud(new pcl::PointCloud<PointT>);
      ext_input.setIndices(indices);
      ext_input.filter(*cluster_cloud);

      pcl::PointCloud<pcl::Normal>::Ptr cluster_normal(new pcl::PointCloud<pcl::Normal>);
      ext_normal.setIndices(indices);
      ext_normal.filter(*cluster_normal);

      pcl::ModelCoefficients::Ptr support_plane(new pcl::ModelCoefficients);
      if (!getSupportPlane(cluster_cloud, polygons, support_plane))
      {
        NODELET_ERROR_STREAM("cloud " << i << " has no support plane. skipped");
        continue;
      }

      pcl::PointIndices::Ptr b(new pcl::PointIndices);
      pcl::PointCloud<PointT>::Ptr pc(new pcl::PointCloud<PointT>);
      float circle_likelihood, box_likelihood;
      estimate(cluster_cloud, cluster_normal, support_plane,
               b, pc,
               circle_likelihood, box_likelihood);
      boundary_indices.push_back(std::move(b));
      *projected_cloud += *pc;

      if (circle_likelihood > circle_threshold_) {
        // circle
        result.labels.push_back(1);
        result.label_names.push_back("circle");
        result.label_proba.push_back(circle_likelihood);
      } else if (box_likelihood > box_threshold_) {
        // box
        result.labels.push_back(0);
        result.label_names.push_back("box");
        result.label_proba.push_back(box_likelihood);
      } else {
        // other
        result.labels.push_back(3);
        result.label_names.push_back("other");
        result.label_proba.push_back(0.0);
      }
    }

    // publish results
    sensor_msgs::PointCloud2 ros_projected_cloud;
    pcl::toROSMsg(*projected_cloud, ros_projected_cloud);
    ros_projected_cloud.header = ros_cloud->header;
    pub_projected_cloud_.publish(ros_projected_cloud);

    jsk_recognition_msgs::ClusterPointIndices ros_boundary_indices;
    ros_boundary_indices.header = ros_cloud->header;
    for (size_t i = 0; i < boundary_indices.size(); ++i)
    {
      pcl_msgs::PointIndices ri;
      pcl_conversions::moveFromPCL(*boundary_indices[i], ri);
      ros_boundary_indices.cluster_indices.push_back(ri);
    }
    pub_boundary_indices_.publish(ros_boundary_indices);

    pub_class_.publish(result);
  }