#!/usr/bin/env bash # One blocking foreground session: boot to flight, then measure angular rate with # the per-frame probe instead of host polling. # # Everything (Xvfb, openbox, xenia) is a plain child of THIS script. Anything # `setsid`'d is reaped at the agent's turn boundary — see the session-lifetime # note in launch_mission.sh — so the whole run has to fit in one call. # # Usage: frame_session.sh [stage] [hold_s] [repeats] set -u STAGE="${1:-10}"; HOLD="${2:-3.0}"; REPS="${3:-2}" export HOME=/sylph-home/re DISPLAY="${DISPLAY:-:99}" SDL_AUDIODRIVER=dummy export XENIA_PAD_FILE=/tmp/xenia_pad.txt export XENIA_FRAME_PROBE=/tmp/xenia_frame_probe.txt HERE="$(cd "$(dirname "$0")" && pwd)" OUT="$HOME/frameprobe"; mkdir -p "$OUT" LOG="$OUT/frame-stage$STAGE.log" say() { echo "[$(date +%H:%M:%S)] $*"; } ensure_display() { if ! xdpyinfo -display "$DISPLAY" >/dev/null 2>&1; then rm -f "/tmp/.X${DISPLAY#:}-lock" 2>/dev/null || true nohup bash -c 'Xvfb "$0" -screen 0 1280x720x24 -ac -nolisten tcp \ +extension GLX +extension RANDR >/tmp/xvfb${DISPLAY#:}.log 2>&1 echo "$(date +%T) XVFB EXIT $? (128+N means signal N)" >>/tmp/xvfb-exit.log' \ "$DISPLAY" /dev/null 2>&1 & for _ in $(seq 1 50); do xdpyinfo -display "$DISPLAY" >/dev/null 2>&1 && break; sleep 0.2; done nohup env DISPLAY="$DISPLAY" HOME=/sylph-home openbox /tmp/openbox${DISPLAY#:}.log 2>&1 & sleep 1 fi xdpyinfo -display "$DISPLAY" >/dev/null 2>&1 || { say "DISPLAY UNAVAILABLE"; exit 1; } } ensure_display # A stale control file would make the probe log the PREVIOUS run's addresses from # the first frame, which land in whatever occupies them now. rm -f "$XENIA_FRAME_PROBE" # REUSE=1 drives a Canary that is already up (it must have been launched with the # same --frame_probe_log). Booting to the title costs minutes under lavapipe and # a run that only failed to navigate should not pay for it again. if [ "${REUSE:-0}" = 1 ] && pgrep -x xenia_canary >/dev/null; then say "re-using the running emulator; navigating to stage $STAGE" "$HERE/nav_to_flight.sh" "$STAGE" 300 || { say "navigation failed ($?)"; exit 2; } else rm -f "$LOG" say "booting to flight on stage $STAGE with the per-frame probe armed" CANARY_EXTRA="--frame_probe_log=$LOG --frame_probe=$XENIA_FRAME_PROBE" \ "$HERE/fly_stage.sh" "$STAGE" 300 || { say "boot failed ($?)"; exit 2; } fi say "arming the probe on the player craft and driving the bursts" python3 "$HERE/frame_burst.py" "$OUT/events-stage$STAGE.csv" "$HOLD" "$REPS" rc=$? # Stop sampling before the emulator is torn down, so the log ends cleanly. rm -f "$XENIA_FRAME_PROBE" say "frame log: $LOG ($(wc -l < "$LOG" 2>/dev/null || echo 0) lines)" exit $rc