AEGLOSLAB ROS 2 Jazzy 대전

제11부 도구·관측성

11.4 RViz2와 플러그인 작성

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

RViz2는 ROS에서 가장 많이 쓰이는 도구이자 가장 자주 오해되는 도구다. 오해의 핵심은 이것이다 — RViz2는 "로봇의 상태"를 보여주지 않는다. "발행된 메시지"를 보여준다. 그 둘은 같지 않다.

이 구분이 진단에서 결정적이다. RViz2에 뭔가 안 보일 때, 원인은 ① 발행이 없음 ② QoS 불일치 ③ tf가 없음 ④ 설정 문제 중 하나이고, 각각 조치가 다르다(11.4.9).

배우는 것:

  • 구조 — 디스플레이·패널·툴·뷰 컨트롤러.
  • 고정 프레임 — 가장 자주 잘못 설정되는 것.
  • 성능 — 무엇이 비용이 큰가.
  • 설정 관리 — .rviz 파일.
  • 마커 — 코드에서 그리는 간단한 방법.
  • 인터랙티브 마커 — 조작 가능한 시각화.
  • 플러그인 작성 — 디스플레이·패널.
  • 진단 — "안 보인다"의 체계적 해결.

선수 지식: 1.6(QoS), 5.1·5.2(tf), 1.1.4(토픽), 4.5(빌드), 4.2.6(pluginlib).

정직: RViz2 플러그인 API(클래스명·시그니처)는 버전 의존이며(확인 필요), Qt·Ogre 지식을 요구한다. 이 장은 구조와 판단에 집중하고, 완전한 플러그인 코드는 골격만 제시한다. 이 환경에서 실행 검증하지 않았다(목차 3).(→ 188차 확인: RViz2 자체를 헤드리스로 실제 실행했고(Xvfb 필요, 아래 실행 확인(188차) 참고), 11.4.4의 RobotModel·Image 디스플레이 두 마커를 실물 소스(rviz-default-plugins 14.1.22)로 확인·정정했다. 플러그인 API 버전 의존성 자체(클래스명·시그니처가 배포판마다 어떻게 다른가)는 이번에도 시도하지 않았다. → 189차 확인: 이 버전 의존성도 Jazzy·Humble 헤더 전수 대조로 확인했다 — rviz_common 20%·rviz_default_plugins 39%의 공개 헤더가 실제로 달랐고, 시그니처가 완전히 바뀐 항목도 있었다. 아래 실행 확인(189차) 참고.)

실행 확인(189차) — "RViz2 플러그인 API는 버전 의존"이라는 서술을 Jazzy(rviz_common·rviz_default_plugins 14.1.22)와 Humble(11.2.28) 두 배포판의 실물 헤더를 전수 대조해 정량 확인했다. 83·84차의 API-diff 방식(그때는 rclcpp)을 재사용했다. rviz_common은 공통 헤더 84개 중 17개(20.2%)가 서로 달랐고(Jazzy 전용 신규 파일 1개, regex_filter_property.hpp), rviz_default_plugins는 공통 헤더 97개 중 38개(39.2%)가 달라 변화율이 두 배 가까이 높았다(Jazzy 전용 신규 파일 3개 — camera_info_display.hpp는 완전히 새로운 디스플레이 타입, get_transport_from_topic.hpp·point_cloud_transport_display.hpp는 PointCloud2도 Image처럼(11.4.4, 188차) image_transport형 전송 지원을 얻었음을 시사). 가장 크게 바뀐 파일 하나를 분석해 보니 실제로 시그니처가 깨지는 변경이었다 — ROSImageTexture의 ImageData 생성자가 Humble의 (std::string encoding, const uint8_t*, size_t size)(3개 인자)에서 Jazzy의 (Ogre::PixelFormat pixformat, const uint8_t*, size_t data_size_in_bytes, bool take_ownership)(4개 인자, 두 번째 인자 타입 자체가 문자열→열거형으로 교체)로 완전히 바뀌었고, getName()·getWidth() 등 접근자 메서드도 비-const(Humble, 헤더에 인라인 정의)에서 const(Jazzy, .cpp로 분리)로 바뀌었다 — Humble용으로 작성한 플러그인 코드는 이 API를 그대로 쓰면 Jazzy에서 컴파일이 안 된다. 반면 가장 기본이 되는 Display 기반 클래스 자체는 종료된 ROS1 시절 코드(#if 0) 제거뿐, 사실상 안정적이었다 — 최소한의 디스플레이 플러그인(속성 몇 개 붙인 정도)은 버전 간 이식성이 상대적으로 높지만, 이미지 텍스처·인터랙티브 마커·TF·맵 디스플레이처럼 세부 내장 기능을 변경하는 플러그인일수록 깨질 위험이 크다는 뜻이다. 정직한 한계: 헤더(.hpp)만 전수 대조했고 .cpp 구현부는 보지 않았다 — 헤더가 그대로인데 구현만 바뀐 경우는 이 방법으로 검출하지 못한다. 실제로 플러그인을 두 버전에 컴파일해 실패를 재현하지는 않았다(헤더 대조만으로 시그니처 불일치를 판단). 원본: tools/gap_harness/gap189/rviz_api_diff/(diff_summary.txt·ros_image_texture_diff.txt·frame_manager_iface_diff.txt·findings_summary.txt).

11.4.2 구조

RViz2 디스플레이 데이터를 3D로 패널 UI 위젯 툴 마우스 상호작용 뷰 컨트롤러 카메라 Ogre 3D 씬 Qt 위젯
구성역할예
디스플레이토픽·tf를 3D로 그림LaserScan·PointCloud2·RobotModel·Map
패널부가 UIDisplays·Views·Tool Properties·Nav2 Goal
툴마우스 조작2D Goal Pose·Publish Point·Select
뷰 컨트롤러카메라 모드Orbit·TopDownOrtho·FPS

모두 pluginlib 기반이라 확장 가능하다(11.4.7).

렌더링은 Ogre가 한다:

결과설명
GPU 사용드라이버 문제가 RViz2 문제로 나타남
원격 실행 어려움X 포워딩이 느림(11.4.6)(→ 188차 확인: 원격이 느린 이유이자 동시에 헤드리스가 완전히 불가능하지는 않은 이유를 실측으로 밝혔다 — Xvfb로 가상 디스플레이를 주면 GPU·원격 접속 없이도 완전히 동작한다. 아래 실행 확인(188차) 참고.)
3D 성능 특성점 개수가 직접 영향

실행 확인(188차) — RViz2가 정말 디스플레이 없이는 기동되지 않는지, Gazebo Harmonic의 카메라 센서(162차)처럼 자동으로 헤드리스 전환이 되는지 직접 실행으로 확인했다. 결론: 안 된다 — 하지만 Xvfb를 주면 완전히 동작한다. 세 조건을 순서대로 시험했다. ① DISPLAY 자체를 안 준 채 rviz2를 그대로 실행 — Qt가 전혀 시작하지 못하고 즉시 코어 덤프로 종료된다("qt.qpa.xcb: could not connect to display", "Could not load the Qt platform plugin \"xcb\"") — Ogre 이전에 Qt 레이어에서부터 실패한다. ② QT_QPA_PLATFORM=offscreen으로 Qt의 자체 헤드리스 플랫폼을 명시 지정 — Qt 단계는 통과하지만, 이번엔 더 안쪽의 Ogre 1.x(GLX 기반, rviz-ogre-vendor) 렌더링 엔진이 명시적으로 예외를 던지며 종료된다("Ogre::RenderingAPIException: Couldn't open X display") — Gazebo Harmonic의 Ogre2(162차)와 달리, RViz2의 Ogre 1.x/GLX 렌더러는 디스플레이 부재를 스스로 감지해 소프트웨어 렌더링으로 자동 전환하는 기능이 없다. ③ Xvfb :99 -screen 0 1280x1024x24 를 실행하고 DISPLAY=:99로 rviz2 실행 — 완전히 정상 기동했다: 로그에 "OpenGl version: 4.5 (GLSL 4.5)"가 출력되고(Xvfb+Mesa 소프트웨어 렌더링으로 실제 OpenGL 컨텍스트를 얻음), timeout으로 강제 종료할 때까지 안정적으로 계속 실행됐다(크래시 아님). xwd+ImageMagick으로 화면을 실제로 캡처하니(rviz2_screen.png) 메뉴바·전체 툴바(Interact·Move Camera·Select·Focus Camera·Measure·2D Pose Estimate·2D Goal Pose·Publish Point)·Displays 패널(Fixed Frame=map, Grid가 3D 뷰포트에 실제로 격자를 그리고 있음)·Views 패널(Orbit 뷰 컨트롤러 속성 전체)·상태 바("RViz is ready", ROS/Wall Time 둘 다 흐름, 31 fps)까지 완전하고 실제로 작동하는 GUI임을 시각적으로 확인했다(단순히 "종료되지 않았다"가 아니라 실제 인터랙티브 수준 렌더링). 정직한 결론: "헤드리스에서 GPU·디스플레이 없이 렌더링이 된다"(162차, 카메라)는 RViz2에는 그대로 적용되지 않는다 — RViz2는 Xvfb(또는 다른 가상 X 서버)가 반드시 있어야 하며, 그것만 있으면 GPU 없이도 완전히 동작한다. 이는 11.4.6의 "X 포워딩이 느리다"는 서술과 정합적이다 — RViz2가 정말로 X 서버(실물·포워딩·가상 불문)를 필요로 한다는 것을 실측으로 확인한 것이다. 원본: tools/gap_harness/gap188/rviz_test/(rviz2_screen.png·findings_summary.txt).

11.4.3 고정 프레임

RViz2 설정에서 가장 자주 잘못되는 항목이다.

고정 프레임(Fixed Frame)은 "세계가 정지해 있다고 볼 기준"이다.

지도 기준 · 측위 확인 주행 · 오도메트리 확인 로봇 중심 · 센서 확인 Fixed Frame 선택 무엇을 보려는가? map odom base_link
고정 프레임보이는 것용도
map로봇이 지도 위를 움직임측위·항법 확인
odom로봇이 부드럽게 움직임, 지도는 튐오도메트리 확인(5.1.7)
base_link로봇이 정지, 세계가 움직임센서 배치 확인

견해: 고정 프레임을 바꿔 보는 것이 강력한 진단 기법이다. odom 기준에서 스캔이 잘 겹치면 오도메트리가 좋은 것이고, map 기준에서 스캔이 급변하면 측위가 흔들리는 것이다(5.1.7의 "odom은 연속·map은 점프"가 눈에 보인다).

함정: 고정 프레임으로 가는 tf가 없으면 아무것도 안 보인다. "Global Status: Error — Fixed Frame [map] does not exist"가 출력된다. map이 없으면(측위 미실행) odom이나 base_link로 바꾼다.

Global Options:

옵션의미
Fixed Frame위
Background Color배경
Frame Rate렌더 목표 — 낮추면 CPU 절약

11.4.4 주요 디스플레이

디스플레이토픽주의
TF/tf·/tf_static프레임 다수면 부하가 큼 — 필요한 것만 표시
RobotModelrobot_description(5.3.8)토픽·파라미터 방식 확인(확인 필요)(→ 188차 확인: 토픽이 기본, 파일도 가능 — 파라미터는 아니다. 아래 실행 확인(188차) 참고)
LaserScansensor_msgs/LaserScanQoS를 BEST_EFFORT로(1.6)
PointCloud2sensor_msgs/PointCloud2가장 부하가 큼 — Decay Time·크기
Imagesensor_msgs/Imageimage_transport 미지원(확인 필요)(→ 188차 정정: 이 서술이 틀렸다 — 실제로는 지원한다. 아래 실행 확인(188차) 참고)
Mapnav_msgs/OccupancyGridTRANSIENT_LOCAL 필요(1.6.3.3)
Pathnav_msgs/Path경로 시각화
Marker·MarkerArrayvisualization_msgs커스텀 시각화(11.4.6)
CostmapMap 또는 전용Nav2(8.4)
PoseWithCovariance측위공분산 타원

함정: 디스플레이마다 QoS를 설정해야 한다. RViz2 기본이 RELIABLE인 디스플레이에 BEST_EFFORT 센서를 연결하면 아무것도 안 보인다(1.6.3.1의 최다 사고가 여기서도). 디스플레이 속성의 "Reliability Policy"를 확인한다.

함정: /map이 안 보이면 Durability를 Transient Local로 바꾸라. map_server가 TRANSIENT_LOCAL로 한 번만 발행하므로(1.6.3.3), VOLATILE 구독자는 못 받는다.

실행 확인(188차) — RobotModel·Image 두 디스플레이의 마커를 apt-get source ros-jazzy-rviz-default-plugins(14.1.22)로 받은 실물 소스로 직접 확인·정정했다. ① RobotModel — "토픽·파라미터 방식"의 정답은 "토픽(기본)·파일, 파라미터는 아님"이다. RobotModelDisplay 클래스 자체가 rviz_common::RosTopicDisplay<std_msgs::msg::String>를 상속하고, description_source_property_라는 EnumProperty(기본값 "Topic")에 등록된 옵션은 "Topic"과 "File" 단 둘뿐이다 — "Parameter" 옵션은 코드 어디에도 없다. 토픽 모드의 QoS는 rclcpp::QoS(rclcpp::KeepLast(1)).transient_local()로 명시돼 있어, /map(1.6.3.3, 바로 위 함정)과 같은 "한 번 발행, 늦게 온 구독자도 받아야 함" 패턴과 정확히 일치한다(관례상 robot_state_publisher가 발행하는 /robot_description 토픽). 정직한 단서: 설치된 헤더의 load_urdf() 주석은 여전히 "Loads a URDF from the ros-param named by our ... property"라고 적혀 있어 파라미터 시절의 흔적이 남아 있지만, 실제 동작하는 코드는 이미 토픽/파일 드롭다운으로 바뀌어 있다 — 주석이 낡았을 뿐 실제 동작과는 다르다. ② Image — "image_transport 미지원"은 틀린 서술이다, 실제로는 지원한다. ImageDisplay 클래스는 ImageTransportDisplay<sensor_msgs::msg::Image>를 상속하며, 이 기반 클래스가 image_transport/image_transport.hpp·image_transport/subscriber_filter.hpp를 실제로 포함하고 image_transport::SubscriberFilter를 실제로 사용한다 — getTransportFromTopic()으로 입력한 토픽 이름 자체에서 전송 방식(예: .../compressed)을 읽어 해당 트랜스포트 플러그인을 로드하는, 일반 노드에서 쓰는 image_transport::Subscriber와 동일한 방식이다(image_transport::TransportLoadException까지 실제로 처리). 책의 이 항목은 단순히 "확인 안 됨"이 아니라 실제로 틀린 서술이었다. 원본: tools/gap_harness/gap188/rviz_test/source_evidence/(robot_model_display_full.hpp·robot_model_display_source_excerpt.cpp·image_transport_display_source_excerpt.hpp).

11.4.5 성능

RViz2가 느려지는 원인은 대부분 몇 가지로 좁혀진다.

원인영향대처
PointCloud2 점 개수가장 큼다운샘플·Decay Time 0·Size 축소
Decay Time누적 렌더0 또는 짧게
TF 프레임 다수선·이름 렌더필요한 프레임만·이름 끄기
이미지 다수대역·디코딩필요한 것만
원격 X 포워딩매우 느림11.4.6
Marker 다수개수에 비례집계·수명
코스트맵 갱신큰 그리드갱신 빈도
아니오 예 RViz2가 느리다 PointCloud2 끄기 빨라졌나? 다운샘플 · Decay 0 · 점 크기 TF · 이미지 순서로 끄기 어느 것? 해당 항목 조정

견해: "하나씩 끄며 원인을 찾는" 절차가 확실하다. 추측으로 조정하기보다 5초면 원인을 특정할 수 있다.

견해: RViz2가 느려서 시스템이 느린 것으로 오해하는 경우가 흔하다. RViz2는 자원 소모가 큰 GUI이며, RViz2를 끄면 로봇이 정상 동작하는지 반드시 확인하라. 특히 개발 PC가 로봇 온보드일 때 RViz2가 CPU를 잠식해 제어 주기를 깨뜨릴 수 있다(6.6.6).

11.4.6 설정과 원격

.rviz 설정 파일:

# 저장: File → Save Config As
# 실행 시 지정
rviz2 -d $(ros2 pkg prefix my_robot_bringup)/share/my_robot_bringup/rviz/nav.rviz
# launch에서
Node(package='rviz2', executable='rviz2',
     arguments=['-d', os.path.join(pkg_share, 'rviz', 'nav.rviz')],
     parameters=[{'use_sim_time': use_sim_time}])   # ★ 재생·시뮬 시 필수

견해: 목적별 .rviz를 만들어 패키지에 두라. nav.rviz(항법)·slam.rviz(매핑)·manip.rviz(조작)·debug.rviz(전체). 매번 디스플레이를 추가하는 시간이 사라지고, 팀이 같은 화면을 본다.

함정: .rviz를 버전 관리에 넣되, 자동 저장되는 변경에 주의하라. RViz2가 종료 시 설정을 덮어쓸 수 있어 의도치 않은 diff가 생긴다(확인 필요: 동작).

함정: use_sim_time을 RViz2에도 줘야 한다. bag 재생·시뮬에서 이것을 빼면 RViz2가 벽시계로 tf를 조회해 "변환이 미래/과거"라며 아무것도 안 그린다(5.2.4·1.10.9).

원격 실행:

방법특성
개발 PC에서 실행 + 네트워크로 토픽권장 — 로봇 CPU 부담 없음
X 포워딩매우 느림 — 3D 렌더를 네트워크로
VNC·원격 데스크톱X보다 나음
웹 기반 도구대안(확인 필요)

견해: "개발 PC에서 RViz2를 실행하고 로봇 토픽을 구독"이 기본이다. 다만 대용량 토픽이 무선을 잠식하므로(3.9.3·7.8), 포인트클라우드·원본 이미지는 필요할 때만 켜고 image_transport의 압축을 쓴다(7.2.7).

함정: RViz2가 구독하는 순간 대역이 발생한다. 디스플레이를 켜 둔 채 로봇을 운영하면 무선이 포화될 수 있다. 운영 중에는 끄라.

11.4.7 마커 — 코드에서 그리기

플러그인을 만들지 않고 커스텀 시각화를 하는 가장 쉬운 방법이다.

#include <visualization_msgs/msg/marker_array.hpp>

visualization_msgs::msg::Marker m;
m.header.frame_id = "map";
m.header.stamp = now();
m.ns = "detections";               // 네임스페이스
m.id = 0;                          // ns 안에서 고유
m.type = visualization_msgs::msg::Marker::SPHERE;
m.action = visualization_msgs::msg::Marker::ADD;
m.pose.position.x = 1.0;
m.pose.orientation.w = 1.0;        // ★ 0이면 경고·미표시
m.scale.x = m.scale.y = m.scale.z = 0.2;
m.color.r = 1.0; m.color.a = 1.0;  // ★ a=0이면 투명 — 안 보임
m.lifetime = rclcpp::Duration::from_seconds(1.0);   // 자동 소멸
타입용도
ARROW·SPHERE·CUBE·CYLINDER기본 도형
LINE_STRIP·LINE_LIST경로·연결
POINTS다수 점 — 효율적
TEXT_VIEW_FACING라벨
MESH_RESOURCE3D 모델
TRIANGLE_LIST임의 표면

함정: 가장 흔한 두 실수 — orientation.w = 0(쿼터니언이 무효)과 color.a = 0(완전 투명). 둘 다 "마커가 안 보인다"의 대표적 원인이다. w = 1.0과 a = 1.0을 기본으로 두라.

함정: lifetime을 0(무한)으로 두고 매 프레임 새 id를 쓰면 마커가 무한 누적된다. RViz2가 느려지고 메모리를 소모한다. 같은 id를 재사용하거나 lifetime을 설정한다.

견해: MarkerArray로 묶어 한 번에 보내라. 개별 Marker를 다수 발행하는 것보다 효율적이고, 원자적으로 갱신된다.

삭제:

m.action = visualization_msgs::msg::Marker::DELETE;       // 하나
m.action = visualization_msgs::msg::Marker::DELETEALL;    // 전체

인터랙티브 마커:

용도예
목표 자세 지정드래그로 위치 설정
캘리브레이션 조정프레임 미세 조정
교시로봇 자세 지정(9.4)
파라미터 조정3D로

견해: 인터랙티브 마커는 만들 가치가 있는 경우가 분명하다 — 3D 공간에서 값을 지정해야 하는 작업. 숫자를 입력하는 것보다 훨씬 빠르다. 다만 구현 비용이 있으므로, 반복적으로 하는 작업에만 만든다.

11.4.8 플러그인 작성

마커로 안 되는 것이 있을 때 플러그인을 만든다.

마커로 충분플러그인이 필요
도형·선·점·텍스트커스텀 메시지 타입 직접 표시
정적 시각화대량 데이터 효율적 렌더
단순 표시속성 UI로 제어
—패널 UI(버튼·입력)

견해: 대부분의 경우 마커로 충분하다. 플러그인은 Qt·Ogre·pluginlib 지식이 필요하고 버전 의존성이 있다. "커스텀 메시지를 RViz2에서 직접 보고 싶다"거나 "조작 패널이 필요하다" 같은 명확한 이유가 있을 때만 만든다.

디스플레이 플러그인 골격:

// my_display.hpp
#include <rviz_common/message_filter_display.hpp>
#include <rviz_common/properties/color_property.hpp>

namespace my_rviz_plugins
{
class MyDisplay
: public rviz_common::MessageFilterDisplay<my_msgs::msg::MyThing>
{
  Q_OBJECT
public:
  MyDisplay();
  void onInitialize() override;
  void reset() override;

private Q_SLOTS:
  void updateColor();

private:
  void processMessage(my_msgs::msg::MyThing::ConstSharedPtr msg) override;

  rviz_common::properties::ColorProperty * color_property_;
  // Ogre 씬 노드·비주얼 객체
};
}  // namespace my_rviz_plugins
// my_display.cpp
#include <pluginlib/class_list_macros.hpp>
PLUGINLIB_EXPORT_CLASS(my_rviz_plugins::MyDisplay, rviz_common::Display)
<!-- plugins_description.xml -->
<library path="my_rviz_plugins">
  <class name="my_rviz_plugins/MyDisplay"
         type="my_rviz_plugins::MyDisplay"
         base_class_type="rviz_common::Display">
    <description>내 커스텀 메시지 표시</description>
    <message_type>my_msgs/msg/MyThing</message_type>
  </class>
</library>
# CMakeLists.txt
set(CMAKE_AUTOMOC ON)                  # ★ Qt MOC
find_package(rviz_common REQUIRED)
find_package(Qt5 REQUIRED COMPONENTS Widgets)
add_library(my_rviz_plugins SHARED src/my_display.cpp)
target_link_libraries(my_rviz_plugins Qt5::Widgets)
ament_target_dependencies(my_rviz_plugins rviz_common rviz_rendering my_msgs)
pluginlib_export_plugin_description_file(rviz_common plugins_description.xml)

정직: 클래스 계층·헤더 이름·필수 매크로는 버전 의존이다(확인 필요). RViz2 소스의 기존 플러그인(예: rviz_default_plugins)을 참조해 현재 API를 확인하는 것이 가장 확실하다.

패널 플러그인:

#include <rviz_common/panel.hpp>

class MyPanel : public rviz_common::Panel
{
  Q_OBJECT
public:
  explicit MyPanel(QWidget * parent = nullptr);
  void onInitialize() override;      // 노드 접근
  void save(rviz_common::Config config) const override;    // 설정 저장
  void load(const rviz_common::Config & config) override;
};
패널 용도예
운영 버튼시작·정지·복귀
상태 표시배터리·모드·진단
파라미터 조정슬라이더
작업 트리거미션 실행

견해: 운영자용 패널은 투자 가치가 높다. 현장에서 터미널로 서비스를 호출하게 하는 것보다, 버튼 몇 개가 있는 패널이 훨씬 안전하고 빠르다. 다만 운영 UI를 RViz2에 의존하는 것이 옳은지는 별개 판단이다 — 전용 UI가 나을 수 있다.

함정: Q_OBJECT를 쓰면 CMAKE_AUTOMOC ON이 필요하다. 빠뜨리면 링크 오류(vtable 없음)가 난다.

11.4.9 "안 보인다" 진단

RViz2 진단의 표준 절차다.

Warn: No messages OK인데 안 보임 아니오 Error: Fixed Frame 예 안 보인다 Display Status? tf 없음 → 프레임 변경· tf 확인 발행 확인 ros2 topic hz 설정·시야 발행되나? 발행자 문제 (1.4.4) QoS 불일치 확인 색 alpha · 크기 · 카메라 위치
증상확인원인
Fixed Frame does not existros2 run tf2_tools view_framestf 없음(5.2.5)
No messages receivedros2 topic hz미발행
발행되는데 안 옴ros2 topic info -vQoS 불일치(1.5.4)
상태 OK인데 안 보임설정alpha 0·크기 0·색 배경과 동일
비정상적인 위치tf프레임 오설정(5.1.8)
깜빡임두 발행자tf 중복(5.1.4)
뒤집힘optical frameREP 105·103(7.1.4)

견해: "Display Status를 먼저 보라"가 첫 단계다. RViz2가 이미 원인을 말해 주는 경우가 많은데, 상태 창을 펼치지 않아 놓친다. 각 디스플레이를 확장하면 Topic·Status가 나온다.

견해: RViz2에서 보이는 것과 알고리즘이 받는 것이 다를 수 있다(11.4.1의 반복). RViz2 디스플레이의 QoS는 별도 설정이라, RViz2에는 보이는데 노드는 못 받거나 그 반대일 수 있다. ros2 topic info -v로 실제 연결을 확인하는 것이 확실하다(1.5.6).

11.4.10 함정 카탈로그

#함정증상대처
1QoS 불일치아무것도 안 보임디스플레이 QoS 설정
2/map Durability지도 안 보임Transient Local
3Fixed Frame 부재Global Status Error프레임 변경·tf 확인
4use_sim_time 누락재생 시 안 보임RViz2에도 설정
5orientation.w = 0마커 안 보임·경고w = 1.0
6color.a = 0투명a = 1.0
7마커 무한 누적느려짐·메모리id 재사용·lifetime
8PointCloud2 과다매우 느림다운샘플·Decay 0
9X 포워딩매우 느림로컬 실행
10운영 중 RViz2 구독무선 포화끄기
11온보드 RViz2제어 주기 방해원격 실행
12Display Status 미확인시행착오먼저 확인
13CMAKE_AUTOMOC 누락링크 오류설정
14RViz2 표시를 알고리즘 입력으로 오해잘못된 진단topic info -v

11.4.11 체크포인트

  • "RViz2는 로봇 상태가 아니라 발행된 메시지를 보여준다"는 말의 진단적 함의는?
  • RViz2의 네 구성 요소와 각각의 예를 들 수 있는가.
  • 고정 프레임 셋과 각각이 보여주는 것을 말할 수 있는가. 진단 기법으로 어떻게 쓰는가.
  • 주요 디스플레이의 QoS 함정 둘은 무엇인가.
  • RViz2 성능 저하 원인 일곱 가지와, 원인을 찾는 절차는?
  • RViz2가 로봇 성능에 미치는 영향과, 온보드 실행의 위험은?
  • 목적별 .rviz를 만들라는 조언의 근거는?
  • 원격 실행 네 방법과 권장안, 그리고 그 대가는?
  • 마커의 두 가지 최다 실수와 누적 문제의 원인·대처는?
  • 마커로 충분한 경우와 플러그인이 필요한 경우를 구분할 수 있는가.
  • 패널 플러그인의 용도와, "운영 UI를 RViz2에 두는 것"에 대한 판단은?
  • "안 보인다" 진단의 첫 단계와, 증상별 원인 일곱 가지를 말할 수 있는가.

다음 장 11.5은 rqt·PlotJuggler — 그래프·시계열·로그를 다루는 분석 도구들이다.