엔지니어 동행하기

LiDAR Timestamp(UTC time)의 의미, Frame rate 계산&분석 방법 본문

Perception Engineering (LiDAR)/LiDAR

LiDAR Timestamp(UTC time)의 의미, Frame rate 계산&분석 방법

엔지니어 설리번 2022. 6. 18. 11:04
반응형
LiDAR 데이터를 다루다 보면, Frame 안에 timestamp 정보가 찍혀 있는 것을 알 수 있습니다. 이 Timestamp의 의미가 무엇인지 설명드리고, 이를 이용해서 Frame rate를 계산하는 방법에 대해 알려드리겠습니다. 

2022.06.07 - [Perception Engineering/LiDAR] - Velodyne LiDAR (Alpha Prime, VLS-128) Data Packet, 센서 데이터

 

Velodyne LiDAR (Alpha Prime, VLS-128) Data Packet, 센서 데이터

LiDAR를 통해 얻을 수 있는 데이터의 형태가 어떤 지 설명드리겠습니다. 즉, LiDAR에 전원을 인가하고 Data Port로 Data Packet 이 얻어집니다. 2022.06.06 - [Perception Engineering/LiDAR] - Velodyne LiDAR (A..

engineer-sullivan.tistory.com

 

Timestamp의 의미와 사용하는 이유

  LiDAR 데이터를 다루다 보면 Frame마다 Timestamp 정보로, "1655103186. 409243" 와 같은 숫자를 보게 됩니다. 숫자의  단위는 초(sec)이고, nano sec까지 표현돼 있습니다.

  Timestamp는 어느 시점에 데이터가 존재했다는 사실을 증명하기 위해 데이터에 표시하는 시각입니다. 1970년 1월 1일 자정을 0으로 시작해서(정확하게 표현하면 00:00:00 UTC on January 1, 1970~ 특정 시점까지 얼마나 많은 시간이 지났는지를 통해 특정 시점을 표기합니다. 

1655103186.409243 / 3600 / 24 / 365 = 52.48297 (년)

계산해보면, 1970년 이후 약 52년이 흘렀고, 현재 2022년의 시점을 나타내는 것을 알 수 있습니다. Frame마다 Timestamp를 찍는 방식으로 입력된 LiDAR 데이터 간의 시간차가 얼마나 나는지, 즉 delay가 생겨서 버려야 하는 데이터인지를 판단할 수 있습니다.

 

(참고) Timestamp to Human-Date(YMD, 연월일)

https://www.epochconverter.com/

 

Epoch Converter

Convert Unix Timestamps (and many other date formats) to regular dates.

www.epochconverter.com

timestamp to human-date

해당 사이트를 통해 직접 timestamp 값을 human date로 변환해보면서 timestamp 숫자만 보고 어떤 의미인지 감을 잡아 보시길 바랍니다. 

 

Frame rate 계산

Frame rate는 LiDAR 데이터가 1초에 몇 번 얻어지는지를 나타냅니다. 일반적으로 LiDAR의 경우, Frame rate로 10Hz를 쓰고 1초에 10번 즉 0.1초마다 Frame이 입력되도록 합니다(Timestamp는 0.1초 간격으로 찍힘). 실제로 LiDAR 데이터의 Timestamp 리스트를 얻은 후, Timestamp 간의 time diff를 계산하는 방식으로 Frame rate를 계산할 수 있습니다. 

  LiDAR Timestamp time_diff
1 1655102672.114800  
2 1655102672.218470 0.103670
3 1655102672.322130 0.103660
4 1655102672.425750 0.103620
5 1655102672.541490 0.115740
6 1655102672.645150 0.103660
7 1655102672.852440 0.207290
8 1655102672.956080 0.103640
9 1655102673.163340 0.207260
10 1655102673.266990 0.103650
11 1655102673.370640 0.103650
12 1655102673.474270 0.103630
13 1655102673.681550 0.207280
14 1655102673.785210 0.103660
15 1655102673.888830 0.103620
16 1655102674.096150 0.207320
17 1655102674.199840 0.103690
18 1655102674.510800 0.310960
19 1655102674.614450 0.103650
20 1655102674.821710 0.207260
21 1655102675.029340 0.207630
22 1655102675.132970 0.103630

위의 표는 약 3초 길이 데이터의 Timestamp 리스트입니다. 10Hz라면 30개의 데이터가 얻어져야 하는데, 22개밖에 얻어지지 않았고, delay가 생겨 time diff 도 0.1초보다 긴 부분이 보입니다. 이때, Frame rate는 다음과 같이 구할 수 있습니다.

frame rate = 1 / AVERAGE(time diff) = 7.01 (Hz)

따라서 약 21~22개 데이터가 얻어진 것을 알 수 있습니다.

 

실시간으로 Frame rate 계산하는 코드

위의 방식은 데이터를 얻은 후, 분석하는 방식입니다. 동일한 개념을 적용해서 실시간으로 데이터의 frame rate를 계산하는 코드는 아래와 같습니다.

class FrameRate(object):
    def __init__(self, window_size):
        import threading
        self.lock = threading.Lock()
        self.msg_t0 = -1.
        self.msg_tn = 0
        self.times = []

        if window_size <= 0 or window_size > 50000:
            window_size = 50000
        self.window_size = window_size

    def callback(self, m):
            with self.lock:
                curr_time = Time.now().to_sec()

                if curr_time == 0:
                    if len(self.times) > 0:
                        print("reset times.")
                        self.times = []
                    return

                if self.msg_t0 < 0 or self.msg_t0 > curr_time:
                    self.msg_t0 = curr_time
                    self.msg_tn = curr_time
                    self.times = []
                else:
                    self.times.append(curr_time - self.msg_tn)
                    self.msg_tn = curr_time

                if len(self.times) > self.window_size - 1:
                    self.times.pop(0)
                    
    def calculate(self):
        if not self.times:
            return
        elif self.msg_tn == self.last_printed_tn:
            print("no new messages")
            return
        with self.lock:
            n = len(self.times)
            mean = sum(self.times) / n
            rate = 1. / mean if mean > 0. else 0

            std_dev = math.sqrt(sum((x - mean) ** 2 for x in self.times) / n)

            max_delta = max(self.times)
            min_delta = min(self.times)

            self.last_printed_tn = self.msg_tn

메시지가 들어온 시간(Timestamp)을 저장하는 변수와 time diff를 저장하는 변수인 times가 있습니다. 그리고 window size 변수를 통해 평균을 내는 최대 메시지 개수를 정해줍니다. 메시지가 들어올 때마다 callback함수가 time diff를 저장하고, calculate 함수를 통해 특정 시간 동안의 frame rate를 계산합니다. 

 

Frame rate 분석 방법 (3-sigma rule)

calculate 함수에서 rate와 동시에 std_dev(표준편차) 값을 계산하고 있습니다. 이 값을 통해, Frame rate가 얼마나 비정상적인 값인지를 판단할 수 있습니다. 통계학에는 3-sigma rule이라는 규칙이 있는데, 계산된 표준편차가 3σ 보다 크면 99.73%에 해당하지 않는 매우 비정상적인 값임을 알 수 있습니다.

3-sigma rule


https://github.com/ApolloAuto/apollo/blob/master/cyber/tools/cyber_channel/cyber_channel.py

 

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