Point Cloud Library (PCL)  1.11.1-dev
elch.hpp
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Point Cloud Library (PCL) - www.pointclouds.org
5  * Copyright (c) 2011, Willow Garage, Inc.
6  * Copyright (c) 2012-, Open Perception, Inc.
7  *
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  *
14  * * Redistributions of source code must retain the above copyright
15  * notice, this list of conditions and the following disclaimer.
16  * * Redistributions in binary form must reproduce the above
17  * copyright notice, this list of conditions and the following
18  * disclaimer in the documentation and/or other materials provided
19  * with the distribution.
20  * * Neither the name of the copyright holder(s) nor the names of its
21  * contributors may be used to endorse or promote products derived
22  * from this software without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35  * POSSIBILITY OF SUCH DAMAGE.
36  *
37  * $Id$
38  *
39  */
40 
41 #ifndef PCL_REGISTRATION_IMPL_ELCH_H_
42 #define PCL_REGISTRATION_IMPL_ELCH_H_
43 
44 #include <pcl/common/transforms.h>
45 #include <pcl/registration/boost.h>
46 #include <pcl/registration/registration.h>
47 
48 #include <algorithm>
49 #include <list>
50 #include <tuple>
51 
52 //////////////////////////////////////////////////////////////////////////////////////////////
53 template <typename PointT>
54 void
56 {
57  std::list<int> crossings, branches;
58  crossings.push_back(static_cast<int>(loop_start_));
59  crossings.push_back(static_cast<int>(loop_end_));
60  weights[loop_start_] = 0;
61  weights[loop_end_] = 1;
62 
63  int* p = new int[num_vertices(g)];
64  int* p_min = new int[num_vertices(g)];
65  double* d = new double[num_vertices(g)];
66  double* d_min = new double[num_vertices(g)];
67  bool do_swap = false;
68  std::list<int>::iterator start_min, end_min;
69 
70  // process all junctions
71  while (!crossings.empty()) {
72  double dist = -1;
73  // find shortest crossing for all vertices on the loop
74  for (auto crossings_it = crossings.begin(); crossings_it != crossings.end();) {
75  dijkstra_shortest_paths(g,
76  *crossings_it,
77  predecessor_map(boost::make_iterator_property_map(
78  p, get(boost::vertex_index, g)))
79  .distance_map(boost::make_iterator_property_map(
80  d, get(boost::vertex_index, g))));
81 
82  auto end_it = crossings_it;
83  end_it++;
84  // find shortest crossing for one vertex
85  for (; end_it != crossings.end(); end_it++) {
86  if (*end_it != p[*end_it] && (dist < 0 || d[*end_it] < dist)) {
87  dist = d[*end_it];
88  start_min = crossings_it;
89  end_min = end_it;
90  do_swap = true;
91  }
92  }
93  if (do_swap) {
94  std::swap(p, p_min);
95  std::swap(d, d_min);
96  do_swap = false;
97  }
98  // vertex starts a branch
99  if (dist < 0) {
100  branches.push_back(static_cast<int>(*crossings_it));
101  crossings_it = crossings.erase(crossings_it);
102  }
103  else
104  crossings_it++;
105  }
106 
107  if (dist > -1) {
108  remove_edge(*end_min, p_min[*end_min], g);
109  for (int i = p_min[*end_min]; i != *start_min; i = p_min[i]) {
110  // even right with weights[*start_min] > weights[*end_min]! (math works)
111  weights[i] = weights[*start_min] + (weights[*end_min] - weights[*start_min]) *
112  d_min[i] / d_min[*end_min];
113  remove_edge(i, p_min[i], g);
114  if (degree(i, g) > 0) {
115  crossings.push_back(i);
116  }
117  }
118 
119  if (degree(*start_min, g) == 0)
120  crossings.erase(start_min);
121 
122  if (degree(*end_min, g) == 0)
123  crossings.erase(end_min);
124  }
125  }
126 
127  delete[] p;
128  delete[] p_min;
129  delete[] d;
130  delete[] d_min;
131 
132  boost::graph_traits<LOAGraph>::adjacency_iterator adjacent_it, adjacent_it_end;
133 
134  // error propagation
135  while (!branches.empty()) {
136  int s = branches.front();
137  branches.pop_front();
138 
139  for (std::tie(adjacent_it, adjacent_it_end) = adjacent_vertices(s, g);
140  adjacent_it != adjacent_it_end;
141  ++adjacent_it) {
142  weights[*adjacent_it] = weights[s];
143  if (degree(*adjacent_it, g) > 1)
144  branches.push_back(static_cast<int>(*adjacent_it));
145  }
146  clear_vertex(s, g);
147  }
148 }
149 
150 //////////////////////////////////////////////////////////////////////////////////////////////
151 template <typename PointT>
152 bool
154 {
155  /*if (!PCLBase<PointT>::initCompute ())
156  {
157  PCL_ERROR ("[pcl::registration:ELCH::initCompute] Init failed.\n");
158  return (false);
159  }*/ //TODO
160 
161  if (loop_end_ == 0) {
162  PCL_ERROR("[pcl::registration::ELCH::initCompute] no end of loop defined!\n");
163  deinitCompute();
164  return (false);
165  }
166 
167  // compute transformation if it's not given
168  if (compute_loop_) {
169  PointCloudPtr meta_start(new PointCloud);
170  PointCloudPtr meta_end(new PointCloud);
171  *meta_start = *(*loop_graph_)[loop_start_].cloud;
172  *meta_end = *(*loop_graph_)[loop_end_].cloud;
173 
174  typename boost::graph_traits<LoopGraph>::adjacency_iterator si, si_end;
175  for (std::tie(si, si_end) = adjacent_vertices(loop_start_, *loop_graph_);
176  si != si_end;
177  si++)
178  *meta_start += *(*loop_graph_)[*si].cloud;
179 
180  for (std::tie(si, si_end) = adjacent_vertices(loop_end_, *loop_graph_);
181  si != si_end;
182  si++)
183  *meta_end += *(*loop_graph_)[*si].cloud;
184 
185  // TODO use real pose instead of centroid
186  // Eigen::Vector4f pose_start;
187  // pcl::compute3DCentroid (*(*loop_graph_)[loop_start_].cloud, pose_start);
188 
189  // Eigen::Vector4f pose_end;
190  // pcl::compute3DCentroid (*(*loop_graph_)[loop_end_].cloud, pose_end);
191 
192  PointCloudPtr tmp(new PointCloud);
193  // Eigen::Vector4f diff = pose_start - pose_end;
194  // Eigen::Translation3f translation (diff.head (3));
195  // Eigen::Affine3f trans = translation * Eigen::Quaternionf::Identity ();
196  // pcl::transformPointCloud (*(*loop_graph_)[loop_end_].cloud, *tmp, trans);
197 
198  reg_->setInputTarget(meta_start);
199 
200  reg_->setInputSource(meta_end);
201 
202  reg_->align(*tmp);
203 
204  loop_transform_ = reg_->getFinalTransformation();
205  // TODO hack
206  // loop_transform_ *= trans.matrix ();
207  }
208 
209  return (true);
210 }
211 
212 //////////////////////////////////////////////////////////////////////////////////////////////
213 template <typename PointT>
214 void
216 {
217  if (!initCompute()) {
218  return;
219  }
220 
221  LOAGraph grb[4];
222 
223  typename boost::graph_traits<LoopGraph>::edge_iterator edge_it, edge_it_end;
224  for (std::tie(edge_it, edge_it_end) = edges(*loop_graph_); edge_it != edge_it_end;
225  edge_it++) {
226  for (auto& j : grb)
227  add_edge(source(*edge_it, *loop_graph_),
228  target(*edge_it, *loop_graph_),
229  1,
230  j); // TODO add variance
231  }
232 
233  double* weights[4];
234  for (int i = 0; i < 4; i++) {
235  weights[i] = new double[num_vertices(*loop_graph_)];
236  loopOptimizerAlgorithm(grb[i], weights[i]);
237  }
238 
239  // TODO use pose
240  // Eigen::Vector4f cend;
241  // pcl::compute3DCentroid (*((*loop_graph_)[loop_end_].cloud), cend);
242  // Eigen::Translation3f tend (cend.head (3));
243  // Eigen::Affine3f aend (tend);
244  // Eigen::Affine3f aendI = aend.inverse ();
245 
246  // TODO iterate ovr loop_graph_
247  // typename boost::graph_traits<LoopGraph>::vertex_iterator vertex_it, vertex_it_end;
248  // for (std::tie (vertex_it, vertex_it_end) = vertices (*loop_graph_); vertex_it !=
249  // vertex_it_end; vertex_it++)
250  for (std::size_t i = 0; i < num_vertices(*loop_graph_); i++) {
251  Eigen::Vector3f t2;
252  t2[0] = loop_transform_(0, 3) * static_cast<float>(weights[0][i]);
253  t2[1] = loop_transform_(1, 3) * static_cast<float>(weights[1][i]);
254  t2[2] = loop_transform_(2, 3) * static_cast<float>(weights[2][i]);
255 
256  Eigen::Affine3f bl(loop_transform_);
257  Eigen::Quaternionf q(bl.rotation());
258  Eigen::Quaternionf q2;
259  q2 = Eigen::Quaternionf::Identity().slerp(static_cast<float>(weights[3][i]), q);
260 
261  // TODO use rotation from branch start
262  Eigen::Translation3f t3(t2);
263  Eigen::Affine3f a(t3 * q2);
264  // a = aend * a * aendI;
265 
266  pcl::transformPointCloud(*(*loop_graph_)[i].cloud, *(*loop_graph_)[i].cloud, a);
267  (*loop_graph_)[i].transform = a;
268  }
269 
270  add_edge(loop_start_, loop_end_, *loop_graph_);
271 
272  deinitCompute();
273 }
274 
275 #endif // PCL_REGISTRATION_IMPL_ELCH_H_
pcl::PCLBase::PointCloudPtr
typename PointCloud::Ptr PointCloudPtr
Definition: pcl_base.h:73
pcl::registration::ELCH::compute
void compute()
Computes new poses for all point clouds by closing the loop between start and end point cloud.
Definition: elch.hpp:215
pcl::PointCloud
PointCloud represents the base class in PCL for storing collections of 3D points.
Definition: distances.h:55
pcl::transformPointCloud
void transformPointCloud(const pcl::PointCloud< PointT > &cloud_in, pcl::PointCloud< PointT > &cloud_out, const Eigen::Matrix< Scalar, 4, 4 > &transform, bool copy_all_fields)
Apply a rigid transform defined by a 4x4 matrix.
Definition: transforms.hpp:221
pcl::registration::ELCH
ELCH (Explicit Loop Closing Heuristic) class
Definition: elch.h:60
pcl::registration::ELCH::initCompute
virtual bool initCompute()
This method should get called before starting the actual computation.
Definition: elch.hpp:153