diff --git a/docker-compose.yml b/docker-compose.yml index df96d06..8bf16b0 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,21 +1,21 @@ # ============================================================================= -# RDC Simulation - Docker Compose (GPU-enabled, Wayland, Multi-Service) +# RDC Simulation - Docker Compose (Multi-Service with Proper Ordering) # ============================================================================= -# Runs the complete simulation stack with 3 services: -# 1. gazebo - Gazebo Harmonic simulation -# 2. sitl - ArduPilot SITL (ArduCopter) -# 3. controller - Python flight controller +# Runs 3 services in order: +# 1. gazebo - Gazebo Harmonic simulation (starts first) +# 2. sitl - ArduPilot SITL (waits for Gazebo) +# 3. controller - Python flight controller (waits for SITL) # # Usage: -# # Start all services +# # Start all 3 services # docker compose up # -# # Or start individually +# # Or start specific services # docker compose up gazebo -# docker compose up sitl -# docker compose up controller +# docker compose up gazebo sitl +# docker compose up gazebo sitl controller # -# # Interactive shell +# # Interactive shell (for debugging) # docker compose run --rm simulation bash # # # Stop everything @@ -49,7 +49,7 @@ x-common: &common # GPU - NVIDIA_VISIBLE_DEVICES=all - NVIDIA_DRIVER_CAPABILITIES=all - # Qt platform - Wayland first, then X11 + # Qt platform - Wayland - QT_QPA_PLATFORM=wayland - QT_WAYLAND_DISABLE_WINDOWDECORATION=1 # OpenGL settings @@ -61,17 +61,14 @@ x-common: &common # Mount Wayland and X11 sockets volumes: - # Wayland socket - ${XDG_RUNTIME_DIR:-/run/user/1000}/${WAYLAND_DISPLAY:-wayland-0}:/run/user/1000/wayland-0:rw - # X11 socket (for XWayland fallback) - /tmp/.X11-unix:/tmp/.X11-unix:rw - # GPU device - /dev/dri:/dev/dri:rw - # Network mode for SITL communication (all services share host network) + # Host network for SITL <-> Gazebo communication network_mode: host - # Run as user with access to Wayland socket + # Run as user 1000 user: "1000:1000" stdin_open: true @@ -80,16 +77,7 @@ x-common: &common services: # ========================================================================= - # Interactive Shell (for manual control) - # ========================================================================= - simulation: - <<: *common - container_name: rdc-sim - entrypoint: [ "/home/pilot/docker-entrypoint.sh" ] - command: [ "bash" ] - - # ========================================================================= - # Service 1: Gazebo Simulation + # SERVICE 1: Gazebo Simulation (must start first) # ========================================================================= gazebo: <<: *common @@ -97,16 +85,25 @@ services: entrypoint: [ "/bin/bash", "-c" ] command: - | + echo "==========================================" + echo " SERVICE 1: Starting Gazebo Harmonic" + echo "==========================================" source /opt/ros/jazzy/setup.bash source ~/.bashrc - echo "Starting Gazebo Harmonic..." - echo "Waiting 5 seconds for initialization..." - sleep 5 + export GZ_SIM_SYSTEM_PLUGIN_PATH=/home/pilot/ardupilot_gazebo/build + export GZ_SIM_RESOURCE_PATH=/home/pilot/ardupilot_gazebo/models:/home/pilot/ardupilot_gazebo/worlds:/home/pilot/RDC_Simulation/gazebo/models cd /home/pilot/RDC_Simulation - ./scripts/run_ardupilot_sim.sh runway + echo "Launching Gazebo world: iris_runway" + gz sim -r /home/pilot/ardupilot_gazebo/worlds/iris_runway.sdf + healthcheck: + test: [ "CMD-SHELL", "pgrep -x gz || exit 1" ] + interval: 5s + timeout: 10s + retries: 30 + start_period: 30s # ========================================================================= - # Service 2: ArduPilot SITL + # SERVICE 2: ArduPilot SITL (waits for Gazebo) # ========================================================================= sitl: <<: *common @@ -117,16 +114,30 @@ services: entrypoint: [ "/bin/bash", "-c" ] command: - | + echo "==========================================" + echo " SERVICE 2: Starting ArduPilot SITL" + echo "==========================================" source /opt/ros/jazzy/setup.bash source ~/.bashrc - echo "Waiting 15 seconds for Gazebo to start..." - sleep 15 - echo "Starting ArduPilot SITL..." + source ~/.profile 2>/dev/null || true + + # Wait for Gazebo to be ready (check if port 9002 is listening) + echo "Waiting for Gazebo to be ready..." + for i in {1..60}; do + if nc -z localhost 9002 2>/dev/null; then + echo "Gazebo is ready!" + break + fi + echo "Waiting... ($$i/60)" + sleep 2 + done + + echo "Starting ArduCopter SITL..." cd /home/pilot/ardupilot - sim_vehicle.py -v ArduCopter -f gazebo-iris --model JSON --console --no-mavproxy + sim_vehicle.py -v ArduCopter -f gazebo-iris --model JSON --console --map # ========================================================================= - # Service 3: Flight Controller + # SERVICE 3: Flight Controller (waits for SITL) # ========================================================================= controller: <<: *common @@ -137,22 +148,49 @@ services: entrypoint: [ "/bin/bash", "-c" ] command: - | + echo "==========================================" + echo " SERVICE 3: Starting Flight Controller" + echo "==========================================" source /opt/ros/jazzy/setup.bash source ~/.bashrc source /home/pilot/RDC_Simulation/venv/bin/activate - echo "Waiting 30 seconds for SITL to initialize..." - sleep 30 - echo "Starting flight controller..." + + # Wait for SITL to be ready (check MAVLink port 14550) + echo "Waiting for ArduPilot SITL to be ready..." + for i in {1..90}; do + if nc -z localhost 14550 2>/dev/null; then + echo "SITL is ready!" + break + fi + echo "Waiting... ($$i/90)" + sleep 2 + done + + # Additional wait for SITL to fully initialize + echo "Waiting 10 more seconds for SITL to stabilize..." + sleep 10 + + echo "Starting flight controller with square pattern..." cd /home/pilot/RDC_Simulation python scripts/run_ardupilot.py --pattern square + # ========================================================================= + # Interactive Shell (for debugging) + # ========================================================================= + simulation: + <<: *common + container_name: rdc-sim + profiles: [ "debug" ] + entrypoint: [ "/home/pilot/docker-entrypoint.sh" ] + command: [ "bash" ] + # ========================================================================= # Headless Mode (CI/Server - no display) # ========================================================================= simulation-headless: <<: *common container_name: rdc-sim-headless - user: "1000:1000" + profiles: [ "headless" ] environment: - NVIDIA_VISIBLE_DEVICES=all - NVIDIA_DRIVER_CAPABILITIES=compute,utility @@ -160,22 +198,6 @@ services: - LIBGL_ALWAYS_SOFTWARE=1 - GZ_SIM_SYSTEM_PLUGIN_PATH=/home/pilot/ardupilot_gazebo/build - GZ_SIM_RESOURCE_PATH=/home/pilot/ardupilot_gazebo/models:/home/pilot/ardupilot_gazebo/worlds:/home/pilot/RDC_Simulation/gazebo/models - volumes: [] # No display mounts needed + volumes: [] entrypoint: [ "/home/pilot/docker-entrypoint.sh" ] command: [ "bash" ] - - # ========================================================================= - # All-in-One (runs everything in one container) - # ========================================================================= - all-in-one: - <<: *common - container_name: rdc-all - entrypoint: [ "/bin/bash", "-c" ] - command: - - | - source /opt/ros/jazzy/setup.bash - source ~/.bashrc - source /home/pilot/RDC_Simulation/venv/bin/activate - cd /home/pilot/RDC_Simulation - echo "Starting all-in-one simulation..." - ./scripts/run_ardupilot_controller.sh