Search code examples
shared-ptrmemcpypoint-cloud-librarypoint-clouds

Use memcpy to store points into pcl::PointCloud<PointT>::ptr


I am trying to optimize my code which is already working but includes multiple deep copies of my data. What I am trying to do is to copy a pointcloud from a device which has the structure defined in struct MyPointType {...} into a pcl::Pointcloud<>::ptr so I can use the pcl functions.

Therefore I allocate memory and memcpy the data into an array called "points". Creating a new pcl:Pointcloud and push_back of each element into this works perfectly but also has a lot of overhead. So I was wondering if there is a way of allocating enough memory for the pcl::PointCloud and then directly memcopy my raw data from the device into the pcl::PointCloud

currently my code looks like this:

// define my own point type
struct MyPointType
{
    float x;
    float y;
    float z;
    float contrast;
    uint32_t rgba;
    EIGEN_MAKE_ALIGNED_OPERATOR_NEW   // make sure our new allocators are aligned
}   EIGEN_ALIGN16;                    // enforce SSE padding for correct memory alignment

// register it for usage in pcl functions
POINT_CLOUD_REGISTER_POINT_STRUCT(MyPointType,
(float, x, x)
(float, y, y)
(float, z, z)
(float, contrast, contrast)
(uint32_t, rgba, rgba)
)


// memcpy of data
size_t maxSize = sizeof(MyPointType)* zividCloud.size();
MyPointType * points = (MyPointType*)malloc(maxSize);
memcpy(points, zividCloud.dataPtr(), maxSize);

// push the data piecewise into my pcl::PointCloud
pcl::PointCloud<MyPointType>::Ptr cloudPCLptr(new pcl::PointCloud<MyPointType>);
for (size_t i = 0; i < zividCloud.size(); i++)
{
    cloudPCLptr->push_back(points[i]);
}       

I hope that makes sense and it would be great if someone can give me some advice on that. Thanks :)


Solution

  • Just in case that anyone is interested, the solution turned out to be pretty simple:

    • simply create a new pcl::PointCloud
    • since this is of type boost::shared_ptr you can access the elemets just like a regular pointer object by dereferencing
    • I misunderstood that a pcl::PointCloud is not a std::vector but in contrast it is a class which has a std::vector as a member variable for the points it stores, thus the resize() operation needs to be called on the points and not on the element itself
    • just memcpy to the pointer of the first element and define the size of bytes that you want to copy

      pcl::PointCloud<MyPointType>::Ptr cloudPCLptr2(new pcl::PointCloud<MyPointType>);
      cloudPCLptr2->points.resize(nbrOfElements);
      
      memcpy(&(cloudPCLptr2->points[0]), zividCloud.dataPtr(), nbrOfBytes);