1 /* 2 * Software License Agreement (BSD License) 3 * 4 * Point Cloud Library (PCL) - www.pointclouds.org 5 * Copyright (c) 2010-2011, Willow Garage, Inc. 6 * 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * * Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * * Redistributions in binary form must reproduce the above 16 * copyright notice, this list of conditions and the following 17 * disclaimer in the documentation and/or other materials provided 18 * with the distribution. 19 * * Neither the name of the copyright holder(s) nor the names of its 20 * contributors may be used to endorse or promote products derived 21 * from this software without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 26 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 27 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 29 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 30 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 31 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 33 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34 * POSSIBILITY OF SUCH DAMAGE. 35 * 36 * $Id$ 37 * 38 */ 39 40 #pragma once 41 42 #include <pcl/memory.h> 43 #include <pcl/pcl_macros.h> 44 #include <pcl/point_cloud.h> 45 #include <pcl/io/file_io.h> 46 #include <boost/interprocess/sync/file_lock.hpp> // for file_lock 47 48 namespace pcl 49 { 50 /** \brief Point Cloud Data (PCD) file format reader. 51 * \author Radu B. Rusu 52 * \ingroup io 53 */ 54 class PCL_EXPORTS PCDReader : public FileReader 55 { 56 public: 57 /** Empty constructor */ PCDReader()58 PCDReader () {} 59 /** Empty destructor */ ~PCDReader()60 ~PCDReader () {} 61 62 /** \brief Various PCD file versions. 63 * 64 * PCD_V6 represents PCD files with version 0.6, which contain the following fields: 65 * - lines beginning with # are treated as comments 66 * - FIELDS ... 67 * - SIZE ... 68 * - TYPE ... 69 * - COUNT ... 70 * - WIDTH ... 71 * - HEIGHT ... 72 * - POINTS ... 73 * - DATA ascii/binary 74 * 75 * Everything that follows \b DATA is interpreted as data points and 76 * will be read accordingly. 77 * 78 * PCD_V7 represents PCD files with version 0.7 and has an important 79 * addon: it adds sensor origin/orientation (aka viewpoint) information 80 * to a dataset through the use of a new header field: 81 * - VIEWPOINT tx ty tz qw qx qy qz 82 */ 83 enum 84 { 85 PCD_V6 = 0, 86 PCD_V7 = 1 87 }; 88 89 /** \brief Read a point cloud data header from a PCD-formatted, binary istream. 90 * 91 * Load only the meta information (number of points, their types, etc), 92 * and not the points themselves, from a given PCD stream. Useful for fast 93 * evaluation of the underlying data structure. 94 * 95 * \attention The PCD data is \b always stored in ROW major format! The 96 * read/write PCD methods will detect column major input and automatically convert it. 97 * 98 * \param[in] binary_istream a std::istream with openmode set to std::ios::binary. 99 * \param[out] cloud the resultant point cloud dataset (only these 100 * members will be filled: width, height, point_step, 101 * row_step, fields[]; data is resized but not written) 102 * \param[out] origin the sensor acquisition origin (only for > PCD_V7 - null if not present) 103 * \param[out] orientation the sensor acquisition orientation (only for > PCD_V7 - identity if not present) 104 * \param[out] pcd_version the PCD version of the file (i.e., PCD_V6, PCD_V7) 105 * \param[out] data_type the type of data (0 = ASCII, 1 = Binary, 2 = Binary compressed) 106 * \param[out] data_idx the offset of cloud data within the file 107 * 108 * \return 109 * * < 0 (-1) on error 110 * * == 0 on success 111 */ 112 int 113 readHeader (std::istream &binary_istream, pcl::PCLPointCloud2 &cloud, 114 Eigen::Vector4f &origin, Eigen::Quaternionf &orientation, int &pcd_version, 115 int &data_type, unsigned int &data_idx); 116 117 /** \brief Read a point cloud data header from a PCD file. 118 * 119 * Load only the meta information (number of points, their types, etc), 120 * and not the points themselves, from a given PCD file. Useful for fast 121 * evaluation of the underlying data structure. 122 * 123 * \attention The PCD data is \b always stored in ROW major format! The 124 * read/write PCD methods will detect column major input and automatically convert it. 125 * 126 * \param[in] file_name the name of the file to load 127 * \param[out] cloud the resultant point cloud dataset (only these 128 * members will be filled: width, height, point_step, 129 * row_step, fields[]; data is resized but not written) 130 * \param[out] origin the sensor acquisition origin (only for > PCD_V7 - null if not present) 131 * \param[out] orientation the sensor acquisition orientation (only for > PCD_V7 - identity if not present) 132 * \param[out] pcd_version the PCD version of the file (i.e., PCD_V6, PCD_V7) 133 * \param[out] data_type the type of data (0 = ASCII, 1 = Binary, 2 = Binary compressed) 134 * \param[out] data_idx the offset of cloud data within the file 135 * \param[in] offset the offset of where to expect the PCD Header in the 136 * file (optional parameter). One usage example for setting the offset 137 * parameter is for reading data from a TAR "archive containing multiple 138 * PCD files: TAR files always add a 512 byte header in front of the 139 * actual file, so set the offset to the next byte after the header 140 * (e.g., 513). 141 * 142 * \return 143 * * < 0 (-1) on error 144 * * == 0 on success 145 */ 146 int 147 readHeader (const std::string &file_name, pcl::PCLPointCloud2 &cloud, 148 Eigen::Vector4f &origin, Eigen::Quaternionf &orientation, int &pcd_version, 149 int &data_type, unsigned int &data_idx, const int offset = 0) override; 150 151 152 /** \brief Read a point cloud data header from a PCD file. 153 * 154 * Load only the meta information (number of points, their types, etc), 155 * and not the points themselves, from a given PCD file. Useful for fast 156 * evaluation of the underlying data structure. 157 * 158 * \attention The PCD data is \b always stored in ROW major format! The 159 * read/write PCD methods will detect column major input and automatically convert it. 160 * 161 * \param[in] file_name the name of the file to load 162 * \param[out] cloud the resultant point cloud dataset (only these 163 * members will be filled: width, height, point_step, 164 * row_step, fields[]; data is resized but not written) 165 * \param[in] offset the offset of where to expect the PCD Header in the 166 * file (optional parameter). One usage example for setting the offset 167 * parameter is for reading data from a TAR "archive containing multiple 168 * PCD files: TAR files always add a 512 byte header in front of the 169 * actual file, so set the offset to the next byte after the header 170 * (e.g., 513). 171 * 172 * \return 173 * * < 0 (-1) on error 174 * * == 0 on success 175 */ 176 int 177 readHeader (const std::string &file_name, pcl::PCLPointCloud2 &cloud, const int offset = 0); 178 179 /** \brief Read the point cloud data (body) from a PCD stream. 180 * 181 * Reads the cloud points from a text-formatted stream. For use after 182 * readHeader(), when the resulting data_type == 0. 183 * 184 * \attention This assumes the stream has been seeked to the position 185 * indicated by the data_idx result of readHeader(). 186 * 187 * \param[in] stream the stream from which to read the body. 188 * \param[out] cloud the resultant point cloud dataset to be filled. 189 * \param[in] pcd_version the PCD version of the stream (from readHeader()). 190 * 191 * \return 192 * * < 0 (-1) on error 193 * * == 0 on success 194 */ 195 int 196 readBodyASCII (std::istream &stream, pcl::PCLPointCloud2 &cloud, int pcd_version); 197 198 /** \brief Read the point cloud data (body) from a block of memory. 199 * 200 * Reads the cloud points from a binary-formatted memory block. For use 201 * after readHeader(), when the resulting data_type is nonzero. 202 * 203 * \param[in] data the memory location from which to read the body. 204 * \param[out] cloud the resultant point cloud dataset to be filled. 205 * \param[in] pcd_version the PCD version of the stream (from readHeader()). 206 * \param[in] compressed indicates whether the PCD block contains compressed 207 * data. This should be true if the data_type returne by readHeader() == 2. 208 * \param[in] data_idx the offset of the body, as reported by readHeader(). 209 * 210 * \return 211 * * < 0 (-1) on error 212 * * == 0 on success 213 */ 214 int 215 readBodyBinary (const unsigned char *data, pcl::PCLPointCloud2 &cloud, 216 int pcd_version, bool compressed, unsigned int data_idx); 217 218 /** \brief Read a point cloud data from a PCD file and store it into a pcl/PCLPointCloud2. 219 * \param[in] file_name the name of the file containing the actual PointCloud data 220 * \param[out] cloud the resultant PointCloud message read from disk 221 * \param[out] origin the sensor acquisition origin (only for > PCD_V7 - null if not present) 222 * \param[out] orientation the sensor acquisition orientation (only for > PCD_V7 - identity if not present) 223 * \param[out] pcd_version the PCD version of the file (either PCD_V6 or PCD_V7) 224 * \param[in] offset the offset of where to expect the PCD Header in the 225 * file (optional parameter). One usage example for setting the offset 226 * parameter is for reading data from a TAR "archive containing multiple 227 * PCD files: TAR files always add a 512 byte header in front of the 228 * actual file, so set the offset to the next byte after the header 229 * (e.g., 513). 230 * 231 * \return 232 * * < 0 (-1) on error 233 * * == 0 on success 234 */ 235 int 236 read (const std::string &file_name, pcl::PCLPointCloud2 &cloud, 237 Eigen::Vector4f &origin, Eigen::Quaternionf &orientation, int &pcd_version, const int offset = 0) override; 238 239 /** \brief Read a point cloud data from a PCD (PCD_V6) and store it into a pcl/PCLPointCloud2. 240 * 241 * \note This function is provided for backwards compatibility only and 242 * it can only read PCD_V6 files correctly, as pcl::PCLPointCloud2 243 * does not contain a sensor origin/orientation. Reading any file 244 * > PCD_V6 will generate a warning. 245 * 246 * \param[in] file_name the name of the file containing the actual PointCloud data 247 * \param[out] cloud the resultant PointCloud message read from disk 248 * \param[in] offset the offset of where to expect the PCD Header in the 249 * file (optional parameter). One usage example for setting the offset 250 * parameter is for reading data from a TAR "archive containing multiple 251 * PCD files: TAR files always add a 512 byte header in front of the 252 * actual file, so set the offset to the next byte after the header 253 * (e.g., 513). 254 * 255 * \return 256 * * < 0 (-1) on error 257 * * == 0 on success 258 */ 259 int 260 read (const std::string &file_name, pcl::PCLPointCloud2 &cloud, const int offset = 0); 261 262 /** \brief Read a point cloud data from any PCD file, and convert it to the given template format. 263 * \param[in] file_name the name of the file containing the actual PointCloud data 264 * \param[out] cloud the resultant PointCloud message read from disk 265 * \param[in] offset the offset of where to expect the PCD Header in the 266 * file (optional parameter). One usage example for setting the offset 267 * parameter is for reading data from a TAR "archive containing multiple 268 * PCD files: TAR files always add a 512 byte header in front of the 269 * actual file, so set the offset to the next byte after the header 270 * (e.g., 513). 271 * 272 * \return 273 * * < 0 (-1) on error 274 * * == 0 on success 275 */ 276 template<typename PointT> int 277 read (const std::string &file_name, pcl::PointCloud<PointT> &cloud, const int offset = 0) 278 { 279 pcl::PCLPointCloud2 blob; 280 int pcd_version; 281 int res = read (file_name, blob, cloud.sensor_origin_, cloud.sensor_orientation_, 282 pcd_version, offset); 283 284 // If no error, convert the data 285 if (res == 0) 286 pcl::fromPCLPointCloud2 (blob, cloud); 287 return (res); 288 } 289 290 PCL_MAKE_ALIGNED_OPERATOR_NEW 291 }; 292 293 /** \brief Point Cloud Data (PCD) file format writer. 294 * \author Radu Bogdan Rusu 295 * \ingroup io 296 */ 297 class PCL_EXPORTS PCDWriter : public FileWriter 298 { 299 public: PCDWriter()300 PCDWriter() : map_synchronization_(false) {} ~PCDWriter()301 ~PCDWriter() {} 302 303 /** \brief Set whether mmap() synchornization via msync() is desired before munmap() calls. 304 * Setting this to true could prevent NFS data loss (see 305 * http://www.pcl-developers.org/PCD-IO-consistency-on-NFS-msync-needed-td4885942.html). 306 * Default: false 307 * \note This option should be used by advanced users only! 308 * \note Please note that using msync() on certain systems can reduce the I/O performance by up to 80%! 309 * \param[in] sync set to true if msync() should be called before munmap() 310 */ 311 void setMapSynchronization(bool sync)312 setMapSynchronization (bool sync) 313 { 314 map_synchronization_ = sync; 315 } 316 317 /** \brief Generate the header of a PCD file format 318 * \param[in] cloud the point cloud data message 319 * \param[in] origin the sensor acquisition origin 320 * \param[in] orientation the sensor acquisition orientation 321 */ 322 std::string 323 generateHeaderBinary (const pcl::PCLPointCloud2 &cloud, 324 const Eigen::Vector4f &origin, 325 const Eigen::Quaternionf &orientation); 326 327 /** \brief Generate the header of a BINARY_COMPRESSED PCD file format 328 * \param[out] os the stream into which to write the header 329 * \param[in] cloud the point cloud data message 330 * \param[in] origin the sensor acquisition origin 331 * \param[in] orientation the sensor acquisition orientation 332 * 333 * \return 334 * * < 0 (-1) on error 335 * * == 0 on success 336 */ 337 int 338 generateHeaderBinaryCompressed (std::ostream &os, 339 const pcl::PCLPointCloud2 &cloud, 340 const Eigen::Vector4f &origin, 341 const Eigen::Quaternionf &orientation); 342 343 /** \brief Generate the header of a BINARY_COMPRESSED PCD file format 344 * \param[in] cloud the point cloud data message 345 * \param[in] origin the sensor acquisition origin 346 * \param[in] orientation the sensor acquisition orientation 347 */ 348 std::string 349 generateHeaderBinaryCompressed (const pcl::PCLPointCloud2 &cloud, 350 const Eigen::Vector4f &origin, 351 const Eigen::Quaternionf &orientation); 352 353 /** \brief Generate the header of a PCD file format 354 * \param[in] cloud the point cloud data message 355 * \param[in] origin the sensor acquisition origin 356 * \param[in] orientation the sensor acquisition orientation 357 */ 358 std::string 359 generateHeaderASCII (const pcl::PCLPointCloud2 &cloud, 360 const Eigen::Vector4f &origin, 361 const Eigen::Quaternionf &orientation); 362 363 /** \brief Generate the header of a PCD file format 364 * \param[in] cloud the point cloud data message 365 * \param[in] nr_points if given, use this to fill in WIDTH, HEIGHT (=1), and POINTS in the header 366 * By default, nr_points is set to INTMAX, and the data in the header is used instead. 367 */ 368 template <typename PointT> static std::string 369 generateHeader (const pcl::PointCloud<PointT> &cloud, 370 const int nr_points = std::numeric_limits<int>::max ()); 371 372 /** \brief Save point cloud data to a PCD file containing n-D points, in ASCII format 373 * \param[in] file_name the output file name 374 * \param[in] cloud the point cloud data message 375 * \param[in] origin the sensor acquisition origin 376 * \param[in] orientation the sensor acquisition orientation 377 * \param[in] precision the specified output numeric stream precision (default: 8) 378 * 379 * Caution: PointCloud structures containing an RGB field have 380 * traditionally used packed float values to store RGB data. Storing a 381 * float as ASCII can introduce variations to the smallest bits, and 382 * thus significantly alter the data. This is a known issue, and the fix 383 * involves switching RGB data to be stored as a packed integer in 384 * future versions of PCL. 385 * 386 * As an intermediary solution, precision 8 is used, which guarantees lossless storage for RGB. 387 */ 388 int 389 writeASCII (const std::string &file_name, const pcl::PCLPointCloud2 &cloud, 390 const Eigen::Vector4f &origin = Eigen::Vector4f::Zero (), 391 const Eigen::Quaternionf &orientation = Eigen::Quaternionf::Identity (), 392 const int precision = 8); 393 394 /** \brief Save point cloud data to a PCD file containing n-D points, in BINARY format 395 * \param[in] file_name the output file name 396 * \param[in] cloud the point cloud data message 397 * \param[in] origin the sensor acquisition origin 398 * \param[in] orientation the sensor acquisition orientation 399 */ 400 int 401 writeBinary (const std::string &file_name, const pcl::PCLPointCloud2 &cloud, 402 const Eigen::Vector4f &origin = Eigen::Vector4f::Zero (), 403 const Eigen::Quaternionf &orientation = Eigen::Quaternionf::Identity ()); 404 405 /** \brief Save point cloud data to a PCD file containing n-D points, in BINARY_COMPRESSED format 406 * \param[in] file_name the output file name 407 * \param[in] cloud the point cloud data message 408 * \param[in] origin the sensor acquisition origin 409 * \param[in] orientation the sensor acquisition orientation 410 * \return 411 * (-1) for a general error 412 * (-2) if the input cloud is too large for the file format 413 * 0 on success 414 */ 415 int 416 writeBinaryCompressed (const std::string &file_name, const pcl::PCLPointCloud2 &cloud, 417 const Eigen::Vector4f &origin = Eigen::Vector4f::Zero (), 418 const Eigen::Quaternionf &orientation = Eigen::Quaternionf::Identity ()); 419 420 /** \brief Save point cloud data to a std::ostream containing n-D points, in BINARY_COMPRESSED format 421 * \param[out] os the stream into which to write the data 422 * \param[in] cloud the point cloud data message 423 * \param[in] origin the sensor acquisition origin 424 * \param[in] orientation the sensor acquisition orientation 425 * \return 426 * (-1) for a general error 427 * (-2) if the input cloud is too large for the file format 428 * 0 on success 429 */ 430 int 431 writeBinaryCompressed (std::ostream &os, const pcl::PCLPointCloud2 &cloud, 432 const Eigen::Vector4f &origin = Eigen::Vector4f::Zero (), 433 const Eigen::Quaternionf &orientation = Eigen::Quaternionf::Identity ()); 434 435 /** \brief Save point cloud data to a PCD file containing n-D points 436 * \param[in] file_name the output file name 437 * \param[in] cloud the point cloud data message 438 * \param[in] origin the sensor acquisition origin 439 * \param[in] orientation the sensor acquisition orientation 440 * \param[in] binary set to true if the file is to be written in a binary 441 * PCD format, false (default) for ASCII 442 * 443 * Caution: PointCloud structures containing an RGB field have 444 * traditionally used packed float values to store RGB data. Storing a 445 * float as ASCII can introduce variations to the smallest bits, and 446 * thus significantly alter the data. This is a known issue, and the fix 447 * involves switching RGB data to be stored as a packed integer in 448 * future versions of PCL. 449 * 450 * As an intermediary solution, precision 8 is used, which guarantees lossless storage for RGB. 451 */ 452 inline int 453 write (const std::string &file_name, const pcl::PCLPointCloud2 &cloud, 454 const Eigen::Vector4f &origin = Eigen::Vector4f::Zero (), 455 const Eigen::Quaternionf &orientation = Eigen::Quaternionf::Identity (), 456 const bool binary = false) override 457 { 458 if (binary) 459 return (writeBinary (file_name, cloud, origin, orientation)); 460 return (writeASCII (file_name, cloud, origin, orientation, 8)); 461 } 462 463 /** \brief Save point cloud data to a PCD file containing n-D points 464 * \param[in] file_name the output file name 465 * \param[in] cloud the point cloud data message (boost shared pointer) 466 * \param[in] binary set to true if the file is to be written in a binary PCD format, 467 * false (default) for ASCII 468 * \param[in] origin the sensor acquisition origin 469 * \param[in] orientation the sensor acquisition orientation 470 * 471 * Caution: PointCloud structures containing an RGB field have 472 * traditionally used packed float values to store RGB data. Storing a 473 * float as ASCII can introduce variations to the smallest bits, and 474 * thus significantly alter the data. This is a known issue, and the fix 475 * involves switching RGB data to be stored as a packed integer in 476 * future versions of PCL. 477 */ 478 inline int 479 write (const std::string &file_name, const pcl::PCLPointCloud2::ConstPtr &cloud, 480 const Eigen::Vector4f &origin = Eigen::Vector4f::Zero (), 481 const Eigen::Quaternionf &orientation = Eigen::Quaternionf::Identity (), 482 const bool binary = false) 483 { 484 return (write (file_name, *cloud, origin, orientation, binary)); 485 } 486 487 /** \brief Save point cloud data to a PCD file containing n-D points, in BINARY format 488 * \param[in] file_name the output file name 489 * \param[in] cloud the point cloud data message 490 */ 491 template <typename PointT> int 492 writeBinary (const std::string &file_name, 493 const pcl::PointCloud<PointT> &cloud); 494 495 /** \brief Save point cloud data to a binary comprssed PCD file 496 * \param[in] file_name the output file name 497 * \param[in] cloud the point cloud data message 498 * \return 499 * (-1) for a general error 500 * (-2) if the input cloud is too large for the file format 501 * 0 on success 502 */ 503 template <typename PointT> int 504 writeBinaryCompressed (const std::string &file_name, 505 const pcl::PointCloud<PointT> &cloud); 506 507 /** \brief Save point cloud data to a PCD file containing n-D points, in BINARY format 508 * \param[in] file_name the output file name 509 * \param[in] cloud the point cloud data message 510 * \param[in] indices the set of point indices that we want written to disk 511 */ 512 template <typename PointT> int 513 writeBinary (const std::string &file_name, 514 const pcl::PointCloud<PointT> &cloud, 515 const pcl::Indices &indices); 516 517 /** \brief Save point cloud data to a PCD file containing n-D points, in ASCII format 518 * \param[in] file_name the output file name 519 * \param[in] cloud the point cloud data message 520 * \param[in] precision the specified output numeric stream precision (default: 8) 521 */ 522 template <typename PointT> int 523 writeASCII (const std::string &file_name, 524 const pcl::PointCloud<PointT> &cloud, 525 const int precision = 8); 526 527 /** \brief Save point cloud data to a PCD file containing n-D points, in ASCII format 528 * \param[in] file_name the output file name 529 * \param[in] cloud the point cloud data message 530 * \param[in] indices the set of point indices that we want written to disk 531 * \param[in] precision the specified output numeric stream precision (default: 8) 532 */ 533 template <typename PointT> int 534 writeASCII (const std::string &file_name, 535 const pcl::PointCloud<PointT> &cloud, 536 const pcl::Indices &indices, 537 const int precision = 8); 538 539 /** \brief Save point cloud data to a PCD file containing n-D points 540 * \param[in] file_name the output file name 541 * \param[in] cloud the pcl::PointCloud data 542 * \param[in] binary set to true if the file is to be written in a binary 543 * PCD format, false (default) for ASCII 544 * 545 * Caution: PointCloud structures containing an RGB field have 546 * traditionally used packed float values to store RGB data. Storing a 547 * float as ASCII can introduce variations to the smallest bits, and 548 * thus significantly alter the data. This is a known issue, and the fix 549 * involves switching RGB data to be stored as a packed integer in 550 * future versions of PCL. 551 */ 552 template<typename PointT> inline int 553 write (const std::string &file_name, 554 const pcl::PointCloud<PointT> &cloud, 555 const bool binary = false) 556 { 557 if (binary) 558 return (writeBinary<PointT> (file_name, cloud)); 559 return (writeASCII<PointT> (file_name, cloud)); 560 } 561 562 /** \brief Save point cloud data to a PCD file containing n-D points 563 * \param[in] file_name the output file name 564 * \param[in] cloud the pcl::PointCloud data 565 * \param[in] indices the set of point indices that we want written to disk 566 * \param[in] binary set to true if the file is to be written in a binary 567 * PCD format, false (default) for ASCII 568 * 569 * Caution: PointCloud structures containing an RGB field have 570 * traditionally used packed float values to store RGB data. Storing a 571 * float as ASCII can introduce variations to the smallest bits, and 572 * thus significantly alter the data. This is a known issue, and the fix 573 * involves switching RGB data to be stored as a packed integer in 574 * future versions of PCL. 575 */ 576 template<typename PointT> inline int 577 write (const std::string &file_name, 578 const pcl::PointCloud<PointT> &cloud, 579 const pcl::Indices &indices, 580 bool binary = false) 581 { 582 if (binary) 583 return (writeBinary<PointT> (file_name, cloud, indices)); 584 return (writeASCII<PointT> (file_name, cloud, indices)); 585 } 586 587 protected: 588 /** \brief Set permissions for file locking (Boost 1.49+). 589 * \param[in] file_name the file name to set permission for file locking 590 * \param[in,out] lock the file lock 591 */ 592 void 593 setLockingPermissions (const std::string &file_name, 594 boost::interprocess::file_lock &lock); 595 596 /** \brief Reset permissions for file locking (Boost 1.49+). 597 * \param[in] file_name the file name to reset permission for file locking 598 * \param[in,out] lock the file lock 599 */ 600 void 601 resetLockingPermissions (const std::string &file_name, 602 boost::interprocess::file_lock &lock); 603 604 private: 605 /** \brief Set to true if msync() should be called before munmap(). Prevents data loss on NFS systems. */ 606 bool map_synchronization_; 607 }; 608 609 namespace io 610 { 611 /** \brief Load a PCD v.6 file into a templated PointCloud type. 612 * 613 * Any PCD files > v.6 will generate a warning as a 614 * pcl/PCLPointCloud2 message cannot hold the sensor origin. 615 * 616 * \param[in] file_name the name of the file to load 617 * \param[out] cloud the resultant templated point cloud 618 * \ingroup io 619 */ 620 inline int loadPCDFile(const std::string & file_name,pcl::PCLPointCloud2 & cloud)621 loadPCDFile (const std::string &file_name, pcl::PCLPointCloud2 &cloud) 622 { 623 pcl::PCDReader p; 624 return (p.read (file_name, cloud)); 625 } 626 627 /** \brief Load any PCD file into a templated PointCloud type. 628 * \param[in] file_name the name of the file to load 629 * \param[out] cloud the resultant templated point cloud 630 * \param[out] origin the sensor acquisition origin (only for > PCD_V7 - null if not present) 631 * \param[out] orientation the sensor acquisition orientation (only for > 632 * PCD_V7 - identity if not present) 633 * \ingroup io 634 */ 635 inline int loadPCDFile(const std::string & file_name,pcl::PCLPointCloud2 & cloud,Eigen::Vector4f & origin,Eigen::Quaternionf & orientation)636 loadPCDFile (const std::string &file_name, pcl::PCLPointCloud2 &cloud, 637 Eigen::Vector4f &origin, Eigen::Quaternionf &orientation) 638 { 639 pcl::PCDReader p; 640 int pcd_version; 641 return (p.read (file_name, cloud, origin, orientation, pcd_version)); 642 } 643 644 /** \brief Load any PCD file into a templated PointCloud type 645 * \param[in] file_name the name of the file to load 646 * \param[out] cloud the resultant templated point cloud 647 * \ingroup io 648 */ 649 template<typename PointT> inline int loadPCDFile(const std::string & file_name,pcl::PointCloud<PointT> & cloud)650 loadPCDFile (const std::string &file_name, pcl::PointCloud<PointT> &cloud) 651 { 652 pcl::PCDReader p; 653 return (p.read (file_name, cloud)); 654 } 655 656 /** \brief Save point cloud data to a PCD file containing n-D points 657 * \param[in] file_name the output file name 658 * \param[in] cloud the point cloud data message 659 * \param[in] origin the sensor acquisition origin 660 * \param[in] orientation the sensor acquisition orientation 661 * \param[in] binary_mode true for binary mode, false (default) for ASCII 662 * 663 * Caution: PointCloud structures containing an RGB field have 664 * traditionally used packed float values to store RGB data. Storing a 665 * float as ASCII can introduce variations to the smallest bits, and 666 * thus significantly alter the data. This is a known issue, and the fix 667 * involves switching RGB data to be stored as a packed integer in 668 * future versions of PCL. 669 * \ingroup io 670 */ 671 inline int 672 savePCDFile (const std::string &file_name, const pcl::PCLPointCloud2 &cloud, 673 const Eigen::Vector4f &origin = Eigen::Vector4f::Zero (), 674 const Eigen::Quaternionf &orientation = Eigen::Quaternionf::Identity (), 675 const bool binary_mode = false) 676 { 677 PCDWriter w; 678 return (w.write (file_name, cloud, origin, orientation, binary_mode)); 679 } 680 681 /** \brief Templated version for saving point cloud data to a PCD file 682 * containing a specific given cloud format 683 * \param[in] file_name the output file name 684 * \param[in] cloud the point cloud data message 685 * \param[in] binary_mode true for binary mode, false (default) for ASCII 686 * 687 * Caution: PointCloud structures containing an RGB field have 688 * traditionally used packed float values to store RGB data. Storing a 689 * float as ASCII can introduce variations to the smallest bits, and 690 * thus significantly alter the data. This is a known issue, and the fix 691 * involves switching RGB data to be stored as a packed integer in 692 * future versions of PCL. 693 * \ingroup io 694 */ 695 template<typename PointT> inline int 696 savePCDFile (const std::string &file_name, const pcl::PointCloud<PointT> &cloud, bool binary_mode = false) 697 { 698 PCDWriter w; 699 return (w.write<PointT> (file_name, cloud, binary_mode)); 700 } 701 702 /** 703 * \brief Templated version for saving point cloud data to a PCD file 704 * containing a specific given cloud format. 705 * 706 * This version is to retain backwards compatibility. 707 * \param[in] file_name the output file name 708 * \param[in] cloud the point cloud data message 709 * 710 * Caution: PointCloud structures containing an RGB field have 711 * traditionally used packed float values to store RGB data. Storing a 712 * float as ASCII can introduce variations to the smallest bits, and 713 * thus significantly alter the data. This is a known issue, and the fix 714 * involves switching RGB data to be stored as a packed integer in 715 * future versions of PCL. 716 * \ingroup io 717 */ 718 template<typename PointT> inline int savePCDFileASCII(const std::string & file_name,const pcl::PointCloud<PointT> & cloud)719 savePCDFileASCII (const std::string &file_name, const pcl::PointCloud<PointT> &cloud) 720 { 721 PCDWriter w; 722 return (w.write<PointT> (file_name, cloud, false)); 723 } 724 725 /** 726 * \brief Templated version for saving point cloud data to a PCD file 727 * containing a specific given cloud format. The resulting file will be an uncompressed binary. 728 * 729 * This version is to retain backwards compatibility. 730 * \param[in] file_name the output file name 731 * \param[in] cloud the point cloud data message 732 * \ingroup io 733 */ 734 template<typename PointT> inline int savePCDFileBinary(const std::string & file_name,const pcl::PointCloud<PointT> & cloud)735 savePCDFileBinary (const std::string &file_name, const pcl::PointCloud<PointT> &cloud) 736 { 737 PCDWriter w; 738 return (w.write<PointT> (file_name, cloud, true)); 739 } 740 741 /** 742 * \brief Templated version for saving point cloud data to a PCD file 743 * containing a specific given cloud format 744 * 745 * \param[in] file_name the output file name 746 * \param[in] cloud the point cloud data message 747 * \param[in] indices the set of indices to save 748 * \param[in] binary_mode true for binary mode, false (default) for ASCII 749 * 750 * Caution: PointCloud structures containing an RGB field have 751 * traditionally used packed float values to store RGB data. Storing a 752 * float as ASCII can introduce variations to the smallest bits, and 753 * thus significantly alter the data. This is a known issue, and the fix 754 * involves switching RGB data to be stored as a packed integer in 755 * future versions of PCL. 756 * \ingroup io 757 */ 758 template<typename PointT> int 759 savePCDFile (const std::string &file_name, 760 const pcl::PointCloud<PointT> &cloud, 761 const pcl::Indices &indices, 762 const bool binary_mode = false) 763 { 764 // Save the data 765 PCDWriter w; 766 return (w.write<PointT> (file_name, cloud, indices, binary_mode)); 767 } 768 769 770 /** 771 * \brief Templated version for saving point cloud data to a PCD file 772 * containing a specific given cloud format. This method will write a compressed binary file. 773 * 774 * This version is to retain backwards compatibility. 775 * \param[in] file_name the output file name 776 * \param[in] cloud the point cloud data message 777 * \ingroup io 778 */ 779 template<typename PointT> inline int savePCDFileBinaryCompressed(const std::string & file_name,const pcl::PointCloud<PointT> & cloud)780 savePCDFileBinaryCompressed (const std::string &file_name, const pcl::PointCloud<PointT> &cloud) 781 { 782 PCDWriter w; 783 return (w.writeBinaryCompressed<PointT> (file_name, cloud)); 784 } 785 786 } 787 } 788 789 #include <pcl/io/impl/pcd_io.hpp> 790