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 }); }
/*! 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; }
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; }
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 }); }
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; }
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 } ); }
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; }
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; }
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); }