3dd0d863fa
- Per-signal, per-plot vertical scale state (sigVScale keyed by plotId:signalKey) so the same signal in two plots has fully independent vscale config - Active signal redrawn on top of all series with 2× line width for clear visual identification; badge click toggles selection and opens/closes the embedded vscale toolbar (click same badge again to deselect) - Vscale configurator moved from floating popup to a slim toolbar strip anchored inside the plot card, with an × close button - Trigger dropdown shows one entry per array signal with [0…N-1] label; opening it shows an index-picker dialog to choose the element - Zoom resampling: when server returns no data for a zoomed range, fall back to the local circular buffer instead of returning empty arrays Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
239 lines
9.4 KiB
Bash
Executable File
239 lines
9.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
# run.sh – Build UDPStreamer and launch the test MARTe2 application.
|
||
#
|
||
# Usage:
|
||
# ./run.sh # run MARTe2 app only
|
||
# ./run.sh --webui # also start the WebUI Go client in the background
|
||
# ./run.sh --nativeui # also start the NativeUI ImGui client in the background
|
||
# ./run.sh --qtui # also start the NativeUI Qt client in the background
|
||
# ./run.sh --help # show this message
|
||
#
|
||
# The clients are started with three sources:
|
||
# Streamer @ 127.0.0.1:44500 (scalar signals, PacketTime, 1 kHz)
|
||
# FastStreamer @ 127.0.0.1:44501 (packed arrays, FirstSample/LastSample, 5 kHz)
|
||
# FullArrStreamer @ 127.0.0.1:44502 (packed arrays, FullArray, 5 kHz)
|
||
#
|
||
# Prerequisites:
|
||
# - marte_env.sh must be present in the repo root (sets MARTe2_DIR, etc.)
|
||
# - MARTe2 and MARTe2-components must already be built
|
||
#
|
||
# The script resolves all paths relative to the repo root so it can be
|
||
# called from any working directory.
|
||
|
||
set -e
|
||
|
||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
REPO_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
|
||
|
||
# ── Parse arguments ──────────────────────────────────────────────────────────
|
||
START_WEBUI=0
|
||
START_NATIVEUI=0
|
||
START_QTUI=0
|
||
for arg in "$@"; do
|
||
case "$arg" in
|
||
--webui) START_WEBUI=1 ;;
|
||
--nativeui) START_NATIVEUI=1 ;;
|
||
--qtui) START_QTUI=1 ;;
|
||
--help|-h)
|
||
sed -n '2,21p' "$0"
|
||
exit 0
|
||
;;
|
||
esac
|
||
done
|
||
|
||
# ── Load MARTe2 environment ──────────────────────────────────────────────────
|
||
ENV_SCRIPT="${REPO_ROOT}/marte_env.sh"
|
||
if [ ! -f "${ENV_SCRIPT}" ]; then
|
||
echo "ERROR: ${ENV_SCRIPT} not found." >&2
|
||
exit 1
|
||
fi
|
||
# shellcheck source=/dev/null
|
||
source "${ENV_SCRIPT}"
|
||
|
||
if [ -z "${MARTe2_DIR}" ]; then
|
||
echo "ERROR: MARTe2_DIR is not set after sourcing marte_env.sh." >&2
|
||
exit 1
|
||
fi
|
||
|
||
# ── Build components ─────────────────────────────────────────────────────────
|
||
TARGET=x86-linux
|
||
UDPSTREAMER_SRC="${REPO_ROOT}/Source/Components/DataSources/UDPStreamer"
|
||
UDPSTREAMER_LIB="${REPO_ROOT}/Build/${TARGET}/Components/DataSources/UDPStreamer"
|
||
SINEARRAYGAM_SRC="${REPO_ROOT}/Source/Components/GAMs/SineArrayGAM"
|
||
SINEARRAYGAM_LIB="${REPO_ROOT}/Build/${TARGET}/Components/GAMs/SineArrayGAM"
|
||
TIMEARRAYGAM_SRC="${REPO_ROOT}/Source/Components/GAMs/TimeArrayGAM"
|
||
TIMEARRAYGAM_LIB="${REPO_ROOT}/Build/${TARGET}/Components/GAMs/TimeArrayGAM"
|
||
|
||
echo "==> Building UDPStreamer (TARGET=${TARGET})..."
|
||
make -C "${UDPSTREAMER_SRC}" \
|
||
-f Makefile.gcc \
|
||
TARGET="${TARGET}" \
|
||
2>&1 | tail -5
|
||
|
||
echo "==> Building SineArrayGAM (TARGET=${TARGET})..."
|
||
make -C "${SINEARRAYGAM_SRC}" \
|
||
-f Makefile.gcc \
|
||
TARGET="${TARGET}" \
|
||
2>&1 | tail -5
|
||
|
||
echo "==> Building TimeArrayGAM (TARGET=${TARGET})..."
|
||
make -C "${TIMEARRAYGAM_SRC}" \
|
||
-f Makefile.gcc \
|
||
TARGET="${TARGET}" \
|
||
2>&1 | tail -5
|
||
echo "==> Build done."
|
||
|
||
# ── Build WebUI binary (if requested and not already built) ──────────────────
|
||
WEBUI_DIR="${REPO_ROOT}/Client/WebUI"
|
||
WEBUI_BIN="${WEBUI_DIR}/udpstreamer-webui"
|
||
if [ "${START_WEBUI}" -eq 1 ] && [ ! -x "${WEBUI_BIN}" ]; then
|
||
echo "==> Building WebUI..."
|
||
(cd "${WEBUI_DIR}" && go build -o udpstreamer-webui ./...)
|
||
echo "==> WebUI build done."
|
||
fi
|
||
|
||
# ── Build NativeUI (ImGui) binary (if requested and not already built) ───────
|
||
NATIVEUI_DIR="${REPO_ROOT}/Client/NativeUI"
|
||
NATIVEUI_BUILD="${NATIVEUI_DIR}/build"
|
||
NATIVEUI_BIN="${NATIVEUI_BUILD}/daq_viewer"
|
||
if [ "${START_NATIVEUI}" -eq 1 ]; then
|
||
if [ ! -x "${NATIVEUI_BIN}" ]; then
|
||
echo "==> Building NativeUI/ImGui (cmake)..."
|
||
cmake -S "${NATIVEUI_DIR}" -B "${NATIVEUI_BUILD}" -DCMAKE_BUILD_TYPE=Release -Wno-dev
|
||
cmake --build "${NATIVEUI_BUILD}" --parallel "$(nproc)"
|
||
echo "==> NativeUI/ImGui build done."
|
||
else
|
||
# Rebuild if sources are newer than the binary
|
||
if find "${NATIVEUI_DIR}/src" -name '*.cpp' -o -name '*.h' \
|
||
| xargs ls -t 2>/dev/null | head -1 \
|
||
| xargs -I{} test {} -nt "${NATIVEUI_BIN}" 2>/dev/null; then
|
||
echo "==> Sources changed — rebuilding NativeUI/ImGui..."
|
||
cmake --build "${NATIVEUI_BUILD}" --parallel "$(nproc)"
|
||
echo "==> NativeUI/ImGui rebuild done."
|
||
fi
|
||
fi
|
||
fi
|
||
|
||
# ── Build NativeUI-Qt binary (if requested and not already built) ─────────────
|
||
QTUI_DIR="${REPO_ROOT}/Client/NativeUI-Qt"
|
||
QTUI_BUILD="${QTUI_DIR}/build"
|
||
QTUI_BIN="${QTUI_BUILD}/daq_viewer"
|
||
if [ "${START_QTUI}" -eq 1 ]; then
|
||
if [ ! -x "${QTUI_BIN}" ]; then
|
||
echo "==> Building NativeUI/Qt (cmake)..."
|
||
cmake -S "${QTUI_DIR}" -B "${QTUI_BUILD}" -DCMAKE_BUILD_TYPE=Release -Wno-dev
|
||
cmake --build "${QTUI_BUILD}" --parallel "$(nproc)"
|
||
echo "==> NativeUI/Qt build done."
|
||
else
|
||
# Rebuild if sources are newer than the binary
|
||
if find "${QTUI_DIR}/src" "${REPO_ROOT}/Client/NativeUI/src" \
|
||
\( -name '*.cpp' -o -name '*.h' \) \
|
||
| xargs ls -t 2>/dev/null | head -1 \
|
||
| xargs -I{} test {} -nt "${QTUI_BIN}" 2>/dev/null; then
|
||
echo "==> Sources changed — rebuilding NativeUI/Qt..."
|
||
cmake --build "${QTUI_BUILD}" --parallel "$(nproc)"
|
||
echo "==> NativeUI/Qt rebuild done."
|
||
fi
|
||
fi
|
||
fi
|
||
|
||
# ── Set LD_LIBRARY_PATH ───────────────────────────────────────────────────────
|
||
COMP="${MARTe2_Components_DIR}/Build/${TARGET}/Components"
|
||
|
||
export LD_LIBRARY_PATH="\
|
||
${UDPSTREAMER_LIB}:\
|
||
${SINEARRAYGAM_LIB}:\
|
||
${TIMEARRAYGAM_LIB}:\
|
||
${MARTe2_DIR}/Build/${TARGET}/Core:\
|
||
${COMP}/DataSources/LinuxTimer:\
|
||
${COMP}/DataSources/LoggerDataSource:\
|
||
${COMP}/GAMs/IOGAM:\
|
||
${COMP}/GAMs/WaveformGAM:\
|
||
${LD_LIBRARY_PATH}"
|
||
|
||
echo "==> LD_LIBRARY_PATH=${LD_LIBRARY_PATH}"
|
||
|
||
# ── Create class-name symlinks for MARTe2 auto-loader ────────────────────────
|
||
WAVEFORM_DIR="${COMP}/GAMs/WaveformGAM"
|
||
for cls in WaveformSin WaveformChirp WaveformPointsDef; do
|
||
target="${WAVEFORM_DIR}/${cls}.so"
|
||
if [ ! -e "${target}" ]; then
|
||
ln -sf "${WAVEFORM_DIR}/WaveformGAM.so" "${target}"
|
||
fi
|
||
done
|
||
|
||
# ── Optionally start WebUI ────────────────────────────────────────────────────
|
||
WEBUI_PID=""
|
||
if [ "${START_WEBUI}" -eq 1 ]; then
|
||
echo "==> Starting WebUI on http://localhost:8080..."
|
||
"${WEBUI_BIN}" \
|
||
--source "Streamer@127.0.0.1:44500/239.0.0.1:44503" \
|
||
--source "FastStreamer@127.0.0.1:44501" \
|
||
--source "FullArrStreamer@127.0.0.1:44502" \
|
||
--listen :8080 &
|
||
WEBUI_PID=$!
|
||
echo "==> WebUI PID ${WEBUI_PID}"
|
||
fi
|
||
|
||
# ── Optionally start NativeUI (ImGui) ────────────────────────────────────────
|
||
NATIVEUI_PID=""
|
||
if [ "${START_NATIVEUI}" -eq 1 ]; then
|
||
if [ ! -x "${NATIVEUI_BIN}" ]; then
|
||
echo "ERROR: NativeUI/ImGui binary not found at ${NATIVEUI_BIN}" >&2
|
||
exit 1
|
||
fi
|
||
echo "==> Starting NativeUI/ImGui..."
|
||
"${NATIVEUI_BIN}" \
|
||
"Streamer@127.0.0.1:44500" \
|
||
"FastStreamer@127.0.0.1:44501" \
|
||
"FullArrStreamer@127.0.0.1:44502" &
|
||
NATIVEUI_PID=$!
|
||
echo "==> NativeUI/ImGui PID ${NATIVEUI_PID}"
|
||
fi
|
||
|
||
# ── Optionally start NativeUI-Qt ──────────────────────────────────────────────
|
||
QTUI_PID=""
|
||
if [ "${START_QTUI}" -eq 1 ]; then
|
||
if [ ! -x "${QTUI_BIN}" ]; then
|
||
echo "ERROR: NativeUI/Qt binary not found at ${QTUI_BIN}" >&2
|
||
exit 1
|
||
fi
|
||
echo "==> Starting NativeUI/Qt..."
|
||
"${QTUI_BIN}" \
|
||
"Streamer@127.0.0.1:44500" \
|
||
"FastStreamer@127.0.0.1:44501" \
|
||
"FullArrStreamer@127.0.0.1:44502" &
|
||
QTUI_PID=$!
|
||
echo "==> NativeUI/Qt PID ${QTUI_PID}"
|
||
fi
|
||
|
||
# ── Launch MARTe2 application ─────────────────────────────────────────────────
|
||
MARTE_APP="${MARTe2_DIR}/Build/${TARGET}/App/MARTeApp.ex"
|
||
CFG="${SCRIPT_DIR}/TestApp.cfg"
|
||
|
||
if [ ! -x "${MARTE_APP}" ]; then
|
||
echo "ERROR: MARTeApp.ex not found at ${MARTE_APP}" >&2
|
||
exit 1
|
||
fi
|
||
|
||
echo "==> Starting MARTe2 application (state=Running)..."
|
||
echo "==> Thread1: scalar signals 1 kHz → port 44500"
|
||
echo "==> Thread2: packed arrays 5 kHz → port 44501 (FirstSample / LastSample)"
|
||
echo "==> Thread3: FullArray arrays 5 kHz → port 44502 (FullArray)"
|
||
echo "==> Press Ctrl+C to stop."
|
||
echo ""
|
||
|
||
cleanup() {
|
||
echo ""
|
||
echo "==> Stopping..."
|
||
[ -n "${WEBUI_PID}" ] && kill -0 "${WEBUI_PID}" 2>/dev/null && kill "${WEBUI_PID}"
|
||
[ -n "${NATIVEUI_PID}" ] && kill -0 "${NATIVEUI_PID}" 2>/dev/null && kill "${NATIVEUI_PID}"
|
||
[ -n "${QTUI_PID}" ] && kill -0 "${QTUI_PID}" 2>/dev/null && kill "${QTUI_PID}"
|
||
}
|
||
trap cleanup EXIT INT TERM
|
||
|
||
"${MARTE_APP}" \
|
||
-l RealTimeLoader \
|
||
-f "${CFG}" \
|
||
-s Running
|