236 lines
7.4 KiB
Bash
Executable File
236 lines
7.4 KiB
Bash
Executable File
#!/bin/bash
|
|
# =============================================================================
|
|
# Record Gazebo Simulation to Video
|
|
# =============================================================================
|
|
# Records the Gazebo simulation window to a video file.
|
|
#
|
|
# Usage:
|
|
# ./scripts/record_simulation.sh # Default: record for 60s
|
|
# ./scripts/record_simulation.sh --duration 120 # Record for 120 seconds
|
|
# ./scripts/record_simulation.sh --output my_video # Custom output name
|
|
# ./scripts/record_simulation.sh --method gazebo # Use Gazebo's recorder
|
|
#
|
|
# Prerequisites:
|
|
# - Gazebo must be running
|
|
# - For ffmpeg method: sudo apt install ffmpeg
|
|
# =============================================================================
|
|
|
|
set -e
|
|
|
|
# Default values
|
|
DURATION=60
|
|
OUTPUT_NAME="drone_simulation_$(date +%Y%m%d_%H%M%S)"
|
|
OUTPUT_DIR="./recordings"
|
|
METHOD="ffmpeg" # ffmpeg or gazebo
|
|
FPS=30
|
|
QUALITY="medium" # low, medium, high
|
|
|
|
# Parse arguments
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
-d|--duration)
|
|
DURATION="$2"
|
|
shift 2
|
|
;;
|
|
-o|--output)
|
|
OUTPUT_NAME="$2"
|
|
shift 2
|
|
;;
|
|
--dir)
|
|
OUTPUT_DIR="$2"
|
|
shift 2
|
|
;;
|
|
-m|--method)
|
|
METHOD="$2"
|
|
shift 2
|
|
;;
|
|
--fps)
|
|
FPS="$2"
|
|
shift 2
|
|
;;
|
|
-q|--quality)
|
|
QUALITY="$2"
|
|
shift 2
|
|
;;
|
|
-h|--help)
|
|
echo "Usage: $0 [OPTIONS]"
|
|
echo ""
|
|
echo "Options:"
|
|
echo " -d, --duration SEC Recording duration in seconds (default: 60)"
|
|
echo " -o, --output NAME Output filename without extension"
|
|
echo " --dir PATH Output directory (default: ./recordings)"
|
|
echo " -m, --method METHOD Recording method: ffmpeg or gazebo"
|
|
echo " --fps FPS Frames per second (default: 30)"
|
|
echo " -q, --quality QUAL Quality: low, medium, high (default: medium)"
|
|
echo " -h, --help Show this help"
|
|
exit 0
|
|
;;
|
|
*)
|
|
echo "Unknown option: $1"
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# Create output directory
|
|
mkdir -p "$OUTPUT_DIR"
|
|
|
|
# Quality presets
|
|
case $QUALITY in
|
|
low)
|
|
CRF=28
|
|
PRESET="faster"
|
|
;;
|
|
medium)
|
|
CRF=23
|
|
PRESET="medium"
|
|
;;
|
|
high)
|
|
CRF=18
|
|
PRESET="slow"
|
|
;;
|
|
esac
|
|
|
|
echo "=============================================="
|
|
echo " Gazebo Simulation Recorder"
|
|
echo "=============================================="
|
|
echo " Duration: ${DURATION}s"
|
|
echo " Output: ${OUTPUT_DIR}/${OUTPUT_NAME}.mp4"
|
|
echo " Method: $METHOD"
|
|
echo " FPS: $FPS"
|
|
echo " Quality: $QUALITY"
|
|
echo "=============================================="
|
|
echo ""
|
|
|
|
if [ "$METHOD" = "gazebo" ]; then
|
|
# ==========================================================================
|
|
# METHOD 1: Gazebo's built-in video recording
|
|
# ==========================================================================
|
|
# Gazebo Harmonic can record video via the GUI or command line
|
|
|
|
OUTPUT_FILE="${OUTPUT_DIR}/${OUTPUT_NAME}.mp4"
|
|
|
|
echo "[INFO] Using Gazebo's built-in recorder..."
|
|
echo "[INFO] In Gazebo GUI:"
|
|
echo " 1. Click the hamburger menu (☰) in top-left"
|
|
echo " 2. Select 'Video Recorder'"
|
|
echo " 3. Click 'Record' to start, 'Stop' to stop"
|
|
echo " 4. Video saves to ~/.gz/sim/recordings/"
|
|
echo ""
|
|
echo "[INFO] Or use gz service to record programmatically..."
|
|
|
|
# Check if Gazebo is running
|
|
if ! pgrep -x "gz" > /dev/null && ! pgrep -x "ruby" > /dev/null; then
|
|
echo "[ERROR] Gazebo doesn't appear to be running"
|
|
echo "[TIP] Start Gazebo first: ./scripts/run_ardupilot_sim.sh runway"
|
|
exit 1
|
|
fi
|
|
|
|
# Start recording via gz service (if available)
|
|
echo "[INFO] Sending record command to Gazebo..."
|
|
gz service -s /gui/record_video --reqtype gz.msgs.VideoRecord --reptype gz.msgs.Boolean \
|
|
--timeout 5000 --req "start: true, format: \"mp4\", save_filename: \"${OUTPUT_FILE}\"" 2>/dev/null || {
|
|
echo "[WARN] Could not start recording via service"
|
|
echo "[TIP] Use the Gazebo GUI to record manually"
|
|
}
|
|
|
|
echo "[INFO] Recording for ${DURATION} seconds..."
|
|
sleep "$DURATION"
|
|
|
|
# Stop recording
|
|
gz service -s /gui/record_video --reqtype gz.msgs.VideoRecord --reptype gz.msgs.Boolean \
|
|
--timeout 5000 --req "start: false" 2>/dev/null || true
|
|
|
|
echo "[OK] Recording stopped"
|
|
echo "[INFO] Check ~/.gz/sim/recordings/ for the video"
|
|
|
|
else
|
|
# ==========================================================================
|
|
# METHOD 2: FFmpeg screen recording
|
|
# ==========================================================================
|
|
# Records the Gazebo window using ffmpeg
|
|
|
|
OUTPUT_FILE="${OUTPUT_DIR}/${OUTPUT_NAME}.mp4"
|
|
|
|
# Check for ffmpeg
|
|
if ! command -v ffmpeg &> /dev/null; then
|
|
echo "[ERROR] ffmpeg not found"
|
|
echo "[TIP] Install: sudo apt install ffmpeg"
|
|
exit 1
|
|
fi
|
|
|
|
# Find the Gazebo window
|
|
echo "[INFO] Looking for Gazebo window..."
|
|
|
|
# Try to find the window ID
|
|
WINDOW_ID=""
|
|
|
|
# Try xdotool first
|
|
if command -v xdotool &> /dev/null; then
|
|
WINDOW_ID=$(xdotool search --name "Gazebo" 2>/dev/null | head -1) || true
|
|
fi
|
|
|
|
# Fallback to wmctrl
|
|
if [ -z "$WINDOW_ID" ] && command -v wmctrl &> /dev/null; then
|
|
WINDOW_ID=$(wmctrl -l | grep -i "gazebo" | awk '{print $1}' | head -1) || true
|
|
fi
|
|
|
|
if [ -n "$WINDOW_ID" ]; then
|
|
# Get window geometry
|
|
if command -v xdotool &> /dev/null; then
|
|
eval $(xdotool getwindowgeometry --shell "$WINDOW_ID" 2>/dev/null) || true
|
|
fi
|
|
|
|
if [ -n "$WIDTH" ] && [ -n "$HEIGHT" ] && [ -n "$X" ] && [ -n "$Y" ]; then
|
|
echo "[INFO] Found Gazebo window: ${WIDTH}x${HEIGHT} at +${X}+${Y}"
|
|
GRAB_REGION="-video_size ${WIDTH}x${HEIGHT} -grab_x $X -grab_y $Y"
|
|
else
|
|
echo "[WARN] Could not get window geometry, recording full screen"
|
|
GRAB_REGION=""
|
|
fi
|
|
else
|
|
echo "[WARN] Could not find Gazebo window, recording full screen"
|
|
GRAB_REGION=""
|
|
fi
|
|
|
|
echo "[INFO] Starting recording..."
|
|
echo "[INFO] Press Ctrl+C to stop early"
|
|
echo ""
|
|
|
|
# Record using ffmpeg
|
|
# Using x11grab to capture the screen
|
|
ffmpeg -y \
|
|
-f x11grab \
|
|
-framerate "$FPS" \
|
|
$GRAB_REGION \
|
|
-i "${DISPLAY:-:0}" \
|
|
-t "$DURATION" \
|
|
-c:v libx264 \
|
|
-preset "$PRESET" \
|
|
-crf "$CRF" \
|
|
-pix_fmt yuv420p \
|
|
"$OUTPUT_FILE" \
|
|
2>&1 | while IFS= read -r line; do
|
|
# Show progress
|
|
if [[ "$line" =~ time=([0-9:\.]+) ]]; then
|
|
echo -ne "\r[Recording] Time: ${BASH_REMATCH[1]} / ${DURATION}s"
|
|
fi
|
|
done
|
|
|
|
echo ""
|
|
echo ""
|
|
echo "[OK] Recording complete!"
|
|
echo "[INFO] Output: $OUTPUT_FILE"
|
|
|
|
# Get file info
|
|
if [ -f "$OUTPUT_FILE" ]; then
|
|
FILE_SIZE=$(du -h "$OUTPUT_FILE" | cut -f1)
|
|
echo "[INFO] Size: $FILE_SIZE"
|
|
fi
|
|
fi
|
|
|
|
echo ""
|
|
echo "=============================================="
|
|
echo " Recording Complete"
|
|
echo "=============================================="
|