Skip to content

适配禾赛OT-128 #447

Description

@ParkerChan

感谢开源!
想咨询下,我的激光雷达是禾赛的OT-128
我查看了工程源码,支持XT-32、AT-128
采集场景:结构化道路、乘用车、路口数据。车速约4~50km/h
我也查看了我自己的点云数据结构,为XYZIRT,对应的timestamp是每个点的绝对时间戳,我就直接适配到的xt32handle,但也加了一个根据相对时间对点云排序的代码:

void Preprocess::xt32_handler(const sensor_msgs::msg::PointCloud2::ConstSharedPtr &msg)
{
  pl_surf.clear();
  pl_corn.clear();
  pl_full.clear();

  pcl::PointCloud<xt32_ros::Point> pl_orig;
  pcl::fromROSMsg(*msg, pl_orig);
  int plsize = pl_orig.points.size();
  pl_surf.reserve(plsize);

  bool is_first[MAX_LINE_NUM];
  double yaw_fp[MAX_LINE_NUM] = {0};     // yaw of first scan point
  double omega_l = 3.61;                 // scan angular velocity
  float yaw_last[MAX_LINE_NUM] = {0.0};  // yaw of last scan point
  float time_last[MAX_LINE_NUM] = {0.0}; // last offset time

  if (pl_orig.points[plsize - 1].timestamp > 0) { given_offset_time = true; }
  else
  {
    given_offset_time = false;
    memset(is_first, true, sizeof(is_first));
    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;

  if (feature_enabled)
  {
    for (int i = 0; i < N_SCANS; i++)
    {
      pl_buff[i].clear();
      pl_buff[i].reserve(plsize);
    }

    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;
      int layer = pl_orig.points[i].ring;
      if (layer >= N_SCANS) continue;
      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 / 1000.0; // units: ms

      if (!given_offset_time)
      {
        double yaw_angle = atan2(added_pt.y, added_pt.x) * 57.2957;
        if (is_first[layer])
        {
          // printf("layer: %d; is first: %d", layer, 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;
        }

        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;
      }

      pl_buff[layer].points.push_back(added_pt);
    }

    for (int j = 0; j < N_SCANS; j++)
    {
      PointCloudXYZI &pl = pl_buff[j];
      int linesize = pl.size();
      if (linesize < 2) continue;
      vector<orgtype> &types = typess[j];
      types.clear();
      types.resize(linesize);
      linesize--;
      for (uint i = 0; i < linesize; i++)
      {
        types[i].range = sqrt(pl[i].x * pl[i].x + pl[i].y * pl[i].y);
        vx = pl[i].x - pl[i + 1].x;
        vy = pl[i].y - pl[i + 1].y;
        vz = pl[i].z - pl[i + 1].z;
        types[i].dista = vx * vx + vy * vy + vz * vz;
      }
      types[linesize].range = sqrt(pl[linesize].x * pl[linesize].x + pl[linesize].y * pl[linesize].y);
      give_feature(pl, types);
    }
  }
  else
  {
    for (int i = 0; i < plsize; i++)
    {
      PointType added_pt;
      // cout<<"!!!!!!"<<i<<" "<<plsize<<endl;

      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;

      // printf("added_pt.curvature: %lf %lf \n", added_pt.curvature,
      // pl_orig.points[i].timestamp);

      // if(i==(plsize-1))  printf("index: %d layer: %d, yaw: %lf, offset-time:
      // %lf, condition: %d\n", i, layer, yaw_angle, added_pt.curvature,
      // prints);
      if (i % point_filter_num == 0)
      {
        double r2 = added_pt.x * added_pt.x + added_pt.y * added_pt.y + added_pt.z * added_pt.z;
        if (r2 > blind_sqr && r2 < 3600)
        {
          pl_surf.points.push_back(added_pt);
          // printf("time mode: %d time: %d \n", given_offset_time,
          // pl_orig.points[i].t);
        }
      }
    }

    auto comparePoints = [](const PointType& a, const PointType& b) -> bool
    {
      return a.curvature < b.curvature;
    };

    std::sort(pl_surf.points.begin(), pl_surf.points.end(), comparePoints);
  }
  // pub_func(pl_surf, pub_full, msg->header.stamp);
  // pub_func(pl_surf, pub_surf, msg->header.stamp);
  // pub_func(pl_surf, pub_corn, msg->header.stamp);
}

我运行lo模式,发现水平方向上的重影比较严重;想询问下,是否是我激光type没有适配正确导致的?
对应的config:请忽略config中线束的数字,因为我将原始的128按ring根据固定步长抽线为32线,取的0,4,8....

/**:
  ros__parameters:
    common:
      img_topic: "/image"
      lid_topic: "/hesai/ot32"
      imu_topic: "/chcnav/devpvt"
      img_en: 0 # 是否使用相机
      lidar_en: 1 # 是否使用激光雷达
      ros_driver_bug_fix: false # 是否修复ROS驱动器bug

    extrin_calib: # 外参 lidar->imu
      extrinsic_T: [0.864749, -0.00179501, 1.62208]
      extrinsic_R: [0.00935207,   -0.999951,  -0.0033473,
                    0.999946,  0.00936742, -0.00459907,
                    0.00463019, -0.00330411,    0.999984]
      Rcl: [-0.00387589,-0.999952, -0.00901998,
            0.0026016, 0.00900993, -0.999956,
            0.999989, -0.00389919, 0.00256655] 
      Pcl: [-0.0483692, -0.76351, -1.47161]

    time_offset: # 时间偏移 
      imu_time_offset: 0.0 # 激光和imu之间的时间差
      img_time_offset: 0.1 # 激光和相机之间的时间差
      exposure_time_init: 0.0 # 曝光时间

    preprocess: # 点云预处理
      point_filter_num: 3 #这里其实是选点的间隔,每搁多少个点选一个点处理,作为系统的待处理点云
      filter_size_surf: 0.1 # # 体素滤波设置 0.1*0.1*0.1 
      # 必须与 common_lib.h 中 LID_TYPE 一致:1=AVIA 2=VELO16 3=OUST64 4=L515 5=XT32 6=PANDAR128
      # 设为 0 会走 preprocess 的 default 分支,不填充点云,易导致空点云段错误(SIGSEGV, exit -11)
      lidar_type: 5
      scan_line: 32 
      blind: 0.1

    vio:
      max_iterations: 5 # ESIKF的最大迭代次数
      outlier_threshold: 1000 # 78 100 156 #100 200 500 700 infinite 每个像素块的阈值
      img_point_cov: 100 # 100 1000 vio观测方程(光度误差)的协方差,也可以说是像素点噪声协方差
      patch_size: 8 # 图像块的尺寸
      patch_pyrimid_level: 4 # 金字塔层数
      normal_en: true # 是否细化法向量,决定是否能够从单应阵获得仿射变换阵
      raycast_en: false # 是否进行体素投射
      inverse_composition_en: false # 是否进行逆补偿,SVO 采用的,Fast-livo2 默认不使用(逆补偿下的状态更新考虑的没有 Fast-livo2 全面)
      exposure_estimate_en: true # 是否估计逆曝光时间
      inv_expo_cov: 0.1 # 逆曝光时间估计的协方差

    imu:
      imu_en: false # 是否使用imu
      imu_int_frame: 30 # 初始化所需要的 IMU 帧数(Fast-LIVO2 需要静止初始化)
      acc_cov: 0.5 # 0.2 加速度计的方差
      gyr_cov: 0.3 # 0.5 陀螺仪的方差
      b_acc_cov: 0.0001 # 0.1 加速度计的偏置协方差
      b_gyr_cov: 0.0001 # 0.1 陀螺仪的偏置协方差

    lio:
      max_iterations: 5 # ESIKF 中的更新迭代次数
      dept_err: 0.02 # 激光雷达的深度误差
      beam_err: 0.05 # 激光雷达的方向误差
      min_eigen_value: 0.0025 # 0.005 # 平面奇异值分解后的最小特征上限(阈值)
      voxel_size: 0.5 # 体素块的大小 0.5*0.5*0.5。有读者可能混淆 filter_size_surf 中设置的体素尺寸,具体就是:系统先将每帧点云用 0.1*0.1*0.1 的体素进行滤波,再用 0.5*0.5*0.5 的体素划分地图。
      max_layer: 2 # 八叉树的最大层数
      max_points_num: 50 # 每个节点的最大存点量
      layer_init_num: [5, 5, 5, 5, 5] # 每个节点的最小存点量

    local_map:  
      map_sliding_en: false # 是否进行滑动地图,当内存较小时使用
      half_map_size: 100 # 地图边长的一半
      sliding_thresh: 8.0 # 每 8 米滑动一次

    uav:
      imu_rate_odom: false
      gravity_align_en: true

    publish:
      dense_map_en: false # 是否进行稠密建图
      pub_effect_point_en: false  # 是否发布有效点
      pub_plane_en: false # 是否发布平面点
      pub_scan_num: 1 # 每次发布的累积点云帧
      blind_rgb_points: 0.0 # 盲区内的 RGB 点值为 0

    evo:
      seq_name: "CBD_Building_01"
      pose_output_en: true

    pcd_save:
      pcd_save_en: true # 是否保存 PCD
      colmap_output_en: false # need to set interval = -1 是否输出 COLMAP 格式
      filter_size_pcd: 0.15 # 对 PCD 文件进行降采样
      # interval: 每个 PCD 的累积帧数。
      # -1: 仅在程序退出时保存一个 all_raw_points.pcd(需 Ctrl+C 正常退出);>0: 运行中按帧数保存 1.pcd, 2.pcd...
      interval: -1 # 建议用 -1 并在退出时 Ctrl+C,否则可能因无 VIO 帧或点云为空而看不到文件

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions