#!/usr/bin/env bash # Точка входа контейнера: окружение ROS + прогрев конвейера. set -e source /opt/ros/humble/setup.bash source /opt/flyguard/ros2_ws/install/setup.bash # Профиль транспорта можно снять для сравнения: FLYGUARD_DDS_PROFILE=0 if [ "${FLYGUARD_DDS_PROFILE:-1}" = "0" ]; then unset FASTRTPS_DEFAULT_PROFILES_FILE fi # Контейнер без --ipc host. Docker монтирует ему свою /dev/shm с источником # «shm», а с --ipc host видна хостовая. С --network host Fast DDS считает # контейнер и хост одной машиной и шлёт кадры через /dev/shm, но сегмент # собеседника отсюда не виден — и кадры пропадают молча: от `ros2 bag play` # на хосте узел не получает НИ ОДНОГО (замерено, и с нашим профилем, и без # него). В таком контейнере транспорт переводится на UDP: тогда работают # проигрывание внутри контейнера и второй контейнер из этого же образа. # Проигрыватель на хосте со своими умолчаниями всё равно пойдёт через память, # и для него выход один — запускать контейнер с --ipc host. shm_source=$(awk '$5 == "/dev/shm" { for (i = 7; i <= NF; i++) if ($i == "-") { print $(i + 2); exit } }' \ /proc/self/mountinfo 2>/dev/null || true) if [ -n "${FASTRTPS_DEFAULT_PROFILES_FILE:-}" ] && [ "$shm_source" = "shm" ]; then export FASTRTPS_DEFAULT_PROFILES_FILE=/opt/flyguard/fastdds_udp.xml echo "ВНИМАНИЕ: контейнер запущен без --ipc host — транспорт переключён на UDP." >&2 echo " Проигрывание внутри контейнера работает, но ros2 bag play на хосте" >&2 echo " кадры сюда не доставит: для него запускайте с --ipc host." >&2 fi # Сегмент разделяемой памяти не поместится в /dev/shm размером 64 МБ, который # Docker даёт по умолчанию, и Fast DDS молча свалится обратно на UDP. if [ "${FASTRTPS_DEFAULT_PROFILES_FILE:-}" = "/opt/flyguard/fastdds_large.xml" ]; then shm_mb=$(df -m /dev/shm 2>/dev/null | awk 'NR==2{print $2}') if [ -n "$shm_mb" ] && [ "$shm_mb" -lt 512 ]; then echo "ВНИМАНИЕ: /dev/shm всего ${shm_mb} МБ — запустите с --shm-size=1g," >&2 echo " иначе крупные кадры пойдут через UDP и часть потеряется." >&2 fi fi # Прогрев: первый вызов numpy/scipy тянет за собой загрузку библиотек и # первичное размещение буферов, и без прогрева первый же кадр уехал бы # за бюджет в 100 мс. Здесь это делается на синтетическом кадре до старта ноды. if [ "${FLYGUARD_WARMUP:-1}" = "1" ]; then python3 - <<'PY' || echo "прогрев пропущен (не критично)" import numpy as np from scipy import ndimage from scipy.sparse.csgraph import connected_components from scipy.sparse import coo_matrix a = np.random.rand(128, 1200).astype(np.float32) ndimage.uniform_filter(a, size=(7, 29), mode="nearest") g = coo_matrix((np.ones(3, np.int8), ([0, 1, 2], [1, 2, 0])), shape=(4, 4)) connected_components(g, directed=False) np.linalg.lstsq(np.random.rand(64, 3), np.random.rand(64), rcond=None) print("прогрев выполнен") PY fi exec "$@"