Skip to content

Latest commit

 

History

History
464 lines (396 loc) · 16.7 KB

File metadata and controls

464 lines (396 loc) · 16.7 KB

Menu:

1. Voxelization overview

The Component Voxelization is a preprocessing that convert pointcloud to pillars according to the definition in paper PointPillars: Fast Encoders for Object Detection from Point Clouds. The raw point cloud is transformed into a stacked pillar tensor and a pillar index tensor.

And this Component Voxelization is based on FastADAS FadasVM library.

2. Voxelization Configuraion

2.1 Voxelization Static JSON Configuration

Parameter Required Type Description
name true string The Node unique name.
id true uint32_t The Node unique ID.
processorType false string The processor type.
Options: htp0, htp1, cpu, gpu
Default: htp0
coreId false uint32_t The core ID of processor.
Default: 0
Xsize true float Pillar size in X direction in meters.
Ysize true float Pillar size in Y direction in meters.
Zsize true float Pillar size in Z direction in meters.
Xmin true float Minimum range value in X direction.
Ymin true float Minimum range value in Y direction.
Zmin true float Minimum range value in Z direction.
Xmax true float Maximum range value in X direction.
Ymax true float Maximum range value in Y direction.
Zmax true float Maximum range value in Z direction.
maxPointNum true uint32_t Maximum number of point pillars that can be created.
maxPointNumPerPlr true uint32_t Maximum number of points to map to each pillar.
inputMode true string Voxelization input pointclouds type.
Options: xyzr, xyzrt
Default: xyzr
outputFeatureDimNum true uint32_t Number of features for each point in output point pillars.
inputPcdBufferIds false uint32_t[] A list of uint32_t values representing the indices of input pointcloud buffers in QCNodeInit::buffers.
outputPlrBufferIds true uint32_t[] A list of uint32_t values representing the indices of output pillar buffers in QCNodeInit::buffers.
outputFeatureBufferIds true uint32_t[] A list of uint32_t values representing the indices of output pillar buffers in QCNodeInit::buffers.
plrPointsBufferId false uint32_t The index of buffer for maximal pillar point number in QCNodeInit::buffers.
Required if processorType is gpu.
coordToPlrIdxBufferId false uint32_t The index of buffer to store coordinate to pillar point transform indices in QCNodeInit::buffers.
Required if processorType is gpu.
globalBufferIdMap false object[] Mapping of buffer names to buffer indices in QCFrameDescriptorNodeIfs.
Each object contains:
- name (string)
- id (uint32_t)
deRegisterAllBuffersWhenStop false bool Flag to deregister all buffers when stopped
Default: false
  • Example Configurations
    • XYZR mode
      {
        "static": 
            {
                "name": "voxelization",
                "id": 0,
                "processorType": "cpu",
                "Xsize": 0.16,
                "Ysize": 0.16,
                "Zsize": 4.0,
                "Xmin": 0.0,
                "Ymin": -39.68,
                "Zmin": -3.0,
                "Xmax": 69.12,
                "Ymax": 39.68,
                "Zmax": 1.0,
                "maxPointNum": 300000,
                "maxPlrNum": 12000,
                "maxPointNumPerPlr": 32,
                "inputMode": "xyzr",
                "outputFeatureDimNum": 10,
                "outputPlrBufferIds": [0, 1, 2, 3],
                "outputFeatureBufferIds": [4, 5, 6, 7],
                "plrPointsBufferId": 8,
                "coordToPlrIdxBufferId": 9
            }
      }

3. Voxelization APIs

3.1 QCNode Voxelization APIS

3.2 QCNode Configuration Interfaces

  • VoxelizationConfig::GetOptions Get Configuration Options
    • Use this API to get the configuration options.
      • Below was a example output for Voxelization XYZR mode:
        {
          "static":
          {
            "name":"voxelization",
            "id":0,
            "processorType":"gpu",
            "Xmax":69.12,
            "Xmin":0.0,
            "Xsize":0.16,
            "Ymax":39.68,
            "Ymin":-39.68,
            "Ysize":0.16,
            "Zmax":1.0,"
            Zmin":-3.0,
            "Zsize":4.0,
            "inputMode":"xyzr",
            "maxPlrNum":12000,
            "maxPointNum":300000,
            "maxPointNumPerPlr":32,
            "outputFeatureDimNum":10,
            "outputPlrBufferIds":[0,1,2,3],
            "outputFeatureBufferIds":[4,5,6,7],
            "plrPointsBufferId":8,
            "coordToPlrIdxBufferId":9
          }
        }

4. Voxelization Examples

4.1 Voxelization Config initialization

#include "QC/Node/Voxelization.hpp"
#include "QC/sample/BufferManager.hpp"
#include "gtest/gtest.h"

#include <chrono>
#include <fstream>
#include <iostream>
#include <string>

using namespace QC;
using namespace QC::Node;
using namespace QC::sample;

#define EXPAND_JSON( ... ) #__VA_ARGS__

std::string g_Config_XYZR = EXPAND_JSON( {
    "static": {
        "name": "voxelization",
        "id": 0,
        "processorType": "cpu",
        "Xsize": 0.16,
        "Ysize": 0.16,
        "Zsize": 4.0,
        "Xmin": 0.0,
        "Ymin": -39.68,
        "Zmin": -3.0,
        "Xmax": 69.12,
        "Ymax": 39.68,
        "Zmax": 1.0,
        "maxPointNum": 300000,
        "maxPlrNum": 12000,
        "maxPointNumPerPlr": 32,
        "inputMode": "xyzr",
        "outputFeatureDimNum": 10,
        "outputPlrBufferIds": [0, 1, 2, 3],
        "outputFeatureBufferIds": [4, 5, 6, 7],
        "plrPointsBufferId": 8,
        "coordToPlrIdxBufferId": 9
    }
} );

void Init_VoxelizationConfig( std::string &jsonStr, std::string &processorType,
                        std::string &inputMode, const char *pcdFile = nullptr )
{
    QCStatus_e ret;
    DataTree dt;
    DataTree staticCfg;
    QCNodeInit_t config;
    std::string errors;
    uint32_t globalIdx = 0;

    float Xsize = 0;
    float Ysize = 0;
    float Zsize = 0;
    float Xmin = 0;
    float Ymin = 0;
    float Zmin = 0;
    float Xmax = 0;
    float Ymax = 0;
    float Zmax = 0;
    uint32_t maxPointNum = 0;
    uint32_t maxPlrNum = 0;
    uint32_t maxPointNumPerPlr = 0;
    uint32_t inputFeatureDimNum = 0;
    uint32_t outputFeatureDimNum = 0;
    uint32_t plrPointsBufferId = 0;
    uint32_t coordToPlrIdxBufferId = 0;
    uint32_t gridXSize = 0;
    uint32_t gridYSize = 0;
    QCProcessorType_e processor;

    std::vector<uint32_t> outputPlrBufferIds;
    std::vector<uint32_t> outputFeatureBufferIds;

    QC::Node::Voxelization voxel;

    ret = dt.Load( jsonStr, errors );
    if ( QC_STATUS_OK == ret )
    {
        dt.Set<std::string>( "static.processorType", processorType );
        dt.Set<std::string>( "static.inputMode", inputMode );
        ret = dt.Get( "static", staticCfg );
    }
    else
    {
        std::cout << "Get config error: " << errors << std::endl;
    }

    if ( QC_STATUS_OK == ret )
    {
        Xsize = staticCfg.Get<float>( "Xsize", 0 );
        Ysize = staticCfg.Get<float>( "Ysize", 0 );
        Zsize = staticCfg.Get<float>( "Zsize", 0 );
        Xmin = staticCfg.Get<float>( "Xmin", 0 );
        Ymin = staticCfg.Get<float>( "Ymin", 0 );
        Zmin = staticCfg.Get<float>( "Zmin", 0 );
        Xmax = staticCfg.Get<float>( "Xmax", 0 );
        Ymax = staticCfg.Get<float>( "Ymax", 0 );
        Zmax = staticCfg.Get<float>( "Zmax", 0 );
        maxPointNum = staticCfg.Get<uint32_t>( "maxPointNum", 0 );
        maxPlrNum = staticCfg.Get<uint32_t>( "maxPlrNum", 0 );
        maxPointNumPerPlr = staticCfg.Get<uint32_t>( "maxPointNumPerPlr", 0 );
        outputFeatureDimNum = staticCfg.Get<uint32_t>( "outputFeatureDimNum", 0 );
        outputPlrBufferIds =
                staticCfg.Get<uint32_t>( "outputPlrBufferIds", std::vector<uint32_t>{} );
        outputFeatureBufferIds =
                staticCfg.Get<uint32_t>( "outputFeatureBufferIds", std::vector<uint32_t>{} );
        plrPointsBufferId = staticCfg.Get<uint32_t>( "plrPointsBufferId", 0 );
        coordToPlrIdxBufferId = staticCfg.Get<uint32_t>( "coordToPlrIdxBufferId", 0 );
        processor = staticCfg.GetProcessorType( "processorType", QC_PROCESSOR_HTP0 );
    }

    if ( QC_STATUS_OK == ret )
    {
        config = { dt.Dump() };
        std::cout << "config: " << config.config << std::endl;
    }
}

4.2 Buffer allocation and data loading

static void LoadPoints( void *pData, uint32_t size, uint32_t &numPts, const char *pcdFile )
{
    FILE *pFile = fopen( pcdFile, "rb" );

    fseek( pFile, 0, SEEK_END );
    int length = ftell( pFile );
    numPts = length / 16;
    fseek( pFile, 0, SEEK_SET );
    int r = fread( pData, 1, numPts * 16, pFile );
    printf( "load %u points from %s\n", numPts, pcdFile );
    fclose( pFile );
}

TensorDescriptor_t inputTensor;
TensorDescriptor_t outputPlrTensor;
TensorDescriptor_t outputFeatureTensor;
TensorDescriptor_t plrPointsTensor;
TensorDescriptor_t coordToPlrIdxTensor;

TensorProps_t inputTensorProp;
TensorProps_t outputPlrTensorProp;
TensorProps_t outputFeatureTensorProp;
TensorProps_t plrPointsTensorProp;
TensorProps_t coordToPlrIdxTensorProp;

BufferManager bufMgr = BufferManager( { "VOXEL", QC_NODE_TYPE_VOXEL, 0 } );

if ( inputMode == "xyzr" )
{
    inputFeatureDimNum = 4;
}
else if ( inputMode == "xyzrt" )
{
    inputFeatureDimNum = 5;
}

if ( ( maxPointNum > 0 ) && ( inputFeatureDimNum > 0 ) )
{
    inputTensorProp.tensorType = QC_TENSOR_TYPE_FLOAT_32;
    inputTensorProp.dims[0] = maxPointNum;
    inputTensorProp.dims[1] = inputFeatureDimNum;
    inputTensorProp.dims[2] = 0;
    inputTensorProp.numDims = 2;
}

if ( ( maxPlrNum > 0 ) && ( maxPointNumPerPlr > 0 ) && ( outputFeatureDimNum > 0 ) )
{
    if ( inputMode == "xyzrt" )
    {
        outputPlrTensorProp.tensorType = QC_TENSOR_TYPE_INT_32;
        outputPlrTensorProp.dims[0] = maxPlrNum;
        outputPlrTensorProp.dims[1] = 2;
        outputPlrTensorProp.dims[2] = 0;
        outputPlrTensorProp.numDims = 2;
    }
    else
    {
        outputPlrTensorProp.tensorType = QC_TENSOR_TYPE_FLOAT_32;
        outputPlrTensorProp.dims[0] = maxPlrNum;
        outputPlrTensorProp.dims[1] = VOXELIZATION_PILLAR_COORDS_DIM;
        outputPlrTensorProp.dims[2] = 0;
        outputPlrTensorProp.numDims = 2;
    }

    outputFeatureTensorProp.tensorType = QC_TENSOR_TYPE_FLOAT_32;
    outputFeatureTensorProp.dims[0] = maxPlrNum;
    outputFeatureTensorProp.dims[1] = maxPointNumPerPlr;
    outputFeatureTensorProp.dims[2] = outputFeatureDimNum;
    outputFeatureTensorProp.dims[3] = 0;
    outputFeatureTensorProp.numDims = 3;

    size_t gridXSize = ceil( ( Xmax - Xmin ) / Xsize );
    size_t gridYSize = ceil( ( Ymax - Ymin ) / Ysize );

    plrPointsTensorProp.tensorType = QC_TENSOR_TYPE_INT_32;
    plrPointsTensorProp.dims[0] = maxPlrNum + 1;
    plrPointsTensorProp.dims[1] = 0;
    plrPointsTensorProp.numDims = 1;

    coordToPlrIdxTensorProp.tensorType = QC_TENSOR_TYPE_INT_32;
    coordToPlrIdxTensorProp.dims[0] = (uint32_t) ( gridXSize * gridYSize * 2 );
    coordToPlrIdxTensorProp.dims[1] = 0;
    coordToPlrIdxTensorProp.numDims = 1;
}

const uint32_t inputBufferNum = 4;
const uint32_t outputPlrBufferNum = outputPlrBufferIds.size();
const uint32_t outputFeatureBufferNum = outputFeatureBufferIds.size();

TensorDescriptor_t inputTensors[inputBufferNum];
TensorDescriptor_t outputPlrTensors[outputPlrBufferNum];
TensorDescriptor_t outputFeatureTensors[outputFeatureBufferNum];

 QCSharedFrameDescriptorNode frameDesc( 3 );

for ( uint32_t i = 0; i < inputBufferNum; i++ )
{
    ret = bufMgr.Allocate( inputTensorProp, inputTensors[i] );

    uint32_t numPts = 0;
    if ( nullptr == pcdFile )
    {
        if ( nullptr == pcdFile )
        {
            std::cout << "point cloud file is not provided " << std::endl;
        }
    }
    else
    {
        LoadPoints( inputTensors[i].pBuf, inputTensors[i].size, numPts, pcdFile );
        std::cout << "using point cloud file: " << pcdFile << std::endl;
    }
    inputTensors[i].dims[0] = numPts;
}

for ( uint32_t i = 0; i < outputPlrBufferNum; i++ )
{
    ret = bufMgr.Allocate( outputPlrTensorProp, outputPlrTensors[i] );
    config.buffers.push_back( outputPlrTensors[i] );
}

for ( uint32_t i = 0; i < outputFeatureBufferNum; i++ )
{
    ret = bufMgr.Allocate( outputFeatureTensorProp, outputFeatureTensors[i] );
    config.buffers.push_back( outputFeatureTensors[i] );
}

if ( QC_PROCESSOR_GPU == processor )
{
    ret = bufMgr.Allocate( plrPointsTensorProp, plrPointsTensor );
    ret = bufMgr.Allocate( coordToPlrIdxTensorProp, coordToPlrIdxTensor );

    config.buffers.push_back( plrPointsTensor );
    config.buffers.push_back( coordToPlrIdxTensor );
}

4.3 Voxelization execution

ret = frameDesc.SetBuffer( 0, inputTensors[0] );
    
ret = frameDesc.SetBuffer( 1, outputPlrTensors[0] );

ret = frameDesc.SetBuffer( 2, outputFeatureTensors[0] );

ret = voxel.Initialize( config );

ret = voxel.Start();

ret = voxel.ProcessFrameDescriptor( frameDesc );

ret = voxel.Stop();

ret = voxel.DeInitialize();

4.4 Buffer Free

for ( uint32_t i = 0; i < inputBufferNum; i++ )
{
    ret = bufMgr.Free( inputTensors[i] );
}

for ( uint32_t i = 0; i < outputPlrBufferNum; i++ )
{
    ret = bufMgr.Free( outputPlrTensors[i] );
}

for ( uint32_t i = 0; i < outputFeatureBufferNum; i++ )
{
    ret = bufMgr.Free( outputFeatureTensors[i] );
}

if ( QC_PROCESSOR_GPU == processor )
{
    ret = bufMgr.Free( coordToPlrIdxTensor );
    ret = bufMgr.Free( plrPointsTensor );
}

5. References

6. Functional Safety

6.1 ASIL

Node ASIL (or equivalent) Supported Platforms
Voxelization ASIL B SA8797

6.2 Assumptions of Use (SWAOU)

SWAOU: Software Assumption of Use.

QCNODE-VOXELIZATION-SWAOU-1

  • Assumption:
    The user shall ensure that QCNode Voxelization is built, linked, and executed using FastADAS header files and libraries that are fully version‑aligned and compatible with the target FastADAS runtime environment, in order to prevent ABI mismatches, unresolved symbols, or undefined behavior during initialization and execution.

  • Sample of "How AoU can be met?":
    The user shall verify that the FastADAS header files used during compilation match the FastADAS libraries linked and loaded at runtime.

  • SW AoU Rationale:
    Prevents ABI mismatches, unresolved symbols, or undefined behavior that could compromise the integrity and stability of the Voxelization node.