From 1b24eebaae48b8a786884910d480e8e7d23db4d3 Mon Sep 17 00:00:00 2001 From: Ruffin Date: Wed, 26 Apr 2023 13:01:42 +0200 Subject: [PATCH] Enable Visualizations for Dev Container (#3523) * Add visualizer stage to install demo dependencies * Install foxglove * Install gzweb * Add hack for resolvable mesh URIs located by the aws SDL model files - https://github.com/aws-robotics/aws-robomaker-small-warehouse-world/pull/24 * Revert hack and use fork that fixes issues with deploy.sh - https://github.com/osrf/gzweb/pull/248 * Update target stage to visualizer * Comment out gzclient and rviz for debugging * Add hack for resolvable mesh URIs as migrating the python3 scripts still hasn't resolved the issue * Reorder stages for readability by keeping sequential builder and tester stages adjacent while keeping tester stage the default exported target * fix typo * Install gdb for launching ros launch files using the ROS VS Code extension - https://github.com/ms-iot/vscode-ros/issues/588 * Add vscode tasks file * Add Start Gzweb task * Add Start Foxglove tasks for bridge and studio * Add Start Foxglove compound task using dependsOn * Set default problemMatcher to empty to avoid nagging the user to select one as currently none really support our use case * Source overlay before running foxglove_bridge to ensure nav2 message types are defined by inlining all args into command and sourcing workspace setup * Formatting * Generalize and simplify hack * Generalize gazebo model discovery * Patch gzserver to run headless using xvfb to avoid host/platform specific x11 quirks exposed by vscode automatic x11 forwarding This is needed to provide gazebo a virtual frame buffer as it still need one after all these years. This also avoids the need modifying launch files to call xvfb-run - https://github.com/microsoft/vscode-remote-release/issues/8031 - https://github.com/gazebosim/gazebo-classic/issues/1602 * Set isBackground for start tasks * Add stop tasks * Add restart foxglove task * Switch to shell for commanding pkill to gracefully return 0 when process is not running allowing sequence of dependsOn tasks to run such as for the restart tasks * Add icons to tasks for readability * Add restart gzweb task * Add global start, stop, and restart tasks for all background visualization tasks * Formatting * Hide tasks users need not run manually to avoid cluttering up the run task quick pick * Shorten label for background tasks so they succinctly show from the running task list * Show global start and stop visualizations tasks as they may be too helpful to hide * Revert "Comment out gzclient and rviz for debugging" This reverts commit 0addae2a1ee70c5771055c5dd8fa050af438b896. * Add --ipc=host to runArgs to enable shared memory transport - https://community.rti.com/kb/communicate-between-two-docker-containers-using-rti-connext-dds-and-shared-memory * Add --pid=host to runArgs to simplify discovery - https://community.rti.com/kb/communicate-between-two-docker-containers-using-rti-connext-dds-and-shared-memory * Add to runArgs to simplify debugging - https://code.visualstudio.com/docs/devcontainers/create-dev-container#_use-docker-compose * Add comments * Comment out runArgs unintended side effects or cross talk between containers by default also avoids interfering with vscode's X11 forwarding --- .devcontainer/devcontainer.json | 10 +- .vscode/tasks.json | 174 ++++++++++++++++++++++++++++++++ Dockerfile | 85 +++++++++++++--- 3 files changed, 252 insertions(+), 17 deletions(-) create mode 100644 .vscode/tasks.json diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 7f2a4524a9d..c81677a58ca 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -3,12 +3,16 @@ "build": { "dockerfile": "../Dockerfile", "context": "..", - "target": "dever", + "target": "visualizer", "cacheFrom": "ghcr.io/ros-planning/navigation2:main" }, "runArgs": [ - "--privileged", - "--network=host" + // "--cap-add=SYS_PTRACE", // enable debugging, e.g. gdb + // "--ipc=host", // shared memory transport with host, e.g. rviz GUIs + // "--network=host", // network access to host interfaces, e.g. eth0 + // "--pid=host", // DDS discovery with host, without --network=host + // "--privileged", // device access to host peripherals, e.g. USB + // "--security-opt=seccomp=unconfined", // enable debugging, e.g. gdb ], "workspaceMount": "source=${localWorkspaceFolder},target=/opt/overlay_ws/src/navigation2,type=bind", "workspaceFolder": "/opt/overlay_ws/src/navigation2", diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 00000000000..2f65dac128b --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,174 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "label": "Gzweb", + "icon": { + "id": "debug-start" + }, + "type": "process", + "command": "npm", + "args": [ + "start" + ], + "options": { + "cwd": "/opt/gzweb", + "env": { + "npm_config_port": "9090" + } + }, + "hide": true, + "isBackground": true, + "problemMatcher": [] + }, + { + "label": "Stop Gzweb", + "icon": { + "id": "debug-stop" + }, + "type": "shell", + "command": "pkill -SIGTERM -f 'npm start' || true", + "hide": true, + "problemMatcher": [] + }, + { + "label": "Restart Gzweb", + "icon": { + "id": "debug-restart" + }, + "dependsOn": [ + "Stop Gzweb", + "Gzweb" + ], + "dependsOrder": "sequence", + "problemMatcher": [] + }, + { + "label": "Foxglove Bridge", + "icon": { + "id": "debug-start" + }, + "type": "shell", + "command": "source ./install/setup.bash && ros2 run foxglove_bridge foxglove_bridge", + "options": { + "cwd": "/opt/overlay_ws", + }, + "isBackground": true, + "hide": true, + "problemMatcher": [] + }, + { + "label": "Stop Foxglove Bridge", + "icon": { + "id": "debug-stop" + }, + "type": "shell", + "command": "pkill -SIGTERM -f 'ros2 run foxglove_bridge foxglove_bridge' || true", + "hide": true, + "problemMatcher": [] + }, + { + "label": "Foxglove Studio", + "icon": { + "id": "debug-start" + }, + "type": "process", + "command": "caddy", + "args": [ + "file-server", + "--listen", + ":8080" + ], + "options": { + "cwd": "/opt/foxglove", + }, + "isBackground": true, + "hide": true, + "problemMatcher": [] + }, + { + "label": "Stop Foxglove Studio", + "icon": { + "id": "debug-stop" + }, + "type": "shell", + "command": "pkill -SIGTERM -f 'caddy file-server --listen :8080' || true", + "hide": true, + "problemMatcher": [] + }, + { + "label": "Foxglove", + "icon": { + "id": "debug-start" + }, + "dependsOn": [ + "Foxglove Bridge", + "Foxglove Studio" + ], + "hide": true, + "problemMatcher": [] + }, + { + "label": "Stop Foxglove", + "icon": { + "id": "debug-stop" + }, + "dependsOn": [ + "Stop Foxglove Bridge", + "Stop Foxglove Studio" + ], + "hide": true, + "problemMatcher": [] + }, + { + "label": "Restart Foxglove", + "icon": { + "id": "debug-restart" + }, + "dependsOn": [ + "Stop Foxglove", + "Foxglove" + ], + "dependsOrder": "sequence", + "problemMatcher": [] + }, + { + "label": "Start Visualizations", + "icon": { + "id": "debug-start" + }, + "dependsOn": [ + "Gzweb", + "Foxglove" + ], + // "hide": true, + "problemMatcher": [] + }, + { + "label": "Stop Visualizations", + "icon": { + "id": "debug-stop" + }, + "dependsOn": [ + "Stop Gzweb", + "Stop Foxglove" + ], + // "hide": true, + "problemMatcher": [] + }, + { + "label": "Restart Visualizations", + "icon": { + "id": "debug-restart" + }, + "dependsOn": [ + "Stop Visualizations", + "Start Visualizations" + ], + "dependsOrder": "sequence", + "problemMatcher": [] + } + ] +} diff --git a/Dockerfile b/Dockerfile index ebba9b5ef11..d30b9d75913 100644 --- a/Dockerfile +++ b/Dockerfile @@ -105,20 +105,6 @@ RUN . $UNDERLAY_WS/install/setup.sh && \ --ignore-src \ && rm -rf /var/lib/apt/lists/* -# multi-stage for developing -FROM builder AS dever - -# edit apt for caching -RUN mv /etc/apt/apt.conf.d/docker-clean /etc/apt/ - -# install developer dependencies -RUN apt-get update && \ - apt-get install -y \ - bash-completion - -# source underlay for shell -RUN echo 'source "$UNDERLAY_WS/install/setup.bash"' >> /etc/bash.bashrc - # multi-stage for testing FROM builder AS tester @@ -146,3 +132,74 @@ RUN if [ -n "$RUN_TESTS" ]; then \ colcon test-result \ || ([ -z "$FAIL_ON_TEST_FAILURE" ] || exit 1) \ fi + +# multi-stage for developing +FROM builder AS dever + +# edit apt for caching +RUN mv /etc/apt/apt.conf.d/docker-clean /etc/apt/ + +# install developer dependencies +RUN apt-get update && \ + apt-get install -y \ + bash-completion \ + gdb + +# source underlay for shell +RUN echo 'source "$UNDERLAY_WS/install/setup.bash"' >> /etc/bash.bashrc + +# multi-stage for visualizing +FROM dever AS visualizer + +# install foxglove dependacies +RUN echo "deb https://dl.cloudsmith.io/public/caddy/stable/deb/debian any-version main" > /etc/apt/sources.list.d/caddy-stable.list +RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 65760c51edea2017cea2ca15155b6d79ca56ea34 + +# install demo dependencies +RUN apt-get update && apt-get install -y \ + ros-$ROS_DISTRO-aws-robomaker-small-warehouse-world \ + ros-$ROS_DISTRO-rviz2 \ + ros-$ROS_DISTRO-turtlebot3-simulations + +# install gzweb dependacies +RUN apt-get install -y --no-install-recommends \ + imagemagick \ + libboost-all-dev \ + libgazebo-dev \ + libgts-dev \ + libjansson-dev \ + libtinyxml-dev \ + nodejs \ + npm \ + psmisc \ + xvfb + +# clone gzweb +ENV GZWEB_WS /opt/gzweb +RUN git clone --branch python3 https://github.com/ruffsl/gzweb.git $GZWEB_WS + +# build gzweb +RUN cd $GZWEB_WS && . /usr/share/gazebo/setup.sh && \ + GAZEBO_MODEL_PATH=$GAZEBO_MODEL_PATH:$(find /opt/ros/$ROS_DISTRO/share \ + -mindepth 1 -maxdepth 2 -type d -name "models" | paste -s -d: -) && \ + xvfb-run -s "-screen 0 1280x1024x24" ./deploy.sh -m local && \ + ln -s $GZWEB_WS/http/client/assets http/client/assets/models + +# patch gzsever +RUN GZSERVER=$(which gzserver) && \ + mv $GZSERVER $GZSERVER.orig && \ + echo '#!/bin/bash' > $GZSERVER && \ + echo 'xvfb-run -s "-screen 0 1280x1024x24" gzserver.orig "$@"' >> $GZSERVER && \ + chmod +x $GZSERVER + +# install foxglove dependacies +RUN apt-get install -y --no-install-recommends \ + caddy \ + ros-$ROS_DISTRO-foxglove-bridge + +# copy foxglove +ENV FOXGLOVE_WS /opt/foxglove +COPY --from=ghcr.io/foxglove/studio /src $FOXGLOVE_WS + +# multi-stage for exporting +FROM tester AS exporter