Skip to content

fix(demos): run headless automatically when no display is available (macOS)#61

Open
mfaferek93 wants to merge 2 commits into
mainfrom
fix/demos-macos-headless
Open

fix(demos): run headless automatically when no display is available (macOS)#61
mfaferek93 wants to merge 2 commits into
mainfrom
fix/demos-macos-headless

Conversation

@mfaferek93
Copy link
Copy Markdown

Problem

On macOS (Docker Desktop) the default run-demo.sh launches the Gazebo/RViz GUI client, but the container has no X server (DISPLAY is empty). The GUI process aborts:

[gazebo-2] qt.qpa.xcb: could not connect to display
[gazebo-2] Could not load the Qt platform plugin "xcb" ... no Qt platform plugin could be initialized
[gazebo-2] process has died ... exit code 134
[launch]: process[gazebo-2] was required: shutting down launched system

Because that GUI process is marked required, its death tears down the entire stack (simulation, Nav2, gateway, web UI). The flagship quick-start therefore fails on macOS out of the box, even though the demo's value (REST API + Web UI diagnostics) needs no GUI.

Fix

run-demo.sh now detects a missing display (macOS, or any headless host) and falls back to headless automatically, instead of launching a GUI that cannot open. An explicit --headless / HEADLESS=true still wins, and the Linux-with-display path is unchanged - X11 forwarding now only runs when a GUI will actually be shown.

When it falls back, it prints what is running so the user knows what works and what they can do:

ℹ️  macOS detected with no X display: running HEADLESS.
    Docker Desktop on macOS cannot open the Gazebo 3D window.
    The simulation, Nav2 and ros2_medkit still run normally:
      REST API -> http://localhost:8080/api/v1/
      Web UI   -> http://localhost:3000/
    You can still send nav goals and inject faults via the helper scripts below.

Applied to the GUI-launching demos: turtlebot3_integration/run-demo.sh, turtlebot3_integration/run-demo-debounce.sh, moveit_pick_place/run-demo.sh. The headless-only demos (sensor_diagnostics, multi_ecu_aggregation) were already fine. As a side effect the documented HEADLESS=true environment variable now actually works (it was previously overwritten by the hardcoded default).

READMEs updated to document the macOS behavior.

Verification

  • shellcheck -S warning and bash -n clean on all three scripts.
  • Ran each script under stubbed environments: macOS / no-DISPLAY and headless Linux force headless and print the notice; Linux with DISPLAY keeps the GUI and sets up X11; explicit HEADLESS=true is respected with no auto-notice.

The GUI run mode launched the Gazebo/RViz client even with no X
server, which aborts the whole required launch on macOS Docker
Desktop. Detect a missing DISPLAY and fall back to headless, printing
what still works (REST API, Web UI). Covers turtlebot3 and moveit.
bburda
bburda previously approved these changes May 30, 2026
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes the macOS quick-start failure where run-demo.sh would launch Gazebo/RViz GUI clients against a Docker Desktop container that has no X server, causing the required GUI process to die and tear down the whole stack. The runners now detect a missing DISPLAY and automatically switch to headless, while preserving the existing GUI-on-Linux flow and honoring explicit --headless/HEADLESS=true. As a side effect the previously-broken HEADLESS=true env var now actually works because the hardcoded default no longer overwrites it.

Changes:

  • Add auto-headless fallback (with macOS-specific messaging) to turtlebot3_integration/run-demo.sh, turtlebot3_integration/run-demo-debounce.sh, and moveit_pick_place/run-demo.sh.
  • Gate X11 forwarding (and its cleanup) on the resolved headless mode in the TurtleBot3 runners, so xhost only runs when a GUI is actually going to be shown.
  • Initialize HEADLESS_MODE from ${HEADLESS:-false} so the documented env variable is respected.
  • Update the TurtleBot3 README and root README quick-start to document the macOS auto-headless behavior.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
README.md Note that the TurtleBot3 quick-start auto-falls back to headless on macOS/headless hosts.
demos/turtlebot3_integration/run-demo.sh Initialize HEADLESS_MODE from env, add auto-headless fallback when DISPLAY is empty, and only run/cleanup xhost when GUI mode is active.
demos/turtlebot3_integration/run-demo-debounce.sh Same auto-headless + gated X11 setup/cleanup pattern for the debounce variant.
demos/turtlebot3_integration/README.md Update prerequisites and add a macOS section explaining the auto-headless fallback.
demos/moveit_pick_place/run-demo.sh Initialize HEADLESS_MODE from env and add auto-headless fallback for the MoveIt runner (X11 setup block above remains unchanged).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread README.md
Mirror the turtlebot3 README updates for the MoveIt demo: the runner
now falls back to headless when no display is present, so the docs no
longer tell macOS users to set up X11/XQuartz.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants