void ProjectImagePoint::project( const geometry_msgs::PointStamped::ConstPtr& msg) { vital_checker_->poke(); boost::mutex::scoped_lock lock(mutex_); if (!camera_info_) { JSK_NODELET_WARN( "[ProjectImagePoint::project] camera info is not yet available"); return; } image_geometry::PinholeCameraModel model; model.fromCameraInfo(camera_info_); cv::Point3d ray = model.projectPixelTo3dRay( cv::Point2d(msg->point.x, msg->point.y)); geometry_msgs::Vector3Stamped vector; vector.header.frame_id = camera_info_->header.frame_id; vector.header = msg->header; vector.vector.x = ray.x; vector.vector.y = ray.y; vector.vector.z = ray.z; pub_vector_.publish(vector); if (ray.z == 0.0) { JSK_NODELET_ERROR("Z value of projected ray is 0"); return; } double alpha = z_ / ray.z; geometry_msgs::PointStamped point; point.header = msg->header; point.header.frame_id = camera_info_->header.frame_id; point.point.x = ray.x * alpha; point.point.y = ray.y * alpha; point.point.z = ray.z * alpha; pub_.publish(point); }
void TiltLaserListener::getPointCloudFromLocalBuffer( const std::vector<sensor_msgs::PointCloud2::ConstPtr>& target_clouds, sensor_msgs::PointCloud2& output_cloud) { if (target_clouds.size() > 0) { output_cloud.fields = target_clouds[0]->fields; output_cloud.is_bigendian = target_clouds[0]->is_bigendian; output_cloud.is_dense = true; output_cloud.point_step = target_clouds[0]->point_step; size_t point_num = 0; size_t data_num = 0; for (size_t i = 0; i < target_clouds.size(); i++) { data_num += target_clouds[i]->row_step; point_num += target_clouds[i]->width * target_clouds[i]->height; } output_cloud.data.reserve(data_num); for (size_t i = 0; i < target_clouds.size(); i++) { std::copy(target_clouds[i]->data.begin(), target_clouds[i]->data.end(), std::back_inserter(output_cloud.data)); } output_cloud.header.frame_id = target_clouds[0]->header.frame_id; output_cloud.width = point_num; output_cloud.height = 1; output_cloud.row_step = data_num; } else { JSK_NODELET_WARN("target_clouds size is 0"); } }
void PlaneSupportedCuboidEstimator::cloudCallback( const sensor_msgs::PointCloud2::ConstPtr& msg) { boost::mutex::scoped_lock lock(mutex_); NODELET_INFO("cloudCallback"); if (!latest_polygon_msg_ || !latest_coefficients_msg_) { JSK_NODELET_WARN("Not yet polygon is available"); return; } if (!tracker_) { NODELET_INFO("initTracker"); // Update polygons_ vector polygons_.clear(); for (size_t i = 0; i < latest_polygon_msg_->polygons.size(); i++) { Polygon::Ptr polygon = Polygon::fromROSMsgPtr(latest_polygon_msg_->polygons[i].polygon); polygons_.push_back(polygon); } // viewpoint tf::StampedTransform transform = lookupTransformWithDuration(tf_, sensor_frame_, msg->header.frame_id, ros::Time(0.0), ros::Duration(0.0)); tf::vectorTFToEigen(transform.getOrigin(), viewpoint_); ParticleCloud::Ptr particles = initParticles(); tracker_.reset(new pcl::tracking::ROSCollaborativeParticleFilterTracker<pcl::PointXYZ, pcl::tracking::ParticleCuboid>); tracker_->setCustomSampleFunc(boost::bind(&PlaneSupportedCuboidEstimator::sample, this, _1)); tracker_->setLikelihoodFunc(boost::bind(&PlaneSupportedCuboidEstimator::likelihood, this, _1, _2)); tracker_->setParticles(particles); tracker_->setParticleNum(particle_num_); support_plane_updated_ = false; // Publish histograms publishHistogram(particles, 0, pub_histogram_global_x_, msg->header); publishHistogram(particles, 1, pub_histogram_global_y_, msg->header); publishHistogram(particles, 2, pub_histogram_global_z_, msg->header); publishHistogram(particles, 3, pub_histogram_global_roll_, msg->header); publishHistogram(particles, 4, pub_histogram_global_pitch_, msg->header); publishHistogram(particles, 5, pub_histogram_global_yaw_, msg->header); publishHistogram(particles, 6, pub_histogram_dx_, msg->header); publishHistogram(particles, 7, pub_histogram_dy_, msg->header); publishHistogram(particles, 8, pub_histogram_dz_, msg->header); // Publish particles sensor_msgs::PointCloud2 ros_particles; pcl::toROSMsg(*particles, ros_particles); ros_particles.header = msg->header; pub_particles_.publish(ros_particles); } else { ParticleCloud::Ptr particles = tracker_->getParticles(); Eigen::Vector4f center; pcl::compute3DCentroid(*particles, center); if (center.norm() > fast_cloud_threshold_) { estimate(msg); } } }
void GridSampler::configCallback(Config &config, uint32_t level) { boost::mutex::scoped_lock(mutex_); if (config.grid_size == 0.0) { JSK_NODELET_WARN("grid_size == 0.0 is prohibited"); return; } else { grid_size_ = config.grid_size; min_indices_ = config.min_indices; } }
void FeatureRegistration::estimate( const sensor_msgs::PointCloud2::ConstPtr& cloud_msg, const sensor_msgs::PointCloud2::ConstPtr& feature_msg) { boost::mutex::scoped_lock lock(mutex_); if (!reference_cloud_ || !reference_feature_) { JSK_NODELET_ERROR("Not yet reference data is available"); return; } pcl::PointCloud<pcl::PointNormal>::Ptr cloud (new pcl::PointCloud<pcl::PointNormal>); pcl::PointCloud<pcl::PointNormal>::Ptr object_aligned (new pcl::PointCloud<pcl::PointNormal>); pcl::PointCloud<pcl::FPFHSignature33>::Ptr feature (new pcl::PointCloud<pcl::FPFHSignature33>); pcl::fromROSMsg(*cloud_msg, *cloud); pcl::fromROSMsg(*feature_msg, *feature); pcl::SampleConsensusPrerejective<pcl::PointNormal, pcl::PointNormal, pcl::FPFHSignature33> align; align.setInputSource(reference_cloud_); align.setSourceFeatures(reference_feature_); align.setInputTarget(cloud); align.setTargetFeatures(feature); align.setMaximumIterations(max_iterations_); // Number of RANSAC iterations align.setNumberOfSamples(3); // Number of points to sample for generating/prerejecting a pose align.setCorrespondenceRandomness(correspondence_randomness_); // Number of nearest features to use align.setSimilarityThreshold(similarity_threshold_); // Polygonal edge length similarity threshold align.setMaxCorrespondenceDistance(max_correspondence_distance_); // Inlier threshold align.setInlierFraction(inlier_fraction_); // Required inlier fraction for accepting a pose hypothesis align.align (*object_aligned); if (align.hasConverged ()) { // Print results printf ("\n"); Eigen::Affine3f transformation(align.getFinalTransformation()); geometry_msgs::PoseStamped ros_pose; tf::poseEigenToMsg(transformation, ros_pose.pose); ros_pose.header = cloud_msg->header; pub_pose_.publish(ros_pose); pcl::PointCloud<pcl::PointNormal>::Ptr result_cloud (new pcl::PointCloud<pcl::PointNormal>); pcl::transformPointCloud( *reference_cloud_, *result_cloud, transformation); sensor_msgs::PointCloud2 ros_cloud; pcl::toROSMsg(*object_aligned, ros_cloud); ros_cloud.header = cloud_msg->header; pub_cloud_.publish(ros_cloud); //pcl::console::print_info ("Inliers: %i/%i\n", align.getInliers ().size (), object->size ()); } else { JSK_NODELET_WARN("failed to align pointcloud"); } }
void GeometricConsistencyGrouping::recognize( const sensor_msgs::PointCloud2::ConstPtr& scene_cloud_msg, const sensor_msgs::PointCloud2::ConstPtr& scene_feature_msg) { boost::mutex::scoped_lock lock(mutex_); if (!reference_cloud_ || !reference_feature_) { NODELET_ERROR_THROTTLE(1.0, "Not yet reference is available"); return; } pcl::PointCloud<pcl::SHOT352>::Ptr scene_feature (new pcl::PointCloud<pcl::SHOT352>); pcl::PointCloud<pcl::PointNormal>::Ptr scene_cloud (new pcl::PointCloud<pcl::PointNormal>); pcl::fromROSMsg(*scene_cloud_msg, *scene_cloud); pcl::fromROSMsg(*scene_feature_msg, *scene_feature); pcl::CorrespondencesPtr model_scene_corrs (new pcl::Correspondences ()); pcl::KdTreeFLANN<pcl::SHOT352> match_search; match_search.setInputCloud (reference_feature_); for (size_t i = 0; i < scene_feature->size(); ++i) { std::vector<int> neigh_indices(1); std::vector<float> neigh_sqr_dists(1); if (!pcl_isfinite (scene_feature->at(i).descriptor[0])) { //skipping NaNs continue; } int found_neighs = match_search.nearestKSearch(scene_feature->at(i), 1, neigh_indices, neigh_sqr_dists); // add match only if the squared descriptor distance is less than 0.25 // (SHOT descriptor distances are between 0 and 1 by design) if (found_neighs == 1 && neigh_sqr_dists[0] < 0.25f) { pcl::Correspondence corr (neigh_indices[0], static_cast<int> (i), neigh_sqr_dists[0]); model_scene_corrs->push_back (corr); } } pcl::GeometricConsistencyGrouping<pcl::PointNormal, pcl::PointNormal> gc_clusterer; gc_clusterer.setGCSize(gc_size_); gc_clusterer.setGCThreshold(gc_thresh_); gc_clusterer.setInputCloud(reference_cloud_); gc_clusterer.setSceneCloud(scene_cloud); gc_clusterer.setModelSceneCorrespondences(model_scene_corrs); //gc_clusterer.cluster (clustered_corrs); std::vector<pcl::Correspondences> clustered_corrs; std::vector<Eigen::Matrix4f, Eigen::aligned_allocator<Eigen::Matrix4f> > rototranslations; gc_clusterer.recognize(rototranslations, clustered_corrs); if (rototranslations.size() > 0) { JSK_NODELET_INFO("detected %lu objects", rototranslations.size()); Eigen::Matrix4f result_mat = rototranslations[0]; Eigen::Affine3f affine(result_mat); geometry_msgs::PoseStamped ros_pose; tf::poseEigenToMsg(affine, ros_pose.pose); ros_pose.header = scene_cloud_msg->header; pub_output_.publish(ros_pose); } else { JSK_NODELET_WARN("Failed to find object"); } }
void PointCloudLocalization::cloudCallback( const sensor_msgs::PointCloud2::ConstPtr& cloud_msg) { vital_checker_->poke(); boost::mutex::scoped_lock lock(mutex_); //JSK_NODELET_INFO("cloudCallback"); latest_cloud_ = cloud_msg; if (localize_requested_){ JSK_NODELET_INFO("localization is requested"); try { pcl::PointCloud<pcl::PointNormal>::Ptr local_cloud (new pcl::PointCloud<pcl::PointNormal>); pcl::fromROSMsg(*latest_cloud_, *local_cloud); JSK_NODELET_INFO("waiting for tf transformation from %s tp %s", latest_cloud_->header.frame_id.c_str(), global_frame_.c_str()); if (tf_listener_->waitForTransform( latest_cloud_->header.frame_id, global_frame_, latest_cloud_->header.stamp, ros::Duration(1.0))) { pcl::PointCloud<pcl::PointNormal>::Ptr input_cloud (new pcl::PointCloud<pcl::PointNormal>); if (use_normal_) { pcl_ros::transformPointCloudWithNormals(global_frame_, *local_cloud, *input_cloud, *tf_listener_); } else { pcl_ros::transformPointCloud(global_frame_, *local_cloud, *input_cloud, *tf_listener_); } pcl::PointCloud<pcl::PointNormal>::Ptr input_downsampled_cloud (new pcl::PointCloud<pcl::PointNormal>); applyDownsampling(input_cloud, *input_downsampled_cloud); if (isFirstTime()) { all_cloud_ = input_downsampled_cloud; first_time_ = false; } else { // run ICP ros::ServiceClient client = pnh_->serviceClient<jsk_pcl_ros::ICPAlign>("icp_align"); jsk_pcl_ros::ICPAlign icp_srv; if (clip_unseen_pointcloud_) { // Before running ICP, remove pointcloud where we cannot see // First, transform reference pointcloud, that is all_cloud_, into // sensor frame. // And after that, remove points which are x < 0. tf::StampedTransform global_sensor_tf_transform = lookupTransformWithDuration( tf_listener_, global_frame_, sensor_frame_, cloud_msg->header.stamp, ros::Duration(1.0)); Eigen::Affine3f global_sensor_transform; tf::transformTFToEigen(global_sensor_tf_transform, global_sensor_transform); pcl::PointCloud<pcl::PointNormal>::Ptr sensor_cloud (new pcl::PointCloud<pcl::PointNormal>); pcl::transformPointCloudWithNormals( *all_cloud_, *sensor_cloud, global_sensor_transform.inverse()); // Remove negative-x points pcl::PassThrough<pcl::PointNormal> pass; pass.setInputCloud(sensor_cloud); pass.setFilterFieldName("x"); pass.setFilterLimits(0.0, 100.0); pcl::PointCloud<pcl::PointNormal>::Ptr filtered_cloud (new pcl::PointCloud<pcl::PointNormal>); pass.filter(*filtered_cloud); JSK_NODELET_INFO("clipping: %lu -> %lu", sensor_cloud->points.size(), filtered_cloud->points.size()); // Convert the pointcloud to global frame again pcl::PointCloud<pcl::PointNormal>::Ptr global_filtered_cloud (new pcl::PointCloud<pcl::PointNormal>); pcl::transformPointCloudWithNormals( *filtered_cloud, *global_filtered_cloud, global_sensor_transform); pcl::toROSMsg(*global_filtered_cloud, icp_srv.request.target_cloud); } else { pcl::toROSMsg(*all_cloud_, icp_srv.request.target_cloud); } pcl::toROSMsg(*input_downsampled_cloud, icp_srv.request.reference_cloud); if (client.call(icp_srv)) { Eigen::Affine3f transform; tf::poseMsgToEigen(icp_srv.response.result.pose, transform); Eigen::Vector3f transform_pos(transform.translation()); float roll, pitch, yaw; pcl::getEulerAngles(transform, roll, pitch, yaw); JSK_NODELET_INFO("aligned parameter --"); JSK_NODELET_INFO(" - pos: [%f, %f, %f]", transform_pos[0], transform_pos[1], transform_pos[2]); JSK_NODELET_INFO(" - rot: [%f, %f, %f]", roll, pitch, yaw); pcl::PointCloud<pcl::PointNormal>::Ptr transformed_input_cloud (new pcl::PointCloud<pcl::PointNormal>); if (use_normal_) { pcl::transformPointCloudWithNormals(*input_cloud, *transformed_input_cloud, transform); } else { pcl::transformPointCloud(*input_cloud, *transformed_input_cloud, transform); } pcl::PointCloud<pcl::PointNormal>::Ptr concatenated_cloud (new pcl::PointCloud<pcl::PointNormal>); *concatenated_cloud = *all_cloud_ + *transformed_input_cloud; // update *all_cloud applyDownsampling(concatenated_cloud, *all_cloud_); // update localize_transform_ tf::Transform icp_transform; tf::transformEigenToTF(transform, icp_transform); { boost::mutex::scoped_lock tf_lock(tf_mutex_); localize_transform_ = localize_transform_ * icp_transform; } } else { JSK_NODELET_ERROR("Failed to call ~icp_align"); return; } } localize_requested_ = false; } else { JSK_NODELET_WARN("No tf transformation is available"); } } catch (tf2::ConnectivityException &e) { JSK_NODELET_ERROR("[%s] Transform error: %s", __PRETTY_FUNCTION__, e.what()); return; } catch (tf2::InvalidArgumentException &e) { JSK_NODELET_ERROR("[%s] Transform error: %s", __PRETTY_FUNCTION__, e.what()); return; } } }
void CollisionDetector::initSelfMask() { // genearte urdf model std::string content; urdf::Model urdf_model; if (nh_->getParam("robot_description", content)) { if (!urdf_model.initString(content)) { JSK_NODELET_ERROR("Unable to parse URDF description!"); } } std::string root_link_id; std::string world_frame_id; pnh_->param<std::string>("root_link_id", root_link_id, "BODY"); pnh_->param<std::string>("world_frame_id", world_frame_id, "map"); double default_padding, default_scale; pnh_->param("self_see_default_padding", default_padding, 0.01); pnh_->param("self_see_default_scale", default_scale, 1.0); std::vector<robot_self_filter::LinkInfo> links; std::string link_names; if (!pnh_->hasParam("self_see_links")) { JSK_NODELET_WARN("No links specified for self filtering."); } else { XmlRpc::XmlRpcValue ssl_vals;; pnh_->getParam("self_see_links", ssl_vals); if (ssl_vals.getType() != XmlRpc::XmlRpcValue::TypeArray) { JSK_NODELET_WARN("Self see links need to be an array"); } else { if (ssl_vals.size() == 0) { JSK_NODELET_WARN("No values in self see links array"); } else { for (int i = 0; i < ssl_vals.size(); i++) { robot_self_filter::LinkInfo li; if (ssl_vals[i].getType() != XmlRpc::XmlRpcValue::TypeStruct) { JSK_NODELET_WARN("Self see links entry %d is not a structure. Stopping processing of self see links",i); break; } if (!ssl_vals[i].hasMember("name")) { JSK_NODELET_WARN("Self see links entry %d has no name. Stopping processing of self see links",i); break; } li.name = std::string(ssl_vals[i]["name"]); if (!ssl_vals[i].hasMember("padding")) { JSK_NODELET_DEBUG("Self see links entry %d has no padding. Assuming default padding of %g",i,default_padding); li.padding = default_padding; } else { li.padding = ssl_vals[i]["padding"]; } if (!ssl_vals[i].hasMember("scale")) { JSK_NODELET_DEBUG("Self see links entry %d has no scale. Assuming default scale of %g",i,default_scale); li.scale = default_scale; } else { li.scale = ssl_vals[i]["scale"]; } links.push_back(li); } } } } self_mask_ = boost::shared_ptr<robot_self_filter::SelfMaskUrdfRobot>(new robot_self_filter::SelfMaskUrdfRobot(tf_listener_, tf_broadcaster_, links, urdf_model, root_link_id, world_frame_id)); }