Suspected Memory Leak in pcl-python during point cloud clipping
Opened this issue · 0 comments
Your Environment
- Operating System and version: Ubuntu 18.04
- Compiler: Python3 and gcc for c++
- PCL Version: 1.8
Context
Memory leak observed in python version of the code. That is when python wrapper is trying to access PCL C/C++ code to perform clipping. Python is unable to handle the memory
Code snippet causing memory leak
# build the filter
condrem = cloud.make_ConditionalRemoval(range_cond)
condrem.set_KeepOrganized(False)
# apply filter
cloud_filtered = condrem.filter()
C++ equivalent implementation of the above code
// build the filter
pcl::ConditionalRemovalpcl::PointXYZ condrem;
condrem.setCondition (range_cond);
condrem.setInputCloud (cloud);
condrem.setKeepOrganized(true);
// apply filter
condrem.filter (*cloud_filtered);
Code to Reproduce
python code:
import pcl
import numpy as np
import random
import os, psutil, gc, time
def main():
cloud = pcl.PointCloud()
cloud_filtered = pcl.PointCloud()
points = np.zeros((5, 3), dtype=np.float32)
RAND_MAX = 1024.0
for i in range(0, 5):
points[i][0] = 1024 * random.random() / RAND_MAX
points[i][1] = 1024 * random.random() / RAND_MAX
points[i][2] = 1024 * random.random() / RAND_MAX
cloud.from_array(points)
range_cond = cloud.make_ConditionAnd()
range_cond.add_Comparison2('z', pcl.CythonCompareOp_Type.GT, 0.0)
range_cond.add_Comparison2('z', pcl.CythonCompareOp_Type.LT, 0.8)
# build the filter
condrem = cloud.make_ConditionalRemoval(range_cond)
condrem.set_KeepOrganized(False)
# apply filter
cloud_filtered = condrem.filter()
#print('Cloud before filtering: ')
for i in range(0, cloud.size):
print('x: ' + str(cloud[i][0]) + ', y : ' +
str(cloud[i][1]) + ', z : ' + str(cloud[i][2]))
#print('Cloud after filtering: ')
#for i in range(0, cloud_filtered.size):
#print('x: ' + str(cloud_filtered[i][0]) + ', y : ' + str(
#cloud_filtered[i][1]) + ', z : ' + str(cloud_filtered[i][2]))
if name == "main":
# import cProfile
# cProfile.run('main()', sort='time')
#for i in range(50):
print(psutil.Process(os.getpid()).memory_info().rss)
main()
time.sleep(1)
C++ code
#include
#include <pcl/point_types.h>
#include <pcl/filters/conditional_removal.h>
#include <unistd.h>
//using namespace std;
int parseLine(char* line){
// This assumes that a digit will be found and the line ends in " Kb".
int i = strlen(line);
const char* p = line;
while (*p <'0' || *p > '9') p++;
line[i-3] = '\0';
i = atoi(p);
return i;
}
int getValue(){ //Note: this value is in KB!
FILE* file = fopen("/proc/self/status", "r");
int result = -1;
char line[128];
while (fgets(line, 128, file) != NULL){
if (strncmp(line, "VmRSS:", 6) == 0){
result = parseLine(line);
break;
}
}
fclose(file);
return result;
}
int main()
{
std::cerr << getValue() << std::endl;
for (int i=0;i < 1; i++)
{
std::cerr << getValue() << std::endl;
pcl::PointCloudpcl::PointXYZ::Ptr cloud (new pcl::PointCloudpcl::PointXYZ);
pcl::PointCloudpcl::PointXYZ::Ptr cloud_filtered (new pcl::PointCloudpcl::PointXYZ);
// Fill in the cloud data
cloud->width = 5;
cloud->height = 1;
cloud->points.resize (cloud->width * cloud->height);
for (size_t i = 0; i < cloud->points.size (); ++i)
{
cloud->points[i].x = 1024 * rand () / (RAND_MAX + 1.0f);
cloud->points[i].y = 1024 * rand () / (RAND_MAX + 1.0f);
cloud->points[i].z = 1024 * rand () / (RAND_MAX + 1.0f);
}
// build the condition
pcl::ConditionAndpcl::PointXYZ::Ptr range_cond (new
pcl::ConditionAndpcl::PointXYZ ());
range_cond->addComparison (pcl::FieldComparisonpcl::PointXYZ::ConstPtr (new
pcl::FieldComparisonpcl::PointXYZ ("z", pcl::ComparisonOps::GT, 0.0)));
range_cond->addComparison (pcl::FieldComparisonpcl::PointXYZ::ConstPtr (new
pcl::FieldComparisonpcl::PointXYZ ("z", pcl::ComparisonOps::LT, 0.8)));
// build the filter
pcl::ConditionalRemovalpcl::PointXYZ condrem;
condrem.setCondition (range_cond);
condrem.setInputCloud (cloud);
condrem.setKeepOrganized(true);
// apply filter
condrem.filter (*cloud_filtered);
//}
std::cerr << "Cloud before filtering: " << std::endl;
for (size_t i = 0; i < cloud->points.size (); ++i)
std::cerr << " " << cloud->points[i].x << " "
<< cloud->points[i].y << " "
<< cloud->points[i].z << std::endl;
// display pointcloud after filtering
/*std::cerr << "Cloud after filtering: " << std::endl;
for (size_t i = 0; i < cloud_filtered->points.size (); ++i)
std::cerr << " " << cloud_filtered->points[i].x << " "
<< cloud_filtered->points[i].y << " "
<< cloud_filtered->points[i].z << std::endl; */
usleep(1000000);
}
std::cerr << getValue() << std::endl;
return 0;
}
Run Python code using python 3 or higher version. Then run "top " command. The RAM memory keeps increasing.
However, when you run C++ version of the code the memory consumed is constant, and no significant fluctuations in memory are observed.
The problem of memory leak is observed in python code. That is when we are trying to build and apply the filter
build the filter
condrem = cloud.make_ConditionalRemoval(range_cond)
condrem.set_KeepOrganized(False)
# apply filter
cloud_filtered = condrem.filter()
In the above python snippet the function cloud.make is accessing C++/C api's to perfrom point cloud clipping and unbale to handle the memory.
Possible Solution
Is this issue resolved in 1.9.1 PCL
Request to kindly suggest next steps.