AEGLOSLAB ROS 2 Jazzy 대전

제6부 하드웨어 인터페이스

6.8 micro-ROS — MCU와 ROS 2

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

로봇에는 리눅스 컴퓨터만 있는 것이 아니다. 모터 드라이버 보드, 센서 인터페이스, 배터리 관리, 비상 정지 회로 — 이런 것들은 MCU(마이크로컨트롤러)에서 실행된다. 램이 수십~수백 KB이고 OS가 없거나 RTOS인 환경이다.

그 MCU를 ROS 2 그래프에 직접 참여시키는 것이 micro-ROS다. MCU가 토픽을 발행하고 서비스를 제공하며, 리눅스 쪽에서 보면 평범한 ROS 2 노드로 보인다.

매력적으로 들리지만 판단이 필요하다. 이 장은 구조를 설명하고, micro-ROS와 "커스텀 프로토콜 + 브리지 노드" 중 무엇을 택할지의 기준까지 다룬다. 후자가 맞는 경우가 생각보다 많다.

배우는 것:

  • 왜 필요한가 — 일반 ROS 2를 MCU에서 못 실행하는 이유.
  • 아키텍처 — 클라이언트·에이전트·XRCE-DDS.
  • rclc — MCU용 클라이언트 라이브러리와 실행 모델.
  • 자원 제약 — 정적 할당·메모리 예산.
  • 전송 — 시리얼·UDP·CAN.
  • 시간 동기화 — MCU와 리눅스의 시계.
  • 한계와 대안 — 언제 브리지 노드가 나은가.

선수 지식: 2.1.7(rclc), 3.1(DDS), 6.7(시리얼·CAN), 1.10.8(시계 동기화), 6.6.7(실시간 판단).

정직: micro-ROS는 이 책에서 다루는 주제 중 생태계 변화가 빠른 편이다. 지원 보드·RTOS·빌드 도구가 계속 바뀌며, Jazzy 지원 상태와 도구 체계는 반드시 현재 문서(micro.ros.org)로 확인해야 한다(확인 필요). 이 환경에서 빌드·실행 검증하지 않았다(목차 3). 아래는 구조와 판단 기준에 집중한다. apt 저장소에 무엇이 있고 없는지는 확인했고(실행 확인 — 6.8.13), MCU가 필요한 항목은 확인하지 못했다(6.8.13.4에 목록). 확인 못 한 항목의 (확인 필요) 표기는 그대로 두었다.

6.8.2 왜 필요한가 — MCU의 제약

일반 ROS 2(rclcpp·rclpy)를 MCU에서 실행할 수 없는 이유:

요구일반 ROS 2전형적 MCU
RAM수십~수백 MB수십~수백 KB
OS리눅스(스레드·소켓·파일)없음 또는 RTOS
동적 할당전제대개 회피
C++ 런타임예외·RTTI·STL제한적
DDS 구현수 MB불가
네트워크 스택완전한 TCP/IP제한적

핵심은 DDS다. 3.1~3.3에서 본 DDS는 디스커버리·QoS·히스토리 캐시를 위해 상당한 메모리와 처리를 요구한다. MCU에서 실행 불가능하다.

micro-ROS의 답: DDS 대신 XRCE-DDS.

6.8.3 아키텍처

MCU (micro-ROS 클라이언트) 시리얼 · UDP · CAN 사용자 코드 rclc rcl rmw_microxrcedds Micro XRCE-DDS Client micro-ROS Agent (리눅스) 일반 DDS 참가자 ROS 2 그래프 일반 노드들
구성 요소위치역할
micro-ROS 클라이언트MCU경량 ROS 2 API
XRCE-DDS 프로토콜사이클라이언트↔에이전트 통신
micro-ROS Agent리눅스MCU를 대신해 DDS에 참여

핵심 통찰: 에이전트가 프록시다. MCU는 DDS를 모르고, 에이전트가 MCU 대신 DDS 엔티티를 만들어 그래프에 참여한다. 다른 ROS 2 노드에서 보면 평범한 노드로 보인다.

# 에이전트 실행 (전송 방식에 따라)
ros2 run micro_ros_agent micro_ros_agent serial --dev /dev/ttyACM0 -b 115200
ros2 run micro_ros_agent micro_ros_agent udp4 --port 8888
# 주의: micro_ros_agent 는 apt 에 없다 — 소스 빌드가 필요하다 (실행 확인, 6.8.13)

XRCE-DDS(eXtremely Resource-Constrained Environments DDS) 는 OMG 표준이며, 클라이언트가 최소한의 상태만 유지하도록 설계됐다 — 디스커버리·QoS 관리·히스토리를 에이전트가 담당한다.

항목클라이언트(MCU)에이전트(리눅스)
메모리수십 KB일반
디스커버리❌ 에이전트만✅
QoS 관리요청만실제 적용
히스토리최소DDS가

함정: 에이전트가 단일 장애점이다. 에이전트가 종료되면 그 MCU의 모든 통신이 끊긴다. 3.4.5에서 Discovery Server를 두고 논의한 것과 같은 성질이며, 에이전트 재시작·클라이언트 재연결 전략이 필요하다.

6.8.4 rclc와 실행 모델

2.1.7에서 언급한 rclc가 여기서 쓰인다.

#include <rcl/rcl.h>
#include <rclc/rclc.h>
#include <rclc/executor.h>
#include <std_msgs/msg/int32.h>

rcl_publisher_t publisher;
std_msgs__msg__Int32 msg;

void timer_callback(rcl_timer_t * timer, int64_t last_call_time)
{
  (void)last_call_time;
  if (timer != NULL) {
    rcl_publish(&publisher, &msg, NULL);
    msg.data++;
  }
}

void appMain(void * arg)
{
  rcl_allocator_t allocator = rcl_get_default_allocator();
  rclc_support_t support;

  // 초기화 — 실패 처리 필수 (MCU에서는 예외가 없다)
  rclc_support_init(&support, 0, NULL, &allocator);

  rcl_node_t node;
  rclc_node_init_default(&node, "mcu_node", "", &support);

  rclc_publisher_init_default(
      &publisher, &node,
      ROSIDL_GET_MSG_TYPE_SUPPORT(std_msgs, msg, Int32), "mcu_counter");

  rcl_timer_t timer;
  rclc_timer_init_default(&timer, &support, RCL_MS_TO_NS(100), timer_callback);

  // executor — 핸들 수를 미리 선언 (정적 할당)
  rclc_executor_t executor;
  rclc_executor_init(&executor, &support.context, 1, &allocator);
  rclc_executor_add_timer(&executor, &timer);

  msg.data = 0;
  while (1) {
    rclc_executor_spin_some(&executor, RCL_MS_TO_NS(100));
  }
}

rclc executor가 rclcpp와 다른 점:

축rclcpp executorrclc executor
할당동적정적(핸들 수 미리 선언)
실행 순서구현 정의(2.2.9)명시 지정 가능
스레드멀티 가능(2.3)단일이 일반적
트리거 조건준비된 것 실행조건 지정 가능(전부 준비되면 등)
결정성낮음높음

rclc의 결정적 실행이 장점이다(12.5에서 다시 다룬다). "구독 A와 B가 모두 도착하면 콜백 실행" 같은 조건을 명시할 수 있어, 제어 애플리케이션에서 예측 가능성이 높다.

// 실행 순서·조건 지정 (개념 — 확인 필요: API 세부)
rclc_executor_set_trigger(&executor, rclc_executor_trigger_all, NULL);

견해: rclc의 결정성은 MCU가 아닌 곳에서도 매력적일 수 있다. 다만 rclcpp 생태계(컴포넌트·라이프사이클·표준 컨트롤러)를 포기해야 하므로, 리눅스에서는 대개 rclcpp + executor 분리(2.3.8)를 택한다.

6.8.5 자원 제약

모든 것이 컴파일 시점에 정해져야 한다.

항목설정
발행자·구독자 수최대치 선언
서비스·클라이언트 수최대치 선언
메시지 크기최대 크기 고정
executor 핸들 수미리 선언
히스토리 깊이작게
# colcon.meta 또는 유사 설정 파일 (확인 필요: 형식)
{
    "names": {
        "rmw_microxrcedds": {
            "cmake-args": [
                "-DRMW_UXRCE_MAX_NODES=1",
                "-DRMW_UXRCE_MAX_PUBLISHERS=5",
                "-DRMW_UXRCE_MAX_SUBSCRIPTIONS=3",
                "-DRMW_UXRCE_MAX_SERVICES=1",
                "-DRMW_UXRCE_MAX_CLIENTS=1",
                "-DRMW_UXRCE_MAX_HISTORY=4",
                "-DRMW_UXRCE_TRANSPORT=serial"
            ]
        }
    }
}

함정: 한도를 넘으면 런타임에 조용히 실패한다. 발행자를 6개 만들려 하는데 최대가 5면 여섯 번째 초기화가 실패하고, 반환값을 확인하지 않으면 아무 표시 없이 동작하지 않는 노드가 된다. MCU에는 예외가 없으므로 모든 반환값을 검사해야 한다.

// 반환값 검사 매크로 관용구
#define RCCHECK(fn) { \
  rcl_ret_t rc = fn; \
  if (rc != RCL_RET_OK) { error_loop(); } }

RCCHECK(rclc_publisher_init_default(&publisher, &node, type_support, "topic"));

메시지 크기 제약이 설계에 영향을 준다:

문제대처
가변 길이 배열·문자열고정 크기로 설계(1.2.3)
큰 메시지분할하거나 요약
표준 메시지가 큼커스텀 경량 타입

1.2.3에서 "유한 배열로 설계하라"고 한 것이 여기서 필수가 된다. micro-ROS에서 무한 배열은 사실상 쓸 수 없다.

// 메시지 안의 문자열·배열은 미리 메모리를 할당해야 한다
std_msgs__msg__String msg;
static char buffer[64];
msg.data.data = buffer;
msg.data.capacity = sizeof(buffer);
msg.data.size = 0;

함정: 메시지 필드에 메모리를 할당하지 않고 쓰면 크래시한다. rclcpp에서는 자동으로 되던 것이 여기서는 수동이다. 특히 구독 메시지도 미리 버퍼를 할당해야 수신할 수 있다.

6.8.6 전송

전송특징용도
시리얼(UART·USB CDC)단순·널리 지원가장 흔함
UDP(이더넷·Wi-Fi)다중 클라이언트·거리네트워크 있는 MCU
CAN기존 CAN 버스 재사용(확인 필요)차량형
커스텀직접 구현특수 링크
# 시리얼 에이전트 (micro_ros_agent 는 apt 에 없다 — 6.8.13.1)
ros2 run micro_ros_agent micro_ros_agent serial --dev /dev/mcu_board -b 921600

# UDP 에이전트 (여러 MCU가 연결될 수 있다)
ros2 run micro_ros_agent micro_ros_agent udp4 --port 8888

대역폭이 제약이다:

$$B_{\text{필요}} = \sum_i S_{\text{msg},i} \cdot f_i \cdot (1 + \text{오버헤드})$$

115200 bps 시리얼은 초당 약 11 KB다. 100바이트 메시지를 100 Hz로 보내면 10 KB/s — 이미 포화에 가깝다. 보율을 높이거나(921600 이상) 발행률·크기를 줄여야 한다.

함정: 6.7.3.1의 USB-시리얼 지연 타이머가 여기서도 적용된다. micro-ROS 통신 주기가 이유 없이 낮다면 이것부터 확인하라.

견해: 전송 선택이 시스템 구조를 정한다. 시리얼은 MCU 하나당 포트 하나이므로 MCU가 여러 개면 포트가 부족하다. UDP는 여러 MCU가 한 에이전트에 연결될 수 있어 확장성이 낫지만, MCU에 이더넷·Wi-Fi가 있어야 한다.

6.8.7 시간 동기화

MCU의 시계는 리눅스와 다르다. 1.10.8의 문제가 여기서 더 심하다 — MCU에는 NTP도 없다.

// micro-ROS의 시간 동기화 API (개념)
rmw_uros_sync_session(1000);            // 에이전트와 동기화, 타임아웃 ms

if (rmw_uros_epoch_synchronized()) {
  int64_t time_ns = rmw_uros_epoch_nanos();
  msg.header.stamp.sec = time_ns / 1000000000;
  msg.header.stamp.nanosec = time_ns % 1000000000;
}
// (확인 필요: API 이름·동작)

동기화 없이 발행하면 무슨 일이 생기는가:

결과설명
tf 외삽 오류스탬프가 미래·과거로(5.2.4)
message_filters 동기화 실패짝이 안 지어짐(7.7)
센서 융합 오차시간 정합 붕괴
bag 재생 이상시간 순서 뒤엉킴

견해: 센서 데이터를 발행하는 MCU라면 시간 동기화는 필수다. 그리고 주기적으로 재동기화해야 한다 — MCU의 크리스털은 드리프트하며, 온도에 따라 달라진다. 동기화 상태를 진단으로 내보내는 것도 좋다(6.9).

정직: micro-ROS의 시간 동기 정밀도는 전송 지연에 좌우된다(확인 필요). 시리얼 왕복이 수 ms면 그만큼의 불확실성이 있다. 정밀한 시각이 필요하면 하드웨어 트리거·PPS 같은 별도 수단을 검토해야 한다(7.7).

6.8.8 한계 — 정직하게

micro-ROS로 못 하거나 어려운 것들:

한계설명
완전한 QoSDDS QoS의 일부만·에이전트가 대신 적용
대용량 데이터메모리·대역 제약
복잡한 그래프엔티티 수 한도
에이전트 의존단일 장애점
디버깅MCU 디버깅 + ROS 디버깅이 겹침
빌드 복잡도크로스 컴파일·RTOS 통합(4.8)
생태계지원 보드·RTOS가 한정(확인 필요)
실시간 보장전송 지연이 예측 불가할 수 있음

마지막 항목이 중요하다. micro-ROS는 MCU를 ROS 그래프에 편입시키는 것이지, 실시간 제어 채널을 만드는 것이 아니다. 시리얼 왕복 지연·에이전트 처리·DDS 전달이 겹치면 지연이 수 ms~수십 ms가 될 수 있다.

견해: 고속 제어 루프를 micro-ROS로 닫으려 하지 말라. MCU에서 제어를 하고(MCU 안에서 닫힌 루프), micro-ROS로는 명령·상태·설정을 주고받는 구조가 맞다. 6.6.7의 "안전 감시를 MCU로 분리"도 같은 발상이다 — 빠른 것은 MCU 안에, 느린 것은 ROS로.

6.8.9 대안 — 커스텀 프로토콜 + 브리지 노드

micro-ROS를 쓰지 않고 같은 목적을 달성하는 방법이다.

MCU 시리얼 · CAN 펌웨어 커스텀 바이너리 프로토콜 브리지 노드 (리눅스) 일반 rclcpp 노드 ROS 2 그래프

비교:

축micro-ROS커스텀 + 브리지
MCU 코드 복잡도높음(ROS 스택)낮음(단순 프로토콜)
MCU 메모리수십 KB+수 KB
브리지 노드불필요(에이전트가)작성 필요
메시지 정의ROS 타입 재사용직접 정의 + 변환
새 토픽 추가MCU 코드 수정MCU + 브리지 수정
디버깅스택이 두꺼움단순(바이트를 직접 봄)
표준 준수ROS 2 표준자체
지원 MCU제한적거의 모든 MCU
학습 곡선가파름완만

커스텀 + 브리지가 나은 경우:

상황이유
MCU가 매우 작다8비트·수 KB RAM
주고받는 것이 단순관절 명령·상태만
이미 프로토콜이 있다벤더 보드·기존 펌웨어
하드웨어 컴포넌트로 충분ros2_control과 통합(6.2)
팀이 MCU 쪽에 익숙학습 비용
극한 실시간프로토콜을 직접 최적화

micro-ROS가 나은 경우:

상황이유
MCU가 여러 토픽·서비스를 다룬다매번 프로토콜 확장은 부담
ROS 표준 메시지를 쓰고 싶다타입 재사용
MCU가 상대적으로 크다STM32F4급 이상
파라미터·라이프사이클 필요ROS 기능 활용
여러 MCU를 일관되게표준화
팀이 ROS 쪽에 익숙—

견해: "모터 드라이버 MCU"라면 커스텀 프로토콜 + ros2_control 하드웨어 컴포넌트(6.2)가 대개 낫다. 주고받는 것이 관절 명령·상태로 정해져 있고, 제어 주기가 중요하며, ros2_control이 이미 추상을 제공한다. micro-ROS의 이점(다양한 토픽·표준 타입)이 발휘될 여지가 적다.

견해: 반대로 "센서 허브 MCU"나 "보조 기능 MCU" — 배터리 상태·환경 센서·LED 제어·버튼 입력을 여러 토픽으로 다루는 경우 — 는 micro-ROS가 어울린다. 토픽이 늘어날 때마다 프로토콜을 확장하는 부담이 없다.

6.8.10 개발 실무

빌드 통합:

# micro_ros_setup 워크플로 (개념 — 확인 필요: 현재 절차)
ros2 run micro_ros_setup create_firmware_ws.sh <RTOS> <보드>
ros2 run micro_ros_setup configure_firmware.sh <앱> -t <전송>
ros2 run micro_ros_setup build_firmware.sh
ros2 run micro_ros_setup flash_firmware.sh

플랫폼별 통합도 있다 — PlatformIO·Arduino·Zephyr·ESP-IDF 등에서 micro-ROS 라이브러리를 쓰는 경로(확인 필요: 지원 상태).

디버깅:

방법설명
에이전트 상세 로그-v6 등으로 프로토콜 수준 관찰
MCU UART 로그별도 포트로 디버그 출력
반환값 검사 + LEDerror_loop()에서 LED 패턴
하드웨어 디버거SWD·JTAG
에이전트만 먼저 시험ros2 topic list로 노드 등장 확인
# 에이전트 상세 로그
ros2 run micro_ros_agent micro_ros_agent serial --dev /dev/ttyACM0 -v6

# MCU 노드가 보이는가
ros2 node list
ros2 topic list
ros2 topic echo /mcu_counter

견해: error_loop()에 LED 깜빡임 패턴을 넣으라. MCU에는 로그가 없거나 보기 어려우므로, 초기화 실패를 눈으로 알 수 있게 하는 것이 개발 속도를 크게 높인다. 오류 코드별로 다른 패턴을 쓰면 더 좋다.

연결 복구:

// 에이전트가 종료됐다 살아나는 경우 처리 (개념)
enum states { WAITING_AGENT, AGENT_AVAILABLE, AGENT_CONNECTED, AGENT_DISCONNECTED };

switch (state) {
  case WAITING_AGENT:
    state = (RMW_RET_OK == rmw_uros_ping_agent(100, 1))
            ? AGENT_AVAILABLE : WAITING_AGENT;
    break;
  case AGENT_AVAILABLE:
    state = create_entities() ? AGENT_CONNECTED : WAITING_AGENT;
    if (state == WAITING_AGENT) destroy_entities();
    break;
  case AGENT_CONNECTED:
    if (RMW_RET_OK != rmw_uros_ping_agent(100, 1)) state = AGENT_DISCONNECTED;
    else rclc_executor_spin_some(&executor, RCL_MS_TO_NS(100));
    break;
  case AGENT_DISCONNECTED:
    destroy_entities();
    state = WAITING_AGENT;
    break;
}
// (확인 필요: API 이름)

이 상태 기계가 사실상 필수다 — 6.7.2의 드라이버 상태 기계와 같은 구조이며, 없으면 에이전트 재시작 후 MCU가 영영 연결되지 않는다.

6.8.13 apt에 있는 것과 없는 것 — 실측

micro-ROS는 MCU 쪽 실물이 있어야 제대로 검증된다. 이 환경에는 보드가 없으므로 확인할 수 있는 것만 확인하고, 나머지는 못 했다고 밝힌다(실행 확인, Jazzy apt 저장소 조회).

6.8.13.1 에이전트는 apt에 없다

가장 실용적인 확인 결과다. ros2 run micro_ros_agent …를 그대로 따라 하면 패키지를 찾을 수 없다.

패키지apt(ros-jazzy-*)
micro_ros_agent없음
microxrcedds_agent없음
micro_ros_msgs있음
micro_ros_diagnostic_msgs있음
micro_ros_diagnostic_bridge있음
rclc · rclc_lifecycle · rclc_parameter · rclc_examples있음

즉 "ROS 2 쪽 조각"은 배포되지만 에이전트는 직접 빌드해야 한다. micro-ROS 공식 문서가 안내하는 대로 워크스페이스에 소스를 받아 colcon build하거나, 제공되는 컨테이너 이미지를 쓰는 것이 실제 경로다.

함정: 이 장의 실행 예시를 그대로 복사하면 첫 줄에서 막힌다. ros2 run micro_ros_agent는 에이전트를 이미 빌드해 둔 워크스페이스를 소싱한 상태를 전제한다. 명령 자체는 맞지만 선행 단계가 빠져 있었다 — 그 단계가 micro-ROS 도입에서 가장 먼저 만나는 한계다.

6.8.13.2 rclc는 정식으로 배포된다

반대로 rclc 계열은 apt에 정식으로 들어 있다. MCU용 C 클라이언트 라이브러리로 알려져 있지만, 리눅스에서도 그대로 설치·사용할 수 있다는 뜻이다.

패키지내용
rclcC 클라이언트 라이브러리 본체(executor 포함)
rclc_lifecycle라이프사이클 노드의 C 판(1.12)
rclc_parameter파라미터 서버의 C 판(1.9)
rclc_examples예제

견해: MCU에 탑재하기 전에 리눅스에서 rclc로 먼저 짜 보는 것이 좋은 순서다. 같은 API로 동작을 확인한 뒤 크로스 컴파일로 넘어가면, "MCU라서 안 되는 것"과 "코드가 틀린 것"을 분리할 수 있다. 디버거·로그·ros2 CLI를 다 쓸 수 있는 환경에서 논리를 검증하는 편이 훨씬 비용이 낮다.

6.8.13.3 micro_ros_msgs가 드러내는 것

이 패키지가 정의하는 인터페이스는 셋뿐이다(실행 확인):

타입뜻
micro_ros_msgs/msg/Entity노드가 가진 엔티티(발행자·구독자 등) 하나
micro_ros_msgs/msg/Node노드 하나와 그 엔티티 목록
micro_ros_msgs/msg/Graph전체 그래프

MCU 쪽 노드를 ROS 2 그래프에 드러내기 위한 것이다. 6.8.5가 말한 "에이전트가 디스커버리를 대행한다"는 구조가 여기서 보인다 — MCU는 자기 엔티티 정보를 이 메시지로 알리고, 그래프 관리는 리눅스 쪽이 한다.

함정: 그래서 ros2 node list에 MCU 노드가 보인다고 해서 그 노드가 DDS 참가자인 것은 아니다. 실제 DDS 참가자는 에이전트이고, MCU는 그 뒤에 있다(3.3.5의 "프로세스당 참가자 1개"와 함께 읽으면 구조가 정리된다). 그래서 에이전트가 종료되면 MCU 노드 전체가 그래프에서 사라진다.

6.8.13.4 확인하지 못한 것

정직하게 남긴다. 아래는 이 회차에서 검증하지 못했다 — MCU 보드·시리얼 장치·크로스 컴파일 툴체인이 필요하다.

  • 에이전트와 클라이언트의 실제 통신(시리얼·UDP 왕복, 재연결 거동)
  • 시간 동기 정밀도(6.8.7) — 전송 지연에 좌우되므로 실측이 필수인 항목
  • 메모리 사용량·정적 할당 설정(colcon.meta)의 실제 효과
  • 지원 보드·RTOS 목록의 현재 상태

이 항목들에 붙은 (확인 필요) 표기는 그대로 둔다. 확인할 수 없는 것을 확인한 척하지 않는 편이 낫다(목차 3).

6.8.11 함정 카탈로그

#함정증상대처
1반환값 미검사조용히 동작 안 함RCCHECK 관용구
2엔티티 한도 초과초기화 실패빌드 설정 확인
3메시지 버퍼 미할당크래시수동 메모리 부착
4무한 배열 사용사실상 불가고정 크기(1.2.3)
5대역폭 초과지연·유실보율·발행률 계산
6USB 지연 타이머 기본값주기 제한latency_timer=1(6.7.3.1)
7시간 동기화 없음tf·융합 오류주기적 동기화
8에이전트 재연결 미처리재시작 후 영영 연결되지 않음상태 기계(6.8.10)
9고속 제어를 micro-ROS로지연·지터MCU 안에서 제어
10에이전트 단일 장애점 무시통신 전면 중단감시·재시작(14.8)
11오류 표시 수단 없음디버깅 지옥LED 패턴
12판단 없이 도입복잡도만 증가대안 비교(6.8.9)
13ros2 run micro_ros_agent 바로 실행패키지 없음 — apt에 없다소스 빌드 후 워크스페이스 소싱(6.8.13.1)

9번을 강조한다. micro-ROS는 통신 경로이지 제어 경로가 아니다. 빠른 루프는 MCU 안에서 닫고, ROS와는 명령·상태만 주고받는 구조가 옳다.

6.8.12 체크포인트

  • 일반 ROS 2를 MCU에서 못 실행하는 이유 여섯 가지를 말할 수 있는가. 핵심 걸림돌은 무엇인가.
  • micro-ROS 아키텍처의 세 구성 요소와, 에이전트가 하는 일을 설명할 수 있는가.
  • 에이전트가 단일 장애점이라는 사실의 함의는?
  • rclc executor가 rclcpp와 다른 다섯 가지를 말할 수 있는가. 결정적 실행이 왜 장점인가.
  • micro-ROS에서 컴파일 시점에 정해야 하는 것 다섯 가지는? 한도를 넘으면 어떻게 되는가.
  • 메시지 버퍼를 수동으로 할당해야 하는 이유와, 1.2.3의 조언이 여기서 필수가 되는 이유는?
  • 전송 선택이 시스템 구조에 미치는 영향을 설명할 수 있는가. 대역폭을 어떻게 계산하는가.
  • MCU 시간 동기화가 필요한 이유와, 동기화 없이 발행할 때의 네 가지 결과는?
  • micro-ROS의 한계 여덟 가지를 들 수 있는가. "통신 경로이지 제어 경로가 아니다"의 의미는?
  • 커스텀 프로토콜 + 브리지가 나은 경우와 micro-ROS가 나은 경우를 각각 네 가지 들 수 있는가.
  • "모터 드라이버 MCU"에 어느 쪽을 권하며 왜인가.
  • 에이전트 재연결 상태 기계가 필수인 이유는?
  • micro-ROS에서 apt로 오는 것과 직접 빌드해야 하는 것은 각각 무엇인가. micro_ros_msgs가 드러내는 구조는(6.8.13).

다음 장 6.9은 제6부의 마지막 — 진단이다. 이 부에서 반복해 "진단으로 내보내라"고 한 것들을 실제로 어떻게 구현하고 운영에서 활용하는가.