제1부 계산 그래프의 코어
1.1 노드와 그래프 — 이름·네임스페이스·리매핑
1.1.1 이 장에서 배우는 것 / 선수 지식
ROS 2에서 이름은 주소다. 두 노드가 통신하는가 아닌가는 결국 "이 문자열과 저 문자열이 같은가"로 결정된다. 그런데 소스에 적힌 이름이 곧 그래프에 나타나는 이름인 것은 아니다 — 그 사이에 네임스페이스 확장·리매핑·~ 치환이라는 해석 단계가 있고, 여기서 어긋나면 "코드는 맞는데 데이터가 안 온다"가 된다. 로봇 두 대를 한 네트워크에 연결하는 순간 이 장의 내용은 선택이 아니라 필수가 된다.
배우는 것:
- 노드의 정체 — 노드는 프로세스가 아니다. 이 구분이 왜 실무적으로 중요한가.
- 이름 문법의 전수 — 상대·절대·사적(
~) 이름, 유효 문자 규칙, 예약된 형태. __예약이 실제로 어디까지 강제되는가(1.1.12) — 이름은 통과하고 리매핑 규칙만 막힌다.- 이름 해석 알고리즘 — 소스의 문자열이 완전 이름(FQN)이 되기까지의 정확한 단계.
- 리매핑 —
--ros-args -r의 문법, 적용 순서, ROS 2가 동적 리매핑을 버린 이유. - 다중 로봇에서의 이름 설계 — 네임스페이스 vs 도메인 vs 접두어의 트레이드오프.
- 그래프 질의 API — 노드가 자기 자신이 아닌 그래프를 관찰하는 법과 그 한계.
- enclave — 보안 이름 공간이 왜 별도로 존재하는가.
선수 지식: 0.6(패키지를 만들고 노드를 실행해 본 경험), 0.7(CLI로 그래프를 조회해 본 경험), 0.4(ROS_DOMAIN_ID).
정직: 이름 규칙은 소스 저장소의
rmw·rcl검증 코드와 설계 문서(design.ros2.org의 Topic and Service name mapping)에 근거한다. 아래 규칙은 그 문서 기준으로 정리했으며 이 환경에서 실행 검증한 것은 아니다(목차 3). 경계 사례는rcl검증 함수의 오류 메시지가 정본이다. 예외 —__예약의 실제 범위(1.1.12),__ns적용 순서(1.1.12.4), 이름 충돌 시 생존 여부(1.1.12.5)는 실행 확인했다.
1.1.2 노드는 프로세스가 아니다
가장 먼저 해소해야 할 오해다. ROS 1에서는 노드와 프로세스가 사실상 1:1이었고(nodelet은 예외였다), 그래서 "노드를 강제 종료한다 = 프로세스를 강제 종료한다"가 성립했다. ROS 2에서 노드는 객체다.
한 프로세스가 여러 노드를 담을 수 있고(컴포지션 — 1.13), 한 노드가 여러 스레드에서 콜백을 실행할 수도 있다(콜백 그룹 — 2.4). 여기서 나오는 실무적 결과:
| 오해 | 실제 |
|---|---|
| 노드를 재시작하려면 프로세스를 강제 종료한다 | 컨테이너에 여러 노드가 있으면 다른 노드까지 종료된다(1.13) |
ros2 node list의 항목 수 = 프로세스 수 | 무관하다. ps와 대조하면 다르다 |
| 노드마다 독립적으로 종료되고 실행된다 | 같은 프로세스면 크래시가 전파된다 |
| 노드 하나 = 스레드 하나 | executor 구성에 따라 다르다(2.3) |
노드가 소유하는 것: 이름·네임스페이스, 발행자·구독자·서비스·클라이언트·액션·타이머, 파라미터(1.9), 로거(1.11), 시계(1.10), 그래프 질의 인터페이스. 노드는 이 자원들의 수명 소유자이고, 실행 주체는 executor다 — 이 분리가 ROS 2 실행 모델의 핵심이며 제2부 전체의 주제다.
1.1.3 이름 문법 — 무엇이 유효한가
노드 이름·토픽 이름·서비스 이름·액션 이름은 공통 규칙을 공유한다.
허용:
- 영문자·숫자·밑줄(
_), 구분자로 슬래시(/), 사적 이름 접두어로 물결(~), 치환용 중괄호({}). - 반드시 영문자 또는
_또는/또는~로 시작한다. 숫자로 시작할 수 없다.
금지:
| 금지 | 예 | 이유 |
|---|---|---|
| 숫자로 시작 | 2dnav | 파싱 모호 |
| 연속 슬래시 | //scan | 빈 토큰 |
| 슬래시로 끝남 | /scan/ | 빈 토큰 |
| 밑줄 두 개로 시작하는 토큰 | /__scan | 예약(리매핑 규칙용) |
| 하이픈·공백·점 | /my-node, /my node | 검증 실패 |
| 점을 포함한 표기 | /my.node | 검증 실패 — 패키지·파일 이름 관습을 그대로 옮기면 걸린다 |
__로 시작하는 토큰이 예약된 이유는 리매핑 규칙(__node·__ns)이 이 형태를 쓰기 때문이다(1.1.5). *다만 그 예약은 리매핑 규칙 문법에서만 강제되고, 이름 자체는 거부되지 않는다* — Node("__weird")도 create_publisher(..., "__weird", ...)도 그대로 만들어진다(85차 실측, 1.1.12).
숨은(hidden) 이름: 토큰 하나가 _로 시작하면 그 이름은 숨은 것으로 간주되어 ros2 topic list·ros2 node list 기본 출력에서 빠진다. CLI가 만드는 임시 노드(_ros2cli_1234)와 액션의 내부 토픽(/nav/_action/feedback)이 이 규칙을 쓴다. 드러내려면 --include-hidden-topics(0.7.4).
세 가지 형태:
| 형태 | 예 | 의미 |
|---|---|---|
| 절대(absolute) | /scan | /로 시작. 네임스페이스와 무관하게 그 이름 그대로. |
| 상대(relative) | scan | 노드의 네임스페이스 앞에 붙는다. |
| 사적(private) | ~/scan | 노드의 완전 이름 아래로 들어간다. |
1.1.4 이름 해석 알고리즘 — 문자열이 FQN이 되기까지
이것이 이 장의 핵심이다. 노드 코드에 create_publisher<...>("scan", ...)이라고 쓴 문자열은 다음 순서로 완전 이름(Fully Qualified Name) 이 된다.
노드가 네임스페이스 /robot1, 이름 laser라고 하자. 이때 노드의 FQN은 /robot1/laser다.
| 소스에 적은 것 | 결과 FQN |
|---|---|
scan (상대) | /robot1/scan |
/scan (절대) | /scan |
~/scan (사적) | /robot1/laser/scan |
sensors/scan | /robot1/sensors/scan |
~/config/rate | /robot1/laser/config/rate |
세 형태의 용도 구분(관행):
- 상대 이름을 기본으로 쓴다. 그래야 네임스페이스를 씌워 로봇을 복제할 수 있다(1.1.7).
- 절대 이름은 시스템 전역에서 하나뿐임이 확실한 것에만 —
/tf,/tf_static,/clock,/rosout. 이 넷은 사실상 예약된 전역 이름이다. 사용자 토픽에 절대 이름을 박으면 다중 로봇에서 반드시 충돌한다. - 사적 이름은 그 노드만의 것 — 디버그 출력, 노드별 상태 토픽.
함정:
~는 노드 이름을 포함한다. 노드 이름을 리매핑으로 바꾸면(-r __node:=laser2)~/scan도/robot1/laser2/scan으로 따라 움직인다. 노드 이름을 바꿨더니 다른 노드가 구독하던 토픽이 사라지는 사고가 여기서 나온다.
함정: ROS 1의
~param과 ROS 2의~/param은 다르다. ROS 1에서 사적 파라미터는~name이었지만, ROS 2에서 파라미터는 이름 해석 대상이 아니다 — 파라미터는 노드에 종속된 키-값이며 네임스페이스 경로를 갖지 않는다(1.9). ROS 1 코드를 옮기며~를 파라미터 이름에 남기면 그대로 문자열의 일부가 된다.
1.1.5 리매핑 — 실행 시점에 이름을 바꾼다
컴파일된 노드의 이름을 실행할 때 바꾸는 장치다. 문법은 --ros-args 뒤에 온다.
ros2 run demo_nodes_cpp talker --ros-args \
-r __node:=talker_a \
-r __ns:=/robot1 \
-r chatter:=/robot1/greetings
| 규칙 | 의미 |
|---|---|
-r 원본:=대상 | 토픽·서비스 이름 치환 |
-r __node:=이름 | 노드 이름 변경 |
-r __ns:=/네임스페이스 | 네임스페이스 변경 |
-r 노드이름:원본:=대상 | 특정 노드에만 적용(컨테이너에 여러 노드가 있을 때) |
-r rosout:=/robot1/rosout | 내부 토픽도 대상이 된다 |
적용 순서가 중요하다. 리매핑은 1.1.4의 확장이 끝난 뒤 적용되는 것이 원칙이지만, __ns·__node 리매핑은 확장의 입력(네임스페이스·노드 이름) 자체를 바꾸므로 사실상 먼저 반영된다. 그래서 다음이 성립한다.
# 노드 ns=/r1, 소스에 "scan" (상대)
-r __ns:=/r2 # → /r2/scan (확장 입력이 바뀜)
-r scan:=/lidar/front # → /lidar/front (확장 결과를 치환)
리매핑 규칙의 좌변에는 확장 전 이름과 확장 후 FQN 모두 매칭될 수 있어 혼동이 잦다. 실무에서 안전한 방법은 좌변에 FQN을 적는 것이다. 애매하면 다음으로 확인한다.
ros2 run <pkg> <exe> --ros-args -r ... &
ros2 node info /robot1/laser # 실제로 어떤 이름이 붙었는지 확인
launch에서:
Node(
package='my_driver', executable='laser_node',
namespace='robot1', # __ns 에 해당
name='laser', # __node 에 해당
remappings=[('scan', '/robot1/lidar/front'),
('~/diagnostics', '/robot1/diag/laser')],
parameters=[{'frame_id': 'robot1/laser_link'}],
)
ROS 2는 동적 리매핑을 버렸다. ROS 1에는 마스터를 통해 실행 중 이름을 바꾸는 여지가 있었지만, ROS 2의 리매핑은 노드 초기화 시점에 한 번 확정된다(static remapping). 이유는 분산 디스커버리 때문이다 — 중앙 마스터가 없으므로 "이제부터 이 이름을 저 이름으로 보라"를 그래프 전체에 원자적으로 전파할 방법이 없다(0.2). 대가는 유연성 상실이고, 이득은 그래프 상태의 예측 가능성이다. 실행 중 연결을 바꿔야 한다면 리매핑이 아니라 라이프사이클 전이(1.12)나 명시적 재구성 서비스로 설계해야 한다.
1.1.6 이름 충돌 — ROS 2는 막아주지 않는다
같은 이름의 노드 둘을 동시에 실행하면 어떻게 되는가? ROS 1이라면 마스터가 나중 것을 살리고 먼저 것을 강제 종료했다. ROS 2에는 그 조정자가 없다. 둘 다 그대로 동작한다.
결과는 조용한 혼돈이다.
ros2 node list에 같은 이름이 두 번 나온다(또는 도구에 따라 한 번만 나온다).ros2 param set /dup_node x 1같은 명령이 어느 쪽에 갔는지 알 수 없다.- 서비스 호출이 무작위로 둘 중 하나에 간다.
- 두 노드가 같은 토픽에 발행하면 구독자는 뒤섞인 스트림을 받는다.
ros2 node list | sort | uniq -d # 중복 노드 이름 탐지
견해: 중복 이름은 버그가 아니라 설계 결과다(0.2의 "마스터 제거" 대가). 방어는 운영 쪽에서 해야 한다 — launch에서 이름을 데이터로 관리하고, 부팅 스크립트에 위
uniq -d검사를 넣고, 다중 로봇은 네임스페이스로 강제 분리한다(14.9).
1.1.7 다중 로봇 — 네임스페이스·도메인·접두어의 선택
로봇 여러 대를 한 시스템에 통합할 때 이름을 분리하는 방법은 크게 셋이다. 정답은 없고 무엇을 공유하려는가에 달렸다.
① 네임스페이스 분리 — 모든 노드를 /robot1, /robot2 아래로.
- 장점: 같은 그래프 안에서 서로 볼 수 있다. 중앙 조정 노드가 두 로봇을 다 관측·명령할 수 있다. 코드 변경이 없다(상대 이름만 썼다면).
- 단점: 디스커버리 부하가 로봇 수에 비례해 커진다(3.3).
/tf가 문제다 — 전역 이름이라 그대로 두면 두 로봇의 변환이 한 트리에 섞인다./tf·/tf_static도 네임스페이스 안으로 리매핑하고, 프레임 이름에도 접두어를 넣어야 한다(5.2). - 맞는 경우: 협조하는 소수(2~10대) 로봇, 중앙 관제가 필요한 경우.
② 도메인 분리 — 로봇마다 ROS_DOMAIN_ID를 다르게.
- 장점: 디스커버리 트래픽이 완전히 격리된다. 이름 충돌이 원천적으로 불가능하다. 한 로봇의 그래프 폭주가 다른 로봇에 영향을 주지 않는다.
- 단점: 로봇 간 통신이 안 된다. 필요하면 브리지 프로세스를 따로 세워야 한다(양쪽 도메인에 참여하는 노드, 또는 상위 레벨 프로토콜).
- 맞는 경우: 로봇이 서로 독립적으로 일하고, 조정은 ROS 밖(클라우드·MQTT·REST)에서 하는 경우. 플릿 운영의 다수가 여기에 해당한다(14.9).
③ 접두어(prefix)만 — 이름 앞에 robot1_을 붙임.
- 장점: 도구 호환성이 가장 좋다(네임스페이스를 다루지 못하는 오래된 도구·설정에서도 동작).
- 단점: 계층 구조가 없어 필터링·일괄 조작이 어렵다. 사실상 수동으로 관리해야 한다.
- 맞는 경우: 임시 조합, 레거시 통합. 새 시스템에는 권하지 않는다.
| 축 | ① 네임스페이스 | ② 도메인 | ③ 접두어 |
|---|---|---|---|
| 로봇 간 통신 | 가능 | 불가(브리지 필요) | 가능 |
| 디스커버리 격리 | 없음 | 완전 | 없음 |
| 확장 한계 | 수십 대에서 디스커버리 병목 | 도메인 수(0~101 권장 범위) | 관리 한계가 먼저 옴 |
/tf 처리 | 리매핑 필수 | 자동 격리 | 프레임 접두어 필수 |
| 도구 친화성 | 좋음 | 좋음(단일 도메인 안에서) | 보통 |
견해: 로봇이 서로 실시간으로 협조해야 하면 ①, 각자 일하고 결과만 모으면 ② 를 기본으로 본다. 실무에서는 혼합도 흔하다 — 로봇 내부는 도메인 격리, 로봇 간은 별도 채널(14.9). 규모가 커지면 어느 쪽이든 Discovery Server(3.4)나 zenoh(3.10)를 검토하게 된다.
1.1.8 그래프 질의 API — 노드가 그래프를 보는 법
CLI가 하는 일을 코드에서도 할 수 있다. 자동 재연결·감시 노드를 만들 때 쓴다.
auto names = node->get_node_names(); // FQN 목록
auto topics = node->get_topic_names_and_types(); // {이름: [타입…]}
auto pubs = node->get_publishers_info_by_topic("/scan"); // 엔드포인트별 QoS·GID 포함
auto n_sub = node->count_subscribers("/scan");
names = node.get_node_names_and_namespaces()
infos = node.get_publishers_info_by_topic('/scan')
get_publishers_info_by_topic이 특히 쓸모 있다 — 상대 엔드포인트의 QoS 프로파일을 실제로 볼 수 있어서, 발행자의 신뢰성에 맞춰 구독자를 만드는 적응형 코드를 작성할 수 있다(ros2 topic info -v가 쓰는 것과 같은 정보 — 0.7.5).
그래프 이벤트 대기:
auto event = node->get_graph_event();
node->wait_for_graph_change(event, std::chrono::seconds(1));
한계를 정확히 알아야 한다.
| 한계 | 설명 |
|---|---|
| 최종 일관성만 보장 | 디스커버리는 점진적이다. 방금 기동된 노드가 아직 안 보일 수 있고, 종료된 노드가 아직 보일 수 있다(0.7.3). |
| "보인다 ≠ 통신된다" | 상대가 목록에 있어도 QoS가 안 맞으면 데이터는 안 온다(1.5). |
| 폴링은 답이 아니다 | 루프에서 get_topic_names_and_types()를 실행하면 비용이 크다. 그래프 이벤트를 쓴다. |
count_subscribers는 시점 값 | 발행 직전에 확인해도 그 사이에 바뀔 수 있다. 경합을 없애는 용도로는 못 쓴다. |
전형적 오용: "구독자가 생길 때까지 기다렸다가 발행"을 count_subscribers 폴링으로 구현하는 것. 초기 메시지 유실을 막으려는 의도는 옳지만, 올바른 해법은 TRANSIENT_LOCAL 내구성이다(1.5·1.6). 폴링은 경합을 줄일 뿐 없애지 못한다.
1.1.9 enclave — 보안을 위한 별도 이름 공간
노드에는 이름·네임스페이스 외에 enclave라는 세 번째 식별자가 있다.
ros2 run my_pkg my_node --ros-args --enclave /robot1/sensors
enclave는 보안 자격(키·인증서·정책)을 묶는 단위이며, 노드 이름과 독립이다(13.2). 여러 노드가 하나의 enclave를 공유할 수도, 노드 하나가 전용 enclave를 가질 수도 있다. 이 분리는 의도적이다 — 보안 경계와 그래프 이름 구조는 서로 다른 축이기 때문이다. 예를 들어 "센서 노드 전부는 같은 키를 쓴다"는 정책은 이름 계층과 일치하지 않을 수 있다.
보안을 켜지 않으면 enclave는 기본값(/)이고 신경 쓸 일이 없다. 하지만 나중에 SROS2를 켤 계획이라면 이름 설계 단계에서 enclave 경계를 함께 그려 두는 편이 낫다 — 나중에 키스토어 구조를 갈아엎는 것보다 비용이 낮다.
1.1.12 __ 예약은 어디까지 강제되는가 — 실측
이 장은 위에서 "__로 시작하는 이름은 검증에서 거부된다"고 적어 두었다. 그 문장이 맞는지 확인하지 않은 채였다. 측정해 봤더니 절반만 맞았다(실행 확인, Jazzy).
1.1.12.1 이름으로서는 전부 통과한다
| 시도 | 결과 |
|---|---|
Node("__weird") | 생성됨 — get_name()이 __weird를 돌려준다 |
validate_node_name("__weird") | 통과 |
validate_topic_name("__weird") · ("/ns/__x") | 통과 |
create_publisher(String, "__weird", 10) | 생성됨 |
거부되지 않는다. 이름 검증기(rmw_validate_node_name·rmw_validate_topic_name 계열)는 문자·형식만 본다 — 밑줄 두 개는 유효한 문자다.
1.1.12.2 리매핑 규칙에서는 정말로 거부된다
$ … --ros-args -r __weird:=foo
RCLError: failed to initialize rcl: Couldn't parse remap rule: '-r __weird:=foo'.
Error: Expecting token or wildcard, at ./src/rcl/arguments.c:1222
| 규칙 | 결과 |
|---|---|
-r __node:=renamed | 노드 이름이 renamed로 바뀐다 |
-r __ns:=/x | 네임스페이스가 /x가 된다 |
-r __weird:=foo | 파싱 실패 — Expecting token or wildcard |
-r normal:=other | 정상 처리(해당 이름이 없으면 아무 일도 안 일어난다) |
__로 시작하는 것은 "예약어 자리"이므로, 파서는 그 자리에 아는 이름(__node·__ns·__name)만 허용한다. 모르는 __weird는 이름이 아니라 잘못된 예약어로 읽혀 거부된다.
1.1.12.3 그래서 정확한 표현은 무엇인가
*예약은 리매핑 규칙의 왼쪽 자리에 걸려 있지, 이름 문자열에 걸려 있지 않다.*
실무적으로는 결과가 비슷하다 —
__로 시작하는 토픽을 만들면 그 토픽을 리매핑할 방법이 없어지므로(규칙 왼쪽에 못 쓴다) 결국 쓰지 말아야 한다. 하지만 "만들면 거부된다"와 "만들어지되 리매핑이 막힌다"는 디버깅 경험이 전혀 다르다. 앞엣것은 즉시 실패하고, 뒤엣것은 한참 뒤에 비정상이 된다.
견해: 이런 문장이 가장 위험하다. 원인 설명("리매핑 규칙이 이 형태를 쓰기 때문")은 정확한데 결론만 한 걸음 더 나갔다. 원인이 그럴듯하니 아무도 결론을 확인하지 않는다 — 84차에
hz에서 겪은 것과 반대 방향의 같은 함정이다(그때는 원인이 틀리고 처방이 맞았다).
1.1.12.4 __ns가 먼저 반영된다는 주장(1.1.5) — 실측
실행 확인(2026-08-18, ros:jazzy-ros-base, rclpy) — 1.1.5가 단정한 순서(__ns·__node가 일반 리매핑보다 먼저 적용된다)를 상대 토픽 chatter에 -r __ns:=/robot1 -r chatter:=say를 동시에 걸어 재현했다.
| 준 인자 | 결과 토픽 |
|---|---|
| (기본, 리매핑 없음) | /chatter |
-r __ns:=/robot1만 | /robot1/chatter |
-r chatter:=say만 | /say |
-r __ns:=/robot1 -r chatter:=say | /robot1/say |
순서를 반대로 지정: -r chatter:=say -r __ns:=/robot1 | /robot1/say(동일) |
책의 서술이 맞았다. __ns가 없었다면 chatter:=say는 /say가 됐어야 하는데(세 번째 행), 함께 주면 네임스페이스가 반영된 뒤의 이름에 리매핑이 걸려 /robot1/say가 된다 — __ns가 확장의 입력 자체를 먼저 바꾼다는 설명과 정확히 일치한다. 덤으로 확인한 것: 마지막 행처럼 커맨드라인에 -r 인자를 쓴 순서를 바꿔도 결과가 같다 — 적용 순서는 인자를 나열한 순서가 아니라 __ns·__node의 특수 지위에서 나온다는 것을 보여 준다.
1.1.12.5 이름 충돌 시 "둘 다 그대로 동작한다"(1.1.6) — 실측
실행 확인(2026-08-18, ros:jazzy-ros-base, rclpy) — 같은 이름(dup_node)의 노드를 별도 프로세스 두 개로 실행해 확인했다.
$ ros2 node list
WARNING: Be aware that there are nodes in the graph that share an exact name,
which can have unintended side effects.
/dup_node
/dup_node
책의 서술이 맞았다 — 둘 다 종료되지 않고 그대로 동작한다(ps로 두 PID 생존 확인). 1.1.6이 "도구에 따라 한 번만 나온다"고 열어 둔 가능성에 대한 답도 얻었다 — 적어도 ros2 node list는 두 번 나오며, 그것도 단순히 나오는 것이 아니라 "의도치 않은 부작용이 있을 수 있다"는 경고를 먼저 출력한다. 같은 프로세스 안에서 노드 둘을 만들 때도(rclpy.create_node 두 번) 오류 없이 둘 다 생성되지만, rosout 퍼블리셔가 하나만 등록되고 나머지는 그 사실을 경고로 알린다 — 로그 유실이 "둘 다 그대로 동작한다"의 숨은 대가다.
1.1.10 함정 카탈로그
| # | 함정 | 증상 | 대처 |
|---|---|---|---|
| 1 | 코드에 절대 이름 하드코딩 | 다중 로봇에서 충돌 | 상대 이름 + 네임스페이스 |
| 2 | ~/x를 쓰는데 노드 이름을 리매핑 | 토픽 경로 전체가 이동 | 노드 이름 변경 시 ~ 사용처 점검 |
| 3 | /tf를 네임스페이스 안 씌움 | 두 로봇의 tf가 한 트리에 섞임 | /tf·/tf_static 리매핑 + 프레임 접두어(5.2) |
| 4 | 노드 이름 중복 | 파라미터·서비스가 무작위 대상에 감 | 부팅 시 uniq -d 검사(1.1.6) |
| 5 | 리매핑 좌변을 상대 이름으로 씀 | 매칭이 안 되거나 다른 것이 매칭 | 좌변에 FQN 사용, node info로 확인 |
| 6 | 숫자로 시작하는 이름(2d_nav) | 초기화 시 예외 | nav_2d 식으로 |
| 7 | count_subscribers 폴링으로 초기 유실 방지 | 여전히 가끔 유실 | TRANSIENT_LOCAL(1.6) |
| 8 | ROS 1 습관으로 ~param | 파라미터 이름에 ~가 그대로 들어감 | 파라미터에 이름 해석 없음(1.9) |
| 9 | 노드 이름에 하이픈 | 검증 실패로 즉시 종료 | 밑줄 사용 |
| 10 | 프레임 이름에 앞 슬래시(/base_link) | tf2가 거부 | tf2 프레임은 슬래시 없는 이름(5.1) |
10번은 특히 ROS 1 경험자가 자주 밟는다. 토픽 이름과 tf 프레임 이름은 다른 이름 공간이다. tf2에서 프레임은 base_link이지 /base_link가 아니다.
1.1.11 체크포인트
- "노드는 프로세스가 아니다"의 실무적 결과 세 가지를 말할 수 있는가.
- 네임스페이스
/r1, 노드 이름cam인 노드에서~/image,image,/image가 각각 어떤 FQN이 되는지 즉시 답할 수 있는가. -r __ns:=와-r scan:=/x가 적용되는 순서와, 리매핑 좌변에 FQN을 쓰라는 권고의 이유를 설명할 수 있는가.- ROS 2가 동적 리매핑을 지원하지 않는 이유를 아키텍처로 설명할 수 있는가. 실행 중 연결을 바꿔야 하면 무엇으로 푸는가.
- 같은 이름의 노드 둘이 동시에 실행 중일 때 벌어지는 일과 탐지 방법을 말할 수 있는가.
- 로봇 5대를 한 시스템에 통합할 때 네임스페이스·도메인·접두어 중 무엇을 고르겠는가. 그 선택이
/tf에 어떤 작업을 요구하는가. get_publishers_info_by_topic으로 알 수 있는 것과, 그래프 질의가 보장하지 않는 것을 구분할 수 있는가.- 초기 메시지 유실을 막는 올바른 수단은 무엇인가. 왜 구독자 수 폴링이 아닌가.
__로 시작하는 토픽 이름을 만들면 어떻게 되는가. 거부되는가, 만들어지는가, 그리고 그 뒤에 무엇이 막히는가(1.1.12).
다음 장 1.2에서는 이 이름들이 실어 나르는 내용물 — msg·srv·action 인터페이스 정의와 그 뒤의 IDL — 로 넘어간다.