Point Cloud Library (PCL) 1.13.0
octree_disk_container.h
1/*
2 * Software License Agreement (BSD License)
3 *
4 * Point Cloud Library (PCL) - www.pointclouds.org
5 * Copyright (c) 2010-2012, Willow Garage, Inc.
6 * Copyright (c) 2012, Urban Robotics, 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 Willow Garage, Inc. 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: octree_disk_container.h 6927M 2012-08-24 13:26:40Z (local) $
38 */
39
40#pragma once
41
42// C++
43#include <mutex>
44#include <string>
45
46// Boost
47#include <boost/uuid/random_generator.hpp>
48
49#include <pcl/common/utils.h> // pcl::utils::ignore
50#include <pcl/outofcore/octree_abstract_node_container.h>
51#include <pcl/io/pcd_io.h>
52#include <pcl/PCLPointCloud2.h>
53
54//allows operation on POSIX
55#if !defined _WIN32
56#define _fseeki64 fseeko
57#elif defined __MINGW32__
58#define _fseeki64 fseeko64
59#endif
60
61namespace pcl
62{
63 namespace outofcore
64 {
65 /** \class OutofcoreOctreeDiskContainer
66 * \note Code was adapted from the Urban Robotics out of core octree implementation.
67 * Contact Jacob Schloss <jacob.schloss@urbanrobotics.net> with any questions.
68 * http://www.urbanrobotics.net/
69 *
70 * \brief Class responsible for serialization and deserialization of out of core point data
71 * \ingroup outofcore
72 * \author Jacob Schloss (jacob.schloss@urbanrobotics.net)
73 */
74 template<typename PointT = pcl::PointXYZ>
76 {
77
78 public:
80
81 /** \brief Empty constructor creates disk container and sets filename from random uuid string*/
83
84 /** \brief Creates uuid named file or loads existing file
85 *
86 * If \b dir is a directory, this constructor will create a new
87 * uuid named file; if \b dir is an existing file, it will load the
88 * file metadata for accessing the tree.
89 *
90 * \param[in] dir Path to the tree. If it is a directory, it
91 * will create the metadata. If it is a file, it will load the metadata into memory.
92 */
93 OutofcoreOctreeDiskContainer (const boost::filesystem::path &dir);
94
95 /** \brief flushes write buffer, then frees memory */
97
98 /** \brief provides random access to points based on a linear index
99 */
100 inline PointT
101 operator[] (std::uint64_t idx) const override;
102
103 /** \brief Adds a single point to the buffer to be written to disk when the buffer grows sufficiently large, the object is destroyed, or the write buffer is manually flushed */
104 inline void
105 push_back (const PointT& p);
106
107 /** \brief Inserts a vector of points into the disk data structure */
108 void
109 insertRange (const AlignedPointTVector& src);
110
111 /** \brief Inserts a PCLPointCloud2 object directly into the disk container */
112 void
113 insertRange (const pcl::PCLPointCloud2::Ptr &input_cloud);
114
115 void
116 insertRange (const PointT* const * start, const std::uint64_t count) override;
117
118 /** \brief This is the primary method for serialization of
119 * blocks of point data. This is called by the outofcore
120 * octree interface, opens the binary file for appending data,
121 * and writes it to disk.
122 *
123 * \param[in] start address of the first point to insert
124 * \param[in] count offset from start of the last point to insert
125 */
126 void
127 insertRange (const PointT* start, const std::uint64_t count) override;
128
129 /** \brief Reads \b count points into memory from the disk container
130 *
131 * Reads \b count points into memory from the disk container, reading at most 2 million elements at a time
132 *
133 * \param[in] start index of first point to read from disk
134 * \param[in] count offset of last point to read from disk
135 * \param[out] dst std::vector as destination for points read from disk into memory
136 */
137 void
138 readRange (const std::uint64_t start, const std::uint64_t count, AlignedPointTVector &dst) override;
139
140 void
141 readRange (const std::uint64_t, const std::uint64_t, pcl::PCLPointCloud2::Ptr &dst);
142
143 /** \brief Reads the entire point contents from disk into \c output_cloud
144 * \param[out] output_cloud
145 */
146 int
147 read (pcl::PCLPointCloud2::Ptr &output_cloud);
148
149 /** \brief grab percent*count random points. points are \b not guaranteed to be
150 * unique (could have multiple identical points!)
151 *
152 * \param[in] start The starting index of points to select
153 * \param[in] count The length of the range of points from which to randomly sample
154 * (i.e. from start to start+count)
155 * \param[in] percent The percentage of count that is enough points to make up this random sample
156 * \param[out] dst std::vector as destination for randomly sampled points; size will
157 * be percentage*count
158 */
159 void
160 readRangeSubSample (const std::uint64_t start, const std::uint64_t count, const double percent,
161 AlignedPointTVector &dst) override;
162
163 /** \brief Use bernoulli trials to select points. All points selected will be unique.
164 *
165 * \param[in] start The starting index of points to select
166 * \param[in] count The length of the range of points from which to randomly sample
167 * (i.e. from start to start+count)
168 * \param[in] percent The percentage of count that is enough points to make up this random sample
169 * \param[out] dst std::vector as destination for randomly sampled points; size will
170 * be percentage*count
171 */
172 void
173 readRangeSubSample_bernoulli (const std::uint64_t start, const std::uint64_t count,
174 const double percent, AlignedPointTVector& dst);
175
176 /** \brief Returns the total number of points for which this container is responsible, \c filelen_ + points in \c writebuff_ that have not yet been flushed to the disk
177 */
178 std::uint64_t
179 size () const override
180 {
181 return (filelen_ + writebuff_.size ());
182 }
183
184 /** \brief STL-like empty test
185 * \return true if container has no data on disk or waiting to be written in \c writebuff_ */
186 inline bool
187 empty () const override
188 {
189 return ((filelen_ == 0) && writebuff_.empty ());
190 }
191
192 /** \brief Exposed functionality for manually flushing the write buffer during tree creation */
193 void
194 flush (const bool force_cache_dealloc)
195 {
196 flushWritebuff (force_cache_dealloc);
197 }
198
199 /** \brief Returns this objects path name */
200 inline std::string&
202 {
203 return (disk_storage_filename_);
204 }
205
206 inline void
207 clear () override
208 {
209 //clear elements that have not yet been written to disk
210 writebuff_.clear ();
211 //remove the binary data in the directory
212 PCL_DEBUG ("[Octree Disk Container] Removing the point data from disk, in file %s\n", disk_storage_filename_.c_str ());
213 boost::filesystem::remove (boost::filesystem::path (disk_storage_filename_.c_str ()));
214 //reset the size-of-file counter
215 filelen_ = 0;
216 }
217
218 /** \brief write points to disk as ascii
219 *
220 * \param[in] path
221 */
222 void
223 convertToXYZ (const boost::filesystem::path &path) override
224 {
225 if (boost::filesystem::exists (disk_storage_filename_))
226 {
227 FILE* fxyz = fopen (path.string ().c_str (), "we");
228
229 FILE* f = fopen (disk_storage_filename_.c_str (), "rbe");
230 assert (f != nullptr);
231
232 std::uint64_t num = size ();
233 PointT p;
234 char* loc = reinterpret_cast<char*> ( &p );
235
236 for (std::uint64_t i = 0; i < num; i++)
237 {
238 int seekret = _fseeki64 (f, i * sizeof (PointT), SEEK_SET);
239 pcl::utils::ignore(seekret);
240 assert (seekret == 0);
241 std::size_t readlen = fread (loc, sizeof (PointT), 1, f);
242 pcl::utils::ignore(readlen);
243 assert (readlen == 1);
244
245 //of << p.x << "\t" << p.y << "\t" << p.z << "\n";
246 std::stringstream ss;
247 ss << std::fixed;
248 ss.precision (16);
249 ss << p.x << "\t" << p.y << "\t" << p.z << "\n";
250
251 fwrite (ss.str ().c_str (), 1, ss.str ().size (), fxyz);
252 }
253 int res = fclose (f);
255 assert (res == 0);
256 res = fclose (fxyz);
257 assert (res == 0);
258 }
259 }
260
261 /** \brief Generate a universally unique identifier (UUID)
262 *
263 * A mutex lock happens to ensure uniqueness
264 *
265 */
266 static void
267 getRandomUUIDString (std::string &s);
268
269 /** \brief Returns the number of points in the PCD file by reading the PCD header. */
270 std::uint64_t
271 getDataSize () const;
272
273 private:
274 //no copy construction
276
277
279 operator= (const OutofcoreOctreeDiskContainer& /*rval*/) { }
280
281 void
282 flushWritebuff (const bool force_cache_dealloc);
283
284 /** \brief Name of the storage file on disk (i.e., the PCD file) */
285 std::string disk_storage_filename_;
286
287 //--- possibly deprecated parameter variables --//
288
289 //number of elements in file
290 std::uint64_t filelen_;
291
292 /** \brief elements [0,...,size()-1] map to [filelen, ..., filelen + size()-1] */
293 AlignedPointTVector writebuff_;
294
295 const static std::uint64_t READ_BLOCK_SIZE_;
296
297 static const std::uint64_t WRITE_BUFF_MAX_;
298
299 static std::mutex rng_mutex_;
300 static boost::mt19937 rand_gen_;
301 static boost::uuids::basic_random_generator<boost::mt19937> uuid_gen_;
302
303 };
304 } //namespace outofcore
305} //namespace pcl
std::vector< PointT, Eigen::aligned_allocator< PointT > > AlignedPointTVector
Class responsible for serialization and deserialization of out of core point data.
int read(pcl::PCLPointCloud2::Ptr &output_cloud)
Reads the entire point contents from disk into output_cloud.
std::string & path()
Returns this objects path name.
void flush(const bool force_cache_dealloc)
Exposed functionality for manually flushing the write buffer during tree creation.
OutofcoreOctreeDiskContainer()
Empty constructor creates disk container and sets filename from random uuid string.
static void getRandomUUIDString(std::string &s)
Generate a universally unique identifier (UUID)
void insertRange(const AlignedPointTVector &src)
Inserts a vector of points into the disk data structure.
void readRangeSubSample_bernoulli(const std::uint64_t start, const std::uint64_t count, const double percent, AlignedPointTVector &dst)
Use bernoulli trials to select points.
void readRange(const std::uint64_t start, const std::uint64_t count, AlignedPointTVector &dst) override
Reads count points into memory from the disk container.
std::uint64_t getDataSize() const
Returns the number of points in the PCD file by reading the PCD header.
typename OutofcoreAbstractNodeContainer< PointT >::AlignedPointTVector AlignedPointTVector
std::uint64_t size() const override
Returns the total number of points for which this container is responsible, filelen_ + points in writ...
void convertToXYZ(const boost::filesystem::path &path) override
write points to disk as ascii
void readRangeSubSample(const std::uint64_t start, const std::uint64_t count, const double percent, AlignedPointTVector &dst) override
grab percent*count random points.
bool empty() const override
STL-like empty test.
void push_back(const PointT &p)
Adds a single point to the buffer to be written to disk when the buffer grows sufficiently large,...
PointT operator[](std::uint64_t idx) const override
provides random access to points based on a linear index
~OutofcoreOctreeDiskContainer() override
flushes write buffer, then frees memory
void ignore(const T &...)
Utility function to eliminate unused variable warnings.
Definition: utils.h:62
shared_ptr< ::pcl::PCLPointCloud2 > Ptr
A point structure representing Euclidean xyz coordinates, and the RGB color.