AEGLOSLAB ROS 2 Jazzy 대전

제7부 센서·인지 파이프라인

7.7 시간 동기화 — message_filters·PTP

7.7.1 이 장에서 배우는 것 / 선수 지식

센서가 여럿이면 같은 순간의 데이터를 짝지어야 한다. 스테레오 두 이미지, 이미지와 CameraInfo(7.2.9), 라이다와 IMU(7.5.8), 카메라와 깊이. 그런데 각 센서는 서로 다른 주기로, 서로 다른 시각에, 서로 다른 지연을 거쳐 도착한다.

이 장은 그 정렬 문제를 다룬다. 소프트웨어로 짝짓는 방법(message_filters)과 하드웨어로 애초에 동시에 측정하는 방법(트리거·PTP), 그리고 둘의 선택 기준.

1.10.8과 5.2.4에서 "시계 동기화를 초기 인프라로 세우라"고 반복했는데, 이 장이 그 구체적 방법이다.

배우는 것:

  • 정렬 문제의 구조 — 무엇이 어긋나는가.
  • message_filters — 정확 동기·근사 동기.
  • 정책 튜닝 — 큐 크기·시간 허용오차.
  • tf2_ros::MessageFilter — tf 준비를 기다리는 필터.
  • 하드웨어 동기 — 트리거·PPS·PTP.
  • 소프트웨어 시계 동기 — chrony 실무.
  • 지연 예산 — 센서에서 판단까지.
  • 정책 수치 실측(7.7.12) — slop·큐 크기의 실제 임계값과 실패의 모양.

선수 지식: 1.10(시계·시간), 5.2(tf 시간 함정), 7.1(스탬프 규약), 7.2.9(이미지·CameraInfo 짝), 7.6(융합).

정직: PTP·하드웨어 동기의 달성 정밀도는 장비·구성에 크게 의존한다. 아래 수치는 일반적으로 알려진 범위이며 (확인 필요)다. PTP·하드웨어 동기 부분은 이 환경에서 검증하지 않았다(목차 3). 반면 message_filters의 정책 수치는 Jazzy에서 확인했다(실행 확인 — 7.7.12) — 그 과정에서 slop 공식을 정정했다.

7.7.2 정렬 문제의 구조

물리 현상 (t=0) 센서 A 측정 t=0 센서 B 측정 t=0.017 (주기 차이) A 전송·처리 지연 B 전송·처리 지연 A 도착 t=0.020 B 도착 t=0.025 소비 노드

어긋나는 원인이 세 층이다:

층원인대처
측정 시각센서 주기·위상이 다름하드웨어 동기(7.7.6)
시계 기준머신·MCU마다 다른 시계시계 동기(7.7.7)
도착 순서전송·처리 지연 차이message_filters(7.7.3)

중요한 구분: message_filters는 세 번째 문제만 푼다. 이미 스탬프에 기록된 시각을 기준으로 짝을 짓는 것이지, 측정 시각 자체를 맞추지는 못한다. 스탬프가 틀렸으면 정확히 틀린 짝을 만든다.

견해: "스탬프가 정확하다"가 모든 것의 전제다. 1.10.6(획득 시점에 기록하기)·7.1.6(헤더 규약)·5.2.4(시계 동기)가 지켜지지 않으면 이 장의 도구가 무의미하다. 순서는 ① 스탬프 정확 → ② 시계 동기 → ③ 소프트웨어 정렬이다.

7.7.3 message_filters — 소프트웨어 정렬

여러 토픽의 메시지를 스탬프 기준으로 짝지어 하나의 콜백으로 전달한다.

7.7.3.1 정확 동기(ExactTime)

#include "message_filters/subscriber.h"
#include "message_filters/time_synchronizer.h"

message_filters::Subscriber<Image> left_sub(node, "left/image_rect");
message_filters::Subscriber<Image> right_sub(node, "right/image_rect");

message_filters::TimeSynchronizer<Image, Image> sync(left_sub, right_sub, 10);
sync.registerCallback(
    [](const Image::ConstSharedPtr & l, const Image::ConstSharedPtr & r) {
      // 스탬프가 정확히 같은 쌍만 온다
    });

스탬프가 나노초까지 정확히 일치해야 짝이 된다.

적합부적합
하드웨어 트리거 스테레오독립 클럭 센서
같은 드라이버가 만든 메시지서로 다른 머신
이미지 + CameraInfo(같은 시각 설정 — 7.2.9)주기가 다른 센서

함정: 정확 동기는 대부분의 경우 짝을 못 짓는다. 두 센서가 독립적으로 동작하면 나노초까지 같을 확률은 0이다. "콜백이 전혀 안 불린다"의 흔한 원인이며, 이때 근사 동기로 바꿔야 한다.

7.7.3.2 근사 동기(ApproximateTime)

#include "message_filters/sync_policies/approximate_time.h"

using SyncPolicy = message_filters::sync_policies::ApproximateTime<Image, PointCloud2>;

message_filters::Synchronizer<SyncPolicy> sync(SyncPolicy(10), image_sub, cloud_sub);
sync.setMaxIntervalDuration(rclcpp::Duration::from_seconds(0.05));   // 허용오차
sync.registerCallback(&MyNode::callback, this);

스탬프가 "충분히 가까운" 쌍을 찾는다. 알고리즘이 최적 조합을 찾으려 하므로 약간의 지연이 발생한다.

파라미터의미
큐 크기(생성자 인자)각 토픽에서 보관할 메시지 수
setMaxIntervalDuration허용 시간 차이 상한
setAgePenalty오래된 메시지 페널티(확인 필요)
setInterMessageLowerBound같은 토픽 메시지 간 최소 간격(확인 필요)

Python:

import message_filters

image_sub = message_filters.Subscriber(self, Image, 'image')
cloud_sub = message_filters.Subscriber(self, PointCloud2, 'points')

sync = message_filters.ApproximateTimeSynchronizer(
    [image_sub, cloud_sub], queue_size=10, slop=0.05)
sync.registerCallback(self.callback)

slop이 허용 시간 차이(초)다.

7.7.4 정책 튜닝

큐 크기와 허용오차가 성능을 좌우한다.

큐 크기 작다: 짝 못 찾음 메시지 유실 크다: 메모리· 지연 증가 허용오차(slop) 작다: 짝이 드물다 크다: 틀린 짝 시간 정합 오차

큐 크기 산정:

$$Q \geq \left\lceil \frac{\Delta t_{\max}}{T_{\text{fast}}} \right\rceil + \text{여유}$$

여기서 $\Delta t_{\max}$는 두 토픽의 최대 도착 시간 차이, $T_{\text{fast}}$는 빠른 쪽의 주기.

예: 이미지 30 Hz(33 ms), 라이다 10 Hz(100 ms). 라이다가 이미지보다 최대 200 ms 늦게 올 수 있다면 $Q \geq 200/33 \approx 6$, 여유를 두어 10.

허용오차 산정:

$$\text{slop} \approx \frac{1}{2}\min(T_A, T_B) = \frac{1}{2}T_{\text{fast}}$$

빠른 쪽 주기의 절반이 출발점이다 — 느린 쪽이 아니다(실행 확인, 7.7.12.1). 빠른 토픽이 촘촘하므로, 느린 토픽의 어떤 메시지에도 그 절반 안에 짝이 하나는 있다.

조합$\tfrac{1}{2}T_{\text{fast}}$실측 임계값
30 Hz + 30 Hz(독립)16.7 ms15 ms
30 Hz + 10 Hz16.7 ms17 ms
100 Hz + 10 Hz5.0 ms5 ms
50 Hz + 5 Hz10.0 ms10 ms

이 책은 앞선 판에서 이 공식을 $\tfrac{1}{2}\max(T_A,T_B)$ 로 적었다 — 느린 쪽 기준이었다. 그러면 100 Hz + 10 Hz에 50 ms를 권하게 되는데 실측 임계값은 5 ms다. 필요한 것보다 열 배 큰 slop이고, 바로 아래 견해가 경고하는 시간 정합 오차를 그만큼 스스로 불러들인다. 정정한다.

견해: slop을 근거 없이 키우지 말라. 짝은 잘 지어지지만 시간 정합 오차가 그만큼 들어온다. 로봇이 1 m/s로 움직이면 50 ms slop은 5 cm 오차다(5.2.3의 계산과 같다). 짝이 안 지어지면 slop을 키우기 전에 원인을 보라 — 대개 스탬프나 주기 문제다.

함정: 동기화 실패는 조용하다. 콜백이 안 불릴 뿐 오류가 없다. 짝지어진 수와 버려진 수를 세어 진단으로 내보내라(6.9).

// 개별 구독으로 도착 수를 세고, 동기 콜백에서 짝 수를 센다
void on_image_raw(...) { ++image_count_; }
void on_synced(...)    { ++synced_count_; }
// 진단: synced_count_ / min(image_count_, cloud_count_) 비율

견해: 동기화 성공률이 90% 미만이면 설정이나 스탬프에 문제가 있다. 이 지표를 진단으로 두면 "결과가 가끔 안 나온다"의 원인을 즉시 안다.

7.7.5 tf2_ros::MessageFilter

메시지를 변환할 수 있을 때까지 기다렸다 콜백을 호출한다.

#include "tf2_ros/message_filter.h"

message_filters::Subscriber<LaserScan> scan_sub(node, "scan");
tf2_ros::MessageFilter<LaserScan> tf_filter(
    scan_sub, *tf_buffer_, "odom", 10, node);
tf_filter.registerCallback(&MyNode::on_scan, this);

void MyNode::on_scan(const LaserScan::ConstSharedPtr & scan) {
  // 이 시점에 "odom" 으로의 변환이 가능함이 보장된다
  auto tf = tf_buffer_->lookupTransform("odom", scan->header.frame_id,
                                        scan->header.stamp);
}

5.2.2.1의 "타임아웃 대기"를 구조적으로 해결한다. 콜백 안에서 블로킹 대기하는 대신, 변환이 준비될 때까지 메시지를 큐에 보관한다.

이점설명
executor를 막지 않는다블로킹 대기 없음(5.2.2.1)
외삽 오류 감소tf가 준비된 뒤 처리
자동 폐기큐 초과·너무 오래된 것은 버림

함정: 큐가 차면 오래된 메시지가 버려진다. tf가 계속 안 오면 데이터를 조용히 잃는다. 폐기 콜백이 있으면 등록해 진단으로 내보내라(확인 필요: API 제공 여부).

견해: Nav2·AMCL 같은 성숙한 패키지가 이 필터를 쓴다. 센서 데이터를 tf와 함께 처리해야 하는 노드를 만든다면 직접 대기 로직을 구현하기보다 이것을 검토하라.

7.7.6 하드웨어 동기

소프트웨어 정렬의 한계를 넘으려면 애초에 동시에 측정해야 한다.

동기 신호원 카메라 1 트리거 카메라 2 트리거 라이다 PPS IMU 샘플링 같은 순간의 데이터
방법정밀도(대략)적용
하드웨어 트리거마이크로초 이하스테레오 카메라
PPS(초당 펄스)마이크로초GNSS·라이다
PTP(IEEE 1588)마이크로초이더넷 센서
gPTP·TSN서브 마이크로초산업용
소프트웨어(NTP·chrony)밀리초일반

정직: 위 수치는 이상적 조건의 일반 범위이며 실제 달성치는 하드웨어·네트워크·부하에 크게 의존한다(확인 필요). 자신의 시스템에서 측정해야 한다.

하드웨어 트리거 스테레오:

두 카메라가 같은 트리거 신호로 노출을 시작한다. 스탬프가 정확히 같으므로 ExactTime 동기가 가능하다(7.7.3).

견해: 스테레오·다중 카메라 시스템에서 하드웨어 트리거는 사실상 필수다. 소프트웨어 동기로는 노출 시각 차이를 없앨 수 없고, 움직이는 장면에서 시차 계산이 어긋난다. 카메라 선택 단계에서 트리거 입력이 있는 모델을 요구사항에 넣으라.

PTP 구성:

# PTP 데몬 (linuxptp)
sudo ptp4l -i eth0 -m -S          # 소프트웨어 타임스탬프
sudo ptp4l -i eth0 -m             # 하드웨어 타임스탬프(NIC 지원 필요)

# PTP 시계를 시스템 시계에 반영
sudo phc2sys -a -r -m

# 상태 확인
pmc -u -b 0 'GET CURRENT_DATA_SET'

함정: PTP의 정밀도는 NIC의 하드웨어 타임스탬프 지원에 달렸다. 소프트웨어 타임스탬프만 되는 NIC에서는 정밀도가 크게 떨어진다. ethtool -T eth0으로 지원 여부를 확인하라.

ethtool -T eth0 | grep -A5 "Time stamping"

PPS 활용:

GNSS가 주는 초당 펄스를 커널이 받아 시계를 정렬한다. 실외 로봇에서 여러 컴퓨터의 시계를 정밀하게 맞추는 데 쓰인다(확인 필요: 구성 방법은 하드웨어 의존).

7.7.7 소프트웨어 시계 동기

대부분의 시스템에서 실용적인 선택이다(1.10.8).

# chrony 설치·설정
sudo apt install chrony

# /etc/chrony/chrony.conf — 로봇 내부 마스터
# 주 컴퓨터를 서버로
local stratum 10
allow 192.168.1.0/24

# 다른 컴퓨터에서
server 192.168.1.10 iburst minpoll 0 maxpoll 4

# 상태 확인
chronyc tracking
chronyc sources -v
항목확인
System time오프셋
RMS offset안정성
Frequency클럭 드리프트
Last offset최근 보정량

견해: 로봇 내부에서는 외부 NTP 서버가 아니라 로봇의 주 컴퓨터를 시각 기준으로 삼으라. 인터넷이 끊겨도 로봇 내부는 일관되고, 네트워크 지연이 작아 정밀도가 높다. 절대 시각이 필요하면 주 컴퓨터만 외부와 동기하면 된다.

함정: 부팅 직후 시계가 크게 불연속적으로 변한다. chrony가 시각을 맞추는 순간 점프가 발생하고, 그 시점의 tf·스탬프가 어긋난다(1.10.4). 시계 동기가 안정된 뒤 노드를 시작하거나, 시간 점프 콜백으로 대응한다(5.2.2.2).

# 부팅 시 동기 대기 (systemd — 14.8)
# [Unit]
# After=chrony-wait.service
# 또는 스크립트에서
chronyc waitsync 30 0.01     # 30회 시도, 오차 0.01초까지

MCU 동기(6.8.7): micro-ROS는 자체 동기 API를 제공하지만 정밀도는 전송 지연에 좌우된다. 정밀한 시각이 필요한 MCU 센서에는 하드웨어 PPS가 표준적 방법이다.

7.7.8 지연 예산

"센서가 본 것이 판단에 반영되기까지 얼마나 걸리는가."

물리 현상 센서 측정·노출 센서 내부 처리 전송(USB·이더넷) 드라이버 수신 ROS 발행 전송(DDS) 처리 노드 판단·명령
구간전형적 크기관련 장
노출·측정센서 의존—
센서 내부수 ms—
전송(USB·이더넷)수 ms6.7
드라이버수 ms6.7
DDS 전달수 ms(대용량이면 더)3.2
처리대개 지배적7.8
동기화 대기slop만큼7.7.4

$$t_{\text{총}} = t_{\text{센서}} + t_{\text{전송}} + t_{\text{처리}} + t_{\text{동기}} + t_{\text{판단}}$$

측정 방법:

// 종단 지연 — 원본 스탬프를 끝까지 전파해야 측정 가능
const auto age = now() - rclcpp::Time(result->header.stamp, clock_type);
latency_stats_.record(age.seconds() * 1000.0);   // p50·p99·max(2.5.6)

이것이 7.2.5에서 "헤더를 전파하라"고 한 이유 중 하나다 — 파이프라인 끝에서 원본 측정 시각을 알아야 종단 지연을 측정할 수 있다.

견해: 지연 예산을 명시적으로 세우라. "장애물을 보고 멈추기까지 300 ms"라는 요구가 있다면, 그것을 구간별로 배분하고 각각을 측정한다. 이것 없이는 어디를 최적화할지 알 수 없고, 대개 예상과 다른 곳이 병목이다.

지연이 만드는 오차:

$$\varepsilon \approx v \cdot t_{\text{지연}}$$

1 m/s에서 300 ms 지연은 30 cm다. 이것이 안전 여유(safety margin) 설계의 근거가 된다(8.7·14.10).

7.7.9 진단·검증

# 두 토픽의 스탬프 차이 관찰
ros2 topic echo /image/header/stamp --once
ros2 topic echo /points/header/stamp --once

# 도착 지연 (스탬프 vs 수신 시각) — tf2_monitor 유사 개념
ros2 run tf2_ros tf2_monitor          # tf에 대해서는(5.1.10)

# 시계 동기 상태
chronyc tracking
chronyc sources

검증 항목:

항목방법
동기화 성공률짝 수 / 입력 수(7.7.4)
스탬프 차이 분포두 토픽의 스탬프 히스토그램
도착 지연스탬프와 수신 시각의 차
시계 오프셋chronyc tracking
종단 지연원본 스탬프 → 결과(7.7.8)

견해: "스탬프 차이 분포"를 한 번 그려 보라. 두 센서의 스탬프 차이가 어떻게 분포하는지 보면, slop을 얼마로 설정해야 할지가 즉시 보인다. 분포가 넓거나 이중 봉우리를 보이면 근본 문제(주기 불일치·시계 오프셋)가 있는 것이다.

# 개념: 스탬프 차이 관측 노드
def on_synced(img, cloud):
    dt = (Time.from_msg(img.header.stamp) -
          Time.from_msg(cloud.header.stamp)).nanoseconds / 1e6
    self.dt_samples.append(dt)      # 히스토그램·백분위수로 분석

7.7.12 동기화 정책을 수치로 확인했다 — 실측

7.7.4의 두 공식(큐 크기·slop)은 논리로 유도한 것이라 수치 근거가 없었다. message_filters의 ApproximateTimeSynchronizer에 스탬프를 직접 입력해 측정해 봤다(실행 확인, Jazzy).

방법: SimpleFilter.signalMessage()로 메시지를 직접 넣으면 네트워크·스케줄링 잡음 없이 결정적으로 측정할 수 있다. 두 스트림에 독립 위상(무작위 오프셋)과 1 ms 지터를 주고, 시드 5회 평균으로 "짝지어진 수 ÷ 느린 쪽 메시지 수"를 봤다.

7.7.12.1 slop — 기준은 빠른 쪽이었다

성공률 90%를 넘는 최소 slop을 1 ms 간격으로 찾았다.

조합$\tfrac{1}{2}T_{\text{fast}}$$\tfrac{1}{2}T_{\text{slow}}$실측 임계값
30 Hz + 30 Hz16.7 ms16.7 ms15 ms
30 Hz + 10 Hz16.7 ms50 ms17 ms
100 Hz + 10 Hz5.0 ms50 ms5 ms
50 Hz + 5 Hz10.0 ms100 ms10 ms

네 조합 모두 $\tfrac{1}{2}T_{\text{fast}}$ 와 일치했다. 느린 쪽 주기는 아무 관계가 없었다.

왜 그런가는 생각해 보면 당연하다 — 빠른 토픽이 촘촘하므로, 느린 토픽의 메시지가 언제 오든 그 주변 $\pm\tfrac{1}{2}T_{\text{fast}}$ 안에 빠른 쪽 메시지가 반드시 하나 있다. 느린 쪽은 짝을 찾는 쪽이지 제약하는 쪽이 아니다.

실무적으로 이 차이가 크다. 100 Hz + 10 Hz에서 느린 쪽 기준으로 50 ms를 설정하면 필요한 것(5 ms)의 열 배다. 7.7.4의 견해대로 1 m/s에서 50 ms는 5 cm 오차인데, 5 ms면 5 mm다. 공식 하나로 정합 오차가 10배 달라진다.

7.7.12.2 큐 크기 — 공식이 정확했고, 실패는 급격한 붕괴다

느린 토픽 B가 스탬프보다 늦게 도착하도록(전송·처리 지연) 두고 큐 크기를 바꿔 가며 측정했다(30 Hz + 10 Hz, slop 17 ms).

B 도착 지연$\lceil \Delta t / T_{\text{fast}} \rceil$q=1q=2q=3q=5q=10q=20
0 ms0100%100%100%100%100%100%
50 ms23.2%100%100%100%100%100%
100 ms30.2%0.6%52%100%100%100%
200 ms60.2%0.6%1.0%1.6%100%100%
500 ms150.2%0.6%1.0%1.6%3.2%100%

7.7.4의 공식 $Q \geq \lceil \Delta t_{\max}/T_{\text{fast}} \rceil$ 가 임계값을 정확히 맞힌다. 50 ms → 2, 100 ms → 3, 200 ms → 6, 500 ms → 15 — 모두 그 값 이상에서 100%가 된다. "여유를 두어라"는 조언도 맞다(100 ms에서 q=3은 52%로 걸치고 q=5에서 완전해진다).

더 중요한 것은 실패의 모양이다.

큐가 하나 모자라면 성공률이 완만히 떨어지는 것이 아니라 1~3%로 급락한다. 90%가 60%가 되는 것이 아니라 사실상 0이 된다. 7.7.4가 "동기화 실패는 조용하다"고 한 것에 하나를 더해야 한다 — 조용할 뿐 아니라 전부 아니면 전무다.

이것이 진단에 주는 지침: 동기 콜백이 "가끔 안 불린다"면 큐 문제가 아닐 가능성이 높다(큐 문제였다면 거의 안 불린다). 반대로 거의 안 불린다면 큐를 먼저 의심하라 — slop을 키워도 해결되지 않는다.

7.7.12.3 확인하지 못한 것

  • 실제 ROS 전송을 거치지 않았다. signalMessage()로 직접 적용했으므로 구독 QoS·유실·콜백 지연의 영향은 빠져 있다. 실물에서는 성공률이 이보다 낮을 수 있다.
  • ExactTime 정책과 tf2_ros::MessageFilter는 측정하지 않았다(확인 필요).
  • C++ 구현의 동작이 Python과 같은지 확인하지 않았다(확인 필요) — message_filters는 두 언어에 별도 구현이 있다.

7.7.10 함정 카탈로그

#함정증상대처
1ExactTime을 독립 센서에콜백이 전혀 안 불림ApproximateTime
2slop을 근거 없이 키움시간 정합 오차 유입원인 진단 우선
3큐 크기 부족짝을 못 찾음지연 차이로 산정
4동기화 실패를 못 알아챔결과가 가끔 없음성공률 진단
5스탬프가 발행 시각정확히 틀린 짝획득 시각(1.10.6)
6시계 미동기(다중 머신)체계적 오프셋chrony·PTP
7부팅 직후 시계 점프tf·스탬프 어긋남동기 대기·점프 콜백
8콜백에서 tf 블로킹 대기executor 정지tf2_ros::MessageFilter
9MessageFilter 폐기를 못 봄조용한 데이터 손실폐기 진단
10스테레오를 소프트웨어 동기로시차 오차하드웨어 트리거
11PTP를 NIC 지원 확인 없이기대 정밀도 미달ethtool -T
12헤더 미전파종단 지연 측정 불가헤더 복사(7.2.5)
13지연 예산 없음최적화 방향 불명구간별 측정
14slop을 느린 쪽 주기로 산정필요의 수 배 — 정합 오차를 자초빠른 쪽 주기의 절반(7.7.12.1)
15짝이 거의 안 지어지는데 slop만 키움해결 안 됨큐 부족을 먼저 의심(7.7.12.2)

7.7.11 체크포인트

  • 정렬 문제의 세 층과 각각의 대처를 말할 수 있는가. message_filters가 푸는 것은 어느 층인가.
  • "스탬프가 정확하다"가 왜 모든 것의 전제인가. 우선순위 순서는?
  • ExactTime이 적합한 경우와, 독립 센서에 쓰면 무슨 일이 생기는가.
  • 큐 크기와 slop을 산정하는 식을 쓸 수 있는가. slop을 키우면 무엇을 지불하는가.
  • 동기화 실패가 조용한 이유와, 이를 감지하는 지표는?
  • tf2_ros::MessageFilter가 5.2.2.1의 어떤 문제를 구조적으로 해결하는가.
  • 하드웨어 동기 방법 다섯 가지의 정밀도 순서를 말할 수 있는가. 스테레오에 트리거가 필수인 이유는?
  • PTP의 정밀도가 무엇에 달렸으며, 어떻게 확인하는가.
  • 로봇 내부 시계 기준을 외부 NTP가 아니라 주 컴퓨터로 두라는 조언의 근거는?
  • 부팅 직후 시계 점프가 만드는 문제와 두 가지 대처는?
  • 지연 예산의 구간 일곱 가지와, 대개 지배적인 것은? 종단 지연을 측정하려면 무엇이 필요한가.
  • 1 m/s에서 300 ms 지연이 만드는 오차는 얼마이며, 그것이 무엇의 근거가 되는가.
  • slop의 기준은 빠른 쪽 주기인가 느린 쪽인가. 왜 그런가(7.7.12.1).
  • 큐가 하나 모자랄 때 성공률은 어떻게 변하는가. 그것이 진단에 뜻하는 바는(7.7.12.2).

다음 장 7.8는 제7부의 마지막 — 이 모든 센서 데이터를 파이프라인으로 조립하는 설계를 다룬다. 대역·CPU·지연을 함께 만족시키는 구조.