pudu_map_gui/start.sh

100 lines
4.0 KiB
Bash
Executable File

#!/usr/bin/env bash
# ─────────────────────────────────────────────────────────────────────────────
# Pudu Map GUI — THE one script.
#
# ./start.sh start it + open the browser
# ./start.sh logs follow the server log
# ./start.sh stop stop it (same as the dashboard's ⏻ Shutdown)
# ./start.sh restart stop + start
# ./start.sh build rebuild the docker image, then start
# ./start.sh fg run attached in this terminal (debugging only)
#
# Everything runs in docker; the host needs only docker + an X server.
# Host paths are mounted VERBATIM so every absolute path behaves the same in
# and out of the container:
# ~/Robotics_workspace stage dirs, map editor, relay, rviz configs
# ~/Downloads Pudu exports
# ~/.ssh (read-only) robot deploys (known_hosts redirected to /tmp)
# X11 + DISPLAY RViz + the native file picker
# --net=host web GUI on :8777, DDS for the local /map, rosbridge
#
# DETACHED BY DEFAULT: the dashboard is a service. Also, `docker run -it` can
# hang forever on a host whose docker attach stream is wedged (seen live on this
# workstation: create/start/stop fine, every attached run hung) — detached
# sidesteps that. Use `fg` only when you need the raw attached output.
# ─────────────────────────────────────────────────────────────────────────────
set -euo pipefail
CMD="${1:-start}"
# not in the docker group in THIS shell? re-run the whole script under sg
docker ps >/dev/null 2>&1 || exec sg docker -c "$0 $CMD"
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
IMG=pudu-map-gui
NAME=pudu-map-gui
PORT=8777
URL="http://127.0.0.1:$PORT"
_stop() {
# the GUI's own viewer processes live INSIDE the container, so removing it
# takes them with it. Robots are never touched by this script.
if docker rm -f "$NAME" >/dev/null 2>&1; then echo "stopped $NAME"
else echo "$NAME was not running"; fi
}
case "$CMD" in
stop) _stop; exit 0 ;;
logs) exec docker logs -f "$NAME" ;;
restart) _stop ;;
esac
if [ "$CMD" = build ] || ! docker image inspect $IMG >/dev/null 2>&1; then
echo "== building $IMG (first run takes a few minutes) =="
docker build -t $IMG "$HERE"
fi
# let the container's root talk to the host X server (RViz / zenity picker)
xhost +local: >/dev/null 2>&1 || true
# a stray host-side instance would hold the port — hand over cleanly
fuser -k "$PORT/tcp" >/dev/null 2>&1 || true
docker rm -f "$NAME" >/dev/null 2>&1 || true
RUN=(docker run --rm --net=host --name "$NAME"
-e DISPLAY="${DISPLAY:-:0}"
-e HOME="$HOME"
-e PUDU_GUI_DIR="$HERE"
-v /tmp/.X11-unix:/tmp/.X11-unix
-v "$HOME/Robotics_workspace:$HOME/Robotics_workspace"
-v "$HOME/Downloads:$HOME/Downloads"
-v "$HOME/.ssh:$HOME/.ssh:ro")
if [ "$CMD" = fg ]; then # attached, for debugging
TT=(-it); [ -t 0 ] || TT=()
exec "${RUN[@]}" "${TT[@]}" $IMG
fi
"${RUN[@]}" -d $IMG >/dev/null
# never claim success blindly — wait until the server actually answers
for _ in $(seq 40); do
if curl -fsS -m 2 -o /dev/null "$URL/" 2>/dev/null; then
[ "${NOBROWSER:-0}" = 1 ] || (xdg-open "$URL" >/dev/null 2>&1 &) || true
cat <<EOT
Pudu Map GUI is up -> $URL
(opened in your browser; if the page looks old, reload with $URL/?v=1)
logs: $0 logs stop: $0 stop restart: $0 restart
or press ⏻ Shutdown in the dashboard header.
EOT
exit 0
fi
docker ps --format '{{.Names}}' | grep -qx "$NAME" || {
echo "container exited during startup — last log lines:" >&2
docker logs "$NAME" 2>&1 | tail -20 >&2 || true
exit 1
}
sleep 1
done
echo "started, but $URL did not answer within 40s — check: $0 logs" >&2
exit 1