37 #ifndef PCL_CONVERSIONS_H__ 38 #define PCL_CONVERSIONS_H__ 44 #include <pcl/conversions.h> 46 #include <pcl/PCLHeader.h> 47 #include <std_msgs/Header.h> 49 #include <pcl/PCLImage.h> 50 #include <sensor_msgs/Image.h> 52 #include <pcl/PCLPointField.h> 53 #include <sensor_msgs/PointField.h> 55 #include <pcl/PCLPointCloud2.h> 56 #include <sensor_msgs/PointCloud2.h> 58 #include <pcl/PointIndices.h> 59 #include <pcl_msgs/PointIndices.h> 61 #include <pcl/ModelCoefficients.h> 62 #include <pcl_msgs/ModelCoefficients.h> 64 #include <pcl/Vertices.h> 65 #include <pcl_msgs/Vertices.h> 67 #include <pcl/PolygonMesh.h> 68 #include <pcl_msgs/PolygonMesh.h> 70 #include <pcl/io/pcd_io.h> 72 #include <Eigen/StdVector> 73 #include <Eigen/Geometry> 88 pcl_stamp = stamp.
toNSec() / 1000ull;
102 std::uint64_t pcl_stamp;
103 toPCL(stamp, pcl_stamp);
110 void fromPCL(
const pcl::PCLHeader &pcl_header, std_msgs::Header &header)
112 fromPCL(pcl_header.stamp, header.stamp);
113 header.seq = pcl_header.seq;
114 header.frame_id = pcl_header.frame_id;
118 void toPCL(
const std_msgs::Header &header, pcl::PCLHeader &pcl_header)
120 toPCL(header.stamp, pcl_header.stamp);
121 pcl_header.seq = header.seq;
122 pcl_header.frame_id = header.frame_id;
126 std_msgs::Header
fromPCL(
const pcl::PCLHeader &pcl_header)
134 pcl::PCLHeader
toPCL(
const std_msgs::Header &header)
136 pcl::PCLHeader pcl_header;
137 toPCL(header, pcl_header);
146 fromPCL(pcl_image.header, image.header);
147 image.height = pcl_image.height;
148 image.width = pcl_image.width;
149 image.encoding = pcl_image.encoding;
150 image.is_bigendian = pcl_image.is_bigendian;
151 image.step = pcl_image.step;
155 void fromPCL(
const pcl::PCLImage &pcl_image, sensor_msgs::Image &image)
158 image.data = pcl_image.data;
162 void moveFromPCL(pcl::PCLImage &pcl_image, sensor_msgs::Image &image)
165 image.data.swap(pcl_image.data);
171 toPCL(image.header, pcl_image.header);
172 pcl_image.height = image.height;
173 pcl_image.width = image.width;
174 pcl_image.encoding = image.encoding;
175 pcl_image.is_bigendian = image.is_bigendian;
176 pcl_image.step = image.step;
180 void toPCL(
const sensor_msgs::Image &image, pcl::PCLImage &pcl_image)
183 pcl_image.data = image.data;
187 void moveToPCL(sensor_msgs::Image &image, pcl::PCLImage &pcl_image)
190 pcl_image.data.swap(image.data);
196 void fromPCL(
const pcl::PCLPointField &pcl_pf, sensor_msgs::PointField &pf)
198 pf.name = pcl_pf.name;
199 pf.offset = pcl_pf.offset;
200 pf.datatype = pcl_pf.datatype;
201 pf.count = pcl_pf.count;
205 void fromPCL(
const std::vector<pcl::PCLPointField> &pcl_pfs, std::vector<sensor_msgs::PointField> &pfs)
207 pfs.resize(pcl_pfs.size());
208 std::vector<pcl::PCLPointField>::const_iterator it = pcl_pfs.begin();
210 for(; it != pcl_pfs.end(); ++it, ++i) {
216 void toPCL(
const sensor_msgs::PointField &pf, pcl::PCLPointField &pcl_pf)
218 pcl_pf.name = pf.name;
219 pcl_pf.offset = pf.offset;
220 pcl_pf.datatype = pf.datatype;
221 pcl_pf.count = pf.count;
225 void toPCL(
const std::vector<sensor_msgs::PointField> &pfs, std::vector<pcl::PCLPointField> &pcl_pfs)
227 pcl_pfs.resize(pfs.size());
228 std::vector<sensor_msgs::PointField>::const_iterator it = pfs.begin();
230 for(; it != pfs.end(); ++it, ++i) {
231 toPCL(*(it), pcl_pfs[i]);
240 fromPCL(pcl_pc2.header, pc2.header);
241 pc2.height = pcl_pc2.height;
242 pc2.width = pcl_pc2.width;
243 fromPCL(pcl_pc2.fields, pc2.fields);
244 pc2.is_bigendian = pcl_pc2.is_bigendian;
245 pc2.point_step = pcl_pc2.point_step;
246 pc2.row_step = pcl_pc2.row_step;
247 pc2.is_dense = pcl_pc2.is_dense;
251 void fromPCL(
const pcl::PCLPointCloud2 &pcl_pc2, sensor_msgs::PointCloud2 &pc2)
254 pc2.data = pcl_pc2.data;
258 void moveFromPCL(pcl::PCLPointCloud2 &pcl_pc2, sensor_msgs::PointCloud2 &pc2)
261 pc2.data.swap(pcl_pc2.data);
267 toPCL(pc2.header, pcl_pc2.header);
268 pcl_pc2.height = pc2.height;
269 pcl_pc2.width = pc2.width;
270 toPCL(pc2.fields, pcl_pc2.fields);
271 pcl_pc2.is_bigendian = pc2.is_bigendian;
272 pcl_pc2.point_step = pc2.point_step;
273 pcl_pc2.row_step = pc2.row_step;
274 pcl_pc2.is_dense = pc2.is_dense;
278 void toPCL(
const sensor_msgs::PointCloud2 &pc2, pcl::PCLPointCloud2 &pcl_pc2)
281 pcl_pc2.data = pc2.data;
285 void moveToPCL(sensor_msgs::PointCloud2 &pc2, pcl::PCLPointCloud2 &pcl_pc2)
288 pcl_pc2.data.swap(pc2.data);
294 void fromPCL(
const pcl::PointIndices &pcl_pi, pcl_msgs::PointIndices &pi)
296 fromPCL(pcl_pi.header, pi.header);
297 pi.indices = pcl_pi.indices;
301 void moveFromPCL(pcl::PointIndices &pcl_pi, pcl_msgs::PointIndices &pi)
303 fromPCL(pcl_pi.header, pi.header);
304 pi.indices.swap(pcl_pi.indices);
308 void toPCL(
const pcl_msgs::PointIndices &pi, pcl::PointIndices &pcl_pi)
310 toPCL(pi.header, pcl_pi.header);
311 pcl_pi.indices = pi.indices;
315 void moveToPCL(pcl_msgs::PointIndices &pi, pcl::PointIndices &pcl_pi)
317 toPCL(pi.header, pcl_pi.header);
318 pcl_pi.indices.swap(pi.indices);
324 void fromPCL(
const pcl::ModelCoefficients &pcl_mc, pcl_msgs::ModelCoefficients &mc)
326 fromPCL(pcl_mc.header, mc.header);
327 mc.values = pcl_mc.values;
331 void moveFromPCL(pcl::ModelCoefficients &pcl_mc, pcl_msgs::ModelCoefficients &mc)
333 fromPCL(pcl_mc.header, mc.header);
334 mc.values.swap(pcl_mc.values);
338 void toPCL(
const pcl_msgs::ModelCoefficients &mc, pcl::ModelCoefficients &pcl_mc)
340 toPCL(mc.header, pcl_mc.header);
341 pcl_mc.values = mc.values;
345 void moveToPCL(pcl_msgs::ModelCoefficients &mc, pcl::ModelCoefficients &pcl_mc)
347 toPCL(mc.header, pcl_mc.header);
348 pcl_mc.values.swap(mc.values);
356 inline void move(std::vector<T> &a, std::vector<T> &b)
361 template <
class T1,
class T2>
362 inline void move(std::vector<T1> &a, std::vector<T2> &b)
364 b.assign(a.cbegin(), a.cend());
369 void fromPCL(
const pcl::Vertices &pcl_vert, pcl_msgs::Vertices &vert)
371 vert.vertices.assign(pcl_vert.vertices.cbegin(), pcl_vert.vertices.cend());
375 void fromPCL(
const std::vector<pcl::Vertices> &pcl_verts, std::vector<pcl_msgs::Vertices> &verts)
377 verts.resize(pcl_verts.size());
378 std::vector<pcl::Vertices>::const_iterator it = pcl_verts.begin();
379 std::vector<pcl_msgs::Vertices>::iterator jt = verts.begin();
380 for (; it != pcl_verts.end() && jt != verts.end(); ++it, ++jt) {
386 void moveFromPCL(pcl::Vertices &pcl_vert, pcl_msgs::Vertices &vert)
392 void fromPCL(std::vector<pcl::Vertices> &pcl_verts, std::vector<pcl_msgs::Vertices> &verts)
394 verts.resize(pcl_verts.size());
395 std::vector<pcl::Vertices>::iterator it = pcl_verts.begin();
396 std::vector<pcl_msgs::Vertices>::iterator jt = verts.begin();
397 for (; it != pcl_verts.end() && jt != verts.end(); ++it, ++jt) {
403 void toPCL(
const pcl_msgs::Vertices &vert, pcl::Vertices &pcl_vert)
405 pcl_vert.vertices.assign(vert.vertices.cbegin(), vert.vertices.cend());
409 void toPCL(
const std::vector<pcl_msgs::Vertices> &verts, std::vector<pcl::Vertices> &pcl_verts)
411 pcl_verts.resize(verts.size());
412 std::vector<pcl_msgs::Vertices>::const_iterator it = verts.begin();
413 std::vector<pcl::Vertices>::iterator jt = pcl_verts.begin();
414 for (; it != verts.end() && jt != pcl_verts.end(); ++it, ++jt) {
420 void moveToPCL(pcl_msgs::Vertices &vert, pcl::Vertices &pcl_vert)
426 void moveToPCL(std::vector<pcl_msgs::Vertices> &verts, std::vector<pcl::Vertices> &pcl_verts)
428 pcl_verts.resize(verts.size());
429 std::vector<pcl_msgs::Vertices>::iterator it = verts.begin();
430 std::vector<pcl::Vertices>::iterator jt = pcl_verts.begin();
431 for (; it != verts.end() && jt != pcl_verts.end(); ++it, ++jt) {
439 void fromPCL(
const pcl::PolygonMesh &pcl_mesh, pcl_msgs::PolygonMesh &mesh)
441 fromPCL(pcl_mesh.header, mesh.header);
442 fromPCL(pcl_mesh.cloud, mesh.cloud);
443 fromPCL(pcl_mesh.polygons, mesh.polygons);
447 void moveFromPCL(pcl::PolygonMesh &pcl_mesh, pcl_msgs::PolygonMesh &mesh)
449 fromPCL(pcl_mesh.header, mesh.header);
454 void toPCL(
const pcl_msgs::PolygonMesh &mesh, pcl::PolygonMesh &pcl_mesh)
456 toPCL(mesh.header, pcl_mesh.header);
457 toPCL(mesh.cloud, pcl_mesh.cloud);
458 toPCL(mesh.polygons, pcl_mesh.polygons);
462 void moveToPCL(pcl_msgs::PolygonMesh &mesh, pcl::PolygonMesh &pcl_mesh)
464 toPCL(mesh.header, pcl_mesh.header);
466 moveToPCL(mesh.polygons, pcl_mesh.polygons);
475 inline int getFieldIndex(
const sensor_msgs::PointCloud2 &cloud,
const std::string &field_name)
478 for (
size_t d = 0;
d < cloud.fields.size(); ++
d) {
479 if (cloud.fields[
d].name == field_name) {
480 return (static_cast<int>(
d));
491 for (
size_t i = 0; i < cloud.fields.size () - 1; ++i) {
492 result += cloud.fields[i].name +
" ";
494 result += cloud.fields[cloud.fields.size () - 1].name;
501 void toROSMsg(
const sensor_msgs::PointCloud2 &cloud, sensor_msgs::Image &image)
503 pcl::PCLPointCloud2 pcl_cloud;
505 pcl::PCLImage pcl_image;
506 pcl::toPCLPointCloud2(pcl_cloud, pcl_image);
511 void moveToROSMsg(sensor_msgs::PointCloud2 &cloud, sensor_msgs::Image &image)
513 pcl::PCLPointCloud2 pcl_cloud;
515 pcl::PCLImage pcl_image;
516 pcl::toPCLPointCloud2(pcl_cloud, pcl_image);
520 template<
typename T>
void 521 toROSMsg (
const pcl::PointCloud<T> &cloud, sensor_msgs::Image& msg)
524 if (cloud.width == 0 && cloud.height == 0)
526 throw std::runtime_error(
"Needs to be a dense like cloud!!");
530 if (cloud.points.size () != cloud.width * cloud.height)
531 throw std::runtime_error(
"The width and height do not match the cloud size!");
532 msg.height = cloud.height;
533 msg.width = cloud.width;
537 msg.encoding =
"bgr8";
538 msg.step = msg.width *
sizeof (std::uint8_t) * 3;
539 msg.data.resize (msg.step * msg.height);
540 for (
size_t y = 0; y < cloud.height; y++)
542 for (
size_t x = 0; x < cloud.width; x++)
544 std::uint8_t * pixel = &(msg.data[y * msg.step + x * 3]);
545 memcpy (pixel, &cloud (x, y).rgb, 3 *
sizeof(std::uint8_t));
553 void toROSMsg(
const pcl::PointCloud<T> &pcl_cloud, sensor_msgs::PointCloud2 &cloud)
555 pcl::PCLPointCloud2 pcl_pc2;
556 pcl::toPCLPointCloud2(pcl_cloud, pcl_pc2);
561 void fromROSMsg(
const sensor_msgs::PointCloud2 &cloud, pcl::PointCloud<T> &pcl_cloud)
563 pcl::PCLPointCloud2 pcl_pc2;
564 #if PCL_VERSION_COMPARE(>=, 1, 13, 1) 566 pcl::MsgFieldMap field_map;
567 pcl::createMapping<T> (pcl_pc2.fields, field_map);
568 pcl::fromPCLPointCloud2(pcl_pc2, pcl_cloud, field_map, &cloud.data[0]);
571 pcl::fromPCLPointCloud2(pcl_pc2, pcl_cloud);
576 void moveFromROSMsg(sensor_msgs::PointCloud2 &cloud, pcl::PointCloud<T> &pcl_cloud)
578 pcl::PCLPointCloud2 pcl_pc2;
580 pcl::fromPCLPointCloud2(pcl_pc2, pcl_cloud);
585 template<
typename Po
intT>
586 void createMapping(
const std::vector<sensor_msgs::PointField>& msg_fields, MsgFieldMap& field_map)
588 std::vector<pcl::PCLPointField> pcl_msg_fields;
590 return createMapping<PointT>(pcl_msg_fields, field_map);
598 savePCDFile(
const std::string &file_name,
const sensor_msgs::PointCloud2 &cloud,
599 const Eigen::Vector4f &origin = Eigen::Vector4f::Zero (),
600 const Eigen::Quaternionf &orientation = Eigen::Quaternionf::Identity (),
601 const bool binary_mode =
false)
603 pcl::PCLPointCloud2 pcl_cloud;
610 const Eigen::Vector4f &origin = Eigen::Vector4f::Zero (),
611 const Eigen::Quaternionf &orientation = Eigen::Quaternionf::Identity (),
612 const bool binary_mode =
false)
614 pcl::PCLPointCloud2 pcl_cloud;
621 inline int loadPCDFile(
const std::string &file_name, sensor_msgs::PointCloud2 &cloud)
623 pcl::PCLPointCloud2 pcl_cloud;
635 const sensor_msgs::PointCloud2 &cloud2,
636 sensor_msgs::PointCloud2 &cloud_out)
639 if (cloud1.width * cloud1.height == 0 && cloud2.width * cloud2.height > 0)
644 else if (cloud1.width*cloud1.height > 0 && cloud2.width*cloud2.height == 0)
651 for (
size_t i = 0; i < cloud1.fields.size (); ++i)
652 if (cloud1.fields[i].name ==
"_")
655 for (
size_t i = 0; i < cloud2.fields.size (); ++i)
656 if (cloud2.fields[i].name ==
"_")
659 if (!strip && cloud1.fields.size () != cloud2.fields.size ())
661 PCL_ERROR (
"[pcl::concatenatePointCloud] Number of fields in cloud1 (%u) != Number of fields in cloud2 (%u)\n", cloud1.fields.size (), cloud2.fields.size ());
667 size_t nrpts = cloud_out.data.size ();
669 cloud_out.width = cloud1.width * cloud1.height + cloud2.width * cloud2.height;
670 cloud_out.height = 1;
671 if (!cloud1.is_dense || !cloud2.is_dense)
672 cloud_out.is_dense =
false;
674 cloud_out.is_dense =
true;
680 std::vector<sensor_msgs::PointField> fields2;
681 std::vector<int> fields2_sizes;
682 for (
size_t j = 0; j < cloud2.fields.size (); ++j)
684 if (cloud2.fields[j].name ==
"_")
687 fields2_sizes.push_back (cloud2.fields[j].count *
688 pcl::getFieldSize (cloud2.fields[j].datatype));
689 fields2.push_back (cloud2.fields[j]);
692 cloud_out.data.resize (nrpts + (cloud2.width * cloud2.height) * cloud_out.point_step);
695 for (
size_t cp = 0; cp < cloud2.width * cloud2.height; ++cp)
698 for (
size_t j = 0; j < fields2.size (); ++j)
700 if (cloud1.fields[i].name ==
"_")
707 if ((cloud1.fields[i].name ==
"rgb" && fields2[j].name ==
"rgba") ||
708 (cloud1.fields[i].name ==
"rgba" && fields2[j].name ==
"rgb") ||
709 (cloud1.fields[i].name == fields2[j].name))
711 memcpy (reinterpret_cast<char*> (&cloud_out.data[nrpts + cp * cloud1.point_step + cloud1.fields[i].offset]),
712 reinterpret_cast<const char*> (&cloud2.data[cp * cloud2.point_step + cloud2.fields[j].offset]),
721 for (
size_t i = 0; i < cloud1.fields.size (); ++i)
724 if ((cloud1.fields[i].name ==
"rgb" && cloud2.fields[i].name ==
"rgba") ||
725 (cloud1.fields[i].name ==
"rgba" && cloud2.fields[i].name ==
"rgb"))
728 if (cloud1.fields[i].name != cloud2.fields[i].name)
730 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 ());
734 cloud_out.data.resize (nrpts + cloud2.data.size ());
735 memcpy (&cloud_out.data[nrpts], &cloud2.data[0], cloud2.data.size ());
754 namespace message_traits
760 static const char*
value(
const pcl::PCLPointCloud2&) {
return value(); }
774 static const char*
value(
const pcl::PCLPointCloud2&) {
return value(); }
781 static const char*
value(
const pcl::PCLPointCloud2&) {
return value(); }
787 namespace serialization
795 template<
typename Stream>
796 inline static void write(
Stream& stream,
const pcl::PCLPointCloud2& m)
801 stream.next(m.height);
802 stream.next(m.width);
803 std::vector<sensor_msgs::PointField> pfs;
806 stream.next(m.is_bigendian);
807 stream.next(m.point_step);
808 stream.next(m.row_step);
810 stream.next(m.is_dense);
813 template<
typename Stream>
814 inline static void read(
Stream& stream, pcl::PCLPointCloud2& m)
819 stream.next(m.height);
820 stream.next(m.width);
821 std::vector<sensor_msgs::PointField> pfs;
824 stream.next(m.is_bigendian);
825 stream.next(m.point_step);
826 stream.next(m.row_step);
828 stream.next(m.is_dense);
840 std::vector<sensor_msgs::PointField> pfs;
847 length += m.data.size() *
sizeof(std::uint8_t);
860 template<
typename Stream>
861 inline static void write(
Stream& stream,
const pcl::PCLPointField& m)
864 stream.next(m.offset);
865 stream.next(m.datatype);
866 stream.next(m.count);
869 template<
typename Stream>
870 inline static void read(
Stream& stream, pcl::PCLPointField& m)
873 stream.next(m.offset);
874 stream.next(m.datatype);
875 stream.next(m.count);
897 template<
typename Stream>
905 template<
typename Stream>
void createMapping(const std::vector< sensor_msgs::PointField > &msg_fields, MsgFieldMap &field_map)
std::string getFieldsList(const sensor_msgs::PointCloud2 &cloud)
static uint32_t serializedLength(const pcl::PCLPointField &m)
void moveFromROSMsg(sensor_msgs::PointCloud2 &cloud, pcl::PointCloud< T > &pcl_cloud)
int destructiveSavePCDFile(const std::string &file_name, sensor_msgs::PointCloud2 &cloud, const Eigen::Vector4f &origin=Eigen::Vector4f::Zero(), const Eigen::Quaternionf &orientation=Eigen::Quaternionf::Identity(), const bool binary_mode=false)
Time & fromNSec(uint64_t t)
static const char * value()
static uint32_t serializedLength(const pcl::PCLPointCloud2 &m)
static void write(Stream &stream, const pcl::PCLPointCloud2 &m)
void fromROSMsg(const sensor_msgs::PointCloud2 &cloud, pcl::PointCloud< T > &pcl_cloud)
static const char * value(const pcl::PCLPointCloud2 &)
static void write(Stream &stream, const pcl::PCLPointField &m)
#define ROS_STATIC_ASSERT(cond)
static void read(Stream &stream, pcl::PCLPointCloud2 &m)
static void read(Stream &stream, pcl::PCLPointField &m)
int loadPCDFile(const std::string &file_name, sensor_msgs::PointCloud2 &cloud)
void copyPCLPointCloud2MetaData(const pcl::PCLPointCloud2 &pcl_pc2, sensor_msgs::PointCloud2 &pc2)
void toPCL(const ros::Time &stamp, std::uint64_t &pcl_stamp)
static const char * value(const pcl::PCLPointCloud2 &)
void toROSMsg(const pcl::PointCloud< T > &pcl_cloud, sensor_msgs::PointCloud2 &cloud)
void copyPCLImageMetaData(const pcl::PCLImage &pcl_image, sensor_msgs::Image &image)
bool concatenatePointCloud(const sensor_msgs::PointCloud2 &cloud1, const sensor_msgs::PointCloud2 &cloud2, sensor_msgs::PointCloud2 &cloud_out)
void copyImageMetaData(const sensor_msgs::Image &image, pcl::PCLImage &pcl_image)
uint32_t serializationLength(const T &t)
void move(std::vector< T > &a, std::vector< T > &b)
static const char * value()
void moveFromPCL(pcl::PCLImage &pcl_image, sensor_msgs::Image &image)
static const char * value()
void fromPCL(const std::uint64_t &pcl_stamp, ros::Time &stamp)
static const char * value(const pcl::PCLPointCloud2 &)
int getFieldIndex(const sensor_msgs::PointCloud2 &cloud, const std::string &field_name)
void moveToPCL(sensor_msgs::Image &image, pcl::PCLImage &pcl_image)
int savePCDFile(const std::string &file_name, const sensor_msgs::PointCloud2 &cloud, const Eigen::Vector4f &origin=Eigen::Vector4f::Zero(), const Eigen::Quaternionf &orientation=Eigen::Quaternionf::Identity(), const bool binary_mode=false)
void moveToROSMsg(sensor_msgs::PointCloud2 &cloud, sensor_msgs::Image &image)
void copyPointCloud2MetaData(const sensor_msgs::PointCloud2 &pc2, pcl::PCLPointCloud2 &pcl_pc2)