# include <iostream>
# include <sstream>
# include <fstream>
# include <random>
# include <algorithm>
# include <cuda_runtime.h>
# include <math.h>
# include "params.h"
# include "laneDet.h"
# include <Eigen/Dense>
# include <ros/ros.h>
# include <pcl/io/pcd_io.h>
# include <pcl/point_cloud.h>
# include <pcl/point_types.h>
# include <pcl_ros/point_cloud.h>
# include <sensor_msgs/PointCloud2.h>
# include <visualization_msgs/Marker.h>
# include <visualization_msgs/MarkerArray.h>
struct PointXYZIRT {
PCL_ADD_POINT4D;
uint8_t intensity;
uint16_t ring;
double timestamp;
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
} EIGEN_ALIGN16;
POINT_CLOUD_REGISTER_POINT_STRUCT ( PointXYZIRT,
( float , x, x)
( float , y, y)
( float , z, z)
( uint8_t , intensity, intensity)
( uint16_t , ring, ring)
( double , timestamp, timestamp)
)
void ConvertPointXYZIRTToPointXYZI ( const pcl:: PointCloud< PointXYZIRT> :: Ptr in_cloud_xyzirt,
pcl:: PointCloud< pcl:: PointXYZI> :: Ptr in_cloud)
{
in_cloud-> header = in_cloud_xyzirt-> header;
in_cloud-> width = in_cloud_xyzirt-> width;
in_cloud-> height = in_cloud_xyzirt-> height;
in_cloud-> is_dense = in_cloud_xyzirt-> is_dense;
for ( size_t i= 0 ; i< in_cloud_xyzirt-> points. size ( ) ; i++ )
{
pcl:: PointXYZI p;
p. x = in_cloud_xyzirt-> points[ i] . x;
p. y = in_cloud_xyzirt-> points[ i] . y;
p. z = in_cloud_xyzirt-> points[ i] . z;
p. intensity = in_cloud_xyzirt-> points[ i] . intensity;
in_cloud-> points. push_back ( p) ;
}
}
std:: string Data_File = "../data/" ;
std:: string Save_Dir = "../eval/kitti/object/pred_velo/" ;
std:: string Model_File = "/home/work_dir/K-Lane/cpp_lane_det/model/best_1215_98.onnx" ;
ros:: Publisher pub_cloud;
ros:: Publisher pub_lane_points;
ros:: Publisher pub_lane_markers;
std_msgs:: Header mHeader;
# define checkCudaErrors ( status) \
{
\
if ( status != 0 ) \
{
\
std:: cout << "Cuda failure: " << cudaGetErrorString ( status) \
<< " at line " << __LINE__ \
<< " in file " << __FILE__ \
<< " error status: " << status \
<< std:: endl; \
abort ( ) ; \
} \
}
void Getinfo ( void )
{
cudaDeviceProp prop;
int count = 0 ;
cudaGetDeviceCount ( & count) ;
printf ( "\nGPU has cuda devices: %d\n" , count) ;
for ( int i = 0 ; i < count; ++ i) {
cudaGetDeviceProperties ( & prop, i) ;
printf ( "----device id: %d info----\n" , i) ;
printf ( " GPU : %s \n" , prop. name) ;
printf ( " Capbility: %d.%d\n" , prop. major, prop. minor) ;
printf ( " Global memory: %luMB\n" , prop. totalGlobalMem >> 20 ) ;
printf ( " Const memory: %luKB\n" , prop. totalConstMem >> 10 ) ;
printf ( " SM in a block: %luKB\n" , prop. sharedMemPerBlock >> 10 ) ;
printf ( " warp size: %d\n" , prop. warpSize) ;
printf ( " threads in a block: %d\n" , prop. maxThreadsPerBlock) ;
printf ( " block dim: (%d,%d,%d)\n" , prop. maxThreadsDim[ 0 ] , prop. maxThreadsDim[ 1 ] , prop. maxThreadsDim[ 2 ] ) ;
printf ( " grid dim: (%d,%d,%d)\n" , prop. maxGridSize[ 0 ] , prop. maxGridSize[ 1 ] , prop. maxGridSize[ 2 ] ) ;
}
printf ( "\n" ) ;
}
int loadData ( const char * file, void * * data, unsigned int * length)
{
std:: fstream dataFile ( file, std:: ifstream:: in) ;
if ( ! dataFile. is_open ( ) )
{
std:: cout << "Can't open files: " << file << std:: endl;
return - 1 ;
}
unsigned int len = 0 ;
dataFile. seekg ( 0 , dataFile. end) ;
len = dataFile. tellg ( ) ;
dataFile. seekg ( 0 , dataFile. beg) ;
char * buffer = new char [ len] ;
if ( buffer== NULL ) {
std:: cout << "Can't malloc buffer." << std:: endl;
dataFile. close ( ) ;
exit ( - 1 ) ;
}
dataFile. read ( buffer, len) ;
dataFile. close ( ) ;
* data = ( void * ) buffer;
* length = len;
return 0 ;
}
void points2Msg ( std:: vector< float4> & points, std:: vector< float3> & color, std:: vector< std:: vector< float4> > & each_lane,
pcl:: PointCloud< pcl:: PointXYZRGB> :: Ptr cloud)
{
for ( size_t i = 0 ; i < points. size ( ) ; ++ i)
{
pcl:: PointXYZRGB p;
int label = points[ i] . w;
for ( int line= 0 ; line < 6 ; ++ line)
{
if ( label == line)
{
p. x = points[ i] . x;
p. y = points[ i] . y;
p. z = points[ i] . z;
int rgb = ( static_cast < int > ( color[ label] . x) << 16 | static_cast < int > ( color[ label] . y) << 8 | static_cast < int > ( color[ label] . z) ) ;
p. rgb = * reinterpret_cast < float * > ( & rgb) ;
cloud-> points. push_back ( p) ;
each_lane[ label] . push_back ( points[ i] ) ;
}
}
}
}
void points2Marker ( std:: vector< float4> & points, float3 & color, std:: vector< double > & coef,
visualization_msgs:: Marker & line)
{
float xMax = 0.0 ;
float xMin = 0.0 ;
double step = 0.5 ;
for ( auto p : points)
{
if ( xMax < p. x) xMax = p. x;
}
int step_num = std:: ceil ( ( xMax - xMin) / step) ;
line. lifetime = ros:: Duration ( 0.3 ) ;
line. type = visualization_msgs:: Marker:: LINE_STRIP;
line. action = visualization_msgs:: Marker:: ADD;
line. ns = "lane" ;
line. scale. x = 0.1 ;
line. color. r = color. x / 255 ;
line. color. g = color. y / 255 ;
line. color. b = color. z / 255 ;
line. color. a = 1. ;
line. pose. orientation. w = 1. ;
for ( size_t j = 0 ; j < step_num + 1 ; ++ j)
{
float x_value = xMin + j * step;
if ( x_value > xMax)
{
x_value = xMax;
}
geometry_msgs:: Point p;
p. x = x_value;
p. y = - ( coef[ 0 ] / coef[ 1 ] ) * x_value - ( coef[ 2 ] / coef[ 1 ] ) ;
p. z = - 1.4 ;
line. points. push_back ( p) ;
}
}
int ransac_line_fitting ( std:: vector< float4> & in_cloud, std:: vector< double > & best_model, std:: vector< float4> & inliers,
int maxiter= 200 , int samples= 2 , int consensus_thres= 10 , double dis_thres= 0.1 )
{
int point_num = in_cloud. size ( ) ;
std:: default_random_engine rng;
rng. seed ( 10 ) ;
std:: uniform_int_distribution< unsigned > uniform ( 0 , point_num- 1 ) ;
std:: set< int > selectIndexs, consensusIndexs;
std:: vector< float4> selectPoints;
int bestconsensus_num = 0 ;
double best_error = 0 ;
double tmp_error = 0 ;
int consensus_error_num = 0 ;
int iter = 0 ;
double tmp_A= 0 , tmp_B= 0 , tmp_C= 0 ;
while ( iter < maxiter)
{
selectIndexs. clear ( ) ;
selectPoints. clear ( ) ;
while ( 1 )
{
int index = uniform ( rng) ;
selectIndexs. insert ( index) ;
if ( selectIndexs. size ( ) == samples)
{
break ;
}
}
std:: set< int > :: iterator selectiter = selectIndexs. begin ( ) ;
while ( selectiter != selectIndexs. end ( ) )
{
int index = * selectiter;
selectPoints. push_back ( in_cloud[ index] ) ;
selectiter++ ;
}
double deltaY = selectPoints[ 1 ] . y - selectPoints[ 0 ] . y;
double deltaX = selectPoints[ 1 ] . x - selectPoints[ 0 ] . x;
tmp_A = deltaY;
tmp_B = - deltaX;
tmp_C = - deltaY * selectPoints[ 1 ] . x + deltaX * selectPoints[ 1 ] . y;
int dataiter = 0 ;
double meanError = 0 ;
std:: set< int > tmpConsensusIndexs;
while ( dataiter < point_num)
{
double dist = ( tmp_A* in_cloud[ dataiter] . x + tmp_B* in_cloud[ dataiter] . y + tmp_C) / sqrt ( tmp_A* tmp_A + tmp_B* tmp_B) ;
dist = dist > 0 ? dist : - dist;
if ( dist <= dis_thres)
{
tmpConsensusIndexs. insert ( dataiter) ;
inliers. push_back ( in_cloud[ dataiter] ) ;
}
meanError += dist;
dataiter++ ;
}
double model_mean_error = 0 ;
if ( tmpConsensusIndexs. size ( ) >= consensus_thres && tmpConsensusIndexs. size ( ) >= bestconsensus_num)
{
bestconsensus_num = consensusIndexs. size ( ) ;
model_mean_error = meanError / point_num;
consensusIndexs. clear ( ) ;
consensusIndexs = tmpConsensusIndexs;
best_model[ 0 ] = tmp_A;
best_model[ 1 ] = tmp_B;
best_model[ 2 ] = tmp_C;
}
if ( model_mean_error < best_error)
{
best_error = model_mean_error;
}
if ( tmp_error != best_error)
{
tmp_error = best_error;
}
else
{
consensus_error_num += 1 ;
if ( consensus_error_num > 10 )
{
break ;
}
}
iter++ ;
}
}
void callback ( const sensor_msgs:: PointCloud2:: Ptr & in_cloud_msg)
{
cudaEvent_t start, stop;
float elapsedTime = 0.0f ;
cudaStream_t stream = NULL ;
checkCudaErrors ( cudaEventCreate ( & start) ) ;
checkCudaErrors ( cudaEventCreate ( & stop) ) ;
checkCudaErrors ( cudaStreamCreate ( & stream) ) ;
LaneDet laneDet ( Model_File, stream) ;
pcl:: PointCloud< PointXYZIRT> :: Ptr in_cloud ( new pcl:: PointCloud< PointXYZIRT> ) ;
pcl:: fromROSMsg ( * in_cloud_msg, * in_cloud) ;
int num_points = in_cloud-> size ( ) ;
float * points_array = new float [ num_points * 255 ] ;
for ( size_t i = 0 ; i < num_points; ++ i) {
PointXYZIRT point = in_cloud-> at ( i) ;
points_array[ i * 4 + 0 ] = point. x;
points_array[ i * 4 + 1 ] = point. y;
points_array[ i * 4 + 2 ] = point. z;
points_array[ i * 4 + 3 ] = point. intensity;
}
unsigned int points_data_size = num_points * 4 * sizeof ( float ) ;
std:: cout << "<char> points num: " << num_points << std:: endl;
std:: cout << "find points num: " << points_data_size << std:: endl;
std:: vector< float4> result;
float * points_data = nullptr ;
checkCudaErrors ( cudaMallocManaged ( ( void * * ) & points_data, points_data_size) ) ;
checkCudaErrors ( cudaMemcpy ( points_data, points_array, points_data_size, cudaMemcpyDefault) ) ;
checkCudaErrors ( cudaDeviceSynchronize ( ) ) ;
cudaEventRecord ( start, stream) ;
laneDet. doinfer ( points_data, num_points, result) ;
cudaEventRecord ( stop, stream) ;
cudaEventSynchronize ( stop) ;
cudaEventElapsedTime ( & elapsedTime, start, stop) ;
std:: cout<< "TIME: laneDet: " << elapsedTime << " ms." << std:: endl;
std:: vector< float3> color = {
{
255 , 0 , 0 } , {
0 , 255 , 0 } , {
0 , 0 , 255 } , {
255 , 255 , 0 } , {
0 , 255 , 255 } , {
255 , 0 , 255 } } ;
pcl:: PointCloud< pcl:: PointXYZRGB> :: Ptr cloud_rgb ( new pcl:: PointCloud< pcl:: PointXYZRGB> ) ;
std:: vector< std:: vector< float4> > each_lane ( 6 ) ;
points2Msg ( result, color, each_lane, cloud_rgb) ;
std:: vector< double > coef_line ( 3 ) ;
std:: vector< float4> inliers;
visualization_msgs:: MarkerArray line_markers;
for ( int i = 0 ; i < each_lane. size ( ) ; ++ i)
{
visualization_msgs:: Marker line_marker;
line_marker. id = i;
line_marker. header = mHeader;
std:: cerr << each_lane[ i] . size ( ) << std:: endl;
int points_num = each_lane[ i] . size ( ) ;
if ( points_num > 3 )
{
ransac_line_fitting ( each_lane[ i] , coef_line, inliers, 200 , 2 , 10 , 0.2 ) ;
points2Marker ( inliers, color[ i] , coef_line, line_marker) ;
line_markers. markers. push_back ( line_marker) ;
}
}
sensor_msgs:: PointCloud2 cloud_msg, cloud_src_msg;
pcl:: toROSMsg ( * cloud_rgb, cloud_msg) ;
pcl:: toROSMsg ( * in_cloud, cloud_src_msg) ;
cloud_msg. header = cloud_src_msg. header = mHeader;
pub_cloud. publish ( cloud_src_msg) ;
pub_lane_points. publish ( cloud_msg) ;
pub_lane_markers. publish ( line_markers) ;
ROS_INFO ( "publish points successfull..." ) ;
std:: cerr << cloud_msg. header << cloud_rgb-> size ( ) << std:: endl;
checkCudaErrors ( cudaFree ( points_data) ) ;
std:: cout << ">>>>>>>>>>>" << std:: endl;
checkCudaErrors ( cudaEventDestroy ( start) ) ;
checkCudaErrors ( cudaEventDestroy ( stop) ) ;
checkCudaErrors ( cudaStreamDestroy ( stream) ) ;
}
class LaneDetector
{
public :
LaneDetector ( ros:: NodeHandle nh) ;
~ LaneDetector ( ) {
} ;
bool doProcess ( ) ;
private :
void callback ( const sensor_msgs:: PointCloud2:: Ptr & msg) ;
} ;
int main ( int argc, char * * argv)
{
ros:: init ( argc, argv, "lane_yht" ) ;
ros:: NodeHandle nh;
pub_cloud = nh. advertise < sensor_msgs:: PointCloud2> ( "/lidar_cloud" , 10 ) ;
pub_lane_points = nh. advertise < sensor_msgs:: PointCloud2> ( "/lane_points" , 10 ) ;
pub_lane_markers = nh. advertise < visualization_msgs:: MarkerArray> ( "/lane_markers" , 10 ) ;
mHeader. frame_id = "base_link" ;
mHeader. stamp = ros:: Time :: now ( ) ;
ros:: Subscriber sub_cloud = nh. subscribe ( "/rslidar_points" , 10 , & callback) ;
ros:: spin ( ) ;
return 0 ;
}
cmake_minimum_required( VERSION 2.8 .7)
project( lane_demo)
find_package( CUDA REQUIRED)
find_package( catkin REQUIRED COMPONENTS
roscpp
pcl_ros
sensor_msgs
)
find_package( PCL REQUIRED)
if( ${CMAKE_HOST_SYSTEM_PROCESSOR} STREQUAL "aarch64" )
set( CMAKE_C_COMPILER /usr/bin/aarch64-linux-gnu-gcc)
set( CMAKE_CXX_COMPILER /usr/bin/aarch64-linux-gnu-g++)
set( CUDA_INSTALL_TARGET_DIR targets/aarch64-linux)
elseif( ${CMAKE_HOST_SYSTEM_PROCESSOR} STREQUAL "x86_64" )
set( CMAKE_C_COMPILER /usr/bin/gcc)
set( CMAKE_CXX_COMPILER /usr/bin/g++)
set( CUDA_INSTALL_TARGET_DIR targets/x86_64-linux)
endif( )
set( CUDA_TOOLKIT_ROOT_DIR /usr/local/cuda)
set( CUDA_INCLUDE_DIRS ${CUDA_TOOLKIT_ROOT_DIR} /${CUDA_INSTALL_TARGET_DIR} /include)
set( CMAKE_BUILD_TYPE "Release" )
set( CMAKE_CXX_FLAGS_RELEASE "-Wno-deprecated-declarations -O2" )
add_compile_options( -W)
add_compile_options( -std= c++11)
set( SMS 30 32 35 37 50 52 53 60 61 62 70 72 75 87 )
foreach( sm ${SMS} )
set( GENCODE ${GENCODE} -gencode arch = compute_${sm} ,code= sm_${sm} )
endforeach( )
set( HIGHEST_SM 87 )
set( GENCODE ${GENCODE} -gencode arch = compute_${HIGHEST_SM} ,code= compute_${HIGHEST_SM} )
set( CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS}
-ccbin ${CMAKE_CXX_COMPILER}
-Xcompiler -DWIN_INTERFACE_CUSTOM
-Xcompiler -I/usr/aarch64-linux-gnu/include/
-Xlinker -lsocket
-Xlinker -rpath = /usr/lib/aarch64-linux-gnu/
-Xlinker -rpath = /usr/aarch64-linux-gnu/lib/
-Xlinker -L/usr/lib/aarch64-linux-gnu/
-Xlinker -L/usr/aarch64-linux-gnu/lib/
)
if( ${CMAKE_BUILD_TYPE} STREQUAL "Debug" )
message( "Using Debug Mode" )
set( CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} -g -G --ptxas-options= -v)
endif( )
set( TENSORRT_INCLUDE_DIRS /opt/TensorRT-8.4.3.1/include)
set( TENSORRT_LIBRARY_DIRS /opt/TensorRT-8.4.3.1/lib)
set( ROS_INCLUDE_DIRS /opt/ros/melodic/include)
set( ROS_LIBRARY_DIRS /opt/ros/melodic/lib)
include_directories(
${CUDA_INCLUDE_DIRS}
${TENSORRT_INCLUDE_DIRS}
include
${ROS_INCLUDE_DIRS}
${PCL_INCLUDE_DIRS}
${catkin_INCLUDE_DIRS}
)
link_directories(
${TENSORRT_LIBRARY_DIRS}
/usr/lib/aarch64-linux-gnu
/usr/aarch64-linux-gnu/lib/
${ROS_LIBRARY_DIRS}
)
file( GLOB_RECURSE SOURCE_FILES
src/*.cu
src/*.cpp
)
cuda_add_executable( ${PROJECT_NAME} main.cpp ${SOURCE_FILES} )
target_link_libraries( ${PROJECT_NAME}
libnvinfer.so
libnvonnxparser.so
${Boost_LIBRARIES}
${catkin_LIBRARIES}
)