Skip to content

RViz panel

Package: ros2/rviz_autodiag_panel · Files: autodiag_panel.cpp (connection, Health, Topic, AI assistant), graph_tab.cpp (Graph), configure_tab.cpp (Configure RViz)

The panel is an rviz_common::Panel plugin exported through pluginlib. It is deliberately thin: it collects RViz context, talks to the server, and applies validated plans. All diagnosis and AI logic stays on the server.

flowchart LR
    subgraph rviz["rviz2 process"]
        dt["Display tree<br/>DisplayGroup · Display · Property"]
        subgraph panel["AutoDiagPanel"]
            net["QNetworkAccessManager<br/>async, per-request timeouts"]
            tabs["Tabs<br/>Health · Topic · Graph · AI · Configure"]
            undo[("Undo snapshot<br/>rviz_common::Config")]
        end
    end
    server["AutoDiag server"]
    tabs <--> net
    net <-- "REST + NDJSON" --> server
    tabs -- "read state" --> dt
    tabs -- "apply actions" --> dt
    dt -- "save()" --> undo
    undo -- "load()" --> dt

Graph tab

graph_tab.cpp draws GET /api/graph in a QGraphicsScene with the dashboard's layout: nodes in columns by role (only publishes | both | only subscribes, "nobody publishes" placeholders on the left), ordered by two barycenter sweeps so lines cross less. Lines are cubic curves colored by status with a wide hit area; their labels move apart when they would overlap. The view scales down to the dock width (never up), and node text is drawn slightly larger than the panel font so it stays readable at that scale.

Reading RViz state

rvizState() walks the display tree (including nested groups) and collects each display's name, class, enabled flag, status level and up to 40 properties (two levels deep, e.g. Topic/Reliability Policy), plus the Fixed Frame and the TF frames from the frame manager. Properties are found by name without subProp(), which would log "Undefined property" errors for missing ones.

Applying a plan

stateDiagram-v2
    [*] --> Snapshot: Apply checked
    Snapshot --> Apply: root group save() + Fixed Frame
    Apply --> Applied: ✔ action succeeded
    Apply --> Failed: ✖ invalid value or missing display
    Apply --> Pending: property not created yet
    Pending --> Applied: retry every 1 s
    Pending --> Failed: after 30 s
    Applied --> [*]
    Failed --> [*]
  • Add display: DisplayGroup::createDisplay(class_id), then name, topic and enable.
  • Set property: string values are converted to the property's type (bool, number, color as r; g; b, enum text). A value RViz already has counts as success.
  • Pending: some properties (for example point-cloud Axis) only exist once data arrives, so they are retried.
  • Undo: the root display group and Fixed Frame saved before Apply are restored with load().

Asynchronous by design

Every request is non-blocking, so RViz keeps rendering while plans and answers arrive:

Request Timeout
Status, overview, topics, topic inspection, providers, models 5–30 s (overview 30 s, topic inspection 25 s)
AI answer stream 300 s (local CPU models)
RViz plan 300 s

The AI stream is parsed line by line as NDJSON and rendered as Markdown, with [doc-id] citations turned into links.

State and persistence

State Where Lifetime
Server URL, provider, model, topic, "Include the topic", "every 30 s" .rviz config Saved with the RViz config; a saved URL overrides AUTODIAG_SERVER_URL
Access token Field or AUTODIAG_UI_TOKEN Never saved
Conversation history (both AI tabs) Panel memory Session only
Provider / model selection Shared by the AI and Configure tabs Kept in sync both ways