Skip to content

Commit e231a5f

Browse files
committed
fix(turtlebot3): resolve port conflict between CPU and NVIDIA profiles
- Add cpu/nvidia profiles to prevent simultaneous service startup - Add stop-demo.sh script for clean shutdown with --volumes/--images options - Add --update flag to pull latest images before running - Add --attached flag for foreground mode (daemon mode is now default) - Update README with daemon mode instructions and new scripts - Add instructions for viewing logs and interacting with ROS 2 in containers Fixes port 8080 conflict when running with --nvidia flag where both turtlebot3-demo and turtlebot3-demo-nvidia services tried to bind to the same port. Now --profile cpu (default) or --profile nvidia must be explicitly specified, ensuring mutual exclusivity. Changes: - docker-compose.yml: Add profiles=['cpu'] to default service - run-demo.sh: Default to --profile cpu, add daemon mode with -d flag - stop-demo.sh: New script for stopping containers with cleanup options - README.md: Update Quick Start, add daemon mode docs, add stop script
1 parent f49df15 commit e231a5f

4 files changed

Lines changed: 178 additions & 17 deletions

File tree

demos/turtlebot3_integration/README.md

Lines changed: 49 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -38,29 +38,45 @@ That's it! The script will:
3838

3939
1. Build the Docker images (first run takes ~5-10 min, downloads ~4GB)
4040
2. Setup X11 forwarding for Gazebo GUI
41-
3. Launch TurtleBot3 simulation + Nav2 + ros2_medkit gateway
41+
3. Launch TurtleBot3 simulation + Nav2 + ros2_medkit gateway in **daemon mode** (background)
4242
4. Launch sovd_web_ui at <http://localhost:3000>
4343

44-
**Note:** By default, the demo runs with **Gazebo GUI** for visualization. Requires X11 display.
44+
**Note:** By default, the demo runs in **daemon mode** with **Gazebo GUI** enabled. This allows you to interact with ROS 2 while the demo is running.
4545

46-
### Running Headless (Server Only)
47-
48-
For CI/CD or remote servers without display:
46+
### Available Options
4947

5048
```bash
51-
HEADLESS=true docker compose up
52-
# or:
53-
./run-demo.sh --headless
49+
./run-demo.sh # Daemon mode with GUI (default)
50+
./run-demo.sh --attached # Foreground mode with live logs
51+
./run-demo.sh --headless # Daemon mode without GUI (headless)
52+
./run-demo.sh --nvidia # Use NVIDIA GPU acceleration
53+
./run-demo.sh --update # Pull latest images before running
54+
./run-demo.sh --no-cache # Rebuild without cache
5455
```
5556

56-
### Running with GUI (Default)
57+
### Viewing Logs and Interacting with ROS 2
5758

58-
With Gazebo visualization:
59+
Since the demo runs in daemon mode by default, you can:
5960

6061
```bash
61-
docker compose up
62-
# or:
63-
./run-demo.sh
62+
# View live logs
63+
docker compose --profile cpu logs -f
64+
65+
# Enter the container to run ROS 2 commands
66+
docker exec -it turtlebot3_medkit_demo bash
67+
68+
# Inside the container:
69+
ros2 node list
70+
ros2 topic list
71+
ros2 topic echo /odom
72+
```
73+
74+
### Stopping the Demo
75+
76+
```bash
77+
./stop-demo.sh # Stop containers
78+
./stop-demo.sh --volumes # Stop and remove volumes
79+
./stop-demo.sh --images # Stop and remove images
6480
```
6581

6682
### 2. Access the Web UI
@@ -85,7 +101,15 @@ For hardware-accelerated Gazebo rendering with NVIDIA GPU:
85101
You can also use Docker Compose directly:
86102

87103
```bash
88-
docker compose --profile nvidia up --build
104+
# CPU version (default profile)
105+
docker compose --profile cpu up -d
106+
107+
# NVIDIA version
108+
docker compose --profile nvidia up -d
109+
110+
# View logs
111+
docker compose --profile cpu logs -f
112+
docker compose --profile nvidia logs -f
89113
```
90114

91115
## Controlling the Robot
@@ -118,14 +142,23 @@ curl -X PUT http://localhost:8080/api/v1/apps/turtlebot3-node/data/cmd_vel \
118142

119143
### Via ROS2 CLI (inside container)
120144

145+
First, enter the running container:
146+
121147
```bash
148+
# Enter the container
149+
docker exec -it turtlebot3_medkit_demo bash
150+
151+
# Inside the container:
122152
# Send navigation goal
123153
ros2 action send_goal /navigate_to_pose nav2_msgs/action/NavigateToPose \
124154
"{pose: {header: {frame_id: 'map'}, pose: {position: {x: 2.0, y: 0.5, z: 0.0}, orientation: {w: 1.0}}}}"
125155

126156
# Manual teleop
127157
ros2 topic pub /cmd_vel geometry_msgs/msg/Twist \
128158
"{linear: {x: 0.2}, angular: {z: 0.0}}" --once
159+
160+
# Exit container
161+
exit
129162
```
130163

131164
## REST API Endpoints
@@ -390,6 +423,7 @@ demos/turtlebot3_integration/
390423
├── Dockerfile # ROS 2 Jazzy + TurtleBot3 + Nav2 + ros2_medkit
391424
├── docker-compose.yml # Docker Compose (CPU & GPU via profiles)
392425
├── run-demo.sh # One-click demo launcher
426+
├── stop-demo.sh # Stop and cleanup demo
393427
├── send-nav-goal.sh # Send navigation goal via SOVD API
394428
├── check-entities.sh # Explore SOVD entity hierarchy
395429
├── check-faults.sh # View active faults
@@ -412,6 +446,7 @@ demos/turtlebot3_integration/
412446
| Script | Description |
413447
|--------|-------------|
414448
| `run-demo.sh` | Start the full demo (Docker) |
449+
| `stop-demo.sh` | Stop containers and cleanup |
415450
| `send-nav-goal.sh [x] [y] [yaw]` | Send navigation goal via SOVD API |
416451
| `check-entities.sh` | Explore SOVD entity hierarchy |
417452
| `check-faults.sh` | View active faults from gateway |

demos/turtlebot3_integration/docker-compose.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
services:
22
# CPU-only version (default)
3+
# Use with: docker compose --profile cpu up
34
turtlebot3-demo:
5+
profiles: ["cpu"]
46
build:
57
context: .
68
dockerfile: Dockerfile

demos/turtlebot3_integration/run-demo.sh

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ trap cleanup EXIT
4141
COMPOSE_ARGS=""
4242
BUILD_ARGS=""
4343
HEADLESS_MODE="false"
44+
UPDATE_IMAGES="false"
45+
DETACH_MODE="true"
4446

4547
usage() {
4648
echo "Usage: $0 [OPTIONS]"
@@ -49,13 +51,17 @@ usage() {
4951
echo " --nvidia Use NVIDIA GPU acceleration"
5052
echo " --no-cache Build Docker images without cache"
5153
echo " --headless Run without Gazebo GUI (default: GUI enabled)"
54+
echo " --update Pull latest images before running"
55+
echo " --attached Run in foreground (default: daemon mode)"
5256
echo " -h, --help Show this help message"
5357
echo ""
5458
echo "Examples:"
55-
echo " $0 # With Gazebo GUI (default)"
59+
echo " $0 # Daemon mode (default)"
60+
echo " $0 --attached # Foreground with logs"
5661
echo " $0 --headless # Headless mode (no GUI)"
5762
echo " $0 --nvidia # GPU acceleration + GUI"
5863
echo " $0 --no-cache # Rebuild without cache"
64+
echo " $0 --update # Pull and run latest version"
5965
echo ""
6066
echo "Environment variables:"
6167
echo " HEADLESS=true|false Control GUI mode (default: false)"
@@ -75,6 +81,14 @@ while [[ $# -gt 0 ]]; do
7581
echo "Running in headless mode (no GUI)"
7682
HEADLESS_MODE="true"
7783
;;
84+
--update)
85+
echo "Will pull latest images"
86+
UPDATE_IMAGES="true"
87+
;;
88+
--attached)
89+
echo "Running in foreground mode"
90+
DETACH_MODE="false"
91+
;;
7892
-h|--help)
7993
usage
8094
exit 0
@@ -90,11 +104,13 @@ done
90104

91105
if [[ -z "$COMPOSE_ARGS" ]]; then
92106
echo "Using CPU-only mode (use --nvidia flag for GPU acceleration)"
107+
COMPOSE_ARGS="--profile cpu"
93108
fi
94109

95110
# Export HEADLESS mode for docker-compose
96111
export HEADLESS=$HEADLESS_MODE
97112
echo "Gazebo mode: $([ "$HEADLESS_MODE" = "true" ] && echo "headless (no GUI)" || echo "GUI enabled")"
113+
echo "Run mode: $([ "$DETACH_MODE" = "true" ] && echo "daemon (background)" || echo "attached (foreground)")"
98114

99115
# Build and run
100116
echo " Building and starting demo..."
@@ -108,12 +124,46 @@ echo "🌐 REST API available at: http://localhost:8080/api/v1/"
108124
echo "🌐 Web UI available at: http://localhost:3000/"
109125
echo ""
110126

127+
# Pull images if --update flag is set
128+
if [[ "$UPDATE_IMAGES" == "true" ]]; then
129+
echo "📥 Pulling latest images..."
130+
if docker compose version &> /dev/null; then
131+
# shellcheck disable=SC2086
132+
docker compose ${COMPOSE_ARGS} pull
133+
else
134+
# shellcheck disable=SC2086
135+
docker-compose ${COMPOSE_ARGS} pull
136+
fi
137+
echo ""
138+
fi
139+
140+
# Set detach flag
141+
DETACH_FLAG=""
142+
if [[ "$DETACH_MODE" == "true" ]]; then
143+
DETACH_FLAG="-d"
144+
fi
145+
111146
if docker compose version &> /dev/null; then
112147
# shellcheck disable=SC2086
113148
docker compose ${COMPOSE_ARGS} build ${BUILD_ARGS} && \
114-
docker compose ${COMPOSE_ARGS} up
149+
docker compose ${COMPOSE_ARGS} up ${DETACH_FLAG}
115150
else
116151
# shellcheck disable=SC2086
117152
docker-compose ${COMPOSE_ARGS} build ${BUILD_ARGS} && \
118-
docker-compose ${COMPOSE_ARGS} up
153+
docker-compose ${COMPOSE_ARGS} up ${DETACH_FLAG}
154+
fi
155+
156+
if [[ "$DETACH_MODE" == "true" ]]; then
157+
echo ""
158+
echo "✅ Demo started in background!"
159+
echo ""
160+
echo "📊 To view logs:"
161+
echo " docker compose --profile cpu logs -f # CPU version"
162+
echo " docker compose --profile nvidia logs -f # NVIDIA version"
163+
echo ""
164+
echo "🔧 To interact with ROS 2:"
165+
echo " docker exec -it turtlebot3_medkit_demo bash # CPU"
166+
echo " docker exec -it turtlebot3_medkit_demo_nvidia bash # NVIDIA"
167+
echo ""
168+
echo "🛑 To stop: ./stop-demo.sh"
119169
fi
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#!/bin/bash
2+
# Stop TurtleBot3 + ros2_medkit Demo
3+
4+
set -eu
5+
6+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
7+
cd "$SCRIPT_DIR"
8+
9+
echo "🛑 Stopping TurtleBot3 + ros2_medkit Demo"
10+
echo "=========================================="
11+
12+
# Check for Docker
13+
if ! command -v docker &> /dev/null; then
14+
echo "Error: Docker is not installed"
15+
exit 1
16+
fi
17+
18+
# Parse arguments
19+
REMOVE_VOLUMES=""
20+
REMOVE_IMAGES=""
21+
22+
usage() {
23+
echo "Usage: $0 [OPTIONS]"
24+
echo ""
25+
echo "Options:"
26+
echo " -v, --volumes Remove named volumes"
27+
echo " --images Remove images"
28+
echo " -h, --help Show this help message"
29+
echo ""
30+
echo "Examples:"
31+
echo " $0 # Stop containers"
32+
echo " $0 --volumes # Stop and remove volumes"
33+
echo " $0 --images # Stop and remove images"
34+
}
35+
36+
while [[ $# -gt 0 ]]; do
37+
case "$1" in
38+
-v|--volumes)
39+
echo "Will remove named volumes"
40+
REMOVE_VOLUMES="-v"
41+
;;
42+
--images)
43+
echo "Will remove images"
44+
REMOVE_IMAGES="--rmi all"
45+
;;
46+
-h|--help)
47+
usage
48+
exit 0
49+
;;
50+
*)
51+
echo "Unknown option: $1"
52+
usage
53+
exit 1
54+
;;
55+
esac
56+
shift
57+
done
58+
59+
# Stop containers
60+
echo "Stopping containers..."
61+
if docker compose version &> /dev/null; then
62+
# shellcheck disable=SC2086
63+
docker compose down ${REMOVE_VOLUMES} ${REMOVE_IMAGES}
64+
else
65+
# shellcheck disable=SC2086
66+
docker-compose down ${REMOVE_VOLUMES} ${REMOVE_IMAGES}
67+
fi
68+
69+
# Cleanup X11
70+
echo "Cleaning up X11 permissions..."
71+
xhost -local:docker 2>/dev/null || true
72+
73+
echo ""
74+
echo "✅ Demo stopped successfully!"

0 commit comments

Comments
 (0)