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
00043 #include "pcl/point_types.h"
00044 #include "pcl/io/io.h"
00045 #include "pcl/io/pcd_io.h"
00046
00048 bool
00049 pcl::concatenatePointCloud (const sensor_msgs::PointCloud2 &cloud1,
00050 const sensor_msgs::PointCloud2 &cloud2,
00051 sensor_msgs::PointCloud2 &cloud_out)
00052 {
00053 if (cloud1.fields.size () != cloud2.fields.size ())
00054 return (false);
00055
00056 for (size_t i = 0; i < cloud1.fields.size (); ++i)
00057 if (cloud1.fields[i].name != cloud2.fields[i].name)
00058 return (false);
00059
00060
00061 cloud_out = cloud1;
00062 size_t nrpts = cloud_out.data.size ();
00063 cloud_out.data.resize (nrpts + cloud2.data.size ());
00064 memcpy (&cloud_out.data[nrpts], &cloud2.data[0], cloud2.data.size ());
00065
00066
00067 cloud_out.width = cloud1.width * cloud1.height + cloud2.width * cloud2.height;
00068 cloud_out.height = 1;
00069 if (!cloud1.is_dense || !cloud2.is_dense)
00070 cloud_out.is_dense = false;
00071 else
00072 cloud_out.is_dense = true;
00073
00074 return (true);
00075 }
00076
00078 bool
00079 pcl::getPointCloudAsEigen (const sensor_msgs::PointCloud2 &in, Eigen::MatrixXf &out)
00080 {
00081
00082 int x_idx = getFieldIndex (in, "x");
00083 int y_idx = getFieldIndex (in, "y");
00084 int z_idx = getFieldIndex (in, "z");
00085
00086 if (x_idx == -1 || y_idx == -1 || z_idx == -1)
00087 {
00088 ROS_ERROR ("Input dataset has no X-Y-Z coordinates! Cannot convert to Eigen format.");
00089 return (false);
00090 }
00091
00092 if (in.fields[x_idx].datatype != sensor_msgs::PointField::FLOAT32 ||
00093 in.fields[y_idx].datatype != sensor_msgs::PointField::FLOAT32 ||
00094 in.fields[z_idx].datatype != sensor_msgs::PointField::FLOAT32)
00095 {
00096 ROS_ERROR ("X-Y-Z coordinates not floats. Currently only floats are supported.");
00097 return (false);
00098 }
00099
00100 size_t npts = in.width * in.height;
00101 out = Eigen::MatrixXf::Ones (4, npts);
00102
00103 Eigen::Array4i xyz_offset (in.fields[x_idx].offset, in.fields[y_idx].offset, in.fields[z_idx].offset, 0);
00104
00105
00106 for (size_t i = 0; i < npts; ++i)
00107 {
00108
00109 memcpy (&out (0, i), &in.data[xyz_offset[0]], sizeof (float));
00110 memcpy (&out (1, i), &in.data[xyz_offset[1]], sizeof (float));
00111 memcpy (&out (2, i), &in.data[xyz_offset[2]], sizeof (float));
00112
00113 xyz_offset += in.point_step;
00114 }
00115
00116 return (true);
00117 }
00118
00120 bool
00121 pcl::getEigenAsPointCloud (Eigen::MatrixXf &in, sensor_msgs::PointCloud2 &out)
00122 {
00123
00124 int x_idx = getFieldIndex (out, "x");
00125 int y_idx = getFieldIndex (out, "y");
00126 int z_idx = getFieldIndex (out, "z");
00127
00128 if (x_idx == -1 || y_idx == -1 || z_idx == -1)
00129 {
00130 ROS_ERROR ("Output dataset has no X-Y-Z coordinates set up as fields! Cannot convert from Eigen format.");
00131 return (false);
00132 }
00133
00134 if (out.fields[x_idx].datatype != sensor_msgs::PointField::FLOAT32 ||
00135 out.fields[y_idx].datatype != sensor_msgs::PointField::FLOAT32 ||
00136 out.fields[z_idx].datatype != sensor_msgs::PointField::FLOAT32)
00137 {
00138 ROS_ERROR ("X-Y-Z coordinates not floats. Currently only floats are supported.");
00139 return (false);
00140 }
00141
00142 if (in.cols () != (int)(out.width * out.height))
00143 {
00144 ROS_ERROR ("Number of points in the point cloud differs from the Eigen matrix. Cannot continue.");
00145 return (false);
00146 }
00147
00148 size_t npts = in.cols ();
00149
00150 Eigen::Array4i xyz_offset (out.fields[x_idx].offset, out.fields[y_idx].offset, out.fields[z_idx].offset, 0);
00151
00152
00153 for (size_t i = 0; i < npts; ++i)
00154 {
00155
00156 memcpy (&out.data[xyz_offset[0]], &in (0, i), sizeof (float));
00157 memcpy (&out.data[xyz_offset[1]], &in (1, i), sizeof (float));
00158 memcpy (&out.data[xyz_offset[2]], &in (2, i), sizeof (float));
00159
00160 xyz_offset += out.point_step;
00161 }
00162
00163 return (true);
00164 }
00165
00167 void
00168 pcl::copyPointCloud (
00169 const sensor_msgs::PointCloud2 &cloud_in, const std::vector<int> &indices,
00170 sensor_msgs::PointCloud2 &cloud_out)
00171 {
00172 cloud_out.header = cloud_in.header;
00173 cloud_out.height = 1;
00174 cloud_out.width = indices.size ();
00175 cloud_out.fields = cloud_in.fields;
00176 cloud_out.is_bigendian = cloud_in.is_bigendian;
00177 cloud_out.point_step = cloud_in.point_step;
00178 cloud_out.row_step = cloud_in.row_step;
00179 if (cloud_in.is_dense)
00180 cloud_out.is_dense = true;
00181 else
00182
00183
00184 cloud_out.is_dense = false;
00185
00186 cloud_out.data.resize (cloud_out.width * cloud_out.height * cloud_out.point_step);
00187
00188
00189 for (size_t i = 0; i < indices.size (); ++i)
00190 {
00191 memcpy (&cloud_out.data[i * cloud_out.point_step], &cloud_in.data[indices[i] * cloud_in.point_step], cloud_in.point_step);
00192
00193
00194 }
00195 }
00196