Point Cloud Library (PCL)  1.6.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
transforms.hpp
Go to the documentation of this file.
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2010, Willow Garage, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above
14  * copyright notice, this list of conditions and the following
15  * disclaimer in the documentation and/or other materials provided
16  * with the distribution.
17  * * Neither the name of Willow Garage, Inc. nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  *
35  */
36 
38 template <typename PointT> void
40  pcl::PointCloud<PointT> &cloud_out,
41  const Eigen::Affine3f &transform)
42 {
43  if (&cloud_in != &cloud_out)
44  {
45  // Note: could be replaced by cloud_out = cloud_in
46  cloud_out.header = cloud_in.header;
47  cloud_out.is_dense = cloud_in.is_dense;
48  cloud_out.width = cloud_in.width;
49  cloud_out.height = cloud_in.height;
50  cloud_out.points.reserve (cloud_out.points.size ());
51  cloud_out.points.assign (cloud_in.points.begin (), cloud_in.points.end ());
52  }
53 
54  if (cloud_in.is_dense)
55  {
56  // If the dataset is dense, simply transform it!
57  for (size_t i = 0; i < cloud_out.points.size (); ++i)
58  cloud_out.points[i].getVector3fMap () = transform *
59  cloud_in.points[i].getVector3fMap ();
60  }
61  else
62  {
63  // Dataset might contain NaNs and Infs, so check for them first,
64  // otherwise we get errors during the multiplication (?)
65  for (size_t i = 0; i < cloud_out.points.size (); ++i)
66  {
67  if (!pcl_isfinite (cloud_in.points[i].x) ||
68  !pcl_isfinite (cloud_in.points[i].y) ||
69  !pcl_isfinite (cloud_in.points[i].z))
70  continue;
71  cloud_out.points[i].getVector3fMap () = transform *
72  cloud_in.points[i].getVector3fMap ();
73  }
74  }
75 }
76 
78 template <typename PointT> void
80  const std::vector<int> &indices,
81  pcl::PointCloud<PointT> &cloud_out,
82  const Eigen::Affine3f &transform)
83 {
84  size_t npts = indices.size ();
85  // In order to transform the data, we need to remove NaNs
86  cloud_out.is_dense = cloud_in.is_dense;
87  cloud_out.header = cloud_in.header;
88  cloud_out.width = npts;
89  cloud_out.height = 1;
90  cloud_out.points.resize (npts);
91 
92  if (cloud_in.is_dense)
93  {
94  // If the dataset is dense, simply transform it!
95  for (size_t i = 0; i < npts; ++i)
96  {
97  // Copy fields first, then transform xyz data
98  cloud_out.points[i] = cloud_in.points[indices[i]];
99  cloud_out.points[i].getVector3fMap () = transform*cloud_out.points[i].getVector3fMap ();
100  }
101  }
102  else
103  {
104  // Dataset might contain NaNs and Infs, so check for them first,
105  // otherwise we get errors during the multiplication (?)
106  for (size_t i = 0; i < npts; ++i)
107  {
108  if (!pcl_isfinite (cloud_in.points[indices[i]].x) ||
109  !pcl_isfinite (cloud_in.points[indices[i]].y) ||
110  !pcl_isfinite (cloud_in.points[indices[i]].z))
111  continue;
112  cloud_out.points[i] = cloud_in.points[indices[i]];
113  cloud_out.points[i].getVector3fMap () = transform*cloud_out.points[i].getVector3fMap ();
114  }
115  }
116 }
117 
119 template <typename PointT> void
121  pcl::PointCloud<PointT> &cloud_out,
122  const Eigen::Affine3f &transform)
123 {
124  if (&cloud_in != &cloud_out)
125  {
126  // Note: could be replaced by cloud_out = cloud_in
127  cloud_out.header = cloud_in.header;
128  cloud_out.width = cloud_in.width;
129  cloud_out.height = cloud_in.height;
130  cloud_out.is_dense = cloud_in.is_dense;
131  cloud_out.points.reserve (cloud_out.points.size ());
132  cloud_out.points.assign (cloud_in.points.begin (), cloud_in.points.end ());
133  }
134 
135  // If the data is dense, we don't need to check for NaN
136  if (cloud_in.is_dense)
137  {
138  for (size_t i = 0; i < cloud_out.points.size (); ++i)
139  {
140  cloud_out.points[i].getVector3fMap() = transform *
141  cloud_in.points[i].getVector3fMap ();
142 
143  // Rotate normals
144  cloud_out.points[i].getNormalVector3fMap() = transform.rotation () *
145  cloud_in.points[i].getNormalVector3fMap ();
146  }
147  }
148  // Dataset might contain NaNs and Infs, so check for them first.
149  else
150  {
151  for (size_t i = 0; i < cloud_out.points.size (); ++i)
152  {
153  if (!pcl_isfinite (cloud_in.points[i].x) ||
154  !pcl_isfinite (cloud_in.points[i].y) ||
155  !pcl_isfinite (cloud_in.points[i].z))
156  continue;
157  cloud_out.points[i].getVector3fMap() = transform *
158  cloud_in.points[i].getVector3fMap ();
159 
160  // Rotate normals
161  cloud_out.points[i].getNormalVector3fMap() = transform.rotation () *
162  cloud_in.points[i].getNormalVector3fMap ();
163  }
164  }
165 }
166 
168 template <typename PointT> void
170  pcl::PointCloud<PointT> &cloud_out,
171  const Eigen::Matrix4f &transform)
172 {
173  if (&cloud_in != &cloud_out)
174  {
175  // Note: could be replaced by cloud_out = cloud_in
176  cloud_out.header = cloud_in.header;
177  cloud_out.width = cloud_in.width;
178  cloud_out.height = cloud_in.height;
179  cloud_out.is_dense = cloud_in.is_dense;
180  cloud_out.points.reserve (cloud_out.points.size ());
181  cloud_out.points.assign (cloud_in.points.begin (), cloud_in.points.end ());
182  }
183 
184  Eigen::Matrix3f rot = transform.block<3, 3> (0, 0);
185  Eigen::Vector3f trans = transform.block<3, 1> (0, 3);
186  // If the data is dense, we don't need to check for NaN
187  if (cloud_in.is_dense)
188  {
189  for (size_t i = 0; i < cloud_out.points.size (); ++i)
190  cloud_out.points[i].getVector3fMap () = rot *
191  cloud_in.points[i].getVector3fMap () + trans;
192  }
193  // Dataset might contain NaNs and Infs, so check for them first.
194  else
195  {
196  for (size_t i = 0; i < cloud_out.points.size (); ++i)
197  {
198  if (!pcl_isfinite (cloud_in.points[i].x) ||
199  !pcl_isfinite (cloud_in.points[i].y) ||
200  !pcl_isfinite (cloud_in.points[i].z))
201  continue;
202  cloud_out.points[i].getVector3fMap () = rot *
203  cloud_in.points[i].getVector3fMap () + trans;
204  }
205  }
206 }
207 
209 template <typename PointT> void
211  pcl::PointCloud<PointT> &cloud_out,
212  const Eigen::Matrix4f &transform)
213 {
214  if (&cloud_in != &cloud_out)
215  {
216  // Note: could be replaced by cloud_out = cloud_in
217  cloud_out.header = cloud_in.header;
218  cloud_out.width = cloud_in.width;
219  cloud_out.height = cloud_in.height;
220  cloud_out.is_dense = cloud_in.is_dense;
221  cloud_out.points.reserve (cloud_out.points.size ());
222  cloud_out.points.assign (cloud_in.points.begin (), cloud_in.points.end ());
223  }
224 
225  Eigen::Matrix3f rot = transform.block<3, 3> (0, 0);
226  Eigen::Vector3f trans = transform.block<3, 1> (0, 3);
227 
228  // If the data is dense, we don't need to check for NaN
229  if (cloud_in.is_dense)
230  {
231  for (size_t i = 0; i < cloud_out.points.size (); ++i)
232  {
233  cloud_out.points[i].getVector3fMap () = rot *
234  cloud_in.points[i].getVector3fMap () + trans;
235 
236  // Rotate normals
237  cloud_out.points[i].getNormalVector3fMap() = rot *
238  cloud_in.points[i].getNormalVector3fMap ();
239  }
240  }
241  // Dataset might contain NaNs and Infs, so check for them first.
242  else
243  {
244  for (size_t i = 0; i < cloud_out.points.size (); ++i)
245  {
246  if (!pcl_isfinite (cloud_in.points[i].x) ||
247  !pcl_isfinite (cloud_in.points[i].y) ||
248  !pcl_isfinite (cloud_in.points[i].z))
249  continue;
250  cloud_out.points[i].getVector3fMap () = rot *
251  cloud_in.points[i].getVector3fMap () + trans;
252 
253  // Rotate normals
254  cloud_out.points[i].getNormalVector3fMap() = rot *
255  cloud_in.points[i].getNormalVector3fMap ();
256  }
257  }
258 }
259 
261 template <typename PointT> inline void
263  pcl::PointCloud<PointT> &cloud_out,
264  const Eigen::Vector3f &offset,
265  const Eigen::Quaternionf &rotation)
266 {
267  Eigen::Translation3f translation (offset);
268  // Assemble an Eigen Transform
269  Eigen::Affine3f t;
270  t = translation * rotation;
271  transformPointCloud (cloud_in, cloud_out, t);
272 }
273 
275 template <typename PointT> inline void
277  pcl::PointCloud<PointT> &cloud_out,
278  const Eigen::Vector3f &offset,
279  const Eigen::Quaternionf &rotation)
280 {
281  Eigen::Translation3f translation (offset);
282  // Assemble an Eigen Transform
283  Eigen::Affine3f t;
284  t = translation * rotation;
285  transformPointCloudWithNormals (cloud_in, cloud_out, t);
286 }
287 
289 template <typename PointT> inline PointT
290 pcl::transformPoint (const PointT &point, const Eigen::Affine3f &transform)
291 {
292  PointT ret = point;
293  ret.getVector3fMap () = transform * point.getVector3fMap ();
294  return ret;
295 }