엔지니어 동행하기

Robosense LiDAR의 Data Packet과 PointCloud Frame의 관계 본문

Perception Engineering (LiDAR)/LiDAR

Robosense LiDAR의 Data Packet과 PointCloud Frame의 관계

엔지니어 설리번 2022. 7. 30. 09:36
반응형
LiDAR에서 출력되는 데이터 형태(Data Packet)와 실제로 LiDAR를 쓸 때  사용하는 Frame이라는 용어를 데이터 측면에서 연관 지어 설명드리도록 하겠습니다. 이에 대한 구체적인 이해를 하기 위해서는 Data Packet을 decoding 하고 frame으로 만들어 주는 Driver 코드를 알아야 합니다.  

참고로 먼저 확인하면 좋은 포스팅 첨부합니다.

2022.07.24 - [Perception Engineering (LiDAR)/LiDAR] - Robosense LiDAR의 Data Packet 분석: Wireshark 활용

 

Robosense LiDAR의 Data Packet 분석: Wireshark 활용

Wireshark를 이용하면 장비 간 주고받는 데이터를 확인할 수 있습니다. LiDAR를 PC에 연결하고 PC에서 LiDAR의 Data Packet을 파싱해 Point Cloud 데이터를 사용합니다. 이때 이를 계산하는 일련의 과정에서

engineer-sullivan.tistory.com

Data Packet의 물리적 해석

Robosense Ruby LiDAR에서 출력되는 데이터 형식, Data Packet의 형태는 아래와 같습니다.

Data Packet

여기서 알아야 하는 사실은 두 가지 입니다.

1) Header에 있는 timestamp가 전체 Data Packet 데이터에 일괄적으로 적용됩니다.

2) Data Packet에는 3개의 Data Block이 있고, 각 Block에는 128ch의 데이터가 포함됩니다. 이때 128개의 channel data(Data Point)는 Azimuh를 공유합니다. 

따라서 3 * 128 개의 Data Point는 같은 timestamp를 공유합니다. 이를 실제 물리적인 상황에서 아래와 같이 나타낼 수 있습니다. Top view에서 본 모습이고, 각 빨간 선이 128개의 채널을 포함한 Data Block입니다. 

Top view, Data Block

 

Data Packet과 Frame의 관계

LiDAR를 사용할 때, 1 Frame이란 (회전식) LiDAR가 한 바퀴 회전하면서 취득한 데이터를 의미합니다. 그런데 LiDAR의 출력인 Data Packet은 3번의 레이저 Firing 값씩 출력하기 때문에 Driver 코드에서 이를 합쳐서 Frame을 만들어줘야 합니다. 

template <typename vpoint>
E_DECODER_RESULT DecoderBase<vpoint>::processMsopPkt(
    const uint8_t *pkt, std::shared_ptr<std::vector<vpoint>> vec_ptr,
    std::shared_ptr<int> height_ptr) {
  if (pkt == NULL) {
    return E_PARAM_INVALID;
  }

  int azimuth = decodeMsopPkt(pkt, vec_ptr, height_ptr);
  if (azimuth < 0) {
    return E_DECODE_FAIL;
  }
  this->pkt_counter_++;
  if (this->cut_angle_ >= 0) {
    if (azimuth < this->last_azimuth_) {
      this->last_azimuth_ -= 36000;
    }
    if (this->last_azimuth_ != -36001 &&
        this->last_azimuth_ < this->cut_angle_ && azimuth >= this->cut_angle_) {
      this->last_azimuth_ = azimuth;
      this->pkt_counter_ = 0;
      return E_FRAME_SPLIT;
    }
    this->last_azimuth_ = azimuth;
  } else {
    if (this->pkt_counter_ >= this->pkts_per_frame_) {
      this->pkt_counter_ = 0;
      return E_FRAME_SPLIT;
    }
  }

  return E_DECODE_OK;
}

processMsopPkt 함수의 입력 파라미터 pkt은 앞선 본 MSOP Packet입니다. 이 값이 decodeMsopPkt의 입력이 되고, vec_ptr를 출력합니다. 따라서 vec_ptr에는 3 * 128개의 Data Point 정보가 저장됩니다. decodeMsopPkt함수의 return 값은 Data Block0의 azimuth 값입니다. last azimuth는 Data Packet을 처리할 때마다 이전 azimuth 값으로 갱신됩니다.

이런 방식으로 Data Packet마다 processMsopPkt 함수가 동작하고 아래와 같은 방식으로 1 Frame을 만듭니다. 

cut angle을 이용해서 Frame 생성

즉, 계속 E_DECODE_OK를 return하다가 azimuth와 last azimuth 사이에 cut angle이 들어오면 E_FRAME_SPLIT을 return 하고 그때까지의 vec_ptr의 값들을 1 Frame으로 출력하게 됩니다. 

 

Frame과 timestamp

1 Frame에는 23만 개 정도의 Point가 포함됩니다.(Point 개수는 하늘 쪽으로 소실되는 Point 등이 존재하여 항상 같지 않습니다.) 23만개는 앞서 설명한 대로 Data Packet들을 cut_angle을 기준으로 묶은 것이고, 384(= 3*128) 개씩 Point의 timestamp가 동일하다는 것을 알 수 있습니다. 일반적으로 Point Cloud Frame의 timestamp는 가장 최근 384개 Point에 찍힌 timestamp를 사용합니다. 


https://github.com/ApolloAuto/apollo/blob/master/modules/drivers/lidar/robosense/decoder/decoder_base.hpp

 

GitHub - ApolloAuto/apollo: An open autonomous driving platform

An open autonomous driving platform. Contribute to ApolloAuto/apollo development by creating an account on GitHub.

github.com

 

반응형
Comments