00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #include <fstream>
00041 #include <fcntl.h>
00042 #include <string>
00043 #include <stdlib.h>
00044 #include <boost/algorithm/string.hpp>
00045 #include <pcl/common/io.h>
00046 #include <pcl/io/pcd_io.h>
00047 #include <pcl/io/lzf.h>
00048
00049 #include <boost/filesystem.hpp>
00050
00051 #include <cstring>
00052 #include <cerrno>
00053
00054 #ifdef _WIN32
00055 # include <io.h>
00056 # include <windows.h>
00057 # define pcl_open _open
00058 # define pcl_close(fd) _close(fd)
00059 # define pcl_lseek(fd,offset,origin) _lseek(fd,offset,origin)
00060 #else
00061 # include <sys/mman.h>
00062 # define pcl_open open
00063 # define pcl_close(fd) close(fd)
00064 # define pcl_lseek(fd,offset,origin) lseek(fd,offset,origin)
00065 #endif
00066
00068 int
00069 pcl::PCDReader::readHeader (const std::string &file_name, sensor_msgs::PointCloud2 &cloud,
00070 Eigen::Vector4f &origin, Eigen::Quaternionf &orientation,
00071 int &pcd_version, int &data_type, unsigned int &data_idx, const int offset)
00072 {
00073
00074 data_idx = 0;
00075 data_type = 0;
00076 pcd_version = PCD_V6;
00077 origin = Eigen::Vector4f::Zero ();
00078 orientation = Eigen::Quaternionf::Identity ();
00079 cloud.width = cloud.height = cloud.point_step = cloud.row_step = 0;
00080 cloud.data.clear ();
00081
00082
00083
00084
00085 int nr_points = 0;
00086 std::ifstream fs;
00087 std::string line;
00088
00089 int specified_channel_count = 0;
00090
00091 if (file_name == "" || !boost::filesystem::exists (file_name))
00092 {
00093 PCL_ERROR ("[pcl::PCDReader::readHeader] Could not find file '%s'.\n", file_name.c_str ());
00094 return (-1);
00095 }
00096
00097
00098 fs.open (file_name.c_str (), std::ios::binary);
00099 if (!fs.is_open () || fs.fail ())
00100 {
00101 PCL_ERROR ("[pcl::PCDReader::readHeader] Could not open file '%s'! Error : %s\n", file_name.c_str (), strerror(errno));
00102 fs.close ();
00103 return (-1);
00104 }
00105
00106
00107 fs.seekg (offset, std::ios::beg);
00108
00109
00110
00111 std::vector<int> field_sizes, field_counts;
00112
00113 std::vector<char> field_types;
00114 std::vector<std::string> st;
00115
00116
00117 try
00118 {
00119 while (!fs.eof ())
00120 {
00121 getline (fs, line);
00122
00123 if (line == "")
00124 continue;
00125
00126
00127 boost::trim (line);
00128 boost::split (st, line, boost::is_any_of ("\t\r "), boost::token_compress_on);
00129
00130 std::stringstream sstream (line);
00131 sstream.imbue (std::locale::classic ());
00132
00133 std::string line_type;
00134 sstream >> line_type;
00135
00136
00137 if (line_type.substr (0, 1) == "#")
00138 continue;
00139
00140
00141 if (line_type.substr (0, 7) == "VERSION")
00142 continue;
00143
00144
00145 if ( (line_type.substr (0, 6) == "FIELDS") || (line_type.substr (0, 7) == "COLUMNS") )
00146 {
00147 specified_channel_count = static_cast<int> (st.size () - 1);
00148
00149
00150 cloud.fields.resize (specified_channel_count);
00151 for (int i = 0; i < specified_channel_count; ++i)
00152 {
00153 std::string col_type = st.at (i + 1);
00154 cloud.fields[i].name = col_type;
00155 }
00156
00157
00158 int offset = 0;
00159 for (int i = 0; i < specified_channel_count; ++i, offset += 4)
00160 {
00161 cloud.fields[i].offset = offset;
00162 cloud.fields[i].datatype = sensor_msgs::PointField::FLOAT32;
00163 cloud.fields[i].count = 1;
00164 }
00165 cloud.point_step = offset;
00166 continue;
00167 }
00168
00169
00170 if (line_type.substr (0, 4) == "SIZE")
00171 {
00172 specified_channel_count = static_cast<int> (st.size () - 1);
00173
00174
00175 if (specified_channel_count != static_cast<int> (cloud.fields.size ()))
00176 throw "The number of elements in <SIZE> differs than the number of elements in <FIELDS>!";
00177
00178
00179 field_sizes.resize (specified_channel_count);
00180
00181 int offset = 0;
00182 for (int i = 0; i < specified_channel_count; ++i)
00183 {
00184 int col_type ;
00185 sstream >> col_type;
00186 cloud.fields[i].offset = offset;
00187 offset += col_type;
00188 field_sizes[i] = col_type;
00189 }
00190 cloud.point_step = offset;
00191
00192
00193 continue;
00194 }
00195
00196
00197 if (line_type.substr (0, 4) == "TYPE")
00198 {
00199 if (field_sizes.empty ())
00200 throw "TYPE of FIELDS specified before SIZE in header!";
00201
00202 specified_channel_count = static_cast<int> (st.size () - 1);
00203
00204
00205 if (specified_channel_count != static_cast<int> (cloud.fields.size ()))
00206 throw "The number of elements in <TYPE> differs than the number of elements in <FIELDS>!";
00207
00208
00209 field_types.resize (specified_channel_count);
00210
00211 for (int i = 0; i < specified_channel_count; ++i)
00212 {
00213 field_types[i] = st.at (i + 1).c_str ()[0];
00214 cloud.fields[i].datatype = static_cast<uint8_t> (getFieldType (field_sizes[i], field_types[i]));
00215 }
00216 continue;
00217 }
00218
00219
00220 if (line_type.substr (0, 5) == "COUNT")
00221 {
00222 if (field_sizes.empty () || field_types.empty ())
00223 throw "COUNT of FIELDS specified before SIZE or TYPE in header!";
00224
00225 specified_channel_count = static_cast<int> (st.size () - 1);
00226
00227
00228 if (specified_channel_count != static_cast<int> (cloud.fields.size ()))
00229 throw "The number of elements in <COUNT> differs than the number of elements in <FIELDS>!";
00230
00231 field_counts.resize (specified_channel_count);
00232
00233 int offset = 0;
00234 for (int i = 0; i < specified_channel_count; ++i)
00235 {
00236 cloud.fields[i].offset = offset;
00237 int col_count;
00238 sstream >> col_count;
00239 cloud.fields[i].count = col_count;
00240 offset += col_count * field_sizes[i];
00241 }
00242
00243 cloud.point_step = offset;
00244 continue;
00245 }
00246
00247
00248 if (line_type.substr (0, 5) == "WIDTH")
00249 {
00250 sstream >> cloud.width;
00251 if (cloud.point_step != 0)
00252 cloud.row_step = cloud.point_step * cloud.width;
00253 continue;
00254 }
00255
00256
00257 if (line_type.substr (0, 6) == "HEIGHT")
00258 {
00259 sstream >> cloud.height;
00260 continue;
00261 }
00262
00263
00264 if (line_type.substr (0, 9) == "VIEWPOINT")
00265 {
00266 pcd_version = PCD_V7;
00267 if (st.size () < 8)
00268 throw "Not enough number of elements in <VIEWPOINT>! Need 7 values (tx ty tz qw qx qy qz).";
00269
00270 float x, y, z, w;
00271 sstream >> x >> y >> z ;
00272 origin = Eigen::Vector4f (x, y, z, 0.0f);
00273 sstream >> w >> x >> y >> z;
00274 orientation = Eigen::Quaternionf (w, x, y, z);
00275 continue;
00276 }
00277
00278
00279 if (line_type.substr (0, 6) == "POINTS")
00280 {
00281 sstream >> nr_points;
00282
00283 cloud.data.resize (nr_points * cloud.point_step);
00284 continue;
00285 }
00286
00287
00288 if (line_type.substr (0, 4) == "DATA")
00289 {
00290 data_idx = static_cast<int> (fs.tellg ());
00291 if (st.at (1).substr (0, 17) == "binary_compressed")
00292 data_type = 2;
00293 else
00294 if (st.at (1).substr (0, 6) == "binary")
00295 data_type = 1;
00296 continue;
00297 }
00298 break;
00299 }
00300 }
00301 catch (const char *exception)
00302 {
00303 PCL_ERROR ("[pcl::PCDReader::readHeader] %s\n", exception);
00304 fs.close ();
00305 return (-1);
00306 }
00307
00308
00309 if (nr_points == 0)
00310 {
00311 PCL_ERROR ("[pcl::PCDReader::readHeader] No points to read\n");
00312 return (-1);
00313 }
00314
00315
00316 if (cloud.width == 0 && cloud.height == 0)
00317 {
00318 cloud.width = nr_points;
00319 cloud.height = 1;
00320 cloud.row_step = cloud.point_step * cloud.width;
00321 }
00322
00323
00324
00325 if (cloud.height == 0)
00326 {
00327 cloud.height = 1;
00328 PCL_WARN ("[pcl::PCDReader::readHeader] no HEIGHT given, setting to 1 (unorganized).\n");
00329 if (cloud.width == 0)
00330 cloud.width = nr_points;
00331 }
00332 else
00333 {
00334 if (cloud.width == 0 && nr_points != 0)
00335 {
00336 PCL_ERROR ("[pcl::PCDReader::readHeader] HEIGHT given (%d) but no WIDTH!\n", cloud.height);
00337 fs.close ();
00338 return (-1);
00339 }
00340 }
00341
00342 if (int (cloud.width * cloud.height) != nr_points)
00343 {
00344 PCL_ERROR ("[pcl::PCDReader::readHeader] HEIGHT (%d) x WIDTH (%d) != number of points (%d)\n", cloud.height, cloud.width, nr_points);
00345 fs.close ();
00346 return (-1);
00347 }
00348
00349
00350 fs.close ();
00351
00352 return (0);
00353 }
00354
00356 int
00357 pcl::PCDReader::readHeader (const std::string &file_name, sensor_msgs::PointCloud2 &cloud, const int offset)
00358 {
00359
00360 cloud.width = cloud.height = cloud.point_step = cloud.row_step = 0;
00361 cloud.data.clear ();
00362
00363
00364
00365
00366 int nr_points = 0;
00367 std::ifstream fs;
00368 std::string line;
00369
00370 int specified_channel_count = 0;
00371
00372 if (file_name == "" || !boost::filesystem::exists (file_name))
00373 {
00374 PCL_ERROR ("[pcl::PCDReader::readHeader] Could not find file '%s'.\n", file_name.c_str ());
00375 return (-1);
00376 }
00377
00378
00379 fs.open (file_name.c_str (), std::ios::binary);
00380 if (!fs.is_open () || fs.fail ())
00381 {
00382 PCL_ERROR ("[pcl::PCDReader::readHeader] Could not open file '%s'! Error : %s\n", file_name.c_str (), strerror(errno));
00383 fs.close ();
00384 return (-1);
00385 }
00386
00387
00388 fs.seekg (offset, std::ios::beg);
00389
00390
00391
00392 std::vector<int> field_sizes, field_counts;
00393
00394 std::vector<char> field_types;
00395 std::vector<std::string> st;
00396
00397
00398 try
00399 {
00400 while (!fs.eof ())
00401 {
00402 getline (fs, line);
00403
00404 if (line == "")
00405 continue;
00406
00407
00408 boost::trim (line);
00409 boost::split (st, line, boost::is_any_of ("\t\r "), boost::token_compress_on);
00410
00411 std::stringstream sstream (line);
00412 sstream.imbue (std::locale::classic ());
00413
00414 std::string line_type;
00415 sstream >> line_type;
00416
00417
00418 if (line_type.substr (0, 1) == "#")
00419 continue;
00420
00421
00422 if (line_type.substr (0, 7) == "VERSION")
00423 continue;
00424
00425
00426 if ( (line_type.substr (0, 6) == "FIELDS") || (line_type.substr (0, 7) == "COLUMNS") )
00427 {
00428 specified_channel_count = static_cast<int> (st.size () - 1);
00429
00430
00431 cloud.fields.resize (specified_channel_count);
00432 for (int i = 0; i < specified_channel_count; ++i)
00433 {
00434 std::string col_type = st.at (i + 1);
00435 cloud.fields[i].name = col_type;
00436 }
00437
00438
00439 int offset = 0;
00440 for (int i = 0; i < specified_channel_count; ++i, offset += 4)
00441 {
00442 cloud.fields[i].offset = offset;
00443 cloud.fields[i].datatype = sensor_msgs::PointField::FLOAT32;
00444 cloud.fields[i].count = 1;
00445 }
00446 cloud.point_step = offset;
00447 continue;
00448 }
00449
00450
00451 if (line_type.substr (0, 4) == "SIZE")
00452 {
00453 specified_channel_count = static_cast<int> (st.size () - 1);
00454
00455
00456 if (specified_channel_count != static_cast<int> (cloud.fields.size ()))
00457 throw "The number of elements in <SIZE> differs than the number of elements in <FIELDS>!";
00458
00459
00460 field_sizes.resize (specified_channel_count);
00461
00462 int offset = 0;
00463 for (int i = 0; i < specified_channel_count; ++i)
00464 {
00465 int col_type ;
00466 sstream >> col_type;
00467 cloud.fields[i].offset = offset;
00468 offset += col_type;
00469 field_sizes[i] = col_type;
00470 }
00471 cloud.point_step = offset;
00472
00473
00474 continue;
00475 }
00476
00477
00478 if (line_type.substr (0, 4) == "TYPE")
00479 {
00480 if (field_sizes.empty ())
00481 throw "TYPE of FIELDS specified before SIZE in header!";
00482
00483 specified_channel_count = static_cast<int> (st.size () - 1);
00484
00485
00486 if (specified_channel_count != static_cast<int> (cloud.fields.size ()))
00487 throw "The number of elements in <TYPE> differs than the number of elements in <FIELDS>!";
00488
00489
00490 field_types.resize (specified_channel_count);
00491
00492 for (int i = 0; i < specified_channel_count; ++i)
00493 {
00494 field_types[i] = st.at (i + 1).c_str ()[0];
00495 cloud.fields[i].datatype = static_cast<uint8_t> (getFieldType (field_sizes[i], field_types[i]));
00496 }
00497 continue;
00498 }
00499
00500
00501 if (line_type.substr (0, 5) == "COUNT")
00502 {
00503 if (field_sizes.empty () || field_types.empty ())
00504 throw "COUNT of FIELDS specified before SIZE or TYPE in header!";
00505
00506 specified_channel_count = static_cast<int> (st.size () - 1);
00507
00508
00509 if (specified_channel_count != static_cast<int> (cloud.fields.size ()))
00510 throw "The number of elements in <COUNT> differs than the number of elements in <FIELDS>!";
00511
00512 field_counts.resize (specified_channel_count);
00513
00514 int offset = 0;
00515 for (int i = 0; i < specified_channel_count; ++i)
00516 {
00517 cloud.fields[i].offset = offset;
00518 int col_count;
00519 sstream >> col_count;
00520 cloud.fields[i].count = col_count;
00521 offset += col_count * field_sizes[i];
00522 }
00523
00524 cloud.point_step = offset;
00525 continue;
00526 }
00527
00528
00529 if (line_type.substr (0, 5) == "WIDTH")
00530 {
00531 sstream >> cloud.width;
00532 if (cloud.point_step != 0)
00533 cloud.row_step = cloud.point_step * cloud.width;
00534 continue;
00535 }
00536
00537
00538 if (line_type.substr (0, 6) == "HEIGHT")
00539 {
00540 sstream >> cloud.height;
00541 continue;
00542 }
00543
00544
00545 if (line_type.substr (0, 9) == "VIEWPOINT")
00546 {
00547 if (st.size () < 8)
00548 throw "Not enough number of elements in <VIEWPOINT>! Need 7 values (tx ty tz qw qx qy qz).";
00549 continue;
00550 }
00551
00552
00553 if (line_type.substr (0, 6) == "POINTS")
00554 {
00555 sstream >> nr_points;
00556
00557 cloud.data.resize (nr_points * cloud.point_step);
00558 continue;
00559 }
00560 break;
00561 }
00562 }
00563 catch (const char *exception)
00564 {
00565 PCL_ERROR ("[pcl::PCDReader::readHeader] %s\n", exception);
00566 fs.close ();
00567 return (-1);
00568 }
00569
00570
00571 if (nr_points == 0)
00572 {
00573 PCL_ERROR ("[pcl::PCDReader::readHeader] No points to read\n");
00574 return (-1);
00575 }
00576
00577
00578 if (cloud.width == 0 && cloud.height == 0)
00579 {
00580 cloud.width = nr_points;
00581 cloud.height = 1;
00582 cloud.row_step = cloud.point_step * cloud.width;
00583 }
00584
00585
00586
00587 if (cloud.height == 0)
00588 {
00589 cloud.height = 1;
00590 PCL_WARN ("[pcl::PCDReader::readHeader] no HEIGHT given, setting to 1 (unorganized).\n");
00591 if (cloud.width == 0)
00592 cloud.width = nr_points;
00593 }
00594 else
00595 {
00596 if (cloud.width == 0 && nr_points != 0)
00597 {
00598 PCL_ERROR ("[pcl::PCDReader::readHeader] HEIGHT given (%d) but no WIDTH!\n", cloud.height);
00599 fs.close ();
00600 return (-1);
00601 }
00602 }
00603
00604 if (int (cloud.width * cloud.height) != nr_points)
00605 {
00606 PCL_ERROR ("[pcl::PCDReader::readHeader] HEIGHT (%d) x WIDTH (%d) != number of points (%d)\n", cloud.height, cloud.width, nr_points);
00607 fs.close ();
00608 return (-1);
00609 }
00610
00611
00612 fs.close ();
00613
00614 return (0);
00615 }
00616
00618 int
00619 pcl::PCDReader::readHeaderEigen (const std::string &file_name, pcl::PointCloud<Eigen::MatrixXf> &cloud,
00620 int &pcd_version, int &data_type, unsigned int &data_idx, const int offset)
00621 {
00622
00623 data_idx = 0;
00624 data_type = 0;
00625 pcd_version = PCD_V6;
00626 cloud.properties.sensor_origin = Eigen::Vector4f::Zero ();
00627 cloud.properties.sensor_orientation = Eigen::Quaternionf::Identity ();
00628 cloud.width = cloud.height = 0;
00629 cloud.points.resize (0, 0);
00630
00631
00632
00633
00634 int nr_points = 0;
00635 std::ifstream fs;
00636 std::string line;
00637
00638 int specified_channel_count = 0;
00639
00640 if (file_name == "" || !boost::filesystem::exists (file_name))
00641 {
00642 PCL_ERROR ("[pcl::PCDReader::readHeader] Could not find file '%s'.\n", file_name.c_str ());
00643 return (-1);
00644 }
00645
00646
00647 fs.open (file_name.c_str (), std::ios::binary);
00648 if (!fs.is_open () || fs.fail ())
00649 {
00650 PCL_ERROR ("[pcl::PCDReader::readHeader] Could not open file '%s'! Error : %s\n", file_name.c_str (), strerror(errno));
00651 return (-1);
00652 }
00653
00654
00655 fs.seekg (offset, std::ios::beg);
00656
00657
00658
00659 std::vector<int> field_sizes, field_counts;
00660
00661 std::vector<char> field_types;
00662 std::vector<std::string> st;
00663
00664 std::vector<pcl::ChannelProperties> channels;
00665 int total_dimensions = 0;
00666
00667 try
00668 {
00669 while (!fs.eof ())
00670 {
00671 getline (fs, line);
00672
00673 if (line == "")
00674 continue;
00675
00676
00677 boost::trim (line);
00678 boost::split (st, line, boost::is_any_of ("\t\r "), boost::token_compress_on);
00679
00680 std::stringstream sstream (line);
00681 sstream.imbue (std::locale::classic ());
00682
00683 std::string line_type;
00684 sstream >> line_type;
00685
00686
00687 if (line_type.substr (0, 1) == "#")
00688 continue;
00689
00690
00691 if (line_type.substr (0, 7) == "VERSION")
00692 continue;
00693
00694
00695 if ( (line_type.substr (0, 6) == "FIELDS") || (line_type.substr (0, 7) == "COLUMNS") )
00696 {
00697 specified_channel_count = static_cast<int> (st.size () - 1);
00698
00699
00700 channels.resize (specified_channel_count);
00701 for (int i = 0; i < specified_channel_count; ++i)
00702 {
00703 std::string col_type = st.at (i + 1);
00704 channels[i].name = col_type;
00705 channels[i].size = 4;
00706 channels[i].offset = 0;
00707 channels[i].count = 1;
00708 channels[i].datatype = sensor_msgs::PointField::FLOAT32;
00709 }
00710 continue;
00711 }
00712
00713
00714 if (line_type.substr (0, 4) == "SIZE")
00715 {
00716 specified_channel_count = static_cast<int> (st.size () - 1);
00717
00718
00719 if (specified_channel_count != static_cast<int> (channels.size ()))
00720 throw "The number of elements in <SIZE> differs than the number of elements in <FIELDS>!";
00721
00722 for (int i = 0; i < specified_channel_count; ++i)
00723 {
00724 int col_type;
00725 sstream >> col_type;
00726 if (col_type != 4)
00727 PCL_WARN ("[pcl::PCDReader::readHeaderEigen] Casting field size %d to 4.\n", col_type);
00728 }
00729 continue;
00730 }
00731
00732
00733 if (line_type.substr (0, 4) == "TYPE")
00734 {
00735 specified_channel_count = static_cast<int> (st.size () - 1);
00736
00737
00738 if (specified_channel_count != static_cast<int> (channels.size ()))
00739 throw "The number of elements in <TYPE> differs than the number of elements in <FIELDS>!";
00740
00741 for (int i = 0; i < specified_channel_count; ++i)
00742 {
00743 std::string field_type (st.at (i + 1).c_str ());
00744 if (field_type != "F")
00745 PCL_WARN ("[pcl::PCDReader::readHeaderEigen] Casting field type %s to FLOAT.\n", field_type.c_str ());
00746 }
00747 continue;
00748 }
00749
00750
00751 if (line_type.substr (0, 5) == "COUNT")
00752 {
00753 specified_channel_count = static_cast<int> (st.size () - 1);
00754
00755
00756 if (specified_channel_count != static_cast<int> (channels.size ()))
00757 throw "The number of elements in <COUNT> differs than the number of elements in <FIELDS>!";
00758
00759 field_counts.resize (specified_channel_count);
00760
00761 int offset = 0;
00762 for (int i = 0; i < specified_channel_count; ++i)
00763 {
00764 int col_count;
00765 sstream >> col_count;
00766 total_dimensions += col_count;
00767 channels[i].count = col_count;
00768 channels[i].offset = offset;
00769 offset += col_count * 4;
00770 }
00771
00772 for (size_t cc = 0; cc < channels.size (); ++cc)
00773 cloud.channels[channels[cc].name] = channels[cc];
00774 continue;
00775 }
00776
00777
00778 if (line_type.substr (0, 5) == "WIDTH")
00779 {
00780 sstream >> cloud.width;
00781 continue;
00782 }
00783
00784
00785 if (line_type.substr (0, 6) == "HEIGHT")
00786 {
00787 sstream >> cloud.height;
00788 continue;
00789 }
00790
00791
00792 if (line_type.substr (0, 9) == "VIEWPOINT")
00793 {
00794 pcd_version = PCD_V7;
00795 if (st.size () < 8)
00796 throw "Not enough number of elements in <VIEWPOINT>! Need 7 values (tx ty tz qw qx qy qz).";
00797
00798 float x, y, z, w;
00799 sstream >> x >> y >> z ;
00800 cloud.properties.sensor_origin = Eigen::Vector4f (x, y, z, 0.0f);
00801 sstream >> w >> x >> y >> z;
00802 cloud.properties.sensor_orientation = Eigen::Quaternionf (w, x, y, z);
00803 continue;
00804 }
00805
00806
00807 if (line_type.substr (0, 6) == "POINTS")
00808 {
00809 sstream >> nr_points;
00810
00811 int nr_cols = 0;
00812 for (std::map<std::string, pcl::ChannelProperties>::const_iterator it = cloud.channels.begin (); it != cloud.channels.end (); ++it)
00813 nr_cols += it->second.count;
00814
00815 cloud.points.resize (nr_points, nr_cols);
00816 continue;
00817 }
00818
00819
00820 if (line_type.substr (0, 4) == "DATA")
00821 {
00822 data_idx = static_cast<int> (fs.tellg ());
00823 if (st.at (1).substr (0, 17) == "binary_compressed")
00824 data_type = 2;
00825 else
00826 if (st.at (1).substr (0, 6) == "binary")
00827 data_type = 1;
00828 continue;
00829 }
00830 break;
00831 }
00832 }
00833 catch (const char *exception)
00834 {
00835 PCL_ERROR ("[pcl::PCDReader::readHeader] %s\n", exception);
00836 fs.close ();
00837 return (-1);
00838 }
00839
00840
00841 if (cloud.width == 0 && cloud.height == 0)
00842 {
00843 cloud.width = nr_points;
00844 cloud.height = 1;
00845 }
00846
00847
00848
00849 if (cloud.height == 0)
00850 {
00851 cloud.height = 1;
00852 PCL_WARN ("[pcl::PCDReader::readHeader] no HEIGHT given, setting to 1 (unorganized).\n");
00853 if (cloud.width == 0)
00854 cloud.width = nr_points;
00855 }
00856 else
00857 {
00858 if (cloud.width == 0 && nr_points != 0)
00859 {
00860 PCL_ERROR ("[pcl::PCDReader::readHeader] HEIGHT given (%d) but no WIDTH!\n", cloud.height);
00861 fs.close ();
00862 return (-1);
00863 }
00864 }
00865
00866 if (int (cloud.width * cloud.height) != nr_points)
00867 {
00868 PCL_ERROR ("[pcl::PCDReader::readHeader] HEIGHT (%d) x WIDTH (%d) != number of points (%d)\n", cloud.height, cloud.width, nr_points);
00869 fs.close ();
00870 return (-1);
00871 }
00872
00873
00874 fs.close ();
00875
00876 return (0);
00877 }
00878
00880 int
00881 pcl::PCDReader::read (const std::string &file_name, sensor_msgs::PointCloud2 &cloud,
00882 Eigen::Vector4f &origin, Eigen::Quaternionf &orientation, int &pcd_version,
00883 const int offset)
00884 {
00885 int data_type;
00886 unsigned int data_idx;
00887
00888 int res = readHeader (file_name, cloud, origin, orientation, pcd_version, data_type, data_idx, offset);
00889
00890 if (res < 0)
00891 return (res);
00892
00893 unsigned int idx = 0;
00894
00895
00896 unsigned int nr_points = cloud.width * cloud.height;
00897
00898
00899 cloud.is_dense = true;
00900
00901
00902 if (data_type == 0)
00903 {
00904
00905 std::ifstream fs;
00906 fs.open (file_name.c_str ());
00907 if (!fs.is_open () || fs.fail ())
00908 {
00909 PCL_ERROR ("[pcl::PCDReader::read] Could not open file %s.\n", file_name.c_str ());
00910 return (-1);
00911 }
00912
00913 fs.seekg (data_idx);
00914
00915 std::string line;
00916 std::vector<std::string> st;
00917
00918
00919 try
00920 {
00921 while (idx < nr_points && !fs.eof ())
00922 {
00923 getline (fs, line);
00924
00925 if (line == "")
00926 continue;
00927
00928
00929 boost::trim (line);
00930 boost::split (st, line, boost::is_any_of ("\t\r "), boost::token_compress_on);
00931
00932 if (idx >= nr_points)
00933 {
00934 PCL_WARN ("[pcl::PCDReader::read] input file %s has more points (%d) than advertised (%d)!\n", file_name.c_str (), idx, nr_points);
00935 break;
00936 }
00937
00938 size_t total = 0;
00939
00940 for (unsigned int d = 0; d < static_cast<unsigned int> (cloud.fields.size ()); ++d)
00941 {
00942
00943 if (cloud.fields[d].name == "_")
00944 {
00945 total += cloud.fields[d].count;
00946 continue;
00947 }
00948 for (unsigned int c = 0; c < cloud.fields[d].count; ++c)
00949 {
00950 switch (cloud.fields[d].datatype)
00951 {
00952 case sensor_msgs::PointField::INT8:
00953 {
00954 copyStringValue<pcl::traits::asType<sensor_msgs::PointField::INT8>::type> (
00955 st.at (total + c), cloud, idx, d, c);
00956 break;
00957 }
00958 case sensor_msgs::PointField::UINT8:
00959 {
00960 copyStringValue<pcl::traits::asType<sensor_msgs::PointField::UINT8>::type> (
00961 st.at (total + c), cloud, idx, d, c);
00962 break;
00963 }
00964 case sensor_msgs::PointField::INT16:
00965 {
00966 copyStringValue<pcl::traits::asType<sensor_msgs::PointField::INT16>::type> (
00967 st.at (total + c), cloud, idx, d, c);
00968 break;
00969 }
00970 case sensor_msgs::PointField::UINT16:
00971 {
00972 copyStringValue<pcl::traits::asType<sensor_msgs::PointField::UINT16>::type> (
00973 st.at (total + c), cloud, idx, d, c);
00974 break;
00975 }
00976 case sensor_msgs::PointField::INT32:
00977 {
00978 copyStringValue<pcl::traits::asType<sensor_msgs::PointField::INT32>::type> (
00979 st.at (total + c), cloud, idx, d, c);
00980 break;
00981 }
00982 case sensor_msgs::PointField::UINT32:
00983 {
00984 copyStringValue<pcl::traits::asType<sensor_msgs::PointField::UINT32>::type> (
00985 st.at (total + c), cloud, idx, d, c);
00986 break;
00987 }
00988 case sensor_msgs::PointField::FLOAT32:
00989 {
00990 copyStringValue<pcl::traits::asType<sensor_msgs::PointField::FLOAT32>::type> (
00991 st.at (total + c), cloud, idx, d, c);
00992 break;
00993 }
00994 case sensor_msgs::PointField::FLOAT64:
00995 {
00996 copyStringValue<pcl::traits::asType<sensor_msgs::PointField::FLOAT64>::type> (
00997 st.at (total + c), cloud, idx, d, c);
00998 break;
00999 }
01000 default:
01001 PCL_WARN ("[pcl::PCDReader::read] Incorrect field data type specified (%d)!\n",cloud.fields[d].datatype);
01002 break;
01003 }
01004 }
01005 total += cloud.fields[d].count;
01006 }
01007 idx++;
01008 }
01009 }
01010 catch (const char *exception)
01011 {
01012 PCL_ERROR ("[pcl::PCDReader::read] %s\n", exception);
01013 return (-1);
01014 }
01015
01016
01017 fs.close ();
01018
01019 }
01020 else
01023 {
01024
01025 int fd = pcl_open (file_name.c_str (), O_RDONLY);
01026 if (fd == -1)
01027 {
01028 PCL_ERROR ("[pcl::PCDReader::read] Failure to open file %s\n", file_name.c_str () );
01029 return (-1);
01030 }
01031
01032
01033 int result = static_cast<int> (pcl_lseek (fd, offset, SEEK_SET));
01034 if (result < 0)
01035 {
01036 pcl_close (fd);
01037 PCL_ERROR ("[pcl::PCDReader::read] Error during lseek ()!\n");
01038 return (-1);
01039 }
01040
01041 size_t data_size = data_idx + cloud.data.size ();
01042
01043 #ifdef _WIN32
01044
01045
01046
01047 HANDLE fm = CreateFileMapping ((HANDLE) _get_osfhandle (fd), NULL, PAGE_READONLY, 0, 0, NULL);
01048
01049
01050 char *map = static_cast<char*>(MapViewOfFile (fm, FILE_MAP_READ, 0, 0, 0));
01051 if (map == NULL)
01052 {
01053 CloseHandle (fm);
01054 pcl_close (fd);
01055 PCL_ERROR ("[pcl::PCDReader::read] Error mapping view of file, %s\n", file_name.c_str ());
01056 return (-1);
01057 }
01058 #else
01059 char *map = static_cast<char*> (mmap (0, data_size, PROT_READ, MAP_SHARED, fd, 0));
01060 if (map == reinterpret_cast<char*> (-1))
01061 {
01062 pcl_close (fd);
01063 PCL_ERROR ("[pcl::PCDReader::read] Error preparing mmap for binary PCD file.\n");
01064 return (-1);
01065 }
01066 #endif
01067
01069 if (data_type == 2)
01070 {
01071
01072 unsigned int compressed_size, uncompressed_size;
01073 memcpy (&compressed_size, &map[data_idx + 0], sizeof (unsigned int));
01074 memcpy (&uncompressed_size, &map[data_idx + 4], sizeof (unsigned int));
01075 PCL_DEBUG ("[pcl::PCDReader::read] Read a binary compressed file with %u bytes compressed and %u original.\n", compressed_size, uncompressed_size);
01076
01077
01078 if (data_size < compressed_size)
01079 {
01080 #if _WIN32
01081 UnmapViewOfFile (map);
01082 data_size = compressed_size;
01083 map = static_cast<char*>(MapViewOfFile (fm, FILE_MAP_READ, 0, 0, data_size));
01084 #else
01085 munmap (map, data_size);
01086 data_size = compressed_size;
01087 map = static_cast<char*> (mmap (0, data_size, PROT_READ, MAP_SHARED, fd, 0));
01088 #endif
01089 }
01090
01091 if (uncompressed_size != cloud.data.size ())
01092 {
01093 PCL_WARN ("[pcl::PCDReader::read] The estimated cloud.data size (%u) is different than the saved uncompressed value (%u)! Data corruption?\n",
01094 cloud.data.size (), uncompressed_size);
01095 cloud.data.resize (uncompressed_size);
01096 }
01097
01098 char *buf = static_cast<char*> (malloc (data_size));
01099
01100 if (pcl::lzfDecompress (&map[data_idx + 8], compressed_size, buf, static_cast<unsigned int> (data_size)) != uncompressed_size)
01101 {
01102 free (buf);
01103 pcl_close (fd);
01104 PCL_ERROR ("[pcl::PCDReader::read] Size of decompressed lzf data does not match value stored in PCD header\n");
01105 return (-1);
01106 }
01107
01108
01109 std::vector<sensor_msgs::PointField> fields (cloud.fields.size ());
01110 std::vector<int> fields_sizes (cloud.fields.size ());
01111 int nri = 0, fsize = 0;
01112 for (size_t i = 0; i < cloud.fields.size (); ++i)
01113 {
01114 if (cloud.fields[i].name == "_")
01115 continue;
01116 fields_sizes[nri] = cloud.fields[i].count * pcl::getFieldSize (cloud.fields[i].datatype);
01117 fsize += fields_sizes[nri];
01118 fields[nri] = cloud.fields[i];
01119 ++nri;
01120 }
01121 fields.resize (nri);
01122 fields_sizes.resize (nri);
01123
01124
01125 std::vector<char*> pters (fields.size ());
01126 int toff = 0;
01127 for (size_t i = 0; i < pters.size (); ++i)
01128 {
01129 pters[i] = &buf[toff];
01130 toff += fields_sizes[i] * cloud.width * cloud.height;
01131 }
01132
01133 for (size_t i = 0; i < cloud.width * cloud.height; ++i)
01134 {
01135 for (size_t j = 0; j < pters.size (); ++j)
01136 {
01137 memcpy (&cloud.data[i * fsize + fields[j].offset], pters[j], fields_sizes[j]);
01138
01139 pters[j] += fields_sizes[j];
01140 }
01141 }
01142
01143
01144 free (buf);
01145 }
01146 else
01147
01148 memcpy (&cloud.data[0], &map[0] + data_idx, cloud.data.size ());
01149
01150
01151 #if _WIN32
01152 UnmapViewOfFile (map);
01153 CloseHandle (fm);
01154 #else
01155 if (munmap (map, data_size) == -1)
01156 {
01157 pcl_close (fd);
01158 PCL_ERROR ("[pcl::PCDReader::read] Munmap failure\n");
01159 return (-1);
01160 }
01161 #endif
01162 pcl_close (fd);
01163 }
01164
01165 if ((idx != nr_points) && (data_type == 0))
01166 {
01167 PCL_ERROR ("[pcl::PCDReader::read] Number of points read (%d) is different than expected (%d)\n", idx, nr_points);
01168 return (-1);
01169 }
01170
01171
01172 if (data_type == 0)
01173 return (0);
01174
01175 int point_size = static_cast<int> (cloud.data.size () / (cloud.height * cloud.width));
01176
01177 for (uint32_t i = 0; i < cloud.width * cloud.height; ++i)
01178 {
01179 for (unsigned int d = 0; d < static_cast<unsigned int> (cloud.fields.size ()); ++d)
01180 {
01181 for (uint32_t c = 0; c < cloud.fields[d].count; ++c)
01182 {
01183 switch (cloud.fields[d].datatype)
01184 {
01185 case sensor_msgs::PointField::INT8:
01186 {
01187 if (!isValueFinite<pcl::traits::asType<sensor_msgs::PointField::INT8>::type>(cloud, i, point_size, d, c))
01188 cloud.is_dense = false;
01189 break;
01190 }
01191 case sensor_msgs::PointField::UINT8:
01192 {
01193 if (!isValueFinite<pcl::traits::asType<sensor_msgs::PointField::UINT8>::type>(cloud, i, point_size, d, c))
01194 cloud.is_dense = false;
01195 break;
01196 }
01197 case sensor_msgs::PointField::INT16:
01198 {
01199 if (!isValueFinite<pcl::traits::asType<sensor_msgs::PointField::INT16>::type>(cloud, i, point_size, d, c))
01200 cloud.is_dense = false;
01201 break;
01202 }
01203 case sensor_msgs::PointField::UINT16:
01204 {
01205 if (!isValueFinite<pcl::traits::asType<sensor_msgs::PointField::UINT16>::type>(cloud, i, point_size, d, c))
01206 cloud.is_dense = false;
01207 break;
01208 }
01209 case sensor_msgs::PointField::INT32:
01210 {
01211 if (!isValueFinite<pcl::traits::asType<sensor_msgs::PointField::INT32>::type>(cloud, i, point_size, d, c))
01212 cloud.is_dense = false;
01213 break;
01214 }
01215 case sensor_msgs::PointField::UINT32:
01216 {
01217 if (!isValueFinite<pcl::traits::asType<sensor_msgs::PointField::UINT32>::type>(cloud, i, point_size, d, c))
01218 cloud.is_dense = false;
01219 break;
01220 }
01221 case sensor_msgs::PointField::FLOAT32:
01222 {
01223 if (!isValueFinite<pcl::traits::asType<sensor_msgs::PointField::FLOAT32>::type>(cloud, i, point_size, d, c))
01224 cloud.is_dense = false;
01225 break;
01226 }
01227 case sensor_msgs::PointField::FLOAT64:
01228 {
01229 if (!isValueFinite<pcl::traits::asType<sensor_msgs::PointField::FLOAT64>::type>(cloud, i, point_size, d, c))
01230 cloud.is_dense = false;
01231 break;
01232 }
01233 }
01234 }
01235 }
01236 }
01237
01238 return (0);
01239 }
01240
01242 int
01243 pcl::PCDReader::readEigen (const std::string &file_name, pcl::PointCloud<Eigen::MatrixXf> &cloud,
01244 const int offset)
01245 {
01246 int data_type;
01247 unsigned int data_idx;
01248 int pcd_version;
01249 int res = readHeaderEigen (file_name, cloud, pcd_version, data_type, data_idx);
01250
01251 if (res < 0)
01252 return (res);
01253
01254 int idx = 0;
01255
01256
01257 int nr_points = cloud.width * cloud.height;
01258
01259
01260 cloud.is_dense = true;
01261
01262
01263 if (data_type == 0)
01264 {
01265
01266 std::ifstream fs;
01267 fs.open (file_name.c_str ());
01268 if (!fs.is_open () || fs.fail ())
01269 {
01270 PCL_ERROR ("[pcl::PCDReader::read] Could not open file %s.\n", file_name.c_str ());
01271 return (-1);
01272 }
01273
01274 fs.seekg (data_idx);
01275
01276 std::string line;
01277 std::vector<std::string> st;
01278
01279
01280 try
01281 {
01282 while (idx < nr_points && !fs.eof ())
01283 {
01284 getline (fs, line);
01285
01286 if (line == "")
01287 continue;
01288
01289
01290 boost::trim (line);
01291 boost::split (st, line, boost::is_any_of ("\t\r "), boost::token_compress_on);
01292
01293 std::stringstream sstream (line);
01294 sstream.imbue (std::locale::classic ());
01295
01296 if (idx >= nr_points)
01297 {
01298 PCL_WARN ("[pcl::PCDReader::read] input file %s has more points than advertised (%d)!\n", file_name.c_str (), nr_points);
01299 break;
01300 }
01301
01302 for (size_t i = 0; i < st.size (); ++i)
01303 sstream >> cloud.points (idx, i);
01304 idx++;
01305 }
01306 }
01307 catch (const char *exception)
01308 {
01309 PCL_ERROR ("[pcl::PCDReader::readEigen] %s\n", exception);
01310 return (-1);
01311 }
01312
01313
01314 fs.close ();
01315
01316 }
01317 else
01320 {
01321
01322 int fd = pcl_open (file_name.c_str (), O_RDONLY);
01323 if (fd == -1)
01324 {
01325 PCL_ERROR ("[pcl::PCDReader::readEigen] Failure to open file %s\n", file_name.c_str () );
01326 return (-1);
01327 }
01328
01329
01330
01331 int result = static_cast<int> (pcl_lseek (fd, offset, SEEK_SET));
01332 if (result < 0)
01333 {
01334 pcl_close (fd);
01335 PCL_ERROR ("[pcl::PCDReader::readEigen] Error during lseek ()!\n");
01336 return (-1);
01337 }
01338
01339 size_t data_size = data_idx + cloud.points.rows () * cloud.points.cols () * sizeof (float);
01340
01341 #ifdef _WIN32
01342
01343
01344
01345 HANDLE fm = CreateFileMapping ((HANDLE) _get_osfhandle (fd), NULL, PAGE_READONLY, 0, 0, NULL);
01346
01347
01348 char *map = static_cast<char*>(MapViewOfFile (fm, FILE_MAP_READ, 0, 0, 0));
01349 if (map == NULL)
01350 {
01351 CloseHandle (fm);
01352 pcl_close (fd);
01353 PCL_ERROR ("[pcl::PCDReader::readEigen] Error mapping view of file\n");
01354 return (-1);
01355 }
01356 #else
01357 char *map = static_cast<char*> (mmap (0, data_size, PROT_READ, MAP_SHARED, fd, 0));
01358 if (map == reinterpret_cast<char*> (-1))
01359 {
01360 pcl_close (fd);
01361 PCL_ERROR ("[pcl::PCDReader::readEigen] Error preparing mmap for binary PCD file.\n");
01362 return (-1);
01363 }
01364 #endif
01365
01367 if (data_type == 2)
01368 throw pcl::IOException ("[pcl::PCDReader::readEigen] PCD binary_compressed mode not implemented for Eigen::MatrixXf!");
01369 else
01370 {
01371
01372 if (cloud.points.Flags & Eigen::RowMajorBit)
01373 memcpy (&cloud.points.coeffRef (0), &map[0] + data_idx, cloud.points.cols () * cloud.points.rows () * sizeof (float));
01374
01375 else
01376 {
01377 Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> pts (cloud.points.rows (), cloud.points.cols ());
01378 memcpy (&pts.coeffRef (0), &map[0] + data_idx, cloud.points.cols () * cloud.points.rows () * sizeof (float));
01379 pts.transposeInPlace ();
01380 memcpy (&cloud.points.coeffRef (0), &pts.coeffRef (0), cloud.points.cols () * cloud.points.rows () * sizeof (float));
01381 }
01382 }
01383
01384
01385 #if _WIN32
01386 UnmapViewOfFile (map);
01387 CloseHandle (fm);
01388 #else
01389 if (munmap (map, data_size) == -1)
01390 {
01391 pcl_close (fd);
01392 PCL_ERROR ("[pcl::PCDReader::readEigen] Error during munmap ()!\n");
01393 return (-1);
01394 }
01395 #endif
01396 pcl_close (fd);
01397 }
01398
01399 if ((idx != nr_points) && (data_type == 0))
01400 {
01401 PCL_ERROR ("[pcl::PCDReader::readEigen] Number of points read (%d) is different than expected (%d)\n", idx, nr_points);
01402 return (-1);
01403 }
01404
01405
01406 if (data_type == 0)
01407 return (0);
01408
01409
01410 for (int i = 0; i < cloud.points.rows (); ++i)
01411 {
01412 for (int j = 0; j < cloud.points.cols (); ++j)
01413 {
01414 if (!pcl_isfinite (cloud.points (i, j)))
01415 {
01416 cloud.is_dense = false;
01417 break;
01418 }
01419 }
01420 }
01421
01422 return (0);
01423 }
01424
01426 int
01427 pcl::PCDReader::read (const std::string &file_name, sensor_msgs::PointCloud2 &cloud, const int offset)
01428 {
01429 int pcd_version;
01430 Eigen::Vector4f origin;
01431 Eigen::Quaternionf orientation;
01432
01433 int res = read (file_name, cloud, origin, orientation, pcd_version, offset);
01434
01435 if (res < 0)
01436 return (res);
01437
01438 return (0);
01439 }
01440
01442 std::string
01443 pcl::PCDWriter::generateHeaderASCII (const sensor_msgs::PointCloud2 &cloud,
01444 const Eigen::Vector4f &origin, const Eigen::Quaternionf &orientation)
01445 {
01446 std::ostringstream oss;
01447 oss.imbue (std::locale::classic ());
01448
01449 oss << "# .PCD v0.7 - Point Cloud Data file format"
01450 "\nVERSION 0.7"
01451 "\nFIELDS ";
01452
01453 std::ostringstream stream;
01454 stream.imbue (std::locale::classic ());
01455 std::string result;
01456
01457 for (size_t d = 0; d < cloud.fields.size () - 1; ++d)
01458 {
01459
01460 if (cloud.fields[d].name != "_")
01461 result += cloud.fields[d].name + " ";
01462 }
01463
01464 if (cloud.fields[cloud.fields.size () - 1].name != "_")
01465 result += cloud.fields[cloud.fields.size () - 1].name;
01466
01467
01468 boost::trim (result);
01469 oss << result << "\nSIZE ";
01470
01471 stream.str ("");
01472
01473 for (size_t d = 0; d < cloud.fields.size () - 1; ++d)
01474 {
01475
01476 if (cloud.fields[d].name != "_")
01477 stream << pcl::getFieldSize (cloud.fields[d].datatype) << " ";
01478 }
01479
01480 if (cloud.fields[cloud.fields.size () - 1].name != "_")
01481 stream << pcl::getFieldSize (cloud.fields[cloud.fields.size () - 1].datatype);
01482
01483
01484 result = stream.str ();
01485 boost::trim (result);
01486 oss << result << "\nTYPE ";
01487
01488 stream.str ("");
01489
01490 for (size_t d = 0; d < cloud.fields.size () - 1; ++d)
01491 {
01492
01493 if (cloud.fields[d].name != "_")
01494 stream << pcl::getFieldType (cloud.fields[d].datatype) << " ";
01495 }
01496
01497 if (cloud.fields[cloud.fields.size () - 1].name != "_")
01498 stream << pcl::getFieldType (cloud.fields[cloud.fields.size () - 1].datatype);
01499
01500
01501 result = stream.str ();
01502 boost::trim (result);
01503 oss << result << "\nCOUNT ";
01504
01505 stream.str ("");
01506
01507 for (size_t d = 0; d < cloud.fields.size () - 1; ++d)
01508 {
01509
01510 if (cloud.fields[d].name == "_")
01511 continue;
01512 int count = abs (static_cast<int> (cloud.fields[d].count));
01513 if (count == 0)
01514 count = 1;
01515
01516 stream << count << " ";
01517 }
01518
01519 if (cloud.fields[cloud.fields.size () - 1].name != "_")
01520 {
01521 int count = abs (static_cast<int> (cloud.fields[cloud.fields.size () - 1].count));
01522 if (count == 0)
01523 count = 1;
01524
01525 stream << count;
01526 }
01527
01528
01529 result = stream.str ();
01530 boost::trim (result);
01531 oss << result << "\nWIDTH " << cloud.width << "\nHEIGHT " << cloud.height << "\n";
01532
01533 oss << "VIEWPOINT " << origin[0] << " " << origin[1] << " " << origin[2] << " " << orientation.w () << " " <<
01534 orientation.x () << " " << orientation.y () << " " << orientation.z () << "\n";
01535
01536 oss << "POINTS " << cloud.width * cloud.height << "\n";
01537
01538 return (oss.str ());
01539 }
01540
01542 std::string
01543 pcl::PCDWriter::generateHeaderBinary (const sensor_msgs::PointCloud2 &cloud,
01544 const Eigen::Vector4f &origin, const Eigen::Quaternionf &orientation)
01545 {
01546 std::ostringstream oss;
01547 oss.imbue (std::locale::classic ());
01548
01549 oss << "# .PCD v0.7 - Point Cloud Data file format"
01550 "\nVERSION 0.7"
01551 "\nFIELDS";
01552
01553
01554 unsigned int fsize = 0;
01555 for (size_t i = 0; i < cloud.fields.size (); ++i)
01556 fsize += cloud.fields[i].count * getFieldSize (cloud.fields[i].datatype);
01557
01558
01559 if (fsize > cloud.point_step)
01560 {
01561 PCL_ERROR ("[pcl::PCDWriter::generateHeaderBinary] The size of the fields (%d) is larger than point_step (%d)! Something is wrong here...\n", fsize, cloud.point_step);
01562 return ("");
01563 }
01564
01565 std::stringstream field_names, field_types, field_sizes, field_counts;
01566
01567 unsigned int toffset = 0;
01568 for (size_t i = 0; i < cloud.fields.size (); ++i)
01569 {
01570
01571 if (toffset != cloud.fields[i].offset)
01572 {
01573
01574 int fake_offset = (i == 0) ?
01575
01576 (cloud.fields[i].offset)
01577 :
01578
01579 (cloud.fields[i].offset -
01580 (cloud.fields[i-1].offset +
01581 cloud.fields[i-1].count * getFieldSize (cloud.fields[i].datatype)));
01582
01583 toffset += fake_offset;
01584
01585 field_names << " _";
01586 field_sizes << " 1";
01587 field_types << " U";
01588 field_counts << " " << fake_offset;
01589 }
01590
01591
01592 toffset += cloud.fields[i].count * getFieldSize (cloud.fields[i].datatype);
01593 field_names << " " << cloud.fields[i].name;
01594 field_sizes << " " << pcl::getFieldSize (cloud.fields[i].datatype);
01595 field_types << " " << pcl::getFieldType (cloud.fields[i].datatype);
01596 int count = abs (static_cast<int> (cloud.fields[i].count));
01597 if (count == 0) count = 1;
01598 field_counts << " " << count;
01599 }
01600
01601 if (toffset < cloud.point_step)
01602 {
01603 field_names << " _";
01604 field_sizes << " 1";
01605 field_types << " U";
01606 field_counts << " " << (cloud.point_step - toffset);
01607 }
01608 oss << field_names.str ();
01609 oss << "\nSIZE" << field_sizes.str ()
01610 << "\nTYPE" << field_types.str ()
01611 << "\nCOUNT" << field_counts.str ();
01612 oss << "\nWIDTH " << cloud.width << "\nHEIGHT " << cloud.height << "\n";
01613
01614 oss << "VIEWPOINT " << origin[0] << " " << origin[1] << " " << origin[2] << " " << orientation.w () << " " <<
01615 orientation.x () << " " << orientation.y () << " " << orientation.z () << "\n";
01616
01617 oss << "POINTS " << cloud.width * cloud.height << "\n";
01618
01619 return (oss.str ());
01620 }
01621
01623 std::string
01624 pcl::PCDWriter::generateHeaderBinaryCompressed (const sensor_msgs::PointCloud2 &cloud,
01625 const Eigen::Vector4f &origin,
01626 const Eigen::Quaternionf &orientation)
01627 {
01628 std::ostringstream oss;
01629 oss.imbue (std::locale::classic ());
01630
01631 oss << "# .PCD v0.7 - Point Cloud Data file format"
01632 "\nVERSION 0.7"
01633 "\nFIELDS";
01634
01635
01636 unsigned int fsize = 0;
01637 for (size_t i = 0; i < cloud.fields.size (); ++i)
01638 fsize += cloud.fields[i].count * getFieldSize (cloud.fields[i].datatype);
01639
01640
01641 if (fsize > cloud.point_step)
01642 {
01643 PCL_ERROR ("[pcl::PCDWriter::generateHeaderBinaryCompressed] The size of the fields (%d) is larger than point_step (%d)! Something is wrong here...\n", fsize, cloud.point_step);
01644 return ("");
01645 }
01646
01647 std::stringstream field_names, field_types, field_sizes, field_counts;
01648
01649 for (size_t i = 0; i < cloud.fields.size (); ++i)
01650 {
01651 if (cloud.fields[i].name == "_")
01652 continue;
01653
01654 field_names << " " << cloud.fields[i].name;
01655 field_sizes << " " << pcl::getFieldSize (cloud.fields[i].datatype);
01656 field_types << " " << pcl::getFieldType (cloud.fields[i].datatype);
01657 int count = abs (static_cast<int> (cloud.fields[i].count));
01658 if (count == 0) count = 1;
01659 field_counts << " " << count;
01660 }
01661 oss << field_names.str ();
01662 oss << "\nSIZE" << field_sizes.str ()
01663 << "\nTYPE" << field_types.str ()
01664 << "\nCOUNT" << field_counts.str ();
01665 oss << "\nWIDTH " << cloud.width << "\nHEIGHT " << cloud.height << "\n";
01666
01667 oss << "VIEWPOINT " << origin[0] << " " << origin[1] << " " << origin[2] << " " << orientation.w () << " " <<
01668 orientation.x () << " " << orientation.y () << " " << orientation.z () << "\n";
01669
01670 oss << "POINTS " << cloud.width * cloud.height << "\n";
01671
01672 return (oss.str ());
01673 }
01674
01676 int
01677 pcl::PCDWriter::writeASCII (const std::string &file_name, const sensor_msgs::PointCloud2 &cloud,
01678 const Eigen::Vector4f &origin, const Eigen::Quaternionf &orientation,
01679 const int precision)
01680 {
01681 if (cloud.data.empty ())
01682 {
01683 PCL_ERROR ("[pcl::PCDWriter::writeASCII] Input point cloud has no data!\n");
01684 return (-1);
01685 }
01686
01687 std::ofstream fs;
01688 fs.precision (precision);
01689 fs.imbue (std::locale::classic ());
01690 fs.open (file_name.c_str ());
01691 if (!fs.is_open () || fs.fail ())
01692 {
01693 PCL_ERROR("[pcl::PCDWriter::writeASCII] Could not open file '%s' for writing! Error : %s\n", file_name.c_str (), strerror(errno));
01694 return (-1);
01695 }
01696
01697 int nr_points = cloud.width * cloud.height;
01698 int point_size = static_cast<int> (cloud.data.size () / nr_points);
01699
01700
01701 fs << generateHeaderASCII (cloud, origin, orientation) << "DATA ascii\n";
01702
01703 std::ostringstream stream;
01704 stream.precision (precision);
01705 stream.imbue (std::locale::classic ());
01706
01707
01708 for (int i = 0; i < nr_points; ++i)
01709 {
01710 for (unsigned int d = 0; d < static_cast<unsigned int> (cloud.fields.size ()); ++d)
01711 {
01712
01713 if (cloud.fields[d].name == "_")
01714 continue;
01715
01716 int count = cloud.fields[d].count;
01717 if (count == 0)
01718 count = 1;
01719
01720 for (int c = 0; c < count; ++c)
01721 {
01722 switch (cloud.fields[d].datatype)
01723 {
01724 case sensor_msgs::PointField::INT8:
01725 {
01726 copyValueString<pcl::traits::asType<sensor_msgs::PointField::INT8>::type>(cloud, i, point_size, d, c, stream);
01727 break;
01728 }
01729 case sensor_msgs::PointField::UINT8:
01730 {
01731 copyValueString<pcl::traits::asType<sensor_msgs::PointField::UINT8>::type>(cloud, i, point_size, d, c, stream);
01732 break;
01733 }
01734 case sensor_msgs::PointField::INT16:
01735 {
01736 copyValueString<pcl::traits::asType<sensor_msgs::PointField::INT16>::type>(cloud, i, point_size, d, c, stream);
01737 break;
01738 }
01739 case sensor_msgs::PointField::UINT16:
01740 {
01741 copyValueString<pcl::traits::asType<sensor_msgs::PointField::UINT16>::type>(cloud, i, point_size, d, c, stream);
01742 break;
01743 }
01744 case sensor_msgs::PointField::INT32:
01745 {
01746 copyValueString<pcl::traits::asType<sensor_msgs::PointField::INT32>::type>(cloud, i, point_size, d, c, stream);
01747 break;
01748 }
01749 case sensor_msgs::PointField::UINT32:
01750 {
01751 copyValueString<pcl::traits::asType<sensor_msgs::PointField::UINT32>::type>(cloud, i, point_size, d, c, stream);
01752 break;
01753 }
01754 case sensor_msgs::PointField::FLOAT32:
01755 {
01756 copyValueString<pcl::traits::asType<sensor_msgs::PointField::FLOAT32>::type>(cloud, i, point_size, d, c, stream);
01757 break;
01758 }
01759 case sensor_msgs::PointField::FLOAT64:
01760 {
01761 copyValueString<pcl::traits::asType<sensor_msgs::PointField::FLOAT64>::type>(cloud, i, point_size, d, c, stream);
01762 break;
01763 }
01764 default:
01765 PCL_WARN ("[pcl::PCDWriter::writeASCII] Incorrect field data type specified (%d)!\n", cloud.fields[d].datatype);
01766 break;
01767 }
01768
01769 if (d < cloud.fields.size () - 1 || c < static_cast<int> (cloud.fields[d].count) - 1)
01770 stream << " ";
01771 }
01772 }
01773
01774 std::string result = stream.str ();
01775 boost::trim (result);
01776 stream.str ("");
01777 fs << result << "\n";
01778 }
01779 fs.close ();
01780 return (0);
01781 }
01782
01784 int
01785 pcl::PCDWriter::writeBinary (const std::string &file_name, const sensor_msgs::PointCloud2 &cloud,
01786 const Eigen::Vector4f &origin, const Eigen::Quaternionf &orientation)
01787 {
01788 if (cloud.data.empty ())
01789 {
01790 PCL_ERROR ("[pcl::PCDWriter::writeBinary] Input point cloud has no data!\n");
01791 return (-1);
01792 }
01793 std::streamoff data_idx = 0;
01794 std::ostringstream oss;
01795 oss.imbue (std::locale::classic ());
01796
01797 oss << generateHeaderBinary (cloud, origin, orientation) << "DATA binary\n";
01798 oss.flush();
01799 data_idx = static_cast<unsigned int> (oss.tellp ());
01800
01801 #if _WIN32
01802 HANDLE h_native_file = CreateFile (file_name.c_str (), GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
01803 if(h_native_file == INVALID_HANDLE_VALUE)
01804 {
01805 PCL_ERROR ("[pcl::PCDWriter::writeBinary] Error during CreateFile (%s)!\n", file_name.c_str());
01806 return (-1);
01807 }
01808 #else
01809 int fd = pcl_open (file_name.c_str (), O_RDWR | O_CREAT | O_TRUNC, static_cast<mode_t> (0600));
01810 if (fd < 0)
01811 {
01812 PCL_ERROR ("[pcl::PCDWriter::writeBinary] Error during open (%s)!\n", file_name.c_str());
01813 return (-1);
01814 }
01815
01816 int result = static_cast<int> (pcl_lseek (fd, getpagesize () + cloud.data.size () - 1, SEEK_SET));
01817 if (result < 0)
01818 {
01819 pcl_close (fd);
01820 PCL_ERROR ("[pcl::PCDWriter::writeBinary] Error during lseek ()!\n");
01821 return (-1);
01822 }
01823
01824 result = static_cast<int> (::write (fd, "", 1));
01825 if (result != 1)
01826 {
01827 pcl_close (fd);
01828 PCL_ERROR ("[pcl::PCDWriter::writeBinary] Error during write ()!\n");
01829 return (-1);
01830 }
01831 #endif
01832
01833 #ifdef _WIN32
01834 HANDLE fm = CreateFileMapping (h_native_file, NULL, PAGE_READWRITE, 0, (DWORD) (data_idx + cloud.data.size ()), NULL);
01835 char *map = static_cast<char*>(MapViewOfFile (fm, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, data_idx + cloud.data.size ()));
01836 CloseHandle (fm);
01837
01838 #else
01839 char *map = static_cast<char*> (mmap (0, static_cast<size_t> (data_idx + cloud.data.size ()), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));
01840 if (map == reinterpret_cast<char*> (-1))
01841 {
01842 pcl_close (fd);
01843 PCL_ERROR ("[pcl::PCDWriter::writeBinary] Error during mmap ()!\n");
01844 return (-1);
01845 }
01846 #endif
01847
01848
01849 memcpy (&map[0], oss.str().c_str (), static_cast<size_t> (data_idx));
01850
01851
01852 memcpy (&map[0] + data_idx, &cloud.data[0], cloud.data.size ());
01853
01854 #if !_WIN32
01855
01856 if (map_synchronization_)
01857 msync (map, static_cast<size_t> (data_idx + cloud.data.size ()), MS_SYNC);
01858 #endif
01859
01860
01861 #if _WIN32
01862 UnmapViewOfFile (map);
01863 #else
01864 if (munmap (map, static_cast<size_t> (data_idx + cloud.data.size ())) == -1)
01865 {
01866 pcl_close (fd);
01867 PCL_ERROR ("[pcl::PCDWriter::writeBinary] Error during munmap ()!\n");
01868 return (-1);
01869 }
01870 #endif
01871
01872 #if _WIN32
01873 CloseHandle(h_native_file);
01874 #else
01875 pcl_close (fd);
01876 #endif
01877 return (0);
01878 }
01879
01881 int
01882 pcl::PCDWriter::writeBinaryCompressed (const std::string &file_name, const sensor_msgs::PointCloud2 &cloud,
01883 const Eigen::Vector4f &origin, const Eigen::Quaternionf &orientation)
01884 {
01885 if (cloud.data.empty ())
01886 {
01887 PCL_ERROR ("[pcl::PCDWriter::writeBinaryCompressed] Input point cloud has no data!\n");
01888 return (-1);
01889 }
01890 std::streamoff data_idx = 0;
01891 std::ostringstream oss;
01892 oss.imbue (std::locale::classic ());
01893
01894 oss << generateHeaderBinaryCompressed (cloud, origin, orientation) << "DATA binary_compressed\n";
01895 oss.flush ();
01896 data_idx = oss.tellp ();
01897
01898 #if _WIN32
01899 HANDLE h_native_file = CreateFile (file_name.c_str (), GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
01900 if(h_native_file == INVALID_HANDLE_VALUE)
01901 {
01902 PCL_ERROR ("[pcl::PCDWriter::writeBinaryCompressed] Error during CreateFile (%s)!\n", file_name.c_str());
01903 return (-1);
01904 }
01905 #else
01906 int fd = pcl_open (file_name.c_str (), O_RDWR | O_CREAT | O_TRUNC, static_cast<mode_t> (0600));
01907 if (fd < 0)
01908 {
01909 PCL_ERROR ("[pcl::PCDWriter::writeBinaryCompressed] Error during open (%s)!\n", file_name.c_str());
01910 return (-1);
01911 }
01912 #endif
01913
01914 size_t fsize = 0;
01915 size_t data_size = 0;
01916 size_t nri = 0;
01917 std::vector<sensor_msgs::PointField> fields (cloud.fields.size ());
01918 std::vector<int> fields_sizes (cloud.fields.size ());
01919
01920 for (size_t i = 0; i < cloud.fields.size (); ++i)
01921 {
01922 if (cloud.fields[i].name == "_")
01923 continue;
01924
01925 fields_sizes[nri] = cloud.fields[i].count * pcl::getFieldSize (cloud.fields[i].datatype);
01926 fsize += fields_sizes[nri];
01927 fields[nri] = cloud.fields[i];
01928 ++nri;
01929 }
01930 fields_sizes.resize (nri);
01931 fields.resize (nri);
01932
01933
01934 data_size = cloud.width * cloud.height * fsize;
01935
01937
01938
01939
01940
01941 char *only_valid_data = static_cast<char*> (malloc (data_size));
01942
01943
01944
01945
01946
01947
01948
01949
01950
01951 std::vector<char*> pters (fields.size ());
01952 int toff = 0;
01953 for (size_t i = 0; i < pters.size (); ++i)
01954 {
01955 pters[i] = &only_valid_data[toff];
01956 toff += fields_sizes[i] * cloud.width * cloud.height;
01957 }
01958
01959
01960 for (size_t i = 0; i < cloud.width * cloud.height; ++i)
01961 {
01962 for (size_t j = 0; j < pters.size (); ++j)
01963 {
01964 memcpy (pters[j], &cloud.data[i * cloud.point_step + fields[j].offset], fields_sizes[j]);
01965
01966 pters[j] += fields_sizes[j];
01967 }
01968 }
01969
01970 char* temp_buf = static_cast<char*> (malloc (static_cast<size_t> (static_cast<float> (data_size) * 1.5f + 8.0f)));
01971
01972 unsigned int compressed_size = pcl::lzfCompress (only_valid_data,
01973 static_cast<unsigned int> (data_size),
01974 &temp_buf[8],
01975 static_cast<unsigned int> (static_cast<float> (data_size) * 1.5f));
01976 unsigned int compressed_final_size = 0;
01977
01978 if (compressed_size)
01979 {
01980 char *header = &temp_buf[0];
01981 memcpy (&header[0], &compressed_size, sizeof (unsigned int));
01982 memcpy (&header[4], &data_size, sizeof (unsigned int));
01983 data_size = compressed_size + 8;
01984 compressed_final_size = static_cast<unsigned int> (data_size + data_idx);
01985 }
01986 else
01987 {
01988 #if !_WIN32
01989 pcl_close (fd);
01990 #endif
01991 throw pcl::IOException ("[pcl::PCDWriter::writeBinaryCompressed] Error during compression!");
01992 return (-1);
01993 }
01994
01995 #if !_WIN32
01996
01997 int result = static_cast<int> (pcl_lseek (fd, getpagesize () + data_size - 1, SEEK_SET));
01998 if (result < 0)
01999 {
02000 pcl_close (fd);
02001 PCL_ERROR ("[pcl::PCDWriter::writeBinaryCompressed] Error during lseek ()!\n");
02002 return (-1);
02003 }
02004
02005 result = static_cast<int> (::write (fd, "", 1));
02006 if (result != 1)
02007 {
02008 pcl_close (fd);
02009 PCL_ERROR ("[pcl::PCDWriter::writeBinaryCompressed] Error during write ()!\n");
02010 return (-1);
02011 }
02012 #endif
02013
02014
02015 #ifdef _WIN32
02016 HANDLE fm = CreateFileMapping (h_native_file, NULL, PAGE_READWRITE, 0, compressed_final_size, NULL);
02017 char *map = static_cast<char*> (MapViewOfFile (fm, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, compressed_final_size));
02018 CloseHandle (fm);
02019
02020 #else
02021 char *map = static_cast<char*> (mmap (0, compressed_final_size, PROT_WRITE, MAP_SHARED, fd, 0));
02022 if (map == reinterpret_cast<char*> (-1))
02023 {
02024 pcl_close (fd);
02025 PCL_ERROR ("[pcl::PCDWriter::writeBinaryCompressed] Error during mmap ()!\n");
02026 return (-1);
02027 }
02028 #endif
02029
02030
02031 memcpy (&map[0], oss.str ().c_str (), static_cast<size_t> (data_idx));
02032
02033 memcpy (&map[data_idx], temp_buf, data_size);
02034
02035 #if !_WIN32
02036
02037 if (map_synchronization_)
02038 msync (map, compressed_final_size, MS_SYNC);
02039 #endif
02040
02041
02042 #if _WIN32
02043 UnmapViewOfFile (map);
02044 #else
02045 if (munmap (map, (compressed_final_size)) == -1)
02046 {
02047 pcl_close (fd);
02048 PCL_ERROR ("[pcl::PCDWriter::writeBinaryCompressed] Error during munmap ()!\n");
02049 return (-1);
02050 }
02051 #endif
02052
02053 #if _WIN32
02054 CloseHandle (h_native_file);
02055 #else
02056 pcl_close (fd);
02057 #endif
02058
02059 free (only_valid_data);
02060 free (temp_buf);
02061 return (0);
02062 }
02063
02065 std::string
02066 pcl::PCDWriter::generateHeaderEigen (const pcl::PointCloud<Eigen::MatrixXf> &cloud,
02067 const int nr_points)
02068 {
02069 std::ostringstream oss;
02070 oss.imbue (std::locale::classic ());
02071
02072 oss << "# .PCD v0.7 - Point Cloud Data file format"
02073 "\nVERSION 0.7"
02074 "\nFIELDS";
02075
02076 std::stringstream field_names, field_types, field_sizes, field_counts;
02077
02078 std::vector<pair_channel_properties> vec (cloud.channels.begin (), cloud.channels.end ());
02079 std::sort (vec.begin (), vec.end (), ChannelPropertiesComparator ());
02080
02081 for (std::vector<pair_channel_properties>::iterator it = vec.begin (); it != vec.end (); ++it)
02082 {
02083
02084 field_names << " " << it->second.name;
02085 field_sizes << " " << pcl::getFieldSize (it->second.datatype);
02086 field_types << " " << pcl::getFieldType (it->second.datatype);
02087 int count = abs (static_cast<int> (it->second.count));
02088 if (count == 0) count = 1;
02089 field_counts << " " << count;
02090 }
02091 oss << field_names.str ();
02092 oss << "\nSIZE" << field_sizes.str ()
02093 << "\nTYPE" << field_types.str ()
02094 << "\nCOUNT" << field_counts.str ();
02095
02096 if (nr_points != std::numeric_limits<int>::max ())
02097 oss << "\nWIDTH " << nr_points << "\nHEIGHT " << 1 << "\n";
02098 else
02099 oss << "\nWIDTH " << cloud.width << "\nHEIGHT " << cloud.height << "\n";
02100
02101 oss << "VIEWPOINT " << cloud.properties.sensor_origin[0] << " " <<
02102 cloud.properties.sensor_origin[1] << " " <<
02103 cloud.properties.sensor_origin[2] << " " <<
02104 cloud.properties.sensor_orientation.w () << " " <<
02105 cloud.properties.sensor_orientation.x () << " " <<
02106 cloud.properties.sensor_orientation.y () << " " <<
02107 cloud.properties.sensor_orientation.z () << "\n";
02108
02109
02110 if (nr_points != std::numeric_limits<int>::max ())
02111 oss << "POINTS " << nr_points << "\n";
02112 else
02113 oss << "POINTS " << cloud.points.rows () << "\n";
02114
02115 return (oss.str ());
02116 }
02117
02119 int
02120 pcl::PCDWriter::writeASCIIEigen (const std::string &file_name, const pcl::PointCloud<Eigen::MatrixXf> &cloud,
02121 const int precision)
02122 {
02123 if (cloud.empty ())
02124 {
02125 throw pcl::IOException ("[pcl::PCDWriter::writeASCII] Input point cloud has no data!");
02126 return (-1);
02127 }
02128
02129 if (static_cast<int> (cloud.width * cloud.height) != cloud.points.rows ())
02130 {
02131 throw pcl::IOException ("[pcl::PCDWriter::writeASCII] Number of points different than width * height!");
02132 return (-1);
02133 }
02134
02135 std::ofstream fs;
02136 fs.open (file_name.c_str ());
02137
02138 if (!fs.is_open () || fs.fail ())
02139 {
02140 throw pcl::IOException ("[pcl::PCDWriter::writeASCII] Could not open file for writing!");
02141 return (-1);
02142 }
02143
02144 fs.precision (precision);
02145 fs.imbue (std::locale::classic ());
02146
02147
02148 fs << generateHeaderEigen (cloud) << "DATA ascii\n";
02149
02150 std::ostringstream stream;
02151 stream.precision (precision);
02152 stream.imbue (std::locale::classic ());
02153
02154 for (int i = 0; i < cloud.points.rows (); ++i)
02155 {
02156 for (int j = 0; j < cloud.points.cols (); ++j)
02157 {
02158 stream << cloud.points.coeffRef (i, j);
02159 if (j < cloud.points.cols () - 1)
02160 stream << " ";
02161 }
02162
02163 std::string result = stream.str ();
02164 boost::trim (result);
02165 stream.str ("");
02166 fs << result << "\n";
02167 }
02168 fs.close ();
02169 return (0);
02170 }
02171
02172
02174 int
02175 pcl::PCDWriter::writeBinaryEigen (const std::string &file_name,
02176 const pcl::PointCloud<Eigen::MatrixXf> &cloud)
02177 {
02178 if (cloud.points.rows () * cloud.points.cols () == 0)
02179 {
02180 throw pcl::IOException ("[pcl::PCDWriter::writeBinary] Input point cloud has no data!");
02181 return (-1);
02182 }
02183 int data_idx = 0;
02184 std::ostringstream oss;
02185 oss << generateHeaderEigen (cloud) << "DATA binary\n";
02186 oss.flush ();
02187 data_idx = static_cast<int> (oss.tellp ());
02188
02189 #if _WIN32
02190 HANDLE h_native_file = CreateFileA (file_name.c_str (), GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
02191 if(h_native_file == INVALID_HANDLE_VALUE)
02192 {
02193 throw pcl::IOException ("[pcl::PCDWriter::writeBinary] Error during CreateFile!");
02194 return (-1);
02195 }
02196 #else
02197 int fd = pcl_open (file_name.c_str (), O_RDWR | O_CREAT | O_TRUNC, static_cast<mode_t> (0600));
02198 if (fd < 0)
02199 {
02200 throw pcl::IOException ("[pcl::PCDWriter::writeBinary] Error during open!");
02201 return (-1);
02202 }
02203 #endif
02204
02205 size_t data_size = cloud.points.rows () * cloud.points.cols () * sizeof (float);
02206
02207
02208 #if _WIN32
02209 HANDLE fm = CreateFileMappingA (h_native_file, NULL, PAGE_READWRITE, 0, (DWORD) (data_idx + data_size), NULL);
02210 char *map = static_cast<char*> (MapViewOfFile (fm, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, data_idx + data_size));
02211 CloseHandle (fm);
02212
02213 #else
02214
02215 int result = static_cast<int> (pcl_lseek (fd, getpagesize () + data_size - 1, SEEK_SET));
02216 if (result < 0)
02217 {
02218 pcl_close (fd);
02219 throw pcl::IOException ("[pcl::PCDWriter::writeBinary] Error during lseek ()!");
02220 return (-1);
02221 }
02222
02223 result = static_cast<int>(::write (fd, "", 1));
02224 if (result != 1)
02225 {
02226 pcl_close (fd);
02227 throw pcl::IOException ("[pcl::PCDWriter::writeBinary] Error during write ()!");
02228 return (-1);
02229 }
02230
02231 char *map = static_cast<char*> (mmap (0, data_idx + data_size, PROT_WRITE, MAP_SHARED, fd, 0));
02232 if (map == reinterpret_cast<char*> (-1))
02233 {
02234 pcl_close (fd);
02235 throw pcl::IOException ("[pcl::PCDWriter::writeBinary] Error during mmap ()!");
02236 return (-1);
02237 }
02238 #endif
02239
02240
02241 memcpy (&map[0], oss.str ().c_str (), data_idx);
02242
02243 Eigen::MatrixXf pts;
02244
02245 if (!(cloud.points.Flags & Eigen::RowMajorBit))
02246 pts = cloud.points.transpose ();
02247 else
02248 pts = cloud.points;
02249
02250 memcpy (&map[0] + data_idx, reinterpret_cast<const char*> (pts.data ()), data_size);
02251
02252
02253 #if !_WIN32
02254 if (map_synchronization_)
02255 msync (map, data_idx + data_size, MS_SYNC);
02256 #endif
02257
02258
02259 #if _WIN32
02260 UnmapViewOfFile (map);
02261 #else
02262 if (munmap (map, (data_idx + data_size)) == -1)
02263 {
02264 pcl_close (fd);
02265 throw pcl::IOException ("[pcl::PCDWriter::writeBinary] Error during munmap ()!");
02266 return (-1);
02267 }
02268 #endif
02269
02270 #if _WIN32
02271 CloseHandle (h_native_file);
02272 #else
02273 pcl_close (fd);
02274 #endif
02275 return (0);
02276 }
02277
02279 int
02280 pcl::PCDWriter::writeBinaryCompressedEigen (
02281 const std::string &file_name,
02282 const pcl::PointCloud<Eigen::MatrixXf> &cloud)
02283 {
02284 if (cloud.points.rows () * cloud.points.cols () == 0)
02285 {
02286 throw pcl::IOException ("[pcl::PCDWriter::writeBinaryCompressed] Input point cloud has no data!");
02287 return (-1);
02288 }
02289 std::ostringstream::pos_type data_idx = 0;
02290 std::ostringstream oss;
02291 oss << generateHeaderEigen (cloud) << "DATA binary_compressed\n";
02292 oss.flush ();
02293 data_idx = oss.tellp ();
02294
02295 #if _WIN32
02296 HANDLE h_native_file = CreateFileA (file_name.c_str (), GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
02297 if(h_native_file == INVALID_HANDLE_VALUE)
02298 {
02299 throw pcl::IOException ("[pcl::PCDWriter::writeBinaryCompressed] Error during CreateFile!");
02300 return (-1);
02301 }
02302 #else
02303 int fd = pcl_open (file_name.c_str (), O_RDWR | O_CREAT | O_TRUNC, static_cast<mode_t> (0600));
02304 if (fd < 0)
02305 {
02306 throw pcl::IOException ("[pcl::PCDWriter::writeBinaryCompressed] Error during open!");
02307 return (-1);
02308 }
02309 #endif
02310
02311 Eigen::MatrixXf pts;
02312
02313 if (cloud.points.Flags & Eigen::RowMajorBit)
02314
02315 pts = cloud.points.transpose ();
02316 else
02317 pts = cloud.points;
02318
02319
02320 size_t data_size = cloud.points.rows () * cloud.points.cols () * sizeof (float);
02321 char* temp_buf = static_cast<char*> (malloc (static_cast<size_t> (static_cast<float> (data_size) * 1.5f + 8.0f)));
02322
02323 unsigned int compressed_size = pcl::lzfCompress (reinterpret_cast<char*> (pts.data ()),
02324 static_cast<unsigned int> (data_size),
02325 &temp_buf[8],
02326 static_cast<unsigned int> (static_cast<float> (data_size) * 1.5f));
02327 unsigned int compressed_final_size = 0;
02328
02329 if (compressed_size)
02330 {
02331 char *header = &temp_buf[0];
02332 memcpy (&header[0], &compressed_size, sizeof (unsigned int));
02333 memcpy (&header[4], &data_size, sizeof (unsigned int));
02334 data_size = compressed_size + 8;
02335 compressed_final_size = static_cast<unsigned int> (data_size + data_idx);
02336 }
02337 else
02338 {
02339 #if !_WIN32
02340 pcl_close (fd);
02341 #endif
02342 throw pcl::IOException ("[pcl::PCDWriter::writeBinaryCompressed] Error during compression!");
02343 return (-1);
02344 }
02345
02346 #if !_WIN32
02347
02348 int result = static_cast<int> (pcl_lseek (fd, getpagesize () + data_size - 1, SEEK_SET));
02349 if (result < 0)
02350 {
02351 pcl_close (fd);
02352 throw pcl::IOException ("[pcl::PCDWriter::writeBinaryCompressed] Error during lseek ()!");
02353 return (-1);
02354 }
02355
02356 result = static_cast<int> (::write (fd, "", 1));
02357 if (result != 1)
02358 {
02359 pcl_close (fd);
02360 throw pcl::IOException ("[pcl::PCDWriter::writeBinaryCompressed] Error during write ()!");
02361 return (-1);
02362 }
02363 #endif
02364
02365
02366 #if _WIN32
02367 HANDLE fm = CreateFileMapping (h_native_file, NULL, PAGE_READWRITE, 0, compressed_final_size, NULL);
02368 char *map = static_cast<char*> (MapViewOfFile (fm, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, compressed_final_size));
02369 CloseHandle (fm);
02370
02371 #else
02372 char *map = static_cast<char*> (mmap (0, compressed_final_size, PROT_WRITE, MAP_SHARED, fd, 0));
02373 if (map == reinterpret_cast<char*> (-1))
02374 {
02375 pcl_close (fd);
02376 throw pcl::IOException ("[pcl::PCDWriter::writeBinaryCompressed] Error during mmap ()!");
02377 return (-1);
02378 }
02379 #endif
02380
02381
02382 memcpy (&map[0], oss.str ().c_str (), static_cast<size_t> (data_idx));
02383
02384 memcpy (&map[data_idx], temp_buf, static_cast<size_t> (data_size));
02385
02386 #if !_WIN32
02387
02388 if (map_synchronization_)
02389 msync (map, compressed_final_size, MS_SYNC);
02390 #endif
02391
02392
02393 #if _WIN32
02394 UnmapViewOfFile (map);
02395 #else
02396 if (munmap (map, (compressed_final_size)) == -1)
02397 {
02398 pcl_close (fd);
02399 throw pcl::IOException ("[pcl::PCDWriter::writeBinaryCompressed] Error during munmap ()!");
02400 return (-1);
02401 }
02402 #endif
02403
02404 #if _WIN32
02405 CloseHandle (h_native_file);
02406 #else
02407 pcl_close (fd);
02408 #endif
02409
02410 free (temp_buf);
02411 return (0);
02412 }
02413
02414