diff --git a/.gitignore b/.gitignore index 05ea5ab..a013aff 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,7 @@ data envs/*.secrets.env +__pycache__/ +*.pyc +*.pyo +*.pyd +*$py.class diff --git a/README.md b/README.md index df11f78..05a72ca 100644 --- a/README.md +++ b/README.md @@ -157,12 +157,13 @@ It’s made up of several Docker images that work together. To install it, run: ```bash -docker pull ghcr.io/haru-project/strawberry-ros-azure-kinect:latest -docker pull ghcr.io/haru-project/strawberry-ros-skeletons:latest -docker pull ghcr.io/haru-project/strawberry-ros-faces-module:latest +docker pull ghcr.io/haru-project/strawberry-ros-azure-kinect:feature-topic-normalize +docker pull ghcr.io/haru-project/strawberry-ros-skeletons:feature-topic-normalize +docker pull ghcr.io/haru-project/strawberry-ros-faces-module:feature-topic-normalize docker pull ghcr.io/haru-project/strawberry-ros-hands:latest +docker pull ghcr.io/haru-project/haru-belief:feature-topic-normalize +docker pull ghcr.io/haru-project/haru-viz:feature-topic-normalize docker pull ghcr.io/haru-project/strawberry-ros-people:latest -docker pull ghcr.io/haru-project/strawberry-ros-visualization:latest docker pull ghcr.io/haru-project/strawberry-resource-monitor:latest docker pull ghcr.io/haru-project/haru-speech:ros2 docker pull ghcr.io/haru-project/haru-llm:feature-eval-test @@ -187,6 +188,24 @@ To quickly validate all compose files, run: bash scripts/validate_compose.sh ``` +### Perception image matrix + +The default perception stack is intended to run as a tested image set rather than a mix of floating branch lines: + +```text +azure-kinect ghcr.io/haru-project/strawberry-ros-azure-kinect:feature-topic-normalize +skeletons ghcr.io/haru-project/strawberry-ros-skeletons:feature-topic-normalize +faces ghcr.io/haru-project/strawberry-ros-faces-module:feature-topic-normalize +haru-belief ghcr.io/haru-project/haru-belief:feature-topic-normalize +haru-viz ghcr.io/haru-project/haru-viz:feature-topic-normalize +hands ghcr.io/haru-project/strawberry-ros-hands:latest +resource-monitor ghcr.io/haru-project/strawberry-resource-monitor:latest +``` + +`hands` and `resource-monitor` still default to `latest` because those images are not currently published on the same branch line. Override any service image with `*_IMAGE=...` in `envs/perception.env` or the shell environment when you need a different tested tag or an immutable digest. + +`haru-belief` and `haru-viz` should publish image-level healthchecks through `ros2-ci` using `healthcheck-nodes`, `healthcheck-topics`, and `healthcheck-services`. The perception compose file relies on those image healthchecks rather than maintaining repo-local overrides. + ### All-in-one compose (single file) If you want to launch all layers from a single compose file, use: @@ -199,6 +218,74 @@ This uses `envs/all.env` for compose-time variables. Optional services still res bash scripts/compose.sh all --profile tts --profile webui up --force-recreate -d ``` +### Isolated perception ROS domain + +This branch runs perception on a separate ROS domain by default. Perception +services use `HARU_PERCEPTION_ROS_DOMAIN_ID` (default `20`) and non-perception +services keep using the existing `ROS_DOMAIN_ID`. + +Start the perception stack with: + +```bash +bash scripts/compose.sh perception up --force-recreate -d +``` + +or the combined stack with: + +```bash +bash scripts/compose.sh all up --force-recreate -d +``` + +The separate `perception-domain-bridge` container is the only ROS bridge between +the perception and robot/application domains. Docker networking is unchanged in +this phase. + +The bridge allowlist is tracked in `config/perception_domain_bridge.yaml`. +It bridges only: + +- `/perception/fusion/persons` +- `/strawberry/people` +- `/tf` +- `/tf_static` +- `/haru_speech/speech_to_text/status_array` from the existing domain back to perception +- `/haru_speech/speech_to_text/result` from the existing domain back to perception + +It does not bridge raw Kinect, image, depth, ffmpeg, zdepth, audio, faces, +skeletons, hands, or debug image topics. + +Validation commands: + +```bash +# Existing robot/application domain should not see raw perception topics. +ROS_DOMAIN_ID=0 ros2 topic list | rg '/perception/sensor/kinect|/perception/proc/(faces|skeletons)|ffmpeg|zdepth|depth_to_rgb|camera_info' + +# Existing domain should see bridged semantic outputs. +ROS_DOMAIN_ID=0 ros2 topic echo --once /perception/fusion/persons +ROS_DOMAIN_ID=0 ros2 topic echo --once /strawberry/people +ROS_DOMAIN_ID=0 ros2 topic echo --once /tf + +# Perception domain should see speech status/results bridged back in. +ROS_DOMAIN_ID=${HARU_PERCEPTION_ROS_DOMAIN_ID:-20} ros2 topic echo --once /haru_speech/speech_to_text/status_array +ROS_DOMAIN_ID=${HARU_PERCEPTION_ROS_DOMAIN_ID:-20} ros2 topic echo --once /haru_speech/speech_to_text/result +``` + +The first command should produce no matches. + +### Perception-domain recorder + +The recorder is isolated to the perception ROS domain in this branch. It records +only topics visible on `HARU_PERCEPTION_ROS_DOMAIN_ID`, which includes raw/internal +perception topics and any speech topics bridged back into perception. + +```bash +HARU_RECORDER_SESSION_ID=trial-001 \ + bash scripts/compose.sh recorder up --force-recreate -d +``` + +Recordings are written under +`data/perception/haru_recorder/recordings/domains/perception/`. The recorder does +not attach to the existing robot/application `ROS_DOMAIN_ID`. + ### Haru Simulator (HS) The Haru Simulator uses a graphical interface, so you need to allow Docker to show windows on your screen. Run the following command in your terminal before starting the simulator: @@ -317,13 +404,13 @@ We recommend starting them **one at a time** so you can confirm each one runs co **Start command**: ```bash - bash scripts/compose.sh perception up azure-kinect skeletons faces hands people visualization --force-recreate -d + bash scripts/compose.sh perception up azure-kinect skeletons faces hands haru-belief haru-viz resource-monitor --force-recreate -d ``` **Expected output**: - - An RViz window appears showing: - - Live camera feed - - Detected skeletons and tracking markers + - Perception, fusion, and monitoring come up on their configured perception tags, while `haru-viz` runs from `ghcr.io/haru-project/haru-viz:develop` + - The `haru-viz` web UI is reachable at `http://127.0.0.1:5173` + - rosbridge stays co-located with `haru-viz` and continues using ports `9090`, `9091`, and `9092` **Related repositories for debug**: [strawberry-ros-people](https://github.com/haru-project/strawberry-ros-people/tree/ros2) diff --git a/apps/docker-compose-all.yaml b/apps/docker-compose-all.yaml index 7c25181..6204646 100644 --- a/apps/docker-compose-all.yaml +++ b/apps/docker-compose-all.yaml @@ -22,21 +22,29 @@ services: file: docker-compose-perception.yaml service: hands - people: + haru-belief: extends: file: docker-compose-perception.yaml - service: people + service: haru-belief - visualization: + haru-viz: extends: file: docker-compose-perception.yaml - service: visualization + service: haru-viz resource-monitor: extends: file: docker-compose-perception.yaml service: resource-monitor + perception-domain-bridge: + extends: + file: docker-compose-perception.yaml + service: perception-domain-bridge + depends_on: + haru-belief: + condition: service_started + # Speech layer audio: extends: diff --git a/apps/docker-compose-llm.yaml b/apps/docker-compose-llm.yaml index e6565e5..0912d02 100644 --- a/apps/docker-compose-llm.yaml +++ b/apps/docker-compose-llm.yaml @@ -14,7 +14,8 @@ services: ] env_file: - ../envs/llm.env - - ../envs/llm.secrets.env + - path: ../envs/llm.secrets.env + required: false environment: - REDIS_HOST=127.0.0.1 - REDIS_PORT=6379 @@ -36,7 +37,8 @@ services: command: ["/bin/bash", "-c", "$PACKAGE_VENV -c 'from haru_llm.dashboard.app import run; run()'"] env_file: - ../envs/llm.env - - ../envs/llm.secrets.env + - path: ../envs/llm.secrets.env + required: false ports: - 8501:8501 depends_on: @@ -67,7 +69,8 @@ services: - "--config=/app/config.yaml" env_file: - ../envs/llm.env - - ../envs/llm.secrets.env + - path: ../envs/llm.secrets.env + required: false ports: - 4050:4000 extra_hosts: @@ -89,7 +92,8 @@ services: image: ghcr.io/open-webui/open-webui:main env_file: - ../envs/llm.env - - ../envs/llm.secrets.env + - path: ../envs/llm.secrets.env + required: false ports: - 8080:8080 volumes: @@ -120,7 +124,8 @@ services: - "--gpu-memory-utilization=0.9" env_file: - ../envs/llm.env - - ../envs/llm.secrets.env + - path: ../envs/llm.secrets.env + required: false ports: - 8000:8000 volumes: diff --git a/apps/docker-compose-perception.yaml b/apps/docker-compose-perception.yaml index eb59e6d..7e71d9d 100644 --- a/apps/docker-compose-perception.yaml +++ b/apps/docker-compose-perception.yaml @@ -16,8 +16,10 @@ x-gpu-reservations: &gpu-reservations x-common-x11: &common-x11 "/tmp/.X11-unix:/tmp/.X11-unix:rw" x-common-docker-xauth: &common-docker-xauth "/tmp/.docker.xauth:/tmp/.docker.xauth" +x-common-root-xauth: &common-root-xauth "${XAUTHORITY:-${HOME}/.Xauthority}:/root/.Xauthority:ro" x-common-dev: &common-dev "/dev:/dev:rw" +x-common-run: &common-run "/run:/run:rw" # Common ROS shutdown behavior x-common-ros: &common-ros @@ -27,146 +29,171 @@ x-common-ros: &common-ros # Centralized network mode — can be overridden with COMPOSE_NETWORK_MODE env var (e.g. bridge) x-network-mode: &network-mode ${COMPOSE_NETWORK_MODE:-host} +x-perception-domain-env: &perception-domain-env + ROS_DOMAIN_ID: ${HARU_PERCEPTION_ROS_DOMAIN_ID:-20} + services: - # Azure Kinect sensor driver - supplies depth + color to downstream modules + # Azure Kinect sensor driver + # Replay-only usage: leave this service stopped and start the consumers with + # `PERCEPTION_USE_SIM_TIME=true`. Replay still requires recorded `/tf` and + # `/tf_static` so belief can reconstruct world/camera transforms. azure-kinect: - image: ghcr.io/haru-project/strawberry-ros-azure-kinect:feature-skeleton-integration + image: ${AZURE_KINECT_IMAGE:-ghcr.io/haru-project/strawberry-ros-azure-kinect:feature-topic-normalize} env_file: - ../envs/perception.env environment: + <<: *perception-domain-env DISPLAY: ${DISPLAY} + XAUTHORITY: /root/.Xauthority + HARU_TOPIC_PREFIX: ${HARU_TOPIC_PREFIX:-} HARU_PARAM_AUTO_PREFIXES: AZURE_KINECT AZURE_KINECT_DEV_AUTOSTART: "true" + AZURE_KINECT_NAMESPACE: ${HARU_TOPIC_PREFIX:-}/perception/sensor/kinect + AZURE_KINECT_TOPIC_PREFIX: ${HARU_TOPIC_PREFIX:-}/perception/sensor/kinect/cam_1 network_mode: *network-mode ipc: host privileged: true restart: unless-stopped volumes: + - *common-x11 + - *common-root-xauth - *common-dev + - *common-run <<: *common-ros - # Faces (InsightFace + fusion node) - faces: - image: ghcr.io/haru-project/strawberry-ros-faces-module:feature-skeleton-integration + # Skeleton pipeline + skeletons: + image: ${SKELETONS_IMAGE:-ghcr.io/haru-project/strawberry-ros-skeletons:feature-topic-normalize} env_file: - ../envs/perception.env environment: - HARU_PARAM_AUTO_PREFIXES: FACES - FACES_DEV_AUTOSTART: "true" + <<: *perception-domain-env + HARU_TOPIC_PREFIX: ${HARU_TOPIC_PREFIX:-} + HARU_PARAM_AUTO_PREFIXES: SKELETONS + SKELETONS_DEV_AUTOSTART: "true" + SKELETONS_USE_SIM_TIME: ${PERCEPTION_USE_SIM_TIME:-false} + SKELETONS_USE_FFMPEG_DECODE_BRIDGE: "false" + SKELETONS_NAMESPACE: ${HARU_TOPIC_PREFIX:-}/perception/proc + SKELETONS_RGB_TOPIC: ${HARU_TOPIC_PREFIX:-}/perception/sensor/kinect/cam_1/rgb + SKELETONS_DEPTH_TOPIC: ${HARU_TOPIC_PREFIX:-}/perception/sensor/kinect/cam_1/depth_to_rgb + SKELETONS_CAMERA_INFO_TOPIC: ${HARU_TOPIC_PREFIX:-}/perception/sensor/kinect/cam_1/camera_info + SKELETONS_OUTPUT_TOPIC_SKELETONS: ${HARU_TOPIC_PREFIX:-}/perception/proc/skeletons network_mode: *network-mode restart: unless-stopped volumes: - - type: bind - source: ../data/perception - target: /ros/strawberry_ros_faces_module + - *common-dev <<: *common-ros deploy: *gpu-reservations - depends_on: - azure-kinect: - condition: service_healthy - # Skeleton (OpenPose + fusion node) - skeletons: - image: ghcr.io/haru-project/strawberry-ros-skeletons:feature-skeleton-integration + # Faces (InsightFace + fusion node) + faces: + image: ${FACES_IMAGE:-ghcr.io/haru-project/strawberry-ros-faces-module:feature-topic-normalize} env_file: - ../envs/perception.env environment: - DISPLAY: ${DISPLAY} # Required by OpenPose even when no display is used - XAUTHORITY: /root/.Xauthority - HARU_PARAM_AUTO_PREFIXES: SKELETONS - SKELETONS_DEV_AUTOSTART: "true" + <<: *perception-domain-env + HARU_TOPIC_PREFIX: ${HARU_TOPIC_PREFIX:-} + HARU_PARAM_AUTO_PREFIXES: FACES + FACES_DEV_AUTOSTART: "true" + FACES_USE_SIM_TIME: ${PERCEPTION_USE_SIM_TIME:-false} + FACES_USE_FFMPEG_DECODE_BRIDGE: "false" + FACES_DATA_ROOT: /ros/strawberry_ros_faces_module + FACES_NAMESPACE: ${HARU_TOPIC_PREFIX:-}/perception/proc + FACES_RGB_TOPIC: ${HARU_TOPIC_PREFIX:-}/perception/sensor/kinect/cam_1/rgb + FACES_CAMERA_INFO_TOPIC: ${HARU_TOPIC_PREFIX:-}/perception/sensor/kinect/cam_1/camera_info network_mode: *network-mode - ipc: host - privileged: true restart: unless-stopped volumes: - - *common-x11 - - ${XAUTHORITY:-$HOME/.Xauthority}:/root/.Xauthority:ro - - *common-dev + - type: bind + source: ../data/perception + target: /ros/strawberry_ros_faces_module <<: *common-ros deploy: *gpu-reservations - depends_on: - azure-kinect: - condition: service_healthy - # Hands module hands: - image: ghcr.io/haru-project/strawberry-ros-hands:latest + image: ${HANDS_IMAGE:-ghcr.io/haru-project/strawberry-ros-hands:latest} env_file: - ../envs/perception.env environment: + <<: *perception-domain-env + DISPLAY: ${DISPLAY} + XAUTHORITY: /root/.Xauthority + HARU_TOPIC_PREFIX: ${HARU_TOPIC_PREFIX:-} HARU_PARAM_AUTO_PREFIXES: HANDS HANDS_DEV_AUTOSTART: "true" + HANDS_NAMESPACE: ${HARU_TOPIC_PREFIX:-}/perception/proc + HANDS_CAMERA_NAME: ${HARU_TOPIC_PREFIX:-}/perception/sensor/kinect/cam_1/rgb + HANDS_IMAGE_TOPIC: ${HARU_TOPIC_PREFIX:-}/perception/sensor/kinect/cam_1/rgb/compressed + HANDS_CAMERA_INFO_TOPIC: ${HARU_TOPIC_PREFIX:-}/perception/sensor/kinect/cam_1/camera_info network_mode: *network-mode restart: unless-stopped volumes: - *common-x11 - - *common-docker-xauth + - *common-root-xauth - *common-dev <<: *common-ros deploy: *gpu-reservations - depends_on: - azure-kinect: - condition: service_healthy - - # People module - people: - image: ghcr.io/haru-project/strawberry-ros-people:feature-skeleton-integration + # Belief authority (default perception fusion output) + haru-belief: + image: ${HARU_BELIEF_IMAGE:-ghcr.io/haru-project/haru-belief:feature-topic-normalize} env_file: - ../envs/perception.env environment: - HARU_PARAM_AUTO_PREFIXES: PEOPLE - PEOPLE_DEV_AUTOSTART: "true" + <<: *perception-domain-env + HARU_TOPIC_PREFIX: ${HARU_TOPIC_PREFIX:-} + HARU_PARAM_AUTO_PREFIXES: HARU_BELIEF + HARU_BELIEF_DEV_AUTOSTART: "true" + HARU_BELIEF_USE_SIM_TIME: ${PERCEPTION_USE_SIM_TIME:-false} + HARU_BELIEF_NAMESPACE: ${HARU_TOPIC_PREFIX:-}/perception/fusion + ROS_HOME: /ros/haru_perception_data network_mode: *network-mode restart: unless-stopped volumes: - - *common-x11 - - *common-docker-xauth + - type: bind + source: ../data/perception + target: /ros/haru_perception_data - *common-dev <<: *common-ros - deploy: *gpu-reservations - depends_on: - azure-kinect: - condition: service_healthy - skeletons: - condition: service_started - - # Visualization nodes (RViz, GUI helpers) - visualization: - image: ghcr.io/haru-project/strawberry-ros-visualization:feature-skeleton-integration + # haru-viz browser UI + rosbridge runtime + haru-viz: + image: ${HARU_VIZ_IMAGE:-ghcr.io/haru-project/haru-viz:feature-topic-normalize} env_file: - ../envs/perception.env environment: - HARU_PARAM_AUTO_PREFIXES: VIZ - NVIDIA_VISIBLE_DEVICES: all - NVIDIA_DRIVER_CAPABILITIES: all - VIZ_DEV_AUTOSTART: "true" + <<: *perception-domain-env + HARU_VIZ_DEV_AUTOSTART: "true" + HARU_VIZ_REPO_ROOT: ${HARU_VIZ_REPO_ROOT:-/workspace/haru-viz} + HARU_VIZ_UI_HOST: ${HARU_VIZ_UI_HOST:-0.0.0.0} + HARU_VIZ_UI_PORT: ${HARU_VIZ_UI_PORT:-5173} + HARU_ROSBRIDGE_PORT: ${HARU_ROSBRIDGE_PORT:-9090} + HARU_ROSBRIDGE_RGB_PORT: ${HARU_ROSBRIDGE_RGB_PORT:-9091} + HARU_ROSBRIDGE_DEPTH_PORT: ${HARU_ROSBRIDGE_DEPTH_PORT:-9092} + HARU_ROSBRIDGE_MAX_MESSAGE_SIZE: ${HARU_ROSBRIDGE_MAX_MESSAGE_SIZE:-8388608} + VITE_ROSBRIDGE_URL: ws://127.0.0.1:${HARU_ROSBRIDGE_PORT:-9090} + VITE_ROSBRIDGE_FORCE_AUTO_CONNECT: "1" + VITE_ROS_DOMAIN_ID: ${HARU_PERCEPTION_ROS_DOMAIN_ID:-20} network_mode: *network-mode restart: unless-stopped + working_dir: /workspace/haru-viz + command: ros2 launch haru_viz haru_viz.launch.py volumes: - - *common-x11 - - ${XAUTHORITY:-$HOME/.Xauthority}:/root/.Xauthority:ro - type: bind - source: ../data/perception/haru_recorder - target: /root/.local/share/haru_recorder + source: ../../haru-viz + target: /workspace/haru-viz - *common-dev <<: *common-ros - deploy: *gpu-reservations depends_on: - azure-kinect: - condition: service_healthy - faces: - condition: service_healthy - skeletons: - condition: service_healthy - hands: - condition: service_healthy - people: - condition: service_healthy + haru-belief: + condition: service_started # Resource monitor (optional; no GPU usage required but kept here for convenience) resource-monitor: - image: ghcr.io/haru-project/strawberry-resource-monitor:latest + image: ${RESOURCE_MONITOR_IMAGE:-ghcr.io/haru-project/strawberry-resource-monitor:latest} + env_file: + - ../envs/perception.env + environment: + <<: *perception-domain-env + HARU_TOPIC_PREFIX: ${HARU_TOPIC_PREFIX:-} network_mode: *network-mode restart: unless-stopped volumes: @@ -175,3 +202,41 @@ services: - *common-dev <<: *common-ros deploy: *gpu-reservations + + perception-domain-bridge: + image: ${PERCEPTION_DOMAIN_BRIDGE_IMAGE:-haru-perception-domain-bridge:local} + build: + context: .. + dockerfile: docker/domain-bridge.Dockerfile + args: + BASE_IMAGE: ${PERCEPTION_DOMAIN_BRIDGE_BASE_IMAGE:-ghcr.io/haru-project/haru-belief:feature-topic-normalize} + env_file: + - ../envs/perception.env + environment: + ROS_DOMAIN_ID: ${ROS_DOMAIN_ID:-0} + HARU_PERCEPTION_ROS_DOMAIN_ID: ${HARU_PERCEPTION_ROS_DOMAIN_ID:-20} + RMW_IMPLEMENTATION: ${RMW_IMPLEMENTATION:-rmw_fastrtps_cpp} + FASTDDS_BUILTIN_TRANSPORTS: ${FASTDDS_BUILTIN_TRANSPORTS:-UDPv4} + command: + [ + "ros2", + "run", + "domain_bridge", + "domain_bridge", + "--from", + "${HARU_PERCEPTION_ROS_DOMAIN_ID:-20}", + "--to", + "${ROS_DOMAIN_ID:-0}", + "/shared/config/perception_domain_bridge.yaml", + ] + network_mode: *network-mode + restart: unless-stopped + volumes: + - type: bind + source: ../config/perception_domain_bridge.yaml + target: /shared/config/perception_domain_bridge.yaml + read_only: true + depends_on: + haru-belief: + condition: service_started + <<: *common-ros diff --git a/apps/docker-compose-reasoner.yaml b/apps/docker-compose-reasoner.yaml index a16753a..92d002d 100644 --- a/apps/docker-compose-reasoner.yaml +++ b/apps/docker-compose-reasoner.yaml @@ -5,7 +5,7 @@ services: extends: file: compose.common.yaml service: common-ros - image: ghcr.io/haru-project/haru-agent-reasoner:feature-web-projector + image: ghcr.io/haru-project/haru-agent-reasoner:feature-topic-normalize command: [ "ros2", @@ -30,7 +30,7 @@ services: extends: file: compose.common.yaml service: common-ros - image: ghcr.io/haru-project/haru-agent-reasoner:feature-web-projector + image: ghcr.io/haru-project/haru-agent-reasoner:feature-topic-normalize command: [ "ros2", @@ -52,7 +52,7 @@ services: extends: file: compose.common.yaml service: common-ros - image: ghcr.io/haru-project/haru-agent-reasoner:feature-web-projector + image: ghcr.io/haru-project/haru-agent-reasoner:feature-topic-normalize command: [ "ros2", @@ -76,7 +76,7 @@ services: extends: file: compose.common.yaml service: common-ros - image: ghcr.io/haru-project/haru-agent-reasoner:feature-web-projector + image: ghcr.io/haru-project/haru-agent-reasoner:feature-topic-normalize command: [ "ros2", @@ -96,7 +96,7 @@ services: extends: file: compose.common.yaml service: common-ros - image: ghcr.io/haru-project/haru-agent-reasoner:feature-web-projector + image: ghcr.io/haru-project/haru-agent-reasoner:feature-topic-normalize command: [ "ros2", diff --git a/apps/docker-compose-recorder.yaml b/apps/docker-compose-recorder.yaml index 18e36d1..c83614c 100644 --- a/apps/docker-compose-recorder.yaml +++ b/apps/docker-compose-recorder.yaml @@ -3,12 +3,30 @@ name: haru-recorder # Centralized network mode — can be overridden with COMPOSE_NETWORK_MODE env var (e.g. bridge) x-network-mode: &network-mode ${COMPOSE_NETWORK_MODE:-host} +x-recorder-command: &recorder-command + - /bin/bash + - -lc + - | + set -euo pipefail + config="$${RECORDER_CONFIG_FILE}" + if [[ -n "$${HARU_RECORDER_SESSION_ID:-}" ]]; then + tmp_config="/tmp/haru_recorder_params.yaml" + cp "$${RECORDER_CONFIG_FILE}" "$${tmp_config}" + sed -i "s|session_id:.*|session_id: \"$${HARU_RECORDER_SESSION_ID}\"|" "$${tmp_config}" + config="$${tmp_config}" + fi + ros2 launch haru_recorder haru_recorder.launch.py config_file:="$${config}" + services: haru-recorder: image: ${HARU_RECORDER_IMAGE:-ghcr.io/haru-project/haru-recorder:latest} network_mode: *network-mode env_file: - ../envs/recorder.env + environment: + ROS_DOMAIN_ID: ${HARU_PERCEPTION_ROS_DOMAIN_ID:-20} + RECORDER_CONFIG_FILE: /shared/configs/recorder-perception-domain.yaml + command: *recorder-command ports: - "${HARU_RECORDER_WEB_UI_PORT:-8088}:${HARU_RECORDER_WEB_UI_PORT:-8088}" volumes: @@ -16,6 +34,7 @@ services: source: ../data/perception/haru_recorder/recordings target: /root/.local/share/haru_recorder - type: bind - source: ../data/perception/haru_recorder/config - target: /shared/configs + source: ../config/recorder-perception-domain.yaml + target: /shared/configs/recorder-perception-domain.yaml + read_only: true restart: unless-stopped diff --git a/apps/docker-compose-simulator.yaml b/apps/docker-compose-simulator.yaml index 554a38f..7355c9f 100644 --- a/apps/docker-compose-simulator.yaml +++ b/apps/docker-compose-simulator.yaml @@ -7,7 +7,18 @@ services: service: common-ros-gpu image: ghcr.io/haru-project/hve-simulator@sha256:fb89b358b9c69ea34fedda4781d42158ef392af2ca96debb12d4344a8b81031d working_dir: /ros2_ws - command: ["/bin/bash", "-c", "export ROS_IP=$(hostname -I | awk '{print $1}') && ros2 launch haru_unity unity_app_launcher_launch.py && tail -f /dev/null"] + command: + - /bin/bash + - -c + - | + export ROS_IP=$(hostname -I | awk '{print $1}') + ros2 run ros_tcp_endpoint default_server_endpoint --ros-args -p ROS_IP:=$$ROS_IP -p ROS_TCP_PORT:=10000 & + for i in {1..50}; do + ss -ltn | grep -q ':10000 ' && break + sleep 0.1 + done + ros2 launch haru_unity unity_app_launcher_launch.py + tail -f /dev/null env_file: ../envs/simulator.env environment: - PULSE_SERVER=${PULSE_SERVER} diff --git a/config/perception_domain_bridge.yaml b/config/perception_domain_bridge.yaml new file mode 100644 index 0000000..ec77040 --- /dev/null +++ b/config/perception_domain_bridge.yaml @@ -0,0 +1,53 @@ +# Explicit allowlist for opt-in isolated perception deployments. +# Domain IDs are supplied by the compose command: +# --from ${HARU_PERCEPTION_ROS_DOMAIN_ID} --to ${ROS_DOMAIN_ID} +name: haru_perception_domain_bridge +from_domain: 0 +to_domain: 0 + +topics: + /perception/fusion/persons: + type: haru_belief_msgs/msg/PersonsState + qos: + reliability: reliable + history: keep_last + depth: 10 + + /strawberry/people: + type: strawberry_ros_msgs/msg/People + qos: + reliability: reliable + history: keep_last + depth: 10 + + /tf: + type: tf2_msgs/msg/TFMessage + qos: + reliability: reliable + durability: volatile + history: keep_last + depth: 100 + + /tf_static: + type: tf2_msgs/msg/TFMessage + qos: + reliability: reliable + durability: transient_local + history: keep_last + depth: 1 + + /haru_speech/speech_to_text/status_array: + type: haru_speech_msgs/msg/SpeechStatusArray + reversed: true + qos: + reliability: reliable + history: keep_last + depth: 10 + + /haru_speech/speech_to_text/result: + type: haru_speech_msgs/msg/SpeechToTextResult + reversed: true + qos: + reliability: reliable + history: keep_last + depth: 10 diff --git a/config/recorder-perception-domain.yaml b/config/recorder-perception-domain.yaml new file mode 100644 index 0000000..3a61fe6 --- /dev/null +++ b/config/recorder-perception-domain.yaml @@ -0,0 +1,37 @@ +haru_recorder: + ros__parameters: + record_all_topics: true + topic_allowlist: [] + topic_denylist: [] + node_allowlist: [] + node_denylist: [] + topic_regex: "" + include_hidden_topics: false + output_dir: /root/.local/share/haru_recorder/domains/perception + session_id: "" + bag_storage_id: "mcap" + bag_compression_format: "zstd" + bag_compression_mode: "file" + max_bag_size_mb: 0 + max_bag_duration_s: 0 + prefer_compressed_images: true + compressed_suffixes: ["/compressed"] + image_record_mode: mp4 + image_video_codec: h264 + image_video_bitrate_mbps: 8.0 + image_video_fps: 30.0 + image_video_out_dir: "${output_dir}/${session_id}/video" + image_video_preset: p4 + record_rosout: true + rosout_log_dir: "${output_dir}/${session_id}/logs" + rosout_format: "jsonl" + upload_enabled: true + s3_bucket: "" + s3_prefix: "haru-recorder/perception/${session_id}" + s3_region: "" + s3_endpoint_url: "" + cloudwatch_enabled: true + cloudwatch_log_group: "haru-recorder" + cloudwatch_stream_prefix: "perception/${session_id}" + delete_after_upload: false + retention_days: 0 diff --git a/docker/domain-bridge.Dockerfile b/docker/domain-bridge.Dockerfile new file mode 100644 index 0000000..08c784f --- /dev/null +++ b/docker/domain-bridge.Dockerfile @@ -0,0 +1,9 @@ +ARG BASE_IMAGE=ghcr.io/haru-project/haru-belief:feature-topic-normalize +FROM ${BASE_IMAGE} + +SHELL ["/bin/bash", "-o", "pipefail", "-c"] +USER root + +RUN apt-get update && \ + apt-get install -y --no-install-recommends "ros-${ROS_DISTRO:-jazzy}-domain-bridge" && \ + rm -rf /var/lib/apt/lists/* diff --git a/envs/all.env b/envs/all.env index 21c06e8..81409f7 100644 --- a/envs/all.env +++ b/envs/all.env @@ -7,9 +7,15 @@ NVIDIA_VISIBLE_DEVICES=all NVIDIA_DRIVER_CAPABILITIES=all # ROS (default domain for most stacks) -ROS_DOMAIN_ID=22 +ROS_DOMAIN_ID=0 +HARU_PERCEPTION_ROS_DOMAIN_ID=20 RMW_IMPLEMENTATION=rmw_fastrtps_cpp -FASTDDS_BUILTIN_TRANSPORTS=DEFAULT # set to UDPv4 if you encounter SHM issues +FASTDDS_BUILTIN_TRANSPORTS=UDPv4 + +# Perception image override +FACES_IMAGE=ghcr.io/haru-project/strawberry-ros-faces-module:feature-topic-normalize +PERCEPTION_DOMAIN_BRIDGE_IMAGE=haru-perception-domain-bridge:local +PERCEPTION_DOMAIN_BRIDGE_BASE_IMAGE=ghcr.io/haru-project/haru-belief:feature-topic-normalize # PYTHON VENV PACKAGE_VENV=/opt/ros/jazzy/workspace/package_venv/bin/python3 diff --git a/envs/perception.env b/envs/perception.env index 063f303..2edee80 100644 --- a/envs/perception.env +++ b/envs/perception.env @@ -5,25 +5,44 @@ NVIDIA_DRIVER_CAPABILITIES=all XAUTH=/tmp/.docker.xauth #LIBGL_ALWAYS_SOFTWARE=1 +# Tested image overrides for the perception stack. +# Leave unset to use the compose defaults. +# AZURE_KINECT_IMAGE=ghcr.io/haru-project/strawberry-ros-azure-kinect:feature-topic-normalize +# SKELETONS_IMAGE=ghcr.io/haru-project/strawberry-ros-skeletons:feature-topic-normalize +FACES_IMAGE=ghcr.io/haru-project/strawberry-ros-faces-module:feature-topic-normalize +# HANDS_IMAGE=ghcr.io/haru-project/strawberry-ros-hands:latest +# HARU_BELIEF_IMAGE=ghcr.io/haru-project/haru-belief:feature-topic-normalize +# HARU_VIZ_IMAGE=ghcr.io/haru-project/haru-viz:feature-topic-normalize +# RESOURCE_MONITOR_IMAGE=ghcr.io/haru-project/strawberry-resource-monitor:latest + # ROS ROS_DOMAIN_ID=0 +HARU_PERCEPTION_ROS_DOMAIN_ID=20 RMW_IMPLEMENTATION=rmw_fastrtps_cpp -FASTDDS_BUILTIN_TRANSPORTS=DEFAULT # set to UDPv4 if you encounter SHM issues +FASTDDS_BUILTIN_TRANSPORTS=UDPv4 +HARU_TOPIC_PREFIX= + +# Isolated perception bridge image. +# Used by the perception and all compose stacks. +PERCEPTION_DOMAIN_BRIDGE_IMAGE=haru-perception-domain-bridge:local +PERCEPTION_DOMAIN_BRIDGE_BASE_IMAGE=ghcr.io/haru-project/haru-belief:feature-topic-normalize # ************ # # AZURE KINECT CAMERA # ************ # -# Depth mode: WFOV_2X2BINNED provides wide field of view (120°x120°) -AZURE_KINECT_DEPTH_MODE=WFOV_2X2BINNED +# Leave depth mode unset so the Azure Kinect driver keeps its sensor/profile default +# from `strawberry_azure_kinect_params.yml` (`NFOV_2X2BINNED` today). +# Uncomment only when you intentionally want to override that default. +# AZURE_KINECT_DEPTH_MODE=WFOV_2X2BINNED # Camera position -AZURE_KINECT_CAMERA_POS_X=-0.3 -AZURE_KINECT_CAMERA_POS_Y=0.0 -AZURE_KINECT_CAMERA_POS_Z=1.3 -AZURE_KINECT_CAMERA_ATT_ROLL=0.0 -AZURE_KINECT_CAMERA_ATT_PITCH=0.0 -AZURE_KINECT_CAMERA_ATT_YAW=0.0 +AZURE_KINECT_POS_X=-0.3 +AZURE_KINECT_POS_Y=0.0 +AZURE_KINECT_POS_Z=1.3 +AZURE_KINECT_ATT_ROLL=0.0 +AZURE_KINECT_ATT_PITCH=0.0 +AZURE_KINECT_ATT_YAW=0.0 # **************** # @@ -42,10 +61,13 @@ TF_CPP_MIN_LOG_LEVEL=2 # ============================================================================= # MODULE-WIDE SETTINGS # ============================================================================= -# Data root - must match the docker volume mount target +# Data root - compose sets this to the persistent bind mount target so +# face_gallery.npz survives container recreation. # FACES_DATA_ROOT=/ros/strawberry_ros_faces_module -# Use raw image topic for same-host deployment (avoids compression overhead) -# FACES_IMAGE_TOPIC=/azure_kinect/rgb/image_raw +# Use the current `rgb_topic` parameter for same-host deployment. +# FACES_NAMESPACE=/perception/proc +# FACES_RGB_TOPIC=/perception/sensor/kinect/cam_1/rgb +# FACES_CAMERA_INFO_TOPIC=/perception/sensor/kinect/cam_1/camera_info # FACES_RESPAWN=true # FACES_LOG_LEVEL=INFO @@ -93,6 +115,7 @@ FACES_ENABLE_DEBUG_TRACKER=true # FACES_TRACKER_COMMIT_MIN_SAMPLES=80 # FACES_TRACKER_RECOGNITION_ARTIFACTS_DIR=/ros/strawberry_ros_faces_module/faces_recognitor/insightface_artifacts # FACES_TRACKER_RECOGNITION_DEVICE=auto +# Keep false: enabling this deletes persisted face IDs and forces re-enrollment. # FACES_WIPE_TRACKER_STORAGE_ON_START=false # ============================================================================= @@ -136,11 +159,6 @@ FACES_ENABLE_DEBUG_TRACKER=true # FACES MERGER # ============================================================================= # FACES_SYNC_USING_STAMP=true -# FACES_CROPS_TOPIC=/faces/crops/tracked -# FACES_IDENTITIES_TOPIC=/faces/identities/recognitor/results -# FACES_GENDERS_TOPIC=/faces/genders/results -# FACES_EMOTIONS_TOPIC=/faces/emotions/results -# FACES_RELATIONS_TOPIC=/faces/relations # FACES_CROPPS_CACHE_DURATION=4.0 # FACES_CROPPS_CACHE_SIZE=20 # FACES_IDENTITIES_CACHE_DURATION=4.0 @@ -162,14 +180,6 @@ FACES_ENABLE_DEBUG_TRACKER=true # FACES_ENABLE_FACES_API=true # FACES_ENABLE_FACES_API_DEBUG_IMAGE=true # FACES_ENABLE_FACES_API_ANNOTATED_IMAGE=true -# FACES_FACES_API_DEBUG_TOPIC=/faces/api/debug/compressed -# FACES_FACES_API_ANNOTATED_TOPIC=/faces/api/annotated/compressed -# FACES_FACES_API_ANNOTATED_SHOW_ID=true -# FACES_FACES_API_ANNOTATED_SHOW_NAME=true -# FACES_FACES_API_ANNOTATED_SHOW_EMOTION=false -# FACES_FACES_API_ANNOTATED_SHOW_GENDER=false -# FACES_FACES_API_ANNOTATED_SHOW_CONFIDENCE=false -# FACES_FACES_API_ANNOTATED_SHOW_SPEAKING=false # **************** # @@ -189,7 +199,10 @@ HANDS_MIN_TRACKING_CONFIDENCE=0.6 HANDS_LOOP_RATE=8 HANDS_VIEW_IMAGES=false HANDS_RUN_CAMERA=false -HANDS_CAMERA_NAME=/azure_kinect/rgb +HANDS_CAMERA_NAME=/perception/sensor/kinect/cam_1/rgb +HANDS_NAMESPACE=/perception/proc +HANDS_IMAGE_TOPIC=/perception/sensor/kinect/cam_1/rgb/compressed +HANDS_CAMERA_INFO_TOPIC=/perception/sensor/kinect/cam_1/camera_info HANDS_RESPAWN=true # Left hand gesture recognition parameters @@ -214,55 +227,46 @@ HANDS_ENABLE_DEBUG_HANDS_IMAGE=true # ******************** # -# VISUALIZATION MODULE +# VISUALIZATION MODULE (deprecated in default perception runtime) # ******************** # -# RViz2 visualization parameters -VIZ_LAUNCH_RVIZ=true -VIZ_RVIZ_CONFIG=/opt/ros/jazzy/workspace/install/share/strawberry_ros_visualization/rviz/people_pipeline_rviz2_view.rviz +# Legacy RViz compatibility parameters only. Default visualization is the +# compose-managed `haru-viz` service, which exposes the browser UI on the host +# and runs rosbridge inside the same container. This path resolves from the +# installed `haru_viz` ROS package share directory. +VIZ_LAUNCH_RVIZ=false +VIZ_RVIZ_CONFIG=/opt/ros/jazzy/workspace/install/share/haru_viz/docs/compatibility/rviz/people_pipeline_rviz2_view.rviz VIZ_RESPAWN=false +# haru-viz service defaults +HARU_VIZ_IMAGE=ghcr.io/haru-project/haru-viz:feature-topic-normalize +HARU_VIZ_REPO_ROOT=/workspace/haru-viz +HARU_VIZ_UI_HOST=0.0.0.0 +HARU_VIZ_UI_PORT=5173 +HARU_ROSBRIDGE_PORT=9090 +HARU_ROSBRIDGE_RGB_PORT=9091 +HARU_ROSBRIDGE_DEPTH_PORT=9092 +HARU_ROSBRIDGE_MAX_MESSAGE_SIZE=8388608 + # ************* # -# PEOPLE MODULE +# PEOPLE MODULE (deprecated in default perception runtime) # ************* # # People seed source: 'skeletons' creates people from skeletons directly, # 'yolo' requires YOLO detections first -PEOPLE_SEED_SOURCE=skeletons -PEOPLE_SKELETON_SPATIAL_MODE=3d # Workspace boundaries -PEOPLE_WS_X_MAX=5.0 -PEOPLE_WS_X_MIN=-5.0 -PEOPLE_WS_Y_MAX=5.0 -PEOPLE_WS_Y_MIN=-5.0 -PEOPLE_WS_Z_MAX=5.0 -PEOPLE_WS_Z_MIN=-5.0 # Skeletons cache and filtering parameters -PEOPLE_SKELETONS_CACHE_DURATION=1.0 -PEOPLE_SKELETONS_CACHE_SIZE=100 -PEOPLE_SKELETONS_MIN_NUM_PER_ID=2 # Association factors -PEOPLE_HANDS_ASSOCIATION_FACTOR=1.0 -PEOPLE_FACES_ASSOCIATION_FACTOR=1.0 # Synchronization parameters -PEOPLE_SYNC_USING_STAMP=true # Topic configuration -PEOPLE_SKELETONS_TOPIC=/strawberry/skeletons -PEOPLE_FACES_TOPIC=/faces/results -PEOPLE_HANDS_TOPIC=/strawberry/hands_with_gestures -PEOPLE_SOUND_TOPIC=/idmind_tabletop/sound_localization -PEOPLE_SPEECH_TOPIC=/haru_speech/speech_to_text/result -PEOPLE_VAD_TOPIC=/haru_speech/speech_to_text/status -PEOPLE_WUW_TOPIC=/idmind_tabletop/wake_up_word # VAD and speech processing parameters -PEOPLE_VAD_HOLD_TIME=1.0 # ====================== # Monitor launcher args @@ -275,7 +279,7 @@ PEOPLE_VAD_HOLD_TIME=1.0 #MON_VENV_PATH=/home/haru/haru_ws/install/strawberry_resource_monitor/share/strawberry_resource_monitor/venv_monitor/bin/python3 MON_RESPAWN=true -MON_TOPIC_PREFIX=/strawberry/consumption +MON_TOPIC_PREFIX=/perception/status/consumption MON_LOG_LEVEL=INFO # Feature toggles diff --git a/envs/reasoner.env b/envs/reasoner.env index 7e422e9..49caf51 100644 --- a/envs/reasoner.env +++ b/envs/reasoner.env @@ -4,7 +4,7 @@ DISPLAY=${DISPLAY:-=:0} # ROS ROS_DOMAIN_ID=0 RMW_IMPLEMENTATION=rmw_fastrtps_cpp -FASTDDS_BUILTIN_TRANSPORTS=DEFAULT # set to UDPv4 if you encounter SHM issues +FASTDDS_BUILTIN_TRANSPORTS=UDPv4 # REASONER REACTIVE_RULES_FILE=/shared/configs/reactiveness/reactive_rules.json diff --git a/envs/recorder.env b/envs/recorder.env index 0dc57a4..9d93ae5 100644 --- a/envs/recorder.env +++ b/envs/recorder.env @@ -1,5 +1,6 @@ # ROS ROS_DOMAIN_ID=0 +HARU_PERCEPTION_ROS_DOMAIN_ID=20 RMW_IMPLEMENTATION=rmw_fastrtps_cpp FASTDDS_BUILTIN_TRANSPORTS=DEFAULT @@ -11,6 +12,7 @@ HARU_RECORDER_IMAGE=ghcr.io/haru-project/haru-recorder:feature-skeleton-integrat # ../data/perception/haru_recorder/config/default_params.yaml. RECORDER_CONFIG_FILE=/opt/ros/jazzy/workspace/install/share/haru_recorder/config/default_params.yaml HARU_RECORDER_WEB_UI_PORT=8088 +HARU_RECORDER_SESSION_ID= # Optional cloud upload settings AWS_ACCESS_KEY_ID= diff --git a/envs/simulator.env b/envs/simulator.env index 9462db4..2d14a77 100644 --- a/envs/simulator.env +++ b/envs/simulator.env @@ -13,4 +13,4 @@ NVIDIA_DRIVER_CAPABILITIES=all # ROS ROS_DOMAIN_ID=0 RMW_IMPLEMENTATION=rmw_fastrtps_cpp -FASTDDS_BUILTIN_TRANSPORTS=DEFAULT # set to UDPv4 if you encounter SHM issues +FASTDDS_BUILTIN_TRANSPORTS=UDPv4 diff --git a/scripts/compose.sh b/scripts/compose.sh index 5bb1ada..d18b722 100755 --- a/scripts/compose.sh +++ b/scripts/compose.sh @@ -7,54 +7,56 @@ APPS_DIR="${ROOT_DIR}/apps" stack="${1:-}" if [[ -z "${stack}" ]]; then echo "Usage: $(basename "$0") " >&2 - echo "Stacks: perception | speech | llm | reasoner | tts | simulator | ipad | projector | user | all" >&2 + echo "Stacks: perception | speech | llm | reasoner | tts | simulator | ipad | projector | user | recorder | all" >&2 exit 1 fi shift +stack_files=() + case "${stack}" in perception) - stack_file="${APPS_DIR}/docker-compose-perception.yaml" + stack_files=("${APPS_DIR}/docker-compose-perception.yaml") env_file="${ROOT_DIR}/envs/perception.env" ;; speech) - stack_file="${APPS_DIR}/docker-compose-speech.yaml" + stack_files=("${APPS_DIR}/docker-compose-speech.yaml") env_file="${ROOT_DIR}/envs/speech.env" ;; llm) - stack_file="${APPS_DIR}/docker-compose-llm.yaml" + stack_files=("${APPS_DIR}/docker-compose-llm.yaml") env_file="${ROOT_DIR}/envs/llm.env" ;; reasoner) - stack_file="${APPS_DIR}/docker-compose-reasoner.yaml" + stack_files=("${APPS_DIR}/docker-compose-reasoner.yaml") env_file="${ROOT_DIR}/envs/reasoner.env" ;; tts) - stack_file="${APPS_DIR}/docker-compose-tts.yaml" + stack_files=("${APPS_DIR}/docker-compose-tts.yaml") env_file="${ROOT_DIR}/envs/tts.env" ;; simulator) - stack_file="${APPS_DIR}/docker-compose-simulator.yaml" + stack_files=("${APPS_DIR}/docker-compose-simulator.yaml") env_file="${ROOT_DIR}/envs/simulator.env" ;; ipad) - stack_file="${APPS_DIR}/docker-compose-ipad.yaml" + stack_files=("${APPS_DIR}/docker-compose-ipad.yaml") env_file="${ROOT_DIR}/envs/ipad.env" ;; projector) - stack_file="${APPS_DIR}/docker-compose-projector.yaml" + stack_files=("${APPS_DIR}/docker-compose-projector.yaml") env_file="${ROOT_DIR}/envs/projector.env" ;; user) - stack_file="${APPS_DIR}/docker-compose-user.yaml" + stack_files=("${APPS_DIR}/docker-compose-user.yaml") env_file="${ROOT_DIR}/envs/user.env" ;; - all) - stack_file="${APPS_DIR}/docker-compose-all.yaml" - env_file="${ROOT_DIR}/envs/all.env" + recorder) + stack_files=("${APPS_DIR}/docker-compose-recorder.yaml") + env_file="${ROOT_DIR}/envs/recorder.env" ;; all) - stack_file="${APPS_DIR}/docker-compose-all.yaml" + stack_files=("${APPS_DIR}/docker-compose-all.yaml") env_file="${ROOT_DIR}/envs/all.env" ;; *) @@ -63,7 +65,10 @@ case "${stack}" in ;; esac -exec docker compose \ --f "${stack_file}" \ ---env-file "${env_file}" \ -"$@" +cmd=(docker compose) +for stack_file in "${stack_files[@]}"; do + cmd+=(-f "${stack_file}") +done +cmd+=(--env-file "${env_file}") + +exec "${cmd[@]}" "$@" diff --git a/scripts/download_reasoner_data.sh b/scripts/download_reasoner_data.sh index 7a98444..cf0c8ad 100755 --- a/scripts/download_reasoner_data.sh +++ b/scripts/download_reasoner_data.sh @@ -3,6 +3,7 @@ set -euo pipefail DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" DATA_FOLDER=$DIR/../data/reasoner +REASONER_IMAGE="${REASONER_IMAGE:-ghcr.io/haru-project/haru-agent-reasoner:feature-topic-normalize}" source "${DIR}/download_helpers.sh" cleanup_data_dir "$DATA_FOLDER" @@ -13,18 +14,23 @@ mkdir -p "$DATA_FOLDER/configs/params" mkdir -p "$DATA_FOLDER/projector" # Reasoner data -copy_with_tar ghcr.io/haru-project/haru-agent-reasoner:feature-web-projector \ +copy_with_tar "$REASONER_IMAGE" \ /opt/ros/jazzy/workspace/install/share/haru_agent_reasoner/examples/tasks \ "$DATA_FOLDER/tasks" -copy_with_tar ghcr.io/haru-project/haru-agent-reasoner:feature-web-projector \ +copy_with_tar "$REASONER_IMAGE" \ /opt/ros/jazzy/workspace/install/share/haru_agent_reasoner/config \ "$DATA_FOLDER/configs" -copy_with_tar ghcr.io/haru-project/haru-agent-reasoner:feature-web-projector \ +copy_with_tar "$REASONER_IMAGE" \ /opt/ros/jazzy/workspace/install/share/haru_agent_reasoner/params \ "$DATA_FOLDER/configs/params" -copy_with_tar ghcr.io/haru-project/haru-agent-reasoner:feature-web-projector \ -/opt/ros/jazzy/workspace/install/share/behavior_tree_unity_projector/examples/resources \ +copy_with_tar "$REASONER_IMAGE" \ +/opt/ros/jazzy/workspace/install/share/behavior_tree_web_projector/examples/resources \ "$DATA_FOLDER/projector" +SOURCE_POSTPROCESSORS_CONFIG="$DIR/../../agent_reasoner/haru_agent_reasoner/params/postprocessors_params.yaml" +if [ -f "$SOURCE_POSTPROCESSORS_CONFIG" ]; then + cp "$SOURCE_POSTPROCESSORS_CONFIG" "$DATA_FOLDER/configs/params/postprocessors_params.yaml" +fi + # Give permissions chmod -R a+rwX "$DATA_FOLDER" diff --git a/scripts/validate_compose.sh b/scripts/validate_compose.sh index 2390f82..12e253e 100755 --- a/scripts/validate_compose.sh +++ b/scripts/validate_compose.sh @@ -6,25 +6,33 @@ APPS_DIR="${ROOT_DIR}/apps" COMMON_FILE="${APPS_DIR}/compose.common.yaml" stacks=( - "perception:envs/perception.env:docker-compose-perception.yaml" - "speech:envs/speech.env:docker-compose-speech.yaml" - "llm:envs/llm.env:docker-compose-llm.yaml" - "reasoner:envs/reasoner.env:docker-compose-reasoner.yaml" - "tts:envs/tts.env:docker-compose-tts.yaml" - "simulator:envs/simulator.env:docker-compose-simulator.yaml" - "projector:envs/projector.env:docker-compose-projector.yaml" - "user:envs/user.env:docker-compose-user.yaml" - "all:envs/all.env:docker-compose-all.yaml" + "perception:envs/perception.env:docker-compose-perception.yaml:" + "speech:envs/speech.env:docker-compose-speech.yaml:" + "llm:envs/llm.env:docker-compose-llm.yaml:" + "reasoner:envs/reasoner.env:docker-compose-reasoner.yaml:" + "tts:envs/tts.env:docker-compose-tts.yaml:" + "simulator:envs/simulator.env:docker-compose-simulator.yaml:" + "ipad:envs/ipad.env:docker-compose-ipad.yaml:" + "projector:envs/projector.env:docker-compose-projector.yaml:" + "user:envs/user.env:docker-compose-user.yaml:" + "recorder:envs/recorder.env:docker-compose-recorder.yaml:" + "all:envs/all.env:docker-compose-all.yaml:" ) for entry in "${stacks[@]}"; do - IFS=":" read -r name env_path file_name <<< "${entry}" + IFS=":" read -r name env_path file_names profiles <<< "${entry}" echo "Validating ${name}..." - docker compose \ - -f "${COMMON_FILE}" \ - -f "${APPS_DIR}/${file_name}" \ - --env-file "${ROOT_DIR}/${env_path}" \ - config >/dev/null + cmd=(docker compose -f "${COMMON_FILE}") + IFS="," read -ra files <<< "${file_names}" + for file_name in "${files[@]}"; do + cmd+=(-f "${APPS_DIR}/${file_name}") + done + cmd+=(--env-file "${ROOT_DIR}/${env_path}" config) + if [[ -n "${profiles}" ]]; then + COMPOSE_PROFILES="${profiles}" "${cmd[@]}" >/dev/null + else + "${cmd[@]}" >/dev/null + fi done echo "All compose files validated." diff --git a/start.sh b/start.sh index c561370..eaf1ab0 100755 --- a/start.sh +++ b/start.sh @@ -66,7 +66,7 @@ bash scripts/compose.sh simulator up unity-app web-server --force-recreate -d bash scripts/compose.sh tts --profile tts up gpt-sovits cerevoice-api tts-client --force-recreate -d # Perception services -bash scripts/compose.sh perception up azure-kinect faces hands people visualization --force-recreate -d +bash scripts/compose.sh perception up azure-kinect faces hands people --force-recreate -d # Speech services bash scripts/compose.sh speech up audio configure recognition verification --force-recreate -d