|
Point Cloud Library (PCL)
1.4.0
|
00001 /* 00002 * Software License Agreement (BSD License) 00003 * 00004 * Point Cloud Library (PCL) - www.pointclouds.org 00005 * Copyright (c) 2011, Willow Garage, Inc. 00006 * 00007 * All rights reserved. 00008 * 00009 * Redistribution and use in source and binary forms, with or without 00010 * modification, are permitted provided that the following conditions 00011 * are met: 00012 * 00013 * * Redistributions of source code must retain the above copyright 00014 * notice, this list of conditions and the following disclaimer. 00015 * * Redistributions in binary form must reproduce the above 00016 * copyright notice, this list of conditions and the following 00017 * disclaimer in the documentation and/or other materials provided 00018 * with the distribution. 00019 * * Neither the name of Willow Garage, Inc. nor the names of its 00020 * contributors may be used to endorse or promote products derived 00021 * from this software without specific prior written permission. 00022 * 00023 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00024 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00025 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00026 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00027 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00028 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00029 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00030 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00031 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00032 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00033 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00034 * POSSIBILITY OF SUCH DAMAGE. 00035 * 00036 * $Id: elch.hpp 3503 2011-12-12 06:07:28Z rusu $ 00037 * 00038 */ 00039 00040 #ifndef PCL_REGISTRATION_IMPL_ELCH_H_ 00041 #define PCL_REGISTRATION_IMPL_ELCH_H_ 00042 00043 #include <list> 00044 #include <algorithm> 00045 00046 #include <boost/graph/adjacency_list.hpp> 00047 #include <boost/graph/graph_traits.hpp> 00048 #include <boost/graph/dijkstra_shortest_paths.hpp> 00049 00050 #include <Eigen/Geometry> 00051 00052 #include <pcl/common/transforms.h> 00053 #include <pcl/registration/registration.h> 00054 00056 template <typename PointT> void 00057 pcl::registration::ELCH<PointT>::loopOptimizerAlgorithm (LOAGraph &g, double *weights) 00058 { 00059 std::list<int> crossings, branches; 00060 crossings.push_back (loop_start_); 00061 crossings.push_back (loop_end_); 00062 weights[loop_start_] = 0; 00063 weights[loop_end_] = 1; 00064 00065 int *p = new int[num_vertices (g)]; 00066 int *p_min = new int[num_vertices (g)]; 00067 double *d = new double[num_vertices (g)]; 00068 double *d_min = new double[num_vertices (g)]; 00069 double dist; 00070 bool do_swap = false; 00071 std::list<int>::iterator crossings_it, end_it, start_min, end_min; 00072 00073 // process all junctions 00074 while (!crossings.empty ()) 00075 { 00076 dist = -1; 00077 // find shortest crossing for all vertices on the loop 00078 for (crossings_it = crossings.begin (); crossings_it != crossings.end (); ) 00079 { 00080 dijkstra_shortest_paths (g, *crossings_it, boost::predecessor_map (p).distance_map (d)); 00081 end_it = crossings_it; 00082 end_it++; 00083 // find shortest crossing for one vertex 00084 for (; end_it != crossings.end (); end_it++) 00085 { 00086 if (*end_it != p[*end_it] && (dist < 0 || d[*end_it] < dist)) 00087 { 00088 dist = d[*end_it]; 00089 start_min = crossings_it; 00090 end_min = end_it; 00091 do_swap = true; 00092 } 00093 } 00094 if (do_swap) 00095 { 00096 std::swap (p, p_min); 00097 std::swap (d, d_min); 00098 do_swap = false; 00099 } 00100 // vertex starts a branch 00101 if (dist < 0) 00102 { 00103 branches.push_back (*crossings_it); 00104 crossings_it = crossings.erase (crossings_it); 00105 } 00106 else 00107 crossings_it++; 00108 } 00109 00110 if (dist > -1) 00111 { 00112 remove_edge (*end_min, p_min[*end_min], g); 00113 for (int i = p_min[*end_min]; i != *start_min; i = p_min[i]) 00114 { 00115 //even right with weights[*start_min] > weights[*end_min]! (math works) 00116 weights[i] = weights[*start_min] + (weights[*end_min] - weights[*start_min]) * d_min[i] / d_min[*end_min]; 00117 remove_edge (i, p_min[i], g); 00118 if (degree (i, g) > 0) 00119 { 00120 crossings.push_back (i); 00121 } 00122 } 00123 00124 if (degree (*start_min, g) == 0) 00125 crossings.erase (start_min); 00126 00127 if (degree (*end_min, g) == 0) 00128 crossings.erase (end_min); 00129 } 00130 } 00131 00132 delete[] p; 00133 delete[] p_min; 00134 delete[] d; 00135 delete[] d_min; 00136 00137 boost::graph_traits<LOAGraph>::adjacency_iterator adjacent_it, adjacent_it_end; 00138 int s; 00139 00140 // error propagation 00141 while (!branches.empty ()) 00142 { 00143 s = branches.front (); 00144 branches.pop_front (); 00145 00146 for (boost::tuples::tie (adjacent_it, adjacent_it_end) = adjacent_vertices (s, g); adjacent_it != adjacent_it_end; ++adjacent_it) 00147 { 00148 weights[*adjacent_it] = weights[s]; 00149 if (degree (*adjacent_it, g) > 1) 00150 branches.push_back (*adjacent_it); 00151 } 00152 clear_vertex (s, g); 00153 } 00154 } 00155 00157 template <typename PointT> bool 00158 pcl::registration::ELCH<PointT>::initCompute () 00159 { 00160 /*if (!PCLBase<PointT>::initCompute ()) 00161 { 00162 PCL_ERROR ("[pcl::registration:ELCH::initCompute] Init failed.\n"); 00163 return (false); 00164 }*/ //TODO 00165 00166 if (!loop_start_) 00167 { 00168 PCL_ERROR ("[pcl::registration::ELCH::initCompute] no start of loop defined is empty!\n"); 00169 deinitCompute (); 00170 return (false); 00171 } 00172 00173 if (!loop_end_) 00174 { 00175 PCL_ERROR ("[pcl::registration::ELCH::initCompute] no end of loop defined is empty!\n"); 00176 deinitCompute (); 00177 return (false); 00178 } 00179 00180 //compute transformation if it's not given 00181 if (compute_loop_) 00182 { 00183 PointCloudPtr meta_start (new PointCloud); 00184 PointCloudPtr meta_end (new PointCloud); 00185 *meta_start = *(*loop_graph_)[loop_start_].cloud; 00186 *meta_end = *(*loop_graph_)[loop_end_].cloud; 00187 00188 typename boost::graph_traits<LoopGraph>::adjacency_iterator si, si_end; 00189 for (boost::tuples::tie (si, si_end) = adjacent_vertices (loop_start_, *loop_graph_); si != si_end; si++) 00190 *meta_start += *(*loop_graph_)[*si].cloud; 00191 00192 for (boost::tuples::tie (si, si_end) = adjacent_vertices (loop_end_, *loop_graph_); si != si_end; si++) 00193 *meta_end += *(*loop_graph_)[*si].cloud; 00194 00195 //TODO use real pose instead of centroid 00196 //Eigen::Vector4f pose_start; 00197 //pcl::compute3DCentroid (*(*loop_graph_)[loop_start_].cloud, pose_start); 00198 00199 //Eigen::Vector4f pose_end; 00200 //pcl::compute3DCentroid (*(*loop_graph_)[loop_end_].cloud, pose_end); 00201 00202 PointCloudPtr tmp (new PointCloud); 00203 //Eigen::Vector4f diff = pose_start - pose_end; 00204 //Eigen::Translation3f translation (diff.head (3)); 00205 //Eigen::Affine3f trans = translation * Eigen::Quaternionf::Identity (); 00206 //pcl::transformPointCloud (*(*loop_graph_)[loop_end_].cloud, *tmp, trans); 00207 00208 reg_->setInputTarget (meta_start); 00209 00210 reg_->setInputCloud (meta_end); 00211 00212 reg_->align (*tmp); 00213 00214 loop_transform_ = reg_->getFinalTransformation (); 00215 //TODO hack 00216 //loop_transform_ *= trans.matrix (); 00217 00218 } 00219 00220 return (true); 00221 } 00222 00224 template <typename PointT> void 00225 pcl::registration::ELCH<PointT>::compute () 00226 { 00227 if (!initCompute ()) 00228 { 00229 return; 00230 } 00231 00232 LOAGraph grb[4]; 00233 00234 typename boost::graph_traits<LoopGraph>::edge_iterator edge_it, edge_it_end; 00235 for (boost::tuples::tie (edge_it, edge_it_end) = edges (*loop_graph_); edge_it != edge_it_end; edge_it++) 00236 { 00237 for (int j = 0; j < 4; j++) 00238 add_edge (source (*edge_it, *loop_graph_), target (*edge_it, *loop_graph_), 1, grb[j]); //TODO add variance 00239 } 00240 00241 double *weights[4]; 00242 for (int i = 0; i < 4; i++) 00243 { 00244 weights[i] = new double[num_vertices (*loop_graph_)]; 00245 loopOptimizerAlgorithm (grb[i], weights[i]); 00246 } 00247 00248 //TODO use pose 00249 //Eigen::Vector4f cend; 00250 //pcl::compute3DCentroid (*((*loop_graph_)[loop_end_].cloud), cend); 00251 //Eigen::Translation3f tend (cend.head (3)); 00252 //Eigen::Affine3f aend (tend); 00253 //Eigen::Affine3f aendI = aend.inverse (); 00254 00255 //TODO iterate ovr loop_graph_ 00256 //typename boost::graph_traits<LoopGraph>::vertex_iterator vertex_it, vertex_it_end; 00257 //for (boost::tuples::tie (vertex_it, vertex_it_end) = vertices (*loop_graph_); vertex_it != vertex_it_end; vertex_it++) 00258 for (size_t i = 0; i < num_vertices (*loop_graph_); i++) 00259 { 00260 Eigen::Vector3f t2; 00261 t2[0] = loop_transform_ (0, 3) * weights[0][i]; 00262 t2[1] = loop_transform_ (1, 3) * weights[1][i]; 00263 t2[2] = loop_transform_ (2, 3) * weights[2][i]; 00264 00265 Eigen::Affine3f bl (loop_transform_); 00266 Eigen::Quaternionf q (bl.rotation ()); 00267 Eigen::Quaternionf q2; 00268 q2 = Eigen::Quaternionf::Identity ().slerp (weights[3][i], q); 00269 00270 //TODO use rotation from branch start 00271 Eigen::Translation3f t3 (t2); 00272 Eigen::Affine3f a (t3 * q2); 00273 //a = aend * a * aendI; 00274 00275 pcl::transformPointCloud (*(*loop_graph_)[i].cloud, *(*loop_graph_)[i].cloud, a); 00276 } 00277 00278 add_edge (loop_start_, loop_end_, *loop_graph_); 00279 00280 deinitCompute (); 00281 } 00282 00283 #endif // PCL_REGISTRATION_IMPL_ELCH_H_
1.7.6.1