diff --git a/BuildInstructions.md b/BuildInstructions.md
index e332d05..7a0d6db 100644
--- a/BuildInstructions.md
+++ b/BuildInstructions.md
@@ -27,52 +27,167 @@ ros2 launch waybionic_bringup ground_station.launch.py
## macOS (Apple Silicon)
-The workspace runs natively through RoboStack. Docker and XQuartz are not required.
-Intel macOS is not currently verified.
+The workspace runs natively through RoboStack. Docker and XQuartz are not
+required. Intel macOS is not verified.
-### Prerequisites
+### First-time setup
-Install the Xcode command-line tools, Git, and Miniforge:
+1. Install the prerequisites:
+
+ ```bash
+ xcode-select --install
+ brew install git
+ brew install --cask miniforge
+ ```
+
+ If Homebrew is missing, install it from [brew.sh](https://brew.sh/) first.
+ If Xcode reports that its tools are already installed, continue.
+
+2. Close Terminal, open a new Terminal window, and verify Miniforge:
+
+ ```bash
+ mamba --version
+ ```
+
+3. Clone the repository:
+
+ ```bash
+ mkdir -p ~/waybionic
+ cd ~/waybionic
+ git clone https://github.com/Waybionic/waybionic_ground_station.git
+ cd waybionic_ground_station
+ ```
+
+ For an existing clone, skip the clone commands and change to that
+ repository's root directory.
+
+4. Create the RoboStack environment and build the workspace:
+
+ ```bash
+ ./scripts/macos.sh setup
+ ```
+
+ Wait for `Setup complete` before continuing.
+
+### Launch
+
+From the repository root, run:
+
+```bash
+./scripts/macos.sh launch
+```
+
+Keep this Terminal window open. Within a few seconds:
+
+- The RViz splash screen is replaced by the main window.
+- `DiagnosticsPanel` displays **WayBionic Engineering Monitor** and
+ **Current State: NORMAL**.
+- Joint State Publisher displays the `base_to_arm` slider.
+
+To stop the application, return to the launch Terminal and press
+Control+C.
+
+Always use `scripts/macos.sh`. It selects the macOS SDK and Cyclone DDS and
+loads the workspace correctly. Do not source `install/setup.bash` from zsh or
+replace the helper with direct `colcon` or `ros2 launch` commands.
+
+### Verify ROS nodes
+
+While the application is running, open a second Terminal, change to the
+repository root, and run:
+
+```bash
+RMW_IMPLEMENTATION=rmw_cyclonedds_cpp ./scripts/macos.sh run ros2 node list
+```
+
+The output must include:
+
+```text
+/joint_state_publisher
+/robot_state_publisher
+/rviz2
+```
+
+### Update or rebuild
+
+After pulling repository changes:
+
+```bash
+git pull
+./scripts/macos.sh setup
+```
+
+To rebuild without updating the environment:
+
+```bash
+./scripts/macos.sh build
+```
+
+### Troubleshooting
+
+Run these commands from the repository root. After applying a fix, use the
+single command in the **Launch** section.
+
+#### `mamba` is not found
+
+Close and reopen Terminal. If `mamba --version` still fails, reinstall
+Miniforge and reopen Terminal again:
```bash
-xcode-select --install
-brew install git
brew install --cask miniforge
```
-Reopen the terminal if `mamba` or `conda` is not immediately available.
+#### Setup cannot solve the environment or reports missing ROS tools
+
+Use this for `Could not solve for environment specs`, `colcon: not found`,
+`xacro: not found`, or a missing Joint State Publisher.
+
+First confirm that `waybionic_robostack` appears in:
-### Setup and launch
+```bash
+mamba env list
+```
-For a new clone, run:
+If it exists, repair and rebuild it:
```bash
-git clone https://github.com/Waybionic/waybionic_ground_station.git && cd waybionic_ground_station && ./scripts/macos.sh setup
+mamba install --yes --name waybionic_robostack --freeze-installed \
+ --channel conda-forge --channel robostack-jazzy \
+ colcon-common-extensions ros-jazzy-xacro \
+ ros-jazzy-joint-state-publisher-gui
+./scripts/macos.sh build
```
-For an existing clone, run `./scripts/macos.sh setup` from the repository root.
-The command creates or updates the `waybionic_robostack` environment and builds
-the workspace.
+If the environment does not exist, rerun the first-time setup command instead.
+
+#### CMake reports a missing OpenGL framework header
-Launch RViz and Joint State Publisher GUI:
+If the error names
+`/System/Library/Frameworks/OpenGL.framework/Headers`, update and rebuild:
```bash
-./scripts/macos.sh launch
+git pull
+./scripts/macos.sh build
```
-Other useful commands:
+#### RViz remains on `Initializing`
+
+Stop the application with Control+C, remove any Fast DDS
+override, and use the launch command above:
```bash
-./scripts/macos.sh build # rebuild the workspace
-./scripts/macos.sh run ros2 topic list # run any overlaid ROS command
+unset RMW_IMPLEMENTATION
```
-After pulling repository changes, update and rebuild with:
+#### `DiagnosticsPanel` reports `_PyExc_RuntimeError`
+
+Stop the application, clean the plugin's CMake cache, and rebuild it:
```bash
-git pull && ./scripts/macos.sh setup
+./scripts/macos.sh run colcon build \
+ --packages-select waybionic_rviz_plugins \
+ --cmake-clean-cache --symlink-install
```
-If RViz reports a missing workspace package, rerun `./scripts/macos.sh build`.
-Do not source `install/setup.bash` directly from zsh; the helper handles the
-workspace overlay through Bash.
+The panel should display **WayBionic Engineering Monitor** after the next
+launch.
diff --git a/scripts/macos.sh b/scripts/macos.sh
index dd297ac..69ad5a5 100755
--- a/scripts/macos.sh
+++ b/scripts/macos.sh
@@ -67,6 +67,10 @@ select_manager() {
prepare() {
check_host
select_manager
+ if [[ -z "${CONDA_BUILD_SYSROOT:-}" ]]; then
+ CONDA_BUILD_SYSROOT="$(xcrun --show-sdk-path)"
+ export CONDA_BUILD_SYSROOT
+ fi
}
setup_environment() {
@@ -150,7 +154,8 @@ case "$command_name" in
;;
launch)
prepare
- run_workspace ros2 launch waybionic_bringup ground_station.launch.py "$@"
+ run_workspace env RMW_IMPLEMENTATION="${RMW_IMPLEMENTATION:-rmw_cyclonedds_cpp}" \
+ ros2 launch waybionic_bringup ground_station.launch.py "$@"
;;
run)
[[ $# -gt 0 ]] || fail "run requires a command"
diff --git a/waybionic_rviz_plugins/CMakeLists.txt b/waybionic_rviz_plugins/CMakeLists.txt
index 2d8ec7f..09030aa 100644
--- a/waybionic_rviz_plugins/CMakeLists.txt
+++ b/waybionic_rviz_plugins/CMakeLists.txt
@@ -41,6 +41,12 @@ target_include_directories(${PROJECT_NAME} PUBLIC
target_link_libraries(${PROJECT_NAME} Qt5::Widgets)
ament_target_dependencies(${PROJECT_NAME} ${THIS_PACKAGE_INCLUDE_DEPENDS})
+if(APPLE)
+ # RoboStack exports optional Python type-support dylibs through RViz targets.
+ # Do not retain those unused dylibs in this C++-only plugin.
+ target_link_options(${PROJECT_NAME} PRIVATE "LINKER:-dead_strip_dylibs")
+endif()
+
pluginlib_export_plugin_description_file(rviz_common plugin_description.xml)
install(