예제 #1
0
void Box::rotate(double angle, glm::vec3 const& point) {
    glm::mat4x4 translate_origin{
        1, 0, 0, 0,
        0, 1, 0, 0,
        0, 0, 1, 0,
        -point.x, -point.y, -point.z, 1
    };

    double rad_angle = angle * M_PI / 180;
    glm::mat4x4 rotate{
        std::cos(rad_angle), std::sin(rad_angle), -std::sin(rad_angle), 0,
        -std::sin(rad_angle), std::cos(rad_angle), std::sin(rad_angle), 0,
        std::sin(rad_angle), -std::sin(rad_angle), std::cos(rad_angle), 0,
        0, 0, 0, 1
    };

    glm::mat4x4 translate_back{
        1, 0, 0, 0,
        0, 1, 0, 0,
        0, 0, 1, 0,
        point.x, point.y, point.z, 1
    };

    glm::mat4x4 trans_matrix = translate_back * rotate * translate_origin;

    transformation_matrix(transformation_matrix() * trans_matrix);

    // Transform min/max back to cartesian coordinates
    glm::vec4 h_min = trans_matrix * glm::vec4(min(), 1);
    glm::vec4 h_max = trans_matrix * glm::vec4(max(), 1);
    min({ h_min.x / h_min.w, h_min.y / h_min.w, h_min.z / h_min.w });
    max({ h_max.x / h_max.w, h_max.y / h_max.w, h_max.z / h_max.w });
}
예제 #2
0
 /*!
   Sets the brush to have a matrix and translation in its
   transformation
   \param p translation value for brush transformation
   \param m matrix value for brush transformation
  */
 PainterBrush&
 transformation(const vec2 &p, const float2x2 &m)
 {
   transformation_translate(p);
   transformation_matrix(m);
   return *this;
 }
예제 #3
0
void Sphere::rotate(double angle, glm::vec3 const& point) {
    glm::mat4x4 translate_origin{
        1, 0, 0, 0,
        0, 1, 0, 0,
        0, 0, 1, 0,
        -point.x, -point.y, -point.z, 1
    };

    double rad_angle = angle * M_PI / 180;
    glm::mat4x4 rotate{
        std::cos(rad_angle), std::sin(rad_angle), -std::sin(rad_angle), 0,
        -std::sin(rad_angle), std::cos(rad_angle), std::sin(rad_angle), 0,
        std::sin(rad_angle), -std::sin(rad_angle), std::cos(rad_angle), 0,
        0, 0, 0, 1
    };

    glm::mat4x4 translate_back{
        1, 0, 0, 0,
        0, 1, 0, 0,
        0, 0, 1, 0,
        point.x, point.y, point.z, 1
    };

    glm::mat4x4 trans_mat = translate_back * rotate * translate_origin;

    transformation_matrix(transformation_matrix() * trans_mat);

    // Transform center back to cartesian coordinates
    glm::vec4 h_center = trans_mat * glm::vec4(center(), 1);
    center(
        glm::vec3{
            h_center.x / h_center.w,
            h_center.y / h_center.w,
            h_center.z / h_center.w
        }
    );

    // std::cout << trans_mat[0][0] << " " << trans_mat[1][0] << " "
    //     << trans_mat[2][0] << " " << trans_mat[3][0] << std::endl;
    // std::cout << trans_mat[0][1] << " " << trans_mat[1][1] << " "
    //     << trans_mat[2][1] << " " << trans_mat[3][1] << std::endl;
    // std::cout << trans_mat[0][2] << " " << trans_mat[1][2] << " "
    //     << trans_mat[2][2] << " " << trans_mat[3][2] << std::endl;
    // std::cout << trans_mat[0][3] << " " << trans_mat[1][3] << " "
    //     << trans_mat[2][3] << " " << trans_mat[3][3] << std::endl;
}
예제 #4
0
void Box::translate(glm::vec3 const& distance) {
    glm::mat4x4 trans_mat{
        1, 0, 0, 0,
        0, 1, 0, 0,
        0, 0, 1, 0,
        distance.x, distance.y, distance.z, 1
    };

    // Multiply transformation matrix with min/max (in homogeneous coordinates)
    glm::vec4 h_min = trans_mat * glm::vec4(min(), 1);
    glm::vec4 h_max = trans_mat * glm::vec4(max(), 1);

    // Set new transformation matrix
    transformation_matrix(transformation_matrix() * trans_mat);

    // Set new min/max (in cartesian coordinates)
    min({ h_min.x / h_min.w, h_min.y / h_min.w, h_min.z / h_min.w });
    max({ h_max.x / h_max.w, h_max.y / h_max.w, h_max.z / h_max.w });
}
예제 #5
0
void Box::scale(double scale_factor) {
    // The center of the box is offset by the origin by the minimum plus
    // half of the distance between minimum and maximum
    glm::vec3 center_offset{
        min().x + (max().x - min().x)/2,
        min().y + (max().y - min().y)/2,
        min().z + (max().z - min().z)/2
    };

    // Translate box to origin so that its center is in the origin
    glm::mat4x4 translate_origin{
        1, 0, 0, 0,
        0, 1, 0, 0,
        0, 0, 1, 0,
        -center_offset.x, -center_offset.y, -center_offset.z, 1
    };

    // Scaling the box in the center
    glm::mat4x4 scale{
        scale_factor, 0, 0, 0,
        0, scale_factor, 0, 0,
        0, 0, scale_factor, 0,
        0, 0, 0, 1
    };

    // Translating back again
    glm::mat4x4 translate_back{
        1, 0, 0, 0,
        0, 1, 0, 0,
        0, 0, 1, 0,
        center_offset.x, center_offset.y, center_offset.z, 1
    };

    glm::mat4x4 trans_matrix = translate_back * scale * translate_origin;

    transformation_matrix(transformation_matrix() * trans_matrix);

    glm::vec4 h_min = trans_matrix * glm::vec4(min(), 1);
    glm::vec4 h_max = trans_matrix * glm::vec4(max(), 1);
    min(glm::vec3{ h_min.x / h_min.w, h_min.y / h_min.w, h_min.z / h_min.w });
    max(glm::vec3{ h_max.x / h_max.w, h_max.y / h_max.w, h_max.z / h_max.w });
}
sensor_msgs::PointCloud2 TrajectoryScans2PointcloudAlgNode::laser_scan_to_point_cloud(const sensor_msgs::LaserScan& LScan, const geometry_msgs::Pose& pose) 
{
  sensor_msgs::PointCloud2 pcloud;
  sensor_msgs::PointCloud2 transformed_pcloud;
  
  laser_projector_.projectLaser(LScan, pcloud, LScan.range_max - 1e-6);
    
  Matrix4f T_pose = transformation_matrix(pose.position.x, pose.position.y, pose.position.z, tf::getYaw(pose.orientation));
  
  pcl_ros::transformPointCloud(T_pose * T_laser_frame_, pcloud, transformed_pcloud);

  return transformed_pcloud;
}
예제 #7
0
void Sphere::translate(glm::vec3 const& distance) {
    glm::mat4x4 trans_mat{
        1, 0, 0, 0,
        0, 1, 0, 0,
        0, 0, 1, 0,
        distance.x, distance.y, distance.z, 1
    };

    // Multiply transformation matrix with center (in homogeneous coordinates)
    glm::vec4 h_center = trans_mat * glm::vec4(center(), 1);

    // Set new transformation matrix
    transformation_matrix(transformation_matrix() * trans_mat);

    // Set new center (in cartesian coordinates)
    center(
        glm::vec3{
            h_center.x / h_center.w,
            h_center.y / h_center.w,
            h_center.z / h_center.w
        }
    );
}
예제 #8
0
파일: shape.cpp 프로젝트: basisbit/neogfx
	void shape::paint(graphics_context& aGraphicsContext) const
	{
		if (frame_count() == 0)
			return;
		auto tm = transformation_matrix();
		auto m = map();
		for (auto& vertex : m)
			vertex = tm * vertex;
		if (current_frame().texture() != boost::none)
		{
			if (current_frame().texture_rect() == boost::none)
				aGraphicsContext.draw_texture(texture_map{ {m[0][0], m[0][1]}, {m[1][0], m[1][1]}, {m[2][0], m[2][1]}, {m[3][0], m[3][1]} }, *current_frame().texture());
			else
				aGraphicsContext.draw_texture(texture_map{ {m[0][0], m[0][1]}, {m[1][0], m[1][1]}, {m[2][0], m[2][1]}, {m[3][0], m[3][1]} }, *current_frame().texture(), *current_frame().texture_rect());
		}
		else if (current_frame().colour() != boost::none)
		{
			aGraphicsContext.fill_shape(position() - origin(), m, *current_frame().colour());
		}
	}
TrajectoryScans2PointcloudAlgNode::TrajectoryScans2PointcloudAlgNode(void) :
  algorithm_base::IriBaseAlgorithm<TrajectoryScans2PointcloudAlgorithm>()
{
  //init class attributes if necessary
  emptyPointCloud_ = true;
  new_trajectory_ = false;

  public_node_handle_.param<bool>("publish_redundant", publish_redundant_, true);
  double d[4];
  public_node_handle_.param<double>("dx_base_2_laser", d[0], 0.57);
  public_node_handle_.param<double>("dy_base_2_laser", d[1], 0.0);
  public_node_handle_.param<double>("dz_base_2_laser", d[2], 0.145);
  public_node_handle_.param<double>("dth_base_2_laser", d[3], 0.0);
  T_laser_frame_ = transformation_matrix(d[0], d[1], d[2], d[3]);

  ROS_DEBUG("TR 2 PC: Config updated");
 

  PointCloud_msg_.header.frame_id = "/map";
  //this->loop_rate_ = 2;//in [Hz]

  // [init publishers]
  this->laser_pointcloud_publisher_ = this->public_node_handle_.advertise<sensor_msgs::PointCloud2>("laser_pointcloud", 1);
  
  // [init subscribers]
  this->scan_subscriber_ = this->public_node_handle_.subscribe("scan", 10, &TrajectoryScans2PointcloudAlgNode::scan_callback, this);
  this->trajectory_subscriber_ = this->public_node_handle_.subscribe("trajectory", 1, &TrajectoryScans2PointcloudAlgNode::trajectory_callback, this);
  
  pthread_mutex_init(&this->last_trajectory_mutex_,NULL);

  // [init services]
  
  // [init clients]
  
  // [init action servers]
  
  // [init action clients]
}
template<template<class > class Distance, typename PointT, typename FeatureT> bool
GlobalNNPipelineROS<Distance,PointT,FeatureT>::classifyROS (classifier_srv_definitions::classify::Request & req, classifier_srv_definitions::classify::Response & response)
    {
        typename pcl::PointCloud<PointT>::Ptr cloud (new pcl::PointCloud<PointT>());
        pcl::fromROSMsg(req.cloud, *cloud);
        this->input_ = cloud;

        pcl::PointCloud<pcl::PointXYZRGB>::Ptr pClusteredPCl (new pcl::PointCloud<pcl::PointXYZRGB>());
        pcl::copyPointCloud(*cloud, *pClusteredPCl);

        //clear all data from previous visualization steps and publish empty markers/point cloud
        for (size_t i=0; i < markerArray_.markers.size(); i++)
        {
            markerArray_.markers[i].action = visualization_msgs::Marker::DELETE;
        }
        vis_pub_.publish( markerArray_ );
        sensor_msgs::PointCloud2 scenePc2;
        vis_pc_pub_.publish(scenePc2);
        markerArray_.markers.clear();

        for(size_t cluster_id=0; cluster_id < req.clusters_indices.size(); cluster_id++)
        {
          std::vector<int> cluster_indices_int;
          Eigen::Vector4f centroid;
          Eigen::Matrix3f covariance_matrix;

          const float r = std::rand() % 255;
          const float g = std::rand() % 255;
          const float b = std::rand() % 255;

          this->indices_.resize(req.clusters_indices[cluster_id].data.size());
          for(size_t kk=0; kk < req.clusters_indices[cluster_id].data.size(); kk++)
          {
                this->indices_[kk] = static_cast<int>(req.clusters_indices[cluster_id].data[kk]);
                pClusteredPCl->at(req.clusters_indices[cluster_id].data[kk]).r = 0.8*r;
                pClusteredPCl->at(req.clusters_indices[cluster_id].data[kk]).g = 0.8*g;
                pClusteredPCl->at(req.clusters_indices[cluster_id].data[kk]).b = 0.8*b;
          }

          this->classify ();

          std::cout << "for cluster " << cluster_id << " with size " << cluster_indices_int.size() << ", I have following hypotheses: " << std::endl;

          object_perception_msgs::classification class_tmp;
          for(size_t kk=0; kk < this->categories_.size(); kk++)
          {
            std::cout << this->categories_[kk] << " with confidence " << this->confidences_[kk] << std::endl;
            std_msgs::String str_tmp;
            str_tmp.data = this->categories_[kk];
            class_tmp.class_type.push_back(str_tmp);
            class_tmp.confidence.push_back( this->confidences_[kk] );
          }
          response.class_results.push_back(class_tmp);

          typename pcl::PointCloud<PointT>::Ptr pClusterPCl_transformed (new pcl::PointCloud<PointT>());
          pcl::computeMeanAndCovarianceMatrix(*this->input_, cluster_indices_int, covariance_matrix, centroid);
          Eigen::Matrix3f eigvects;
          Eigen::Vector3f eigvals;
          pcl::eigen33(covariance_matrix, eigvects,  eigvals);

          Eigen::Vector3f centroid_transformed = eigvects.transpose() * centroid.topRows(3);

          Eigen::Matrix4f transformation_matrix = Eigen::Matrix4f::Zero(4,4);
          transformation_matrix.block<3,3>(0,0) = eigvects.transpose();
          transformation_matrix.block<3,1>(0,3) = -centroid_transformed;
          transformation_matrix(3,3) = 1;

          pcl::transformPointCloud(*this->input_, cluster_indices_int, *pClusterPCl_transformed, transformation_matrix);

          //pcl::transformPointCloud(*frame_, cluster_indices_int, *frame_eigencoordinates_, eigvects);
          PointT min_pt, max_pt;
          pcl::getMinMax3D(*pClusterPCl_transformed, min_pt, max_pt);
          std::cout << "Elongations along eigenvectors: " << max_pt.x - min_pt.x << ", " << max_pt.y - min_pt.y
                    << ", " << max_pt.z - min_pt.z << std::endl;
          geometry_msgs::Point32 centroid_ros;
          centroid_ros.x = centroid[0];
          centroid_ros.y = centroid[1];
          centroid_ros.z = centroid[2];
          response.centroid.push_back(centroid_ros);

          // calculating the bounding box of the cluster
          Eigen::Vector4f min;
          Eigen::Vector4f max;
          pcl::getMinMax3D (*this->input_, cluster_indices_int, min, max);

          object_perception_msgs::BBox bbox;
          geometry_msgs::Point32 pt;
          pt.x = min[0]; pt.y = min[1]; pt.z = min[2]; bbox.point.push_back(pt);
          pt.x = min[0]; pt.y = min[1]; pt.z = max[2]; bbox.point.push_back(pt);
          pt.x = min[0]; pt.y = max[1]; pt.z = min[2]; bbox.point.push_back(pt);
          pt.x = min[0]; pt.y = max[1]; pt.z = max[2]; bbox.point.push_back(pt);
          pt.x = max[0]; pt.y = min[1]; pt.z = min[2]; bbox.point.push_back(pt);
          pt.x = max[0]; pt.y = min[1]; pt.z = max[2]; bbox.point.push_back(pt);
          pt.x = max[0]; pt.y = max[1]; pt.z = min[2]; bbox.point.push_back(pt);
          pt.x = max[0]; pt.y = max[1]; pt.z = max[2]; bbox.point.push_back(pt);
          response.bbox.push_back(bbox);

          // getting the point cloud of the cluster
          typename pcl::PointCloud<PointT>::Ptr cluster (new pcl::PointCloud<PointT>);
          pcl::copyPointCloud(*this->input_, cluster_indices_int, *cluster);

          sensor_msgs::PointCloud2  pc2;
          pcl::toROSMsg (*cluster, pc2);
          response.cloud.push_back(pc2);

          // visualize the result as ROS topic
            visualization_msgs::Marker marker;
            marker.header.frame_id = camera_frame_;
            marker.header.stamp = ros::Time::now();
            //marker.header.seq = ++marker_seq_;
            marker.ns = "object_classification";
            marker.id = cluster_id;
            marker.type = visualization_msgs::Marker::TEXT_VIEW_FACING;
            marker.action = visualization_msgs::Marker::ADD;
            marker.pose.position.x = centroid_ros.x;
            marker.pose.position.y = centroid_ros.y - 0.1;
            marker.pose.position.z = centroid_ros.z - 0.1;
            marker.pose.orientation.x = 0;
            marker.pose.orientation.y = 0;
            marker.pose.orientation.z = 0;
            marker.pose.orientation.w = 1.0;
            marker.scale.z = 0.1;
            marker.color.a = 1.0;
            marker.color.r = r/255.f;
            marker.color.g = g/255.f;
            marker.color.b = b/255.f;
            std::stringstream marker_text;
            marker_text.precision(2);
            marker_text << this->categories_[0] << this->confidences_[0];
            marker.text = marker_text.str();
            markerArray_.markers.push_back(marker);
        }

        pcl::toROSMsg (*pClusteredPCl, scenePc2);
        vis_pc_pub_.publish(scenePc2);
        vis_pub_.publish( markerArray_ );

        response.clusters_indices = req.clusters_indices;
        return true;
    }
예제 #11
0
파일: numerics.c 프로젝트: Leixushu/ISITEK
int update_face_numerics(int n_variables_old, int n_variables, int *variable_order_old, int *variable_order, int n_faces, struct FACE *face, int n_boundaries_old, struct BOUNDARY *boundary_old)
{
	int a, b, f, g, h, i, j, v;

	// lists of old face boundaries
	int **face_n_boundaries_old = allocate_integer_matrix(NULL,n_faces,n_variables);
	exit_if_false(face_n_boundaries_old != NULL,"allocating face_n_boundaries_old");
	for(i = 0; i < n_faces; i ++) for(j = 0; j < n_variables; j ++) face_n_boundaries_old[i][j] = 0;

	int ***face_boundary_old = allocate_integer_tensor(NULL,n_faces,n_variables,MAX_FACE_N_BOUNDARIES);
	exit_if_false(face_boundary_old != NULL,"allocating face_boundary_old");

	for(b = 0; b < n_boundaries_old; b ++)
	{
		for(i = 0; i < boundary_old[b].n_faces; i ++)
		{
			v = boundary_old[b].variable;
			f = boundary_old[b].face[i] - &face[0];
			face_boundary_old[f][v][face_n_boundaries_old[f][v]++] = b;
		}
	}

	// order and numbers of integration points and bases
	int max_variable_order = 0, max_variable_order_old = 0;
	for(v = 0; v < n_variables; v ++) max_variable_order = MAX(max_variable_order,variable_order[v]);
	for(v = 0; v < n_variables_old; v ++) max_variable_order_old = MAX(max_variable_order_old,variable_order_old[v]);

	int n_gauss = ORDER_TO_N_GAUSS(max_variable_order), n_hammer = ORDER_TO_N_HAMMER(max_variable_order);
	int n_points[MAX_FACE_N_BORDERS], sum_n_points[MAX_FACE_N_BORDERS+1];

	int *n_basis = (int *)malloc(n_variables * sizeof(int)), max_n_basis = ORDER_TO_N_BASIS(max_variable_order);
	exit_if_false(n_basis != NULL,"allocating n_basis");
	for(v = 0; v < n_variables; v ++) n_basis[v] = ORDER_TO_N_BASIS(variable_order[v]);

	// truth values for updating the interpolation on a face
	int *update = (int *)malloc(n_variables * sizeof(int)), max_update = max_variable_order != max_variable_order_old, any_update;
	exit_if_false(update != NULL,"allocating update");

	// transformation
	double **R = allocate_double_matrix(NULL,2,2), det_R, **inv_R = allocate_double_matrix(NULL,2,2);
	exit_if_false(R != NULL,"allocating R");
	exit_if_false(inv_R != NULL,"allocating inv_R");
	double **T = allocate_double_matrix(NULL,max_n_basis,max_n_basis);
	exit_if_false(T != NULL,"allocating T");

	// centre
	double **centre = allocate_double_matrix(NULL,2,1);
	exit_if_false(centre != NULL,"allocating centre");

	// differentials
	int condition[2], none[2] = {0,0};

	// integration locations in cartesian (x) and tranformed (y) coordinates
	double **x, **y;
	double **x_adj[MAX_FACE_N_BORDERS], ***y_adj;
	exit_if_false(y = allocate_double_matrix(NULL,2,n_gauss),"allocating y");
	exit_if_false(y_adj = allocate_double_tensor(NULL,MAX_FACE_N_BORDERS,2,n_hammer*(MAX_ELEMENT_N_FACES-2)),"allocating y_adj");

	// adjacent elements and boundaries to the face
	int n_adj, n_bnd;
	struct ELEMENT **adj;
	struct BOUNDARY **bnd;

	// interpolation problem sizes
	int n_adj_bases = MAX_FACE_N_BORDERS*max_n_basis; // number of adjacent bases
	int n_int_terms = MAX_FACE_N_BORDERS*max_n_basis + MAX_FACE_N_BOUNDARIES; // number of terms from which to interpolate
	int n_int_bases = MAX_FACE_N_BORDERS*max_n_basis + MAX_FACE_N_BOUNDARIES*max_variable_order; // number of interpolant bases

	// face basis taylor indices
	int *face_taylor = (int *)malloc(n_int_bases * sizeof(int));
	exit_if_false(face_taylor != NULL,"allocating face_taylor");

	// temporary matrices
	int ldp, lds, ldq;
	ldp = lds = ldq = MAX_FACE_N_BORDERS*(MAX_ELEMENT_N_FACES-2)*n_hammer;
	int sizep = n_adj_bases*ldp;
	double **P = allocate_double_matrix(NULL,n_adj_bases,ldp);
	double **S = allocate_double_matrix(NULL,n_adj_bases,lds);
	double **Q = allocate_double_matrix(NULL,n_int_bases,ldp);

	int lda, ldb;
	lda = ldb = n_int_bases;
	double **A = allocate_double_matrix(NULL,n_int_bases,n_int_bases);
	double **B = allocate_double_matrix(NULL,n_int_bases,n_int_bases);

	int ldf, ldd;
	ldf = ldd = n_gauss;
	double **F = allocate_double_matrix(NULL,n_int_bases,n_gauss);
	double ***D = allocate_double_tensor(NULL,max_n_basis,n_int_terms,n_gauss);

	int incd = n_int_terms*n_gauss, incq;

	exit_if_false(P != NULL && S != NULL && Q != NULL && A != NULL && B != NULL && F != NULL && D != NULL,"allocating working matrices");

	// blas 
	char trans[2] = "NT";
	int i_one = 1;
	double d_one = 1.0, d_zero = 0.0;

	// lapack
	int info, *pivot = (int *)malloc(n_int_bases * sizeof(int));
	exit_if_false(pivot != NULL,"allocating pivot");

	int updated = 0;

	for(f = 0; f < n_faces; f ++)
	{
		// see if face interpolation needs updating
		any_update = 0;
		for(v = 0; v < n_variables; v ++)
		{
			update[v] = 0;
			if(v >= n_variables_old) update[v] = 1;
			else if(variable_order[v] != variable_order_old[v]) update[v] = 1;
			else if(face[f].n_boundaries[v] != face_n_boundaries_old[f][v]) update[v] = 1;
			else for(i = 0; i < face[f].n_boundaries[v]; i ++)
				for(j = 0; j < 2; j ++)
					if(face[f].boundary[v][i]->condition[j] != boundary_old[face_boundary_old[f][v][i]].condition[j])
						update[v] = 1;
			any_update += update[v];
		}
		if(!any_update) continue;

		// allocate matrices
		exit_if_false(face[f].Q = allocate_face_q(&face[f],n_variables,n_basis,n_gauss),"allocating face Q");

		// rotation to face coordinates
		R[0][0] = + face[f].normal[0]; R[0][1] = + face[f].normal[1];
		R[1][0] = - face[f].normal[1]; R[1][1] = + face[f].normal[0];
		det_R = R[0][0]*R[1][1] - R[0][1]*R[1][0];
		inv_R[0][0] = + R[1][1]/det_R; inv_R[0][1] = - R[0][1]/det_R;
		inv_R[1][0] = - R[1][0]/det_R; inv_R[1][1] = + R[0][0]/det_R;
		transformation_matrix(max_variable_order,T,inv_R);

		// face integration locations
		x = face[f].X;
		for(g = 0; g < n_gauss; g ++)
		{
			for(i = 0; i < 2; i ++)
			{
				y[i][g] = face[f].centre[i];
				for(j = 0; j < 2; j ++) y[i][g] += R[i][j]*(x[j][g] - face[f].centre[j]);
			}
		}

		// numbers of element integration locations
		for(a = 0; a < face[f].n_borders; a ++) n_points[a] = n_hammer*(face[f].border[a]->n_faces-2);
		sum_n_points[0] = 0;
		for(a = 0; a < face[f].n_borders; a ++) sum_n_points[a+1] = sum_n_points[a] + n_points[a];

		// adjacent element integration locations
		for(a = 0; a < face[f].n_borders; a ++)
		{
			x_adj[a] = face[f].border[a]->X;
			for(h = 0; h < n_points[a]; h ++)
			{
				for(i = 0; i < 2; i ++)
				{
					y_adj[a][i][h] = face[f].centre[i];
					for(j = 0; j < 2; j ++) y_adj[a][i][h] += R[i][j]*(x_adj[a][j][h] - face[f].centre[j]);
				}
			}
		}

		// for all variables
		for(v = 0; v < n_variables; v ++)
		{
			if(!max_update && !update[v]) continue;

			n_adj = face[f].n_borders;
			adj = face[f].border;
			n_bnd = face[f].n_boundaries[v];
			bnd = face[f].boundary[v];

			n_adj_bases = n_adj*n_basis[v];
			n_int_terms = n_adj_bases + n_bnd;

			// face basis indices
			n_int_bases = 0;
			for(i = 0; i < n_adj*variable_order[v] + n_bnd; i ++)
				for(j = 0; j < n_adj*variable_order[v] + n_bnd; j ++)
					if(i + n_adj*j < n_adj*variable_order[v] + n_bnd && j < variable_order[v])
						face_taylor[n_int_bases ++] = powers_taylor[i][j];
			exit_if_false(n_int_bases == n_adj_bases + n_bnd*variable_order[v],"mismatched number of interpolation unknowns");

			// element bases at the integration locations
			for(i = 0; i < n_adj*n_basis[v]; i ++) for(j = 0; j < sum_n_points[n_adj]; j ++) P[i][j] = 0.0;
			for(a = 0; a < n_adj; a ++)
				for(i = 0; i < n_basis[v]; i ++)
					basis(n_points[a],&P[i+a*n_basis[v]][sum_n_points[a]],x_adj[a],adj[a]->centre,adj[a]->size,i,none);

			// face bases at the integration locations
			for(a = 0; a < n_adj; a ++)
				for(i = 0; i < n_int_bases; i ++)
					basis(n_points[a],&Q[i][sum_n_points[a]],y_adj[a],face[f].centre,face[f].size,face_taylor[i],none);

			// centre of face in form which can be passed to basis
			for(i = 0; i < 2; i ++) centre[i][0] = face[f].centre[i];

			// integration matrix
			dcopy_(&sizep,P[0],&i_one,S[0],&i_one);
			for(a = 0; a < n_adj; a ++)
				for(i = 0; i < n_points[a]; i ++)
					dscal_(&n_basis[v],&adj[a]->W[i],&S[a*n_basis[v]][i+sum_n_points[a]],&lds);

			// weak interpolation system
			dgemm_(&trans[1],&trans[0],&n_adj_bases,&n_int_bases,&sum_n_points[n_adj],&d_one,S[0],&lds,Q[0],&ldq,&d_zero,A[0],&lda);

			// weak interpolation rhs
			dgemm_(&trans[1],&trans[0],&n_adj_bases,&n_adj_bases,&sum_n_points[n_adj],&d_one,S[0],&lds,P[0],&ldp,&d_zero,B[0],&ldb);

			// boundary conditions
			for(b = 0; b < n_bnd; b ++)
			{
				condition[0] = bnd[b]->condition[0];
				for(i = 0; i < variable_order[v]; i ++)
				{
					condition[1] = bnd[b]->condition[1] + i;
					for(j = 0; j < n_int_bases; j ++)
						basis(1,&A[j][i+n_adj_bases],centre,face[f].centre,face[f].size,face_taylor[j],condition);
				}

				for(i = 0; i < variable_order[v]; i ++) for(j = 0; j < n_int_terms; j ++) B[j][i+n_adj_bases] = 0.0;
				for(i = 0; i < n_adj_bases; i ++) B[n_adj_bases+b][i] = 0.0;
				B[b+n_adj_bases][b*variable_order[v]+n_adj_bases] = 1.0;
			}

			// solve interpolation problem
			dgesv_(&n_int_bases,&n_int_terms,A[0],&lda,pivot,B[0],&ldb,&info);

			// interpolate values to the face integration locations
			for(i = 0; i < n_basis[v]; i ++)
			{
				for(j = 0; j < n_int_bases; j ++) basis(n_gauss,F[j],y,face[f].centre,face[f].size,face_taylor[j],taylor_powers[i]);
				dgemm_(&trans[0],&trans[0],&n_gauss,&n_int_terms,&n_int_bases,&d_one,F[0],&ldf,B[0],&ldb,&d_zero,D[i][0],&ldd);
			}

			// transform from face to cartesian coordinates
			incq = n_int_terms*n_gauss;
			for(i = 0; i < n_int_terms; i ++)
				for(j = 0; j < n_gauss; j ++)
					dgemv_(&trans[1],&n_basis[v],&n_basis[v],&d_one,T[0],&max_n_basis,&D[0][i][j],&incd,&d_zero,&face[f].Q[v][0][i][j],&incq);

			updated ++;
		}
	}

	// clean up
	destroy_matrix((void *)face_n_boundaries_old);
	destroy_tensor((void *)face_boundary_old);

	free(n_basis);
	free(update);

	destroy_matrix((void *)R);
	destroy_matrix((void *)inv_R);
	destroy_matrix((void *)T);

	destroy_matrix((void *)centre);
	destroy_matrix((void *)y);
	destroy_tensor((void *)y_adj);

	free(face_taylor);

	destroy_matrix((void *)P);
	destroy_matrix((void *)Q);
	destroy_matrix((void *)S);
	destroy_matrix((void *)A);
	destroy_matrix((void *)B);
	destroy_matrix((void *)F);
	destroy_tensor((void *)D);

	free(pivot);

	return updated;
}
예제 #12
0
int
main (int argc,
      char* argv[])
{
  // The point clouds we will be using
  PointCloudT::Ptr cloud_in (new PointCloudT);  // Original point cloud
  PointCloudT::Ptr cloud_tr (new PointCloudT);  // Transformed point cloud
  PointCloudT::Ptr cloud_icp (new PointCloudT);  // ICP output point cloud

  // Checking program arguments
  if (argc < 2)
  {
    printf ("Usage :\n");
    printf ("\t\t%s file.ply number_of_ICP_iterations\n", argv[0]);
    PCL_ERROR ("Provide one ply file.\n");
    return (-1);
  }

  int iterations = 1;  // Default number of ICP iterations
  if (argc > 2)
  {
    // If the user passed the number of iteration as an argument
    iterations = atoi (argv[2]);
    if (iterations < 1)
    {
      PCL_ERROR ("Number of initial iterations must be >= 1\n");
      return (-1);
    }
  }

  pcl::console::TicToc time;
  time.tic ();
  if (pcl::io::loadPLYFile (argv[1], *cloud_in) < 0)
  {
    PCL_ERROR ("Error loading cloud %s.\n", argv[1]);
    return (-1);
  }
  std::cout << "\nLoaded file " << argv[1] << " (" << cloud_in->size () << " points) in " << time.toc () << " ms\n" << std::endl;

  // Defining a rotation matrix and translation vector
  Eigen::Matrix4d transformation_matrix = Eigen::Matrix4d::Identity ();

  // A rotation matrix (see https://en.wikipedia.org/wiki/Rotation_matrix)
  double theta = M_PI / 8;  // The angle of rotation in radians
  transformation_matrix (0, 0) = cos (theta);
  transformation_matrix (0, 1) = -sin (theta);
  transformation_matrix (1, 0) = sin (theta);
  transformation_matrix (1, 1) = cos (theta);

  // A translation on Z axis (0.4 meters)
  transformation_matrix (2, 3) = 0.4;

  // Display in terminal the transformation matrix
  std::cout << "Applying this rigid transformation to: cloud_in -> cloud_icp" << std::endl;
  print4x4Matrix (transformation_matrix);

  // Executing the transformation
  pcl::transformPointCloud (*cloud_in, *cloud_icp, transformation_matrix);
  *cloud_tr = *cloud_icp;  // We backup cloud_icp into cloud_tr for later use

  // The Iterative Closest Point algorithm
  time.tic ();
  pcl::IterativeClosestPoint<PointT, PointT> icp;
  icp.setMaximumIterations (iterations);
  icp.setInputSource (cloud_icp);
  icp.setInputTarget (cloud_in);
  icp.align (*cloud_icp);
  icp.setMaximumIterations (1);  // We set this variable to 1 for the next time we will call .align () function
  std::cout << "Applied " << iterations << " ICP iteration(s) in " << time.toc () << " ms" << std::endl;

  if (icp.hasConverged ())
  {
    std::cout << "\nICP has converged, score is " << icp.getFitnessScore () << std::endl;
    std::cout << "\nICP transformation " << iterations << " : cloud_icp -> cloud_in" << std::endl;
    transformation_matrix = icp.getFinalTransformation ().cast<double>();
    print4x4Matrix (transformation_matrix);
  }
  else
  {
    PCL_ERROR ("\nICP has not converged.\n");
    return (-1);
  }

  // Visualization
  pcl::visualization::PCLVisualizer viewer ("ICP demo");
  // Create two vertically separated viewports
  int v1 (0);
  int v2 (1);
  viewer.createViewPort (0.0, 0.0, 0.5, 1.0, v1);
  viewer.createViewPort (0.5, 0.0, 1.0, 1.0, v2);

  // The color we will be using
  float bckgr_gray_level = 0.0;  // Black
  float txt_gray_lvl = 1.0 - bckgr_gray_level;

  // Original point cloud is white
  pcl::visualization::PointCloudColorHandlerCustom<PointT> cloud_in_color_h (cloud_in, (int) 255 * txt_gray_lvl, (int) 255 * txt_gray_lvl,
                                                                             (int) 255 * txt_gray_lvl);
  viewer.addPointCloud (cloud_in, cloud_in_color_h, "cloud_in_v1", v1);
  viewer.addPointCloud (cloud_in, cloud_in_color_h, "cloud_in_v2", v2);

  // Transformed point cloud is green
  pcl::visualization::PointCloudColorHandlerCustom<PointT> cloud_tr_color_h (cloud_tr, 20, 180, 20);
  viewer.addPointCloud (cloud_tr, cloud_tr_color_h, "cloud_tr_v1", v1);

  // ICP aligned point cloud is red
  pcl::visualization::PointCloudColorHandlerCustom<PointT> cloud_icp_color_h (cloud_icp, 180, 20, 20);
  viewer.addPointCloud (cloud_icp, cloud_icp_color_h, "cloud_icp_v2", v2);

  // Adding text descriptions in each viewport
  viewer.addText ("White: Original point cloud\nGreen: Matrix transformed point cloud", 10, 15, 16, txt_gray_lvl, txt_gray_lvl, txt_gray_lvl, "icp_info_1", v1);
  viewer.addText ("White: Original point cloud\nRed: ICP aligned point cloud", 10, 15, 16, txt_gray_lvl, txt_gray_lvl, txt_gray_lvl, "icp_info_2", v2);

  std::stringstream ss;
  ss << iterations;
  std::string iterations_cnt = "ICP iterations = " + ss.str ();
  viewer.addText (iterations_cnt, 10, 60, 16, txt_gray_lvl, txt_gray_lvl, txt_gray_lvl, "iterations_cnt", v2);

  // Set background color
  viewer.setBackgroundColor (bckgr_gray_level, bckgr_gray_level, bckgr_gray_level, v1);
  viewer.setBackgroundColor (bckgr_gray_level, bckgr_gray_level, bckgr_gray_level, v2);

  // Set camera position and orientation
  viewer.setCameraPosition (-3.68332, 2.94092, 5.71266, 0.289847, 0.921947, -0.256907, 0);
  viewer.setSize (1280, 1024);  // Visualiser window size

  // Register keyboard callback :
  viewer.registerKeyboardCallback (&keyboardEventOccurred, (void*) NULL);

  // Display the visualiser
  while (!viewer.wasStopped ())
  {
    viewer.spinOnce ();

    // The user pressed "space" :
    if (next_iteration)
    {
      // The Iterative Closest Point algorithm
      time.tic ();
      icp.align (*cloud_icp);
      std::cout << "Applied 1 ICP iteration in " << time.toc () << " ms" << std::endl;

      if (icp.hasConverged ())
      {
        printf ("\033[11A");  // Go up 11 lines in terminal output.
        printf ("\nICP has converged, score is %+.0e\n", icp.getFitnessScore ());
        std::cout << "\nICP transformation " << ++iterations << " : cloud_icp -> cloud_in" << std::endl;
        transformation_matrix *= icp.getFinalTransformation ().cast<double>();  // WARNING /!\ This is not accurate! For "educational" purpose only!
        print4x4Matrix (transformation_matrix);  // Print the transformation between original pose and current pose

        ss.str ("");
        ss << iterations;
        std::string iterations_cnt = "ICP iterations = " + ss.str ();
        viewer.updateText (iterations_cnt, 10, 60, 16, txt_gray_lvl, txt_gray_lvl, txt_gray_lvl, "iterations_cnt");
        viewer.updatePointCloud (cloud_icp, cloud_icp_color_h, "cloud_icp_v2");
      }
      else
      {
        PCL_ERROR ("\nICP has not converged.\n");
        return (-1);
      }
    }
    next_iteration = false;
  }
  return (0);
}