diff --git a/.dockerignore b/.dockerignore index 679e11b25ef..0255e920e4f 100644 --- a/.dockerignore +++ b/.dockerignore @@ -10,13 +10,13 @@ docker !docker/etc !docker/scripts +!docker/tools # Ignore a part of files under src src/**/.* src/**/*.asc src/**/*.gif src/**/*.md -src/**/*.pcd src/**/*.svg # Ignore generated files by colcon diff --git a/.github/actions/docker-build-and-push-tools/action.yaml b/.github/actions/docker-build-and-push-tools/action.yaml new file mode 100644 index 00000000000..5b9f4d10a82 --- /dev/null +++ b/.github/actions/docker-build-and-push-tools/action.yaml @@ -0,0 +1,68 @@ +name: docker-build-and-push-tools +description: Composite action to build and push tools images to registry. + +inputs: + platform: + description: Target platform. + required: true + target-image: + description: Target docker image name in the registry. + required: true + build-args: + description: Additional build args. + required: false + +runs: + using: composite + steps: + - name: Install jq and vcstool + run: | + sudo apt-get -y update + sudo apt-get -y install jq python3-pip + pip install --no-cache-dir vcstool + shell: bash + + - name: Run vcs import + run: | + vcs import src < autoware.repos + vcs import src < simulator.repos + shell: bash + + - name: Setup Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Get current date + id: date + run: echo "date=$(date +'%Y%m%d')" >> $GITHUB_OUTPUT + shell: bash + + - name: Docker meta for autoware:scenario-simulator + id: meta-scenario-simulator + uses: docker/metadata-action@v5 + with: + images: ghcr.io/${{ github.repository_owner }}/${{ inputs.target-image }} + tags: | + type=raw,value=scenario-simulator-${{ inputs.platform }} + type=raw,value=scenario-simulator-${{ steps.date.outputs.date }}-${{ inputs.platform }} + type=ref,event=tag,prefix=scenario-simulator-,suffix=-${{ inputs.platform }} + bake-target: docker-metadata-action-scenario-simulator + flavor: | + latest=false + + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ github.token }} + + - name: Build and Push to GitHub Container Registry + uses: docker/bake-action@v5 + with: + push: true + files: | + docker/docker-bake-tools.hcl + ${{ steps.meta-scenario-simulator.outputs.bake-file }} + provenance: false + set: | + ${{ inputs.build-args }} diff --git a/.github/workflows/docker-build-and-push-arm64.yaml b/.github/workflows/docker-build-and-push-arm64.yaml index 0388d324e6f..4b6418509e6 100644 --- a/.github/workflows/docker-build-and-push-arm64.yaml +++ b/.github/workflows/docker-build-and-push-arm64.yaml @@ -72,6 +72,22 @@ jobs: *.cache-from=type=registry,ref=ghcr.io/${{ github.repository }}-buildcache:arm64-main *.cache-to=type=registry,ref=ghcr.io/${{ github.repository }}-buildcache:arm64-${{ github.ref_name }},mode=max + - name: Build 'autoware-tools' + uses: ./.github/actions/docker-build-and-push-tools + with: + platform: arm64 + target-image: autoware-tools + build-args: | + *.platform=linux/arm64 + *.args.ROS_DISTRO=${{ needs.load-env.outputs.rosdistro }} + *.args.BASE_IMAGE=${{ needs.load-env.outputs.base_image }} + *.args.AUTOWARE_BASE_IMAGE=${{ needs.load-env.outputs.autoware_base_image }} + *.args.AUTOWARE_BASE_CUDA_IMAGE=${{ needs.load-env.outputs.autoware_base_cuda_image }} + *.args.LIB_DIR=aarch64 + *.cache-from=type=registry,ref=ghcr.io/${{ github.repository }}-buildcache:arm64-${{ github.ref_name }} + *.cache-from=type=registry,ref=ghcr.io/${{ github.repository }}-buildcache:arm64-main + *.cache-to=type=registry,ref=ghcr.io/${{ github.repository }}-buildcache:arm64-${{ github.ref_name }},mode=max + - name: Show disk space if: always() run: | diff --git a/.github/workflows/docker-build-and-push.yaml b/.github/workflows/docker-build-and-push.yaml index 567678bde3e..478ba6a473a 100644 --- a/.github/workflows/docker-build-and-push.yaml +++ b/.github/workflows/docker-build-and-push.yaml @@ -62,6 +62,22 @@ jobs: *.cache-from=type=registry,ref=ghcr.io/${{ github.repository }}-buildcache:amd64-main *.cache-to=type=registry,ref=ghcr.io/${{ github.repository }}-buildcache:amd64-${{ github.ref_name }},mode=max + - name: Build 'autoware-tools' + uses: ./.github/actions/docker-build-and-push-tools + with: + platform: amd64 + target-image: autoware-tools + build-args: | + *.platform=linux/amd64 + *.args.ROS_DISTRO=${{ needs.load-env.outputs.rosdistro }} + *.args.BASE_IMAGE=${{ needs.load-env.outputs.base_image }} + *.args.AUTOWARE_BASE_IMAGE=${{ needs.load-env.outputs.autoware_base_image }} + *.args.AUTOWARE_BASE_CUDA_IMAGE=${{ needs.load-env.outputs.autoware_base_cuda_image }} + *.args.LIB_DIR=x86_64 + *.cache-from=type=registry,ref=ghcr.io/${{ github.repository }}-buildcache:amd64-${{ github.ref_name }} + *.cache-from=type=registry,ref=ghcr.io/${{ github.repository }}-buildcache:amd64-main + *.cache-to=type=registry,ref=ghcr.io/${{ github.repository }}-buildcache:amd64-${{ github.ref_name }},mode=max + - name: Show disk space if: always() run: | diff --git a/docker/docker-bake-tools.hcl b/docker/docker-bake-tools.hcl new file mode 100644 index 00000000000..f3dc7a81ee3 --- /dev/null +++ b/docker/docker-bake-tools.hcl @@ -0,0 +1,14 @@ +group "default" { + targets = [ + "scenario-simulator", + ] +} + +// For docker/metadata-action +target "docker-metadata-action-scenario-simulator" {} + +target "scenario-simulator" { + inherits = ["docker-metadata-action-scenario-simulator"] + dockerfile = "docker/tools/scenario-simulator/Dockerfile.scenario-simulator" + target = "scenario-simulator" +} diff --git a/docker/tools/README.md b/docker/tools/README.md new file mode 100644 index 00000000000..df19c8ee265 --- /dev/null +++ b/docker/tools/README.md @@ -0,0 +1,30 @@ +# Open AD Kit Tools + +This directory offers tools for [Open AD Kit](https://autoware.org/open-ad-kit/) containers to make deployment and simulation easier. + +- `scenario-simulator`: a container that can visualize the Autoware and scenario simulation on RViz. + +## Scenario Simulator + +### Run + +```bash +docker run --rm --name openadkit-scenario-simulator ghcr.io/autowarefoundation/autoware-tools:scenario-simulator +``` + +### Settings + +The following environment variables can be configured for the scenario simulator container: + +| Variable | Default Value | Possible Values | Description | +| --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------- | -------------------------------------------------------- | +| `SCENARIO` | [`scenario_test_runner/scenario/sample.yaml`](https://github.com/tier4/scenario_simulator_v2/blob/master/test_runner/scenario_test_runner/scenario/sample.yaml) | Any valid path | The full path to the scenario file inside the container | +| `ARCHITECTURE_TYPE` | `awf/universe/20240605` | Any valid architecture type | The architecture type to use for the scenario simulation | +| `SENSOR_MODEL` | `sample_sensor_kit` | Any valid sensor model | The sensor model to use for the scenario simulation | +| `VEHICLE_MODEL` | `sample_vehicle` | Any valid vehicle model | The vehicle model to use for the scenario simulation | +| `INITIALIZE_DURATION` | `90` | Any positive integer | The duration to initialize the scenario simulation | +| `GLOBAL_FRAME_RATE` | `30` | Any positive integer | The frame rate of the scenario simulation | +| `GLOBAL_TIMEOUT` | `120` | Any positive integer | The timeout of the scenario simulation | +| `OUTPUT_DIRECTORY` | `/autoware/scenario-sim/output` | Any valid path | The directory to save the simulation results | +| `USE_SIM_TIME` | `false` | `true`, `false` | Whether to use simulation time instead of system time | +| `RECORD` | `false` | `true`, `false` | Whether to record the scenario simulation rosbag | diff --git a/docker/tools/scenario-simulator/Dockerfile.scenario-simulator b/docker/tools/scenario-simulator/Dockerfile.scenario-simulator new file mode 100644 index 00000000000..2ec90c48a06 --- /dev/null +++ b/docker/tools/scenario-simulator/Dockerfile.scenario-simulator @@ -0,0 +1,59 @@ +### Builder +FROM ghcr.io/autowarefoundation/autoware:universe-devel AS builder +SHELL ["/bin/bash", "-o", "pipefail", "-c"] +ARG ROS_DISTRO +ARG LIB_DIR +ENV CCACHE_DIR="/root/.ccache" +WORKDIR /autoware +COPY src /autoware/src +COPY docker/scripts/resolve_rosdep_keys.sh /autoware/resolve_rosdep_keys.sh +RUN chmod +x /autoware/resolve_rosdep_keys.sh + +# Install dependencies and build the scenario simulator +# hadolint ignore=SC1091 +RUN --mount=type=ssh \ + --mount=type=cache,target=/var/cache/apt,sharing=locked \ + apt-get update \ + && rosdep update && rosdep install -y --from-paths src --ignore-src --rosdistro $ROS_DISTRO \ + && source /opt/ros/"$ROS_DISTRO"/setup.bash && source /opt/autoware/setup.bash \ + && colcon build --cmake-args \ + "-Wno-dev" \ + "--no-warn-unused-cli" \ + --install-base /opt/autoware \ + --merge-install \ + --mixin release compile-commands ccache \ + --base-paths /autoware/src/simulator \ + && find /opt/autoware/lib -type f -name "*.py" -exec chmod +x {} \; \ + && find /opt/autoware/share -type f -name "*.py" -exec chmod +x {} \; \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* "$HOME"/.cache + +# Extract rosdep dependencies for simulator +RUN /autoware/resolve_rosdep_keys.sh /autoware/src/simulator ${ROS_DISTRO} --dependency-types=exec \ + > /rosdep-simulator-depend-packages.txt \ + && cat /rosdep-simulator-depend-packages.txt + +### Scenario Simulator +FROM ghcr.io/autowarefoundation/autoware:core AS scenario-simulator +SHELL ["/bin/bash", "-o", "pipefail", "-c"] +ARG ROS_DISTRO +ARG LIB_DIR +WORKDIR /autoware +COPY --from=builder /opt/autoware /opt/autoware +COPY --from=builder /rosdep-simulator-depend-packages.txt /tmp/rosdep-simulator-depend-packages.txt + +# hadolint ignore=SC2002 +RUN --mount=type=ssh \ + --mount=type=cache,target=/var/cache/apt,sharing=locked \ + apt-get update && apt-get install -y curl unzip \ + && source /opt/ros/"$ROS_DISTRO"/setup.bash && source /opt/autoware/setup.bash \ + && rosdep update \ + # Remove xmlschema and yamale from rosdep packages since we install via pip + && sed -i '/\(xmlschema\|yamale\)/d' /tmp/rosdep-simulator-depend-packages.txt \ + && pip install --no-cache-dir yamale xmlschema \ + && cat /tmp/rosdep-simulator-depend-packages.txt | xargs apt-get install -y --no-install-recommends \ + && /autoware/cleanup_system.sh $LIB_DIR $ROS_DISTRO + +COPY docker/tools/scenario-simulator/entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh +ENTRYPOINT ["/entrypoint.sh"] diff --git a/docker/tools/scenario-simulator/entrypoint.sh b/docker/tools/scenario-simulator/entrypoint.sh new file mode 100644 index 00000000000..969783ff945 --- /dev/null +++ b/docker/tools/scenario-simulator/entrypoint.sh @@ -0,0 +1,57 @@ +#!/usr/bin/env bash +# cspell:ignore +# shellcheck disable=SC1090,SC1091 + +run_scenario_simulator() { + echo -e "\e[32mRunning scenario simulator...\e[0m" + + # Set default values if not provided + ARCHITECTURE_TYPE=${ARCHITECTURE_TYPE:-awf/universe/20240605} + SENSOR_MODEL=${SENSOR_MODEL:-sample_sensor_kit} + VEHICLE_MODEL=${VEHICLE_MODEL:-sample_vehicle} + INITIALIZE_DURATION=${INITIALIZE_DURATION:-90} + GLOBAL_FRAME_RATE=${GLOBAL_FRAME_RATE:-30} + OUTPUT_DIRECTORY=${OUTPUT_DIRECTORY:-/autoware/scenario-sim/output} + SCENARIO=${SCENARIO:-$(ros2 pkg prefix --share scenario_test_runner)/scenario/sample.yaml} + GLOBAL_TIMEOUT=${GLOBAL_TIMEOUT:-120} + RECORD=${RECORD:-false} + USE_SIM_TIME=${USE_SIM_TIME:-false} + + # Print all variables + echo "ARCHITECTURE_TYPE: $ARCHITECTURE_TYPE" + echo "SENSOR_MODEL: $SENSOR_MODEL" + echo "VEHICLE_MODEL: $VEHICLE_MODEL" + echo "INITIALIZE_DURATION: $INITIALIZE_DURATION" + echo "GLOBAL_FRAME_RATE: $GLOBAL_FRAME_RATE" + echo "OUTPUT_DIRECTORY: $OUTPUT_DIRECTORY" + echo "SCENARIO: $SCENARIO" + echo "GLOBAL_TIMEOUT: $GLOBAL_TIMEOUT" + echo "RECORD: $RECORD" + echo "USE_SIM_TIME: $USE_SIM_TIME" + + # Launch scenario test runner + ros2 launch scenario_test_runner scenario_test_runner.launch.py \ + launch_autoware:=false \ + launch_rviz:=false \ + architecture_type:="$ARCHITECTURE_TYPE" \ + sensor_model:="$SENSOR_MODEL" \ + vehicle_model:="$VEHICLE_MODEL" \ + initialize_duration:="$INITIALIZE_DURATION" \ + global_frame_rate:="$GLOBAL_FRAME_RATE" \ + output_directory:="$OUTPUT_DIRECTORY" \ + scenario:="$SCENARIO" \ + global_timeout:="$GLOBAL_TIMEOUT" \ + record:="$RECORD" \ + use_sim_time:="$USE_SIM_TIME" +} + +# Source ROS and Autoware setup files +source "/opt/ros/$ROS_DISTRO/setup.bash" +source "/opt/autoware/setup.bash" + +# Execute passed command if provided, otherwise run scenario simulator +if [ $# -gt 0 ]; then + exec "$@" +else + run_scenario_simulator +fi