Пример #1
0
Файл: hit.c Проект: Elytum/rtv1
int			find_closest(t_data *data, const int get_normal)
{
	data->closest[1] = -1;
	if (get_normal == 1)
	{
		find_closest_sphere(data, data->viewray, &(data->t));
		find_closest_plane(data, data->viewray, &(data->t));
		find_closest_cone(data, data->viewray, &(data->t));
		find_closest_cylinder(data, data->viewray, &(data->t));
		if (data->closest[1] == -1)
			return (0);
		if (data->closest[0] == SPHERE)
			return (sphere_normal(data));
		else if (data->closest[0] == PLANE)
			return (plane_normal(data));
		else if (data->closest[0] == CYLINDER)
			return (cylinder_normal(data));
		else if (data->closest[0] == CONE)
			return (cone_normal(data));
		return (1);
	}
	return (hit_any_sphere(data, data->lightray, data->t) ||
			hit_any_plane(data, data->lightray, data->t) ||
			hit_any_cone(data, data->lightray, data->t) ||
			hit_any_cylinder(data, data->lightray, data->t));
}
/*****************************************************************
   double* excess_of_quad(int ni, int nj, double *vec1, double *vec2, 
                          double *vec3, double *vec4 )
*******************************************************************/
double* excess_of_quad(int ni, int nj, double *vec1, double *vec2, double *vec3, double *vec4 )
{
  int n;
  double ang12, ang23, ang34, ang41;
  double *excess, *plane1, *plane2, *plane3, *plane4;
  double *angle12, *angle23, *angle34, *angle41;
  
  excess = (double *)malloc(ni*nj*sizeof(double));

  plane1=plane_normal(ni, nj, vec1, vec2);
  plane2=plane_normal(ni, nj, vec2, vec3);
  plane3=plane_normal(ni, nj, vec3, vec4);
  plane4=plane_normal(ni, nj, vec4, vec1);
  angle12=angle_between_vectors(ni, nj, plane2,plane1);
  angle23=angle_between_vectors(ni, nj, plane3,plane2);
  angle34=angle_between_vectors(ni, nj, plane4,plane3);
  angle41=angle_between_vectors(ni, nj, plane1,plane4);

  for(n=0; n<ni*nj; n++) {
    ang12 = M_PI-angle12[n];
    ang23 = M_PI-angle23[n];
    ang34 = M_PI-angle34[n];
    ang41 = M_PI-angle41[n];
    excess[n] = ang12+ang23+ang34+ang41-2*M_PI;
  }

  free(plane1);
  free(plane2);
  free(plane3);
  free(plane4);
  free(angle12);
  free(angle23);
  free(angle34);
  free(angle41);
  
  return excess;

}; /* excess_of_quad */
Пример #3
0
bool ObjectFinder::find_toy_block(float surface_height, geometry_msgs::PoseStamped &object_pose) {
    Eigen::Vector3f plane_normal;
    double plane_dist;
    //bool valid_plane;
    Eigen::Vector3f major_axis;
    Eigen::Vector3f centroid;
    bool found_object = true; //should verify this
    double block_height = 0.035; //this height is specific to the TOY_BLOCK model
    //if insufficient points in plane, find_plane_fit returns "false"
    //should do more sanity testing on found_object status
    //hard-coded search bounds based on a block of width 0.035
    found_object = pclUtils_.find_plane_fit(0.4, 1, -0.5, 0.5, surface_height + 0.025, surface_height + 0.045, 0.001,
            plane_normal, plane_dist, major_axis, centroid);
    //should have put a return value on find_plane_fit;
    //
    if (plane_normal(2) < 0) plane_normal(2) *= -1.0; //in world frame, normal must point UP
    Eigen::Matrix3f R;
    Eigen::Vector3f y_vec;
    R.col(0) = major_axis;
    R.col(2) = plane_normal;
    R.col(1) = plane_normal.cross(major_axis);
    Eigen::Quaternionf quat(R);
    object_pose.header.frame_id = "base_link";
    object_pose.pose.position.x = centroid(0);
    object_pose.pose.position.y = centroid(1);
    //the TOY_BLOCK model has its origin in the middle of the block, not the top surface
    //so lower the block model origin by half the block height from upper surface
    object_pose.pose.position.z = centroid(2)-0.5*block_height;
    //create R from normal and major axis, then convert R to quaternion

    object_pose.pose.orientation.x = quat.x();
    object_pose.pose.orientation.y = quat.y();
    object_pose.pose.orientation.z = quat.z();
    object_pose.pose.orientation.w = quat.w();
    return found_object;
}
Пример #4
0
static void
do_normal(GLfloat x1, GLfloat y1, GLfloat z1,
	  GLfloat x2, GLfloat y2, GLfloat z2,
	  GLfloat x3, GLfloat y3, GLfloat z3)
{
  plane plane;
  vector n;
  vector_set(&plane.p1, x1, y1, z1);
  vector_set(&plane.p2, x2, y2, z2);
  vector_set(&plane.p3, x3, y3, z3);
  plane_normal(plane, &n);
  n.x = -n.x; n.y = -n.y; n.z = -n.z;

  glNormal3f(n.x, n.y, n.z);

#ifdef DEBUG
  /* Draw a line in the direction of this face's normal. */
  {
    GLfloat ax = n.x > 0 ? n.x : -n.x;
    GLfloat ay = n.y > 0 ? n.y : -n.y;
    GLfloat az = n.z > 0 ? n.z : -n.z;
    GLfloat mx = (x1 + x2 + x3) / 3;
    GLfloat my = (y1 + y2 + y3) / 3;
    GLfloat mz = (z1 + z2 + z3) / 3;
    GLfloat xx, yy, zz;

    GLfloat max = ax > ay ? ax : ay;
    if (az > max) max = az;
    max *= 2;
    xx = n.x / max;
    yy = n.y / max;
    zz = n.z / max;

    glBegin(GL_LINE_LOOP);
    glVertex3f(mx, my, mz);
    glVertex3f(mx+xx, my+yy, mz+zz);
    glEnd();
  }
#endif /* DEBUG */
}
Пример #5
0
bool Picker3d::pick(const glm::ivec2 &input, const float z,
					glm::vec3 &pickedPosition) const {
	if (!mData) return false;

	ci::CameraPersp&	cam(mData->mCamera);
	// generate a ray from the camera into our world
	float				u = static_cast<float>(input.x) / mData->mWindowSize.x;
	float				v = static_cast<float>(input.y) / mData->mWindowSize.y;

	// because OpenGL and Cinder use a coordinate system
	// where (0, 0) is in the LOWERleft corner, we have to flip the v-coordinate
	ci::Ray				ray = cam.generateRay(u , 1.0f - v, cam.getAspectRatio() );

	glm::vec3			plane_origin(glm::vec3(0.0f, 0.0f, z)),
						plane_normal(glm::vec3(0.0f, 0.0f, 1.0f));
	float				t;
	if (ray.calcPlaneIntersection(plane_origin, plane_normal, &t)) {
		pickedPosition = ray.calcPosition(t);
		return true;
	}
	return false;
}
Пример #6
0
void OnePointRansac::planesCheck(
        pcl::PointCloud<PointType>::Ptr& cloud,
        pcl::PointCloud<NormalType>::Ptr& cloud_normals,
        std::vector<int>& filtered_indices,
        std::vector<int>& planes_indices,
        float max_angle,
        int map_min_inliers
        ){

        pcl::PointIndices::Ptr inliers(new pcl::PointIndices);
        pcl::ModelCoefficients model_coefficients;
        inliers->indices.clear ();
        model_coefficients.values.clear ();


        inliers->header = model_coefficients.header = cloud->header;
        model_coefficients.values.resize (4);

        size_t best_score = 0;
        const size_t no_of_pts = cloud->points.size();
        const double no_of_pts_inverse = 1.0/(double)no_of_pts;
        const double lognum = std::log(1-this->probability);

        //Random
        srand (time(NULL));
        unsigned current_max_iterations = this->max_iterations;


        unsigned it = 0;
        for(; it < current_max_iterations; ++it)
        {
                const int idx = rand() % no_of_pts;
                const Eigen::Vector3f& current_plane_normal = cloud_normals->points[idx].getNormalVector3fMap ();
                float current_plane_offset = current_plane_normal.dot(cloud->points[idx].getVector3fMap ());

                size_t current_score = 0;
                for (size_t k = 0; k < no_of_pts; ++k)
                {
                        const int kidx = k;
                        if (current_plane_normal.dot (cloud_normals->points[kidx].getNormalVector3fMap ()) > this->min_cosangle_th &&
                            (((current_plane_offset - current_plane_normal.dot (cloud->points[kidx].getVector3fMap ())) /
                              current_plane_normal.dot (cloud_normals->points[kidx].getNormalVector3fMap ())) *
                             cloud_normals->points[kidx].getNormalVector3fMap ()).squaredNorm () < this->distance_th)
                                ++current_score;
                }

                // update
                if(current_score > best_score)
                {
                        best_score = current_score;
                        model_coefficients.values[0] = current_plane_normal.x ();
                        model_coefficients.values[1] = current_plane_normal.y ();
                        model_coefficients.values[2] = current_plane_normal.z ();
                        model_coefficients.values[3] = current_plane_offset;

                        if(best_score == no_of_pts)
                                current_max_iterations = 0;
                        else
                                current_max_iterations = std::min((double)this->max_iterations, std::ceil(lognum / std::log(1.0 - std::pow((double)best_score * no_of_pts_inverse, 3.0))));
                }
        }

        Eigen::Map<Eigen::Vector3f> plane_normal (&(model_coefficients.values[0]));
        for (size_t k = 0; k < no_of_pts; ++k)
        {
                const int kidx = k;
                if (plane_normal.dot (cloud_normals->points[kidx].getNormalVector3fMap ()) > this->min_cosangle_th &&
                    (((model_coefficients.values[3] - plane_normal.dot (cloud->points[kidx].getVector3fMap ())) /
                      plane_normal.dot (cloud_normals->points[kidx].getNormalVector3fMap ())) *
                     cloud_normals->points[kidx].getNormalVector3fMap ()).squaredNorm () < this->distance_th)
                        inliers->indices.push_back (kidx);
        }


        pcl::ExtractIndices<PointType> extract;
       extract.setInputCloud (cloud);
       extract.setIndices (inliers);
       extract.setNegative (false);

       extract.filter (planes_indices);

       extract.setNegative (true);
       extract.filter (filtered_indices);
}
void ClusterExtraction::processCloud(float plane_tolerance)
{
	ros::Time stamp = ros::Time::now();

	if(!pcl_data)
	{
		ROS_INFO("No xtion_camera data.");
		sleep(1);
		return;
	}

	//pcl::PointCloud<PoinT>::Ptr _cloud;// (new pcl::PointCloud<PoinT>);
	sensor_msgs::PointCloud2ConstPtr _temp_cloud_ = pcl_data;
	pcl::PointCloud<PoinT>::Ptr _cloud (new pcl::PointCloud<PoinT>);
	pcl::fromROSMsg(*_temp_cloud_, *_cloud);

	pcl::VoxelGrid<PoinT> vg_filter;
	pcl::PointCloud<PoinT>::Ptr cloud_filtered (new pcl::PointCloud<PoinT>);

	vg_filter.setInputCloud (_cloud);
	vg_filter.setLeafSize (0.01f, 0.01f, 0.01f);
	vg_filter.filter (*cloud_filtered);

	_cloud = cloud_filtered;

	/**********************************************
	 * NEW BULL
	 *********************************************/

	//////////////////////////////////////////////////////////////////////
	// Cluster Extraction
	//////////////////////////////////////////////////////////////////////
	// Findout the points that are more than 1.25 m away.
	pcl::PointIndices::Ptr out_of_range_points (new pcl::PointIndices);
	unsigned int i = 0;

	BOOST_FOREACH(const PoinT& pt, _cloud->points)
	{
		if(sqrt( (pt.x*pt.x) + (pt.y*pt.y) + (pt.z*pt.z) ) > 1.5 || isnan (pt.x) || isnan (pt.y) || isnan (pt.z) ||
				  isinf (pt.x) || isinf (pt.y) || isinf (pt.z) )
			out_of_range_points->indices.push_back(i);

		i++;

	}

	pcl::ExtractIndices<PoinT> extract;
	pcl::PointCloud<PoinT>::Ptr cloud (new pcl::PointCloud<PoinT>);

	// Perform the extraction of these points (indices).
	extract.setInputCloud(_cloud);
	extract.setIndices(out_of_range_points);
	extract.setNegative (true);
	extract.filter (*cloud);


	// Prepare plane segmentation.
	pcl::SACSegmentation<PoinT> seg;
	pcl::PointIndices::Ptr inliers (new pcl::PointIndices);
	pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients);

	pcl::PointCloud<PoinT>::Ptr cloud_plane; // This door is opened elsewhere.

	pcl::PointCloud<PoinT>::Ptr cloud_f (new pcl::PointCloud<PoinT> ());

	seg.setOptimizeCoefficients (true);
	seg.setModelType (pcl::SACMODEL_PLANE);
	seg.setMethodType (pcl::SAC_RANSAC);
	seg.setMaxIterations (1000);
	seg.setDistanceThreshold (0.02);

	// Remove the planes.
	i = 0;

	int nr_points =  (int) cloud->points.size();
	tf::StampedTransform base_link_to_openni;
	
	try
	{
		tf_listener->waitForTransform("base_link", cloud->header.frame_id, ros::Time(0), ros::Duration(1));
		//tf_listener->transformPoint("base_link", plane_normal, _plane_normal);
		tf_listener->lookupTransform("base_link", cloud->header.frame_id, ros::Time(0), base_link_to_openni);
	}
	catch(tf::TransformException& ex)
	{
	  	ROS_INFO("COCKED UP POINT INFO! Why: %s", ex.what());
	}


	// We do this here so that we can put in an empty cluster, if we see no table in the first place.
	doro_msgs::ClusterArray __clusters;

	while (cloud->points.size () > 0.5 * nr_points)
	{
		seg.setInputCloud (cloud);
		seg.segment (*inliers, *coefficients);

		if (inliers->indices.size () == 0)
		{
		  //std::cout << "Could not estimate a planar model for the given dataset." << std::endl;
		  break;
		}

		// Extract the planar inliers from the input cloud
		extract.setInputCloud (cloud);
		extract.setIndices (inliers);
		extract.setNegative (false);
		extract.filter (*cloud_f);


		// Is this a parallel to ground plane? If yes, save it.
		tf::Vector3 plane_normal (coefficients->values[0], coefficients->values[1], coefficients->values[2]);
		tf::Vector3 _plane_normal = base_link_to_openni*plane_normal;
		
		// What's the angle between this vector and the actual z axis? cos_inverse ( j component )...
		tf::Vector3 normal (_plane_normal.x(), _plane_normal.y(), _plane_normal.z());
		normal = normal.normalized();

		//std::cout<<"x: "<<normal.x()<<"\t";
		//std::cout<<"y: "<<normal.y()<<"\t";
		//std::cout<<"z: "<<normal.z()<<"\t";

		if(acos (normal.z()) < plane_tolerance)
		{
			cloud_plane = pcl::PointCloud<PoinT>::Ptr(new pcl::PointCloud<PoinT>);
			*cloud_plane = *cloud_f;
		}


		extract.setNegative (true);
		extract.filter (*cloud_f);
		*cloud = *cloud_f;
	}

	if(!cloud_plane)
	{
		ROS_INFO("No table or table-like object could be seen. Can't extract...");
		//clusters_pub.publish(__clusters);
		//sleep(1);
		return;
	}

	//ROS_INFO("Table seen.");
	//table_cloud_pub.publish(cloud_plane);

    //////////////////////////////////////////////////////////////////////
    /**
     * COMPUTE THE CENTROID OF THE PLANE AND PUBLISH IT.
     */
    //////////////////////////////////////////////////////////////////////
    Eigen::Vector4f plane_cen;

    // REMOVE COMMENTS WITH REAL ROBOT!!!
    pcl::compute3DCentroid(*cloud_plane, plane_cen);
    //std::cout<< plane_cen;

    tf::Vector3 plane_centroid (plane_cen[0], plane_cen[1], plane_cen[2]);
    tf::Vector3 _plane_centroid = base_link_to_openni*plane_centroid;
    
    geometry_msgs::PointStamped _plane_centroid_ROSMsg;
    _plane_centroid_ROSMsg.header.frame_id = "base_link";
    _plane_centroid_ROSMsg.header.stamp = stamp;
    _plane_centroid_ROSMsg.point.x = _plane_centroid.x();
    _plane_centroid_ROSMsg.point.y = _plane_centroid.y();
    _plane_centroid_ROSMsg.point.z = _plane_centroid.z();

    // Publish the centroid.
    table_position_pub.publish(_plane_centroid_ROSMsg);

    pcl::search::KdTree<PoinT>::Ptr tree (new pcl::search::KdTree<PoinT>);

   	if(cloud->points.size() == 0)
   	{
   		clusters_pub.publish(__clusters);
   		return;
   	}

   	tree->setInputCloud (cloud);

   	std::vector<pcl::PointIndices> cluster_indices;
   	pcl::EuclideanClusterExtraction<PoinT> ec;
   	ec.setClusterTolerance (0.02); // 2cm
   	ec.setMinClusterSize (20);
   	ec.setMaxClusterSize (25000);
   	ec.setSearchMethod (tree);
   	ec.setInputCloud (cloud);

   	ec.extract (cluster_indices);

   	//ROS_INFO("WIDTH: %d, HEIGHT: %d\n", _cloud->width, _cloud->height);

   	//ROS_INFO("GOOD TILL HERE!");

   	int j = 0;


   	for (std::vector<pcl::PointIndices>::const_iterator it = cluster_indices.begin (); it != cluster_indices.end (); ++it)
   	{
   		pcl::PointCloud<PoinT>::Ptr cloud_cluster (new pcl::PointCloud<PoinT>);

		cloud_cluster->header.frame_id = cloud->header.frame_id;

   		long int color_r, color_g, color_b;
   		uint8_t mean_r, mean_g, mean_b;

   		for (std::vector<int>::const_iterator pit = it->indices.begin (); pit != it->indices.end (); pit++)
   		{
   			cloud_cluster->points.push_back (cloud->points[*pit]);
   			/* ***************** */
   			/* COLOR COMPUTATION */
   			/* ***************** */

   			color_r += cloud->points[*pit].r;
   			color_g += cloud->points[*pit].g;
   			color_b += cloud->points[*pit].b;

   		}

   		geometry_msgs::Point a, b;
   		std::vector <double> cluster_dims = getClusterDimensions(cloud_cluster, a, b);

   		mean_r = (uint8_t) (color_r / cloud_cluster->points.size ());
   		mean_g = (uint8_t) (color_g / cloud_cluster->points.size ());
   		mean_b = (uint8_t) (color_b / cloud_cluster->points.size ());

   		cloud_cluster->width = cloud_cluster->points.size ();
   		cloud_cluster->height = 1;
   		cloud_cluster->is_dense = true;
   		cloud_cluster->header.frame_id = cloud->header.frame_id;

   		Eigen::Vector4f cluster_cen;

   		pcl::compute3DCentroid(*cloud_cluster, cluster_cen);

   		tf::Vector3 cluster_centroid (cluster_cen[0], cluster_cen[1], cluster_cen[2]);
   		tf::Vector3 _cluster_centroid = base_link_to_openni*cluster_centroid;

   		geometry_msgs::PointStamped _cluster_centroid_ROSMsg;
   		_cluster_centroid_ROSMsg.header.frame_id = "base_link";
   		_cluster_centroid_ROSMsg.header.stamp = stamp;
   		_cluster_centroid_ROSMsg.point.x = _cluster_centroid.x();
  		_cluster_centroid_ROSMsg.point.y = _cluster_centroid.y();
   		_cluster_centroid_ROSMsg.point.z = _cluster_centroid.z();

   		if(DIST(cluster_centroid,plane_centroid) < 0.6 && _cluster_centroid.z() > _plane_centroid.z())
   		{
   			doro_msgs::Cluster __cluster;
   			__cluster.centroid = _cluster_centroid_ROSMsg;
   			// Push cluster dimentions. Viewed width, breadth and height
   			__cluster.cluster_size = cluster_dims;
   			__cluster.a = a;
   			__cluster.b = b;
   			// Push colors
   			__cluster.color.push_back(mean_r);
   			__cluster.color.push_back(mean_g);
   			__cluster.color.push_back(mean_b);
   			__clusters.clusters.push_back (__cluster);
   			j++;
   		}

   	}

   	clusters_pub.publish(__clusters);

   	/////////////// RUBBISH ENDS ////////////////

    //if(pcl_data)
    //	pcl_data.reset();

}
Пример #8
0
  /* Accepts a range of inverted tris. Refacets affected surface so that no tris
     are inverted. */
  MBErrorCode remove_inverted_tris(MBTag normal_tag, MBRange tris, const bool debug ) {
      
    MBErrorCode result;
    bool failures_occur = false;
    while(!tris.empty()) {

      /* Get a group of triangles to re-facet. They must be adjacent to each other
	 and in the same surface. */
      MBRange tris_to_refacet;
      tris_to_refacet.insert( tris.front() );
      MBRange surf_set;
      result = MBI()->get_adjacencies( tris_to_refacet, 4, false, surf_set );
      assert(MB_SUCCESS == result);
      if(1 != surf_set.size()) {
	std::cout << "remove_inverted_tris: tri is in " << surf_set.size() 
                  << " surfaces" << std::endl;
        return MB_FAILURE;
      }

      // get all tris in the surface
      MBRange surf_tris;
      result = MBI()->get_entities_by_type( surf_set.front(), MBTRI, surf_tris );
      assert(MB_SUCCESS == result); 

      /* Find all of the adjacent inverted triangles of the same surface. Keep
	 searching until a search returns no new triangles. */
      bool search_again = true;
      while(search_again) {

        // Here edges are being created. Remember to delete them. Outside of this
        // function. Skinning gets bogged down if unused MBEdges (from other 
        // surfaces) accumulate.
        MBRange tri_edges;
        result = MBI()->get_adjacencies( tris_to_refacet, 1, true, tri_edges,
                                         MBInterface::UNION );
        assert(MB_SUCCESS == result);
        MBRange connected_tris;
        result = MBI()->get_adjacencies( tri_edges, 2, false, connected_tris, 
                                         MBInterface::UNION );
        assert(MB_SUCCESS == result);
        result = MBI()->delete_entities( tri_edges );
        assert(MB_SUCCESS == result);
        MBRange tris_to_refacet2 = intersect( tris_to_refacet, connected_tris );
        tris_to_refacet2 = intersect( tris_to_refacet, surf_tris );

        if(tris_to_refacet.size() == tris_to_refacet2.size()) search_again = false;
        tris_to_refacet.swap( tris_to_refacet2 );
      }

      // Remove the inverted tris that will be refaceted.
      tris = subtract( tris, tris_to_refacet );

        // do edges already exist?
	MBRange temp;
          result = MBI()->get_entities_by_type(0, MBEDGE, temp );
          assert(MB_SUCCESS == result);
          if(!temp.empty()) MBI()->list_entities( temp );
	  assert(temp.empty());


      // keep enlarging patch until we have tried to refacet the entire surface
      int counter=0;
      while(true) {
        // do edges already exist?
	temp.clear();
          result = MBI()->get_entities_by_type(0, MBEDGE, temp );
          assert(MB_SUCCESS == result);
          if(!temp.empty()) MBI()->list_entities( temp );
	  assert(temp.empty());


        counter++;
        // Only try enlarging each patch a few times
        if(48 == counter) {
          failures_occur = true;
	  if(debug) std::cout << "remove_inverted_tris: ear clipping failed, counter="
		              << counter << std::endl;
	  break;
        }
        // THIS PROVIDES A BAD EXIT. MUST FIX

        // get the edges of the patch of inverted tris
	MBRange tri_edges;
	result = MBI()->get_adjacencies( tris_to_refacet, 1, true, tri_edges,
                                         MBInterface::UNION );
	assert(MB_SUCCESS == result);

	// get all adjacent tris to the patch of inverted tris in the surface
	MBRange adj_tris;
	result = MBI()->get_adjacencies( tri_edges, 2, false, adj_tris, 
                                         MBInterface::UNION );
	assert(MB_SUCCESS == result);
        result = MBI()->delete_entities( tri_edges );
        assert(MB_SUCCESS == result);
	tris_to_refacet = intersect( surf_tris, adj_tris );
        if(tris_to_refacet.empty()) continue;
	//gen::print_triangles( tris_to_refacet );    
	
	// get an area-weighted normal of the adj_tris
	MBCartVect plane_normal(0,0,0);
	//for(unsigned int i=0; i<tris_to_refacet.size(); i++) {
	for(MBRange::iterator i=tris_to_refacet.begin(); i!=tris_to_refacet.end(); i++) {
	  MBCartVect norm;
	  result = MBI()->tag_get_data( normal_tag, &(*i), 1, &norm);
	  assert(MB_SUCCESS == result);
	  double area;
          result = gen::triangle_area( *i, area );
          assert(MB_SUCCESS == result);
	  if(debug) std::cout << "norm=" << norm << " area=" << area << std::endl;
	  //plane_normal += norm*area;
	  plane_normal += norm;
	}
	plane_normal.normalize();

        // do edges already exist?
	temp.clear();
          result = MBI()->get_entities_by_type(0, MBEDGE, temp );
          assert(MB_SUCCESS == result);
          if(!temp.empty()) MBI()->list_entities( temp );
	  assert(temp.empty());
 
	// skin the tris
	MBRange unordered_edges;
	//MBSkinner tool(MBI());
	//result = tool.find_skin( tris_to_refacet, 1, unordered_edges, false );
	result = gen::find_skin( tris_to_refacet, 1, unordered_edges, false );
	assert(MB_SUCCESS == result);
        if(unordered_edges.empty()) {
        // do edges already exist?
          MBRange temp;
          result = MBI()->get_entities_by_type(0, MBEDGE, temp );
          assert(MB_SUCCESS == result);
          if(!temp.empty()) MBI()->list_entities( temp );
	  assert(temp.empty());
          continue;
        }

	//std::cout << "remove_inverted_tris: surf_id=" 
	//  << gen::geom_id_by_handle(surf_set.front()) << std::endl;
	//result = MBI()->list_entities( tris_to_refacet );
	//assert(MB_SUCCESS == result);

	// assemble into a polygon
	std::vector<MBEntityHandle> polygon_of_verts;
	result = arc::order_verts_by_edge( unordered_edges, polygon_of_verts );
	if(debug) gen::print_loop( polygon_of_verts ); 
	//assert(MB_SUCCESS == result);
	if(MB_SUCCESS != result) {
	  if(debug) std::cout << "remove_inverted_tris: couldn't order polygon by edge" << std::endl;
	  return MB_FAILURE;
	}

        // remember to remove edges
        result = MBI()->delete_entities( unordered_edges );
        assert(MB_SUCCESS == result);

	// remove the duplicate endpt
	polygon_of_verts.pop_back();

	// the polygon should have at least 3 verts
	if(3 > polygon_of_verts.size()) {
	  if(debug) std::cout << "remove_inverted_tris: polygon has too few points" << std::endl;
	  return MB_FAILURE;
	}

	// orient the polygon with the triangles (could be backwards)
	// get the first adjacent tri
	MBEntityHandle edge[2] = { polygon_of_verts[0], polygon_of_verts[1] };
	MBRange one_tri;
	result = MBI()->get_adjacencies( edge, 2, 2, false, one_tri );
	assert(MB_SUCCESS == result);
	one_tri = intersect( tris_to_refacet, one_tri );
	assert(1 == one_tri.size());
	const MBEntityHandle *conn;
	int n_conn;
	result = MBI()->get_connectivity( one_tri.front(), conn, n_conn );
	assert(MB_SUCCESS == result);
	assert(3 == n_conn);
	if( (edge[0]==conn[1] && edge[1]==conn[0]) ||
	    (edge[0]==conn[2] && edge[1]==conn[1]) ||
	    (edge[0]==conn[0] && edge[1]==conn[2]) ) {
	  reverse( polygon_of_verts.begin(), polygon_of_verts.end() );
	  if(debug) std::cout << "remove_inverted_tris: polygon reversed" << std::endl;
	}

	/* facet the polygon. Returns MB_FAILURE if it fails to facet the polygon. */
	MBRange new_tris;
	result = gen::ear_clip_polygon( polygon_of_verts, plane_normal, new_tris );

        // break if the refaceting is successful
	if(MB_SUCCESS == result) {
          // summarize tri area
          for(MBRange::iterator i=new_tris.begin(); i!=new_tris.end(); i++) {
            double area;
            result = gen::triangle_area( *i, area );
            assert(MB_SUCCESS == result);
	    if(debug) std::cout << "  new tri area=" << area << std::endl;
          }

  	  // check the new normals
	  std::vector<MBCartVect> new_normals;
	  result = gen::triangle_normals( new_tris, new_normals );
	  if(MB_SUCCESS != result) return result;

	  // test the new triangles
	  std::vector<int> inverted_tri_indices;
	  std::vector<MBCartVect> normals ( new_normals.size(), plane_normal );
	  result = zip::test_normals( normals, new_normals, inverted_tri_indices );
	  assert(MB_SUCCESS == result);
	  if(inverted_tri_indices.empty()) {
  	    // remove the tris that were re-faceted
            tris = subtract( tris, tris_to_refacet );
  	    result = MBI()->remove_entities( surf_set.front(), tris_to_refacet );
	    assert(MB_SUCCESS == result);
	    result = MBI()->delete_entities( tris_to_refacet ); 
	    assert(MB_SUCCESS == result);

	    // add the new tris to the surf set
	    result = MBI()->add_entities( surf_set.front(), new_tris );
	    assert(MB_SUCCESS == result);

            // put the new normals on the new tris
            result = gen::save_normals( new_tris, normal_tag );
            assert(MB_SUCCESS == result);
	    if(debug) std::cout << "remove_inverted_tris: success fixing a patch" << std::endl;
            break;
          }
        }

        // remember to delete the tris that were created from the failed ear clipping
        else {
          result = MBI()->delete_entities( new_tris );
          assert(MB_SUCCESS == result);
        }

        // If the entire surface could not be ear clipped, give up
        if (tris_to_refacet.size() == surf_tris.size()) {
	  if(debug) std::cout << "remove_inverted_tris: ear clipping entire surface failed"
			    << std::endl;
	  return MB_FAILURE;
	}

      } // loop until the entire surface has attempted to be refaceted
    }   // loop over each patch of inverted tris
   
    if(failures_occur) {
      if(debug) std::cout << "remove_inverted_facets: at least one failure occured" << std::endl;
      return MB_FAILURE;
    } else {
      return MB_SUCCESS;
    }
  }
Пример #9
0
void callback_planes(const vision_msgs::PlanesConstPtr& planes)
{
    if (!_correct_lateral) {
        _avg_plane_dist = 0;
        _accumulated_plane_dists = 0;
        return;
    }

    //find wall that is perpendicular to the robots direction
    double max_dot = 0.0;
    int ortho_plane = 0;
    for(int i = 0; i < planes->planes.size(); ++i)
    {
        const vision_msgs::Plane& plane = planes->planes[i];
        if (plane.is_ground_plane) continue;

        Eigen::Vector3f plane_normal(plane.plane_coefficients[0],
                                     plane.plane_coefficients[1],
                                     plane.plane_coefficients[2]);
        Eigen::Vector3f forward(1,0,0);

        double dotprod = std::abs(forward.dot(plane_normal));
        if (dotprod > max_dot) {
            max_dot = dotprod;
            ortho_plane = i;
        }
    }

    if (max_dot > 0.9) {
        _front_plane = planes->planes[ortho_plane];
        _see_front_plane = true;

        _iteration_lateral++;

        double x_diff = get_x_diff();
        ROS_ERROR("x diff = %.3lf",x_diff);

        if (!std::isnan(x_diff)) {
            _avg_plane_dist += x_diff;
            _accumulated_plane_dists++;
        }

        if (_iteration_lateral >= _max_iterations()) {

            if (_accumulated_plane_dists > 0) {

                double avg_diff = _avg_plane_dist / (double)_accumulated_plane_dists;

                ROS_ERROR("Attempt to correct position based on wall");

                if (std::abs(avg_diff) < 0.1) {
                    double dx = cos(_theta);
                    double dy = sin(_theta);

                    double new_x = _x + avg_diff*dx;
                    double new_y = _y + avg_diff*dy;

                    ROS_ERROR("corrected position (%.3lf,%.3lf) -> (%.3lf,%.3lf)", _x, _y, new_x, new_y);

                    _x = new_x;
                    _y = new_y;
                }
            }

            _iteration_lateral = 0;
            _avg_plane_dist = 0;
            _accumulated_plane_dists = 0;
            _correct_lateral = false;
        }
    }
    else {
        _see_front_plane = false;

        if (_correct_lateral) _correct_lateral = false;
    }
}