AEGLOSLAB ROS 2 Jazzy 대전

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

7.1 센서 메시지 규약 — REP 103·105·145

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

로봇 소프트웨어에서 가장 비용이 큰 버그는 단위와 좌표 규약을 틀리는 것이다. 컴파일도 되고 실행도 되고 값도 그럴듯한데, 로봇이 잘못된 방향으로 간다. 그리고 원인을 찾기까지 며칠이 걸린다.

ROS 생태계는 이 문제를 REP(ROS Enhancement Proposal) 로 표준화했다. REP 103(단위·좌표), REP 105(프레임), REP 145(IMU)가 그것이며, Nav2·MoveIt 2·robot_localization·tf2가 전부 이 규약을 전제한다. 규약을 어기면 라이브러리가 조용히 틀린 답을 낸다.

이 장은 제7부의 기초를 세운다. 이후 장들(이미지·포인트클라우드·IMU·융합)이 전부 여기 의존한다.

배우는 것:

  • REP 103 — 단위·좌표계·회전 표현의 표준.
  • REP 105 — 프레임 계층과 각 프레임의 의미(5.1.7 심화).
  • REP 145 — IMU 데이터 규약.
  • 광학 프레임 — 왜 예외가 있는가.
  • 표준 센서 메시지 — 각각의 의미론과 필수 필드.
  • 공분산 규약 — 표현 방식과 "모름"을 나타내는 법.
  • 위반의 결과 — 무엇이 어떻게 깨지는가.

선수 지식: 5.1(tf·REP 105 개요), 1.2.7(표준 인터페이스), 1.10.6(타임스탬프를 기록하는 지점).

정직: 단위와 공분산 "모름" 표현은 Jazzy에 설치된 sensor_msgs의 메시지 정의를 직접 열어 확인했다(7.1.12) — .msg 파일 주석이 규약의 정본이고, 상당수 (확인 필요)가 그것으로 해소됐다. 프레임 이름 관행처럼 드라이버에 달린 항목은 여전히 확인이 필요하다(목차 3).

7.1.2 REP 103 — 단위와 좌표

단위는 SI다. 예외 없다.

물리량단위
길이미터(m)
질량킬로그램(kg)
시간초(s)
각도라디안(rad)
주파수헤르츠(Hz)
힘뉴턴(N)
토크뉴턴미터(N·m)
속도m/s
각속도rad/s
가속도m/s²
온도섭씨(℃) — Temperature.msg가 "Degrees Celsius"로 명시(실행 확인)

함정: 각도가 도(degree)가 아니라 라디안이다. 센서 드라이버가 도를 주면 변환해야 하고, 이것을 빠뜨리면 57배 오차가 난다. 드라이버 코드에서 변환 지점을 명확히 표시하라.

좌표계: 오른손 좌표계.

로봇 몸체 기준 base_link x: 앞(forward) y: 왼쪽(left) z: 위(up)
축방향회전(오른손 법칙)
x앞roll(굴림)
y왼쪽pitch(끄덕임)
z위yaw(방향) — 반시계가 양

"y가 왼쪽"이 중요하다. 자동차 공학이나 항공(NED: North-East-Down)에서는 다른 규약을 쓰므로, 그쪽 배경에서 온 사람이 자주 틀린다.

규약xyz쓰는 곳
ROS(ENU 계열)앞·동왼쪽·북위ROS 전체
NED앞·북오른쪽·동아래항공·해양
비전(광학)오른쪽아래앞OpenCV·카메라

함정: 드론·항공 배경의 코드를 가져오면 NED일 가능성이 높다. z 부호가 반대이므로 고도가 음수로 나오거나 상하가 뒤집힌다. 좌표 변환을 명시적 함수로 만들고 이름에 규약을 적으라(ned_to_enu()).

지리 좌표: 야외 로봇에서는 ENU(East-North-Up) 를 쓴다. map 프레임의 x가 동쪽, y가 북쪽, z가 위다.

회전 표현:

표현ROS에서
쿼터니언메시지의 표준(geometry_msgs/Quaternion)
회전 행렬계산 중간
오일러각(RPY)URDF·사람 입력용. 고정축 x-y-z 순

함정: 쿼터니언이 정규화되지 않으면 tf2가 거부하거나 비정상적인 결과를 낸다. 직접 만들 때는 정규화를 확인하고, w=0, x=y=z=0인 영 쿼터니언은 유효하지 않다 — 초기화 시 w=1로 두어야 한다. 메시지 구조체의 기본값이 전부 0이므로 이것을 빠뜨리는 실수가 흔하다.

geometry_msgs::msg::Quaternion q;   // 전부 0 — 무효!
q.w = 1.0;                          // 항등 회전으로 초기화

7.1.3 REP 105 — 프레임 계층

5.1.7에서 개요를 봤다. 여기서는 센서 관점으로 확장한다.

earth map odom base_link base_footprint (선택) laser_link camera_link camera_optical_frame imu_link
프레임정의센서 관점
earth지구 고정(ECEF)GNSS 다중 map 연결
map세계 고정전역 측위 결과
odom오도메트리 기준연속 — 지역 인지의 기준
base_link로봇 본체센서 장착의 기준
base_footprint지면 투영2D 항법 편의(확인 필요: 선택적 관행)
센서 프레임각 센서데이터의 frame_id

센서 데이터의 frame_id는 그 센서의 물리적 위치여야 한다.

scan.header.frame_id = "laser_link";      // ✅ 센서 자체
scan.header.frame_id = "base_link";       // ❌ 센서가 아닌 곳
scan.header.frame_id = "";                // ❌ 비어 있음
scan.header.frame_id = "/laser_link";     // ❌ 앞 슬래시(1.1.11)

함정: frame_id를 base_link로 두면 센서 오프셋이 무시된다. 라이다가 로봇 앞 20 cm에 있는데 base_link라고 하면, 장애물이 20 cm 가까이 있는 것으로 계산된다. URDF에 위치를 정의했어도 frame_id가 틀리면 소용없다.

견해: base_footprint의 사용 여부는 시스템마다 다르다. Nav2 설정에서 어느 것을 쓰는지 확인하고 일관되게 유지하라. 2D 항법에서는 지면 투영이 편리하지만, 필수는 아니다.

7.1.4 광학 프레임 — 규약의 예외

카메라만 다른 축 규약을 쓴다. 컴퓨터 비전 관례(OpenCV) 때문이다.

프레임xyz
camera_link앞왼쪽위
camera_optical_frame오른쪽아래앞
고정 회전 camera_link ROS 규약 (x 앞) camera_optical_frame 비전 규약 (z 앞) 이미지 처리 결과는 이 프레임 기준

둘 사이의 변환은 고정 회전이다:

<!-- URDF에서 (5.3) -->
<joint name="camera_optical_joint" type="fixed">
  <origin xyz="0 0 0" rpy="${-pi/2} 0 ${-pi/2}"/>
  <parent link="camera_link"/>
  <child link="camera_optical_frame"/>
</joint>

어느 쪽을 frame_id로 쓰는가:

데이터프레임
sensor_msgs/Imagecamera_optical_frame
sensor_msgs/CameraInfocamera_optical_frame(7.3)
이미지에서 계산한 3D 점camera_optical_frame
깊이 카메라 포인트클라우드camera_optical_frame(확인 필요: 드라이버마다 다를 수 있다)

함정: 이것을 혼동하면 결과가 90도씩 회전한다. 5.1.11의 7번에서 예고한 것이며, 실무에서 매우 흔하다. "검출한 물체가 옆에 있다고 나온다"의 전형적 원인이다.

견해: 카메라 드라이버가 두 프레임과 그 사이 변환을 함께 제공하는지 확인하라. 제공하지 않으면 URDF에 직접 추가해야 하며, 회전값을 틀리면 조용한 오차가 된다. rpy="-1.5708 0 -1.5708"이 표준 값이다.

7.1.5 REP 145 — IMU 규약

IMU는 규약이 특히 까다롭다.

sensor_msgs::msg::Imu imu;
imu.header.frame_id = "imu_link";
imu.header.stamp = measurement_time;      // 측정 시각(1.10.6)

// 방향 (쿼터니언) — 없으면 covariance[0] = -1
imu.orientation = q;
imu.orientation_covariance = {...};

// 각속도 (rad/s) — 센서 프레임 기준
imu.angular_velocity.x = wx;

// 선가속도 (m/s²) — ★ 중력 포함
imu.linear_acceleration.z = az;

핵심 규약:

항목규약
데이터 프레임IMU 자체 프레임(frame_id), 축은 REP 103
선가속도중력을 포함한다 — 정지 시 z ≈ +9.81
각속도rad/s, 오른손 법칙
방향 기준ENU 기준(x 동, y 북, z 위)(확인 필요: 센서·드라이버마다 다름)
없는 데이터해당 공분산의 첫 원소를 -1

함정: "중력 포함"이 가장 자주 틀린다. 정지한 IMU가 z축 +9.81을 보고해야 하는데, 어떤 센서·드라이버는 중력을 뺀 "선형 가속도"를 준다. 이것을 그대로 쓰면 robot_localization(7.6)이 로봇이 자유낙하 중이라고 판단한다.

// 정지 상태에서 확인 — 가장 빠른 검증
// ros2 topic echo /imu/data --field linear_acceleration
// z ≈ 9.81 이어야 정상 (센서가 수평일 때)

함정: 방향(orientation)의 기준이 센서마다 다르다. 어떤 IMU는 자북 기준, 어떤 것은 전원 인가 시점 기준, 어떤 것은 방향을 전혀 제공하지 않는다. 드라이버 문서를 확인하고, 융합에 쓸 때 무엇을 신뢰할지 명시적으로 결정하라(7.6).

"데이터 없음" 표현:

// 방향을 제공하지 않는 IMU
imu.orientation_covariance[0] = -1.0;     // 이 필드를 무시하라는 신호

이 규약을 지키지 않으면 소비자가 쓰레기 값을 신뢰한다. 방향이 0인데 공분산이 정상이면, 융합 노드는 "로봇이 항등 자세"라고 믿는다.

7.1.6 표준 센서 메시지

메시지용도핵심 주의
Image이미지encoding·optical frame(7.2)
CompressedImage압축 이미지format 필드
CameraInfo카메라 파라미터Image와 같은 스탬프·프레임(7.3)
PointCloud23D 점field 레이아웃(7.4)
LaserScan2D 스캔각도·시간 규약(7.5)
Imu관성중력 포함(7.1.5)
MagneticField자기장테슬라 단위
NavSatFixGNSS위경도(도!)·고도
Range단일 거리시야각
JointState관절5.5
BatteryState배터리전압·전류 부호
Temperature·FluidPressure환경단위
TimeReference시각 기준시간 동기(7.7)

함정: NavSatFix의 위경도는 도(degree) 단위다 — REP 103의 라디안 규칙의 예외다. 지리 좌표는 관례상 도를 쓴다(확인 필요: 메시지 정의 주석이 정본).

함정: BatteryState의 전류 부호 규약(방전이 음수인지 양수인지)을 확인하라. 메시지 주석에 명시되어 있으며, 틀리면 충전 중인데 방전으로 표시된다.

헤더 규약(모든 stamped 메시지 공통):

필드규약
stamp측정 시각(발행 시각 아님 — 1.10.6)
frame_id센서 프레임(슬래시 없이 — 1.1.11)

7.1.7 공분산 규약

불확실성을 표현하는 방식이며, 융합에서 결정적이다.

메시지공분산
Imuorientation_covariance·angular_velocity_covariance·linear_acceleration_covariance (각 3×3 = 9)
Odometrypose.covariance·twist.covariance (각 6×6 = 36)
PoseWithCovariance6×6
NavSatFixposition_covariance (3×3)

행 우선(row-major) 순서로 저장된다.

$$ \Sigma_{6\times6} = \begin{bmatrix} \sigma_{xx} & \sigma_{xy} & \sigma_{xz} & \sigma_{x\phi} & \sigma_{x\theta} & \sigma_{x\psi} \\ \vdots & & & & & \vdots \\ \sigma_{\psi x} & \cdots & & & & \sigma_{\psi\psi} \end{bmatrix} $$

6×6의 순서는 x, y, z, roll(φ), pitch(θ), yaw(ψ) 다.

// 대각 원소 접근
odom.pose.covariance[0]  = var_x;      // (0,0)
odom.pose.covariance[7]  = var_y;      // (1,1)
odom.pose.covariance[14] = var_z;      // (2,2)
odom.pose.covariance[21] = var_roll;   // (3,3)
odom.pose.covariance[28] = var_pitch;  // (4,4)
odom.pose.covariance[35] = var_yaw;    // (5,5)

"모름"을 표현하는 세 가지 관행:

값의미
covariance[0] = -1이 데이터 자체가 없다(IMU orientation 등)
전부 0규약상 "공분산을 모른다" — Imu.msg 주석이 명시(실행 확인, 7.1.12.2)
매우 큰 값(예: 1e9)"이 값을 믿지 말라" — 융합에서 사실상 무시

규약과 구현을 나눠서 봐야 한다. 규약은 확정되어 있다 — Imu.msg가 "A covariance matrix of all zeros will be interpreted as covariance unknown"이라고 명시한다(실행 확인). 문제는 구현이다. 소비자가 그 규약을 확인하지 않고 0을 분산 값으로 그대로 쓰면, 수학적으로 "분산 0 = 완벽하게 정확"이 되어 그 센서를 절대 신뢰한다. 융합이 다른 센서를 전부 무시하게 되는 경로가 이것이며, 7.6.9가 경고하는 바로 그 증상이다.

견해: 그래서 "규약이 0을 모름으로 정했으니 0을 써도 된다"고 생각하면 안 된다. 규약을 지키는 소비자만 안전하고, 안 지키는 소비자에게는 최악의 값이 된다. 발행자는 0을 피하라 — 데이터가 없으면 -1, 불확실하면 큰 값을 넣는 편이 어느 소비자에게도 안전하다.

견해: 공분산을 0으로 두지 말라. 모르면 큰 값(1e6~1e9)을 넣어 "믿지 말라"고 명시하는 편이 안전하다. 실제 값을 아는 것이 최선이지만, 틀린 확신보다 정직한 무지가 낫다.

공분산 값 정하기:

방법설명
센서 사양서노이즈 밀도·바이어스 안정성
정지 상태 측정분산을 직접 계산
경험적 튜닝융합 결과를 보며 조정
# 정지 상태에서 IMU 분산 측정
ros2 topic echo /imu/data --field angular_velocity.z > /tmp/gyro_z.txt
# → 표준편차를 계산해 공분산으로

7.1.8 위반의 결과

규약 위반은 조용히 틀린 결과를 만든다. 무엇이 어떻게 깨지는지 알면 진단이 빨라진다.

위반증상
각도를 도로 발행로봇이 57배 회전·발산
y축이 오른쪽(NED)좌우 반전 — 왼쪽으로 가라니 오른쪽으로
z축이 아래(NED)상하 반전·중력 부호 오류
광학 프레임 혼동결과가 90도 회전
IMU 중력 미포함융합이 자유낙하로 판단
frame_id가 base_link센서 오프셋 무시
stamp가 발행 시각tf 변환 오차(1.10.6)
stamp가 0시간 정합 상실(1.10.6)
공분산 0융합이 그 센서만 신뢰
공분산 과소동일
쿼터니언 미정규화tf2 거부·비정상적인 회전
쿼터니언이 전부 0무효 회전

견해: 이 표를 진단 도구로 쓰라. "로봇이 반대로 간다"·"결과가 90도 틀어졌다"·"융합이 이상하다" 같은 증상에서 원인 후보가 즉시 좁혀진다. 규약 위반은 코드 버그처럼 보이지 않기 때문에, 이 가능성을 목록에 두는 것 자체가 중요하다.

7.1.9 검증

드라이버를 만들거나 새 센서를 장착할 때 확인할 것들이다.

① 단위·부호 확인:

# IMU 정지 상태 — z ≈ +9.81
ros2 topic echo /imu/data --field linear_acceleration --once

# 로봇을 반시계로 회전 — angular_velocity.z 가 양수여야
ros2 topic echo /imu/data --field angular_velocity.z

# 로봇을 앞으로 이동 — odom position.x 증가
ros2 topic echo /odom --field pose.pose.position

② 프레임 확인:

# frame_id 가 올바른가
ros2 topic echo /scan --field header.frame_id --once

# 그 프레임이 tf에 있는가 (5.1.10)
ros2 run tf2_ros tf2_echo base_link laser_link

③ 시각적 확인 — 가장 확실:

RViz2에서 센서 데이터를 표시하고 로봇을 실제로 움직이며 본다.

확인방법
라이다 방향앞에 벽을 두고 점이 앞(+x)에 출력되는가
카메라 방향오른쪽 물체가 이미지 오른쪽인가, 3D 투영이 맞는가
IMU로봇을 기울이면 같은 방향으로 기우는가
오도메트리앞으로 밀면 앞으로 가는가

견해: "앞에 벽을 두고 확인"이 가장 빠르고 확실한 검증이다. 수식과 문서로 확인하는 것보다 RViz2에서 눈으로 보는 것이 오류를 즉시 드러낸다. 새 센서를 장착할 때마다 이 절차를 거치라 — 5분이면 되고, 나중에 며칠을 아낀다.

④ 자동 검사:

# 개념: 규약 검사 노드
def check_imu(msg):
    warnings = []
    # 중력 포함 여부 (정지 가정)
    acc_norm = (msg.linear_acceleration.x**2 +
                msg.linear_acceleration.y**2 +
                msg.linear_acceleration.z**2) ** 0.5
    if abs(acc_norm - 9.81) > 2.0:
        warnings.append(f'가속도 크기 {acc_norm:.2f} — 중력 포함 여부 확인')

    # 쿼터니언 정규화
    q = msg.orientation
    qn = (q.x**2 + q.y**2 + q.z**2 + q.w**2) ** 0.5
    if msg.orientation_covariance[0] >= 0 and abs(qn - 1.0) > 0.01:
        warnings.append(f'쿼터니언 노름 {qn:.4f} — 미정규화')

    # 공분산 0
    if all(c == 0.0 for c in msg.angular_velocity_covariance):
        warnings.append('각속도 공분산이 전부 0 — 융합에서 위험')

    # 프레임
    if not msg.header.frame_id or msg.header.frame_id.startswith('/'):
        warnings.append(f'frame_id 이상: "{msg.header.frame_id}"')

    return warnings

견해: 이런 검사 노드를 개발 도구로 만들어 두면 값을 한다. 새 센서·새 드라이버를 추가할 때 한 번 실행해 보면 규약 위반이 즉시 드러난다. 진단 토픽으로 내보내면 상시 감시도 된다(6.9).

7.1.12 .msg 파일이 규약의 정본이다 — 실측

REP 문서를 찾기 전에 메시지 정의 파일을 먼저 열어라. 단위와 "모름" 표현이 주석으로 적혀 있고, 그것이 실제 생태계가 따르는 규약이다. Jazzy의 sensor_msgs를 확인한 결과다(실행 확인).

ros2 interface show sensor_msgs/msg/Imu           # 주석까지 함께 나온다
cat /opt/ros/jazzy/share/sensor_msgs/msg/Imu.msg  # 원문

7.1.12.1 단위 — 정의 파일에 적힌 그대로

메시지·필드단위정의 파일의 표현
Temperature.temperature섭씨"Measurement of the Temperature in Degrees Celsius"
NavSatFix.latitude · longitude도(degree)"Latitude [degrees]. Positive is north of equator"
NavSatFix.altitudem"Altitude [m]. Positive is above the WGS 84 ellipsoid"
Imu.linear_accelerationm/s²"should be in m/s^2 (not in g's)"
Imu.angular_velocityrad/s"rotational velocity should be in rad/sec"
MagneticField.magnetic_fieldTesla"field vector in Tesla"

NavSatFix.altitude의 기준면이 WGS 84 타원체라는 점을 놓치기 쉽다. 지도·고도계가 흔히 쓰는 평균해수면(MSL, 지오이드)과 다르다 — 지역에 따라 수십 미터 차이가 난다. 두 값을 섞어 쓰면 고도가 조용히 어긋난다.

함정: 가속도 단위가 g가 아니라는 것을 정의 파일이 굳이 명시해 두었다("not in g's"). 그만큼 자주 틀린다는 뜻이다. 센서 데이터시트는 대개 g 단위이므로 드라이버에서 9.80665를 곱해야 한다(7.1.4의 중력 포함 문제와는 별개의 실수다 — 단위 변환과 중력 보정 둘 다 틀릴 수 있다).

7.1.12.2 공분산의 "모름"은 두 가지다

이 장이 (확인 필요)로 남겨 둔 항목이다. Imu.msg의 주석이 정확히 답한다(실행 확인):

표현뜻
공분산 행렬이 전부 0"공분산을 모른다" — 값 자체는 유효하되 불확실도를 제공하지 않음
첫 원소([0])가 -1그 추정값이 전혀 없다 — 필드를 해석하지 말 것

즉 0과 -1은 다른 말이다. 0은 "값은 쓰되 불확실도는 네가 정하라"이고, -1은 "이 필드를 보지 마라"다. Imu에는 orientation·angular_velocity·linear_acceleration 세 묶음이 있어 각각 독립적으로 -1을 가질 수 있다 — 방향은 없지만 각속도는 있는 IMU가 흔하다.

정의 파일의 원문은 이렇다:

# A covariance matrix of all zeros will be interpreted as "covariance unknown", and to use the
# ... please set element 0 of the associated covariance matrix to -1
# If you are interpreting this message, please check for a value of -1 in the first element of each

함정: 규약을 아는 것과 소비자가 지키는 것은 다르다. 전부 0을 "모름"으로 읽지 않고 분산 0(=완벽히 정확) 으로 쓰는 코드가 실제로 있고, 그 결과가 7.6.9의 "한 센서만 신뢰하는 융합"이다. 발행자 입장에서 가장 안전한 선택은 0을 전혀 쓰지 않는 것이다(7.1.7).

함정: 소비하는 쪽에서 -1을 확인하라고 정의 파일이 직접 요구한다. 확인 없이 공분산을 그대로 필터에 넣으면 -1이라는 음수 분산이 들어가 추정이 발산한다. robot_localization(7.6)은 이를 걸러 주지만, 직접 만든 융합 코드는 그렇지 않다.

견해: 발행하는 쪽이라면 -1을 성실히 채워라. "방향을 안 쓰니 단순히 0으로 두자"는 흔한 선택인데, 그러면 소비자는 그것을 유효한 방향 추정(공분산 모름)으로 읽는다. 0과 -1의 차이가 바로 여기서 사고가 된다.

7.1.10 함정 카탈로그

#함정증상대처
1각도를 도로 발행57배 오차·발산라디안 변환
2NED 규약 코드 이식좌우·상하 반전명시적 변환 함수
3광학 프레임 혼동90도 회전된 결과_optical_frame 구분
4IMU 중력 미포함융합이 자유낙하 판단정지 시 z≈9.81 확인
5frame_id를 base_link로센서 오프셋 무시센서 프레임 사용
6frame_id에 앞 슬래시tf2 거부슬래시 없이(1.1.11)
7stamp가 발행 시각·0tf 오차·정합 상실측정 시각(1.10.6)
8공분산 전부 0융합이 절대 신뢰큰 값으로 "모름" 표현
9쿼터니언 전부 0무효 회전w=1로 초기화
10쿼터니언 미정규화tf2 거부·이상 회전정규화 확인
11없는 데이터를 0으로소비자가 신뢰covariance[0]=-1
12NavSatFix 단위 혼동위치 오류위경도는 도
13시각 검증 생략규약 오류가 나중에 발견RViz2 + 실제 움직임
14공분산 -1 미확인음수 분산으로 추정 발산첫 원소 검사 후 사용(7.1.12.2)
15안 쓰는 필드 공분산을 0으로소비자가 유효한 추정으로 오독없으면 -1(7.1.12.2)
16규약대로 공분산 0 발행지키지 않는 소비자가 절대 신뢰로 읽음-1 또는 큰 값(7.1.7)

7.1.11 체크포인트

  • REP 103의 SI 단위 표를 재구성할 수 있는가. 각도의 예외는 어디서 발생하는가.
  • ROS의 좌표 규약(x·y·z 방향)과 NED·광학 규약의 차이를 표로 말할 수 있는가.
  • 쿼터니언을 초기화할 때 주의할 점은 무엇인가.
  • 센서 데이터의 frame_id가 무엇이어야 하는가. base_link로 두면 무슨 일이 생기는가.
  • camera_link와 camera_optical_frame의 축 차이와, 그 사이의 표준 회전값은?
  • 어떤 데이터가 광학 프레임을 frame_id로 갖는가.
  • REP 145에서 선가속도의 핵심 규약은 무엇인가. 정지 상태에서 어떤 값을 기대하는가.
  • IMU가 방향을 제공하지 않을 때 어떻게 표현하는가. 그 규약을 안 지키면?
  • 6×6 공분산의 원소 순서와 대각 원소의 인덱스를 말할 수 있는가.
  • 공분산을 0으로 두면 안 되는 이유와, "모름"의 안전한 표현은?
  • 규약 위반의 증상 다섯 가지를 원인과 짝지을 수 있는가.
  • 새 센서를 장착할 때 가장 빠르고 확실한 검증 방법은 무엇인가.
  • .msg 주석이 정하는 단위 규약을 네 가지 들 수 있는가. 공분산이 전부 0인 것과 첫 원소가 -1인 것은 어떻게 다른가(7.1.12).

다음 장 7.2은 이 규약 위에서 가장 대용량 데이터 — 이미지 파이프라인을 다룬다. image_transport의 플러그인 구조, cv_bridge의 복사 비용, 그리고 대역폭 설계.