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
00041 #include <pcl/point_types.h>
00042 #include <pcl/common/io.h>
00043
00045 void
00046 getFieldsSizes (const std::vector<pcl::PCLPointField> &fields,
00047 std::vector<int> &fields_sizes)
00048 {
00049 int valid = 0;
00050 fields_sizes.resize (fields.size ());
00051 for (size_t i = 0; i < fields.size (); ++i)
00052 {
00053 if (fields[i].name == "_")
00054 continue;
00055
00056 int fs = fields[i].count * pcl::getFieldSize (fields[i].datatype);
00057 fields_sizes[i] = fs;
00058 valid++;
00059 }
00060 fields_sizes.resize (valid);
00061 }
00062
00063 bool fieldComp (const pcl::PCLPointField* i, const pcl::PCLPointField* j)
00064 {
00065 return i->offset < j->offset;
00066 }
00067
00069 bool
00070 pcl::concatenateFields (const pcl::PCLPointCloud2 &cloud1,
00071 const pcl::PCLPointCloud2 &cloud2,
00072 pcl::PCLPointCloud2 &cloud_out)
00073 {
00074
00075 if (cloud1.width != cloud2.width || cloud1.height != cloud2.height)
00076 {
00077 PCL_ERROR ("[pcl::concatenateFields] Dimensions of input clouds do not match: cloud1 (w, %d, h, %d), cloud2 (w, %d, h, %d)\n", cloud1.width, cloud1.height, cloud2.width, cloud2.height );
00078 return (false);
00079 }
00080
00081
00082 if (cloud1.is_bigendian != cloud2.is_bigendian)
00083 {
00084 PCL_ERROR ("[pcl::concatenateFields] Endianness of clouds does not match\n");
00085 return (false);
00086 }
00087
00088
00089
00090
00091 cloud_out.header = cloud2.header;
00092 cloud_out.fields = cloud2.fields;
00093 cloud_out.width = cloud2.width;
00094 cloud_out.height = cloud2.height;
00095 cloud_out.is_bigendian = cloud2.is_bigendian;
00096
00097
00098 size_t total_fields = cloud2.fields.size ();
00099
00100
00101
00102 std::vector<const pcl::PCLPointField*> cloud1_unique_fields;
00103 std::vector<int> field_sizes;
00104
00105
00106
00107
00108 std::vector<const pcl::PCLPointField*> cloud1_fields_sorted;
00109 for (size_t i = 0; i < cloud1.fields.size (); ++i)
00110 cloud1_fields_sorted.push_back (&(cloud1.fields[i]));
00111
00112 std::sort (cloud1_fields_sorted.begin (), cloud1_fields_sorted.end (), fieldComp);
00113
00114 for (size_t i = 0; i < cloud1_fields_sorted.size (); ++i)
00115 {
00116 bool match = false;
00117 for (size_t j = 0; j < cloud2.fields.size (); ++j)
00118 {
00119 if (cloud1_fields_sorted[i]->name == cloud2.fields[j].name)
00120 match = true;
00121 }
00122
00123
00124 if (!match && cloud1_fields_sorted[i]->name != "_")
00125 {
00126 cloud1_unique_fields.push_back (cloud1_fields_sorted[i]);
00127
00128 int size = 0;
00129 size_t next_valid_field = i + 1;
00130
00131 while (next_valid_field < cloud1_fields_sorted.size())
00132 {
00133 if (cloud1_fields_sorted[next_valid_field]->name != "_")
00134 break;
00135 next_valid_field++;
00136 }
00137
00138 if (next_valid_field < cloud1_fields_sorted.size ())
00139
00140 size = cloud1_fields_sorted[next_valid_field]->offset - cloud1_fields_sorted[i]->offset;
00141 else
00142
00143 size = cloud1.point_step - cloud1_fields_sorted[i]->offset;
00144
00145 field_sizes.push_back (size);
00146
00147 total_fields++;
00148 }
00149 }
00150
00151
00152 uint32_t cloud1_unique_point_step = 0;
00153 for (size_t i = 0; i < cloud1_unique_fields.size (); ++i)
00154 cloud1_unique_point_step += field_sizes[i];
00155
00156
00157
00158 uint32_t cloud1_unique_data_size = cloud1_unique_point_step * cloud1.width * cloud1.height;
00159
00160
00161 cloud_out.point_step = cloud2.point_step + cloud1_unique_point_step;
00162
00163 cloud_out.row_step = cloud_out.point_step * cloud_out.width;
00164
00165
00166 cloud_out.data.resize (cloud2.data.size () + cloud1_unique_data_size);
00167
00168
00169 cloud_out.fields.resize (cloud2.fields.size () + cloud1_unique_fields.size ());
00170 int offset = cloud2.point_step;
00171
00172 for (size_t d = 0; d < cloud1_unique_fields.size (); ++d)
00173 {
00174 const pcl::PCLPointField& f = *cloud1_unique_fields[d];
00175 cloud_out.fields[cloud2.fields.size () + d].name = f.name;
00176 cloud_out.fields[cloud2.fields.size () + d].datatype = f.datatype;
00177 cloud_out.fields[cloud2.fields.size () + d].count = f.count;
00178
00179 cloud_out.fields[cloud2.fields.size () + d].offset = offset;
00180 offset += field_sizes[d];
00181 }
00182
00183
00184 int point_offset = 0;
00185 for (size_t cp = 0; cp < cloud_out.width * cloud_out.height; ++cp)
00186 {
00187 memcpy (&cloud_out.data[point_offset], &cloud2.data[cp * cloud2.point_step], cloud2.point_step);
00188 int field_offset = cloud2.point_step;
00189
00190
00191
00192 for (size_t i = 0; i < cloud1_unique_fields.size (); ++i)
00193 {
00194 const pcl::PCLPointField& f = *cloud1_unique_fields[i];
00195 int local_data_size = f.count * pcl::getFieldSize (f.datatype);
00196 int padding_size = field_sizes[i] - local_data_size;
00197
00198 memcpy (&cloud_out.data[point_offset + field_offset], &cloud1.data[cp * cloud1.point_step + f.offset], local_data_size);
00199 field_offset += local_data_size;
00200
00201
00202 if (padding_size > 0)
00203 memset (&cloud_out.data[point_offset + field_offset], 0, padding_size);
00204 field_offset += padding_size;
00205 }
00206 point_offset += field_offset;
00207 }
00208
00209 if (!cloud1.is_dense || !cloud2.is_dense)
00210 cloud_out.is_dense = false;
00211 else
00212 cloud_out.is_dense = true;
00213
00214 return (true);
00215 }
00216
00218 bool
00219 pcl::concatenatePointCloud (const pcl::PCLPointCloud2 &cloud1,
00220 const pcl::PCLPointCloud2 &cloud2,
00221 pcl::PCLPointCloud2 &cloud_out)
00222 {
00223
00224 if (cloud1.width*cloud1.height == 0 && cloud2.width*cloud2.height > 0)
00225 {
00226 cloud_out = cloud2;
00227 return (true);
00228 }
00229 else if (cloud1.width*cloud1.height > 0 && cloud2.width*cloud2.height == 0)
00230 {
00231 cloud_out = cloud1;
00232 return (true);
00233 }
00234
00235 bool strip = false;
00236 for (size_t i = 0; i < cloud1.fields.size (); ++i)
00237 if (cloud1.fields[i].name == "_")
00238 strip = true;
00239
00240 for (size_t i = 0; i < cloud2.fields.size (); ++i)
00241 if (cloud2.fields[i].name == "_")
00242 strip = true;
00243
00244 if (!strip && cloud1.fields.size () != cloud2.fields.size ())
00245 {
00246 PCL_ERROR ("[pcl::concatenatePointCloud] Number of fields in cloud1 (%u) != Number of fields in cloud2 (%u)\n", cloud1.fields.size (), cloud2.fields.size ());
00247 return (false);
00248 }
00249
00250
00251 cloud_out = cloud1;
00252 size_t nrpts = cloud_out.data.size ();
00253
00254 cloud_out.width = cloud1.width * cloud1.height + cloud2.width * cloud2.height;
00255 cloud_out.height = 1;
00256 if (!cloud1.is_dense || !cloud2.is_dense)
00257 cloud_out.is_dense = false;
00258 else
00259 cloud_out.is_dense = true;
00260
00261
00262 if (strip)
00263 {
00264
00265 std::vector<pcl::PCLPointField> fields2;
00266 std::vector<int> fields2_sizes;
00267 for (size_t j = 0; j < cloud2.fields.size (); ++j)
00268 {
00269 if (cloud2.fields[j].name == "_")
00270 continue;
00271
00272 fields2_sizes.push_back (cloud2.fields[j].count *
00273 pcl::getFieldSize (cloud2.fields[j].datatype));
00274 fields2.push_back (cloud2.fields[j]);
00275 }
00276
00277 cloud_out.data.resize (nrpts + (cloud2.width * cloud2.height) * cloud_out.point_step);
00278
00279
00280 for (size_t cp = 0; cp < cloud2.width * cloud2.height; ++cp)
00281 {
00282 int i = 0;
00283 for (size_t j = 0; j < fields2.size (); ++j)
00284 {
00285 if (cloud1.fields[i].name == "_")
00286 {
00287 ++i;
00288 continue;
00289 }
00290
00291
00292 if ((cloud1.fields[i].name == "rgb" && fields2[j].name == "rgba") ||
00293 (cloud1.fields[i].name == "rgba" && fields2[j].name == "rgb") ||
00294 (cloud1.fields[i].name == fields2[j].name))
00295 {
00296 memcpy (reinterpret_cast<char*> (&cloud_out.data[nrpts + cp * cloud1.point_step + cloud1.fields[i].offset]),
00297 reinterpret_cast<const char*> (&cloud2.data[cp * cloud2.point_step + cloud2.fields[j].offset]),
00298 fields2_sizes[j]);
00299 ++i;
00300 }
00301 }
00302 }
00303 }
00304 else
00305 {
00306 for (size_t i = 0; i < cloud1.fields.size (); ++i)
00307 {
00308
00309 if ((cloud1.fields[i].name == "rgb" && cloud2.fields[i].name == "rgba") ||
00310 (cloud1.fields[i].name == "rgba" && cloud2.fields[i].name == "rgb"))
00311 continue;
00312
00313 if (cloud1.fields[i].name != cloud2.fields[i].name)
00314 {
00315 PCL_ERROR ("[pcl::concatenatePointCloud] Name of field %d in cloud1, %s, does not match name in cloud2, %s\n", i, cloud1.fields[i].name.c_str (), cloud2.fields[i].name.c_str ());
00316 return (false);
00317 }
00318 }
00319
00320 cloud_out.data.resize (nrpts + cloud2.data.size ());
00321 memcpy (&cloud_out.data[nrpts], &cloud2.data[0], cloud2.data.size ());
00322 }
00323 return (true);
00324 }
00325
00327 bool
00328 pcl::getPointCloudAsEigen (const pcl::PCLPointCloud2 &in, Eigen::MatrixXf &out)
00329 {
00330
00331 int x_idx = getFieldIndex (in, "x");
00332 int y_idx = getFieldIndex (in, "y");
00333 int z_idx = getFieldIndex (in, "z");
00334
00335 if (x_idx == -1 || y_idx == -1 || z_idx == -1)
00336 {
00337 PCL_ERROR ("Input dataset has no X-Y-Z coordinates! Cannot convert to Eigen format.\n");
00338 return (false);
00339 }
00340
00341 if (in.fields[x_idx].datatype != pcl::PCLPointField::FLOAT32 ||
00342 in.fields[y_idx].datatype != pcl::PCLPointField::FLOAT32 ||
00343 in.fields[z_idx].datatype != pcl::PCLPointField::FLOAT32)
00344 {
00345 PCL_ERROR ("X-Y-Z coordinates not floats. Currently only floats are supported.\n");
00346 return (false);
00347 }
00348
00349 size_t npts = in.width * in.height;
00350 out = Eigen::MatrixXf::Ones (4, npts);
00351
00352 Eigen::Array4i xyz_offset (in.fields[x_idx].offset, in.fields[y_idx].offset, in.fields[z_idx].offset, 0);
00353
00354
00355 for (size_t i = 0; i < npts; ++i)
00356 {
00357
00358 memcpy (&out (0, i), &in.data[xyz_offset[0]], sizeof (float));
00359 memcpy (&out (1, i), &in.data[xyz_offset[1]], sizeof (float));
00360 memcpy (&out (2, i), &in.data[xyz_offset[2]], sizeof (float));
00361
00362 xyz_offset += in.point_step;
00363 }
00364
00365 return (true);
00366 }
00367
00369 bool
00370 pcl::getEigenAsPointCloud (Eigen::MatrixXf &in, pcl::PCLPointCloud2 &out)
00371 {
00372
00373 int x_idx = getFieldIndex (out, "x");
00374 int y_idx = getFieldIndex (out, "y");
00375 int z_idx = getFieldIndex (out, "z");
00376
00377 if (x_idx == -1 || y_idx == -1 || z_idx == -1)
00378 {
00379 PCL_ERROR ("Output dataset has no X-Y-Z coordinates set up as fields! Cannot convert from Eigen format.\n");
00380 return (false);
00381 }
00382
00383 if (out.fields[x_idx].datatype != pcl::PCLPointField::FLOAT32 ||
00384 out.fields[y_idx].datatype != pcl::PCLPointField::FLOAT32 ||
00385 out.fields[z_idx].datatype != pcl::PCLPointField::FLOAT32)
00386 {
00387 PCL_ERROR ("X-Y-Z coordinates not floats. Currently only floats are supported.\n");
00388 return (false);
00389 }
00390
00391 if (in.cols () != static_cast<int>(out.width * out.height))
00392 {
00393 PCL_ERROR ("Number of points in the point cloud differs from the Eigen matrix. Cannot continue.\n");
00394 return (false);
00395 }
00396
00397 size_t npts = in.cols ();
00398
00399 Eigen::Array4i xyz_offset (out.fields[x_idx].offset, out.fields[y_idx].offset, out.fields[z_idx].offset, 0);
00400
00401
00402 for (size_t i = 0; i < npts; ++i)
00403 {
00404
00405 memcpy (&out.data[xyz_offset[0]], &in (0, i), sizeof (float));
00406 memcpy (&out.data[xyz_offset[1]], &in (1, i), sizeof (float));
00407 memcpy (&out.data[xyz_offset[2]], &in (2, i), sizeof (float));
00408
00409 xyz_offset += out.point_step;
00410 }
00411
00412 return (true);
00413 }
00414
00416 void
00417 pcl::copyPointCloud (
00418 const pcl::PCLPointCloud2 &cloud_in,
00419 const std::vector<int> &indices,
00420 pcl::PCLPointCloud2 &cloud_out)
00421 {
00422 cloud_out.header = cloud_in.header;
00423 cloud_out.height = 1;
00424 cloud_out.width = static_cast<uint32_t> (indices.size ());
00425 cloud_out.fields = cloud_in.fields;
00426 cloud_out.is_bigendian = cloud_in.is_bigendian;
00427 cloud_out.point_step = cloud_in.point_step;
00428 cloud_out.row_step = cloud_in.row_step;
00429 cloud_out.is_dense = cloud_in.is_dense;
00430
00431 cloud_out.data.resize (cloud_out.width * cloud_out.height * cloud_out.point_step);
00432
00433
00434 for (size_t i = 0; i < indices.size (); ++i)
00435 memcpy (&cloud_out.data[i * cloud_out.point_step], &cloud_in.data[indices[i] * cloud_in.point_step], cloud_in.point_step);
00436 }
00437
00439 void
00440 pcl::copyPointCloud (
00441 const pcl::PCLPointCloud2 &cloud_in,
00442 const std::vector<int, Eigen::aligned_allocator<int> > &indices,
00443 pcl::PCLPointCloud2 &cloud_out)
00444 {
00445 cloud_out.header = cloud_in.header;
00446 cloud_out.height = 1;
00447 cloud_out.width = static_cast<uint32_t> (indices.size ());
00448 cloud_out.fields = cloud_in.fields;
00449 cloud_out.is_bigendian = cloud_in.is_bigendian;
00450 cloud_out.point_step = cloud_in.point_step;
00451 cloud_out.row_step = cloud_in.row_step;
00452 cloud_out.is_dense = cloud_in.is_dense;
00453
00454 cloud_out.data.resize (cloud_out.width * cloud_out.height * cloud_out.point_step);
00455
00456
00457 for (size_t i = 0; i < indices.size (); ++i)
00458 memcpy (&cloud_out.data[i * cloud_out.point_step], &cloud_in.data[indices[i] * cloud_in.point_step], cloud_in.point_step);
00459 }
00460
00462 void
00463 pcl::copyPointCloud (const pcl::PCLPointCloud2 &cloud_in,
00464 pcl::PCLPointCloud2 &cloud_out)
00465 {
00466 cloud_out.header = cloud_in.header;
00467 cloud_out.height = cloud_in.height;
00468 cloud_out.width = cloud_in.width;
00469 cloud_out.fields = cloud_in.fields;
00470 cloud_out.is_bigendian = cloud_in.is_bigendian;
00471 cloud_out.point_step = cloud_in.point_step;
00472 cloud_out.row_step = cloud_in.row_step;
00473 cloud_out.is_dense = cloud_in.is_dense;
00474 cloud_out.data = cloud_in.data;
00475 }
00476