Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Calibration problem,Ask for help #315

Open
Sisyphus-neo opened this issue Mar 24, 2024 · 0 comments
Open

Calibration problem,Ask for help #315

Sisyphus-neo opened this issue Mar 24, 2024 · 0 comments
Labels
question Further information is requested

Comments

@Sisyphus-neo
Copy link

Describe your question
A clear and concise description of your question.
I'm calibrating lidar and imu, and I use Li _ calib, https://github.com/April-zju/lidar _ IMU _ calib.git. The problem now is that the algorithm needs to extend the radar by itself, but I can't get the required parameters correspondingly, so I hope to get help.
The part of the code that needs to be modified:
#ifndef VELODYNE_CORRECTION_HPP
#define VELODYNE_CORRECTION_HPP

#include <ros/ros.h>
#include <velodyne_msgs/VelodynePacket.h>
#include <velodyne_msgs/VelodyneScan.h>
#include <sensor_msgs/PointCloud2.h>
#include <pcl_ros/point_cloud.h>
#include <angles/angles.h>
#include
#include

#include <utils/pcl_utils.h>

namespace licalib {

class VelodyneCorrection {
public:
typedef std::shared_ptr Ptr;

enum ModelType {
ouster_32,
};

VelodyneCorrection(ModelType modelType = ouster_32) : m_modelType(modelType) {
setParameters(m_modelType);
}

void unpack_scan(const ouster_ros::Cloud::ConstPtr &lidarMsg,
TPointCloud &outPointCloud) const
{

  outPointCloud.clear();
  outPointCloud.header = pcl_conversions::toPCL(lidarMsg->header);
  //设置点云格式
  if (m_modelType == ModelType::RS_32)
  {
    outPointCloud.height = 32;
    outPointCloud.width = 12 * (int)lidarMsg->packets.size();
    outPointCloud.is_dense = false; //点云中的数据不都是有限的,包含inf/NaN 值
    outPointCloud.resize(outPointCloud.height * outPointCloud.width);
  }

  int block_counter = 0;

  double scan_timestamp = lidarMsg->header.stamp.toSec();

  for (size_t i = 0; i < lidarMsg->packets.size(); ++i) // lidarMsg->packets.size():packet总数
  {
    float azimuth; //方位
    float azimuth_diff;
    float last_azimuth_diff = 0;
    float azimuth_corrected_f;
    int azimuth_corrected;
    float x, y, z;

    const raw_packet_t *raw = (const raw_packet_t *)&lidarMsg->packets[i].data[0]; //将第i个packets的data数据(1204个字节)赋值给自定义数据类型raw_packet_t的对象

    for (int block = 0; block < BLOCKS_PER_PACKET; block++, block_counter++) //遍历12个block块
    {
      // Calculate difference between current and next block's azimuth angle.
      //计算当前block和下一block的角度差
      azimuth = (float)(raw->blocks[block].rotation);

      if (block < (BLOCKS_PER_PACKET - 1))
      {
        azimuth_diff = (float)((36000 + raw->blocks[block + 1].rotation - raw->blocks[block].rotation) % 36000);
        last_azimuth_diff = azimuth_diff;
      }
      else
      {
        azimuth_diff = last_azimuth_diff;
      }

      for (int firing = 0, k = 0; firing < FIRINGS_PER_BLOCK; firing++) //一个block有两个firing(直接改为1个)
      {
        for (int dsr = 0; dsr < SCANS_PER_FIRING; dsr++, k += RAW_SCAN_SIZE) //每个firing有16个点(改为32)
        {

          /** Position Calculation ,2字节距离值*/
          union two_bytes tmp;
          //RS-32的距离数据前一个字节是高位,后一个字节是低位,与VLP-16相反 ?
          tmp.bytes[0] = raw->blocks[block].data[k + 1];
          tmp.bytes[1] = raw->blocks[block].data[k];

          /** correct for the laser rotation as a function of timing during the firings **/
          azimuth_corrected_f = azimuth + (azimuth_diff * (dsr * DSR_TOFFSET) / BLOCK_TDURATION); //该点的角度值
          //四舍五入并转化为整型2
          azimuth_corrected = ((int)round(azimuth_corrected_f)) % 36000;

          /*condition added to avoid calculating points which are not
      in the interesting defined area (min_angle < area < max_angle)(添加条件以避免计算不在感兴趣的定义区域内的点)*/
          if ((azimuth_corrected >= m_config.min_angle && azimuth_corrected <= m_config.max_angle && m_config.min_angle < m_config.max_angle) || (m_config.min_angle > m_config.max_angle && (azimuth_corrected <= m_config.max_angle || azimuth_corrected >= m_config.min_angle)))
          {
            // convert polar coordinates to Euclidean XYZ(将极坐标转换为欧几里得 XYZ)
            float distance = tmp.uint * DISTANCE_RESOLUTION; //距离值乘以分辨率 

            float cos_vert_angle = cos_vert_angle_[dsr];
            float sin_vert_angle = sin_vert_angle_[dsr];

            float cos_rot_angle = cos_rot_table_[azimuth_corrected];
            float sin_rot_angle = sin_rot_table_[azimuth_corrected];
            //将极坐标下的角度和距离信息转化为笛卡尔坐标系下的 x,y,z 坐标
            x = distance * cos_vert_angle * sin_rot_angle;
            y = distance * cos_vert_angle * cos_rot_angle;
            z = distance * sin_vert_angle;

            /** Use standard ROS coordinate system (right-hand rule) ——使用标准 ROS 坐标系(右手法则)*/
            float x_coord = y;
            float y_coord = -x;
            float z_coord = z;
            // 反射率
            float intensity = raw->blocks[block].data[k + 2];
            double point_timestamp = scan_timestamp + getExactTime(scan_mapping_32[dsr],block_counter ); //激光点的时间戳
            //定义云点
            TPoint point;
            point.timestamp = point_timestamp;
            //距离满足要求,则将求得的值赋值给云点,否则赋值NAN
            if (pointInRange(distance))
            {
              point.x = x_coord;
              point.y = y_coord;
              point.z = z_coord;
              point.intensity = intensity;
            }
            else
            {
              point.x = NAN;
              point.y = NAN;
              point.z = NAN;
              point.intensity = 0;
            }
            //如果为RS_32的激光雷达,赋值给点云
            if (m_modelType == ModelType::ouster_32)
              outPointCloud.at(block_counter , scan_mapping_32[dsr]) = point;
          }
        }
      }
    }
  }
}

 //点云格式转换函数(将PointCloud2格式点云转换为XYZIT格式点云)
void unpack_scan(const sensor_msgs::PointCloud2::ConstPtr &lidarMsg,
                 TPointCloud &outPointCloud) const
{
  VPointCloud temp_pc; //XYZI格式点云
  pcl::fromROSMsg(*lidarMsg, temp_pc); //将PointCloud2格式转换为XYZI格式

  outPointCloud.clear();
  outPointCloud.header = pcl_conversions::toPCL(lidarMsg->header);// 时间戳的转换
  outPointCloud.height = 32;
  outPointCloud.width = temp_pc.size() / 32;
  outPointCloud.is_dense = true;
  outPointCloud.resize(outPointCloud.height * outPointCloud.width);

  double timebase = lidarMsg->header.stamp.toSec(); //初始时间
  for (int h = 0; h < outPointCloud.height; h++)
  {
    for (int w = 0; w < outPointCloud.width; w++)
    {
      TPoint point; //XYZIT格式云点
  pcl::PointXYZI& rs_point =  temp_pc[w + h * temp_pc.size() / 32];

      point.x = rs_point.x;
      point.y = rs_point.y;
      point.z = rs_point.z;
      point.intensity = rs_point.intensity;
      point.timestamp = timebase + getExactTime(h, w); //计算云点时间戳
      outPointCloud.at(w, h) = point;
    }
  }
}

inline double getExactTime(int dsr, int firing) const {
return mOS32TimeBlock[firing][dsr];
}

private:
void setParameters(ModelType modelType) {
m_modelType = modelType;
m_config.max_range = 120;
m_config.min_range = 0.3;
m_config.min_angle = 0;
m_config.max_angle = 36000;
// Set up cached values for sin and cos of all the possible headings
for (uint16_t rot_index = 0; rot_index < ROTATION_MAX_UNITS; ++rot_index) {
float rotation = angles::from_degrees(ROTATION_RESOLUTION * rot_index);
cos_rot_table_[rot_index] = cosf(rotation);
sin_rot_table_[rot_index] = sinf(rotation);
}

if (modelType ==ouster_32) {
  FIRINGS_PER_BLOCK =   12;
  SCANS_PER_FIRING  =  3;
  BLOCK_TDURATION   = 100.00f;   // [µs]
  DSR_TOFFSET       =   0.00f;   // [µs]
  FIRING_TOFFSET    =  0.00f;   // [µs]
  PACKET_TIME = (BLOCKS_PER_PACKET*2*FIRING_TOFFSET);

  float vert_correction[16] = {
          -0.2617993877991494,
          0.017453292519943295,
          -0.22689280275926285,
          0.05235987755982989,
          -0.19198621771937624,
          0.08726646259971647,
          -0.15707963267948966,
          0.12217304763960307,
          -0.12217304763960307,
          0.15707963267948966,
          -0.08726646259971647,
          0.19198621771937624,
          -0.05235987755982989,
          0.22689280275926285,
          -0.017453292519943295,
          0.2617993877991494
  };
  for(int i = 0; i < 16; i++) {
    cos_vert_angle_[i] = std::cos(vert_correction[i]);
    sin_vert_angle_[i] = std::sin(vert_correction[i]);
  }
  scan_mapping_16[0]=15;
  scan_mapping_16[1]=7;
  scan_mapping_16[2]=14;
  scan_mapping_16[3]=6;
  scan_mapping_16[4]=13;
  scan_mapping_16[5]=5;
  scan_mapping_16[6]=12;
  scan_mapping_16[7]=4;
  scan_mapping_16[8]=11;
  scan_mapping_16[9]=3;
  scan_mapping_16[10]=10;
  scan_mapping_16[11]=2;
  scan_mapping_16[12]=9;
  scan_mapping_16[13]=1;
  scan_mapping_16[14]=8;
  scan_mapping_16[15]=0;

  for(unsigned int w = 0; w < 1824; w++) {
    for(unsigned int h = 0; h < 16; h++) {
      mOS32TimeBlock[w][h] = h * 2.304 * 1e-6 + w * 55.296 * 1e-6; /// VLP_16 16*1824
    }
  }
}

}

inline bool pointInRange(float range) const {
return (range >= m_config.min_range
&& range <= m_config.max_range);
}

private:
static const int RAW_SCAN_SIZE = 3;
static const int SCANS_PER_BLOCK = 32;
static const int BLOCK_DATA_SIZE = (SCANS_PER_BLOCK * RAW_SCAN_SIZE);
constexpr static const float ROTATION_RESOLUTION = 0.01f;
static const uint16_t ROTATION_MAX_UNITS = 36000u;
constexpr static const float DISTANCE_RESOLUTION = 0.002f;

/** @todo make this work for both big and little-endian machines */
static const uint16_t UPPER_BANK = 0xeeff;
static const uint16_t LOWER_BANK = 0xddff;

static const int BLOCKS_PER_PACKET = 12;
static const int PACKET_STATUS_SIZE = 2;

int FIRINGS_PER_BLOCK;
int SCANS_PER_FIRING;
float BLOCK_TDURATION;
float DSR_TOFFSET;
float FIRING_TOFFSET;
float PACKET_TIME ;

float sin_rot_table_[ROTATION_MAX_UNITS];
float cos_rot_table_[ROTATION_MAX_UNITS];
float cos_vert_angle_[32];
float sin_vert_angle_[32];
int scan_mapping_16[16];
int scan_mapping_32[32];

typedef struct raw_block {
uint16_t header; ///< UPPER_BANK or LOWER_BANK
uint16_t rotation; ///< 0-35999, divide by 100 to get degrees
uint8_t data[BLOCK_DATA_SIZE];
} raw_block_t;

union two_bytes {
uint16_t uint;
uint8_t bytes[2];
};

union four_bytes {
uint32_t uint32;
float_t float32;
};

typedef struct raw_packet {
raw_block_t blocks[BLOCKS_PER_PACKET];
uint32_t revolution;
uint8_t status[PACKET_STATUS_SIZE];
} raw_packet_t;

/** configuration parameters */
typedef struct {
double max_range; ///< maximum range to publish
double min_range;
int min_angle; ///< minimum angle to publish
int max_angle; ///< maximum angle to publish
} Config;
Config m_config;

ModelType m_modelType;

double mOS32TimeBlock[1824][16];
};

}

#endif

Screenshots
If applicable, add screenshots to help explain your problem.

Platform (please complete the following information):

  • Ouster Sensor? [e.g. OS-0, OS-1, ..] OS1-32-U3
  • Ouster Firmware Version? [e.g. 2.3, 2.4, ..] 2.4
  • ROS version/distro? [e.g. noetic, foxy, humble, ..] noetic
  • Operating System? [e.g. Linux, Windows, MacOS] linux
  • Machine Architecture? [e.g. x64, arm] arm
  • git commit hash (if not the latest).
@Sisyphus-neo Sisyphus-neo added the question Further information is requested label Mar 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

1 participant