asmaloney/libE57Format

WriteData3DGroupsData

dagata-mining opened this issue · 4 comments

Hi,
Im trying to write a code in order to write PCL->E57.
However there's no example on this API. I've been stuck the last couple of days..
I'm getting segment fault on : SetUpData3DPointsData() and I' having a hard time to understand the WriteData3DGroupsData() Parameters
Here's my code for now:

int saveE57File(
        const std::string & filePath,
        const pcl::PointCloud<pcl::PointXYZRGBNormal> & cloud
        )
{
    // Creating the Writer Object from e57
    e57::Writer convert((e57::ustring(filePath)));

    const bool isOpen = convert.IsOpen();

    // Creating the header for the 3D data for e57
    e57::Data3D data3DHeader = data3DGenerator(cloud);
    int64_t indexHeader = convert.NewData3D(data3DHeader);

    // Creating the buffer for writing the points in e5
    e57::Data3DPointsData bufferCloud;
    uint32_t h = cloud.size();

    bufferCloud.cartesianX = new float[h];
    bufferCloud.cartesianY = new float[h];
    bufferCloud.cartesianZ = new float[h];

    for(size_t i=0; i<cloud.size(); ++i)
    {
        bufferCloud.cartesianX [i] = cloud.at(i).x;
        bufferCloud.cartesianY [i] = cloud.at(i).y;
        bufferCloud.cartesianZ [i] = cloud.at(i).z;
        i++;
    }


     convert.SetUpData3DPointsData(indexHeader, h, bufferCloud);


    delete[] bufferCloud.cartesianX;
    delete[] bufferCloud.cartesianY;
    delete[] bufferCloud.cartesianZ;

    //Writing the data to the file
    bool success = convert.WriteData3DGroupsData(indexHeader, 1, 0, 0,h);
    UERROR("Here 5");
    if (!success) {
        UERROR("E57: Could not successfully convert point clod to E57 format");
        return 1;
    } else {
        UERROR("E57: File was written successfully to \"%s\"", filePath.c_str());
        return 0;
    }
}

e57::Data3D data3DGenerator(const pcl::PointCloud<pcl::PointXYZRGBNormal> & cloud,
                            bool hasRGB,
                            bool hasIntensity,
                            bool hasNormals
                            )
{
    // Defining Data 3D header
    e57::Data3D pointCloud;
    pointCloud.name = e57::ustring("Point Laz data");
    pointCloud.description = e57::ustring("An E57 format of data from Point Laz data that uses 2D images and 3D PointCloud");

    pointCloud.sensorVendor = e57::ustring("Lazaruss & XT & 319 Alvium");
    pointCloud.sensorModel = e57::ustring("Point Laz & Hesai & Allied Vision");
    pointCloud.sensorFirmwareVersion = e57::ustring("1.5");
    pointCloud.sensorHardwareVersion = e57::ustring("1.5");
    pointCloud.sensorSoftwareVersion = e57::ustring("1.0");
    pointCloud.sensorSerialNumber = e57::ustring("1");

    pointCloud.temperature=25.0f;
    pointCloud.atmosphericPressure=101.3f;
    pointCloud.relativeHumidity=50.0f;

    e57::DateTime start;
    e57::DateTime end;
    start.dateTimeValue=1633208100;
    end.dateTimeValue=1633208400;
    pointCloud.acquisitionStart=start;
    pointCloud.acquisitionEnd=end;

    e57::RigidBodyTransform pose;
    pointCloud.pose = e57::RigidBodyTransform::identity();

    e57::IndexBounds indexBounds;
    indexBounds.columnMaximum = (int64_t)cloud.width;
    indexBounds.rowMaximum = (int64_t)cloud.height;
    pointCloud.indexBounds=indexBounds;

    e57::CartesianBounds cartesianBounds;
    pcl::PointXYZRGBNormal minPt, maxPt;
    pcl::getMinMax3D (cloud, minPt, maxPt);
    cartesianBounds.xMinimum =  minPt.x;
    cartesianBounds.yMinimum =  minPt.y;
    cartesianBounds.zMinimum =  minPt.z;
    cartesianBounds.xMaximum =  maxPt.x;
    cartesianBounds.yMaximum =  maxPt.y;
    cartesianBounds.zMaximum =  maxPt.z;
    pointCloud.cartesianBounds=cartesianBounds;

    e57::IntensityLimits intensityLimits;
    intensityLimits.intensityMaximum= 255.0;
    intensityLimits.intensityMinimum= 0.;
    pointCloud.intensityLimits=intensityLimits;

    e57::ColorLimits colorLimits;
    colorLimits.colorRedMaximum = 255.0;
    colorLimits.colorGreenMaximum = 255.0;
    colorLimits.colorBlueMaximum = 255.0;
    colorLimits.colorRedMinimum = 0.;
    colorLimits.colorGreenMinimum = 0.;
    colorLimits.colorBlueMinimum = 0.;
    pointCloud.colorLimits=colorLimits;

    e57::PointStandardizedFieldsAvailable standardFields;
    standardFields.cartesianXField = true;
    standardFields.cartesianYField = true;
    standardFields.cartesianZField = true;
    standardFields.normalX = false;
    standardFields.normalY = false;
    standardFields.normalZ = false;
    standardFields.intensityField = false;
    standardFields.colorRedField = false;
    standardFields.colorGreenField = false;
    standardFields.colorBlueField = false;
    if (hasIntensity)
    {
        standardFields.intensityField = true;
    }
    else if (hasRGB)
    {
        standardFields.colorRedField = true;
        standardFields.colorGreenField = true;
        standardFields.colorBlueField = true;
    }
    if (hasNormals)
    {
        standardFields.normalX = true;
        standardFields.normalY = true;
        standardFields.normalZ = true;
    }
    pointCloud.pointFields = standardFields;
    return pointCloud;
}

(Edited by @asmaloney to format code properly)

As I mentioned over here, you should be able to wrap your calls in try/catch to get more info about what's failing and why.

That (and a debugger) should at least get you started to help figure out the crash.

Thanks, much appreciated.
Hadn't seen this issue, helps alot.
But examples would really help. I know you got a pr regarding that, hope it will be there soon for the future users. Anyway great repo btw... I'll post my code when its running properly!

For Anyone Outhere wondering how to convert PCL to E57 here's an example that worked for me:

int saveE57File(
        const std::string & filePath,
        const pcl::PointCloud<pcl::PointXYZRGBNormal> & cloud
        )
{
    // Creating the Writer Object from e57
    e57::Writer convert((e57::ustring(filePath)));

    // Creating the header for the 3D data for e57
    e57::Data3D data3DHeader = data3DGenerator(cloud,false,false,false);
    int64_t indexHeader = convert.NewData3D(data3DHeader);

    // Creating the buffer for writing the points in e5
    e57::Data3DPointsData bufferCloud;
    uint32_t h = cloud.size();

    bufferCloud.cartesianX = new float[h];
    bufferCloud.cartesianY = new float[h];
    bufferCloud.cartesianZ = new float[h];
    
    for(size_t i=0; i<cloud.size(); ++i)
    {
        bufferCloud.cartesianX [i] = cloud.points[i].x;
        bufferCloud.cartesianY [i] = cloud.points[i].y;
        bufferCloud.cartesianZ [i] = cloud.points[i].z;
    }
    e57::CompressedVectorWriter dataWriter = convert.SetUpData3DPointsData(indexHeader, h, bufferCloud);

    try {
        dataWriter.write(h);
    }
    catch ( e57::E57Exception &err )
    {
        UERROR( "Function:\"%s\" In:\"%s\" Line:\"%i\" Context:\"%s\"",err.sourceFunctionName(), err.sourceFileName(), err.sourceLineNumber(), err.context().c_str());
        UERROR("E57: Could not successfully convert point cloud to E57 format");
        return 1;
    }
    dataWriter.close();
    convert.Close();
    delete bufferCloud.cartesianX;
    delete bufferCloud.cartesianY;
    delete bufferCloud.cartesianZ;


    UINFO("E57: File was written successfully to \"%s\"", filePath.c_str());
    return 0;
}

e57::Data3D data3DGenerator(const pcl::PointCloud<pcl::PointXYZRGBNormal> & cloud,
                            bool hasRGB,
                            bool hasIntensity,
                            bool hasNormals
                            )
{
    // Defining Data 3D header
    e57::Data3D pointCloud;
    pointCloud.name = e57::ustring("Point Laz data");
    pointCloud.description = e57::ustring("An E57 format of data from Point Laz data that uses 2D images and 3D PointCloud");
    pointCloud.pointsSize = cloud.size();
    pointCloud.sensorVendor = e57::ustring("Lazaruss & XT & 319 Alvium");
    pointCloud.sensorModel = e57::ustring("Point Laz & Hesai & Allied Vision");
    pointCloud.sensorFirmwareVersion = e57::ustring("1.5");
    pointCloud.sensorHardwareVersion = e57::ustring("1.5");
    pointCloud.sensorSoftwareVersion = e57::ustring("1.0");
    pointCloud.sensorSerialNumber = e57::ustring("1");


    e57::PointStandardizedFieldsAvailable standardFields;
    standardFields.cartesianXField = true;
    standardFields.cartesianYField = true;
    standardFields.cartesianZField = true;
    standardFields.normalX = false;
    standardFields.normalY = false;
    standardFields.normalZ = false;
    standardFields.intensityField = false;
    standardFields.colorRedField = false;
    standardFields.colorGreenField = false;
    standardFields.colorBlueField = false;
    if (hasIntensity)
    {
        standardFields.intensityField = true;
    }
    else if (hasRGB)
    {
        standardFields.colorRedField = true;
        standardFields.colorGreenField = true;
        standardFields.colorBlueField = true;
    }
    if (hasNormals)
    {
        standardFields.normalX = true;
        standardFields.normalY = true;
        standardFields.normalZ = true;
    }
    pointCloud.pointFields = standardFields;



    return pointCloud;
}

(Edited by @asmaloney to format code properly)