00001 #include "filter_jump_edge_alg.h" 00002 00003 FilterJumpEdgeAlgorithm::FilterJumpEdgeAlgorithm(void) 00004 { 00005 } 00006 00007 FilterJumpEdgeAlgorithm::~FilterJumpEdgeAlgorithm(void) 00008 { 00009 } 00010 00011 void FilterJumpEdgeAlgorithm::config_update(Config& new_cfg, uint32_t level) 00012 { 00013 this->lock(); 00014 00015 // save the current configuration 00016 this->config_=new_cfg; 00017 00018 this->unlock(); 00019 } 00020 00021 // FilterJumpEdgeAlgorithm Public API 00022 00023 bool FilterJumpEdgeAlgorithm::apply_jump_edge_filter(const sensor_msgs::PointCloud2::ConstPtr& msg) 00024 { 00025 // Convert from msg to algorithm based inputs 00026 //pcl::fromROSMsg(*msg, filtered_pc_); 00027 //pcl::fromROSMsg(*msg, residual_pc_); 00028 filtered_pc_ = *msg; 00029 residual_pc_ = *msg; 00030 00031 // Jump Edge depth image 00032 residual_img_.header = msg->header; 00033 residual_img_.height = msg->height; 00034 residual_img_.width = msg->width; 00035 residual_img_.encoding = sensor_msgs::image_encodings::MONO8; 00036 residual_img_.step = msg->width; 00037 residual_img_.data.resize(msg->width * msg->height); 00038 00039 // [JUMP EDGE FILTER ALGORITHM] 00040 00041 // focal distance 00042 float fd = sx_/(0.5*msg->width/u0_); 00043 // X and Y pixel scale 00044 float mx = (0.5*msg->width/u0_); 00045 float my = (0.5*msg->height/u0_); 00046 // Angle of incidence in X coords 00047 float apex_X = atan(mx/fd); 00048 // Angle of incidence in Y coords 00049 float apex_Y = atan(my/fd); 00050 // Angle of incidence in the diagonal XY. 00051 // apex = 2.0*atan(0.5*n_cc/sx_)/n_cc; 00052 float apex_XY = atan((1/sqrt(pow(mx,2)+pow(my,2)))/fd); 00053 00054 //pcl::PointCloud<pcl::PointXYZRGB>::iterator fil_it = filtered_pc_.begin(); 00055 //pcl::PointCloud<pcl::PointXYZRGB>::iterator res_it = residual_pc_.begin(); 00056 00057 for (unsigned int rr=0; rr<msg->height; ++rr){ 00058 //for (unsigned int cc=0; cc<msg->width; ++cc, ++fil_it, ++res_it){ 00059 for (unsigned int cc=0; cc<msg->width; ++cc){ 00060 int idx0 = rr*msg->width + cc; 00061 //residual_img_.data[idx0] = 0.0; // Initialize image to black 00062 //residual_img_.data[idx0] = fil_it->r; // Initialize image to previous input pcl image 00063 float *fil_step = (float*)&filtered_pc_.data[idx0 * filtered_pc_.point_step]; 00064 float *res_step = (float*)&residual_pc_.data[idx0 * residual_pc_.point_step]; 00065 residual_img_.data[idx0] = 255*fil_step[3]/50000; // Initialize image to previous input pcl image 00066 00067 // Bounding Box Threshold 00068 // std::cout << std::endl << " z_e: " << this->z_e; 00069 // if ( x_ < this->x_s || y_ < this->y_s || z_ < this->z_s || x_ > this->x_e || y_ > this->y_e || z_ > this->z_e) 00070 // nstep[0] = nstep[1] = nstep[2] = nstep[3] = std::numeric_limits<float>::quiet_NaN (); 00071 00072 //if (rr==0 || rr == msg->height-1 || cc == 0 || cc == msg->width-1 || fil_it->z == 0.0){ 00073 if (rr==0 || rr == msg->height-1 || cc == 0 || cc == msg->width-1 || fil_step[2] == 0.0){ 00074 //fil_it->z = std::numeric_limits<float>::quiet_NaN (); 00075 fil_step[2] = std::numeric_limits<float>::quiet_NaN (); 00076 residual_img_.data[idx0] = 0.0; // Initialize image to black 00077 filtered_pc_.is_dense = false; 00078 continue; 00079 } 00080 00081 Eigen::Vector3f Va; 00082 //Va(0) = fil_it->z*(cc - u0_)/sx_; 00083 //Va(1) = fil_it->z*(rr - v0_)/sy_; 00084 //Va(2) = fil_it->z; 00085 Va(0) = fil_step[2]*(cc - u0_)/sx_; 00086 Va(1) = fil_step[2]*(rr - v0_)/sy_; 00087 Va(2) = fil_step[2]; 00088 int kk=0; 00089 Eigen::ArrayXf neigh_ang(8); 00090 00091 for (int ii=-1; ii < 2; ii++){ 00092 for (int jj=-1; jj < 2; jj++){ 00093 if (ii==0 && jj==0) 00094 continue; 00095 int tr = rr + ii; 00096 int tc = cc + jj; 00097 int idx1 = tr*msg->width + tc; 00098 float *pstep1 = (float*)&msg->data[idx1 * msg->point_step]; 00099 float tmp_value1 = pstep1[2]; 00100 Eigen::Vector3f Vb; 00101 Vb(0) = tmp_value1*(tc - u0_)/sx_; 00102 Vb(1) = tmp_value1*(tr - v0_)/sy_; 00103 Vb(2) = tmp_value1; 00104 float modVectNeigh = Vb.norm(); 00105 float modVectDif = (Va-Vb).norm(); 00106 if (ii==jj) { 00107 neigh_ang(kk) = 180.0/M_PI * asin(sin(apex_XY)*(modVectNeigh)/modVectDif); 00108 } else if (ii==0) { 00109 neigh_ang(kk) = 180.0/M_PI * asin(sin(apex_Y)*(modVectNeigh)/modVectDif); 00110 } else if (jj==0) { 00111 neigh_ang(kk) = 180.0/M_PI * asin(sin(apex_X)*(modVectNeigh)/modVectDif); 00112 } else { 00113 neigh_ang(kk) = 180.0/M_PI * asin(sin(apex_XY)*(modVectNeigh)/modVectDif); 00114 } 00115 kk++; 00116 } 00117 } 00118 // IF it is a flying point 00119 if (neigh_ang.minCoeff() < ang_thr_){ 00120 residual_img_.data[idx0] = 0.0; 00121 //fil_it->z = std::numeric_limits<float>::quiet_NaN (); 00122 //fil_it->rgb = 0.0; 00123 fil_step[2] = std::numeric_limits<float>::quiet_NaN (); 00124 fil_step[3] = 0.0; 00125 filtered_pc_.is_dense = false; 00126 // ELSE 00127 } else { 00128 // residual_img_.data[idx0] = 255.0; 00129 //res_it->z = std::numeric_limits<float>::quiet_NaN (); 00130 res_step[2] = std::numeric_limits<float>::quiet_NaN (); 00131 residual_pc_.is_dense = false; 00132 } 00133 } 00134 } 00135 00136 return true; 00137 } 00138 00139 sensor_msgs::PointCloud2* FilterJumpEdgeAlgorithm::get_filtered_pc(void) 00140 { 00141 return &filtered_pc_; 00142 } 00143 00144 sensor_msgs::PointCloud2* FilterJumpEdgeAlgorithm::get_residual_pc(void) 00145 { 00146 return &residual_pc_; 00147 } 00148 00149 sensor_msgs::Image* FilterJumpEdgeAlgorithm::get_residual_img(void) 00150 { 00151 return &residual_img_; 00152 } 00153 00154 void FilterJumpEdgeAlgorithm::set_sx(double sx) 00155 { 00156 sx_ = sx; 00157 } 00158 00159 void FilterJumpEdgeAlgorithm::set_sy(double sy) 00160 { 00161 sy_ = sy; 00162 } 00163 00164 void FilterJumpEdgeAlgorithm::set_u0(double u0) 00165 { 00166 u0_ = u0; 00167 } 00168 00169 void FilterJumpEdgeAlgorithm::set_v0(double v0) 00170 { 00171 v0_ = v0; 00172 } 00173 00174 void FilterJumpEdgeAlgorithm::set_skw(double skw) 00175 { 00176 skw_ = skw; 00177 } 00178 00179 void FilterJumpEdgeAlgorithm::set_ang_thr(double ang_thr) 00180 { 00181 ang_thr_ = ang_thr; 00182 } 00183