diff --git a/config/hesai.yaml b/config/hesai.yaml new file mode 100644 index 0000000..f9ac431 --- /dev/null +++ b/config/hesai.yaml @@ -0,0 +1,48 @@ +common: + lid_topic: "/hesai/pandar" + imu_topic: "/imu/data" + time_sync_en: false # ONLY turn on when external time synchronization is really not possible + +preprocess: + lidar_type: 4 # 1 for Livox serials LiDAR, 2 for Velodyne LiDAR, 3 for ouster LiDAR, 4 for Hesai LiDAR + scan_line: 32 + blind: 4 + time_scale: 1e-3 # 兼容不同数据集的时间单位,仅对Velodyne LiDAR(lidar_type=2)生效 + +mapping: + acc_cov: 0.1 + gyr_cov: 0.1 + b_acc_cov: 0.0001 + b_gyr_cov: 0.0001 + fov_degree: 180 + det_range: 100.0 + extrinsic_est_en: true # true: enable the online estimation of IMU-LiDAR extrinsic + extrinsic_T: [ 0, 0, 0.28 ] + extrinsic_R: [ 1, 0, 0, + 0, 1, 0, + 0, 0, 1 ] + +publish: + path_publish_en: false + scan_publish_en: true # false: close all the point cloud output + scan_effect_pub_en: true # true: publish the pointscloud of effect point + dense_publish_en: false # false: low down the points number in a global-frame point clouds scan. + scan_bodyframe_pub_en: true # true: output the point cloud scans in IMU-body-frame + +path_save_en: true # 保存轨迹,用于精度计算和比较 + +pcd_save: + pcd_save_en: true + interval: -1 # how many LiDAR frames saved in each pcd file; + # -1 : all frames will be saved in ONE pcd file, may lead to memory crash when having too much frames. + +feature_extract_enable: false +point_filter_num: 6 +max_iteration: 3 +filter_size_surf: 0.5 +filter_size_map: 0.5 +cube_side_length: 1000 + +ivox_grid_resolution: 0.5 # default=0.2 +ivox_nearby_type: 18 # 6, 18, 26 +esti_plane_threshold: 0.1 # default=0.1 \ No newline at end of file diff --git a/include/pointcloud_preprocess.h b/include/pointcloud_preprocess.h index 4b25424..89f9855 100644 --- a/include/pointcloud_preprocess.h +++ b/include/pointcloud_preprocess.h @@ -53,9 +53,30 @@ POINT_CLOUD_REGISTER_POINT_STRUCT(ouster_ros::Point, ) // clang-format on +namespace hesai_ros { +struct EIGEN_ALIGN16 Point { + PCL_ADD_POINT4D; + float intensity; + double timestamp; + uint16_t ring; + EIGEN_MAKE_ALIGNED_OPERATOR_NEW +}; +} // namespace hesai_ros + +// clang-format off +POINT_CLOUD_REGISTER_POINT_STRUCT(hesai_ros::Point, + (float, x, x) + (float, y, y) + (float, z, z) + (float, intensity, intensity) + (double, timestamp, timestamp) + (std::uint16_t, ring, ring) +) +// clang-format on + namespace faster_lio { -enum class LidarType { AVIA = 1, VELO32, OUST64 }; +enum class LidarType { AVIA = 1, VELO32, OUST64, HESAIxt32}; //{1, 2, 3, 4} /** * point cloud preprocess @@ -86,6 +107,7 @@ class PointCloudPreprocess { void AviaHandler(const livox_ros_driver::CustomMsg::ConstPtr &msg); void Oust64Handler(const sensor_msgs::PointCloud2::ConstPtr &msg); void VelodyneHandler(const sensor_msgs::PointCloud2::ConstPtr &msg); + void HesaiHandler(const sensor_msgs::PointCloud2::ConstPtr &msg); PointCloudType cloud_full_, cloud_out_; diff --git a/launch/mapping_hesai.launch b/launch/mapping_hesai.launch new file mode 100644 index 0000000..2a90676 --- /dev/null +++ b/launch/mapping_hesai.launch @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/laser_mapping.cc b/src/laser_mapping.cc index b047958..192286c 100644 --- a/src/laser_mapping.cc +++ b/src/laser_mapping.cc @@ -105,6 +105,9 @@ bool LaserMapping::LoadParams(ros::NodeHandle &nh) { } else if (lidar_type == 3) { preprocess_->SetLidarType(LidarType::OUST64); LOG(INFO) << "Using OUST 64 Lidar"; + } else if (lidar_type == 4) { + preprocess_->SetLidarType(LidarType::HESAIxt32); + LOG(INFO) << "Using Hesai Pandar 32 Lidar"; } else { LOG(WARNING) << "unknown lidar_type"; return false; @@ -199,6 +202,9 @@ bool LaserMapping::LoadParamsFromYAML(const std::string &yaml_file) { } else if (lidar_type == 3) { preprocess_->SetLidarType(LidarType::OUST64); LOG(INFO) << "Using OUST 64 Lidar"; + } else if (lidar_type == 4) { + preprocess_->SetLidarType(LidarType::HESAIxt32); + LOG(INFO) << "Using Hesai Pandar 32 Lidar"; } else { LOG(WARNING) << "unknown lidar_type"; return false; diff --git a/src/pointcloud_preprocess.cc b/src/pointcloud_preprocess.cc index 77be1bc..9788643 100644 --- a/src/pointcloud_preprocess.cc +++ b/src/pointcloud_preprocess.cc @@ -26,6 +26,10 @@ void PointCloudPreprocess::Process(const sensor_msgs::PointCloud2::ConstPtr &msg VelodyneHandler(msg); break; + case LidarType::HESAIxt32: + HesaiHandler(msg); + break; + default: LOG(ERROR) << "Error LiDAR Type"; break; @@ -187,4 +191,88 @@ void PointCloudPreprocess::VelodyneHandler(const sensor_msgs::PointCloud2::Const } } +void PointCloudPreprocess::HesaiHandler(const sensor_msgs::PointCloud2::ConstPtr &msg) +{ + cloud_out_.clear(); + cloud_full_.clear(); + + pcl::PointCloud pl_orig; + pcl::fromROSMsg(*msg, pl_orig); + int plsize = pl_orig.points.size(); + cloud_out_.reserve(plsize); + + /*** These variables only works when no point timestamps given ***/ + double omega_l = 3.61; // scan angular velocity + std::vector is_first(num_scans_,true); + std::vector yaw_fp(num_scans_, 0.0); // yaw of first scan point + std::vector yaw_last(num_scans_, 0.0); // yaw of last scan point + std::vector time_last(num_scans_, 0.0); // last offset time + /*****************************************************************/ + + if (pl_orig.points[plsize - 1].timestamp > 0) { + given_offset_time_ = true; + } else { + given_offset_time_ = false; + double yaw_first = atan2(pl_orig.points[0].y, pl_orig.points[0].x) * 57.29578; + double yaw_end = yaw_first; + int layer_first = pl_orig.points[0].ring; + for (uint i = plsize - 1; i > 0; i--) { + if (pl_orig.points[i].ring == layer_first) { + yaw_end = atan2(pl_orig.points[i].y, pl_orig.points[i].x) * 57.29578; + break; + } + } + } + + double time_head = pl_orig.points[0].timestamp; + + for (int i = 0; i < plsize; i++) { + PointType added_pt; + + added_pt.normal_x = 0; + added_pt.normal_y = 0; + added_pt.normal_z = 0; + added_pt.x = pl_orig.points[i].x; + added_pt.y = pl_orig.points[i].y; + added_pt.z = pl_orig.points[i].z; + added_pt.intensity = pl_orig.points[i].intensity; + added_pt.curvature = (pl_orig.points[i].timestamp - time_head) * 1000.f; // curvature unit: ms + + if (!given_offset_time_) + { + int layer = pl_orig.points[i].ring; + double yaw_angle = atan2(added_pt.y, added_pt.x) * 57.2957; + + if (is_first[layer]) { + yaw_fp[layer]=yaw_angle; + is_first[layer]=false; + added_pt.curvature = 0.0; + yaw_last[layer]=yaw_angle; + time_last[layer]=added_pt.curvature; + continue; + } + + // compute offset time + if (yaw_angle <= yaw_fp[layer]) { + added_pt.curvature = (yaw_fp[layer]-yaw_angle) / omega_l; + } else { + added_pt.curvature = (yaw_fp[layer]-yaw_angle+360.0) / omega_l; + } + + if (added_pt.curvature < time_last[layer]) added_pt.curvature+=360.0/omega_l; + + yaw_last[layer] = yaw_angle; + time_last[layer]=added_pt.curvature; + } + + if (i % point_filter_num_ == 0) + { + if(added_pt.x*added_pt.x+added_pt.y*added_pt.y+added_pt.z*added_pt.z > (blind_ * blind_)) { + cloud_out_.points.push_back(added_pt); + } + } + } + +} + } // namespace faster_lio