c++ - PCL八叉树std::bad_alloc c++
问题描述
我正在使用 PCl 库来压缩激光雷达数据。然后通过 ROS 网络将这些数据与自定义消息一起发送。为此,我有一个压缩节点和一个解压缩节点。如果我运行压缩节点,一切都会按预期工作。然而,当调用 decodePointCloud() 函数时,解压缩节点会给出一个 std::bad_alloc。
为了调试它,我将解压的代码复制到压缩程序中。当我现在运行压缩程序时,它可以工作。激光雷达数据首先被压缩并在同一个文件中解压缩。我用可视化软件rviz验证了这一点。
为什么我在同一个节点解压可以,但是代码在一个单独的节点就不行?我一开始以为是因为内存不足,但是当我在同一个节点解压数据的时候就可以了。我认为这应该占用大约相同数量的内存。
我在带有 Ubuntu 18.04、5gb 内存和 4 个处理器的 VM 上运行这两个程序。
压缩代码:
#include <stdint.h>
#include <ros/ros.h>
// PCL specific includes
#include <sensor_msgs/PointCloud2.h>
#include <pcl_conversions/pcl_conversions.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <inttypes.h>
#include <pcl/compression/octree_pointcloud_compression.h>
#include <stdio.h>
#include <sstream>
#include <stdlib.h>
#include <chrono>
#include <string>
#include <std_msgs/String.h>
#include <bitset>
#include <std_msgs/UInt8MultiArray.h>
#include <stdint.h>
#include <iostream>
#include <vector>
#include <iterator>
//blob message
#include "my_pcl_tutorial/Blob.h"
ros::Publisher pub;
pcl::io::OctreePointCloudCompression<pcl::PointXYZRGBA>* PointCloudEncoder;
void
cloud_cb (const sensor_msgs::PointCloud2ConstPtr& input)
{
// Create a container for the data.
std::string output;
std_msgs::String outputString;
//convert to pointxyzrgba type
pcl::PCLPointCloud2 pcl_pc2;
pcl::PointCloud<pcl::PointXYZRGBA>::Ptr temp_cloud (new pcl::PointCloud<pcl::PointXYZRGBA>);//convert to pointer to satisfy function requirement
pcl_conversions::toPCL(*input, pcl_pc2);
pcl::fromPCLPointCloud2(pcl_pc2, *temp_cloud);
// stringstream to store compressed point cloud
std::stringstream compressedData;
// compress point cloud
PointCloudEncoder->encodePointCloud (temp_cloud, compressedData);
compressedData.seekg(0,ios::end);
int size = compressedData.tellg();
compressedData.seekg(0,ios::beg);
std::cout<<size<<std::endl;
char * buffer = new char[size];
compressedData.read(buffer,size);
uint8_t * tempor = reinterpret_cast<uint8_t *>(buffer);
std::vector<unsigned char> v(tempor, tempor + size);
std::cout<<"Size: "<<v.size()<<std::endl;
my_pcl_tutorial::Blob blobmsg;
blobmsg.data=v;
blobmsg.size=size;
sensor_msgs::PointCloud2 pointcloudheader;
pointcloudheader = *input;
blobmsg.header = pointcloudheader.header;
//////////////////////////////////////////////
/*
//converting back, used for testing
std::stringstream test25;
std::vector<unsigned char> v2(blobmsg.data);
std::cout<<"Size2: "<<v2.size()<<std::endl;
std::cout<<"Size of message: "<<blobmsg.size<<std::endl;
std::copy(v2.begin(), v2.end(), std::ostream_iterator<unsigned char>(test25));
std::cout<<"debug"<<std::endl;
test25.seekg(0,ios::end);
int size2 = test25.tellg();
test25.seekg(0,ios::beg);
std::cout<<size2<<std::endl;
pcl::PointCloud<pcl::PointXYZRGBA>::Ptr cloudOut (new pcl::PointCloud<pcl::PointXYZRGBA> ());
//decompress
PointCloudDecoder->decodePointCloud (test25, cloudOut);
sensor_msgs::PointCloud2 outputmessage;
std::cout<<"Convert to right format now .."<<std::endl;
//save header info since toROSmsg throws away this information
//convert to pointcloud2
pcl::toROSMsg(*cloudOut, outputmessage);
outputmessage.header = blobmsg.header;
std::cout<<outputmessage.header<<std::endl;
/**/
/////////////////////////////
// Publish the data.
pub.publish (blobmsg);
}
int
main (int argc, char** argv)
{
// Initialize ROS
ros::init (argc, argv, "my_pcl_tutorial");
ros::NodeHandle nh;
//\\
//setup compression algorithm
bool showStatistics = false;
pcl::io::compression_Profiles_e compressionProfile = pcl::io::LOW_RES_ONLINE_COMPRESSION_WITHOUT_COLOR;
// instantiate point cloud compression for encoding and decoding
PointCloudEncoder = new pcl::io::OctreePointCloudCompression<pcl::PointXYZRGBA> (compressionProfile, showStatistics);
//\\
// Create a ROS subscriber for the input point cloud
ros::Subscriber sub = nh.subscribe ("velodyne_points", 1, cloud_cb);
// Create a ROS publisher for the output point cloud
pub = nh.advertise<my_pcl_tutorial::Blob> ("velodyne_points/compressed", 1);
// Spin
ros::spin ();
delete(PointCloudEncoder);
}
解压代码:
#include <stdint.h>
#include <ros/ros.h>
// PCL specific includes
#include <sensor_msgs/PointCloud2.h>
#include <pcl_conversions/pcl_conversions.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <inttypes.h>
#include <pcl/compression/octree_pointcloud_compression.h>
#include <stdio.h>
#include <sstream>
#include <stdlib.h>
#include <chrono>
#include <string>
#include <std_msgs/String.h>
#include <iostream>
#include <cstring>
#include <bitset>
#include <std_msgs/UInt8MultiArray.h>
#include <stdint.h>
#include <iostream>
#include <vector>
#include <iterator>
//blob message
//#include "decompression/Blob.h"
#include <my_pcl_tutorial/Blob.h>
ros::Publisher pub;
pcl::io::OctreePointCloudCompression<pcl::PointXYZRGBA>* PointCloudDecoder;
void
cloud_cb (const my_pcl_tutorial::Blob& input)
{
//converting back, used for testing
std::stringstream test25;
std::vector<unsigned char> v2(input.data);
std::cout<<"Size2: "<<v2.size()<<std::endl;
std::cout<<"Size of message: "<<input.size<<std::endl;
std::copy(v2.begin(), v2.end(), std::ostream_iterator<unsigned char>(test25));
std::cout<<"debug"<<std::endl;
test25.seekg(0,ios::end);
int size2 = test25.tellg();
test25.seekg(0,ios::beg);
std::cout<<size2<<std::endl;
pcl::PointCloud<pcl::PointXYZRGBA>::Ptr cloudOut (new pcl::PointCloud<pcl::PointXYZRGBA> ());
//decompress
PointCloudDecoder->decodePointCloud (test25, cloudOut);
sensor_msgs::PointCloud2 outputmessage;
std::cout<<"Convert to right format now .."<<std::endl;
//save header info since toROSmsg throws away this information
//convert to pointcloud2
pcl::toROSMsg(*cloudOut, outputmessage);
outputmessage.header = input.header;
std::cout<<outputmessage.header<<std::endl;
pub.publish(outputmessage);
}
int
main (int argc, char** argv)
{
// Initialize ROS
ros::init (argc, argv, "decompressLidar");
ros::NodeHandle nh;
//\\
//setup compression algorithm
PointCloudDecoder = new pcl::io::OctreePointCloudCompression<pcl::PointXYZRGBA> ();
//\\
// Create a ROS subscriber for the input point cloud
ros::Subscriber sub = nh.subscribe ("velodyne_points/compressed", 1, cloud_cb);
// Create a ROS publisher for the output point cloud
pub = nh.advertise<sensor_msgs::PointCloud2> ("decompress", 1);
// Spin
ros::spin ();
//delete(PointCloudDecoder);
}
解决方案
看起来您正在正确使用/调用 pcl 函数。我有我的怀疑。唯一(除非我错过了什么)decodePointCloud
调用可能抛出错误分配的函数是vector::reserve
. 所以,我怀疑你的内存不足。对于非 ros 分配/使用,请参阅其他 SO 帖子 ( ex )。至于相同节点与不同节点,这是节点和nodelet之间的精确区别:
Nodelets 旨在提供一种在单个机器上、在单个进程中运行多种算法的方法,而不会在进程内传递消息时产生复制成本。roscpp 进行了优化,可以在同一节点内的发布和订阅调用之间进行零复制指针传递。为此,nodelet 允许将类动态加载到同一个节点中,但是它们提供了简单的单独命名空间,因此 nodelet 就像一个单独的节点一样,尽管处于同一个进程中。这已进一步扩展,因为它可以在运行时使用 pluginlib 动态加载。
另请参阅此答案。
推荐阅读
- uwp - 在 UWP 中以编程方式设置 Telerik RadAutoCompleteBox 的 SelectedItem 的推荐方法是什么
- python - Carla 模拟器示例效果不佳
- flutter - 如何使用带有颤振的firebase使用电话号码登录?
- git - 在分支上压缩多个提交
- azure - 如何从 Angular 7 调用图形 AD api
- python - 如何将 CSV 文件作为参数传递给 python 文件
- unix - ps auwx 是什么?grep nginx 是什么意思?
- sql - 找到日期的连续范围
- c# - 我需要丢弃不适合扩展名的文件
- ms-access - MS Access 启用宏内容