diff --git a/.cppcheck_suppressions b/.cppcheck_suppressions
index 5e1035de20c64..ab267ec3ac007 100644
--- a/.cppcheck_suppressions
+++ b/.cppcheck_suppressions
@@ -1,4 +1,5 @@
*:*/test/*
+*:*/examples/*
checkersReport
missingInclude
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 7403da173eb13..cda3c8ceaca89 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -140,7 +140,7 @@ planning/autoware_obstacle_cruise_planner/** berkay@leodrive.ai kosuke.takeuchi@
planning/autoware_obstacle_stop_planner/** berkay@leodrive.ai bnk@leodrive.ai satoshi.ota@tier4.jp shumpei.wakabayashi@tier4.jp taiki.tanaka@tier4.jp tomoya.kimura@tier4.jp
planning/autoware_path_optimizer/** kosuke.takeuchi@tier4.jp takamasa.horibe@tier4.jp takayuki.murooka@tier4.jp
planning/autoware_path_smoother/** maxime.clement@tier4.jp takayuki.murooka@tier4.jp
-planning/autoware_planning_test_manager/** kyoichi.sugahara@tier4.jp takamasa.horibe@tier4.jp
+planning/autoware_planning_test_manager/** kyoichi.sugahara@tier4.jp mamoru.sobue@tier4.jp takamasa.horibe@tier4.jp
planning/autoware_planning_topic_converter/** kosuke.takeuchi@tier4.jp satoshi.ota@tier4.jp shumpei.wakabayashi@tier4.jp
planning/autoware_planning_validator/** kosuke.takeuchi@tier4.jp takamasa.horibe@tier4.jp
planning/autoware_remaining_distance_time_calculator/** ahmed.ebrahim@leodrive.ai
diff --git a/.github/actions/build-and-test-differential/action.yaml b/.github/actions/build-and-test-differential/action.yaml
deleted file mode 100644
index 89893e9f55fb5..0000000000000
--- a/.github/actions/build-and-test-differential/action.yaml
+++ /dev/null
@@ -1,111 +0,0 @@
-name: build-and-test-differential
-description: ""
-
-inputs:
- rosdistro:
- description: ""
- required: true
- container:
- description: ""
- required: true
- container-suffix:
- description: ""
- required: true
- runner:
- description: ""
- required: true
- build-depends-repos:
- description: ""
- required: true
- build-pre-command:
- description: ""
- required: true
- codecov-token:
- description: ""
- required: true
-
-runs:
- using: composite
- steps:
- - name: Show disk space before the tasks
- run: df -h
- shell: bash
-
- - name: Show machine specs
- run: lscpu && free -h
- shell: bash
-
- - name: Remove exec_depend
- uses: autowarefoundation/autoware-github-actions/remove-exec-depend@v1
-
- - name: Get modified packages
- id: get-modified-packages
- uses: autowarefoundation/autoware-github-actions/get-modified-packages@v1
-
- - name: Create ccache directory
- run: |
- mkdir -p ${CCACHE_DIR}
- du -sh ${CCACHE_DIR} && ccache -s
- shell: bash
-
- - name: Attempt to restore ccache
- uses: actions/cache/restore@v4
- with:
- path: |
- /root/.ccache
- key: ccache-main-${{ runner.arch }}-${{ inputs.rosdistro }}-${{ github.event.pull_request.base.sha }}
- restore-keys: |
- ccache-main-${{ runner.arch }}-${{ inputs.rosdistro }}-
-
- - name: Show ccache stats before build and reset stats
- run: |
- du -sh ${CCACHE_DIR} && ccache -s
- ccache --zero-stats
- shell: bash
-
- - name: Export CUDA state as a variable for adding to cache key
- run: |
- build_type_cuda_state=nocuda
- if [[ "${{ inputs.container-suffix }}" == "-cuda" ]]; then
- build_type_cuda_state=cuda
- fi
- echo "BUILD_TYPE_CUDA_STATE=$build_type_cuda_state" >> "${GITHUB_ENV}"
- echo "::notice::BUILD_TYPE_CUDA_STATE=$build_type_cuda_state"
- shell: bash
-
- - name: Build
- if: ${{ steps.get-modified-packages.outputs.modified-packages != '' }}
- uses: autowarefoundation/autoware-github-actions/colcon-build@v1
- with:
- rosdistro: ${{ inputs.rosdistro }}
- target-packages: ${{ steps.get-modified-packages.outputs.modified-packages }}
- build-depends-repos: ${{ inputs.build-depends-repos }}
- cache-key-element: ${{ env.BUILD_TYPE_CUDA_STATE }}
- build-pre-command: ${{ inputs.build-pre-command }}
-
- - name: Show ccache stats after build
- run: du -sh ${CCACHE_DIR} && ccache -s
- shell: bash
-
- - name: Test
- id: test
- if: ${{ steps.get-modified-packages.outputs.modified-packages != '' }}
- uses: autowarefoundation/autoware-github-actions/colcon-test@v1
- with:
- rosdistro: ${{ inputs.rosdistro }}
- target-packages: ${{ steps.get-modified-packages.outputs.modified-packages }}
- build-depends-repos: ${{ inputs.build-depends-repos }}
-
- - name: Upload coverage to CodeCov
- if: ${{ steps.test.outputs.coverage-report-files != '' }}
- uses: codecov/codecov-action@v4
- with:
- files: ${{ steps.test.outputs.coverage-report-files }}
- fail_ci_if_error: false
- verbose: true
- flags: differential
- token: ${{ inputs.codecov-token }}
-
- - name: Show disk space after the tasks
- run: df -h
- shell: bash
diff --git a/.github/actions/evaluate-job-result/action.yaml b/.github/actions/evaluate-job-result/action.yaml
new file mode 100644
index 0000000000000..c5c013080fd27
--- /dev/null
+++ b/.github/actions/evaluate-job-result/action.yaml
@@ -0,0 +1,45 @@
+name: Evaluate Job Result
+description: Evaluates the result of a job and updates the summary.
+inputs:
+ job_result:
+ description: Result of the job to evaluate (e.g., success, failure, skipped)
+ required: true
+ type: string
+ job_name:
+ description: Name of the job to evaluate
+ required: true
+ type: string
+ expected_results:
+ description: Comma-separated list of acceptable results (e.g., success,skipped)
+ required: true
+ type: string
+outputs:
+ failed:
+ description: Indicates if the job failed
+ value: ${{ steps.evaluate.outputs.failed }}
+
+runs:
+ using: composite
+ steps:
+ - name: Evaluate Job Result
+ id: evaluate
+ run: |
+ JOB_RESULT="${{ inputs.job_result }}"
+ IFS=',' read -ra EXPECTED <<< "${{ inputs.expected_results }}"
+ FAILED=false
+
+ for RESULT in "${EXPECTED[@]}"; do
+ if [[ "$JOB_RESULT" == "$RESULT" ]]; then
+ echo "- **${{ inputs.job_name }}:** "$JOB_RESULT" ✅" >> "$GITHUB_STEP_SUMMARY"
+ echo "failed=false" >> "$GITHUB_OUTPUT"
+ exit 0
+ fi
+ done
+
+ # If no expected result matched
+ echo "::error::${{ inputs.job_name }} failed. ❌"
+ echo "- **${{ inputs.job_name }}:** failed ❌" >> "$GITHUB_STEP_SUMMARY"
+ echo "failed=true" >> "$GITHUB_OUTPUT"
+
+ exit 1
+ shell: bash
diff --git a/.github/dependabot.yaml b/.github/dependabot.yaml
index 8fd9b7f4ae0a5..8e2d7193aed5d 100644
--- a/.github/dependabot.yaml
+++ b/.github/dependabot.yaml
@@ -6,8 +6,9 @@ version: 2
updates:
- package-ecosystem: github-actions
directory: /
+ # https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#scheduleinterval
schedule:
- interval: daily
+ interval: monthly
open-pull-requests-limit: 1
labels:
- tag:bot
diff --git a/.github/labeler.yaml b/.github/labeler.yaml
index 115f75197f41a..47f8737ebbf39 100644
--- a/.github/labeler.yaml
+++ b/.github/labeler.yaml
@@ -39,6 +39,3 @@
- tools/**/*
"component:vehicle":
- vehicle/**/*
-"tag:require-cuda-build-and-test":
- - perception/**/*
- - sensing/**/*
diff --git a/.github/workflows/build-and-test-differential.yaml b/.github/workflows/build-and-test-differential.yaml
index f62904b03c6e4..0925cb0f53930 100644
--- a/.github/workflows/build-and-test-differential.yaml
+++ b/.github/workflows/build-and-test-differential.yaml
@@ -1,57 +1,35 @@
name: build-and-test-differential
on:
- pull_request:
- types:
- - opened
- - synchronize
- - reopened
- - labeled
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
- cancel-in-progress: true
+ workflow_call:
+ inputs:
+ container:
+ required: true
+ type: string
+ runner:
+ default: ubuntu-24.04
+ required: false
+ type: string
+ rosdistro:
+ default: humble
+ required: false
+ type: string
+ container-suffix:
+ required: false
+ default: ""
+ type: string
+ secrets:
+ codecov-token:
+ required: true
env:
CC: /usr/lib/ccache/gcc
CXX: /usr/lib/ccache/g++
jobs:
- make-sure-label-is-present:
- uses: autowarefoundation/autoware-github-actions/.github/workflows/make-sure-label-is-present.yaml@v1
- with:
- label: tag:run-build-and-test-differential
-
- make-sure-require-cuda-label-is-present:
- uses: autowarefoundation/autoware-github-actions/.github/workflows/make-sure-label-is-present.yaml@v1
- with:
- label: tag:require-cuda-build-and-test
-
- prepare-build-and-test-differential:
- runs-on: ubuntu-latest
- needs: [make-sure-label-is-present, make-sure-require-cuda-label-is-present]
- outputs:
- cuda_build: ${{ steps.check-if-cuda-build-is-required.outputs.cuda_build }}
- steps:
- - name: Check if cuda-build is required
- id: check-if-cuda-build-is-required
- run: |
- if ${{ needs.make-sure-require-cuda-label-is-present.outputs.result == 'true' }}; then
- echo "cuda-build is required"
- echo "cuda_build=true" >> $GITHUB_OUTPUT
- else
- echo "cuda-build is not required"
- echo "cuda_build=false" >> $GITHUB_OUTPUT
- fi
- shell: bash
- - name: Fail if the tag:run-build-and-test-differential is missing
- if: ${{ needs.make-sure-label-is-present.outputs.result != 'true' }}
- run: exit 1
-
build-and-test-differential:
- runs-on: ubuntu-latest
- container: ghcr.io/autowarefoundation/autoware:universe-devel
- needs: prepare-build-and-test-differential
+ runs-on: ${{ inputs.runner }}
+ container: ${{ inputs.container }}${{ inputs.container-suffix }}
steps:
- name: Set PR fetch depth
run: echo "PR_FETCH_DEPTH=$(( ${{ github.event.pull_request.commits }} + 1 ))" >> "${GITHUB_ENV}"
@@ -63,61 +41,13 @@ jobs:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: ${{ env.PR_FETCH_DEPTH }}
- - name: Run build-and-test-differential action
- uses: ./.github/actions/build-and-test-differential
- with:
- rosdistro: humble
- container: ghcr.io/autowarefoundation/autoware:universe-devel
- container-suffix: ""
- runner: ubuntu-latest
- build-depends-repos: build_depends.repos
- build-pre-command: ""
- codecov-token: ${{ secrets.CODECOV_TOKEN }}
-
- build-and-test-differential-cuda:
- runs-on: codebuild-autoware-us-east-1-${{ github.run_id }}-${{ github.run_attempt }}-ubuntu-7.0-large
- container: ghcr.io/autowarefoundation/autoware:universe-devel-cuda
- needs: prepare-build-and-test-differential
- if: ${{ needs.prepare-build-and-test-differential.outputs.cuda_build == 'true' }}
- steps:
- - name: Set PR fetch depth
- run: echo "PR_FETCH_DEPTH=$(( ${{ github.event.pull_request.commits }} + 1 ))" >> "${GITHUB_ENV}"
- shell: bash
-
- - name: Checkout PR branch and all PR commits
- uses: actions/checkout@v4
- with:
- ref: ${{ github.event.pull_request.head.sha }}
- fetch-depth: ${{ env.PR_FETCH_DEPTH }}
-
- - name: Run build-and-test-differential action
- uses: ./.github/actions/build-and-test-differential
- with:
- rosdistro: humble
- container: ghcr.io/autowarefoundation/autoware:universe-devel
- container-suffix: -cuda
- runner: codebuild-autoware-us-east-1-${{ github.run_id }}-${{ github.run_attempt }}-ubuntu-7.0-large
- build-depends-repos: build_depends.repos
- build-pre-command: taskset --cpu-list 0-5
- codecov-token: ${{ secrets.CODECOV_TOKEN }}
-
- clang-tidy-differential:
- needs: [build-and-test-differential, prepare-build-and-test-differential]
- if: ${{ needs.prepare-build-and-test-differential.outputs.cuda_build == 'false' }}
- runs-on: ubuntu-latest
- container: ghcr.io/autowarefoundation/autoware:universe-devel
- steps:
- - name: Set PR fetch depth
- run: echo "PR_FETCH_DEPTH=$(( ${{ github.event.pull_request.commits }} + 1 ))" >> "${GITHUB_ENV}"
-
- - name: Checkout PR branch and all PR commits
- uses: actions/checkout@v4
- with:
- ref: ${{ github.event.pull_request.head.sha }}
- fetch-depth: ${{ env.PR_FETCH_DEPTH }}
-
- name: Show disk space before the tasks
run: df -h
+ shell: bash
+
+ - name: Show machine specs
+ run: lscpu && free -h
+ shell: bash
- name: Remove exec_depend
uses: autowarefoundation/autoware-github-actions/remove-exec-depend@v1
@@ -126,66 +56,69 @@ jobs:
id: get-modified-packages
uses: autowarefoundation/autoware-github-actions/get-modified-packages@v1
- - name: Get changed files (existing files only)
- id: get-changed-files
+ - name: Create ccache directory
run: |
- echo "changed-files=$(git diff --name-only "origin/${{ github.base_ref }}"...HEAD | grep -E '\.(cpp|hpp)$' | while read -r file; do [ -e "$file" ] && echo -n "$file "; done)" >> $GITHUB_OUTPUT
+ mkdir -p ${CCACHE_DIR}
+ du -sh ${CCACHE_DIR} && ccache -s
shell: bash
- - name: Run clang-tidy
- if: ${{ steps.get-changed-files.outputs.changed-files != '' }}
- uses: autowarefoundation/autoware-github-actions/clang-tidy@v1
+ - name: Attempt to restore ccache
+ uses: actions/cache/restore@v4
with:
- rosdistro: humble
- target-packages: ${{ steps.get-modified-packages.outputs.modified-packages }}
- clang-tidy-config-url: https://raw.githubusercontent.com/autowarefoundation/autoware/main/.clang-tidy-ci
- clang-tidy-ignore-path: .clang-tidy-ignore
- build-depends-repos: build_depends.repos
- cache-key-element: cuda
+ path: |
+ /root/.ccache
+ key: ccache-main-${{ runner.arch }}-${{ inputs.rosdistro }}-${{ github.event.pull_request.base.sha }}
+ restore-keys: |
+ ccache-main-${{ runner.arch }}-${{ inputs.rosdistro }}-
- - name: Show disk space after the tasks
- run: df -h
+ - name: Show ccache stats before build and reset stats
+ run: |
+ du -sh ${CCACHE_DIR} && ccache -s
+ ccache --zero-stats
+ shell: bash
- clang-tidy-differential-cuda:
- needs: build-and-test-differential-cuda
- runs-on: codebuild-autoware-us-east-1-${{ github.run_id }}-${{ github.run_attempt }}-ubuntu-7.0-large
- container: ghcr.io/autowarefoundation/autoware:universe-devel-cuda
- steps:
- - name: Set PR fetch depth
- run: echo "PR_FETCH_DEPTH=$(( ${{ github.event.pull_request.commits }} + 1 ))" >> "${GITHUB_ENV}"
+ - name: Export CUDA state as a variable for adding to cache key
+ run: |
+ build_type_cuda_state=nocuda
+ if [[ "${{ inputs.container-suffix }}" == "-cuda" ]]; then
+ build_type_cuda_state=cuda
+ fi
+ echo "BUILD_TYPE_CUDA_STATE=$build_type_cuda_state" >> "${GITHUB_ENV}"
+ echo "::notice::BUILD_TYPE_CUDA_STATE=$build_type_cuda_state"
+ shell: bash
- - name: Checkout PR branch and all PR commits
- uses: actions/checkout@v4
+ - name: Build
+ if: ${{ steps.get-modified-packages.outputs.modified-packages != '' }}
+ uses: autowarefoundation/autoware-github-actions/colcon-build@v1
with:
- ref: ${{ github.event.pull_request.head.sha }}
- fetch-depth: ${{ env.PR_FETCH_DEPTH }}
-
- - name: Show disk space before the tasks
- run: df -h
-
- - name: Remove exec_depend
- uses: autowarefoundation/autoware-github-actions/remove-exec-depend@v1
-
- - name: Get modified packages
- id: get-modified-packages
- uses: autowarefoundation/autoware-github-actions/get-modified-packages@v1
+ rosdistro: ${{ inputs.rosdistro }}
+ target-packages: ${{ steps.get-modified-packages.outputs.modified-packages }}
+ build-depends-repos: build_depends.repos
+ cache-key-element: ${{ env.BUILD_TYPE_CUDA_STATE }}
- - name: Get changed files (existing files only)
- id: get-changed-files
- run: |
- echo "changed-files=$(git diff --name-only "origin/${{ github.base_ref }}"...HEAD | grep -E '\.(cpp|hpp)$' | while read -r file; do [ -e "$file" ] && echo -n "$file "; done)" >> $GITHUB_OUTPUT
+ - name: Show ccache stats after build
+ run: du -sh ${CCACHE_DIR} && ccache -s
shell: bash
- - name: Run clang-tidy
- if: ${{ steps.get-changed-files.outputs.changed-files != '' }}
- uses: autowarefoundation/autoware-github-actions/clang-tidy@v1
+ - name: Test
+ id: test
+ if: ${{ steps.get-modified-packages.outputs.modified-packages != '' }}
+ uses: autowarefoundation/autoware-github-actions/colcon-test@v1
with:
- rosdistro: humble
+ rosdistro: ${{ inputs.rosdistro }}
target-packages: ${{ steps.get-modified-packages.outputs.modified-packages }}
- clang-tidy-config-url: https://raw.githubusercontent.com/autowarefoundation/autoware/main/.clang-tidy-ci
- clang-tidy-ignore-path: .clang-tidy-ignore
build-depends-repos: build_depends.repos
- cache-key-element: cuda
+
+ - name: Upload coverage to CodeCov
+ if: ${{ steps.test.outputs.coverage-report-files != '' }}
+ uses: codecov/codecov-action@v4
+ with:
+ files: ${{ steps.test.outputs.coverage-report-files }}
+ fail_ci_if_error: false
+ verbose: true
+ flags: differential${{ inputs.container-suffix }}
+ token: ${{ secrets.codecov-token }}
- name: Show disk space after the tasks
run: df -h
+ shell: bash
diff --git a/.github/workflows/build-test-tidy-pr.yaml b/.github/workflows/build-test-tidy-pr.yaml
new file mode 100644
index 0000000000000..d1ea9b2d0f79d
--- /dev/null
+++ b/.github/workflows/build-test-tidy-pr.yaml
@@ -0,0 +1,137 @@
+name: build-test-tidy-pr
+
+on:
+ pull_request:
+ types:
+ - opened
+ - synchronize
+ - reopened
+ - labeled
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
+ cancel-in-progress: true
+
+jobs:
+ require-label:
+ uses: autowarefoundation/autoware-github-actions/.github/workflows/require-label.yaml@v1
+ with:
+ label: run:build-and-test-differential
+
+ check-if-cuda-job-is-needed:
+ needs: require-label
+ runs-on: ubuntu-latest
+ outputs:
+ cuda_job_is_needed: ${{ steps.check.outputs.any_changed }}
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Check if relevant files changed
+ id: check
+ uses: tj-actions/changed-files@v45
+ with:
+ files: |
+ perception/**
+ sensing/**
+
+ - name: Output result
+ run: |
+ echo "CUDA job needed: ${{ steps.check.outputs.any_changed }}"
+ shell: bash
+
+ build-and-test-differential:
+ needs:
+ - require-label
+ uses: ./.github/workflows/build-and-test-differential.yaml
+ with:
+ container: ghcr.io/autowarefoundation/autoware:universe-devel
+ secrets:
+ codecov-token: ${{ secrets.CODECOV_TOKEN }}
+
+ build-and-test-differential-cuda:
+ needs: check-if-cuda-job-is-needed
+ if: ${{ needs.check-if-cuda-job-is-needed.outputs.cuda_job_is_needed == 'true' }}
+ uses: ./.github/workflows/build-and-test-differential.yaml
+ with:
+ container: ghcr.io/autowarefoundation/autoware:universe-devel
+ container-suffix: -cuda
+ secrets:
+ codecov-token: ${{ secrets.CODECOV_TOKEN }}
+
+ build-test-pr:
+ needs:
+ - build-and-test-differential
+ - build-and-test-differential-cuda
+ if: ${{ always() }}
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Initialize Summary
+ run: echo "### Build Test PR Results" > $GITHUB_STEP_SUMMARY
+ shell: bash
+
+ - name: Evaluate build-and-test-differential
+ uses: ./.github/actions/evaluate-job-result
+ with:
+ job_result: ${{ needs.build-and-test-differential.result }}
+ job_name: build-and-test-differential
+ expected_results: success
+
+ - name: Evaluate build-and-test-differential-cuda
+ if: ${{ always() }}
+ uses: ./.github/actions/evaluate-job-result
+ with:
+ job_result: ${{ needs.build-and-test-differential-cuda.result }}
+ job_name: build-and-test-differential-cuda
+ expected_results: success,skipped
+
+ clang-tidy-differential:
+ needs:
+ - check-if-cuda-job-is-needed
+ - build-and-test-differential
+ if: ${{ needs.check-if-cuda-job-is-needed.outputs.cuda_job_is_needed == 'false' }}
+ uses: ./.github/workflows/clang-tidy-differential.yaml
+ with:
+ container: ghcr.io/autowarefoundation/autoware:universe-devel
+
+ clang-tidy-differential-cuda:
+ needs:
+ - build-and-test-differential-cuda
+ uses: ./.github/workflows/clang-tidy-differential.yaml
+ with:
+ container: ghcr.io/autowarefoundation/autoware:universe-devel
+ container-suffix: -cuda
+
+ clang-tidy-pr:
+ needs:
+ - clang-tidy-differential
+ - clang-tidy-differential-cuda
+ if: ${{ always() }}
+ runs-on: ubuntu-latest
+ steps:
+ - name: Initialize Summary
+ run: echo "### Clang Tidy PR Results" > $GITHUB_STEP_SUMMARY
+ shell: bash
+
+ - name: Check clang-tidy success
+ if: ${{ needs.clang-tidy-differential.result == 'success' || needs.clang-tidy-differential-cuda.result == 'success' }}
+ run: |
+ echo "✅ Either one of the following has succeeded:" >> $GITHUB_STEP_SUMMARY
+
+ - name: Fail if conditions not met
+ if: ${{ !(needs.clang-tidy-differential.result == 'success' || needs.clang-tidy-differential-cuda.result == 'success') }}
+ run: |
+ echo "::error::❌ Either one of the following should have succeeded:"
+ echo "::error::clang-tidy-differential: ${{ needs.clang-tidy-differential.result }}"
+ echo "::error::clang-tidy-differential-cuda: ${{ needs.clang-tidy-differential-cuda.result }}"
+
+ echo "❌ Either one of the following should have succeeded:" >> $GITHUB_STEP_SUMMARY
+
+ exit 1
+
+ - name: Print the results
+ if: ${{ always() }}
+ run: |
+ echo "- **clang-tidy-differential:** ${{ needs.clang-tidy-differential.result }}" >> $GITHUB_STEP_SUMMARY
+ echo "- **clang-tidy-differential-cuda:** ${{ needs.clang-tidy-differential-cuda.result }}" >> $GITHUB_STEP_SUMMARY
diff --git a/.github/workflows/clang-tidy-differential.yaml b/.github/workflows/clang-tidy-differential.yaml
new file mode 100644
index 0000000000000..51e0a8408468c
--- /dev/null
+++ b/.github/workflows/clang-tidy-differential.yaml
@@ -0,0 +1,75 @@
+name: clang-tidy-differential
+
+on:
+ workflow_call:
+ inputs:
+ container:
+ required: true
+ type: string
+ container-suffix:
+ required: false
+ default: ""
+ type: string
+ runner:
+ default: ubuntu-24.04
+ required: false
+ type: string
+
+jobs:
+ clang-tidy-differential:
+ runs-on: ${{ inputs.runner }}
+ container: ${{ inputs.container }}${{ inputs.container-suffix }}
+ steps:
+ - name: Set PR fetch depth
+ run: echo "PR_FETCH_DEPTH=$(( ${{ github.event.pull_request.commits }} + 1 ))" >> "${GITHUB_ENV}"
+
+ - name: Checkout PR branch and all PR commits
+ uses: actions/checkout@v4
+ with:
+ ref: ${{ github.event.pull_request.head.sha }}
+ fetch-depth: ${{ env.PR_FETCH_DEPTH }}
+
+ - name: Show machine specs
+ run: lscpu && free -h
+ shell: bash
+
+ - name: Show disk space before the tasks
+ run: df -h
+ shell: bash
+
+ - name: Remove exec_depend
+ uses: autowarefoundation/autoware-github-actions/remove-exec-depend@v1
+
+ - name: Get modified packages
+ id: get-modified-packages
+ uses: autowarefoundation/autoware-github-actions/get-modified-packages@v1
+
+ - name: Get changed files (existing files only)
+ id: get-changed-files
+ run: |
+ echo "changed-files=$(git diff --name-only "origin/${{ github.base_ref }}"...HEAD | grep -E '\.(cpp|hpp)$' | while read -r file; do [ -e "$file" ] && echo -n "$file "; done)" >> $GITHUB_OUTPUT
+ shell: bash
+
+ - name: Export CUDA state as a variable for adding to cache key
+ run: |
+ build_type_cuda_state=nocuda
+ if [[ "${{ inputs.container-suffix }}" == "-cuda" ]]; then
+ build_type_cuda_state=cuda
+ fi
+ echo "BUILD_TYPE_CUDA_STATE=$build_type_cuda_state" >> "${GITHUB_ENV}"
+ echo "::notice::BUILD_TYPE_CUDA_STATE=$build_type_cuda_state"
+ shell: bash
+
+ - name: Run clang-tidy
+ if: ${{ steps.get-changed-files.outputs.changed-files != '' }}
+ uses: autowarefoundation/autoware-github-actions/clang-tidy@v1
+ with:
+ rosdistro: humble
+ target-packages: ${{ steps.get-modified-packages.outputs.modified-packages }}
+ clang-tidy-config-url: https://raw.githubusercontent.com/autowarefoundation/autoware/main/.clang-tidy-ci
+ clang-tidy-ignore-path: .clang-tidy-ignore
+ build-depends-repos: build_depends.repos
+ cache-key-element: ${{ env.BUILD_TYPE_CUDA_STATE }}
+
+ - name: Show disk space after the tasks
+ run: df -h
diff --git a/.github/workflows/deploy-docs.yaml b/.github/workflows/deploy-docs.yaml
index d39e97e540794..47009a25e69fd 100644
--- a/.github/workflows/deploy-docs.yaml
+++ b/.github/workflows/deploy-docs.yaml
@@ -26,7 +26,7 @@ jobs:
prevent-no-label-execution:
uses: autowarefoundation/autoware-github-actions/.github/workflows/prevent-no-label-execution.yaml@v1
with:
- label: tag:deploy-docs
+ label: run:deploy-docs
deploy-docs:
needs: prevent-no-label-execution
diff --git a/.github/workflows/pre-commit-autoupdate.yaml b/.github/workflows/pre-commit-autoupdate.yaml
index 489e32a1de166..60c17d9dabf72 100644
--- a/.github/workflows/pre-commit-autoupdate.yaml
+++ b/.github/workflows/pre-commit-autoupdate.yaml
@@ -6,7 +6,7 @@ name: pre-commit-autoupdate
on:
schedule:
- - cron: 0 0 * * *
+ - cron: 0 0 1 1,4,7,10 * # quarterly
workflow_dispatch:
jobs:
diff --git a/.github/workflows/pre-commit-optional-autoupdate.yaml b/.github/workflows/pre-commit-optional-autoupdate.yaml
index be79ad481d16e..6639e5ca6c61a 100644
--- a/.github/workflows/pre-commit-optional-autoupdate.yaml
+++ b/.github/workflows/pre-commit-optional-autoupdate.yaml
@@ -6,7 +6,7 @@ name: pre-commit-optional-autoupdate
on:
schedule:
- - cron: 0 0 * * *
+ - cron: 0 0 1 1,4,7,10 * # quarterly
workflow_dispatch:
jobs:
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 6e7c64fd982fc..48a97c13ef958 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -2,8 +2,12 @@
# https://github.com/autowarefoundation/sync-file-templates
# To make changes, update the source repository and follow the guidelines in its README.
+# https://pre-commit.ci/#configuration
ci:
autofix_commit_msg: "style(pre-commit): autofix"
+ # we already have our own daily update mechanism, we set this to quarterly
+ autoupdate_schedule: quarterly
+ autoupdate_commit_msg: "ci(pre-commit): quarterly autoupdate"
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
@@ -70,7 +74,7 @@ repos:
args: [--line-length=100]
- repo: https://github.com/pre-commit/mirrors-clang-format
- rev: v19.1.4
+ rev: v19.1.5
hooks:
- id: clang-format
types_or: [c++, c, cuda]
diff --git a/build_depends.repos b/build_depends.repos
index 4db947b7c26a8..2313a9be487a6 100644
--- a/build_depends.repos
+++ b/build_depends.repos
@@ -32,7 +32,7 @@ repositories:
core/autoware_internal_msgs:
type: git
url: https://github.com/autowarefoundation/autoware_internal_msgs.git
- version: 1.1.0
+ version: 1.3.0
# universe
universe/external/tier4_autoware_msgs:
type: git
diff --git a/common/autoware_adapi_specs/include/autoware/adapi_specs/vehicle.hpp b/common/autoware_adapi_specs/include/autoware/adapi_specs/vehicle.hpp
index a7568d54b5e1a..dc907b6610cde 100644
--- a/common/autoware_adapi_specs/include/autoware/adapi_specs/vehicle.hpp
+++ b/common/autoware_adapi_specs/include/autoware/adapi_specs/vehicle.hpp
@@ -41,7 +41,7 @@ struct VehicleStatus
using Message = autoware_adapi_v1_msgs::msg::VehicleStatus;
static constexpr char name[] = "/api/vehicle/status";
static constexpr size_t depth = 1;
- static constexpr auto reliability = RMW_QOS_POLICY_RELIABILITY_RELIABLE;
+ static constexpr auto reliability = RMW_QOS_POLICY_RELIABILITY_BEST_EFFORT;
static constexpr auto durability = RMW_QOS_POLICY_DURABILITY_VOLATILE;
};
diff --git a/common/autoware_interpolation/test/src/test_interpolation_utils.cpp b/common/autoware_interpolation/test/src/test_interpolation_utils.cpp
index 2aa41b6fdef00..9131b458dd68b 100644
--- a/common/autoware_interpolation/test/src/test_interpolation_utils.cpp
+++ b/common/autoware_interpolation/test/src/test_interpolation_utils.cpp
@@ -18,8 +18,6 @@
#include
-constexpr double epsilon = 1e-6;
-
TEST(interpolation_utils, isIncreasing)
{
// empty
diff --git a/common/autoware_motion_utils/include/autoware/motion_utils/factor/planning_factor_interface.hpp b/common/autoware_motion_utils/include/autoware/motion_utils/factor/planning_factor_interface.hpp
new file mode 100644
index 0000000000000..7b720c69c6701
--- /dev/null
+++ b/common/autoware_motion_utils/include/autoware/motion_utils/factor/planning_factor_interface.hpp
@@ -0,0 +1,240 @@
+// Copyright 2024 TIER IV, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef AUTOWARE__MOTION_UTILS__FACTOR__PLANNING_FACTOR_INTERFACE_HPP_
+#define AUTOWARE__MOTION_UTILS__FACTOR__PLANNING_FACTOR_INTERFACE_HPP_
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+namespace autoware::motion_utils
+{
+
+using geometry_msgs::msg::Pose;
+using tier4_planning_msgs::msg::ControlPoint;
+using tier4_planning_msgs::msg::PlanningFactor;
+using tier4_planning_msgs::msg::PlanningFactorArray;
+using tier4_planning_msgs::msg::SafetyFactorArray;
+
+class PlanningFactorInterface
+{
+public:
+ PlanningFactorInterface(rclcpp::Node * node, const std::string & name)
+ : name_{name},
+ pub_factors_{
+ node->create_publisher("/planning/planning_factors/" + name, 1)},
+ clock_{node->get_clock()}
+ {
+ }
+
+ /**
+ * @brief factor setter for single control point.
+ *
+ * @param path points.
+ * @param ego current pose.
+ * @param control point pose. (e.g. stop or slow down point pose)
+ * @param behavior of this planning factor.
+ * @param safety factor.
+ * @param driving direction.
+ * @param target velocity of the control point.
+ * @param shift length of the control point.
+ * @param detail information.
+ */
+ template
+ void add(
+ const std::vector & points, const Pose & ego_pose, const Pose & control_point_pose,
+ const uint16_t behavior, const SafetyFactorArray & safety_factors,
+ const bool is_driving_forward = true, const double velocity = 0.0,
+ const double shift_length = 0.0, const std::string & detail = "")
+ {
+ const auto distance = static_cast(autoware::motion_utils::calcSignedArcLength(
+ points, ego_pose.position, control_point_pose.position));
+ add(
+ distance, control_point_pose, behavior, safety_factors, is_driving_forward, velocity,
+ shift_length, detail);
+ }
+
+ /**
+ * @brief factor setter for two control points (section).
+ *
+ * @param path points.
+ * @param ego current pose.
+ * @param control section start pose. (e.g. lane change start point pose)
+ * @param control section end pose. (e.g. lane change end point pose)
+ * @param behavior of this planning factor.
+ * @param safety factor.
+ * @param driving direction.
+ * @param target velocity of the control point.
+ * @param shift length of the control point.
+ * @param detail information.
+ */
+ template
+ void add(
+ const std::vector & points, const Pose & ego_pose, const Pose & start_pose,
+ const Pose & end_pose, const uint16_t behavior, const SafetyFactorArray & safety_factors,
+ const bool is_driving_forward = true, const double velocity = 0.0,
+ const double shift_length = 0.0, const std::string & detail = "")
+ {
+ const auto start_distance = static_cast(
+ autoware::motion_utils::calcSignedArcLength(points, ego_pose.position, start_pose.position));
+ const auto end_distance = static_cast(
+ autoware::motion_utils::calcSignedArcLength(points, ego_pose.position, end_pose.position));
+ add(
+ start_distance, end_distance, start_pose, end_pose, behavior, safety_factors,
+ is_driving_forward, velocity, shift_length, detail);
+ }
+
+ /**
+ * @brief factor setter for single control point.
+ *
+ * @param distance to control point.
+ * @param control point pose. (e.g. stop point pose)
+ * @param behavior of this planning factor.
+ * @param safety factor.
+ * @param driving direction.
+ * @param target velocity of the control point.
+ * @param shift length of the control point.
+ * @param detail information.
+ */
+ void add(
+ const double distance, const Pose & control_point_pose, const uint16_t behavior,
+ const SafetyFactorArray & safety_factors, const bool is_driving_forward = true,
+ const double velocity = 0.0, const double shift_length = 0.0, const std::string & detail = "")
+ {
+ const auto control_point = tier4_planning_msgs::build()
+ .pose(control_point_pose)
+ .velocity(velocity)
+ .shift_length(shift_length)
+ .distance(distance);
+
+ const auto factor = tier4_planning_msgs::build()
+ .module(name_)
+ .is_driving_forward(is_driving_forward)
+ .control_points({control_point})
+ .behavior(behavior)
+ .detail(detail)
+ .safety_factors(safety_factors);
+
+ factors_.push_back(factor);
+ }
+
+ /**
+ * @brief factor setter for two control points (section).
+ *
+ * @param distance to control section start point.
+ * @param distance to control section end point.
+ * @param control section start pose. (e.g. lane change start point pose)
+ * @param control section end pose. (e.g. lane change end point pose)
+ * @param behavior of this planning factor.
+ * @param safety factor.
+ * @param driving direction.
+ * @param target velocity of the control point.
+ * @param shift length of the control point.
+ * @param detail information.
+ */
+ void add(
+ const double start_distance, const double end_distance, const Pose & start_pose,
+ const Pose & end_pose, const uint16_t behavior, const SafetyFactorArray & safety_factors,
+ const bool is_driving_forward = true, const double velocity = 0.0,
+ const double shift_length = 0.0, const std::string & detail = "")
+ {
+ const auto control_start_point = tier4_planning_msgs::build()
+ .pose(start_pose)
+ .velocity(velocity)
+ .shift_length(shift_length)
+ .distance(start_distance);
+
+ const auto control_end_point = tier4_planning_msgs::build()
+ .pose(end_pose)
+ .velocity(velocity)
+ .shift_length(shift_length)
+ .distance(end_distance);
+
+ const auto factor = tier4_planning_msgs::build()
+ .module(name_)
+ .is_driving_forward(is_driving_forward)
+ .control_points({control_start_point, control_end_point})
+ .behavior(behavior)
+ .detail(detail)
+ .safety_factors(safety_factors);
+
+ factors_.push_back(factor);
+ }
+
+ /**
+ * @brief publish planning factors.
+ */
+ void publish()
+ {
+ PlanningFactorArray msg;
+ msg.header.frame_id = "map";
+ msg.header.stamp = clock_->now();
+ msg.factors = factors_;
+
+ pub_factors_->publish(msg);
+
+ factors_.clear();
+ }
+
+private:
+ std::string name_;
+
+ rclcpp::Publisher::SharedPtr pub_factors_;
+
+ rclcpp::Clock::SharedPtr clock_;
+
+ std::vector factors_;
+};
+
+extern template void PlanningFactorInterface::add(
+ const std::vector &, const Pose &, const Pose &,
+ const uint16_t behavior, const SafetyFactorArray &, const bool, const double, const double,
+ const std::string &);
+extern template void PlanningFactorInterface::add(
+ const std::vector &, const Pose &, const Pose &,
+ const uint16_t behavior, const SafetyFactorArray &, const bool, const double, const double,
+ const std::string &);
+extern template void PlanningFactorInterface::add(
+ const std::vector &, const Pose &, const Pose &,
+ const uint16_t behavior, const SafetyFactorArray &, const bool, const double, const double,
+ const std::string &);
+
+extern template void PlanningFactorInterface::add(
+ const std::vector &, const Pose &, const Pose &,
+ const Pose &, const uint16_t behavior, const SafetyFactorArray &, const bool, const double,
+ const double, const std::string &);
+extern template void PlanningFactorInterface::add(
+ const std::vector &, const Pose &, const Pose &,
+ const Pose &, const uint16_t behavior, const SafetyFactorArray &, const bool, const double,
+ const double, const std::string &);
+extern template void PlanningFactorInterface::add(
+ const std::vector &, const Pose &, const Pose &,
+ const Pose &, const uint16_t behavior, const SafetyFactorArray &, const bool, const double,
+ const double, const std::string &);
+
+} // namespace autoware::motion_utils
+
+#endif // AUTOWARE__MOTION_UTILS__FACTOR__PLANNING_FACTOR_INTERFACE_HPP_
diff --git a/common/autoware_motion_utils/src/factor/planing_factor_interface.cpp b/common/autoware_motion_utils/src/factor/planing_factor_interface.cpp
new file mode 100644
index 0000000000000..d09355b4003ae
--- /dev/null
+++ b/common/autoware_motion_utils/src/factor/planing_factor_interface.cpp
@@ -0,0 +1,47 @@
+// Copyright 2024 TIER IV, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include
+
+#include
+#include
+
+namespace autoware::motion_utils
+{
+template void PlanningFactorInterface::add(
+ const std::vector &, const Pose &, const Pose &,
+ const uint16_t behavior, const SafetyFactorArray &, const bool, const double, const double,
+ const std::string &);
+template void PlanningFactorInterface::add(
+ const std::vector &, const Pose &, const Pose &,
+ const uint16_t behavior, const SafetyFactorArray &, const bool, const double, const double,
+ const std::string &);
+template void PlanningFactorInterface::add(
+ const std::vector &, const Pose &, const Pose &,
+ const uint16_t behavior, const SafetyFactorArray &, const bool, const double, const double,
+ const std::string &);
+
+template void PlanningFactorInterface::add(
+ const std::vector &, const Pose &, const Pose &,
+ const Pose &, const uint16_t behavior, const SafetyFactorArray &, const bool, const double,
+ const double, const std::string &);
+template void PlanningFactorInterface::add(
+ const std::vector &, const Pose &, const Pose &,
+ const Pose &, const uint16_t behavior, const SafetyFactorArray &, const bool, const double,
+ const double, const std::string &);
+template void PlanningFactorInterface::add(
+ const std::vector &, const Pose &, const Pose &,
+ const Pose &, const uint16_t behavior, const SafetyFactorArray &, const bool, const double,
+ const double, const std::string &);
+} // namespace autoware::motion_utils
diff --git a/common/autoware_motion_utils/test/src/trajectory/benchmark_calcLateralOffset.cpp b/common/autoware_motion_utils/test/src/trajectory/benchmark_calcLateralOffset.cpp
index dc828e885af64..d00053a7b4ff6 100644
--- a/common/autoware_motion_utils/test/src/trajectory/benchmark_calcLateralOffset.cpp
+++ b/common/autoware_motion_utils/test/src/trajectory/benchmark_calcLateralOffset.cpp
@@ -26,8 +26,6 @@ using autoware::universe_utils::createPoint;
using autoware::universe_utils::createQuaternionFromRPY;
using autoware_planning_msgs::msg::Trajectory;
-constexpr double epsilon = 1e-6;
-
geometry_msgs::msg::Pose createPose(
double x, double y, double z, double roll, double pitch, double yaw)
{
diff --git a/common/autoware_pyplot/CMakeLists.txt b/common/autoware_pyplot/CMakeLists.txt
index 6922d5d9306f7..5871929676a2d 100644
--- a/common/autoware_pyplot/CMakeLists.txt
+++ b/common/autoware_pyplot/CMakeLists.txt
@@ -15,8 +15,12 @@ autoware_package()
ament_auto_add_library(${PROJECT_NAME} STATIC
DIRECTORY src
)
+target_compile_options(${PROJECT_NAME} PUBLIC "-fPIC")
target_link_libraries(${PROJECT_NAME} ${Python3_LIBRARIES} pybind11::embed)
+# NOTE(soblin): this is workaround for propagating the include of "Python.h" to user modules to avoid "'Python.h' not found"
+ament_export_include_directories(${Python3_INCLUDE_DIRS})
+
if(BUILD_TESTING)
find_package(ament_cmake_ros REQUIRED)
diff --git a/common/autoware_test_utils/include/autoware_test_utils/visualization.hpp b/common/autoware_test_utils/include/autoware_test_utils/visualization.hpp
new file mode 100644
index 0000000000000..c2185e65422e8
--- /dev/null
+++ b/common/autoware_test_utils/include/autoware_test_utils/visualization.hpp
@@ -0,0 +1,229 @@
+// Copyright 2024 TIER IV
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// NOTE(soblin): this file is intentionally inline to deal with link issue
+
+#ifndef AUTOWARE_TEST_UTILS__VISUALIZATION_HPP_
+#define AUTOWARE_TEST_UTILS__VISUALIZATION_HPP_
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+namespace autoware::test_utils
+{
+
+struct PointConfig
+{
+ std::optional color{};
+ std::optional marker{};
+ std::optional marker_size{};
+};
+
+struct LineConfig
+{
+ static constexpr const char * default_color = "blue";
+ static LineConfig defaults()
+ {
+ return LineConfig{std::string(default_color), 1.0, "solid", std::nullopt};
+ }
+ std::optional color{};
+ std::optional linewidth{};
+ std::optional linestyle{};
+ std::optional label{};
+};
+
+struct LaneConfig
+{
+ static LaneConfig defaults() { return LaneConfig{std::nullopt, LineConfig::defaults(), true}; }
+
+ std::optional label{};
+ std::optional line_config{};
+ bool plot_centerline = true; // alpha{};
+ std::optional color{};
+ bool fill{true};
+ std::optional linewidth{};
+ std::optional point_config{};
+};
+
+/**
+ * @brief plot the linestring by `axes.plot()`
+ * @param [in] config_opt argument for plotting the linestring. if valid, each field is used as the
+ * kwargs
+ */
+inline void plot_lanelet2_object(
+ const lanelet::ConstLineString3d & line, autoware::pyplot::Axes & axes,
+ const std::optional & config_opt = std::nullopt)
+{
+ py::dict kwargs{};
+ if (config_opt) {
+ const auto & config = config_opt.value();
+ if (config.color) {
+ kwargs["color"] = config.color.value();
+ }
+ if (config.linewidth) {
+ kwargs["linewidth"] = config.linewidth.value();
+ }
+ if (config.linestyle) {
+ kwargs["linestyle"] = config.linestyle.value();
+ }
+ if (config.label) {
+ kwargs["label"] = config.label.value();
+ }
+ }
+ std::vector xs;
+ for (const auto & p : line) {
+ xs.emplace_back(p.x());
+ }
+ std::vector ys;
+ for (const auto & p : line) {
+ ys.emplace_back(p.y());
+ }
+ axes.plot(Args(xs, ys), kwargs);
+}
+
+/**
+ * @brief plot the left/right bounds and optionally centerline
+ * @param [in] args used for plotting the left/right bounds as
+ */
+inline void plot_lanelet2_object(
+ const lanelet::ConstLanelet & lanelet, autoware::pyplot::Axes & axes,
+ const std::optional & config_opt = std::nullopt)
+{
+ const auto left = lanelet.leftBound();
+ const auto right = lanelet.rightBound();
+
+ const auto line_config = [&]() -> std::optional {
+ if (!config_opt) {
+ return LineConfig{std::string(LineConfig::default_color)};
+ }
+ return config_opt.value().line_config;
+ }();
+
+ if (config_opt) {
+ const auto & config = config_opt.value();
+
+ // plot lanelet centerline
+ if (config.plot_centerline) {
+ auto centerline_config = [&]() -> LineConfig {
+ if (!config.line_config) {
+ return LineConfig{"k", std::nullopt, "dashed"};
+ }
+ auto cfg = config.line_config.value();
+ cfg.color = "k";
+ cfg.linestyle = "dashed";
+ return cfg;
+ }();
+ plot_lanelet2_object(
+ lanelet.centerline(), axes, std::make_optional(std::move(centerline_config)));
+ }
+
+ // plot lanelet-id
+ const auto center = (left.front().basicPoint2d() + left.back().basicPoint2d() +
+ right.front().basicPoint2d() + right.back().basicPoint2d()) /
+ 4.0;
+ axes.text(Args(center.x(), center.y(), std::to_string(lanelet.id())));
+ }
+
+ if (config_opt && config_opt.value().label) {
+ auto left_line_config_for_legend = line_config ? line_config.value() : LineConfig::defaults();
+ left_line_config_for_legend.label = config_opt.value().label.value();
+
+ // plot left
+ plot_lanelet2_object(lanelet.leftBound(), axes, left_line_config_for_legend);
+
+ // plot right
+ plot_lanelet2_object(lanelet.rightBound(), axes, line_config);
+ } else {
+ // plot left
+ plot_lanelet2_object(lanelet.leftBound(), axes, line_config);
+
+ // plot right
+ plot_lanelet2_object(lanelet.rightBound(), axes, line_config);
+ }
+
+ // plot centerline direction
+ const auto centerline_size = lanelet.centerline().size();
+ const auto mid_index = centerline_size / 2;
+ const auto before = static_cast(std::max(0, mid_index - 1));
+ const auto after = static_cast(std::min(centerline_size - 1, mid_index + 1));
+ const auto p_before = lanelet.centerline()[before];
+ const auto p_after = lanelet.centerline()[after];
+ const double azimuth = std::atan2(p_after.y() - p_before.y(), p_after.x() - p_before.x());
+ const auto & mid = lanelet.centerline()[mid_index];
+ axes.quiver(
+ Args(mid.x(), mid.y(), std::cos(azimuth), std::sin(azimuth)), Kwargs("units"_a = "width"));
+}
+
+/**
+ * @brief plot the polygon as matplotlib.patches.Polygon
+ * @param [in] config_opt argument for plotting the polygon. if valid, each field is used as the
+ * kwargs
+ */
+inline void plot_lanelet2_object(
+ const lanelet::ConstPolygon3d & polygon, autoware::pyplot::Axes & axes,
+ const std::optional & config_opt = std::nullopt)
+{
+ std::vector> xy(polygon.size());
+ for (unsigned i = 0; i < polygon.size(); ++i) {
+ xy.at(i) = std::vector({polygon[i].x(), polygon[i].y()});
+ }
+ py::dict kwargs;
+ if (config_opt) {
+ const auto & config = config_opt.value();
+ if (config.alpha) {
+ kwargs["alpha"] = config.alpha.value();
+ }
+ if (config.color) {
+ kwargs["color"] = config.color.value();
+ }
+ kwargs["fill"] = config.fill;
+ if (config.linewidth) {
+ kwargs["linewidth"] = config.linewidth.value();
+ }
+ }
+ auto poly = autoware::pyplot::Polygon(Args(xy), kwargs);
+ axes.add_patch(Args(poly.unwrap()));
+}
+
+/**
+ * @brief plot the point by `axes.plot()`
+ * @param [in] config_opt argument for plotting the point. if valid, each field is used as the
+ * kwargs
+ */
+/*
+void plot_lanelet2_point(
+const lanelet::ConstPoint3d & point, autoware::pyplot::Axes & axes,
+const std::optional & config_opt = std::nullopt);
+*/
+} // namespace autoware::test_utils
+
+#endif // AUTOWARE_TEST_UTILS__VISUALIZATION_HPP_
diff --git a/common/autoware_test_utils/package.xml b/common/autoware_test_utils/package.xml
index 22572abb72b69..c328f37ba357d 100644
--- a/common/autoware_test_utils/package.xml
+++ b/common/autoware_test_utils/package.xml
@@ -23,6 +23,7 @@
autoware_map_msgs
autoware_perception_msgs
autoware_planning_msgs
+ autoware_pyplot
autoware_universe_utils
autoware_vehicle_msgs
lanelet2_io
diff --git a/common/autoware_test_utils/test_map/road_shoulder/lanelet2_map.osm b/common/autoware_test_utils/test_map/road_shoulder/lanelet2_map.osm
index 09c6297f83752..2c86dad61875f 100644
--- a/common/autoware_test_utils/test_map/road_shoulder/lanelet2_map.osm
+++ b/common/autoware_test_utils/test_map/road_shoulder/lanelet2_map.osm
@@ -1,6 +1,6 @@
-
+
@@ -2336,31 +2336,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -2771,316 +2746,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -3831,41 +3496,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -47975,9 +47605,9 @@
-
-
-
+
+
+
@@ -48018,8 +47648,8 @@
-
-
+
+
@@ -48053,9 +47683,9 @@
-
-
-
+
+
+
@@ -48108,19 +47738,19 @@
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
@@ -48128,15 +47758,15 @@
-
+
-
-
+
+
-
-
-
+
+
+
@@ -48180,9 +47810,9 @@
-
-
-
+
+
+
@@ -48243,14 +47873,14 @@
-
-
-
+
+
+
-
-
-
+
+
+
@@ -48258,9 +47888,9 @@
-
-
-
+
+
+
@@ -48333,9 +47963,9 @@
-
-
-
+
+
+
@@ -48343,6 +47973,71 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -49132,99 +48827,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -49658,17 +49260,6 @@
-
-
-
-
-
-
-
-
-
-
-
@@ -64187,15 +63778,6 @@
-
-
-
-
-
-
-
-
-
@@ -64239,19 +63821,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -64330,6 +63899,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -64478,7 +64063,7 @@
-
+
@@ -67744,15 +67329,14 @@
-
-
-
-
-
-
+
+
+
+
+
diff --git a/common/autoware_universe_utils/CMakeLists.txt b/common/autoware_universe_utils/CMakeLists.txt
index f295662e69091..72486b5de8818 100644
--- a/common/autoware_universe_utils/CMakeLists.txt
+++ b/common/autoware_universe_utils/CMakeLists.txt
@@ -21,6 +21,7 @@ ament_auto_add_library(autoware_universe_utils SHARED
src/geometry/sat_2d.cpp
src/math/sin_table.cpp
src/math/trigonometry.cpp
+ src/ros/diagnostics_interface.cpp
src/ros/msg_operation.cpp
src/ros/marker_helper.cpp
src/ros/logger_level_configure.cpp
diff --git a/common/autoware_universe_utils/include/autoware/universe_utils/ros/debug_traits.hpp b/common/autoware_universe_utils/include/autoware/universe_utils/ros/debug_traits.hpp
index 8420f930e0ce9..5878641676d9f 100644
--- a/common/autoware_universe_utils/include/autoware/universe_utils/ros/debug_traits.hpp
+++ b/common/autoware_universe_utils/include/autoware/universe_utils/ros/debug_traits.hpp
@@ -15,6 +15,16 @@
#ifndef AUTOWARE__UNIVERSE_UTILS__ROS__DEBUG_TRAITS_HPP_
#define AUTOWARE__UNIVERSE_UTILS__ROS__DEBUG_TRAITS_HPP_
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
#include
#include
#include
@@ -84,6 +94,58 @@ template <>
struct is_debug_message : std::true_type
{
};
+
+template <>
+struct is_debug_message : std::true_type
+{
+};
+
+template <>
+struct is_debug_message
+: std::true_type
+{
+};
+
+template <>
+struct is_debug_message : std::true_type
+{
+};
+
+template <>
+struct is_debug_message
+: std::true_type
+{
+};
+
+template <>
+struct is_debug_message : std::true_type
+{
+};
+
+template <>
+struct is_debug_message : std::true_type
+{
+};
+
+template <>
+struct is_debug_message : std::true_type
+{
+};
+
+template <>
+struct is_debug_message : std::true_type
+{
+};
+
+template <>
+struct is_debug_message : std::true_type
+{
+};
+
+template <>
+struct is_debug_message : std::true_type
+{
+};
} // namespace autoware::universe_utils::debug_traits
#endif // AUTOWARE__UNIVERSE_UTILS__ROS__DEBUG_TRAITS_HPP_
diff --git a/localization/autoware_localization_util/include/autoware/localization_util/diagnostics_module.hpp b/common/autoware_universe_utils/include/autoware/universe_utils/ros/diagnostics_interface.hpp
similarity index 70%
rename from localization/autoware_localization_util/include/autoware/localization_util/diagnostics_module.hpp
rename to common/autoware_universe_utils/include/autoware/universe_utils/ros/diagnostics_interface.hpp
index 8c19c94127630..db370eb46ef43 100644
--- a/localization/autoware_localization_util/include/autoware/localization_util/diagnostics_module.hpp
+++ b/common/autoware_universe_utils/include/autoware/universe_utils/ros/diagnostics_interface.hpp
@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef AUTOWARE__LOCALIZATION_UTIL__DIAGNOSTICS_MODULE_HPP_
-#define AUTOWARE__LOCALIZATION_UTIL__DIAGNOSTICS_MODULE_HPP_
+#ifndef AUTOWARE__UNIVERSE_UTILS__ROS__DIAGNOSTICS_INTERFACE_HPP_
+#define AUTOWARE__UNIVERSE_UTILS__ROS__DIAGNOSTICS_INTERFACE_HPP_
#include
@@ -22,16 +22,18 @@
#include
#include
-namespace autoware::localization_util
+namespace autoware::universe_utils
{
-class DiagnosticsModule
+class DiagnosticsInterface
{
public:
- DiagnosticsModule(rclcpp::Node * node, const std::string & diagnostic_name);
+ DiagnosticsInterface(rclcpp::Node * node, const std::string & diagnostic_name);
void clear();
void add_key_value(const diagnostic_msgs::msg::KeyValue & key_value_msg);
template
void add_key_value(const std::string & key, const T & value);
+ void add_key_value(const std::string & key, const std::string & value);
+ void add_key_value(const std::string & key, bool value);
void update_level_and_message(const int8_t level, const std::string & message);
void publish(const rclcpp::Time & publish_time_stamp);
@@ -46,7 +48,7 @@ class DiagnosticsModule
};
template
-void DiagnosticsModule::add_key_value(const std::string & key, const T & value)
+void DiagnosticsInterface::add_key_value(const std::string & key, const T & value)
{
diagnostic_msgs::msg::KeyValue key_value;
key_value.key = key;
@@ -54,11 +56,6 @@ void DiagnosticsModule::add_key_value(const std::string & key, const T & value)
add_key_value(key_value);
}
-template <>
-void DiagnosticsModule::add_key_value(const std::string & key, const std::string & value);
-template <>
-void DiagnosticsModule::add_key_value(const std::string & key, const bool & value);
+} // namespace autoware::universe_utils
-} // namespace autoware::localization_util
-
-#endif // AUTOWARE__LOCALIZATION_UTIL__DIAGNOSTICS_MODULE_HPP_
+#endif // AUTOWARE__UNIVERSE_UTILS__ROS__DIAGNOSTICS_INTERFACE_HPP_
diff --git a/common/autoware_universe_utils/package.xml b/common/autoware_universe_utils/package.xml
index d04e1a57e78ab..0e7b892a8c689 100644
--- a/common/autoware_universe_utils/package.xml
+++ b/common/autoware_universe_utils/package.xml
@@ -12,6 +12,7 @@
ament_cmake_auto
autoware_cmake
+ autoware_internal_debug_msgs
autoware_internal_msgs
autoware_perception_msgs
autoware_planning_msgs
diff --git a/localization/autoware_localization_util/src/diagnostics_module.cpp b/common/autoware_universe_utils/src/ros/diagnostics_interface.cpp
similarity index 76%
rename from localization/autoware_localization_util/src/diagnostics_module.cpp
rename to common/autoware_universe_utils/src/ros/diagnostics_interface.cpp
index 2b68dbf4f5890..e4d1ec8494113 100644
--- a/localization/autoware_localization_util/src/diagnostics_module.cpp
+++ b/common/autoware_universe_utils/src/ros/diagnostics_interface.cpp
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "autoware/localization_util/diagnostics_module.hpp"
+#include "autoware/universe_utils/ros/diagnostics_interface.hpp"
#include
@@ -21,9 +21,9 @@
#include
#include
-namespace autoware::localization_util
+namespace autoware::universe_utils
{
-DiagnosticsModule::DiagnosticsModule(rclcpp::Node * node, const std::string & diagnostic_name)
+DiagnosticsInterface::DiagnosticsInterface(rclcpp::Node * node, const std::string & diagnostic_name)
: clock_(node->get_clock())
{
diagnostics_pub_ =
@@ -34,7 +34,7 @@ DiagnosticsModule::DiagnosticsModule(rclcpp::Node * node, const std::string & di
diagnostics_status_msg_.hardware_id = node->get_name();
}
-void DiagnosticsModule::clear()
+void DiagnosticsInterface::clear()
{
diagnostics_status_msg_.values.clear();
diagnostics_status_msg_.values.shrink_to_fit();
@@ -43,7 +43,7 @@ void DiagnosticsModule::clear()
diagnostics_status_msg_.message = "";
}
-void DiagnosticsModule::add_key_value(const diagnostic_msgs::msg::KeyValue & key_value_msg)
+void DiagnosticsInterface::add_key_value(const diagnostic_msgs::msg::KeyValue & key_value_msg)
{
auto it = std::find_if(
std::begin(diagnostics_status_msg_.values), std::end(diagnostics_status_msg_.values),
@@ -56,8 +56,7 @@ void DiagnosticsModule::add_key_value(const diagnostic_msgs::msg::KeyValue & key
}
}
-template <>
-void DiagnosticsModule::add_key_value(const std::string & key, const std::string & value)
+void DiagnosticsInterface::add_key_value(const std::string & key, const std::string & value)
{
diagnostic_msgs::msg::KeyValue key_value;
key_value.key = key;
@@ -65,8 +64,7 @@ void DiagnosticsModule::add_key_value(const std::string & key, const std::string
add_key_value(key_value);
}
-template <>
-void DiagnosticsModule::add_key_value(const std::string & key, const bool & value)
+void DiagnosticsInterface::add_key_value(const std::string & key, bool value)
{
diagnostic_msgs::msg::KeyValue key_value;
key_value.key = key;
@@ -74,7 +72,7 @@ void DiagnosticsModule::add_key_value(const std::string & key, const bool & valu
add_key_value(key_value);
}
-void DiagnosticsModule::update_level_and_message(const int8_t level, const std::string & message)
+void DiagnosticsInterface::update_level_and_message(const int8_t level, const std::string & message)
{
if ((level > diagnostic_msgs::msg::DiagnosticStatus::OK)) {
if (!diagnostics_status_msg_.message.empty()) {
@@ -87,12 +85,12 @@ void DiagnosticsModule::update_level_and_message(const int8_t level, const std::
}
}
-void DiagnosticsModule::publish(const rclcpp::Time & publish_time_stamp)
+void DiagnosticsInterface::publish(const rclcpp::Time & publish_time_stamp)
{
diagnostics_pub_->publish(create_diagnostics_array(publish_time_stamp));
}
-diagnostic_msgs::msg::DiagnosticArray DiagnosticsModule::create_diagnostics_array(
+diagnostic_msgs::msg::DiagnosticArray DiagnosticsInterface::create_diagnostics_array(
const rclcpp::Time & publish_time_stamp) const
{
diagnostic_msgs::msg::DiagnosticArray diagnostics_msg;
@@ -105,4 +103,4 @@ diagnostic_msgs::msg::DiagnosticArray DiagnosticsModule::create_diagnostics_arra
return diagnostics_msg;
}
-} // namespace autoware::localization_util
+} // namespace autoware::universe_utils
diff --git a/common/autoware_universe_utils/test/src/math/test_trigonometry.cpp b/common/autoware_universe_utils/test/src/math/test_trigonometry.cpp
index df05b698693d6..5c8f96ddee67f 100644
--- a/common/autoware_universe_utils/test/src/math/test_trigonometry.cpp
+++ b/common/autoware_universe_utils/test/src/math/test_trigonometry.cpp
@@ -18,6 +18,7 @@
#include
#include
+#include
TEST(trigonometry, sin)
{
@@ -60,11 +61,15 @@ float normalize_angle(double angle)
TEST(trigonometry, opencv_fast_atan2)
{
+ std::random_device rd;
+ std::mt19937 gen(rd());
+
+ // Generate random x and y between -10.0 and 10.0 as float
+ std::uniform_real_distribution dis(-10.0f, 10.0f);
+
for (int i = 0; i < 100; ++i) {
- // Generate random x and y between -10 and 10
- std::srand(0);
- float x = static_cast(std::rand()) / RAND_MAX * 20.0 - 10.0;
- float y = static_cast(std::rand()) / RAND_MAX * 20.0 - 10.0;
+ const float x = dis(gen);
+ const float y = dis(gen);
float fast_atan = autoware::universe_utils::opencv_fast_atan2(y, x);
float std_atan = normalize_angle(std::atan2(y, x));
diff --git a/common/autoware_universe_utils/test/src/ros/test_diagnostics_interface.cpp b/common/autoware_universe_utils/test/src/ros/test_diagnostics_interface.cpp
new file mode 100644
index 0000000000000..6ec4fccf78b43
--- /dev/null
+++ b/common/autoware_universe_utils/test/src/ros/test_diagnostics_interface.cpp
@@ -0,0 +1,179 @@
+// Copyright 2024 Autoware Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "autoware/universe_utils/ros/diagnostics_interface.hpp"
+
+#include
+
+#include
+#include
+#include
+
+#include
+
+#include
+#include
+
+using autoware::universe_utils::DiagnosticsInterface;
+
+class TestDiagnosticsInterface : public ::testing::Test
+{
+protected:
+ void SetUp() override
+ {
+ // Create a test node
+ node_ = std::make_shared("test_diagnostics_interface");
+ }
+
+ // Automatically destroyed at the end of each test
+ std::shared_ptr node_;
+};
+
+/*
+ * Test clear():
+ * Verify that calling clear() resets DiagnosticStatus values, level, and message.
+ */
+TEST_F(TestDiagnosticsInterface, ClearTest)
+{
+ DiagnosticsInterface module(node_.get(), "test_diagnostic");
+
+ // Add some key-value pairs and update level/message
+ module.add_key_value("param1", 42);
+ module.update_level_and_message(
+ diagnostic_msgs::msg::DiagnosticStatus::WARN, "Something is not OK");
+
+ // Call clear()
+ module.clear();
+
+ // After calling clear(), publish and check the contents of the message
+ diagnostic_msgs::msg::DiagnosticArray::ConstSharedPtr received_msg;
+ auto sub = node_->create_subscription(
+ "/diagnostics", 10,
+ [&](diagnostic_msgs::msg::DiagnosticArray::ConstSharedPtr msg) { received_msg = msg; });
+
+ // Publish the message
+ module.publish(node_->now());
+
+ // Spin to allow the subscriber to receive messages
+ rclcpp::spin_some(node_);
+
+ ASSERT_NE(nullptr, received_msg);
+ ASSERT_FALSE(received_msg->status.empty());
+ const auto & status = received_msg->status.front();
+
+ // After clear(), key-value pairs should be empty
+ EXPECT_TRUE(status.values.empty());
+
+ // After clear(), level should be OK (=0)
+ EXPECT_EQ(status.level, diagnostic_msgs::msg::DiagnosticStatus::OK);
+
+ // After clear(), message is empty internally,
+ // but "OK" is set during publishing when level == OK
+ EXPECT_EQ(status.message, "OK");
+}
+
+/*
+ * Test add_key_value():
+ * Verify that adding the same key updates its value instead of adding a duplicate.
+ */
+TEST_F(TestDiagnosticsInterface, AddKeyValueTest)
+{
+ DiagnosticsInterface module(node_.get(), "test_diagnostic");
+
+ // Call the template version of add_key_value() with different types
+ module.add_key_value("string_key", std::string("initial_value"));
+ module.add_key_value("int_key", 123);
+ module.add_key_value("bool_key", true);
+
+ // Overwrite the value for "string_key"
+ module.add_key_value("string_key", std::string("updated_value"));
+
+ // Capture the published message to verify its contents
+ diagnostic_msgs::msg::DiagnosticArray::ConstSharedPtr received_msg;
+ auto sub = node_->create_subscription(
+ "/diagnostics", 10,
+ [&](diagnostic_msgs::msg::DiagnosticArray::ConstSharedPtr msg) { received_msg = msg; });
+ module.publish(node_->now());
+ rclcpp::spin_some(node_);
+
+ ASSERT_NE(nullptr, received_msg);
+ ASSERT_FALSE(received_msg->status.empty());
+ const auto & status = received_msg->status.front();
+
+ // Expect 3 key-value pairs
+ ASSERT_EQ(status.values.size(), 3U);
+
+ // Helper lambda to find a value by key
+ auto find_value = [&](const std::string & key) -> std::string {
+ for (const auto & kv : status.values) {
+ if (kv.key == key) {
+ return kv.value;
+ }
+ }
+ return "";
+ };
+
+ EXPECT_EQ(find_value("string_key"), "updated_value");
+ EXPECT_EQ(find_value("int_key"), "123");
+ EXPECT_EQ(find_value("bool_key"), "True");
+
+ // Status level should still be OK
+ EXPECT_EQ(status.level, diagnostic_msgs::msg::DiagnosticStatus::OK);
+ // Message should be "OK"
+ EXPECT_EQ(status.message, "OK");
+}
+
+/*
+ * Test update_level_and_message():
+ * Verify that the level is updated to the highest severity and
+ * that messages are concatenated if level > OK.
+ */
+TEST_F(TestDiagnosticsInterface, UpdateLevelAndMessageTest)
+{
+ DiagnosticsInterface module(node_.get(), "test_diagnostic");
+
+ // Initial status is level=OK(0), message=""
+ module.update_level_and_message(diagnostic_msgs::msg::DiagnosticStatus::OK, "Initial OK");
+ // Update to WARN (1)
+ module.update_level_and_message(diagnostic_msgs::msg::DiagnosticStatus::WARN, "Low battery");
+ // Update to ERROR (2)
+ module.update_level_and_message(diagnostic_msgs::msg::DiagnosticStatus::ERROR, "Sensor failure");
+ // Another WARN (1) after ERROR should not downgrade the overall level
+ module.update_level_and_message(
+ diagnostic_msgs::msg::DiagnosticStatus::WARN, "Should not override error");
+
+ diagnostic_msgs::msg::DiagnosticArray::ConstSharedPtr received_msg;
+ auto sub = node_->create_subscription(
+ "/diagnostics", 10,
+ [&](diagnostic_msgs::msg::DiagnosticArray::ConstSharedPtr msg) { received_msg = msg; });
+
+ module.publish(node_->now());
+ rclcpp::spin_some(node_);
+
+ ASSERT_NE(nullptr, received_msg);
+ ASSERT_FALSE(received_msg->status.empty());
+ const auto & status = received_msg->status.front();
+
+ // Final level should be ERROR (2)
+ EXPECT_EQ(status.level, diagnostic_msgs::msg::DiagnosticStatus::ERROR);
+
+ // The message should contain all parts that were added when level > OK.
+ // Thus, we expect something like:
+ // "Low battery; Sensor failure; Should not override error"
+ const std::string & final_message = status.message;
+ EXPECT_FALSE(final_message.find("Initial OK") != std::string::npos);
+ EXPECT_TRUE(final_message.find("Low battery") != std::string::npos);
+ EXPECT_TRUE(final_message.find("Sensor failure") != std::string::npos);
+ EXPECT_TRUE(final_message.find("Should not override error") != std::string::npos);
+}
diff --git a/control/autoware_mpc_lateral_controller/README.md b/control/autoware_mpc_lateral_controller/README.md
index 7585e7db140b3..a4b2fa3045a74 100644
--- a/control/autoware_mpc_lateral_controller/README.md
+++ b/control/autoware_mpc_lateral_controller/README.md
@@ -95,13 +95,11 @@ AutonomouStuff Lexus RX 450h for under 40 km/h driving.
#### System
-| Name | Type | Description | Default value |
-| :------------------------ | :------ | :-------------------------------------------------------------------------- | :------------ |
-| traj_resample_dist | double | distance of waypoints in resampling [m] | 0.1 |
-| use_steer_prediction | boolean | flag for using steer prediction (do not use steer measurement) | false |
-| admissible_position_error | double | stop vehicle when following position error is larger than this value [m] | 5.0 |
-| admissible_yaw_error_rad | double | stop vehicle when following yaw angle error is larger than this value [rad] | 1.57 |
-| use_delayed_initial_state | boolean | flag to use x0_delayed as initial state for predicted trajectory | true |
+| Name | Type | Description | Default value |
+| :------------------------ | :------ | :--------------------------------------------------------------- | :------------ |
+| traj_resample_dist | double | distance of waypoints in resampling [m] | 0.1 |
+| use_steer_prediction | boolean | flag for using steer prediction (do not use steer measurement) | false |
+| use_delayed_initial_state | boolean | flag to use x0_delayed as initial state for predicted trajectory | true |
#### Path Smoothing
diff --git a/control/autoware_mpc_lateral_controller/include/autoware/mpc_lateral_controller/mpc.hpp b/control/autoware_mpc_lateral_controller/include/autoware/mpc_lateral_controller/mpc.hpp
index 81c8b71683092..4c8d5df2c22a7 100644
--- a/control/autoware_mpc_lateral_controller/include/autoware/mpc_lateral_controller/mpc.hpp
+++ b/control/autoware_mpc_lateral_controller/include/autoware/mpc_lateral_controller/mpc.hpp
@@ -421,10 +421,8 @@ class MPC
double m_raw_steer_cmd_prev = 0.0; // Previous MPC raw output.
/* Parameters for control */
- double m_admissible_position_error; // Threshold for lateral error to trigger stop command [m].
- double m_admissible_yaw_error_rad; // Threshold for yaw error to trigger stop command [rad].
- double m_steer_lim; // Steering command limit [rad].
- double m_ctrl_period; // Control frequency [s].
+ double m_steer_lim; // Steering command limit [rad].
+ double m_ctrl_period; // Control frequency [s].
//!< @brief steering rate limit list depending on curvature [/m], [rad/s]
std::vector> m_steer_rate_lim_map_by_curvature{};
diff --git a/control/autoware_mpc_lateral_controller/include/autoware/mpc_lateral_controller/vehicle_model/vehicle_model_bicycle_kinematics.hpp b/control/autoware_mpc_lateral_controller/include/autoware/mpc_lateral_controller/vehicle_model/vehicle_model_bicycle_kinematics.hpp
index d638142daa844..015b4e6fad4d6 100644
--- a/control/autoware_mpc_lateral_controller/include/autoware/mpc_lateral_controller/vehicle_model/vehicle_model_bicycle_kinematics.hpp
+++ b/control/autoware_mpc_lateral_controller/include/autoware/mpc_lateral_controller/vehicle_model/vehicle_model_bicycle_kinematics.hpp
@@ -14,6 +14,7 @@
/*
* Representation
+ * k : reference curvature (input)
* e : lateral error
* th : heading angle error
* steer : steering angle
@@ -32,10 +33,12 @@
* dx3/dt = -(x3 - u) / tau
*
* Linearized model around reference point (v = v_r, th = th_r, steer = steer_r)
- * [0, vr, 0] [ 0] [ 0]
- * dx/dt = [0, 0, vr/W/cos(steer_r)^2] * x + [ 0] * u + [-vr*steer_r/W/cos(steer_r)^2]
- * [0, 0, 1/tau] [1/tau] [ 0]
+ * [0, vr, 0] [ 0] [ 0]
+ * dx/dt = [0, 0, B] * x + [ 0] * u + [-vr*k + A - B*steer_r]
+ * [0, 0, -1/tau] [1/tau] [ 0]
*
+ * where A = vr*tan(steer_r)/W
+ * B = vr/(W*cos(steer_r)^2) (partial derivative of A with respect to steer_r)
*/
#ifndef AUTOWARE__MPC_LATERAL_CONTROLLER__VEHICLE_MODEL__VEHICLE_MODEL_BICYCLE_KINEMATICS_HPP_
diff --git a/control/autoware_mpc_lateral_controller/model_predictive_control_algorithm.md b/control/autoware_mpc_lateral_controller/model_predictive_control_algorithm.md
index a1116d8a11c74..f28869bf950fb 100644
--- a/control/autoware_mpc_lateral_controller/model_predictive_control_algorithm.md
+++ b/control/autoware_mpc_lateral_controller/model_predictive_control_algorithm.md
@@ -365,10 +365,10 @@ and aligning the inequality signs
$$
\begin{align}
-u_{1} - u_{0} &< \dot u_{max}\text{d}t \\\ +
-u_{1} + u_{0} &< -\dot u_{min}\text{d}t \\\
-u_{2} - u_{1} &< \dot u_{max}\text{d}t \\\ +
-u_{2} + u_{1} &< - \dot u_{min}\text{d}t
+u_{1} - u_{0} &< \dot u_{max}\text{d}t \\\
+- u_{1} + u_{0} &< -\dot u_{min}\text{d}t \\\
+u_{2} - u_{1} &< \dot u_{max}\text{d}t \\\
+- u_{2} + u_{1} &< - \dot u_{min}\text{d}t
\end{align}
$$
diff --git a/control/autoware_mpc_lateral_controller/param/lateral_controller_defaults.param.yaml b/control/autoware_mpc_lateral_controller/param/lateral_controller_defaults.param.yaml
index b358e95f86f99..1d30a28d05cb8 100644
--- a/control/autoware_mpc_lateral_controller/param/lateral_controller_defaults.param.yaml
+++ b/control/autoware_mpc_lateral_controller/param/lateral_controller_defaults.param.yaml
@@ -3,8 +3,6 @@
# -- system --
traj_resample_dist: 0.1 # path resampling interval [m]
use_steer_prediction: false # flag for using steer prediction (do not use steer measurement)
- admissible_position_error: 5.0 # stop mpc calculation when error is larger than the following value
- admissible_yaw_error_rad: 1.57 # stop mpc calculation when error is larger than the following value
use_delayed_initial_state: true # flag to use x0_delayed as initial state for predicted trajectory
# -- path smoothing --
diff --git a/control/autoware_mpc_lateral_controller/src/mpc.cpp b/control/autoware_mpc_lateral_controller/src/mpc.cpp
index 4c3c8bec9b12e..49bf90b89bc90 100644
--- a/control/autoware_mpc_lateral_controller/src/mpc.cpp
+++ b/control/autoware_mpc_lateral_controller/src/mpc.cpp
@@ -307,17 +307,6 @@ std::pair MPC::getData(
// get predicted steer
data.predicted_steer = m_steering_predictor->calcSteerPrediction();
- // check error limit
- const double dist_err = calcDistance2d(current_pose, data.nearest_pose);
- if (dist_err > m_admissible_position_error) {
- return {ResultWithReason{false, "too large position error"}, MPCData{}};
- }
-
- // check yaw error limit
- if (std::fabs(data.yaw_err) > m_admissible_yaw_error_rad) {
- return {ResultWithReason{false, "too large yaw error"}, MPCData{}};
- }
-
// check trajectory time length
const double max_prediction_time =
m_param.min_prediction_length / static_cast(m_param.prediction_horizon - 1);
diff --git a/control/autoware_mpc_lateral_controller/src/mpc_lateral_controller.cpp b/control/autoware_mpc_lateral_controller/src/mpc_lateral_controller.cpp
index 76e5b4737e418..86d0c0143ed34 100644
--- a/control/autoware_mpc_lateral_controller/src/mpc_lateral_controller.cpp
+++ b/control/autoware_mpc_lateral_controller/src/mpc_lateral_controller.cpp
@@ -57,8 +57,6 @@ MpcLateralController::MpcLateralController(
p_filt.traj_resample_dist = dp_double("traj_resample_dist");
p_filt.extend_trajectory_for_end_yaw_control = dp_bool("extend_trajectory_for_end_yaw_control");
- m_mpc->m_admissible_position_error = dp_double("admissible_position_error");
- m_mpc->m_admissible_yaw_error_rad = dp_double("admissible_yaw_error_rad");
m_mpc->m_use_steer_prediction = dp_bool("use_steer_prediction");
m_mpc->m_param.steer_tau = dp_double("vehicle_model_steer_tau");
@@ -434,11 +432,18 @@ Lateral MpcLateralController::getInitialControlCommand() const
bool MpcLateralController::isStoppedState() const
{
+ const double current_vel = m_current_kinematic_state.twist.twist.linear.x;
// If the nearest index is not found, return false
- if (m_current_trajectory.points.empty()) {
+ if (
+ m_current_trajectory.points.empty() || std::fabs(current_vel) > m_stop_state_entry_ego_speed) {
return false;
}
+ const auto latest_published_cmd = m_ctrl_cmd_prev; // use prev_cmd as a latest published command
+ if (m_keep_steer_control_until_converged && !isSteerConverged(latest_published_cmd)) {
+ return false; // not stopState: keep control
+ }
+
// Note: This function used to take into account the distance to the stop line
// for the stop state judgement. However, it has been removed since the steering
// control was turned off when approaching/exceeding the stop line on a curve or
@@ -447,21 +452,23 @@ bool MpcLateralController::isStoppedState() const
m_current_trajectory.points, m_current_kinematic_state.pose.pose, m_ego_nearest_dist_threshold,
m_ego_nearest_yaw_threshold);
- const double current_vel = m_current_kinematic_state.twist.twist.linear.x;
- const double target_vel = m_current_trajectory.points.at(nearest).longitudinal_velocity_mps;
-
- const auto latest_published_cmd = m_ctrl_cmd_prev; // use prev_cmd as a latest published command
- if (m_keep_steer_control_until_converged && !isSteerConverged(latest_published_cmd)) {
- return false; // not stopState: keep control
- }
+ // It is possible that stop is executed earlier than stop point, and velocity controller
+ // will not start when the distance from ego to stop point is less than 0.5 meter.
+ // So we use a distance margin to ensure we can detect stopped state.
+ static constexpr double distance_margin = 1.0;
+ const double target_vel = std::invoke([&]() -> double {
+ auto min_vel = m_current_trajectory.points.at(nearest).longitudinal_velocity_mps;
+ auto covered_distance = 0.0;
+ for (auto i = nearest + 1; i < m_current_trajectory.points.size(); ++i) {
+ min_vel = std::min(min_vel, m_current_trajectory.points.at(i).longitudinal_velocity_mps);
+ covered_distance += autoware::universe_utils::calcDistance2d(
+ m_current_trajectory.points.at(i - 1).pose, m_current_trajectory.points.at(i).pose);
+ if (covered_distance > distance_margin) break;
+ }
+ return min_vel;
+ });
- if (
- std::fabs(current_vel) < m_stop_state_entry_ego_speed &&
- std::fabs(target_vel) < m_stop_state_entry_target_speed) {
- return true;
- } else {
- return false;
- }
+ return std::fabs(target_vel) < m_stop_state_entry_target_speed;
}
Lateral MpcLateralController::createCtrlCmdMsg(const Lateral & ctrl_cmd)
diff --git a/control/autoware_mpc_lateral_controller/test/test_mpc.cpp b/control/autoware_mpc_lateral_controller/test/test_mpc.cpp
index ccc91d0e7751b..9c30369305f6e 100644
--- a/control/autoware_mpc_lateral_controller/test/test_mpc.cpp
+++ b/control/autoware_mpc_lateral_controller/test/test_mpc.cpp
@@ -96,8 +96,6 @@ class MPCTest : public ::testing::Test
double error_deriv_lpf_cutoff_hz = 5.0;
// Test Parameters
- double admissible_position_error = 5.0;
- double admissible_yaw_error_rad = M_PI_2;
double steer_lim = 0.610865; // 35 degrees
double steer_rate_lim = 2.61799; // 150 degrees
double ctrl_period = 0.03;
@@ -162,8 +160,6 @@ class MPCTest : public ::testing::Test
void initializeMPC(mpc_lateral_controller::MPC & mpc)
{
mpc.m_param = param;
- mpc.m_admissible_position_error = admissible_position_error;
- mpc.m_admissible_yaw_error_rad = admissible_yaw_error_rad;
mpc.m_steer_lim = steer_lim;
mpc.m_steer_rate_lim_map_by_curvature.emplace_back(0.0, steer_rate_lim);
mpc.m_steer_rate_lim_map_by_velocity.emplace_back(0.0, steer_rate_lim);
@@ -480,37 +476,4 @@ TEST_F(MPCTest, MultiSolveWithBuffer)
EXPECT_EQ(ctrl_cmd_horizon.controls.front().steering_tire_angle, 0.0f);
EXPECT_EQ(ctrl_cmd_horizon.controls.front().steering_tire_rotation_rate, 0.0f);
}
-
-TEST_F(MPCTest, FailureCases)
-{
- auto node = rclcpp::Node("mpc_test_node", rclcpp::NodeOptions{});
- auto mpc = std::make_unique(node);
- std::shared_ptr vehicle_model_ptr =
- std::make_shared(wheelbase, steer_limit, steer_tau);
- mpc->setVehicleModel(vehicle_model_ptr);
- std::shared_ptr qpsolver_ptr = std::make_shared();
- mpc->setQPSolver(qpsolver_ptr);
-
- // Init parameters and reference trajectory
- initializeMPC(*mpc);
-
- // Calculate MPC with a pose too far from the trajectory
- Pose pose_far;
- pose_far.position.x = pose_zero.position.x - admissible_position_error - 1.0;
- pose_far.position.y = pose_zero.position.y - admissible_position_error - 1.0;
- Lateral ctrl_cmd;
- Trajectory pred_traj;
- Float32MultiArrayStamped diag;
- LateralHorizon ctrl_cmd_horizon;
- const auto odom = makeOdometry(pose_far, default_velocity);
- EXPECT_FALSE(
- mpc->calculateMPC(neutral_steer, odom, ctrl_cmd, pred_traj, diag, ctrl_cmd_horizon).result);
-
- // Calculate MPC with a fast velocity to make the prediction go further than the reference path
- EXPECT_FALSE(mpc
- ->calculateMPC(
- neutral_steer, makeOdometry(pose_far, default_velocity + 10.0), ctrl_cmd,
- pred_traj, diag, ctrl_cmd_horizon)
- .result);
-}
} // namespace autoware::motion::control::mpc_lateral_controller
diff --git a/control/autoware_pid_longitudinal_controller/README.md b/control/autoware_pid_longitudinal_controller/README.md
index b147b3b795391..aba0f36f04d65 100644
--- a/control/autoware_pid_longitudinal_controller/README.md
+++ b/control/autoware_pid_longitudinal_controller/README.md
@@ -68,6 +68,8 @@ There are two sources of the slope information, which can be switched by a param
- Cons: z-coordinates of high-precision map is needed.
- Cons: Does not support free space planning (for now)
+We also offer the options to switch between these, depending on driving conditions.
+
**Notation:** This function works correctly only in a vehicle system that does not have acceleration feedback in the low-level control system.
This compensation adds gravity correction to the target acceleration, resulting in an output value that is no longer equal to the target acceleration that the autonomous driving system desires. Therefore, it conflicts with the role of the acceleration feedback in the low-level controller.
diff --git a/control/autoware_pid_longitudinal_controller/config/autoware_pid_longitudinal_controller.param.yaml b/control/autoware_pid_longitudinal_controller/config/autoware_pid_longitudinal_controller.param.yaml
index 6d9b93ab98870..ec6a6f11b437d 100644
--- a/control/autoware_pid_longitudinal_controller/config/autoware_pid_longitudinal_controller.param.yaml
+++ b/control/autoware_pid_longitudinal_controller/config/autoware_pid_longitudinal_controller.param.yaml
@@ -16,8 +16,6 @@
stopped_state_entry_vel: 0.01
stopped_state_entry_acc: 0.1
emergency_state_overshoot_stop_dist: 1.5
- emergency_state_traj_trans_dev: 3.0
- emergency_state_traj_rot_dev: 0.7854
# drive state
kp: 1.0
@@ -76,7 +74,7 @@
# slope compensation
lpf_pitch_gain: 0.95
- slope_source: "raw_pitch" # raw_pitch, trajectory_pitch or trajectory_adaptive
+ slope_source: "trajectory_goal_adaptive" # raw_pitch, trajectory_pitch, trajectory_adaptive or trajectory_goal_adaptive
adaptive_trajectory_velocity_th: 1.0
max_pitch_rad: 0.1
min_pitch_rad: -0.1
diff --git a/control/autoware_pid_longitudinal_controller/include/autoware/pid_longitudinal_controller/debug_values.hpp b/control/autoware_pid_longitudinal_controller/include/autoware/pid_longitudinal_controller/debug_values.hpp
index a0bceda625b21..e1cc4d2fd1690 100644
--- a/control/autoware_pid_longitudinal_controller/include/autoware/pid_longitudinal_controller/debug_values.hpp
+++ b/control/autoware_pid_longitudinal_controller/include/autoware/pid_longitudinal_controller/debug_values.hpp
@@ -34,9 +34,9 @@ class DebugValues
NEAREST_VEL = 4,
NEAREST_ACC = 5,
SHIFT = 6,
- PITCH_LPF_RAD = 7,
+ PITCH_USING_RAD = 7,
PITCH_RAW_RAD = 8,
- PITCH_LPF_DEG = 9,
+ PITCH_USING_DEG = 9,
PITCH_RAW_DEG = 10,
ERROR_VEL = 11,
ERROR_VEL_FILTERED = 12,
@@ -61,6 +61,9 @@ class DebugValues
ERROR_ACC = 31,
ERROR_ACC_FILTERED = 32,
ACC_CMD_ACC_FB_APPLIED = 33,
+ PITCH_LPF_RAD = 34,
+ PITCH_LPF_DEG = 35,
+ SMOOTH_STOP_MODE = 36,
SIZE // this is the number of enum elements
};
@@ -76,6 +79,9 @@ class DebugValues
* @return array of all debug values
*/
std::array(TYPE::SIZE)> getValues() const { return m_values; }
+ double getValue(const size_t index) const { return m_values.at(index); }
+ double getValue(const TYPE type) const { return m_values.at(static_cast(type)); }
+
/**
* @brief set the given type to the given value
* @param [in] type TYPE of the value
diff --git a/control/autoware_pid_longitudinal_controller/include/autoware/pid_longitudinal_controller/pid_longitudinal_controller.hpp b/control/autoware_pid_longitudinal_controller/include/autoware/pid_longitudinal_controller/pid_longitudinal_controller.hpp
index 7daf3013bab4a..1d03d1b339af6 100644
--- a/control/autoware_pid_longitudinal_controller/include/autoware/pid_longitudinal_controller/pid_longitudinal_controller.hpp
+++ b/control/autoware_pid_longitudinal_controller/include/autoware/pid_longitudinal_controller/pid_longitudinal_controller.hpp
@@ -50,11 +50,8 @@
namespace autoware::motion::control::pid_longitudinal_controller
{
-using autoware::universe_utils::createDefaultMarker;
-using autoware::universe_utils::createMarkerColor;
-using autoware::universe_utils::createMarkerScale;
using autoware_adapi_v1_msgs::msg::OperationModeState;
-using visualization_msgs::msg::Marker;
+using visualization_msgs::msg::MarkerArray;
namespace trajectory_follower = ::autoware::motion::control::trajectory_follower;
@@ -87,7 +84,6 @@ class PidLongitudinalController : public trajectory_follower::LongitudinalContro
struct ControlData
{
- bool is_far_from_trajectory{false};
autoware_planning_msgs::msg::Trajectory interpolated_traj{};
size_t nearest_idx{0}; // nearest_idx = 0 when nearest_idx is not found with findNearestIdx
size_t target_idx{0};
@@ -104,7 +100,7 @@ class PidLongitudinalController : public trajectory_follower::LongitudinalContro
// ros variables
rclcpp::Publisher::SharedPtr m_pub_slope;
rclcpp::Publisher::SharedPtr m_pub_debug;
- rclcpp::Publisher::SharedPtr m_pub_stop_reason_marker;
+ rclcpp::Publisher::SharedPtr m_pub_virtual_wall_marker;
rclcpp::Node::OnSetParametersCallbackHandle::SharedPtr m_set_param_res;
rcl_interfaces::msg::SetParametersResult paramCallback(
@@ -162,8 +158,6 @@ class PidLongitudinalController : public trajectory_follower::LongitudinalContro
double stopped_state_entry_acc;
// emergency
double emergency_state_overshoot_stop_dist;
- double emergency_state_traj_trans_dev;
- double emergency_state_traj_rot_dev;
};
StateTransitionParams m_state_transition_params;
@@ -210,12 +204,18 @@ class PidLongitudinalController : public trajectory_follower::LongitudinalContro
double m_max_acc_cmd_diff;
// slope compensation
- enum class SlopeSource { RAW_PITCH = 0, TRAJECTORY_PITCH, TRAJECTORY_ADAPTIVE };
+ enum class SlopeSource {
+ RAW_PITCH = 0,
+ TRAJECTORY_PITCH,
+ TRAJECTORY_ADAPTIVE,
+ TRAJECTORY_GOAL_ADAPTIVE
+ };
SlopeSource m_slope_source{SlopeSource::RAW_PITCH};
double m_adaptive_trajectory_velocity_th;
std::shared_ptr m_lpf_pitch{nullptr};
double m_max_pitch_rad;
double m_min_pitch_rad;
+ std::optional m_previous_slope_angle{std::nullopt};
// ego nearest index search
double m_ego_nearest_dist_threshold;
@@ -245,12 +245,6 @@ class PidLongitudinalController : public trajectory_follower::LongitudinalContro
// Diagnostic
std::shared_ptr
diag_updater_{}; // Diagnostic updater for publishing diagnostic data.
- struct DiagnosticData
- {
- double trans_deviation{0.0}; // translation deviation between nearest point and current_pose
- double rot_deviation{0.0}; // rotation deviation between nearest point and current_pose
- };
- DiagnosticData m_diagnostic_data;
void setupDiagnosticUpdater();
void checkControlState(diagnostic_updater::DiagnosticStatusWrapper & stat);
@@ -411,11 +405,14 @@ class PidLongitudinalController : public trajectory_follower::LongitudinalContro
/**
* @brief update variables for debugging about pitch
- * @param [in] pitch current pitch of the vehicle (filtered)
- * @param [in] traj_pitch current trajectory pitch
- * @param [in] raw_pitch current raw pitch of the vehicle (unfiltered)
+ * @param [in] pitch_using
+ * @param [in] traj_pitch
+ * @param [in] localization_pitch
+ * @param [in] localization_pitch_lpf
*/
- void updatePitchDebugValues(const double pitch, const double traj_pitch, const double raw_pitch);
+ void updatePitchDebugValues(
+ const double pitch_using, const double traj_pitch, const double localization_pitch,
+ const double localization_pitch_lpf);
/**
* @brief update variables for velocity and acceleration
diff --git a/control/autoware_pid_longitudinal_controller/include/autoware/pid_longitudinal_controller/smooth_stop.hpp b/control/autoware_pid_longitudinal_controller/include/autoware/pid_longitudinal_controller/smooth_stop.hpp
index e84b44d95c886..8f8fc57e278ef 100644
--- a/control/autoware_pid_longitudinal_controller/include/autoware/pid_longitudinal_controller/smooth_stop.hpp
+++ b/control/autoware_pid_longitudinal_controller/include/autoware/pid_longitudinal_controller/smooth_stop.hpp
@@ -15,6 +15,7 @@
#ifndef AUTOWARE__PID_LONGITUDINAL_CONTROLLER__SMOOTH_STOP_HPP_
#define AUTOWARE__PID_LONGITUDINAL_CONTROLLER__SMOOTH_STOP_HPP_
+#include "autoware/pid_longitudinal_controller/debug_values.hpp"
#include "rclcpp/rclcpp.hpp"
#include // NOLINT
@@ -85,7 +86,8 @@ class SmoothStop
*/
double calculate(
const double stop_dist, const double current_vel, const double current_acc,
- const std::vector> & vel_hist, const double delay_time);
+ const std::vector> & vel_hist, const double delay_time,
+ DebugValues & debug_values);
private:
struct Params
@@ -106,6 +108,8 @@ class SmoothStop
};
Params m_params;
+ enum class Mode { STRONG = 0, WEAK, WEAK_STOP, STRONG_STOP };
+
double m_strong_acc;
rclcpp::Time m_weak_acc_time;
bool m_is_set_params = false;
diff --git a/control/autoware_pid_longitudinal_controller/media/LongitudinalControllerStateTransition.drawio.svg b/control/autoware_pid_longitudinal_controller/media/LongitudinalControllerStateTransition.drawio.svg
index 88ac881f4f43c..f669b647dbf84 100644
--- a/control/autoware_pid_longitudinal_controller/media/LongitudinalControllerStateTransition.drawio.svg
+++ b/control/autoware_pid_longitudinal_controller/media/LongitudinalControllerStateTransition.drawio.svg
@@ -175,7 +175,7 @@
: For 500 [ms], self velocity is smaller than C1, and self acceleration is smaller than C2.
emergency condition
- : Speed command is zero velocity, and distance to stop is smaller than D1, or self pose is not within D2, D3 from trajectory.
+ : Speed command is zero velocity, and distance to stop is smaller than D1.
@@ -315,10 +315,6 @@
C2 : stopped_state_entry_acc
D1 : emergency_state_overshoot_stop_dist
-
- D2 : emergency_state_traj_trans_dev
-
- D3 : emergency_state_traj_rot_dev
diff --git a/control/autoware_pid_longitudinal_controller/schema/autoware_pid_longitudinal_controller.schema.json b/control/autoware_pid_longitudinal_controller/schema/autoware_pid_longitudinal_controller.schema.json
index ef1272582e52b..14a34f04458eb 100644
--- a/control/autoware_pid_longitudinal_controller/schema/autoware_pid_longitudinal_controller.schema.json
+++ b/control/autoware_pid_longitudinal_controller/schema/autoware_pid_longitudinal_controller.schema.json
@@ -71,16 +71,6 @@
"description": "If `enable_overshoot_emergency` is true and the ego is `emergency_state_overshoot_stop_dist`-meter ahead of the stop point, the state will transit to EMERGENCY. [m]",
"default": "1.5"
},
- "emergency_state_traj_trans_dev": {
- "type": "number",
- "description": "If the ego's position is `emergency_state_traj_trans_dev` meter away from the nearest trajectory point, the state will transit to EMERGENCY. [m]",
- "default": "3.0"
- },
- "emergency_state_traj_rot_dev": {
- "type": "number",
- "description": "If the ego's orientation is `emergency_state_traj_rot_dev` rad away from the nearest trajectory point orientation, the state will transit to EMERGENCY. [rad]",
- "default": "0.7854"
- },
"kp": {
"type": "number",
"description": "p gain for longitudinal control",
@@ -326,8 +316,6 @@
"stopped_state_entry_vel",
"stopped_state_entry_acc",
"emergency_state_overshoot_stop_dist",
- "emergency_state_traj_trans_dev",
- "emergency_state_traj_rot_dev",
"kp",
"ki",
"kd",
diff --git a/control/autoware_pid_longitudinal_controller/src/pid_longitudinal_controller.cpp b/control/autoware_pid_longitudinal_controller/src/pid_longitudinal_controller.cpp
index 7f6da35527290..ec95ce656fa6f 100644
--- a/control/autoware_pid_longitudinal_controller/src/pid_longitudinal_controller.cpp
+++ b/control/autoware_pid_longitudinal_controller/src/pid_longitudinal_controller.cpp
@@ -14,6 +14,7 @@
#include "autoware/pid_longitudinal_controller/pid_longitudinal_controller.hpp"
+#include "autoware/motion_utils/marker/marker_helper.hpp"
#include "autoware/motion_utils/trajectory/trajectory.hpp"
#include "autoware/universe_utils/geometry/geometry.hpp"
#include "autoware/universe_utils/math/normalization.hpp"
@@ -79,10 +80,6 @@ PidLongitudinalController::PidLongitudinalController(
// emergency
p.emergency_state_overshoot_stop_dist =
node.declare_parameter("emergency_state_overshoot_stop_dist"); // [m]
- p.emergency_state_traj_trans_dev =
- node.declare_parameter("emergency_state_traj_trans_dev"); // [m]
- p.emergency_state_traj_rot_dev =
- node.declare_parameter("emergency_state_traj_rot_dev"); // [m]
}
// parameters for drive state
@@ -199,6 +196,8 @@ PidLongitudinalController::PidLongitudinalController(
m_slope_source = SlopeSource::TRAJECTORY_PITCH;
} else if (slope_source == "trajectory_adaptive") {
m_slope_source = SlopeSource::TRAJECTORY_ADAPTIVE;
+ } else if (slope_source == "trajectory_goal_adaptive") {
+ m_slope_source = SlopeSource::TRAJECTORY_GOAL_ADAPTIVE;
} else {
RCLCPP_ERROR(logger_, "Slope source is not valid. Using raw_pitch option as default");
m_slope_source = SlopeSource::RAW_PITCH;
@@ -219,7 +218,7 @@ PidLongitudinalController::PidLongitudinalController(
"~/output/slope_angle", rclcpp::QoS{1});
m_pub_debug = node.create_publisher(
"~/output/longitudinal_diagnostic", rclcpp::QoS{1});
- m_pub_stop_reason_marker = node.create_publisher("~/output/stop_reason", rclcpp::QoS{1});
+ m_pub_virtual_wall_marker = node.create_publisher("~/virtual_wall", 1);
// set parameter callback
m_set_param_res = node.add_on_set_parameters_callback(
@@ -286,8 +285,6 @@ rcl_interfaces::msg::SetParametersResult PidLongitudinalController::paramCallbac
update_param("stopped_state_entry_vel", p.stopped_state_entry_vel);
update_param("stopped_state_entry_acc", p.stopped_state_entry_acc);
update_param("emergency_state_overshoot_stop_dist", p.emergency_state_overshoot_stop_dist);
- update_param("emergency_state_traj_trans_dev", p.emergency_state_traj_trans_dev);
- update_param("emergency_state_traj_rot_dev", p.emergency_state_traj_rot_dev);
}
// drive state
@@ -423,24 +420,6 @@ trajectory_follower::LongitudinalOutput PidLongitudinalController::run(
const auto control_data = getControlData(current_pose);
- // self pose is far from trajectory
- if (control_data.is_far_from_trajectory) {
- if (m_enable_large_tracking_error_emergency) {
- // update control state
- changeControlState(ControlState::EMERGENCY, "the tracking error is too large");
- }
- const Motion raw_ctrl_cmd = calcEmergencyCtrlCmd(control_data.dt); // calculate control command
- m_prev_raw_ctrl_cmd = raw_ctrl_cmd;
- const auto cmd_msg =
- createCtrlCmdMsg(raw_ctrl_cmd, control_data.current_motion.vel); // create control command
- publishDebugData(raw_ctrl_cmd, control_data); // publish debug data
- trajectory_follower::LongitudinalOutput output;
- output.control_cmd = cmd_msg;
- output.control_cmd_horizon.controls.push_back(cmd_msg);
- output.control_cmd_horizon.time_step_ms = 0.0;
- return output;
- }
-
// update control state
updateControlState(control_data);
@@ -491,23 +470,6 @@ PidLongitudinalController::ControlData PidLongitudinalController::getControlData
const auto nearest_point = current_interpolated_pose.first;
auto target_point = current_interpolated_pose.first;
- // check if the deviation is worth emergency
- m_diagnostic_data.trans_deviation =
- autoware::universe_utils::calcDistance2d(current_interpolated_pose.first, current_pose);
- const bool is_dist_deviation_large =
- m_state_transition_params.emergency_state_traj_trans_dev < m_diagnostic_data.trans_deviation;
- m_diagnostic_data.rot_deviation = std::abs(autoware::universe_utils::normalizeRadian(
- tf2::getYaw(current_interpolated_pose.first.pose.orientation) -
- tf2::getYaw(current_pose.orientation)));
- const bool is_yaw_deviation_large =
- m_state_transition_params.emergency_state_traj_rot_dev < m_diagnostic_data.rot_deviation;
-
- if (is_dist_deviation_large || is_yaw_deviation_large) {
- // return here if nearest index is not found
- control_data.is_far_from_trajectory = true;
- return control_data;
- }
-
// Delay compensation - Calculate the distance we got, predicted velocity and predicted
// acceleration after delay
control_data.state_after_delay =
@@ -562,35 +524,52 @@ PidLongitudinalController::ControlData PidLongitudinalController::getControlData
// distance to stopline
control_data.stop_dist = longitudinal_utils::calcStopDistance(
- control_data.interpolated_traj.points.at(control_data.nearest_idx).pose,
- control_data.interpolated_traj, m_ego_nearest_dist_threshold, m_ego_nearest_yaw_threshold);
+ current_pose, control_data.interpolated_traj, m_ego_nearest_dist_threshold,
+ m_ego_nearest_yaw_threshold);
// pitch
// NOTE: getPitchByTraj() calculates the pitch angle as defined in
// ../media/slope_definition.drawio.svg while getPitchByPose() is not, so `raw_pitch` is reversed
const double raw_pitch = (-1.0) * longitudinal_utils::getPitchByPose(current_pose.orientation);
+ m_lpf_pitch->filter(raw_pitch);
const double traj_pitch = longitudinal_utils::getPitchByTraj(
control_data.interpolated_traj, control_data.target_idx, m_wheel_base);
if (m_slope_source == SlopeSource::RAW_PITCH) {
- control_data.slope_angle = m_lpf_pitch->filter(raw_pitch);
+ control_data.slope_angle = m_lpf_pitch->getValue();
} else if (m_slope_source == SlopeSource::TRAJECTORY_PITCH) {
control_data.slope_angle = traj_pitch;
- } else if (m_slope_source == SlopeSource::TRAJECTORY_ADAPTIVE) {
+ } else if (
+ m_slope_source == SlopeSource::TRAJECTORY_ADAPTIVE ||
+ m_slope_source == SlopeSource::TRAJECTORY_GOAL_ADAPTIVE) {
// if velocity is high, use target idx for slope, otherwise, use raw_pitch
- if (control_data.current_motion.vel > m_adaptive_trajectory_velocity_th) {
- control_data.slope_angle = traj_pitch;
- m_lpf_pitch->filter(raw_pitch);
- } else {
- control_data.slope_angle = m_lpf_pitch->filter(raw_pitch);
+ const bool is_vel_slow = control_data.current_motion.vel < m_adaptive_trajectory_velocity_th &&
+ m_slope_source == SlopeSource::TRAJECTORY_ADAPTIVE;
+
+ const double goal_dist = autoware::motion_utils::calcSignedArcLength(
+ control_data.interpolated_traj.points, current_pose.position,
+ control_data.interpolated_traj.points.size() - 1);
+ const bool is_close_to_trajectory_end =
+ goal_dist < m_wheel_base && m_slope_source == SlopeSource::TRAJECTORY_GOAL_ADAPTIVE;
+
+ control_data.slope_angle =
+ (is_close_to_trajectory_end || is_vel_slow) ? m_lpf_pitch->getValue() : traj_pitch;
+
+ if (m_previous_slope_angle.has_value()) {
+ constexpr double gravity_const = 9.8;
+ control_data.slope_angle = std::clamp(
+ control_data.slope_angle,
+ m_previous_slope_angle.value() + m_min_jerk * control_data.dt / gravity_const,
+ m_previous_slope_angle.value() + m_max_jerk * control_data.dt / gravity_const);
}
+ m_previous_slope_angle = control_data.slope_angle;
} else {
RCLCPP_ERROR_THROTTLE(
logger_, *clock_, 3000, "Slope source is not valid. Using raw_pitch option as default");
- control_data.slope_angle = m_lpf_pitch->filter(raw_pitch);
+ control_data.slope_angle = m_lpf_pitch->getValue();
}
- updatePitchDebugValues(control_data.slope_angle, traj_pitch, raw_pitch);
+ updatePitchDebugValues(control_data.slope_angle, traj_pitch, raw_pitch, m_lpf_pitch->getValue());
return control_data;
}
@@ -609,6 +588,11 @@ PidLongitudinalController::Motion PidLongitudinalController::calcEmergencyCtrlCm
longitudinal_utils::applyDiffLimitFilter(raw_ctrl_cmd.acc, m_prev_raw_ctrl_cmd.acc, dt, p.jerk);
m_debug_values.setValues(DebugValues::TYPE::ACC_CMD_JERK_LIMITED, raw_ctrl_cmd.acc);
+ const auto virtual_wall_marker = autoware::motion_utils::createStopVirtualWallMarker(
+ m_current_kinematic_state.pose.pose, "velocity control\n (emergency)", clock_->now(), 0,
+ m_wheel_base + m_front_overhang);
+ m_pub_virtual_wall_marker->publish(virtual_wall_marker);
+
return raw_ctrl_cmd;
}
@@ -773,14 +757,12 @@ void PidLongitudinalController::updateControlState(const ControlData & control_d
}
// publish debug marker
- auto marker = createDefaultMarker(
- "map", clock_->now(), "stop_reason", 0, Marker::TEXT_VIEW_FACING,
- createMarkerScale(0.0, 0.0, 1.0), createMarkerColor(1.0, 1.0, 1.0, 0.999));
- marker.pose = autoware::universe_utils::calcOffsetPose(
- m_current_kinematic_state.pose.pose, m_wheel_base + m_front_overhang,
- m_vehicle_width / 2 + 2.0, 1.5);
- marker.text = "steering not\nconverged";
- m_pub_stop_reason_marker->publish(marker);
+ if (is_under_control) {
+ const auto virtual_wall_marker = autoware::motion_utils::createStopVirtualWallMarker(
+ m_current_kinematic_state.pose.pose, "velocity control\n(steering not converged)",
+ clock_->now(), 0, m_wheel_base + m_front_overhang);
+ m_pub_virtual_wall_marker->publish(virtual_wall_marker);
+ }
// keep STOPPED
return;
@@ -863,7 +845,7 @@ PidLongitudinalController::Motion PidLongitudinalController::calcCtrlCmd(
} else if (m_control_state == ControlState::STOPPING) {
raw_ctrl_cmd.acc = m_smooth_stop.calculate(
control_data.stop_dist, control_data.current_motion.vel, control_data.current_motion.acc,
- m_vel_hist, m_delay_compensation_time);
+ m_vel_hist, m_delay_compensation_time, m_debug_values);
raw_ctrl_cmd.vel = m_stopped_state_params.vel;
RCLCPP_DEBUG(
@@ -1189,13 +1171,16 @@ double PidLongitudinalController::applyVelocityFeedback(const ControlData & cont
}
void PidLongitudinalController::updatePitchDebugValues(
- const double pitch, const double traj_pitch, const double raw_pitch)
+ const double pitch_using, const double traj_pitch, const double localization_pitch,
+ const double localization_pitch_lpf)
{
const double to_degrees = (180.0 / static_cast(M_PI));
- m_debug_values.setValues(DebugValues::TYPE::PITCH_LPF_RAD, pitch);
- m_debug_values.setValues(DebugValues::TYPE::PITCH_LPF_DEG, pitch * to_degrees);
- m_debug_values.setValues(DebugValues::TYPE::PITCH_RAW_RAD, raw_pitch);
- m_debug_values.setValues(DebugValues::TYPE::PITCH_RAW_DEG, raw_pitch * to_degrees);
+ m_debug_values.setValues(DebugValues::TYPE::PITCH_USING_RAD, pitch_using);
+ m_debug_values.setValues(DebugValues::TYPE::PITCH_USING_DEG, pitch_using * to_degrees);
+ m_debug_values.setValues(DebugValues::TYPE::PITCH_LPF_RAD, localization_pitch_lpf);
+ m_debug_values.setValues(DebugValues::TYPE::PITCH_LPF_DEG, localization_pitch_lpf * to_degrees);
+ m_debug_values.setValues(DebugValues::TYPE::PITCH_RAW_RAD, localization_pitch);
+ m_debug_values.setValues(DebugValues::TYPE::PITCH_RAW_DEG, localization_pitch * to_degrees);
m_debug_values.setValues(DebugValues::TYPE::PITCH_RAW_TRAJ_RAD, traj_pitch);
m_debug_values.setValues(DebugValues::TYPE::PITCH_RAW_TRAJ_DEG, traj_pitch * to_degrees);
}
@@ -1239,23 +1224,7 @@ void PidLongitudinalController::checkControlState(
msg = "emergency occurred due to ";
}
- if (
- m_state_transition_params.emergency_state_traj_trans_dev < m_diagnostic_data.trans_deviation) {
- msg += "translation deviation";
- }
-
- if (m_state_transition_params.emergency_state_traj_rot_dev < m_diagnostic_data.rot_deviation) {
- msg += "rotation deviation";
- }
-
stat.add("control_state", static_cast(m_control_state));
- stat.addf(
- "translation deviation threshold", "%lf",
- m_state_transition_params.emergency_state_traj_trans_dev);
- stat.addf("translation deviation", "%lf", m_diagnostic_data.trans_deviation);
- stat.addf(
- "rotation deviation threshold", "%lf", m_state_transition_params.emergency_state_traj_rot_dev);
- stat.addf("rotation deviation", "%lf", m_diagnostic_data.rot_deviation);
stat.summary(level, msg);
}
diff --git a/control/autoware_pid_longitudinal_controller/src/smooth_stop.cpp b/control/autoware_pid_longitudinal_controller/src/smooth_stop.cpp
index 9ee4763c6c05f..2dd2950d4356e 100644
--- a/control/autoware_pid_longitudinal_controller/src/smooth_stop.cpp
+++ b/control/autoware_pid_longitudinal_controller/src/smooth_stop.cpp
@@ -116,7 +116,8 @@ std::experimental::optional SmoothStop::calcTimeToStop(
double SmoothStop::calculate(
const double stop_dist, const double current_vel, const double current_acc,
- const std::vector> & vel_hist, const double delay_time)
+ const std::vector> & vel_hist, const double delay_time,
+ DebugValues & debug_values)
{
if (!m_is_set_params) {
throw std::runtime_error("Trying to calculate uninitialized SmoothStop");
@@ -132,8 +133,11 @@ double SmoothStop::calculate(
// when exceeding the stopline (stop_dist is negative in these cases.)
if (stop_dist < m_params.strong_stop_dist) { // when exceeding the stopline much
+ debug_values.setValues(
+ DebugValues::TYPE::SMOOTH_STOP_MODE, static_cast(Mode::STRONG_STOP));
return m_params.strong_stop_acc;
} else if (stop_dist < m_params.weak_stop_dist) { // when exceeding the stopline a bit
+ debug_values.setValues(DebugValues::TYPE::SMOOTH_STOP_MODE, static_cast(Mode::WEAK_STOP));
return m_params.weak_stop_acc;
}
@@ -143,19 +147,23 @@ double SmoothStop::calculate(
if (
(time_to_stop && *time_to_stop > m_params.weak_stop_time + delay_time) ||
(!time_to_stop && is_fast_vel)) {
+ debug_values.setValues(DebugValues::TYPE::SMOOTH_STOP_MODE, static_cast(Mode::STRONG));
return m_strong_acc;
}
m_weak_acc_time = rclcpp::Clock{RCL_ROS_TIME}.now();
+ debug_values.setValues(DebugValues::TYPE::SMOOTH_STOP_MODE, static_cast(Mode::WEAK));
return m_params.weak_acc;
}
// for 0.5 seconds after the car stopped
if ((rclcpp::Clock{RCL_ROS_TIME}.now() - m_weak_acc_time).seconds() < 0.5) {
+ debug_values.setValues(DebugValues::TYPE::SMOOTH_STOP_MODE, static_cast(Mode::WEAK));
return m_params.weak_acc;
}
// when the car is not running
+ debug_values.setValues(DebugValues::TYPE::SMOOTH_STOP_MODE, static_cast(Mode::STRONG_STOP));
return m_params.strong_stop_acc;
}
} // namespace autoware::motion::control::pid_longitudinal_controller
diff --git a/control/autoware_pid_longitudinal_controller/test/test_smooth_stop.cpp b/control/autoware_pid_longitudinal_controller/test/test_smooth_stop.cpp
index a6d03b8032fe6..30d582bbbf1ef 100644
--- a/control/autoware_pid_longitudinal_controller/test/test_smooth_stop.cpp
+++ b/control/autoware_pid_longitudinal_controller/test/test_smooth_stop.cpp
@@ -21,6 +21,7 @@
TEST(TestSmoothStop, calculate_stopping_acceleration)
{
+ using ::autoware::motion::control::pid_longitudinal_controller::DebugValues;
using ::autoware::motion::control::pid_longitudinal_controller::SmoothStop;
using rclcpp::Duration;
using rclcpp::Time;
@@ -40,9 +41,10 @@ TEST(TestSmoothStop, calculate_stopping_acceleration)
const double delay_time = 0.17;
SmoothStop ss;
+ DebugValues debug_values;
// Cannot calculate before setting parameters
- EXPECT_THROW(ss.calculate(0.0, 0.0, 0.0, {}, delay_time), std::runtime_error);
+ EXPECT_THROW(ss.calculate(0.0, 0.0, 0.0, {}, delay_time, debug_values), std::runtime_error);
ss.setParams(
max_strong_acc, min_strong_acc, weak_acc, weak_stop_acc, strong_stop_acc, max_fast_vel,
@@ -62,34 +64,45 @@ TEST(TestSmoothStop, calculate_stopping_acceleration)
stop_dist = strong_stop_dist - 0.1;
current_vel = 2.0;
ss.init(vel_in_target, stop_dist);
- accel = ss.calculate(stop_dist, current_vel, current_acc, velocity_history, delay_time);
+ accel =
+ ss.calculate(stop_dist, current_vel, current_acc, velocity_history, delay_time, debug_values);
EXPECT_EQ(accel, strong_stop_acc);
+ EXPECT_EQ(debug_values.getValue(DebugValues::TYPE::SMOOTH_STOP_MODE), 3);
// weak stop when the stop distance is below the threshold (but not bellow the strong_stop_dist)
stop_dist = weak_stop_dist - 0.1;
current_vel = 2.0;
ss.init(vel_in_target, stop_dist);
- accel = ss.calculate(stop_dist, current_vel, current_acc, velocity_history, delay_time);
+ accel =
+ ss.calculate(stop_dist, current_vel, current_acc, velocity_history, delay_time, debug_values);
EXPECT_EQ(accel, weak_stop_acc);
+ EXPECT_EQ(debug_values.getValue(DebugValues::TYPE::SMOOTH_STOP_MODE), 2);
// if not running, weak accel for 0.5 seconds after the previous init or previous weak_acc
rclcpp::Rate rate_quart(1.0 / 0.25);
rclcpp::Rate rate_half(1.0 / 0.5);
stop_dist = 0.0;
current_vel = 0.0;
- EXPECT_EQ(
- ss.calculate(stop_dist, current_vel, current_acc, velocity_history, delay_time), weak_acc);
+ accel =
+ ss.calculate(stop_dist, current_vel, current_acc, velocity_history, delay_time, debug_values);
+ EXPECT_EQ(accel, weak_acc);
+ EXPECT_EQ(debug_values.getValue(DebugValues::TYPE::SMOOTH_STOP_MODE), 1);
rate_quart.sleep();
- EXPECT_EQ(
- ss.calculate(stop_dist, current_vel, current_acc, velocity_history, delay_time), weak_acc);
+ accel =
+ ss.calculate(stop_dist, current_vel, current_acc, velocity_history, delay_time, debug_values);
+ EXPECT_EQ(accel, weak_acc);
+ EXPECT_EQ(debug_values.getValue(DebugValues::TYPE::SMOOTH_STOP_MODE), 1);
rate_half.sleep();
- EXPECT_NE(
- ss.calculate(stop_dist, current_vel, current_acc, velocity_history, delay_time), weak_acc);
+ accel =
+ ss.calculate(stop_dist, current_vel, current_acc, velocity_history, delay_time, debug_values);
+ EXPECT_NE(accel, weak_acc);
+ EXPECT_NE(debug_values.getValue(DebugValues::TYPE::SMOOTH_STOP_MODE), 1);
// strong stop when the car is not running (and is at least 0.5seconds after initialization)
- EXPECT_EQ(
- ss.calculate(stop_dist, current_vel, current_acc, velocity_history, delay_time),
- strong_stop_acc);
+ accel =
+ ss.calculate(stop_dist, current_vel, current_acc, velocity_history, delay_time, debug_values);
+ EXPECT_EQ(accel, strong_stop_acc);
+ EXPECT_EQ(debug_values.getValue(DebugValues::TYPE::SMOOTH_STOP_MODE), 3);
// accel between min/max_strong_acc when the car is running:
// not predicted to exceed the stop line and is predicted to stop after weak_stop_time + delay
@@ -97,19 +110,22 @@ TEST(TestSmoothStop, calculate_stopping_acceleration)
current_vel = 1.0;
vel_in_target = 1.0;
ss.init(vel_in_target, stop_dist);
- EXPECT_EQ(
- ss.calculate(stop_dist, current_vel, current_acc, velocity_history, delay_time),
- max_strong_acc);
+ accel =
+ ss.calculate(stop_dist, current_vel, current_acc, velocity_history, delay_time, debug_values);
+ EXPECT_EQ(accel, max_strong_acc);
+ EXPECT_EQ(debug_values.getValue(DebugValues::TYPE::SMOOTH_STOP_MODE), 0);
vel_in_target = std::sqrt(2.0);
ss.init(vel_in_target, stop_dist);
- EXPECT_EQ(
- ss.calculate(stop_dist, current_vel, current_acc, velocity_history, delay_time),
- min_strong_acc);
+ accel =
+ ss.calculate(stop_dist, current_vel, current_acc, velocity_history, delay_time, debug_values);
+ EXPECT_EQ(accel, min_strong_acc);
+ EXPECT_EQ(debug_values.getValue(DebugValues::TYPE::SMOOTH_STOP_MODE), 0);
for (double vel_in_target = 1.1; vel_in_target < std::sqrt(2.0); vel_in_target += 0.1) {
ss.init(vel_in_target, stop_dist);
- accel = ss.calculate(stop_dist, current_vel, current_acc, velocity_history, delay_time);
+ accel =
+ ss.calculate(stop_dist, current_vel, current_acc, velocity_history, delay_time, debug_values);
EXPECT_GT(accel, min_strong_acc);
EXPECT_LT(accel, max_strong_acc);
}
diff --git a/control/autoware_trajectory_follower_node/config/plot_juggler_trajectory_follower.xml b/control/autoware_trajectory_follower_node/config/plot_juggler_trajectory_follower.xml
index 0de08076b8c06..fda7e1f3906e0 100644
--- a/control/autoware_trajectory_follower_node/config/plot_juggler_trajectory_follower.xml
+++ b/control/autoware_trajectory_follower_node/config/plot_juggler_trajectory_follower.xml
@@ -1,130 +1,130 @@
-
-
+
+
-
-
+
+
-
-
+
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
-
+
+
-
+
-
+
-
-
+
+
-
+
-
+
-
+
-
-
+
+
-
+
-
+
-
+
-
+
-
-
+
+
-
+
-
+
-
-
+
+
@@ -133,114 +133,150 @@
-
+
-
+
-
-
+
+
-
+
-
+
-
+
-
+
-
-
+
+
-
-
-
-
-
-
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
-
+
-
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
-
+
-
+
-
+
-
-
+
+
-
+
+
+
+
+
+
@@ -255,7 +291,7 @@
-
+
@@ -270,11 +306,11 @@
-
+
-
-
-
+
+
+
diff --git a/control/autoware_trajectory_follower_node/test/test_controller_node.cpp b/control/autoware_trajectory_follower_node/test/test_controller_node.cpp
index 0b1dac644a8ab..982af104538b5 100644
--- a/control/autoware_trajectory_follower_node/test/test_controller_node.cpp
+++ b/control/autoware_trajectory_follower_node/test/test_controller_node.cpp
@@ -510,34 +510,6 @@ TEST_F(FakeNodeFixture, longitudinal_reverse)
EXPECT_GT(tester.cmd_msg->longitudinal.acceleration, 0.0f);
}
-TEST_F(FakeNodeFixture, longitudinal_emergency)
-{
- const auto node_options = makeNodeOptions();
- ControllerTester tester(this, node_options);
-
- tester.send_default_transform();
- tester.publish_default_odom();
- tester.publish_autonomous_operation_mode();
- tester.publish_default_steer();
- tester.publish_default_acc();
-
- // Publish trajectory starting away from the current ego pose
- Trajectory traj;
- traj.header.stamp = tester.node->now();
- traj.header.frame_id = "map";
- traj.points.push_back(make_traj_point(10.0, 0.0, 1.0f));
- traj.points.push_back(make_traj_point(50.0, 0.0, 1.0f));
- traj.points.push_back(make_traj_point(100.0, 0.0, 1.0f));
- tester.traj_pub->publish(traj);
-
- test_utils::waitForMessage(tester.node, this, tester.received_control_command);
-
- ASSERT_TRUE(tester.received_control_command);
- // Emergencies (e.g., far from trajectory) produces braking command (0 vel, negative accel)
- EXPECT_DOUBLE_EQ(tester.cmd_msg->longitudinal.velocity, 0.0f);
- EXPECT_LT(tester.cmd_msg->longitudinal.acceleration, 0.0f);
-}
-
TEST_F(FakeNodeFixture, longitudinal_not_check_steer_converged)
{
const auto node_options = makeNodeOptions();
diff --git a/evaluator/autoware_control_evaluator/src/control_evaluator_node.cpp b/evaluator/autoware_control_evaluator/src/control_evaluator_node.cpp
index 9c8579469f878..b0db41b0fdc73 100644
--- a/evaluator/autoware_control_evaluator/src/control_evaluator_node.cpp
+++ b/evaluator/autoware_control_evaluator/src/control_evaluator_node.cpp
@@ -21,6 +21,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -52,45 +53,51 @@ ControlEvaluatorNode::~ControlEvaluatorNode()
return;
}
- // generate json data
- using json = nlohmann::json;
- json j;
- for (Metric metric : metrics_) {
- const std::string base_name = metric_to_str.at(metric) + "/";
- j[base_name + "min"] = metric_accumulators_[static_cast(metric)].min();
- j[base_name + "max"] = metric_accumulators_[static_cast(metric)].max();
- j[base_name + "mean"] = metric_accumulators_[static_cast(metric)].mean();
- j[base_name + "count"] = metric_accumulators_[static_cast(metric)].count();
- j[base_name + "description"] = metric_descriptions.at(metric);
- }
+ try {
+ // generate json data
+ using json = nlohmann::json;
+ json j;
+ for (Metric metric : metrics_) {
+ const std::string base_name = metric_to_str.at(metric) + "/";
+ j[base_name + "min"] = metric_accumulators_[static_cast(metric)].min();
+ j[base_name + "max"] = metric_accumulators_[static_cast(metric)].max();
+ j[base_name + "mean"] = metric_accumulators_[static_cast(metric)].mean();
+ j[base_name + "count"] = metric_accumulators_[static_cast(metric)].count();
+ j[base_name + "description"] = metric_descriptions.at(metric);
+ }
- // get output folder
- const std::string output_folder_str =
- rclcpp::get_logging_directory().string() + "/autoware_metrics";
- if (!std::filesystem::exists(output_folder_str)) {
- if (!std::filesystem::create_directories(output_folder_str)) {
- RCLCPP_ERROR(
- this->get_logger(), "Failed to create directories: %s", output_folder_str.c_str());
- return;
+ // get output folder
+ const std::string output_folder_str =
+ rclcpp::get_logging_directory().string() + "/autoware_metrics";
+ if (!std::filesystem::exists(output_folder_str)) {
+ if (!std::filesystem::create_directories(output_folder_str)) {
+ RCLCPP_ERROR(
+ this->get_logger(), "Failed to create directories: %s", output_folder_str.c_str());
+ return;
+ }
}
- }
- // get time stamp
- std::time_t now_time_t = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
- std::tm * local_time = std::localtime(&now_time_t);
- std::ostringstream oss;
- oss << std::put_time(local_time, "%Y-%m-%d-%H-%M-%S");
- std::string cur_time_str = oss.str();
-
- // Write metrics .json to file
- const std::string output_file_str =
- output_folder_str + "/autoware_control_evaluator-" + cur_time_str + ".json";
- std::ofstream f(output_file_str);
- if (f.is_open()) {
- f << j.dump(4);
- f.close();
- } else {
- RCLCPP_ERROR(this->get_logger(), "Failed to open file: %s", output_file_str.c_str());
+ // get time stamp
+ std::time_t now_time_t = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
+ std::tm * local_time = std::localtime(&now_time_t);
+ std::ostringstream oss;
+ oss << std::put_time(local_time, "%Y-%m-%d-%H-%M-%S");
+ std::string cur_time_str = oss.str();
+
+ // Write metrics .json to file
+ const std::string output_file_str =
+ output_folder_str + "/autoware_control_evaluator-" + cur_time_str + ".json";
+ std::ofstream f(output_file_str);
+ if (f.is_open()) {
+ f << j.dump(4);
+ f.close();
+ } else {
+ RCLCPP_ERROR(this->get_logger(), "Failed to open file: %s", output_file_str.c_str());
+ }
+ } catch (const std::exception & e) {
+ std::cerr << "Exception in ControlEvaluatorNode destructor: " << e.what() << std::endl;
+ } catch (...) {
+ std::cerr << "Unknown exception in ControlEvaluatorNode destructor" << std::endl;
}
}
diff --git a/evaluator/autoware_planning_evaluator/README.md b/evaluator/autoware_planning_evaluator/README.md
index 4fcdf4d7e55fd..b9dd3201a2541 100644
--- a/evaluator/autoware_planning_evaluator/README.md
+++ b/evaluator/autoware_planning_evaluator/README.md
@@ -13,6 +13,7 @@ Metrics are calculated using the following information:
- the previous trajectory `T(-1)`.
- the _reference_ trajectory assumed to be used as the reference to plan `T(0)`.
- the current ego pose.
+- the current ego odometry.
- the set of objects in the environment.
These information are maintained by an instance of class `MetricsCalculator`
diff --git a/evaluator/autoware_planning_evaluator/config/planning_evaluator.param.yaml b/evaluator/autoware_planning_evaluator/config/planning_evaluator.param.yaml
index 14c1bcc6beea4..7605ed2a5e859 100644
--- a/evaluator/autoware_planning_evaluator/config/planning_evaluator.param.yaml
+++ b/evaluator/autoware_planning_evaluator/config/planning_evaluator.param.yaml
@@ -14,6 +14,8 @@
- lateral_deviation
- yaw_deviation
- velocity_deviation
+ - lateral_trajectory_displacement_local
+ - lateral_trajectory_displacement_lookahead
- stability
- stability_frechet
- obstacle_distance
@@ -24,6 +26,7 @@
trajectory:
min_point_dist_m: 0.1 # [m] minimum distance between two successive points to use for angle calculation
+ evaluation_time_s: 5.0 # [s] time duration for trajectory evaluation in seconds
lookahead:
max_dist_m: 5.0 # [m] maximum distance from ego along the trajectory to use for calculation
max_time_s: 3.0 # [s] maximum time ahead of ego along the trajectory to use for calculation
diff --git a/evaluator/autoware_planning_evaluator/include/autoware/planning_evaluator/metrics/deviation_metrics.hpp b/evaluator/autoware_planning_evaluator/include/autoware/planning_evaluator/metrics/deviation_metrics.hpp
index 59866c96ad702..2341ad2bb6ba3 100644
--- a/evaluator/autoware_planning_evaluator/include/autoware/planning_evaluator/metrics/deviation_metrics.hpp
+++ b/evaluator/autoware_planning_evaluator/include/autoware/planning_evaluator/metrics/deviation_metrics.hpp
@@ -38,6 +38,16 @@ using geometry_msgs::msg::Pose;
*/
Accumulator calcLateralDeviation(const Trajectory & ref, const Trajectory & traj);
+/**
+ * @brief calculate lateral trajectory displacement from the previous trajectory and the trajectory
+ * @param [in] prev previous trajectory
+ * @param [in] traj input trajectory
+ * @param [in] base_pose base pose
+ * @return calculated statistics
+ */
+Accumulator calcLocalLateralTrajectoryDisplacement(
+ const Trajectory & prev, const Trajectory & traj, const Pose & base_pose);
+
/**
* @brief calculate yaw deviation of the given trajectory from the reference trajectory
* @param [in] ref reference trajectory
diff --git a/evaluator/autoware_planning_evaluator/include/autoware/planning_evaluator/metrics/metric.hpp b/evaluator/autoware_planning_evaluator/include/autoware/planning_evaluator/metrics/metric.hpp
index c0313ed0727dd..7c207bf6c8f57 100644
--- a/evaluator/autoware_planning_evaluator/include/autoware/planning_evaluator/metrics/metric.hpp
+++ b/evaluator/autoware_planning_evaluator/include/autoware/planning_evaluator/metrics/metric.hpp
@@ -37,6 +37,8 @@ enum class Metric {
lateral_deviation,
yaw_deviation,
velocity_deviation,
+ lateral_trajectory_displacement_local,
+ lateral_trajectory_displacement_lookahead,
stability,
stability_frechet,
obstacle_distance,
@@ -62,6 +64,8 @@ static const std::unordered_map str_to_metric = {
{"lateral_deviation", Metric::lateral_deviation},
{"yaw_deviation", Metric::yaw_deviation},
{"velocity_deviation", Metric::velocity_deviation},
+ {"lateral_trajectory_displacement_local", Metric::lateral_trajectory_displacement_local},
+ {"lateral_trajectory_displacement_lookahead", Metric::lateral_trajectory_displacement_lookahead},
{"stability", Metric::stability},
{"stability_frechet", Metric::stability_frechet},
{"obstacle_distance", Metric::obstacle_distance},
@@ -82,6 +86,8 @@ static const std::unordered_map metric_to_str = {
{Metric::lateral_deviation, "lateral_deviation"},
{Metric::yaw_deviation, "yaw_deviation"},
{Metric::velocity_deviation, "velocity_deviation"},
+ {Metric::lateral_trajectory_displacement_local, "lateral_trajectory_displacement_local"},
+ {Metric::lateral_trajectory_displacement_lookahead, "lateral_trajectory_displacement_lookahead"},
{Metric::stability, "stability"},
{Metric::stability_frechet, "stability_frechet"},
{Metric::obstacle_distance, "obstacle_distance"},
@@ -103,6 +109,8 @@ static const std::unordered_map metric_descriptions = {
{Metric::lateral_deviation, "Lateral_deviation[m]"},
{Metric::yaw_deviation, "Yaw_deviation[rad]"},
{Metric::velocity_deviation, "Velocity_deviation[m/s]"},
+ {Metric::lateral_trajectory_displacement_local, "Nearest Pose Lateral Deviation[m]"},
+ {Metric::lateral_trajectory_displacement_lookahead, "Lateral_Offset_Over_Distance_Ahead[m]"},
{Metric::stability, "Stability[m]"},
{Metric::stability_frechet, "StabilityFrechet[m]"},
{Metric::obstacle_distance, "Obstacle_distance[m]"},
diff --git a/evaluator/autoware_planning_evaluator/include/autoware/planning_evaluator/metrics/metrics_utils.hpp b/evaluator/autoware_planning_evaluator/include/autoware/planning_evaluator/metrics/metrics_utils.hpp
index 0006e49c3338a..9f2b99007af7d 100644
--- a/evaluator/autoware_planning_evaluator/include/autoware/planning_evaluator/metrics/metrics_utils.hpp
+++ b/evaluator/autoware_planning_evaluator/include/autoware/planning_evaluator/metrics/metrics_utils.hpp
@@ -25,6 +25,7 @@ namespace metrics
namespace utils
{
using autoware_planning_msgs::msg::Trajectory;
+using geometry_msgs::msg::Pose;
/**
* @brief find the index in the trajectory at the given distance of the given index
@@ -35,6 +36,29 @@ using autoware_planning_msgs::msg::Trajectory;
*/
size_t getIndexAfterDistance(const Trajectory & traj, const size_t curr_id, const double distance);
+/**
+ * @brief trim a trajectory from the current ego pose to some fixed time or distance
+ * @param [in] traj input trajectory to trim
+ * @param [in] max_dist_m [m] maximum distance ahead of the ego pose
+ * @param [in] max_time_s [s] maximum time ahead of the ego pose
+ * @return sub-trajectory starting from the ego pose and of maximum length max_dist_m, maximum
+ * duration max_time_s
+ */
+Trajectory get_lookahead_trajectory(
+ const Trajectory & traj, const Pose & ego_pose, const double max_dist_m, const double max_time_s);
+
+/**
+ * @brief calculate the total distance from ego position to the end of trajectory
+ * @details finds the nearest point to ego position on the trajectory and calculates
+ * the cumulative distance by summing up the distances between consecutive points
+ * from that position to the end of the trajectory.
+ *
+ * @param [in] traj input trajectory to calculate distance along
+ * @param [in] ego_pose current ego vehicle pose
+ * @return total distance from ego position to trajectory end in meters
+ */
+double calc_lookahead_trajectory_distance(const Trajectory & traj, const Pose & ego_pose);
+
} // namespace utils
} // namespace metrics
} // namespace planning_diagnostics
diff --git a/evaluator/autoware_planning_evaluator/include/autoware/planning_evaluator/metrics/stability_metrics.hpp b/evaluator/autoware_planning_evaluator/include/autoware/planning_evaluator/metrics/stability_metrics.hpp
index 38f388feeadda..1b46fbddfb297 100644
--- a/evaluator/autoware_planning_evaluator/include/autoware/planning_evaluator/metrics/stability_metrics.hpp
+++ b/evaluator/autoware_planning_evaluator/include/autoware/planning_evaluator/metrics/stability_metrics.hpp
@@ -18,6 +18,7 @@
#include "autoware/universe_utils/math/accumulator.hpp"
#include "autoware_planning_msgs/msg/trajectory.hpp"
+#include
namespace planning_diagnostics
{
@@ -42,6 +43,23 @@ Accumulator calcFrechetDistance(const Trajectory & traj1, const Trajecto
*/
Accumulator calcLateralDistance(const Trajectory & traj1, const Trajectory & traj2);
+/**
+ * @brief calculate the total lateral displacement between two trajectories
+ * @details Evaluates the cumulative absolute lateral displacement by sampling points
+ * along the first trajectory and measuring their offset from the second trajectory.
+ * The evaluation section length is determined by the ego vehicle's velocity and
+ * the specified evaluation time.
+ *
+ * @param traj1 first trajectory to compare
+ * @param traj2 second trajectory to compare against
+ * @param [in] ego_odom current ego vehicle odometry containing pose and velocity
+ * @param [in] trajectory_eval_time_s time duration for trajectory evaluation in seconds
+ * @return statistical accumulator containing the total lateral displacement
+ */
+Accumulator calcLookaheadLateralTrajectoryDisplacement(
+ const Trajectory traj1, const Trajectory traj2, const nav_msgs::msg::Odometry & ego_odom,
+ const double trajectory_eval_time_s);
+
} // namespace metrics
} // namespace planning_diagnostics
diff --git a/evaluator/autoware_planning_evaluator/include/autoware/planning_evaluator/metrics_calculator.hpp b/evaluator/autoware_planning_evaluator/include/autoware/planning_evaluator/metrics_calculator.hpp
index 97d23cad10af2..fe9d9eaf4278b 100644
--- a/evaluator/autoware_planning_evaluator/include/autoware/planning_evaluator/metrics_calculator.hpp
+++ b/evaluator/autoware_planning_evaluator/include/autoware/planning_evaluator/metrics_calculator.hpp
@@ -23,6 +23,7 @@
#include "autoware_planning_msgs/msg/trajectory.hpp"
#include "autoware_planning_msgs/msg/trajectory_point.hpp"
#include "geometry_msgs/msg/pose.hpp"
+#include
#include
@@ -74,7 +75,7 @@ class MetricsCalculator
* @brief set the ego pose
* @param [in] traj input previous trajectory
*/
- void setEgoPose(const geometry_msgs::msg::Pose & pose);
+ void setEgoPose(const nav_msgs::msg::Odometry & ego_odometry);
/**
* @brief get the ego pose
@@ -83,23 +84,13 @@ class MetricsCalculator
Pose getEgoPose();
private:
- /**
- * @brief trim a trajectory from the current ego pose to some fixed time or distance
- * @param [in] traj input trajectory to trim
- * @param [in] max_dist_m [m] maximum distance ahead of the ego pose
- * @param [in] max_time_s [s] maximum time ahead of the ego pose
- * @return sub-trajectory starting from the ego pose and of maximum length max_dist_m, maximum
- * duration max_time_s
- */
- Trajectory getLookaheadTrajectory(
- const Trajectory & traj, const double max_dist_m, const double max_time_s) const;
-
Trajectory reference_trajectory_;
Trajectory reference_trajectory_lookahead_;
Trajectory previous_trajectory_;
Trajectory previous_trajectory_lookahead_;
PredictedObjects dynamic_objects_;
geometry_msgs::msg::Pose ego_pose_;
+ nav_msgs::msg::Odometry ego_odometry_;
PoseWithUuidStamped modified_goal_;
}; // class MetricsCalculator
diff --git a/evaluator/autoware_planning_evaluator/include/autoware/planning_evaluator/parameters.hpp b/evaluator/autoware_planning_evaluator/include/autoware/planning_evaluator/parameters.hpp
index cd894fecc2331..94920195ee89c 100644
--- a/evaluator/autoware_planning_evaluator/include/autoware/planning_evaluator/parameters.hpp
+++ b/evaluator/autoware_planning_evaluator/include/autoware/planning_evaluator/parameters.hpp
@@ -31,6 +31,7 @@ struct Parameters
struct
{
double min_point_dist_m = 0.1;
+ double evaluation_time_s = 5.0;
struct
{
double max_dist_m = 5.0;
diff --git a/evaluator/autoware_planning_evaluator/schema/autoware_planning_evaluator.schema.json b/evaluator/autoware_planning_evaluator/schema/autoware_planning_evaluator.schema.json
index 1ef3874a0dcbc..263bd374a7e45 100644
--- a/evaluator/autoware_planning_evaluator/schema/autoware_planning_evaluator.schema.json
+++ b/evaluator/autoware_planning_evaluator/schema/autoware_planning_evaluator.schema.json
@@ -34,6 +34,7 @@
"lateral_deviation",
"yaw_deviation",
"velocity_deviation",
+ "lateral_trajectory_displacement",
"stability",
"stability_frechet",
"obstacle_distance",
diff --git a/evaluator/autoware_planning_evaluator/src/metrics/deviation_metrics.cpp b/evaluator/autoware_planning_evaluator/src/metrics/deviation_metrics.cpp
index 7e2217a49ef87..82ba86c65d6af 100644
--- a/evaluator/autoware_planning_evaluator/src/metrics/deviation_metrics.cpp
+++ b/evaluator/autoware_planning_evaluator/src/metrics/deviation_metrics.cpp
@@ -45,6 +45,24 @@ Accumulator calcLateralDeviation(const Trajectory & ref, const Trajector
return stat;
}
+Accumulator calcLocalLateralTrajectoryDisplacement(
+ const Trajectory & prev, const Trajectory & traj, const Pose & ego_pose)
+{
+ Accumulator stat;
+
+ if (prev.points.empty() || traj.points.empty()) {
+ return stat;
+ }
+
+ const auto prev_lateral_deviation =
+ autoware::motion_utils::calcLateralOffset(prev.points, ego_pose.position);
+ const auto traj_lateral_deviation =
+ autoware::motion_utils::calcLateralOffset(traj.points, ego_pose.position);
+ const auto lateral_trajectory_displacement = traj_lateral_deviation - prev_lateral_deviation;
+ stat.add(lateral_trajectory_displacement);
+ return stat;
+}
+
Accumulator calcYawDeviation(const Trajectory & ref, const Trajectory & traj)
{
Accumulator stat;
diff --git a/evaluator/autoware_planning_evaluator/src/metrics/metrics_utils.cpp b/evaluator/autoware_planning_evaluator/src/metrics/metrics_utils.cpp
index 669afdd7229b0..7451264f037a6 100644
--- a/evaluator/autoware_planning_evaluator/src/metrics/metrics_utils.cpp
+++ b/evaluator/autoware_planning_evaluator/src/metrics/metrics_utils.cpp
@@ -12,8 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include "autoware/motion_utils/trajectory/trajectory.hpp"
#include "autoware/planning_evaluator/metrics/trajectory_metrics.hpp"
#include "autoware/universe_utils/geometry/geometry.hpp"
+
namespace planning_diagnostics
{
namespace metrics
@@ -23,6 +25,7 @@ namespace utils
using autoware::universe_utils::calcDistance2d;
using autoware_planning_msgs::msg::Trajectory;
using autoware_planning_msgs::msg::TrajectoryPoint;
+using geometry_msgs::msg::Pose;
size_t getIndexAfterDistance(const Trajectory & traj, const size_t curr_id, const double distance)
{
@@ -41,6 +44,52 @@ size_t getIndexAfterDistance(const Trajectory & traj, const size_t curr_id, cons
return target_id;
}
+Trajectory get_lookahead_trajectory(
+ const Trajectory & traj, const Pose & ego_pose, const double max_dist_m, const double max_time_s)
+{
+ if (traj.points.empty()) {
+ return traj;
+ }
+
+ const auto ego_index =
+ autoware::motion_utils::findNearestSegmentIndex(traj.points, ego_pose.position);
+ Trajectory lookahead_traj;
+ lookahead_traj.header = traj.header;
+ double dist = 0.0;
+ double time = 0.0;
+ auto curr_point_it = std::next(traj.points.begin(), ego_index);
+ auto prev_point_it = curr_point_it;
+ while (curr_point_it != traj.points.end() && dist <= max_dist_m && time <= max_time_s) {
+ lookahead_traj.points.push_back(*curr_point_it);
+ const auto d = autoware::universe_utils::calcDistance2d(
+ prev_point_it->pose.position, curr_point_it->pose.position);
+ dist += d;
+ if (prev_point_it->longitudinal_velocity_mps != 0.0) {
+ time += d / std::abs(prev_point_it->longitudinal_velocity_mps);
+ }
+ prev_point_it = curr_point_it;
+ ++curr_point_it;
+ }
+ return lookahead_traj;
+}
+
+double calc_lookahead_trajectory_distance(const Trajectory & traj, const Pose & ego_pose)
+{
+ const auto ego_index =
+ autoware::motion_utils::findNearestSegmentIndex(traj.points, ego_pose.position);
+ double dist = 0.0;
+ auto curr_point_it = std::next(traj.points.begin(), ego_index);
+ auto prev_point_it = curr_point_it;
+ for (size_t i = 0; i < traj.points.size(); ++i) {
+ const auto d = autoware::universe_utils::calcDistance2d(
+ prev_point_it->pose.position, curr_point_it->pose.position);
+ dist += d;
+ prev_point_it = curr_point_it;
+ ++curr_point_it;
+ }
+
+ return dist;
+}
} // namespace utils
} // namespace metrics
} // namespace planning_diagnostics
diff --git a/evaluator/autoware_planning_evaluator/src/metrics/stability_metrics.cpp b/evaluator/autoware_planning_evaluator/src/metrics/stability_metrics.cpp
index e6ede0d07b9b3..61e18a6ad0b63 100644
--- a/evaluator/autoware_planning_evaluator/src/metrics/stability_metrics.cpp
+++ b/evaluator/autoware_planning_evaluator/src/metrics/stability_metrics.cpp
@@ -14,7 +14,9 @@
#include "autoware/planning_evaluator/metrics/stability_metrics.hpp"
+#include "autoware/motion_utils/resample/resample.hpp"
#include "autoware/motion_utils/trajectory/trajectory.hpp"
+#include "autoware/planning_evaluator/metrics/metrics_utils.hpp"
#include "autoware/universe_utils/geometry/geometry.hpp"
#include
@@ -96,5 +98,47 @@ Accumulator calcLateralDistance(const Trajectory & traj1, const Trajecto
return stat;
}
+Accumulator calcLookaheadLateralTrajectoryDisplacement(
+ const Trajectory traj1, const Trajectory traj2, const nav_msgs::msg::Odometry & ego_odom,
+ const double trajectory_eval_time_s)
+{
+ Accumulator stat;
+
+ if (traj1.points.empty() || traj2.points.empty()) {
+ return stat;
+ }
+
+ const double ego_velocity =
+ std::hypot(ego_odom.twist.twist.linear.x, ego_odom.twist.twist.linear.y);
+
+ const double evaluation_section_length = trajectory_eval_time_s * std::abs(ego_velocity);
+
+ const double traj1_lookahead_distance =
+ utils::calc_lookahead_trajectory_distance(traj1, ego_odom.pose.pose);
+ const double traj2_lookahead_distance =
+ utils::calc_lookahead_trajectory_distance(traj2, ego_odom.pose.pose);
+
+ if (
+ traj1_lookahead_distance < evaluation_section_length ||
+ traj2_lookahead_distance < evaluation_section_length) {
+ return stat;
+ }
+
+ constexpr double num_evaluation_points = 10.0;
+ const double interval = evaluation_section_length / num_evaluation_points;
+
+ const auto resampled_traj1 = autoware::motion_utils::resampleTrajectory(
+ utils::get_lookahead_trajectory(
+ traj1, ego_odom.pose.pose, evaluation_section_length, trajectory_eval_time_s),
+ interval);
+
+ for (const auto & point : resampled_traj1.points) {
+ const auto p0 = autoware::universe_utils::getPoint(point);
+ const double dist = autoware::motion_utils::calcLateralOffset(traj2.points, p0);
+ stat.add(std::abs(dist));
+ }
+ return stat;
+}
+
} // namespace metrics
} // namespace planning_diagnostics
diff --git a/evaluator/autoware_planning_evaluator/src/metrics_calculator.cpp b/evaluator/autoware_planning_evaluator/src/metrics_calculator.cpp
index 6e057bcc9fc3d..c30420a5632fa 100644
--- a/evaluator/autoware_planning_evaluator/src/metrics_calculator.cpp
+++ b/evaluator/autoware_planning_evaluator/src/metrics_calculator.cpp
@@ -16,6 +16,7 @@
#include "autoware/motion_utils/trajectory/trajectory.hpp"
#include "autoware/planning_evaluator/metrics/deviation_metrics.hpp"
+#include "autoware/planning_evaluator/metrics/metrics_utils.hpp"
#include "autoware/planning_evaluator/metrics/obstacle_metrics.hpp"
#include "autoware/planning_evaluator/metrics/stability_metrics.hpp"
#include "autoware/planning_evaluator/metrics/trajectory_metrics.hpp"
@@ -49,21 +50,26 @@ std::optional> MetricsCalculator::calculate(
return metrics::calcYawDeviation(reference_trajectory_, traj);
case Metric::velocity_deviation:
return metrics::calcVelocityDeviation(reference_trajectory_, traj);
+ case Metric::lateral_trajectory_displacement_local:
+ return metrics::calcLocalLateralTrajectoryDisplacement(previous_trajectory_, traj, ego_pose_);
+ case Metric::lateral_trajectory_displacement_lookahead:
+ return metrics::calcLookaheadLateralTrajectoryDisplacement(
+ previous_trajectory_, traj, ego_odometry_, parameters.trajectory.evaluation_time_s);
case Metric::stability_frechet:
return metrics::calcFrechetDistance(
- getLookaheadTrajectory(
- previous_trajectory_, parameters.trajectory.lookahead.max_dist_m,
+ metrics::utils::get_lookahead_trajectory(
+ previous_trajectory_, ego_pose_, parameters.trajectory.lookahead.max_dist_m,
parameters.trajectory.lookahead.max_time_s),
- getLookaheadTrajectory(
- traj, parameters.trajectory.lookahead.max_dist_m,
+ metrics::utils::get_lookahead_trajectory(
+ traj, ego_pose_, parameters.trajectory.lookahead.max_dist_m,
parameters.trajectory.lookahead.max_time_s));
case Metric::stability:
return metrics::calcLateralDistance(
- getLookaheadTrajectory(
- previous_trajectory_, parameters.trajectory.lookahead.max_dist_m,
+ metrics::utils::get_lookahead_trajectory(
+ previous_trajectory_, ego_pose_, parameters.trajectory.lookahead.max_dist_m,
parameters.trajectory.lookahead.max_time_s),
- getLookaheadTrajectory(
- traj, parameters.trajectory.lookahead.max_dist_m,
+ metrics::utils::get_lookahead_trajectory(
+ traj, ego_pose_, parameters.trajectory.lookahead.max_dist_m,
parameters.trajectory.lookahead.max_time_s));
case Metric::obstacle_distance:
return metrics::calcDistanceToObstacle(dynamic_objects_, traj);
@@ -105,9 +111,10 @@ void MetricsCalculator::setPredictedObjects(const PredictedObjects & objects)
dynamic_objects_ = objects;
}
-void MetricsCalculator::setEgoPose(const geometry_msgs::msg::Pose & pose)
+void MetricsCalculator::setEgoPose(const nav_msgs::msg::Odometry & ego_odometry)
{
- ego_pose_ = pose;
+ ego_pose_ = ego_odometry.pose.pose;
+ ego_odometry_ = ego_odometry;
}
Pose MetricsCalculator::getEgoPose()
@@ -115,33 +122,4 @@ Pose MetricsCalculator::getEgoPose()
return ego_pose_;
}
-Trajectory MetricsCalculator::getLookaheadTrajectory(
- const Trajectory & traj, const double max_dist_m, const double max_time_s) const
-{
- if (traj.points.empty()) {
- return traj;
- }
-
- const auto ego_index =
- autoware::motion_utils::findNearestSegmentIndex(traj.points, ego_pose_.position);
- Trajectory lookahead_traj;
- lookahead_traj.header = traj.header;
- double dist = 0.0;
- double time = 0.0;
- auto curr_point_it = std::next(traj.points.begin(), ego_index);
- auto prev_point_it = curr_point_it;
- while (curr_point_it != traj.points.end() && dist <= max_dist_m && time <= max_time_s) {
- lookahead_traj.points.push_back(*curr_point_it);
- const auto d = autoware::universe_utils::calcDistance2d(
- prev_point_it->pose.position, curr_point_it->pose.position);
- dist += d;
- if (prev_point_it->longitudinal_velocity_mps != 0.0) {
- time += d / std::abs(prev_point_it->longitudinal_velocity_mps);
- }
- prev_point_it = curr_point_it;
- ++curr_point_it;
- }
- return lookahead_traj;
-}
-
} // namespace planning_diagnostics
diff --git a/evaluator/autoware_planning_evaluator/src/motion_evaluator_node.cpp b/evaluator/autoware_planning_evaluator/src/motion_evaluator_node.cpp
index ac6f35179f771..d43aed1ec5687 100644
--- a/evaluator/autoware_planning_evaluator/src/motion_evaluator_node.cpp
+++ b/evaluator/autoware_planning_evaluator/src/motion_evaluator_node.cpp
@@ -19,6 +19,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -50,47 +51,52 @@ MotionEvaluatorNode::~MotionEvaluatorNode()
if (!output_metrics_) {
return;
}
-
- // generate json data
- using json = nlohmann::json;
- json j;
- for (Metric metric : metrics_) {
- const std::string base_name = metric_to_str.at(metric) + "/";
- const auto & stat = metrics_calculator_.calculate(metric, accumulated_trajectory_);
- if (stat) {
- j[base_name + "min"] = stat->min();
- j[base_name + "max"] = stat->max();
- j[base_name + "mean"] = stat->mean();
+ try {
+ // generate json data
+ using json = nlohmann::json;
+ json j;
+ for (Metric metric : metrics_) {
+ const std::string base_name = metric_to_str.at(metric) + "/";
+ const auto & stat = metrics_calculator_.calculate(metric, accumulated_trajectory_);
+ if (stat) {
+ j[base_name + "min"] = stat->min();
+ j[base_name + "max"] = stat->max();
+ j[base_name + "mean"] = stat->mean();
+ }
}
- }
- // get output folder
- const std::string output_folder_str =
- rclcpp::get_logging_directory().string() + "/autoware_metrics";
- if (!std::filesystem::exists(output_folder_str)) {
- if (!std::filesystem::create_directories(output_folder_str)) {
- RCLCPP_ERROR(
- this->get_logger(), "Failed to create directories: %s", output_folder_str.c_str());
- return;
+ // get output folder
+ const std::string output_folder_str =
+ rclcpp::get_logging_directory().string() + "/autoware_metrics";
+ if (!std::filesystem::exists(output_folder_str)) {
+ if (!std::filesystem::create_directories(output_folder_str)) {
+ RCLCPP_ERROR(
+ this->get_logger(), "Failed to create directories: %s", output_folder_str.c_str());
+ return;
+ }
}
- }
- // get time stamp
- std::time_t now_time_t = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
- std::tm * local_time = std::localtime(&now_time_t);
- std::ostringstream oss;
- oss << std::put_time(local_time, "%Y-%m-%d-%H-%M-%S");
- std::string cur_time_str = oss.str();
-
- // Write metrics .json to file
- const std::string output_file_str =
- output_folder_str + "/autoware_motion_evaluator-" + cur_time_str + ".json";
- std::ofstream f(output_file_str);
- if (f.is_open()) {
- f << j.dump(4);
- f.close();
- } else {
- RCLCPP_ERROR(this->get_logger(), "Failed to open file: %s", output_file_str.c_str());
+ // get time stamp
+ std::time_t now_time_t = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
+ std::tm * local_time = std::localtime(&now_time_t);
+ std::ostringstream oss;
+ oss << std::put_time(local_time, "%Y-%m-%d-%H-%M-%S");
+ std::string cur_time_str = oss.str();
+
+ // Write metrics .json to file
+ const std::string output_file_str =
+ output_folder_str + "/autoware_motion_evaluator-" + cur_time_str + ".json";
+ std::ofstream f(output_file_str);
+ if (f.is_open()) {
+ f << j.dump(4);
+ f.close();
+ } else {
+ RCLCPP_ERROR(this->get_logger(), "Failed to open file: %s", output_file_str.c_str());
+ }
+ } catch (const std::exception & e) {
+ std::cerr << "Exception in MotionEvaluatorNode destructor: " << e.what() << std::endl;
+ } catch (...) {
+ std::cerr << "Unknown exception in MotionEvaluatorNode destructor" << std::endl;
}
}
diff --git a/evaluator/autoware_planning_evaluator/src/planning_evaluator_node.cpp b/evaluator/autoware_planning_evaluator/src/planning_evaluator_node.cpp
index a61e56cd532ad..5889f15e48390 100644
--- a/evaluator/autoware_planning_evaluator/src/planning_evaluator_node.cpp
+++ b/evaluator/autoware_planning_evaluator/src/planning_evaluator_node.cpp
@@ -25,6 +25,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -50,6 +51,8 @@ PlanningEvaluatorNode::PlanningEvaluatorNode(const rclcpp::NodeOptions & node_op
declare_parameter("trajectory.lookahead.max_dist_m");
metrics_calculator_.parameters.trajectory.lookahead.max_time_s =
declare_parameter("trajectory.lookahead.max_time_s");
+ metrics_calculator_.parameters.trajectory.evaluation_time_s =
+ declare_parameter("trajectory.evaluation_time_s");
metrics_calculator_.parameters.obstacle.dist_thr_m =
declare_parameter("obstacle.dist_thr_m");
@@ -74,45 +77,51 @@ PlanningEvaluatorNode::~PlanningEvaluatorNode()
return;
}
- // generate json data
- using json = nlohmann::json;
- json j;
- for (Metric metric : metrics_) {
- const std::string base_name = metric_to_str.at(metric) + "/";
- j[base_name + "min"] = metric_accumulators_[static_cast(metric)][0].min();
- j[base_name + "max"] = metric_accumulators_[static_cast(metric)][1].max();
- j[base_name + "mean"] = metric_accumulators_[static_cast(metric)][2].mean();
- j[base_name + "count"] = metric_accumulators_[static_cast(metric)][2].count();
- j[base_name + "description"] = metric_descriptions.at(metric);
- }
+ try {
+ // generate json data
+ using json = nlohmann::json;
+ json j;
+ for (Metric metric : metrics_) {
+ const std::string base_name = metric_to_str.at(metric) + "/";
+ j[base_name + "min"] = metric_accumulators_[static_cast(metric)][0].min();
+ j[base_name + "max"] = metric_accumulators_[static_cast(metric)][1].max();
+ j[base_name + "mean"] = metric_accumulators_[static_cast(metric)][2].mean();
+ j[base_name + "count"] = metric_accumulators_[static_cast(metric)][2].count();
+ j[base_name + "description"] = metric_descriptions.at(metric);
+ }
- // get output folder
- const std::string output_folder_str =
- rclcpp::get_logging_directory().string() + "/autoware_metrics";
- if (!std::filesystem::exists(output_folder_str)) {
- if (!std::filesystem::create_directories(output_folder_str)) {
- RCLCPP_ERROR(
- this->get_logger(), "Failed to create directories: %s", output_folder_str.c_str());
- return;
+ // get output folder
+ const std::string output_folder_str =
+ rclcpp::get_logging_directory().string() + "/autoware_metrics";
+ if (!std::filesystem::exists(output_folder_str)) {
+ if (!std::filesystem::create_directories(output_folder_str)) {
+ RCLCPP_ERROR(
+ this->get_logger(), "Failed to create directories: %s", output_folder_str.c_str());
+ return;
+ }
}
- }
- // get time stamp
- std::time_t now_time_t = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
- std::tm * local_time = std::localtime(&now_time_t);
- std::ostringstream oss;
- oss << std::put_time(local_time, "%Y-%m-%d-%H-%M-%S");
- std::string cur_time_str = oss.str();
-
- // Write metrics .json to file
- const std::string output_file_str =
- output_folder_str + "/autoware_planning_evaluator-" + cur_time_str + ".json";
- std::ofstream f(output_file_str);
- if (f.is_open()) {
- f << j.dump(4);
- f.close();
- } else {
- RCLCPP_ERROR(this->get_logger(), "Failed to open file: %s", output_file_str.c_str());
+ // get time stamp
+ std::time_t now_time_t = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
+ std::tm * local_time = std::localtime(&now_time_t);
+ std::ostringstream oss;
+ oss << std::put_time(local_time, "%Y-%m-%d-%H-%M-%S");
+ std::string cur_time_str = oss.str();
+
+ // Write metrics .json to file
+ const std::string output_file_str =
+ output_folder_str + "/autoware_planning_evaluator-" + cur_time_str + ".json";
+ std::ofstream f(output_file_str);
+ if (f.is_open()) {
+ f << j.dump(4);
+ f.close();
+ } else {
+ RCLCPP_ERROR(this->get_logger(), "Failed to open file: %s", output_file_str.c_str());
+ }
+ } catch (const std::exception & e) {
+ std::cerr << "Exception in MotionEvaluatorNode destructor: " << e.what() << std::endl;
+ } catch (...) {
+ std::cerr << "Unknown exception in MotionEvaluatorNode destructor" << std::endl;
}
}
@@ -343,7 +352,7 @@ void PlanningEvaluatorNode::onModifiedGoal(
void PlanningEvaluatorNode::onOdometry(const Odometry::ConstSharedPtr odometry_msg)
{
if (!odometry_msg) return;
- metrics_calculator_.setEgoPose(odometry_msg->pose.pose);
+ metrics_calculator_.setEgoPose(*odometry_msg);
{
getRouteData();
if (route_handler_.isHandlerReady() && odometry_msg) {
diff --git a/launch/tier4_perception_launch/launch/object_recognition/detection/merger/camera_lidar_merger.launch.xml b/launch/tier4_perception_launch/launch/object_recognition/detection/merger/camera_lidar_merger.launch.xml
index fcfa9baf4ae20..236fea11d9dda 100644
--- a/launch/tier4_perception_launch/launch/object_recognition/detection/merger/camera_lidar_merger.launch.xml
+++ b/launch/tier4_perception_launch/launch/object_recognition/detection/merger/camera_lidar_merger.launch.xml
@@ -120,6 +120,7 @@
+
@@ -132,6 +133,7 @@
+
diff --git a/launch/tier4_perception_launch/launch/object_recognition/detection/merger/camera_lidar_radar_merger.launch.xml b/launch/tier4_perception_launch/launch/object_recognition/detection/merger/camera_lidar_radar_merger.launch.xml
index c289a81c906fe..5da942e8ff8f3 100644
--- a/launch/tier4_perception_launch/launch/object_recognition/detection/merger/camera_lidar_radar_merger.launch.xml
+++ b/launch/tier4_perception_launch/launch/object_recognition/detection/merger/camera_lidar_radar_merger.launch.xml
@@ -143,6 +143,7 @@
+
@@ -155,6 +156,7 @@
+
@@ -178,6 +180,7 @@
Control parameter 'use_radar_tracking_fusion' should defined in perception.launch.xml -->
+
diff --git a/launch/tier4_perception_launch/launch/object_recognition/detection/merger/lidar_merger.launch.xml b/launch/tier4_perception_launch/launch/object_recognition/detection/merger/lidar_merger.launch.xml
index a492e7667c347..4242903c1082d 100644
--- a/launch/tier4_perception_launch/launch/object_recognition/detection/merger/lidar_merger.launch.xml
+++ b/launch/tier4_perception_launch/launch/object_recognition/detection/merger/lidar_merger.launch.xml
@@ -58,6 +58,7 @@
+
@@ -70,6 +71,7 @@
+
diff --git a/launch/tier4_perception_launch/launch/object_recognition/tracking/tracking.launch.xml b/launch/tier4_perception_launch/launch/object_recognition/tracking/tracking.launch.xml
index ce13a742c6202..1d34dd279b5fa 100644
--- a/launch/tier4_perception_launch/launch/object_recognition/tracking/tracking.launch.xml
+++ b/launch/tier4_perception_launch/launch/object_recognition/tracking/tracking.launch.xml
@@ -57,6 +57,7 @@
+
diff --git a/localization/autoware_gyro_odometer/src/gyro_odometer_core.cpp b/localization/autoware_gyro_odometer/src/gyro_odometer_core.cpp
index 9511f168f346f..0a85f75b74ad7 100644
--- a/localization/autoware_gyro_odometer/src/gyro_odometer_core.cpp
+++ b/localization/autoware_gyro_odometer/src/gyro_odometer_core.cpp
@@ -73,7 +73,7 @@ GyroOdometerNode::GyroOdometerNode(const rclcpp::NodeOptions & node_options)
"twist_with_covariance", rclcpp::QoS{10});
diagnostics_ =
- std::make_unique(this, "gyro_odometer_status");
+ std::make_unique(this, "gyro_odometer_status");
// TODO(YamatoAndo) createTimer
}
diff --git a/localization/autoware_gyro_odometer/src/gyro_odometer_core.hpp b/localization/autoware_gyro_odometer/src/gyro_odometer_core.hpp
index 036b3d7cab527..b59e6af341ec2 100644
--- a/localization/autoware_gyro_odometer/src/gyro_odometer_core.hpp
+++ b/localization/autoware_gyro_odometer/src/gyro_odometer_core.hpp
@@ -15,7 +15,7 @@
#ifndef GYRO_ODOMETER_CORE_HPP_
#define GYRO_ODOMETER_CORE_HPP_
-#include "autoware/localization_util/diagnostics_module.hpp"
+#include "autoware/universe_utils/ros/diagnostics_interface.hpp"
#include "autoware/universe_utils/ros/logger_level_configure.hpp"
#include "autoware/universe_utils/ros/msg_covariance.hpp"
#include "autoware/universe_utils/ros/transform_listener.hpp"
@@ -80,7 +80,7 @@ class GyroOdometerNode : public rclcpp::Node
std::deque vehicle_twist_queue_;
std::deque gyro_queue_;
- std::unique_ptr diagnostics_;
+ std::unique_ptr diagnostics_;
};
} // namespace autoware::gyro_odometer
diff --git a/localization/autoware_landmark_based_localizer/autoware_lidar_marker_localizer/src/lidar_marker_localizer.cpp b/localization/autoware_landmark_based_localizer/autoware_lidar_marker_localizer/src/lidar_marker_localizer.cpp
index 2faf2d19168a5..34fc61797231b 100644
--- a/localization/autoware_landmark_based_localizer/autoware_lidar_marker_localizer/src/lidar_marker_localizer.cpp
+++ b/localization/autoware_landmark_based_localizer/autoware_lidar_marker_localizer/src/lidar_marker_localizer.cpp
@@ -124,22 +124,22 @@ LidarMarkerLocalizer::LidarMarkerLocalizer(const rclcpp::NodeOptions & node_opti
tf_buffer_ = std::make_shared(this->get_clock());
tf_listener_ = std::make_shared(*tf_buffer_, this, false);
- diagnostics_module_.reset(
- new autoware::localization_util::DiagnosticsModule(this, "marker_detection_status"));
+ diagnostics_interface_.reset(
+ new autoware::universe_utils::DiagnosticsInterface(this, "marker_detection_status"));
}
void LidarMarkerLocalizer::initialize_diagnostics()
{
- diagnostics_module_->clear();
- diagnostics_module_->add_key_value("is_received_map", false);
- diagnostics_module_->add_key_value("is_received_self_pose", false);
- diagnostics_module_->add_key_value("detect_marker_num", 0);
- diagnostics_module_->add_key_value("distance_self_pose_to_nearest_marker", 0.0);
- diagnostics_module_->add_key_value(
+ diagnostics_interface_->clear();
+ diagnostics_interface_->add_key_value("is_received_map", false);
+ diagnostics_interface_->add_key_value("is_received_self_pose", false);
+ diagnostics_interface_->add_key_value("detect_marker_num", 0);
+ diagnostics_interface_->add_key_value("distance_self_pose_to_nearest_marker", 0.0);
+ diagnostics_interface_->add_key_value(
"limit_distance_from_self_pose_to_nearest_marker",
param_.limit_distance_from_self_pose_to_nearest_marker);
- diagnostics_module_->add_key_value("distance_lanelet2_marker_to_detected_marker", 0.0);
- diagnostics_module_->add_key_value(
+ diagnostics_interface_->add_key_value("distance_lanelet2_marker_to_detected_marker", 0.0);
+ diagnostics_interface_->add_key_value(
"limit_distance_from_lanelet2_marker_to_detected_marker",
param_.limit_distance_from_self_pose_to_marker);
}
@@ -176,7 +176,7 @@ void LidarMarkerLocalizer::points_callback(const PointCloud2::ConstSharedPtr & p
main_process(points_msg_ptr);
- diagnostics_module_->publish(sensor_ros_time);
+ diagnostics_interface_->publish(sensor_ros_time);
}
void LidarMarkerLocalizer::main_process(const PointCloud2::ConstSharedPtr & points_msg_ptr)
@@ -186,13 +186,13 @@ void LidarMarkerLocalizer::main_process(const PointCloud2::ConstSharedPtr & poin
// (1) check if the map have be received
const std::vector map_landmarks = landmark_manager_.get_landmarks();
const bool is_received_map = !map_landmarks.empty();
- diagnostics_module_->add_key_value("is_received_map", is_received_map);
+ diagnostics_interface_->add_key_value("is_received_map", is_received_map);
if (!is_received_map) {
std::stringstream message;
message << "Not receive the landmark information. Please check if the vector map is being "
<< "published and if the landmark information is correctly specified.";
RCLCPP_INFO_STREAM_THROTTLE(this->get_logger(), *this->get_clock(), 1000, message.str());
- diagnostics_module_->update_level_and_message(
+ diagnostics_interface_->update_level_and_message(
diagnostic_msgs::msg::DiagnosticStatus::WARN, message.str());
return;
}
@@ -202,13 +202,13 @@ void LidarMarkerLocalizer::main_process(const PointCloud2::ConstSharedPtr & poin
interpolate_result = ekf_pose_buffer_->interpolate(sensor_ros_time);
const bool is_received_self_pose = interpolate_result != std::nullopt;
- diagnostics_module_->add_key_value("is_received_self_pose", is_received_self_pose);
+ diagnostics_interface_->add_key_value("is_received_self_pose", is_received_self_pose);
if (!is_received_self_pose) {
std::stringstream message;
message << "Could not get self_pose. Please check if the self pose is being published and if "
<< "the timestamp of the self pose is correctly specified";
RCLCPP_INFO_STREAM_THROTTLE(this->get_logger(), *this->get_clock(), 1000, message.str());
- diagnostics_module_->update_level_and_message(
+ diagnostics_interface_->update_level_and_message(
diagnostic_msgs::msg::DiagnosticStatus::WARN, message.str());
return;
}
@@ -221,7 +221,7 @@ void LidarMarkerLocalizer::main_process(const PointCloud2::ConstSharedPtr & poin
detect_landmarks(points_msg_ptr);
const bool is_detected_marker = !detected_landmarks.empty();
- diagnostics_module_->add_key_value("detect_marker_num", detected_landmarks.size());
+ diagnostics_interface_->add_key_value("detect_marker_num", detected_landmarks.size());
// (4) check distance to the nearest marker
const landmark_manager::Landmark nearest_marker = get_nearest_landmark(self_pose, map_landmarks);
@@ -230,7 +230,7 @@ void LidarMarkerLocalizer::main_process(const PointCloud2::ConstSharedPtr & poin
const double distance_from_self_pose_to_nearest_marker =
std::abs(nearest_marker_pose_on_base_link.position.x);
- diagnostics_module_->add_key_value(
+ diagnostics_interface_->add_key_value(
"distance_self_pose_to_nearest_marker", distance_from_self_pose_to_nearest_marker);
const bool is_exist_marker_within_self_pose =
@@ -242,14 +242,14 @@ void LidarMarkerLocalizer::main_process(const PointCloud2::ConstSharedPtr & poin
std::stringstream message;
message << "Could not detect marker, because the distance from self_pose to nearest_marker "
<< "is too far (" << distance_from_self_pose_to_nearest_marker << " [m]).";
- diagnostics_module_->update_level_and_message(
+ diagnostics_interface_->update_level_and_message(
diagnostic_msgs::msg::DiagnosticStatus::OK, message.str());
} else {
std::stringstream message;
message << "Could not detect marker, although the distance from self_pose to nearest_marker "
<< "is near (" << distance_from_self_pose_to_nearest_marker << " [m]).";
RCLCPP_INFO_STREAM_THROTTLE(this->get_logger(), *this->get_clock(), 1000, message.str());
- diagnostics_module_->update_level_and_message(
+ diagnostics_interface_->update_level_and_message(
diagnostic_msgs::msg::DiagnosticStatus::WARN, message.str());
}
return;
@@ -279,13 +279,13 @@ void LidarMarkerLocalizer::main_process(const PointCloud2::ConstSharedPtr & poin
const bool is_exist_marker_within_lanelet2_map =
diff_norm < param_.limit_distance_from_self_pose_to_marker;
- diagnostics_module_->add_key_value("distance_lanelet2_marker_to_detected_marker", diff_norm);
+ diagnostics_interface_->add_key_value("distance_lanelet2_marker_to_detected_marker", diff_norm);
if (!is_exist_marker_within_lanelet2_map) {
std::stringstream message;
message << "The distance from lanelet2 to the detect marker is too far(" << diff_norm
<< " [m]). The limit is " << param_.limit_distance_from_self_pose_to_marker << ".";
RCLCPP_INFO_STREAM_THROTTLE(this->get_logger(), *this->get_clock(), 1000, message.str());
- diagnostics_module_->update_level_and_message(
+ diagnostics_interface_->update_level_and_message(
diagnostic_msgs::msg::DiagnosticStatus::WARN, message.str());
return;
}
diff --git a/localization/autoware_landmark_based_localizer/autoware_lidar_marker_localizer/src/lidar_marker_localizer.hpp b/localization/autoware_landmark_based_localizer/autoware_lidar_marker_localizer/src/lidar_marker_localizer.hpp
index d1482c6912592..22a0c3f642563 100644
--- a/localization/autoware_landmark_based_localizer/autoware_lidar_marker_localizer/src/lidar_marker_localizer.hpp
+++ b/localization/autoware_landmark_based_localizer/autoware_lidar_marker_localizer/src/lidar_marker_localizer.hpp
@@ -15,8 +15,8 @@
#ifndef LIDAR_MARKER_LOCALIZER_HPP_
#define LIDAR_MARKER_LOCALIZER_HPP_
-#include "autoware/localization_util/diagnostics_module.hpp"
#include "autoware/localization_util/smart_pose_buffer.hpp"
+#include "autoware/universe_utils/ros/diagnostics_interface.hpp"
#include
@@ -134,7 +134,7 @@ class LidarMarkerLocalizer : public rclcpp::Node
rclcpp::Publisher::SharedPtr pub_debug_pose_with_covariance_;
rclcpp::Publisher::SharedPtr pub_marker_pointcloud_;
- std::shared_ptr diagnostics_module_;
+ std::shared_ptr diagnostics_interface_;
Param param_;
bool is_activated_;
diff --git a/localization/autoware_localization_error_monitor/CHANGELOG.rst b/localization/autoware_localization_error_monitor/CHANGELOG.rst
index e9583916e2e8f..69833a04a8d3a 100644
--- a/localization/autoware_localization_error_monitor/CHANGELOG.rst
+++ b/localization/autoware_localization_error_monitor/CHANGELOG.rst
@@ -43,8 +43,8 @@ Changelog for package autoware_localization_error_monitor
* unify package.xml version to 0.37.0
* refactor(localization_util)!: prefix package and namespace with autoware (`#8922 `_)
add autoware prefix to localization_util
-* fix(localization_error_monitor, system diag): fix to use diagnostics_module in localization_util (`#8543 `_)
- * fix(localization_error_monitor): fix to use diagnostics_module in localization_util
+* fix(localization_error_monitor, system diag): fix to use diagnostics_interface in localization_util (`#8543 `_)
+ * fix(localization_error_monitor): fix to use diagnostics_interface in localization_util
* fix: update media
* fix: update component name
* fix: rename include file
diff --git a/localization/autoware_localization_error_monitor/src/localization_error_monitor.cpp b/localization/autoware_localization_error_monitor/src/localization_error_monitor.cpp
index 63edbe5f6a9c7..1f26f6b80aa17 100644
--- a/localization/autoware_localization_error_monitor/src/localization_error_monitor.cpp
+++ b/localization/autoware_localization_error_monitor/src/localization_error_monitor.cpp
@@ -59,7 +59,7 @@ LocalizationErrorMonitor::LocalizationErrorMonitor(const rclcpp::NodeOptions & o
logger_configure_ = std::make_unique(this);
diagnostics_error_monitor_ =
- std::make_unique(this, "ellipse_error_status");
+ std::make_unique(this, "ellipse_error_status");
}
void LocalizationErrorMonitor::on_odom(nav_msgs::msg::Odometry::ConstSharedPtr input_msg)
diff --git a/localization/autoware_localization_error_monitor/src/localization_error_monitor.hpp b/localization/autoware_localization_error_monitor/src/localization_error_monitor.hpp
index 7b26573964b38..b7d2454eb9f75 100644
--- a/localization/autoware_localization_error_monitor/src/localization_error_monitor.hpp
+++ b/localization/autoware_localization_error_monitor/src/localization_error_monitor.hpp
@@ -16,7 +16,7 @@
#define LOCALIZATION_ERROR_MONITOR_HPP_
#include "autoware/localization_util/covariance_ellipse.hpp"
-#include "autoware/localization_util/diagnostics_module.hpp"
+#include "autoware/universe_utils/ros/diagnostics_interface.hpp"
#include
#include
@@ -39,7 +39,7 @@ class LocalizationErrorMonitor : public rclcpp::Node
std::unique_ptr logger_configure_;
- std::unique_ptr diagnostics_error_monitor_;
+ std::unique_ptr diagnostics_error_monitor_;
double scale_;
double error_ellipse_size_;
diff --git a/localization/autoware_localization_util/CMakeLists.txt b/localization/autoware_localization_util/CMakeLists.txt
index dd18f3cbad932..de62633124f3d 100644
--- a/localization/autoware_localization_util/CMakeLists.txt
+++ b/localization/autoware_localization_util/CMakeLists.txt
@@ -6,7 +6,6 @@ autoware_package()
ament_auto_add_library(${PROJECT_NAME} SHARED
src/util_func.cpp
- src/diagnostics_module.cpp
src/smart_pose_buffer.cpp
src/tree_structured_parzen_estimator.cpp
src/covariance_ellipse.cpp
diff --git a/localization/autoware_ndt_scan_matcher/include/autoware/ndt_scan_matcher/map_update_module.hpp b/localization/autoware_ndt_scan_matcher/include/autoware/ndt_scan_matcher/map_update_module.hpp
index d2dce42e3923e..12990259f88cd 100644
--- a/localization/autoware_ndt_scan_matcher/include/autoware/ndt_scan_matcher/map_update_module.hpp
+++ b/localization/autoware_ndt_scan_matcher/include/autoware/ndt_scan_matcher/map_update_module.hpp
@@ -15,8 +15,8 @@
#ifndef AUTOWARE__NDT_SCAN_MATCHER__MAP_UPDATE_MODULE_HPP_
#define AUTOWARE__NDT_SCAN_MATCHER__MAP_UPDATE_MODULE_HPP_
-#include "autoware/localization_util/diagnostics_module.hpp"
#include "autoware/localization_util/util_func.hpp"
+#include "autoware/universe_utils/ros/diagnostics_interface.hpp"
#include "hyper_parameters.hpp"
#include "ndt_omp/multigrid_ndt_omp.h"
#include "particle.hpp"
@@ -42,7 +42,7 @@
namespace autoware::ndt_scan_matcher
{
-using DiagnosticsModule = autoware::localization_util::DiagnosticsModule;
+using DiagnosticsInterface = autoware::universe_utils::DiagnosticsInterface;
class MapUpdateModule
{
@@ -63,19 +63,19 @@ class MapUpdateModule
void callback_timer(
const bool is_activated, const std::optional & position,
- std::unique_ptr & diagnostics_ptr);
+ std::unique_ptr & diagnostics_ptr);
[[nodiscard]] bool should_update_map(
const geometry_msgs::msg::Point & position,
- std::unique_ptr & diagnostics_ptr);
+ std::unique_ptr & diagnostics_ptr);
void update_map(
const geometry_msgs::msg::Point & position,
- std::unique_ptr & diagnostics_ptr);
+ std::unique_ptr & diagnostics_ptr);
// Update the specified NDT
bool update_ndt(
const geometry_msgs::msg::Point & position, NdtType & ndt,
- std::unique_ptr & diagnostics_ptr);
+ std::unique_ptr & diagnostics_ptr);
void publish_partial_pcd_map();
rclcpp::Publisher::SharedPtr loaded_pcd_pub_;
diff --git a/localization/autoware_ndt_scan_matcher/include/autoware/ndt_scan_matcher/ndt_scan_matcher_core.hpp b/localization/autoware_ndt_scan_matcher/include/autoware/ndt_scan_matcher/ndt_scan_matcher_core.hpp
index 22b6bfb2ff740..e083e6751c3db 100644
--- a/localization/autoware_ndt_scan_matcher/include/autoware/ndt_scan_matcher/ndt_scan_matcher_core.hpp
+++ b/localization/autoware_ndt_scan_matcher/include/autoware/ndt_scan_matcher/ndt_scan_matcher_core.hpp
@@ -17,8 +17,8 @@
#define FMT_HEADER_ONLY
-#include "autoware/localization_util/diagnostics_module.hpp"
#include "autoware/localization_util/smart_pose_buffer.hpp"
+#include "autoware/universe_utils/ros/diagnostics_interface.hpp"
#include "hyper_parameters.hpp"
#include "map_update_module.hpp"
#include "ndt_omp/multigrid_ndt_omp.h"
@@ -211,12 +211,12 @@ class NDTScanMatcher : public rclcpp::Node
std::unique_ptr regularization_pose_buffer_;
std::atomic is_activated_;
- std::unique_ptr diagnostics_scan_points_;
- std::unique_ptr diagnostics_initial_pose_;
- std::unique_ptr diagnostics_regularization_pose_;
- std::unique_ptr diagnostics_map_update_;
- std::unique_ptr diagnostics_ndt_align_;
- std::unique_ptr diagnostics_trigger_node_;
+ std::unique_ptr diagnostics_scan_points_;
+ std::unique_ptr diagnostics_initial_pose_;
+ std::unique_ptr diagnostics_regularization_pose_;
+ std::unique_ptr diagnostics_map_update_;
+ std::unique_ptr diagnostics_ndt_align_;
+ std::unique_ptr diagnostics_trigger_node_;
std::unique_ptr map_update_module_;
std::unique_ptr logger_configure_;
diff --git a/localization/autoware_ndt_scan_matcher/src/map_update_module.cpp b/localization/autoware_ndt_scan_matcher/src/map_update_module.cpp
index 25b51b55aebd7..299d596401b19 100644
--- a/localization/autoware_ndt_scan_matcher/src/map_update_module.cpp
+++ b/localization/autoware_ndt_scan_matcher/src/map_update_module.cpp
@@ -56,7 +56,7 @@ MapUpdateModule::MapUpdateModule(
void MapUpdateModule::callback_timer(
const bool is_activated, const std::optional & position,
- std::unique_ptr & diagnostics_ptr)
+ std::unique_ptr & diagnostics_ptr)
{
// check is_activated
diagnostics_ptr->add_key_value("is_activated", is_activated);
@@ -86,7 +86,8 @@ void MapUpdateModule::callback_timer(
}
bool MapUpdateModule::should_update_map(
- const geometry_msgs::msg::Point & position, std::unique_ptr & diagnostics_ptr)
+ const geometry_msgs::msg::Point & position,
+ std::unique_ptr & diagnostics_ptr)
{
last_update_position_mtx_.lock();
@@ -141,7 +142,8 @@ bool MapUpdateModule::out_of_map_range(const geometry_msgs::msg::Point & positio
}
void MapUpdateModule::update_map(
- const geometry_msgs::msg::Point & position, std::unique_ptr & diagnostics_ptr)
+ const geometry_msgs::msg::Point & position,
+ std::unique_ptr & diagnostics_ptr)
{
diagnostics_ptr->add_key_value("is_need_rebuild", need_rebuild_);
@@ -229,7 +231,7 @@ void MapUpdateModule::update_map(
bool MapUpdateModule::update_ndt(
const geometry_msgs::msg::Point & position, NdtType & ndt,
- std::unique_ptr & diagnostics_ptr)
+ std::unique_ptr & diagnostics_ptr)
{
diagnostics_ptr->add_key_value("maps_size_before", ndt.getCurrentMapIDs().size());
diff --git a/localization/autoware_ndt_scan_matcher/src/ndt_scan_matcher_core.cpp b/localization/autoware_ndt_scan_matcher/src/ndt_scan_matcher_core.cpp
index a1871023d525b..d3e1fa5982867 100644
--- a/localization/autoware_ndt_scan_matcher/src/ndt_scan_matcher_core.cpp
+++ b/localization/autoware_ndt_scan_matcher/src/ndt_scan_matcher_core.cpp
@@ -49,9 +49,9 @@ using autoware::localization_util::matrix4f_to_pose;
using autoware::localization_util::point_to_vector3d;
using autoware::localization_util::pose_to_matrix4f;
-using autoware::localization_util::DiagnosticsModule;
using autoware::localization_util::SmartPoseBuffer;
using autoware::localization_util::TreeStructuredParzenEstimator;
+using autoware::universe_utils::DiagnosticsInterface;
tier4_debug_msgs::msg::Float32Stamped make_float32_stamped(
const builtin_interfaces::msg::Time & stamp, const float data)
@@ -141,7 +141,7 @@ NDTScanMatcher::NDTScanMatcher(const rclcpp::NodeOptions & options)
std::make_unique(this->get_logger(), value_as_unlimited, value_as_unlimited);
diagnostics_regularization_pose_ =
- std::make_unique(this, "regularization_pose_subscriber_status");
+ std::make_unique(this, "regularization_pose_subscriber_status");
}
sensor_aligned_pose_pub_ =
@@ -209,13 +209,13 @@ NDTScanMatcher::NDTScanMatcher(const rclcpp::NodeOptions & options)
map_update_module_ =
std::make_unique(this, &ndt_ptr_mtx_, ndt_ptr_, param_.dynamic_map_loading);
- diagnostics_scan_points_ = std::make_unique(this, "scan_matching_status");
+ diagnostics_scan_points_ = std::make_unique(this, "scan_matching_status");
diagnostics_initial_pose_ =
- std::make_unique(this, "initial_pose_subscriber_status");
- diagnostics_map_update_ = std::make_unique(this, "map_update_status");
- diagnostics_ndt_align_ = std::make_unique(this, "ndt_align_service_status");
+ std::make_unique(this, "initial_pose_subscriber_status");
+ diagnostics_map_update_ = std::make_unique(this, "map_update_status");
+ diagnostics_ndt_align_ = std::make_unique(this, "ndt_align_service_status");
diagnostics_trigger_node_ =
- std::make_unique(this, "trigger_node_service_status");
+ std::make_unique(this, "trigger_node_service_status");
logger_configure_ = std::make_unique(this);
}
diff --git a/localization/autoware_pose_initializer/package.xml b/localization/autoware_pose_initializer/package.xml
index eeeb46a8db3e5..de3ecd880ea45 100644
--- a/localization/autoware_pose_initializer/package.xml
+++ b/localization/autoware_pose_initializer/package.xml
@@ -21,7 +21,6 @@
autoware_component_interface_specs
autoware_component_interface_utils
- autoware_localization_util
autoware_map_height_fitter
autoware_motion_utils
autoware_universe_utils
diff --git a/localization/autoware_pose_initializer/src/pose_initializer_core.cpp b/localization/autoware_pose_initializer/src/pose_initializer_core.cpp
index 5e9c68d2acc80..5bde25a564f1d 100644
--- a/localization/autoware_pose_initializer/src/pose_initializer_core.cpp
+++ b/localization/autoware_pose_initializer/src/pose_initializer_core.cpp
@@ -40,7 +40,7 @@ PoseInitializer::PoseInitializer(const rclcpp::NodeOptions & options)
output_pose_covariance_ = get_covariance_parameter(this, "output_pose_covariance");
gnss_particle_covariance_ = get_covariance_parameter(this, "gnss_particle_covariance");
- diagnostics_pose_reliable_ = std::make_unique(
+ diagnostics_pose_reliable_ = std::make_unique(
this, "pose_initializer_status");
if (declare_parameter("ekf_enabled")) {
diff --git a/localization/autoware_pose_initializer/src/pose_initializer_core.hpp b/localization/autoware_pose_initializer/src/pose_initializer_core.hpp
index 28d2eae08c3f1..a0c1ed3a86576 100644
--- a/localization/autoware_pose_initializer/src/pose_initializer_core.hpp
+++ b/localization/autoware_pose_initializer/src/pose_initializer_core.hpp
@@ -15,10 +15,9 @@
#ifndef POSE_INITIALIZER_CORE_HPP_
#define POSE_INITIALIZER_CORE_HPP_
-#include "autoware/localization_util/diagnostics_module.hpp"
-
#include
#include
+#include
#include
#include
@@ -61,7 +60,7 @@ class PoseInitializer : public rclcpp::Node
std::unique_ptr ekf_localization_trigger_;
std::unique_ptr ndt_localization_trigger_;
std::unique_ptr logger_configure_;
- std::unique_ptr diagnostics_pose_reliable_;
+ std::unique_ptr diagnostics_pose_reliable_;
double stop_check_duration_;
void change_node_trigger(bool flag, bool need_spin = false);
diff --git a/perception/autoware_bytetrack/lib/src/lapjv.cpp b/perception/autoware_bytetrack/lib/src/lapjv.cpp
index 1b8b39ccbb9f7..8949c199f9b21 100644
--- a/perception/autoware_bytetrack/lib/src/lapjv.cpp
+++ b/perception/autoware_bytetrack/lib/src/lapjv.cpp
@@ -44,7 +44,7 @@
/** Column-reduction and reduction transfer for a dense cost matrix.
*/
-int_t _ccrrt_dense(
+int_t ccrrt_dense(
const uint_t n, cost_t * cost[], int_t * free_rows, int_t * x, int_t * y, cost_t * v)
{
int_t n_free_rows;
@@ -108,7 +108,7 @@ int_t _ccrrt_dense(
/** Augmenting row reduction for a dense cost matrix.
*/
-int_t _carr_dense(
+int_t carr_dense(
const uint_t n, cost_t * cost[], const uint_t n_free_rows, int_t * free_rows, int_t * x,
int_t * y, cost_t * v)
{
@@ -181,7 +181,7 @@ int_t _carr_dense(
/** Find columns with minimum d[j] and put them on the SCAN list.
*/
-uint_t _find_dense(
+uint_t find_dense(
const uint_t n, uint_t lo, const cost_t * d, int_t * cols, [[maybe_unused]] int_t * y)
{
uint_t hi = lo + 1;
@@ -202,7 +202,7 @@ uint_t _find_dense(
// Scan all columns in TODO starting from arbitrary column in SCAN
// and try to decrease d of the TODO columns using the SCAN column.
-int_t _scan_dense(
+int_t scan_dense(
const uint_t n, cost_t * cost[], uint_t * plo, uint_t * phi, cost_t * d, int_t * cols,
int_t * pred, const int_t * y, const cost_t * v)
{
@@ -267,7 +267,7 @@ int_t find_path_dense(
if (lo == hi) {
PRINTF("%d..%d -> find\n", lo, hi);
n_ready = lo;
- hi = _find_dense(n, lo, d, cols, y);
+ hi = find_dense(n, lo, d, cols, y);
PRINTF("check %d..%d\n", lo, hi);
PRINT_INDEX_ARRAY(cols, n);
for (uint_t k = lo; k < hi; k++) {
@@ -279,7 +279,7 @@ int_t find_path_dense(
}
if (final_j == -1) {
PRINTF("%d..%d -> scan\n", lo, hi);
- final_j = _scan_dense(n, cost, &lo, &hi, d, cols, pred, y, v);
+ final_j = scan_dense(n, cost, &lo, &hi, d, cols, pred, y, v);
PRINT_COST_ARRAY(d, n);
PRINT_INDEX_ARRAY(cols, n);
PRINT_INDEX_ARRAY(pred, n);
@@ -304,7 +304,7 @@ int_t find_path_dense(
/** Augment for a dense cost matrix.
*/
-int_t _ca_dense(
+int_t ca_dense(
const uint_t n, cost_t * cost[], const uint_t n_free_rows, int_t * free_rows, int_t * x,
int_t * y, cost_t * v)
{
@@ -348,14 +348,14 @@ int lapjv_internal(const uint_t n, cost_t * cost[], int_t * x, int_t * y)
NEW(free_rows, int_t, n);
NEW(v, cost_t, n);
- ret = _ccrrt_dense(n, cost, free_rows, x, y, v);
+ ret = ccrrt_dense(n, cost, free_rows, x, y, v);
int i = 0;
while (ret > 0 && i < 2) {
- ret = _carr_dense(n, cost, ret, free_rows, x, y, v);
+ ret = carr_dense(n, cost, ret, free_rows, x, y, v);
i++;
}
if (ret > 0) {
- ret = _ca_dense(n, cost, ret, free_rows, x, y, v);
+ ret = ca_dense(n, cost, ret, free_rows, x, y, v);
}
FREE(v);
FREE(free_rows);
diff --git a/perception/autoware_detected_object_validation/config/obstacle_pointcloud_based_validator.param.yaml b/perception/autoware_detected_object_validation/config/obstacle_pointcloud_based_validator.param.yaml
index cddee782e8af0..37b77eb436c7d 100644
--- a/perception/autoware_detected_object_validation/config/obstacle_pointcloud_based_validator.param.yaml
+++ b/perception/autoware_detected_object_validation/config/obstacle_pointcloud_based_validator.param.yaml
@@ -12,5 +12,7 @@
#UNKNOWN, CAR, TRUCK, BUS, TRAILER, MOTORBIKE, BICYCLE, PEDESTRIAN
[800.0, 800.0, 800.0, 800.0, 800.0, 800.0, 800.0, 800.0]
+ validate_max_distance_m: 70.0 # [m]
+
using_2d_validator: false
enable_debugger: false
diff --git a/perception/autoware_detected_object_validation/schema/obstacle_pointcloud_based_validator.schema.json b/perception/autoware_detected_object_validation/schema/obstacle_pointcloud_based_validator.schema.json
index d7aa970993ca1..95c83a90f075f 100644
--- a/perception/autoware_detected_object_validation/schema/obstacle_pointcloud_based_validator.schema.json
+++ b/perception/autoware_detected_object_validation/schema/obstacle_pointcloud_based_validator.schema.json
@@ -30,6 +30,11 @@
"default": [800, 800, 800, 800, 800, 800, 800, 800],
"description": "Threshold value of the number of point clouds per object when the distance from baselink is 1m, because the number of point clouds varies with the distance from baselink."
},
+ "validate_max_distance_m": {
+ "type": "number",
+ "default": 70.0,
+ "description": "The maximum distance from the baselink to the object to be validated"
+ },
"using_2d_validator": {
"type": "boolean",
"default": false,
diff --git a/perception/autoware_detected_object_validation/src/obstacle_pointcloud/obstacle_pointcloud_validator.cpp b/perception/autoware_detected_object_validation/src/obstacle_pointcloud/obstacle_pointcloud_validator.cpp
index 194f333acd87e..979cdd3909f14 100644
--- a/perception/autoware_detected_object_validation/src/obstacle_pointcloud/obstacle_pointcloud_validator.cpp
+++ b/perception/autoware_detected_object_validation/src/obstacle_pointcloud/obstacle_pointcloud_validator.cpp
@@ -295,6 +295,8 @@ ObstaclePointCloudBasedValidator::ObstaclePointCloudBasedValidator(
declare_parameter>("max_points_num");
points_num_threshold_param_.min_points_and_distance_ratio =
declare_parameter>("min_points_and_distance_ratio");
+ const double validate_max_distance = declare_parameter("validate_max_distance_m");
+ validate_max_distance_sq_ = validate_max_distance * validate_max_distance;
using_2d_validator_ = declare_parameter("using_2d_validator");
@@ -346,6 +348,18 @@ void ObstaclePointCloudBasedValidator::onObjectsAndObstaclePointCloud(
for (size_t i = 0; i < transformed_objects.objects.size(); ++i) {
const auto & transformed_object = transformed_objects.objects.at(i);
const auto & object = input_objects->objects.at(i);
+ // check object distance
+ const double distance_sq =
+ transformed_object.kinematics.pose_with_covariance.pose.position.x *
+ transformed_object.kinematics.pose_with_covariance.pose.position.x +
+ transformed_object.kinematics.pose_with_covariance.pose.position.y *
+ transformed_object.kinematics.pose_with_covariance.pose.position.y;
+ if (distance_sq > validate_max_distance_sq_) {
+ // pass to output
+ output.objects.push_back(object);
+ continue;
+ }
+
const auto validated =
validation_is_ready ? validator_->validate_object(transformed_object) : false;
if (debugger_) {
diff --git a/perception/autoware_detected_object_validation/src/obstacle_pointcloud/obstacle_pointcloud_validator.hpp b/perception/autoware_detected_object_validation/src/obstacle_pointcloud/obstacle_pointcloud_validator.hpp
index 6d9a11634ea08..f10dbb7531d36 100644
--- a/perception/autoware_detected_object_validation/src/obstacle_pointcloud/obstacle_pointcloud_validator.hpp
+++ b/perception/autoware_detected_object_validation/src/obstacle_pointcloud/obstacle_pointcloud_validator.hpp
@@ -152,6 +152,7 @@ class ObstaclePointCloudBasedValidator : public rclcpp::Node
typedef message_filters::Synchronizer Sync;
Sync sync_;
PointsNumThresholdParam points_num_threshold_param_;
+ double validate_max_distance_sq_; // maximum object distance to validate, squared [m^2]
std::shared_ptr debugger_;
bool using_2d_validator_;
diff --git a/perception/autoware_ground_segmentation/src/scan_ground_filter/node.cpp b/perception/autoware_ground_segmentation/src/scan_ground_filter/node.cpp
index 488de2da47f91..74b4edbe595ea 100644
--- a/perception/autoware_ground_segmentation/src/scan_ground_filter/node.cpp
+++ b/perception/autoware_ground_segmentation/src/scan_ground_filter/node.cpp
@@ -246,7 +246,7 @@ void ScanGroundFilterComponent::classifyPointCloud(
float radius_distance_from_gnd = pd.radius - prev_gnd_radius;
float height_from_gnd = point_curr.z - prev_gnd_point.z;
float height_from_obj = point_curr.z - non_ground_cluster.getAverageHeight();
- bool calculate_slope = false;
+ bool calculate_slope = true;
bool is_point_close_to_prev =
(points_distance <
(pd.radius * radial_divider_angle_rad_ + split_points_distance_tolerance_));
@@ -264,8 +264,6 @@ void ScanGroundFilterComponent::classifyPointCloud(
// close to the previous point, set point follow label
point_label_curr = PointLabel::POINT_FOLLOW;
calculate_slope = false;
- } else {
- calculate_slope = true;
}
if (is_point_close_to_prev) {
height_from_gnd = point_curr.z - ground_cluster.getAverageHeight();
diff --git a/perception/autoware_image_projection_based_fusion/CMakeLists.txt b/perception/autoware_image_projection_based_fusion/CMakeLists.txt
index 73d305d2ab2a8..7c8160d6fe1b7 100644
--- a/perception/autoware_image_projection_based_fusion/CMakeLists.txt
+++ b/perception/autoware_image_projection_based_fusion/CMakeLists.txt
@@ -16,6 +16,7 @@ endif()
# Build non-CUDA dependent nodes
ament_auto_add_library(${PROJECT_NAME} SHARED
+ src/camera_projection.cpp
src/fusion_node.cpp
src/debugger.cpp
src/utils/geometry.cpp
diff --git a/perception/autoware_image_projection_based_fusion/README.md b/perception/autoware_image_projection_based_fusion/README.md
index c976697b0396d..dcf35e45bbd9d 100644
--- a/perception/autoware_image_projection_based_fusion/README.md
+++ b/perception/autoware_image_projection_based_fusion/README.md
@@ -66,6 +66,12 @@ ros2 launch autoware_image_projection_based_fusion pointpainting_fusion.launch.x
The rclcpp::TimerBase timer could not break a for loop, therefore even if time is out when fusing a roi msg at the middle, the program will run until all msgs are fused.
+### Approximate camera projection
+
+For algorithms like `pointpainting_fusion`, the computation required to project points onto an unrectified (raw) image can be substantial. To address this, an option is provided to reduce the computational load. Set the [`approximate_camera_projection parameter`](config/fusion_common.param.yaml) to `true` for each camera (ROIs). If the corresponding `point_project_to_unrectified_image` parameter is also set to true, the projections will be pre-cached.
+
+The cached projections are calculated using a grid, with the grid size specified by the `approximation_grid_width_size` and `approximation_grid_height_size` parameters in the [configuration file](config/fusion_common.param.yaml). The centers of the grid are used as the projected points.
+
### Detail description of each fusion's algorithm is in the following links
| Fusion Name | Description | Detail |
diff --git a/perception/autoware_image_projection_based_fusion/config/fusion_common.param.yaml b/perception/autoware_image_projection_based_fusion/config/fusion_common.param.yaml
index 662362c4fd7c5..86db3bad4f8f8 100644
--- a/perception/autoware_image_projection_based_fusion/config/fusion_common.param.yaml
+++ b/perception/autoware_image_projection_based_fusion/config/fusion_common.param.yaml
@@ -4,7 +4,8 @@
timeout_ms: 70.0
match_threshold_ms: 50.0
image_buffer_size: 15
- point_project_to_unrectified_image: false
+ # projection setting for each ROI whether unrectify image
+ point_project_to_unrectified_image: [false, false, false, false, false, false]
debug_mode: false
filter_scope_min_x: -100.0
filter_scope_min_y: -100.0
@@ -12,3 +13,12 @@
filter_scope_max_x: 100.0
filter_scope_max_y: 100.0
filter_scope_max_z: 100.0
+
+ # camera cache setting for each ROI
+ approximate_camera_projection: [true, true, true, true, true, true]
+ # grid size in pixels
+ approximation_grid_cell_width: 1.0
+ approximation_grid_cell_height: 1.0
+
+ # debug parameters
+ publish_processing_time_detail: false
diff --git a/perception/autoware_image_projection_based_fusion/include/autoware/image_projection_based_fusion/camera_projection.hpp b/perception/autoware_image_projection_based_fusion/include/autoware/image_projection_based_fusion/camera_projection.hpp
new file mode 100644
index 0000000000000..f9b3158b1672a
--- /dev/null
+++ b/perception/autoware_image_projection_based_fusion/include/autoware/image_projection_based_fusion/camera_projection.hpp
@@ -0,0 +1,81 @@
+// Copyright 2024 TIER IV, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef AUTOWARE__IMAGE_PROJECTION_BASED_FUSION__CAMERA_PROJECTION_HPP_
+#define AUTOWARE__IMAGE_PROJECTION_BASED_FUSION__CAMERA_PROJECTION_HPP_
+
+#define EIGEN_MPL2_ONLY
+
+#include
+#include
+
+#include
+
+#include
+
+#include
+
+namespace autoware::image_projection_based_fusion
+{
+struct PixelPos
+{
+ float x;
+ float y;
+};
+
+class CameraProjection
+{
+public:
+ explicit CameraProjection(
+ const sensor_msgs::msg::CameraInfo & camera_info, const float grid_cell_width,
+ const float grid_cell_height, const bool unrectify, const bool use_approximation);
+ CameraProjection() : cell_width_(1.0), cell_height_(1.0), unrectify_(false) {}
+ void initialize();
+ std::function calcImageProjectedPoint;
+ sensor_msgs::msg::CameraInfo getCameraInfo();
+ bool isOutsideHorizontalView(const float px, const float pz);
+ bool isOutsideVerticalView(const float py, const float pz);
+ bool isOutsideFOV(const float px, const float py, const float pz);
+
+protected:
+ bool calcRectifiedImageProjectedPoint(
+ const cv::Point3d & point3d, Eigen::Vector2d & projected_point);
+ bool calcRawImageProjectedPoint(const cv::Point3d & point3d, Eigen::Vector2d & projected_point);
+ bool calcRawImageProjectedPointWithApproximation(
+ const cv::Point3d & point3d, Eigen::Vector2d & projected_point);
+ void initializeCache();
+
+ sensor_msgs::msg::CameraInfo camera_info_;
+ uint32_t image_height_, image_width_;
+ double tan_h_x_, tan_h_y_;
+ double fov_left_, fov_right_, fov_top_, fov_bottom_;
+
+ uint32_t cache_size_;
+ float cell_width_;
+ float cell_height_;
+ float inv_cell_width_;
+ float inv_cell_height_;
+ int grid_width_;
+ int grid_height_;
+
+ bool unrectify_;
+ bool use_approximation_;
+
+ std::unique_ptr projection_cache_;
+ image_geometry::PinholeCameraModel camera_model_;
+};
+
+} // namespace autoware::image_projection_based_fusion
+
+#endif // AUTOWARE__IMAGE_PROJECTION_BASED_FUSION__CAMERA_PROJECTION_HPP_
diff --git a/perception/autoware_image_projection_based_fusion/include/autoware/image_projection_based_fusion/fusion_node.hpp b/perception/autoware_image_projection_based_fusion/include/autoware/image_projection_based_fusion/fusion_node.hpp
index c9b4f1f7b903f..239d406650ce8 100644
--- a/perception/autoware_image_projection_based_fusion/include/autoware/image_projection_based_fusion/fusion_node.hpp
+++ b/perception/autoware_image_projection_based_fusion/include/autoware/image_projection_based_fusion/fusion_node.hpp
@@ -15,9 +15,11 @@
#ifndef AUTOWARE__IMAGE_PROJECTION_BASED_FUSION__FUSION_NODE_HPP_
#define AUTOWARE__IMAGE_PROJECTION_BASED_FUSION__FUSION_NODE_HPP_
+#include
#include
#include
#include
+#include
#include
#include
@@ -54,6 +56,7 @@ using sensor_msgs::msg::PointCloud2;
using tier4_perception_msgs::msg::DetectedObjectsWithFeature;
using tier4_perception_msgs::msg::DetectedObjectWithFeature;
using PointCloud = pcl::PointCloud;
+using autoware::image_projection_based_fusion::CameraProjection;
using autoware_perception_msgs::msg::ObjectClassification;
template
@@ -85,7 +88,7 @@ class FusionNode : public rclcpp::Node
virtual void fuseOnSingleImage(
const TargetMsg3D & input_msg, const std::size_t image_id, const Msg2D & input_roi_msg,
- const sensor_msgs::msg::CameraInfo & camera_info, TargetMsg3D & output_msg) = 0;
+ TargetMsg3D & output_msg) = 0;
// set args if you need
virtual void postprocess(TargetMsg3D & output_msg);
@@ -99,11 +102,16 @@ class FusionNode : public rclcpp::Node
tf2_ros::Buffer tf_buffer_;
tf2_ros::TransformListener tf_listener_;
- bool point_project_to_unrectified_image_{false};
+ std::vector point_project_to_unrectified_image_;
// camera_info
std::map camera_info_map_;
std::vector::SharedPtr> camera_info_subs_;
+ // camera projection
+ std::vector camera_projectors_;
+ std::vector approx_camera_projection_;
+ float approx_grid_cell_w_size_;
+ float approx_grid_cell_h_size_;
rclcpp::TimerBase::SharedPtr timer_;
double timeout_ms_{};
@@ -142,6 +150,11 @@ class FusionNode : public rclcpp::Node
/** \brief processing time publisher. **/
std::unique_ptr> stop_watch_ptr_;
std::unique_ptr debug_publisher_;
+
+ // timekeeper
+ rclcpp::Publisher::SharedPtr
+ detailed_processing_time_publisher_;
+ std::shared_ptr time_keeper_;
};
} // namespace autoware::image_projection_based_fusion
diff --git a/perception/autoware_image_projection_based_fusion/include/autoware/image_projection_based_fusion/pointpainting_fusion/node.hpp b/perception/autoware_image_projection_based_fusion/include/autoware/image_projection_based_fusion/pointpainting_fusion/node.hpp
index 8c0e2ed78fc6c..cd6cd87976522 100644
--- a/perception/autoware_image_projection_based_fusion/include/autoware/image_projection_based_fusion/pointpainting_fusion/node.hpp
+++ b/perception/autoware_image_projection_based_fusion/include/autoware/image_projection_based_fusion/pointpainting_fusion/node.hpp
@@ -53,15 +53,12 @@ class PointPaintingFusionNode
void fuseOnSingleImage(
const sensor_msgs::msg::PointCloud2 & input_pointcloud_msg, const std::size_t image_id,
const DetectedObjectsWithFeature & input_roi_msg,
- const sensor_msgs::msg::CameraInfo & camera_info,
sensor_msgs::msg::PointCloud2 & painted_pointcloud_msg) override;
void postprocess(sensor_msgs::msg::PointCloud2 & painted_pointcloud_msg) override;
rclcpp::Publisher::SharedPtr obj_pub_ptr_;
- std::vector tan_h_; // horizontal field of view
-
int omp_num_threads_{1};
float score_threshold_{0.0};
std::vector class_names_;
diff --git a/perception/autoware_image_projection_based_fusion/include/autoware/image_projection_based_fusion/roi_cluster_fusion/node.hpp b/perception/autoware_image_projection_based_fusion/include/autoware/image_projection_based_fusion/roi_cluster_fusion/node.hpp
index 2c0283a190023..903b153af0681 100644
--- a/perception/autoware_image_projection_based_fusion/include/autoware/image_projection_based_fusion/roi_cluster_fusion/node.hpp
+++ b/perception/autoware_image_projection_based_fusion/include/autoware/image_projection_based_fusion/roi_cluster_fusion/node.hpp
@@ -38,7 +38,6 @@ class RoiClusterFusionNode
void fuseOnSingleImage(
const DetectedObjectsWithFeature & input_cluster_msg, const std::size_t image_id,
const DetectedObjectsWithFeature & input_roi_msg,
- const sensor_msgs::msg::CameraInfo & camera_info,
DetectedObjectsWithFeature & output_cluster_msg) override;
std::string trust_object_iou_mode_{"iou"};
@@ -53,6 +52,7 @@ class RoiClusterFusionNode
double fusion_distance_;
double trust_object_distance_;
std::string non_trust_object_iou_mode_{"iou_x"};
+
bool is_far_enough(const DetectedObjectWithFeature & obj, const double distance_threshold);
bool out_of_scope(const DetectedObjectWithFeature & obj) override;
double cal_iou_by_mode(
diff --git a/perception/autoware_image_projection_based_fusion/include/autoware/image_projection_based_fusion/roi_detected_object_fusion/node.hpp b/perception/autoware_image_projection_based_fusion/include/autoware/image_projection_based_fusion/roi_detected_object_fusion/node.hpp
index 7103537ec852d..43ec134168ef9 100644
--- a/perception/autoware_image_projection_based_fusion/include/autoware/image_projection_based_fusion/roi_detected_object_fusion/node.hpp
+++ b/perception/autoware_image_projection_based_fusion/include/autoware/image_projection_based_fusion/roi_detected_object_fusion/node.hpp
@@ -42,13 +42,11 @@ class RoiDetectedObjectFusionNode
void fuseOnSingleImage(
const DetectedObjects & input_object_msg, const std::size_t image_id,
- const DetectedObjectsWithFeature & input_roi_msg,
- const sensor_msgs::msg::CameraInfo & camera_info, DetectedObjects & output_object_msg) override;
+ const DetectedObjectsWithFeature & input_roi_msg, DetectedObjects & output_object_msg) override;
std::map generateDetectedObjectRoIs(
- const DetectedObjects & input_object_msg, const double image_width, const double image_height,
- const Eigen::Affine3d & object2camera_affine,
- const image_geometry::PinholeCameraModel & pinhole_camera_model);
+ const DetectedObjects & input_object_msg, const std::size_t & image_id,
+ const Eigen::Affine3d & object2camera_affine);
void fuseObjectsOnImage(
const DetectedObjects & input_object_msg,
diff --git a/perception/autoware_image_projection_based_fusion/include/autoware/image_projection_based_fusion/roi_pointcloud_fusion/node.hpp b/perception/autoware_image_projection_based_fusion/include/autoware/image_projection_based_fusion/roi_pointcloud_fusion/node.hpp
index 4de49df61a071..2f2c8222e196f 100644
--- a/perception/autoware_image_projection_based_fusion/include/autoware/image_projection_based_fusion/roi_pointcloud_fusion/node.hpp
+++ b/perception/autoware_image_projection_based_fusion/include/autoware/image_projection_based_fusion/roi_pointcloud_fusion/node.hpp
@@ -19,8 +19,10 @@
#include
+#include
#include
#include
+
namespace autoware::image_projection_based_fusion
{
class RoiPointCloudFusionNode
@@ -47,8 +49,7 @@ class RoiPointCloudFusionNode
void fuseOnSingleImage(
const PointCloud2 & input_pointcloud_msg, const std::size_t image_id,
- const DetectedObjectsWithFeature & input_roi_msg,
- const sensor_msgs::msg::CameraInfo & camera_info, PointCloud2 & output_pointcloud_msg) override;
+ const DetectedObjectsWithFeature & input_roi_msg, PointCloud2 & output_pointcloud_msg) override;
bool out_of_scope(const DetectedObjectWithFeature & obj) override;
};
diff --git a/perception/autoware_image_projection_based_fusion/include/autoware/image_projection_based_fusion/segmentation_pointcloud_fusion/node.hpp b/perception/autoware_image_projection_based_fusion/include/autoware/image_projection_based_fusion/segmentation_pointcloud_fusion/node.hpp
index b09e9521bdcdb..7454cb7bcd173 100644
--- a/perception/autoware_image_projection_based_fusion/include/autoware/image_projection_based_fusion/segmentation_pointcloud_fusion/node.hpp
+++ b/perception/autoware_image_projection_based_fusion/include/autoware/image_projection_based_fusion/segmentation_pointcloud_fusion/node.hpp
@@ -20,6 +20,7 @@
#include
#include
+#include
#include
#include
#include
@@ -60,7 +61,7 @@ class SegmentPointCloudFusionNode : public FusionNode getTransformStamped(
const tf2_ros::Buffer & tf_buffer, const std::string & target_frame_id,
const std::string & source_frame_id, const rclcpp::Time & time);
diff --git a/perception/autoware_image_projection_based_fusion/schema/fusion_common.schema.json b/perception/autoware_image_projection_based_fusion/schema/fusion_common.schema.json
index 73ee1661adaea..8077f3e2f3e30 100644
--- a/perception/autoware_image_projection_based_fusion/schema/fusion_common.schema.json
+++ b/perception/autoware_image_projection_based_fusion/schema/fusion_common.schema.json
@@ -31,6 +31,11 @@
"default": 15,
"minimum": 1
},
+ "point_project_to_unrectified_image": {
+ "type": "array",
+ "description": "An array of options indicating whether to project point to unrectified image or not.",
+ "default": [false, false, false, false, false, false]
+ },
"debug_mode": {
"type": "boolean",
"description": "Whether to debug or not.",
@@ -65,6 +70,21 @@
"type": "number",
"description": "Maximum z position [m].",
"default": 100.0
+ },
+ "approximate_camera_projection": {
+ "type": "array",
+ "description": "An array of options indicating whether to use approximated projection for each camera.",
+ "default": [true, true, true, true, true, true]
+ },
+ "approximation_grid_cell_width": {
+ "type": "number",
+ "description": "The width of grid cell used in approximated projection [pixel].",
+ "default": 1.0
+ },
+ "approximation_grid_cell_height": {
+ "type": "number",
+ "description": "The height of grid cell used in approximated projection [pixel].",
+ "default": 1.0
}
}
}
diff --git a/perception/autoware_image_projection_based_fusion/src/camera_projection.cpp b/perception/autoware_image_projection_based_fusion/src/camera_projection.cpp
new file mode 100644
index 0000000000000..c0a820609a0a7
--- /dev/null
+++ b/perception/autoware_image_projection_based_fusion/src/camera_projection.cpp
@@ -0,0 +1,252 @@
+// Copyright 2024 TIER IV, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "autoware/image_projection_based_fusion/camera_projection.hpp"
+
+#include
+
+namespace autoware::image_projection_based_fusion
+{
+CameraProjection::CameraProjection(
+ const sensor_msgs::msg::CameraInfo & camera_info, const float grid_cell_width,
+ const float grid_cell_height, const bool unrectify, const bool use_approximation = false)
+: camera_info_(camera_info),
+ cell_width_(grid_cell_width),
+ cell_height_(grid_cell_height),
+ unrectify_(unrectify),
+ use_approximation_(use_approximation)
+{
+ if (grid_cell_width <= 0.0 || grid_cell_height <= 0.0) {
+ throw std::runtime_error("Both grid_cell_width and grid_cell_height must be > 0.0");
+ }
+
+ image_width_ = camera_info.width;
+ image_height_ = camera_info.height;
+
+ // prepare camera model
+ camera_model_.fromCameraInfo(camera_info);
+
+ // cache settings
+ inv_cell_width_ = 1 / cell_width_;
+ inv_cell_height_ = 1 / cell_height_;
+ grid_width_ = static_cast(std::ceil(image_width_ / cell_width_));
+ grid_height_ = static_cast(std::ceil(image_height_ / cell_height_));
+ cache_size_ = grid_width_ * grid_height_;
+
+ // compute 3D rays for the image corners and pixels related to optical center
+ // to find the actual FOV size
+ // optical centers
+ const double ocx = static_cast(camera_info.k.at(2));
+ const double ocy = static_cast(camera_info.k.at(5));
+ // for checking pincushion shape case
+ const cv::Point3d ray_top_left = camera_model_.projectPixelTo3dRay(cv::Point(0, 0));
+ const cv::Point3d ray_top_right =
+ camera_model_.projectPixelTo3dRay(cv::Point(image_width_ - 1, 0));
+ const cv::Point3d ray_bottom_left =
+ camera_model_.projectPixelTo3dRay(cv::Point(0, image_height_ - 1));
+ const cv::Point3d ray_bottom_right =
+ camera_model_.projectPixelTo3dRay(cv::Point(image_width_ - 1, image_height_ - 1));
+ // for checking barrel shape case
+ const cv::Point3d ray_mid_top = camera_model_.projectPixelTo3dRay(cv::Point(ocx, 0));
+ const cv::Point3d ray_mid_left = camera_model_.projectPixelTo3dRay(cv::Point(0, ocy));
+ const cv::Point3d ray_mid_right =
+ camera_model_.projectPixelTo3dRay(cv::Point(image_width_ - 1, ocy));
+ const cv::Point3d ray_mid_bottom =
+ camera_model_.projectPixelTo3dRay(cv::Point(ocx, image_height_ - 1));
+
+ cv::Point3d x_left = ray_top_left;
+ cv::Point3d x_right = ray_top_right;
+ cv::Point3d y_top = ray_top_left;
+ cv::Point3d y_bottom = ray_bottom_left;
+
+ // check each side of the view
+ if (ray_bottom_left.x < x_left.x) x_left = ray_bottom_left;
+ if (ray_mid_left.x < x_left.x) x_left = ray_mid_left;
+
+ if (x_right.x < ray_bottom_right.x) x_right = ray_bottom_right;
+ if (x_right.x < ray_mid_right.x) x_right = ray_mid_right;
+
+ if (y_top.y < ray_top_right.y) y_top = ray_top_right;
+ if (y_top.y < ray_mid_top.y) y_top = ray_mid_top;
+
+ if (ray_bottom_left.y < y_bottom.y) y_bottom = ray_bottom_left;
+ if (ray_mid_bottom.y < y_bottom.y) y_bottom = ray_mid_bottom;
+
+ // set FOV at z = 1.0
+ fov_left_ = x_left.x / x_left.z;
+ fov_right_ = x_right.x / x_right.z;
+ fov_top_ = y_top.y / y_top.z;
+ fov_bottom_ = y_bottom.y / y_bottom.z;
+}
+
+void CameraProjection::initialize()
+{
+ if (unrectify_) {
+ if (use_approximation_) {
+ // create the cache with size of grid center
+ // store only xy position in float to reduce memory consumption
+ projection_cache_ = std::make_unique(cache_size_);
+ initializeCache();
+
+ calcImageProjectedPoint = [this](
+ const cv::Point3d & point3d, Eigen::Vector2d & projected_point) {
+ return this->calcRawImageProjectedPointWithApproximation(point3d, projected_point);
+ };
+ } else {
+ calcImageProjectedPoint = [this](
+ const cv::Point3d & point3d, Eigen::Vector2d & projected_point) {
+ return this->calcRawImageProjectedPoint(point3d, projected_point);
+ };
+ }
+ } else {
+ calcImageProjectedPoint = [this](
+ const cv::Point3d & point3d, Eigen::Vector2d & projected_point) {
+ return this->calcRectifiedImageProjectedPoint(point3d, projected_point);
+ };
+ }
+}
+
+void CameraProjection::initializeCache()
+{
+ // sample grid cell centers till the camera height, width to precompute the projections
+ //
+ // grid cell size
+ // /
+ // v
+ // |---| w
+ // 0----------------->
+ // 0 | . | . | . |
+ // |___|___|___|
+ // | . | . | . |
+ // | ^
+ // h | |
+ // v grid cell center
+ //
+ // each pixel will be rounded in these grid cell centers
+ // edge pixels in right and bottom side in the image will be assign to these centers
+ // that is the outside of the image
+
+ for (int idx_y = 0; idx_y < grid_height_; idx_y++) {
+ for (int idx_x = 0; idx_x < grid_width_; idx_x++) {
+ const uint32_t grid_index = idx_y * grid_width_ + idx_x;
+ const float px = (idx_x + 0.5f) * cell_width_;
+ const float py = (idx_y + 0.5f) * cell_height_;
+
+ // precompute projected point
+ cv::Point2d raw_image_point = camera_model_.unrectifyPoint(cv::Point2d(px, py));
+ projection_cache_[grid_index] =
+ PixelPos{static_cast(raw_image_point.x), static_cast(raw_image_point.y)};
+ }
+ }
+}
+
+/**
+ * @brief Calculate a projection of 3D point to rectified image plane 2D point.
+ * @return Return a boolean indicating whether the projected point is on the image plane.
+ */
+bool CameraProjection::calcRectifiedImageProjectedPoint(
+ const cv::Point3d & point3d, Eigen::Vector2d & projected_point)
+{
+ const cv::Point2d rectified_image_point = camera_model_.project3dToPixel(point3d);
+
+ if (
+ rectified_image_point.x < 0.0 || rectified_image_point.x >= image_width_ ||
+ rectified_image_point.y < 0.0 || rectified_image_point.y >= image_height_) {
+ return false;
+ } else {
+ projected_point << rectified_image_point.x, rectified_image_point.y;
+ return true;
+ }
+}
+
+/**
+ * @brief Calculate a projection of 3D point to raw image plane 2D point.
+ * @return Return a boolean indicating whether the projected point is on the image plane.
+ */
+bool CameraProjection::calcRawImageProjectedPoint(
+ const cv::Point3d & point3d, Eigen::Vector2d & projected_point)
+{
+ const cv::Point2d rectified_image_point = camera_model_.project3dToPixel(point3d);
+ const cv::Point2d raw_image_point = camera_model_.unrectifyPoint(rectified_image_point);
+
+ if (
+ rectified_image_point.x < 0.0 || rectified_image_point.x >= image_width_ ||
+ rectified_image_point.y < 0.0 || rectified_image_point.y >= image_height_) {
+ return false;
+ } else {
+ projected_point << raw_image_point.x, raw_image_point.y;
+ return true;
+ }
+}
+
+/**
+ * @brief Calculate a projection of 3D point to raw image plane 2D point with approximation.
+ * @return Return a boolean indicating whether the projected point is on the image plane.
+ */
+bool CameraProjection::calcRawImageProjectedPointWithApproximation(
+ const cv::Point3d & point3d, Eigen::Vector2d & projected_point)
+{
+ const cv::Point2d rectified_image_point = camera_model_.project3dToPixel(point3d);
+
+ // round to a near grid cell
+ const int grid_idx_x = static_cast(std::floor(rectified_image_point.x * inv_cell_width_));
+ const int grid_idx_y = static_cast