mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-06-13 01:10:07 +08:00
Compare commits
68 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b64ba9efe5 | |||
| 7ef57f6262 | |||
| 2a0b795760 | |||
| 911fc81c59 | |||
| b2fc5993cc | |||
| d5ddc9135d | |||
| 6b67ccb0ad | |||
| 0e6b904e80 | |||
| 864df9fc7b | |||
| d17a5b2c26 | |||
| d46a9266ce | |||
| 3a6f566e80 | |||
| d84903d520 | |||
| 4331f880f5 | |||
| 11007dc893 | |||
| fd4b958790 | |||
| a06f062bf7 | |||
| 79bf7810d4 | |||
| 066e8f7fea | |||
| 08dc2a776e | |||
| 061fe4806e | |||
| 4bebbbae93 | |||
| e52ce5c43b | |||
| 32c94bd3b1 | |||
| b08fefa903 | |||
| 302d0601bf | |||
| c90811a277 | |||
| 79a7ef2869 | |||
| b9f4de0b51 | |||
| 14cbcee49f | |||
| f38aba3c5b | |||
| 84933cfbdf | |||
| be3e1fb2ef | |||
| 82850cb149 | |||
| 3d457528d2 | |||
| d74007dc87 | |||
| 47b3f5f6f9 | |||
| 6d8441dc89 | |||
| f29afe1342 | |||
| 9849d90877 | |||
| 497704f3b9 | |||
| b60aa5dd2b | |||
| 5d151c54a4 | |||
| 83a4d648e3 | |||
| 0646fa6c9d | |||
| d9b3e48ec5 | |||
| 29fefeeada | |||
| 618a6aa98f | |||
| 8a007d38e7 | |||
| e831c66ae1 | |||
| 021eee0c5c | |||
| 385450ca37 | |||
| 23c9af20da | |||
| d196d37ef2 | |||
| dc4aa749d3 | |||
| 767eb75662 | |||
| c29630f6ae | |||
| c511e72d4f | |||
| a235b5c87f | |||
| 87163c1578 | |||
| 841fccf6b9 | |||
| 8a3e227dc0 | |||
| ad0b6bdc6b | |||
| aecd1461d7 | |||
| 8017baa6e6 | |||
| 103a61450e | |||
| df242827d2 | |||
| d9996742be |
+83
@@ -105,6 +105,89 @@ Checks: '*,
|
||||
-readability-redundant-declaration,
|
||||
-readability-static-accessed-through-instance,
|
||||
-readability-static-definition-in-anonymous-namespace,
|
||||
-altera-struct-pack-align,
|
||||
-bugprone-easily-swappable-parameters,
|
||||
-concurrency-mt-unsafe,
|
||||
-cppcoreguidelines-avoid-const-or-ref-data-members,
|
||||
-cppcoreguidelines-macro-usage,
|
||||
-cppcoreguidelines-non-private-member-variables-in-classes,
|
||||
-hicpp-uppercase-literal-suffix,
|
||||
-llvm-qualified-auto,
|
||||
-misc-non-private-member-variables-in-classes,
|
||||
-misc-use-anonymous-namespace,
|
||||
-modernize-concat-nested-namespaces,
|
||||
-readability-const-return-type,
|
||||
-readability-identifier-length,
|
||||
-readability-isolate-declaration,
|
||||
-readability-qualified-auto,
|
||||
-readability-redundant-access-specifiers,
|
||||
-cppcoreguidelines-avoid-do-while,
|
||||
-misc-include-cleaner,
|
||||
-misc-const-correctness,
|
||||
-llvm-else-after-return,
|
||||
-readability-function-cognitive-complexity,
|
||||
-cppcoreguidelines-init-variables,
|
||||
-bugprone-reserved-identifier,
|
||||
-cert-dcl37-c,
|
||||
-cert-dcl51-cpp,
|
||||
-modernize-use-nodiscard,
|
||||
-misc-confusable-identifiers,
|
||||
-cert-err33-c,
|
||||
-readability-redundant-inline-specifier,
|
||||
-readability-uppercase-literal-suffix,
|
||||
-bugprone-narrowing-conversions,
|
||||
-cppcoreguidelines-narrowing-conversions,
|
||||
-bugprone-switch-missing-default-case,
|
||||
-cppcoreguidelines-avoid-goto,
|
||||
-hicpp-avoid-goto,
|
||||
-bugprone-branch-clone,
|
||||
-bugprone-unhandled-self-assignment,
|
||||
-cert-oop54-cpp,
|
||||
-performance-enum-size,
|
||||
-readability-avoid-nested-conditional-operator,
|
||||
-cppcoreguidelines-prefer-member-initializer,
|
||||
-cppcoreguidelines-explicit-virtual-functions,
|
||||
-cppcoreguidelines-virtual-class-destructor,
|
||||
-readability-convert-member-functions-to-static,
|
||||
-readability-make-member-function-const,
|
||||
-bugprone-assignment-in-if-condition,
|
||||
-bugprone-implicit-widening-of-multiplication-result,
|
||||
-bugprone-incorrect-roundings,
|
||||
-bugprone-macro-parentheses,
|
||||
-bugprone-multi-level-implicit-pointer-conversion,
|
||||
-bugprone-signed-char-misuse,
|
||||
-bugprone-too-small-loop-variable,
|
||||
-cppcoreguidelines-avoid-non-const-global-variables,
|
||||
-cppcoreguidelines-use-default-member-init,
|
||||
-hicpp-multiway-paths-covered,
|
||||
-hicpp-named-parameter,
|
||||
-misc-header-include-cycle,
|
||||
-misc-no-recursion,
|
||||
-performance-no-int-to-ptr,
|
||||
-readability-avoid-return-with-void-value,
|
||||
-readability-avoid-unconditional-preprocessor-if,
|
||||
-readability-delete-null-pointer,
|
||||
-readability-duplicate-include,
|
||||
-readability-redundant-casting,
|
||||
-readability-redundant-member-init,
|
||||
-readability-reference-to-constructed-temporary,
|
||||
-readability-simplify-boolean-expr,
|
||||
-bugprone-unsafe-functions,
|
||||
-cert-msc24-c,
|
||||
-cert-msc32-c,
|
||||
-cert-msc33-c,
|
||||
-cert-msc51-cpp,
|
||||
-cert-str34-c,
|
||||
-cppcoreguidelines-macro-to-enum,
|
||||
-modernize-macro-to-enum,
|
||||
-abseil-string-find-str-contains,
|
||||
-bugprone-suspicious-include,
|
||||
-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,
|
||||
-clang-analyzer-optin.core.EnumCastOutOfRange,
|
||||
-modernize-type-traits,
|
||||
-misc-definitions-in-headers,
|
||||
-bugprone-casting-through-void,
|
||||
-readability-redundant-string-init,
|
||||
'
|
||||
WarningsAsErrors: '*'
|
||||
CheckOptions:
|
||||
|
||||
@@ -2,6 +2,37 @@
|
||||
# - If you want to keep the tests running in GitHub Actions you need to uncomment the "runs-on: ubuntu-latest" lines
|
||||
# and comment the "runs-on: [runs-on,runner=..." lines.
|
||||
# - If you would like to duplicate this setup try setting up "RunsOn" on your own AWS account try https://runs-on.com
|
||||
#
|
||||
# ===================================================================================
|
||||
# RELEASE UPLOAD LOGIC
|
||||
# ===================================================================================
|
||||
# This workflow handles building firmware and uploading to S3 + GitHub Releases.
|
||||
#
|
||||
# S3 Bucket Structure (s3://px4-travis/Firmware/):
|
||||
# - master/ <- Latest main branch build (for QGC compatibility)
|
||||
# - stable/ <- Latest stable release, controlled by 'stable' branch
|
||||
# - beta/ <- Latest pre-release, controlled by 'beta' branch
|
||||
# - vX.Y.Z/ <- Archived stable release
|
||||
# - vX.Y.Z-beta1/ <- Archived pre-release
|
||||
#
|
||||
# Trigger Behavior:
|
||||
# - Tag v1.16.1 -> Upload to: v1.16.1/ only (versioned archive)
|
||||
# - Tag v1.17.0-beta1 -> Upload to: v1.17.0-beta1/ only (versioned archive)
|
||||
# - Branch main -> Upload to: master/ (for QGC compatibility)
|
||||
# - Branch stable -> Upload to: stable/ (QGC stable firmware)
|
||||
# - Branch beta -> Upload to: beta/ (QGC beta firmware)
|
||||
# - Branch release/** -> Build only, no S3 upload (CI validation)
|
||||
# - Pull requests -> Build only, no S3 upload (CI validation)
|
||||
#
|
||||
# GitHub Releases:
|
||||
# - All version tags create a draft GitHub Release
|
||||
# - Pre-releases (alpha/beta/rc suffixes) are automatically marked as such
|
||||
#
|
||||
# IMPORTANT: Version tags do NOT upload to stable/ or beta/. Only the
|
||||
# corresponding branch pushes control those directories. This prevents
|
||||
# pre-release tags from accidentally overwriting stable firmware (#26340)
|
||||
# and avoids race conditions between tag and branch builds.
|
||||
# ===================================================================================
|
||||
|
||||
name: Build all targets
|
||||
|
||||
@@ -163,6 +194,13 @@ jobs:
|
||||
path: ~/.ccache
|
||||
key: ${{ steps.cc_restore.outputs.cache-primary-key }}
|
||||
|
||||
# ===========================================================================
|
||||
# ARTIFACT UPLOAD JOB
|
||||
# ===========================================================================
|
||||
# Uploads build artifacts to S3 and creates GitHub Releases.
|
||||
# Runs for version tags (v*), main, stable, and beta branch pushes.
|
||||
# See header comments for full upload logic documentation.
|
||||
# ===========================================================================
|
||||
artifacts:
|
||||
name: Upload Artifacts
|
||||
# runs-on: ubuntu-latest
|
||||
@@ -181,31 +219,31 @@ jobs:
|
||||
- name: Choose Upload Location
|
||||
id: upload-location
|
||||
run: |
|
||||
# Determine upload location based on branch or tag with the following considerations:
|
||||
# Destination: AWS S3 bucket px4-travis in folder Firmware/
|
||||
# - If branch is main -> upload to master/
|
||||
# - Older versions of QGC are hardocded to look for master/
|
||||
# - If branch is stable or beta -> upload to stable/ or beta/
|
||||
# - If a tag vX.Y.Z -> upload to vX.Y.Z/
|
||||
# - Also update stable/ to point to the same version
|
||||
#. - Older versions of QGC are hardocded to look for stable/
|
||||
# - If a pull request -> do not upload
|
||||
set -euo pipefail
|
||||
|
||||
ref="${GITHUB_REF}"
|
||||
branch=${{ needs.group_targets.outputs.branchname }}
|
||||
location="$branch"
|
||||
is_prerelease="false"
|
||||
|
||||
# Main branch uploads to "master" for QGC backward compatibility
|
||||
if [[ "$branch" == "main" ]]; then
|
||||
location="master"
|
||||
fi
|
||||
|
||||
# Version tags: upload to versioned directory (e.g., v1.16.1/)
|
||||
if [[ "$ref" == refs/tags/v[0-9]* ]]; then
|
||||
tag="${ref#refs/tags/}"
|
||||
location="$tag"
|
||||
|
||||
# Pre-release tags contain -alpha, -beta, or -rc suffix
|
||||
if [[ "$tag" =~ -(alpha|beta|rc) ]]; then
|
||||
is_prerelease="true"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "uploadlocation=$location" >> $GITHUB_OUTPUT
|
||||
echo "is_prerelease=$is_prerelease" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Uploading Artifacts to S3 [${{ steps.upload-location.outputs.uploadlocation }}]
|
||||
uses: jakejarvis/s3-sync-action@master
|
||||
@@ -219,28 +257,13 @@ jobs:
|
||||
SOURCE_DIR: artifacts/
|
||||
DEST_DIR: Firmware/${{ steps.upload-location.outputs.uploadlocation }}/
|
||||
|
||||
# if we are uploading artifacts to a versioned folder
|
||||
# we should also update the stable folder in the s3 bucket
|
||||
- name: Uploading Artifacts to S3 [stable]
|
||||
uses: jakejarvis/s3-sync-action@master
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
with:
|
||||
args: --acl public-read
|
||||
env:
|
||||
AWS_S3_BUCKET: 'px4-travis'
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
AWS_REGION: 'us-west-1'
|
||||
SOURCE_DIR: artifacts/
|
||||
DEST_DIR: Firmware/stable/
|
||||
|
||||
# if build is a release triggered by a versioned tag then create a github release
|
||||
# and upload the build artifacts. A draft release is created so that the release
|
||||
# can be reviewed before publishing
|
||||
# Create a draft GitHub Release for all version tags
|
||||
# Pre-releases are automatically marked as such
|
||||
- name: Upload Artifacts to GitHub Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
with:
|
||||
draft: true
|
||||
prerelease: ${{ steps.upload-location.outputs.is_prerelease == 'true' }}
|
||||
files: artifacts/*.px4
|
||||
name: ${{ steps.upload-location.outputs.uploadlocation }}
|
||||
|
||||
@@ -19,6 +19,10 @@ concurrency:
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
container:
|
||||
image: px4io/px4-dev:v1.16.0-rc1-258-g0369abd556
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -35,20 +39,17 @@ jobs:
|
||||
"px4_sitl_allyes",
|
||||
"module_documentation",
|
||||
]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Building [${{ matrix.check }}]
|
||||
uses: addnab/docker-run-action@v3
|
||||
with:
|
||||
image: px4io/px4-dev:v1.16.0-rc1-258-g0369abd556
|
||||
options: -v ${{ github.workspace }}:/workspace
|
||||
run: |
|
||||
cd /workspace
|
||||
git config --global --add safe.directory /workspace
|
||||
make ${{ matrix.check }}
|
||||
run: |
|
||||
cd "$GITHUB_WORKSPACE"
|
||||
git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
||||
make ${{ matrix.check }}
|
||||
|
||||
- name: Uploading Coverage to Codecov.io
|
||||
if: contains(matrix.check, 'coverage')
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
name: Clang Tidy
|
||||
name: Static Analysis
|
||||
|
||||
on:
|
||||
push:
|
||||
@@ -11,20 +11,59 @@ on:
|
||||
- '**'
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
clang_tidy:
|
||||
name: Clang-Tidy
|
||||
runs-on: [runs-on, runner=16cpu-linux-x64, "run-id=${{ github.run_id }}", "extras=s3-cache"]
|
||||
container:
|
||||
image: px4io/px4-dev:v1.17.0-beta1
|
||||
steps:
|
||||
- uses: runs-on/action@v2
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
fetch-tags: true
|
||||
|
||||
- name: Testing (clang-tidy)
|
||||
uses: addnab/docker-run-action@v3
|
||||
- name: Configure Git Safe Directory
|
||||
run: git config --system --add safe.directory '*'
|
||||
|
||||
- name: Restore Compiler Cache
|
||||
id: cc_restore
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
image: px4io/px4-dev-clang:2021-09-08
|
||||
options: -v ${{ github.workspace }}:/workspace
|
||||
run: |
|
||||
cd /workspace
|
||||
git config --global --add safe.directory /workspace
|
||||
make clang-tidy
|
||||
path: ~/.ccache
|
||||
key: ccache-clang-tidy-${{ github.head_ref || github.ref_name }}
|
||||
restore-keys: |
|
||||
ccache-clang-tidy-${{ github.head_ref || github.ref_name }}-
|
||||
ccache-clang-tidy-main-
|
||||
ccache-clang-tidy-
|
||||
|
||||
- name: Configure Compiler Cache
|
||||
run: |
|
||||
mkdir -p ~/.ccache
|
||||
echo "base_dir = ${GITHUB_WORKSPACE}" > ~/.ccache/ccache.conf
|
||||
echo "compression = true" >> ~/.ccache/ccache.conf
|
||||
echo "compression_level = 6" >> ~/.ccache/ccache.conf
|
||||
echo "max_size = 120M" >> ~/.ccache/ccache.conf
|
||||
echo "hash_dir = false" >> ~/.ccache/ccache.conf
|
||||
echo "compiler_check = content" >> ~/.ccache/ccache.conf
|
||||
ccache -s
|
||||
ccache -z
|
||||
|
||||
- name: Run Clang-Tidy Analysis
|
||||
run: make -j16 clang-tidy
|
||||
|
||||
- name: Compiler Cache Stats
|
||||
if: always()
|
||||
run: ccache -s
|
||||
|
||||
- name: Save Compiler Cache
|
||||
if: always()
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ${{ steps.cc_restore.outputs.cache-primary-key }}
|
||||
|
||||
@@ -15,21 +15,21 @@ concurrency:
|
||||
jobs:
|
||||
unit_tests:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: main test
|
||||
uses: addnab/docker-run-action@v3
|
||||
with:
|
||||
image: px4io/px4-dev:v1.16.0-rc1-258-g0369abd556
|
||||
options: -v ${{ github.workspace }}:/workspace
|
||||
container:
|
||||
image: px4io/px4-dev:v1.16.0-rc1-258-g0369abd556
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: main test
|
||||
run: |
|
||||
cd /workspace
|
||||
git config --global --add safe.directory /workspace
|
||||
cd "$GITHUB_WORKSPACE"
|
||||
git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
||||
make tests TESTFILTER=EKF
|
||||
|
||||
- name: Check if there is a functional change
|
||||
run: git diff --exit-code
|
||||
working-directory: src/modules/ekf2/test/change_indication
|
||||
- name: Check if there is a functional change
|
||||
run: git diff --exit-code
|
||||
working-directory: src/modules/ekf2/test/change_indication
|
||||
|
||||
@@ -8,40 +8,47 @@ on:
|
||||
jobs:
|
||||
unit_tests:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
container:
|
||||
image: px4io/px4-dev:v1.16.0-rc1-258-g0369abd556
|
||||
|
||||
env:
|
||||
GIT_COMMITTER_EMAIL: bot@px4.io
|
||||
GIT_COMMITTER_NAME: PX4BuildBot
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: main test
|
||||
uses: addnab/docker-run-action@v3
|
||||
with:
|
||||
image: px4io/px4-dev:v1.16.0-rc1-258-g0369abd556
|
||||
options: -v ${{ github.workspace }}:/workspace
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: main test
|
||||
run: |
|
||||
cd /workspace
|
||||
git config --global --add safe.directory /workspace
|
||||
cd "$GITHUB_WORKSPACE"
|
||||
git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
||||
make tests TESTFILTER=EKF
|
||||
|
||||
- name: Check if there exists diff and save result in variable
|
||||
id: diff-check
|
||||
run: echo "CHANGE_INDICATED=$(git diff --exit-code --output=/dev/null || echo $?)" >> $GITHUB_OUTPUT
|
||||
working-directory: src/modules/ekf2/test/change_indication
|
||||
- name: Check if there exists diff and save result in variable
|
||||
id: diff-check
|
||||
working-directory: src/modules/ekf2/test/change_indication
|
||||
run: |
|
||||
if git diff --quiet; then
|
||||
echo "CHANGE_INDICATED=false" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "CHANGE_INDICATED=true" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: auto-commit any changes to change indication
|
||||
uses: stefanzweifel/git-auto-commit-action@v4
|
||||
with:
|
||||
file_pattern: 'src/modules/ekf2/test/change_indication/*.csv'
|
||||
commit_user_name: ${GIT_COMMITTER_NAME}
|
||||
commit_user_email: ${GIT_COMMITTER_EMAIL}
|
||||
commit_message: |
|
||||
'[AUTO COMMIT] update change indication'
|
||||
- name: auto-commit any changes to change indication
|
||||
if: steps.diff-check.outputs.CHANGE_INDICATED == 'true'
|
||||
uses: stefanzweifel/git-auto-commit-action@v4
|
||||
with:
|
||||
file_pattern: 'src/modules/ekf2/test/change_indication/*.csv'
|
||||
commit_user_name: ${{ env.GIT_COMMITTER_NAME }}
|
||||
commit_user_email: ${{ env.GIT_COMMITTER_EMAIL }}
|
||||
commit_message: |
|
||||
[AUTO COMMIT] update change indication
|
||||
|
||||
See .github/workflopws/ekf_update_change_indicator.yml for more details
|
||||
See .github/workflows/ekf_update_change_indicator.yml for more details
|
||||
|
||||
- name: if there is a functional change, fail check
|
||||
if: ${{ steps.diff-check.outputs.CHANGE_INDICATED }}
|
||||
run: exit 1
|
||||
- name: if there is a functional change, fail check
|
||||
if: steps.diff-check.outputs.CHANGE_INDICATED == 'true'
|
||||
run: exit 1
|
||||
|
||||
@@ -19,25 +19,27 @@ concurrency:
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
config:
|
||||
- {vehicle: "iris", mission: "MC_mission_box"}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Build SITL and Run Tests
|
||||
uses: addnab/docker-run-action@v3
|
||||
with:
|
||||
image: px4io/px4-dev-ros-melodic:2021-09-08
|
||||
options: -v ${{ github.workspace }}:/workspace
|
||||
- name: Build SITL and Run Tests (inside old ROS container)
|
||||
run: |
|
||||
cd /workspace
|
||||
git config --global --add safe.directory /workspace
|
||||
make px4_sitl_default
|
||||
make px4_sitl_default sitl_gazebo-classic
|
||||
./test/rostest_px4_run.sh mavros_posix_test_mission.test mission:=${{matrix.config.mission}} vehicle:=${{matrix.config.vehicle}}
|
||||
docker run --rm \
|
||||
-v "${GITHUB_WORKSPACE}:/workspace" \
|
||||
-w /workspace \
|
||||
px4io/px4-dev-ros-melodic:2021-09-08 \
|
||||
bash -c '
|
||||
git config --global --add safe.directory /workspace
|
||||
make px4_sitl_default
|
||||
make px4_sitl_default sitl_gazebo-classic
|
||||
./test/rostest_px4_run.sh \
|
||||
mavros_posix_test_mission.test \
|
||||
mission:=MC_mission_box \
|
||||
vehicle:=iris
|
||||
'
|
||||
|
||||
@@ -19,27 +19,26 @@ concurrency:
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
config:
|
||||
- {test_file: "mavros_posix_tests_offboard_posctl.test", vehicle: "iris"}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Build PX4 and Run Tests
|
||||
uses: addnab/docker-run-action@v3
|
||||
with:
|
||||
image: px4io/px4-dev-ros-melodic:2021-09-08
|
||||
options: -v ${{ github.workspace }}:/workspace
|
||||
- name: Build SITL and Run Tests (inside old ROS container)
|
||||
run: |
|
||||
cd /workspace
|
||||
git config --global --add safe.directory /workspace
|
||||
make px4_sitl_default
|
||||
make px4_sitl_default sitl_gazebo-classic
|
||||
./test/rostest_px4_run.sh ${{matrix.config.test_file}} vehicle:=${{matrix.config.vehicle}}
|
||||
docker run --rm \
|
||||
-v "${GITHUB_WORKSPACE}:/workspace" \
|
||||
-w /workspace \
|
||||
px4io/px4-dev-ros-melodic:2021-09-08 \
|
||||
bash -c '
|
||||
git config --global --add safe.directory /workspace
|
||||
make px4_sitl_default
|
||||
make px4_sitl_default sitl_gazebo-classic
|
||||
./test/rostest_px4_run.sh \
|
||||
mavros_posix_tests_offboard_posctl.test \
|
||||
vehicle:=iris
|
||||
'
|
||||
|
||||
@@ -19,27 +19,28 @@ concurrency:
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
container:
|
||||
image: px4io/px4-dev:v1.16.0-rc1-258-g0369abd556
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
config: [
|
||||
px4_fmu-v5_default,
|
||||
]
|
||||
config:
|
||||
- px4_fmu-v5_default
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Build PX4 and Run Test [${{ matrix.config }}]
|
||||
uses: addnab/docker-run-action@v3
|
||||
with:
|
||||
image: px4io/px4-dev:v1.16.0-rc1-258-g0369abd556
|
||||
options: -v ${{ github.workspace }}:/workspace
|
||||
- name: Build PX4 and Run Test [${{ matrix.config }}]
|
||||
run: |
|
||||
cd /workspace
|
||||
git config --global --add safe.directory /workspace
|
||||
export PX4_EXTRA_NUTTX_CONFIG="CONFIG_NSH_LOGIN_PASSWORD=\"test\";CONFIG_NSH_CONSOLE_LOGIN=y"
|
||||
cd "$GITHUB_WORKSPACE"
|
||||
git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
||||
export PX4_EXTRA_NUTTX_CONFIG='CONFIG_NSH_LOGIN_PASSWORD="test";CONFIG_NSH_CONSOLE_LOGIN=y'
|
||||
echo "PX4_EXTRA_NUTTX_CONFIG: $PX4_EXTRA_NUTTX_CONFIG"
|
||||
|
||||
make ${{ matrix.config }} nuttx_context
|
||||
|
||||
echo "Check that the config option is set"
|
||||
grep CONFIG_NSH_LOGIN_PASSWORD build/${{ matrix.config }}/NuttX/nuttx/.config
|
||||
|
||||
@@ -33,8 +33,10 @@ jobs:
|
||||
matrix:
|
||||
config:
|
||||
- {model: "iris", latitude: "59.617693", longitude: "-151.145316", altitude: "48", build_type: "RelWithDebInfo" } # Alaska
|
||||
- {model: "tailsitter" , latitude: "29.660316", longitude: "-82.316658", altitude: "30", build_type: "RelWithDebInfo" } # Florida
|
||||
- {model: "standard_vtol", latitude: "47.397742", longitude: "8.545594", altitude: "488", build_type: "Coverage" } # Zurich
|
||||
# VTOL/tailsitter disabled: persistent flaky CI failures (timeouts, erratic
|
||||
# transitions). Re-enable once the test infrastructure is stabilized.
|
||||
# - {model: "tailsitter" , latitude: "29.660316", longitude: "-82.316658", altitude: "30", build_type: "RelWithDebInfo" } # Florida
|
||||
# - {model: "standard_vtol", latitude: "47.397742", longitude: "8.545594", altitude: "488", build_type: "Coverage" } # Zurich
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
@@ -412,7 +412,7 @@ tests:
|
||||
$(call cmake-build,px4_sitl_test)
|
||||
|
||||
# work around lcov bug #316; remove once lcov is fixed (see https://github.com/linux-test-project/lcov/issues/316)
|
||||
LCOBUG = --ignore-errors mismatch
|
||||
LCOBUG = --ignore-errors mismatch,negative
|
||||
tests_coverage:
|
||||
@$(MAKE) clean
|
||||
@$(MAKE) --no-print-directory tests PX4_CMAKE_BUILD_TYPE=Coverage
|
||||
@@ -492,13 +492,29 @@ px4_sitl_default-clang:
|
||||
@cd "$(SRC_DIR)"/build/px4_sitl_default-clang && cmake "$(SRC_DIR)" $(CMAKE_ARGS) -G"$(PX4_CMAKE_GENERATOR)" -DCONFIG=px4_sitl_default -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++
|
||||
@$(PX4_MAKE) -C "$(SRC_DIR)"/build/px4_sitl_default-clang
|
||||
|
||||
# Paths to exclude from clang-tidy (auto-generated from .gitmodules + manual additions):
|
||||
# - All submodules (external code we consume, not edit)
|
||||
# - Test code (allowed looser style)
|
||||
# - Example code (educational, not production)
|
||||
# - Vendored third-party code (e.g., CMSIS_5)
|
||||
# - NuttX-only drivers excluded at CMake level (mcp_common); I2C-dependent libs excluded here (smbus)
|
||||
# - GPIO excluded here (NuttX platform headers)
|
||||
# - Emscripten failsafe web build: source path + Unity build path (failsafe_test.dir)
|
||||
# because CMake Unity Builds merge sources into a generated .cxx under build/
|
||||
#
|
||||
# To add manual exclusions, append to CLANG_TIDY_EXCLUDE_EXTRA below.
|
||||
# Submodules are automatically excluded - no action needed when adding new ones.
|
||||
CLANG_TIDY_SUBMODULES := $(shell git config --file .gitmodules --get-regexp path | awk '{print $$2}' | tr '\n' '|' | sed 's/|$$//')
|
||||
CLANG_TIDY_EXCLUDE_EXTRA := src/systemcmds/tests|src/examples|src/modules/gyro_fft/CMSIS_5|src/lib/drivers/smbus|src/drivers/gpio|src/modules/commander/failsafe/emscripten|failsafe_test\.dir|\.pb\.cc
|
||||
CLANG_TIDY_EXCLUDE := $(CLANG_TIDY_SUBMODULES)|$(CLANG_TIDY_EXCLUDE_EXTRA)
|
||||
|
||||
clang-tidy: px4_sitl_default-clang
|
||||
@cd "$(SRC_DIR)"/build/px4_sitl_default-clang && "$(SRC_DIR)"/Tools/run-clang-tidy.py -header-filter=".*\.hpp" -j$(j_clang_tidy) -p .
|
||||
@cd "$(SRC_DIR)"/build/px4_sitl_default-clang && "$(SRC_DIR)"/Tools/run-clang-tidy.py -header-filter=".*\.hpp" -j$(j_clang_tidy) -exclude="$(CLANG_TIDY_EXCLUDE)" -p .
|
||||
|
||||
# to automatically fix a single check at a time, eg modernize-redundant-void-arg
|
||||
# % run-clang-tidy-4.0.py -fix -j4 -checks=-\*,modernize-redundant-void-arg -p .
|
||||
clang-tidy-fix: px4_sitl_default-clang
|
||||
@cd "$(SRC_DIR)"/build/px4_sitl_default-clang && "$(SRC_DIR)"/Tools/run-clang-tidy.py -header-filter=".*\.hpp" -j$(j_clang_tidy) -fix -p .
|
||||
@cd "$(SRC_DIR)"/build/px4_sitl_default-clang && "$(SRC_DIR)"/Tools/run-clang-tidy.py -header-filter=".*\.hpp" -j$(j_clang_tidy) -exclude="$(CLANG_TIDY_EXCLUDE)" -fix -p .
|
||||
|
||||
# TODO: Fix cppcheck errors then try --enable=warning,performance,portability,style,unusedFunction or --enable=all
|
||||
cppcheck: px4_sitl_default
|
||||
|
||||
@@ -101,6 +101,7 @@ param set-default NAV_ACC_RAD 5
|
||||
param set-default NAV_DLL_ACT 2
|
||||
|
||||
param set-default VT_FWD_THRUST_EN 4
|
||||
param set-default VT_PITCH_MIN -5
|
||||
param set-default VT_F_TRANS_THR 1
|
||||
param set-default VT_TYPE 2
|
||||
param set-default FD_ESCS_EN 0
|
||||
|
||||
@@ -22,6 +22,9 @@
|
||||
|
||||
. ${R}etc/init.d/rc.uuv_defaults
|
||||
|
||||
# Overwrite DDS AG IP to `192.168.0.1`
|
||||
param set-default UXRCE_DDS_AG_IP -1062731775
|
||||
|
||||
# param set-default MAV_1_CONFIG 102
|
||||
|
||||
param set-default BAT1_A_PER_V 37.8798
|
||||
|
||||
@@ -10,9 +10,6 @@ set VEHICLE_TYPE uuv
|
||||
# MAV_TYPE_SUBMARINE 12
|
||||
param set-default MAV_TYPE 12
|
||||
|
||||
# Set micro-dds-client to use ethernet and IP-address 192.168.0.1
|
||||
param set-default UXRCE_DDS_AG_IP -1062731775
|
||||
|
||||
# Disable preflight disarm to not interfere with external launching
|
||||
param set-default COM_DISARM_PRFLT -1
|
||||
param set-default CBRK_SUPPLY_CHK 894281
|
||||
|
||||
+4
-24
@@ -1,47 +1,27 @@
|
||||
#! /bin/bash
|
||||
|
||||
if [ -z ${PX4_DOCKER_REPO+x} ]; then
|
||||
echo "guessing PX4_DOCKER_REPO based on input";
|
||||
if [[ $@ =~ .*clang.* ]] || [[ $@ =~ .*scan-build.* ]]; then
|
||||
# clang tools
|
||||
PX4_DOCKER_REPO="px4io/px4-dev-clang:2021-02-04"
|
||||
elif [[ $@ =~ .*tests* ]]; then
|
||||
# run all tests with simulation
|
||||
PX4_DOCKER_REPO="px4io/px4-dev-simulation-bionic:2021-12-11"
|
||||
fi
|
||||
PX4_DOCKER_REPO="px4io/px4-dev:v1.17.0-beta1"
|
||||
else
|
||||
echo "PX4_DOCKER_REPO is set to '$PX4_DOCKER_REPO'";
|
||||
fi
|
||||
|
||||
# otherwise default to nuttx
|
||||
if [ -z ${PX4_DOCKER_REPO+x} ]; then
|
||||
PX4_DOCKER_REPO="px4io/px4-dev:v1.16.0-rc1-258-g0369abd556"
|
||||
fi
|
||||
|
||||
echo "PX4_DOCKER_REPO: $PX4_DOCKER_REPO";
|
||||
|
||||
PWD=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||
SRC_DIR=$PWD/../
|
||||
SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||
SRC_DIR=${SCRIPT_DIR}/../
|
||||
|
||||
CCACHE_DIR=${HOME}/.ccache
|
||||
mkdir -p "${CCACHE_DIR}"
|
||||
|
||||
docker run -it --rm -w "${SRC_DIR}" \
|
||||
--user="$(id -u):$(id -g)" \
|
||||
--env=AWS_ACCESS_KEY_ID \
|
||||
--env=AWS_SECRET_ACCESS_KEY \
|
||||
--env=BRANCH_NAME \
|
||||
--env=CCACHE_DIR="${CCACHE_DIR}" \
|
||||
--env=CI \
|
||||
--env=CODECOV_TOKEN \
|
||||
--env=COVERALLS_REPO_TOKEN \
|
||||
--env=PX4_ASAN \
|
||||
--env=PX4_MSAN \
|
||||
--env=PX4_TSAN \
|
||||
--env=PX4_UBSAN \
|
||||
--env=TRAVIS_BRANCH \
|
||||
--env=TRAVIS_BUILD_ID \
|
||||
--publish 14556:14556/udp \
|
||||
--volume=${CCACHE_DIR}:${CCACHE_DIR}:rw \
|
||||
--volume=${SRC_DIR}:${SRC_DIR}:rw \
|
||||
${PX4_DOCKER_REPO} /bin/bash -c "$1 $2 $3"
|
||||
${PX4_DOCKER_REPO} /bin/bash -c "$@"
|
||||
|
||||
@@ -144,6 +144,8 @@ def main():
|
||||
help='number of tidy instances to be run in parallel.')
|
||||
parser.add_argument('files', nargs='*', default=['.*'],
|
||||
help='files to be processed (regex on path)')
|
||||
parser.add_argument('-exclude', dest='exclude', default=None,
|
||||
help='regular expression matching files to exclude')
|
||||
parser.add_argument('-fix', action='store_true', help='apply fix-its')
|
||||
parser.add_argument('-format', action='store_true', help='Reformat code '
|
||||
'after applying fixes')
|
||||
@@ -192,6 +194,7 @@ def main():
|
||||
|
||||
# Build up a big regexy filter from all command line arguments.
|
||||
file_name_re = re.compile('(' + ')|('.join(args.files) + ')')
|
||||
exclude_re = re.compile(args.exclude) if args.exclude else None
|
||||
|
||||
try:
|
||||
# Spin up a bunch of tidy-launching threads.
|
||||
@@ -205,6 +208,8 @@ def main():
|
||||
# Fill the queue with files.
|
||||
for name in files:
|
||||
if file_name_re.search(name):
|
||||
if exclude_re and exclude_re.search(name):
|
||||
continue
|
||||
queue.put(name)
|
||||
|
||||
# Wait for all threads to be done.
|
||||
|
||||
@@ -4,7 +4,7 @@ GREEN='\033[0;32m'
|
||||
NO_COLOR='\033[0m' # No Color
|
||||
SCRIPTID="${GREEN}[docker-entrypoint.sh]${NO_COLOR}"
|
||||
|
||||
echo -e "$SCRIPTID Starting"
|
||||
echo -e "$SCRIPTID $( uname -m ) | $(date -u +%FT%TZ)"
|
||||
|
||||
# Start virtual X server in the background
|
||||
# - DISPLAY default is :99, set in dockerfile
|
||||
@@ -22,6 +22,4 @@ if [ -n "${ROS_DISTRO}" ]; then
|
||||
source "/opt/ros/$ROS_DISTRO/setup.bash"
|
||||
fi
|
||||
|
||||
echo -e "$SCRIPTID ($( uname -m ))"
|
||||
|
||||
exec "$@"
|
||||
|
||||
+12
-31
@@ -6,9 +6,9 @@ set -e
|
||||
## Can also be used in docker.
|
||||
##
|
||||
## Installs:
|
||||
## - Common dependencies and tools for nuttx, jMAVSim, Gazebo
|
||||
## - Common dependencies and tools for nuttx, Gazebo
|
||||
## - NuttX toolchain (omit with arg: --no-nuttx)
|
||||
## - jMAVSim and Gazebo9 simulator (omit with arg: --no-sim-tools)
|
||||
## - Gazebo Harmonic simulator (omit with arg: --no-sim-tools)
|
||||
##
|
||||
|
||||
INSTALL_NUTTX="true"
|
||||
@@ -207,37 +207,18 @@ if [[ $INSTALL_SIM == "true" ]]; then
|
||||
bc \
|
||||
;
|
||||
|
||||
# Gazebo / Gazebo classic installation
|
||||
if [[ "${UBUNTU_RELEASE}" == "18.04" || "${UBUNTU_RELEASE}" == "20.04" ]]; then
|
||||
sudo sh -c 'echo "deb http://packages.osrfoundation.org/gazebo/ubuntu-stable `lsb_release -cs` main" > /etc/apt/sources.list.d/gazebo-stable.list'
|
||||
wget http://packages.osrfoundation.org/gazebo.key -O - | sudo apt-key add -
|
||||
# Update list, since new gazebo-stable.list has been added
|
||||
sudo apt-get update -y --quiet
|
||||
# Gazebo Harmonic installation (Ubuntu 22.04+)
|
||||
echo "[ubuntu.sh] Gazebo (Harmonic) will be installed"
|
||||
# Add Gazebo binary repository
|
||||
sudo wget https://packages.osrfoundation.org/gazebo.gpg -O /usr/share/keyrings/pkgs-osrf-archive-keyring.gpg
|
||||
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/pkgs-osrf-archive-keyring.gpg] http://packages.osrfoundation.org/gazebo/ubuntu-stable $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/gazebo-stable.list > /dev/null
|
||||
sudo apt-get update -y --quiet
|
||||
|
||||
# Install Gazebo classic
|
||||
if [[ "${UBUNTU_RELEASE}" == "18.04" ]]; then
|
||||
gazebo_classic_version=9
|
||||
gazebo_packages="gazebo$gazebo_classic_version libgazebo$gazebo_classic_version-dev"
|
||||
else
|
||||
# default and Ubuntu 20.04
|
||||
gazebo_classic_version=11
|
||||
gazebo_packages="gazebo$gazebo_classic_version libgazebo$gazebo_classic_version-dev"
|
||||
fi
|
||||
else
|
||||
# Expects Ubuntu 22.04 > by default
|
||||
echo "[ubuntu.sh] Gazebo (Harmonic) will be installed"
|
||||
echo "[ubuntu.sh] Earlier versions will be removed"
|
||||
# Add Gazebo binary repository
|
||||
sudo wget https://packages.osrfoundation.org/gazebo.gpg -O /usr/share/keyrings/pkgs-osrf-archive-keyring.gpg
|
||||
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/pkgs-osrf-archive-keyring.gpg] http://packages.osrfoundation.org/gazebo/ubuntu-stable $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/gazebo-stable.list > /dev/null
|
||||
sudo apt-get update -y --quiet
|
||||
# Install Gazebo
|
||||
gazebo_packages="gz-harmonic libunwind-dev"
|
||||
|
||||
# Install Gazebo
|
||||
gazebo_packages="gz-harmonic libunwind-dev"
|
||||
|
||||
if [[ "${UBUNTU_RELEASE}" == "24.04" ]]; then
|
||||
gazebo_packages="$gazebo_packages cppzmq-dev"
|
||||
fi
|
||||
if [[ "${UBUNTU_RELEASE}" == "24.04" ]]; then
|
||||
gazebo_packages="$gazebo_packages cppzmq-dev"
|
||||
fi
|
||||
|
||||
sudo DEBIAN_FRONTEND=noninteractive apt-get -y --quiet --no-install-recommends install \
|
||||
|
||||
@@ -66,15 +66,15 @@ then
|
||||
fi
|
||||
fi
|
||||
|
||||
iim42652 -R 6 -s -C 32768 start
|
||||
bmi088 -A -R 4 -s start
|
||||
bmi088 -G -R 4 -s start
|
||||
iim42652 -R 6 -s -C 32768 start
|
||||
icm45686 -R 2 -s start
|
||||
|
||||
rm3100 -I -b 4 start
|
||||
|
||||
icp201xx -I -a 0x64 start
|
||||
bmp581 -b 2 -X -a 0x47 start
|
||||
icp201xx -I -a 0x64 start
|
||||
|
||||
# External compass on GPS1/I2C1 (the 3rd external bus): standard Holybro Pixhawk 4 or CUAV V5 GPS/compass puck (with lights, safety button, and buzzer)
|
||||
ist8310 -X -b 1 -R 10 start
|
||||
|
||||
@@ -127,8 +127,8 @@
|
||||
#define GPIO_VDD_5V_RC_EN /* PG5 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTG|GPIO_PIN5)
|
||||
#define GPIO_VDD_3V3_SD_CARD_EN /* PG7 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTG|GPIO_PIN7)
|
||||
|
||||
#define GPIO_VDD_5V_HIPOWER_OC /* PJ3 */ (GPIO_INPUT|GPIO_FLOAT|GPIO_PORTJ|GPIO_PIN3)
|
||||
#define GPIO_nVDD_5V_PERIPH_OC /* PJ4 */ (GPIO_INPUT|GPIO_FLOAT|GPIO_PORTJ|GPIO_PIN4)
|
||||
#define GPIO_VDD_5V_HIPOWER_OC /* PJ3 */ (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTJ|GPIO_PIN3)
|
||||
#define GPIO_nVDD_5V_PERIPH_OC /* PJ4 */ (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTJ|GPIO_PIN4)
|
||||
|
||||
/* Power switch controls ******************************************************/
|
||||
#define VDD_5V_PERIPH_EN(on_true) px4_arch_gpiowrite(GPIO_nVDD_5V_PERIPH_EN, (on_true))
|
||||
|
||||
@@ -19,6 +19,7 @@ CONFIG_COMMON_DIFFERENTIAL_PRESSURE=y
|
||||
CONFIG_DRIVERS_DIFFERENTIAL_PRESSURE_AUAV=y
|
||||
CONFIG_COMMON_DISTANCE_SENSOR=y
|
||||
CONFIG_DRIVERS_DISTANCE_SENSOR_LIGHTWARE_SF45_SERIAL=y
|
||||
CONFIG_DRIVERS_DISTANCE_SENSOR_LIGHTWARE_GRF_SERIAL=y
|
||||
CONFIG_DRIVERS_DSHOT=y
|
||||
CONFIG_DRIVERS_GNSS_SEPTENTRIO=y
|
||||
CONFIG_DRIVERS_GPS=y
|
||||
|
||||
@@ -1056,9 +1056,6 @@
|
||||
1 1 UAVCAN_EC_REV 0 6
|
||||
1 1 UAVCAN_ENABLE 2 6
|
||||
1 1 UAVCAN_LGT_ANTCL 2 6
|
||||
1 1 UAVCAN_LGT_LAND 0 6
|
||||
1 1 UAVCAN_LGT_NAV 3 6
|
||||
1 1 UAVCAN_LGT_STROB 1 6
|
||||
1 1 UAVCAN_NODE_ID 1 6
|
||||
1 1 UAVCAN_PUB_ARM 0 6
|
||||
1 1 UAVCAN_PUB_MBD 0 6
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 108 KiB |
@@ -255,6 +255,7 @@
|
||||
- [Lidar-Lite](sensor/lidar_lite.md)
|
||||
- [Lightware Lidars (SF/LW/GRF)](sensor/sfxx_lidar.md)
|
||||
- [Lightware SF45 Rotary Lidar](sensor/sf45_rotating_lidar.md)
|
||||
- [Lightware GRF250/GRF500 Gimbal Lidar](sensor/grf_lidar.md)
|
||||
- [TeraRanger](sensor/teraranger.md)
|
||||
- [✘ Lanbao PSK-CM8JL65-CC5](sensor/cm8jl65_ir_distance_sensor.md)
|
||||
- [Avionics Anonymous Laser Altimeter UAVCAN Interface (CAN)](dronecan/avanon_laser_interface.md)
|
||||
|
||||
@@ -19596,6 +19596,18 @@ Launch is detected when acceleration in body forward direction is above FW_LAUN_
|
||||
| ------ | -------- | -------- | --------- | ------- | ----- |
|
||||
| | 0 | | 0.5 | 30.0 | m/s^2 |
|
||||
|
||||
### FW_LAUN_CS_LK_DY (`FLOAT`) {#FW_LAUN_CS_LK_DY}
|
||||
|
||||
Control surface launch delay.
|
||||
|
||||
Locks control surfaces during pre-launch (armed) and until this time since launch has passed.
|
||||
Only affects control surfaces that have corresponding flag set, and not active for runway takeoff.
|
||||
Set to 0 to disable any surface locking after arming.
|
||||
|
||||
| Reboot | minValue | maxValue | increment | default | unit |
|
||||
| ------ | -------- | -------- | --------- | ------- | ---- |
|
||||
| | 0.0 | | 0.1 | 0. | s |
|
||||
|
||||
### FW_LAUN_DETCN_ON (`INT32`) {#FW_LAUN_DETCN_ON}
|
||||
|
||||
Fixed-wing launch detection.
|
||||
@@ -21325,6 +21337,27 @@ Some are generic, while others are specifically fit to a certain vehicle with a
|
||||
| ------ | -------- | -------- | --------- | ------- | ---- |
|
||||
| | | | | 0 |
|
||||
|
||||
### CA_CS_LAUN_LK (`INT32`) {#CA_CS_LAUN_LK}
|
||||
|
||||
Control surface launch lock enabled.
|
||||
|
||||
If actuator launch lock is enabled, this surface is kept at the disarmed value.
|
||||
|
||||
**Bitmask:**
|
||||
|
||||
- `0`: Control Surface 1
|
||||
- `1`: Control Surface 2
|
||||
- `2`: Control Surface 3
|
||||
- `3`: Control Surface 4
|
||||
- `4`: Control Surface 5
|
||||
- `5`: Control Surface 6
|
||||
- `6`: Control Surface 7
|
||||
- `7`: Control Surface 8
|
||||
|
||||
| Reboot | minValue | maxValue | increment | default | unit |
|
||||
| ------ | -------- | -------- | --------- | ------- | ---- |
|
||||
| | 0 | 255 | | 0 |
|
||||
|
||||
### CA_FAILURE_MODE (`INT32`) {#CA_FAILURE_MODE}
|
||||
|
||||
Motor failure handling mode.
|
||||
@@ -33078,6 +33111,44 @@ Use SENS_MAG_SIDES instead
|
||||
| ------ | -------- | -------- | --------- | ------- | ---- |
|
||||
| | | | | 63 |
|
||||
|
||||
### GRF_RATE_CFG (`INT32`) {#GRF_RATE_CFG}
|
||||
|
||||
Lightware GRF lidar update rate.
|
||||
|
||||
The Lightware GRF distance sensor can increase the update rate to enable greater resolution.
|
||||
|
||||
**Values:**
|
||||
|
||||
- `1`: 1 Hz
|
||||
- `2`: 2 Hz
|
||||
- `3`: 4 Hz
|
||||
- `4`: 5 Hz
|
||||
- `5`: 10 Hz
|
||||
- `6`: 20 Hz
|
||||
- `7`: 30 Hz
|
||||
- `8`: 40 Hz
|
||||
- `9`: 50 Hz
|
||||
|
||||
| Reboot | minValue | maxValue | increment | default | unit |
|
||||
| ------- | -------- | -------- | --------- | ------- | ---- |
|
||||
| ✓ | | | | 4 |
|
||||
|
||||
### GRF_SENS_MODEL (`INT32`) {#GRF_SENS_MODEL}
|
||||
|
||||
GRF Sensor model.
|
||||
|
||||
GRF Sensor Model used to distinush between the GRF250 and GRF500 since both have different max distance range.
|
||||
|
||||
**Values:**
|
||||
|
||||
- `0`: disable
|
||||
- `1`: GRF250
|
||||
- `2`: GRF500
|
||||
|
||||
| Reboot | minValue | maxValue | increment | default | unit |
|
||||
| ------- | -------- | -------- | --------- | ------- | ---- |
|
||||
| ✓ | | | | 0 |
|
||||
|
||||
### ILABS_MODE (`INT32`) {#ILABS_MODE}
|
||||
|
||||
InertialLabs INS sensor mode configuration.
|
||||
@@ -34286,6 +34357,31 @@ Enable simulated GPS sinstance.
|
||||
| ------- | -------- | -------- | --------- | ------- | ---- |
|
||||
| ✓ | 0 | 1 | | 0 |
|
||||
|
||||
### SENS_EN_GRF_CFG (`INT32`) {#SENS_EN_GRF_CFG}
|
||||
|
||||
Serial Configuration for Lightware GRF Rangefinder (serial).
|
||||
|
||||
Configure on which serial port to run Lightware GRF Rangefinder (serial).
|
||||
|
||||
**Values:**
|
||||
|
||||
- `0`: Disabled
|
||||
- `6`: UART 6
|
||||
- `101`: TELEM 1
|
||||
- `102`: TELEM 2
|
||||
- `103`: TELEM 3
|
||||
- `104`: TELEM/SERIAL 4
|
||||
- `201`: GPS 1
|
||||
- `202`: GPS 2
|
||||
- `203`: GPS 3
|
||||
- `300`: Radio Controller
|
||||
- `301`: Wifi Port
|
||||
- `401`: EXT2
|
||||
|
||||
| Reboot | minValue | maxValue | increment | default | unit |
|
||||
| ------- | -------- | -------- | --------- | ------- | ---- |
|
||||
| ✓ | | | | 0 |
|
||||
|
||||
### SENS_EN_INA220 (`INT32`) {#SENS_EN_INA220}
|
||||
|
||||
Enable INA220 Power Monitor.
|
||||
@@ -34511,7 +34607,7 @@ Lightware Laser Rangefinder hardware model (serial).
|
||||
|
||||
### SENS_EN_SF1XX (`INT32`) {#SENS_EN_SF1XX}
|
||||
|
||||
Lightware SF1xx/SF20/LW20 laser rangefinder (i2c).
|
||||
Lightware laser rangefinder (i2c).
|
||||
|
||||
**Values:**
|
||||
|
||||
@@ -35686,6 +35782,26 @@ Configure on which serial port to run VectorNav (VN-100, VN-200, VN-300).
|
||||
| ------- | -------- | -------- | --------- | ------- | ---- |
|
||||
| ✓ | | | | 0 |
|
||||
|
||||
### SF1XX_ROT (`INT32`) {#SF1XX_ROT}
|
||||
|
||||
Lightware laser rangefinder Rotation.
|
||||
|
||||
Distance sensor orientation as MAV_SENSOR_ORIENTATION enum.
|
||||
Applies to all models supported by SENS_EN_SF1XX.
|
||||
|
||||
**Values:**
|
||||
|
||||
- `0`: Forward
|
||||
- `2`: Right
|
||||
- `4`: Backward
|
||||
- `6`: Left
|
||||
- `24`: Upward
|
||||
- `25`: Downward
|
||||
|
||||
| Reboot | minValue | maxValue | increment | default | unit |
|
||||
| ------- | -------- | -------- | --------- | ------- | ---- |
|
||||
| ✓ | 0 | 25 | | 25 |
|
||||
|
||||
### SF45_ORIENT_CFG (`INT32`) {#SF45_ORIENT_CFG}
|
||||
|
||||
Orientation upright or facing downward.
|
||||
@@ -40288,7 +40404,7 @@ starve other nodes on the bus.
|
||||
UAVCAN ANTI_COLLISION light operating mode.
|
||||
|
||||
This parameter defines the minimum condition under which the system will command
|
||||
the ANTI_COLLISION lights on
|
||||
lights with anti-collision function to turn on (white).
|
||||
0 - Always off
|
||||
1 - When autopilot is armed
|
||||
2 - When autopilot is prearmed
|
||||
@@ -40305,67 +40421,97 @@ the ANTI_COLLISION lights on
|
||||
| ------- | -------- | -------- | --------- | ------- | ---- |
|
||||
| ✓ | 0 | 3 | | 2 |
|
||||
|
||||
### UAVCAN_LGT_LAND (`INT32`) {#UAVCAN_LGT_LAND}
|
||||
### UAVCAN_LGT_FN0 (`INT32`) {#UAVCAN_LGT_FN0}
|
||||
|
||||
UAVCAN LIGHT_ID_LANDING light operating mode.
|
||||
Light 0 function.
|
||||
|
||||
This parameter defines the minimum condition under which the system will command
|
||||
the LIGHT_ID_LANDING lights on
|
||||
0 - Always off
|
||||
1 - When autopilot is armed
|
||||
2 - When autopilot is prearmed
|
||||
3 - Always on
|
||||
Function assigned to light 0.
|
||||
0: Status - displays system status colors
|
||||
1: Anti-collision - white beacon controlled by LGT_ANTCL parameter
|
||||
|
||||
**Values:**
|
||||
|
||||
- `0`: Always off
|
||||
- `1`: When autopilot is armed
|
||||
- `2`: When autopilot is prearmed
|
||||
- `3`: Always on
|
||||
- `0`: Status Light
|
||||
- `1`: Anti-collision Light
|
||||
|
||||
| Reboot | minValue | maxValue | increment | default | unit |
|
||||
| ------- | -------- | -------- | --------- | ------- | ---- |
|
||||
| ✓ | 0 | 3 | | 0 |
|
||||
| Reboot | minValue | maxValue | increment | default | unit |
|
||||
| ------ | -------- | -------- | --------- | ------- | ---- |
|
||||
| | 0 | 1 | | 0 |
|
||||
|
||||
### UAVCAN_LGT_NAV (`INT32`) {#UAVCAN_LGT_NAV}
|
||||
### UAVCAN_LGT_FN1 (`INT32`) {#UAVCAN_LGT_FN1}
|
||||
|
||||
UAVCAN RIGHT_OF_WAY light operating mode.
|
||||
Light 1 function.
|
||||
|
||||
This parameter defines the minimum condition under which the system will command
|
||||
the RIGHT_OF_WAY lights on
|
||||
0 - Always off
|
||||
1 - When autopilot is armed
|
||||
2 - When autopilot is prearmed
|
||||
3 - Always on
|
||||
Function assigned to light 1.
|
||||
0: Status - displays system status colors
|
||||
1: Anti-collision - white beacon controlled by LGT_ANTCL parameter
|
||||
|
||||
**Values:**
|
||||
|
||||
- `0`: Always off
|
||||
- `1`: When autopilot is armed
|
||||
- `2`: When autopilot is prearmed
|
||||
- `3`: Always on
|
||||
- `0`: Status Light
|
||||
- `1`: Anti-collision Light
|
||||
|
||||
| Reboot | minValue | maxValue | increment | default | unit |
|
||||
| ------- | -------- | -------- | --------- | ------- | ---- |
|
||||
| ✓ | 0 | 3 | | 3 |
|
||||
| Reboot | minValue | maxValue | increment | default | unit |
|
||||
| ------ | -------- | -------- | --------- | ------- | ---- |
|
||||
| | 0 | 1 | | 0 |
|
||||
|
||||
### UAVCAN_LGT_STROB (`INT32`) {#UAVCAN_LGT_STROB}
|
||||
### UAVCAN_LGT_FN2 (`INT32`) {#UAVCAN_LGT_FN2}
|
||||
|
||||
UAVCAN STROBE light operating mode.
|
||||
Light 2 function.
|
||||
|
||||
This parameter defines the minimum condition under which the system will command
|
||||
the STROBE lights on
|
||||
0 - Always off
|
||||
1 - When autopilot is armed
|
||||
2 - When autopilot is prearmed
|
||||
3 - Always on
|
||||
Function assigned to light 2.
|
||||
0: Status - displays system status colors
|
||||
1: Anti-collision - white beacon controlled by LGT_ANTCL parameter
|
||||
|
||||
**Values:**
|
||||
|
||||
- `0`: Always off
|
||||
- `1`: When autopilot is armed
|
||||
- `2`: When autopilot is prearmed
|
||||
- `3`: Always on
|
||||
- `0`: Status Light
|
||||
- `1`: Anti-collision Light
|
||||
|
||||
| Reboot | minValue | maxValue | increment | default | unit |
|
||||
| ------ | -------- | -------- | --------- | ------- | ---- |
|
||||
| | 0 | 1 | | 0 |
|
||||
|
||||
### UAVCAN_LGT_ID0 (`INT32`) {#UAVCAN_LGT_ID0}
|
||||
|
||||
Light 0 ID.
|
||||
|
||||
specifies the light_id value for light 0 in UAVCAN LightsCommand messages.
|
||||
This determines which physical LED responds to commands for this light slot.
|
||||
|
||||
| Reboot | minValue | maxValue | increment | default | unit |
|
||||
| ------ | -------- | -------- | --------- | ------- | ---- |
|
||||
| | 0 | 255 | | 0 |
|
||||
|
||||
### UAVCAN_LGT_ID1 (`INT32`) {#UAVCAN_LGT_ID1}
|
||||
|
||||
Light 1 ID.
|
||||
|
||||
specifies the light_id value for light 1 in UAVCAN LightsCommand messages.
|
||||
This determines which physical LED responds to commands for this light slot.
|
||||
|
||||
| Reboot | minValue | maxValue | increment | default | unit |
|
||||
| ------ | -------- | -------- | --------- | ------- | ---- |
|
||||
| | 0 | 255 | | 0 |
|
||||
|
||||
### UAVCAN_LGT_ID2 (`INT32`) {#UAVCAN_LGT_ID2}
|
||||
|
||||
Light 2 ID.
|
||||
|
||||
specifies the light_id value for light 2 in UAVCAN LightsCommand messages.
|
||||
This determines which physical LED responds to commands for this light slot.
|
||||
|
||||
| Reboot | minValue | maxValue | increment | default | unit |
|
||||
| ------ | -------- | -------- | --------- | ------- | ---- |
|
||||
| | 0 | 255 | | 0 |
|
||||
|
||||
### UAVCAN_LGT_NUM (`INT32`) {#UAVCAN_LGT_NUM}
|
||||
|
||||
Number of UAVCAN lights to configure.
|
||||
|
||||
Number of lights to control via UAVCAN LightsCommand messages.
|
||||
Set to 0 to disable UAVCAN light control.
|
||||
Each light uses two parameters: LGT_IDx for the light_id and LGT_FNx for the function.
|
||||
|
||||
| Reboot | minValue | maxValue | increment | default | unit |
|
||||
| ------- | -------- | -------- | --------- | ------- | ---- |
|
||||
@@ -42484,7 +42630,7 @@ Gyro filter settings.
|
||||
|
||||
### SF1XX_MODE (`INT32`) {#SF1XX_MODE}
|
||||
|
||||
Lightware SF1xx/SF20/LW20 Operation Mode.
|
||||
Lightware laser rangefinder Operation Mode.
|
||||
|
||||
**Values:**
|
||||
|
||||
|
||||
+26
-11
@@ -181,17 +181,22 @@ The following settings also apply, but are not displayed in the QGC UI.
|
||||
| <a id="GF_PREDICT"></a>Preemptive geofence triggering | [GF_PREDICT](../advanced_config/parameter_reference.md#GF_PREDICT) | (Experimental) Trigger geofence if current motion of the vehicle is predicted to trigger the breach (rather than late triggering after the breach). |
|
||||
| <a id="CBRK_FLIGHTTERM"></a>Circuit breaker for flight termination | [CBRK_FLIGHTTERM](../advanced_config/parameter_reference.md#CBRK_FLIGHTTERM) | Enables/Disables flight termination action (disabled by default). |
|
||||
|
||||
## Position (GNSS) Loss Failsafe
|
||||
## Position Estimation Failsafes
|
||||
|
||||
This section describes failsafes related to the quality of the vehicle's position estimate.
|
||||
|
||||
### Position Loss Failsafe
|
||||
|
||||
The _Position Loss Failsafe_ is triggered if the quality of the PX4 position estimate falls below acceptable levels (this might be caused by GPS loss) while in a mode that requires an acceptable position estimate.
|
||||
The sections below cover first the trigger and then the failsafe action taken by the controller.
|
||||
|
||||
### Position Loss Failsafe Trigger
|
||||
|
||||
There are basically two mechanisms in PX4 to trigger position failsafes:
|
||||
The position loss failsafe triggers if the position estimate becomes _invalid_. There are two mechanisms in PX4 to invalidate the position estimate:
|
||||
|
||||
- A timeout since the last sensor data was fused that provides direct speed or horizontal position measurements. Sensors that fall into that category are: GNSS, optical flow, airspeed, VIO, auxiliary global position.
|
||||
- The estimated horizontal position accuracy exceeds a certain threshold. This check is only done on hovering systems (rotary wing vehicles or VTOLs in hover phase).
|
||||
- A timeout since the last sensor data was fused that provides direct speed or horizontal position measurements.
|
||||
- Sensors that fall into that category are: GNSS, optical flow, airspeed, VIO, auxiliary global position.
|
||||
- The estimated horizontal position inaccuracy exceeds the threshold [COM_POS_LOW_EPH](../advanced_config/parameter_reference.md#COM_POS_LOW_EPH)
|
||||
- This check is only done on hovering systems (rotary-wing vehicles or VTOLs in hover phase). For fixed-wing vehicles, refer to the [Position Accuracy Low](#position-accuracy-low-failsafe) section.
|
||||
|
||||
The relevant parameters shown below.
|
||||
|
||||
@@ -207,14 +212,24 @@ Multicopters will switch to [Altitude mode](../flight_modes_mc/altitude.md) if a
|
||||
Fixed-wing planes, and VTOLs not configured to land in hover ([NAV_FORCE_VT](../advanced_config/parameter_reference.md#NAV_FORCE_VT)), have a parameter ([FW_GPSF_LT](../advanced_config/parameter_reference.md#FW_GPSF_LT)) that defines how long they will loiter (circle with a constant roll angle ([FW_GPSF_R](../advanced_config/parameter_reference.md#FW_GPSF_R)) at the current altitude) after losing position before attempting to land.
|
||||
If VTOLs have are configured to switch to hover for landing ([NAV_FORCE_VT](../advanced_config/parameter_reference.md#NAV_FORCE_VT)) then they will first transition and then descend.
|
||||
|
||||
The relevant parameters for all vehicles shown below.
|
||||
The relevant parameters are:
|
||||
|
||||
Parameters that only affect Fixed-wing vehicles:
|
||||
| Parameter | Description |
|
||||
| ----------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| <a id="FW_GPSF_LT"></a>[FW_GPSF_LT](../advanced_config/parameter_reference.md#FW_GPSF_LT) | Fixed-wing only: Loiter time (waiting at current altitude for position estimation recovery before starting to descend). Set to 0 to disable. |
|
||||
| <a id="FW_GPSF_R"></a>[FW_GPSF_R](../advanced_config/parameter_reference.md#FW_GPSF_R) | Fixed roll/bank angle while circling. |
|
||||
| <a id="NAV_FORCE_VT"></a>[NAV_FORCE_VT](../advanced_config/parameter_reference.md#NAV_FORCE_VT) | If true, force VTOL takeoff and landing, even in `Descend` failsafe. |
|
||||
|
||||
| Parameter | Description |
|
||||
| ----------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
|
||||
| <a id="FW_GPSF_LT"></a>[FW_GPSF_LT](../advanced_config/parameter_reference.md#FW_GPSF_LT) | Loiter time (waiting for GPS recovery before it goes into land or flight termination). Set to 0 to disable. |
|
||||
| <a id="FW_GPSF_R"></a>[FW_GPSF_R](../advanced_config/parameter_reference.md#FW_GPSF_R) | Fixed roll/bank angle while circling. |
|
||||
### Position Accuracy Low Failsafe
|
||||
|
||||
In Fixed-wing, the position estimate is never strictly invalidated as long as we have a horizontal aiding source, such as an airspeed sensor. In that case, a separate failsafe can be configured that triggers if the position estimate inacuraccy exceeds the threshold [COM_POS_LOW_EPH](../advanced_config/parameter_reference.md#COM_POS_LOW_EPH). The failsafe action is taken if the vehicle is in mission or hold mode, otherwise it is only a warning. The relevant parameters are:
|
||||
|
||||
| Parameter | Description |
|
||||
| -------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
|
||||
| <a id="COM_POS_LOW_EPH"></a>[COM_POS_LOW_EPH](../advanced_config/parameter_reference.md#COM_POS_LOW_EPH) | Position inaccuracy threshold above which COM_POS_LOW_ACT is taken. |
|
||||
| <a id="COM_POS_LOW_ACT"></a>[COM_POS_LOW_ACT](../advanced_config/parameter_reference.md#COM_POS_LOW_ACT) | Failsafe action taken when position inaccuracy is above configured threshold. |
|
||||
|
||||
Note that if there is no horizontal aiding source anymore, the position estimate is invalidated after `EKF2_NOAID_TOUT`, and the standard position loss failsafe applies.
|
||||
|
||||
## Offboard Loss Failsafe
|
||||
|
||||
|
||||
@@ -39,15 +39,6 @@ Navigate into the **PX4-Autopilot** directory and start [Gazebo SITL](../sim_gaz
|
||||
make px4_sitl gz_x500
|
||||
```
|
||||
|
||||
::: details If you installed Gazebo Classic
|
||||
Start [Gazebo Classic SITL](../sim_gazebo_classic/index.md) using the following command:
|
||||
|
||||
```sh
|
||||
make px4_sitl gazebo-classic
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
This will bring up the PX4 console:
|
||||
|
||||

|
||||
@@ -88,6 +79,16 @@ cd PX4-Autopilot
|
||||
make px4_fmu-v5_default
|
||||
```
|
||||
|
||||
:::tip
|
||||
You can also build using the [px4-dev Docker container](../test_and_ci/docker.md) without installing the toolchain locally.
|
||||
From the PX4-Autopilot directory:
|
||||
|
||||
```sh
|
||||
./Tools/docker_run.sh 'make px4_fmu-v5_default'
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
A successful run will end with similar output to:
|
||||
|
||||
```sh
|
||||
@@ -126,7 +127,8 @@ The following list shows the build commands for the [Pixhawk standard](../flight
|
||||
- [Pixhawk 1 (FMUv2)](../flight_controller/pixhawk.md): `make px4_fmu-v2_default`
|
||||
|
||||
:::warning
|
||||
You **must** use a supported version of GCC to build this board (e.g. the same as used by [CI/docker](../test_and_ci/docker.md)) or remove modules from the build. Building with an unsupported GCC may fail, as PX4 is close to the board's 1MB flash limit.
|
||||
You **must** use a supported version of GCC to build this board (e.g. the `gcc-arm-none-eabi` package from the current Ubuntu LTS, which is the same toolchain used by CI) or remove modules from the build.
|
||||
Building with an unsupported GCC may fail, as PX4 is close to the board's 1MB flash limit.
|
||||
:::
|
||||
|
||||
- Pixhawk 1 with 2 MB flash: `make px4_fmu-v3_default`
|
||||
@@ -191,7 +193,7 @@ The `region 'flash' overflowed by XXXX bytes` error indicates that the firmware
|
||||
This is common for `make px4_fmu-v2_default` builds, where the flash size is limited to 1MB.
|
||||
|
||||
If you're building the _vanilla_ master branch, the most likely cause is using an unsupported version of GCC.
|
||||
In this case, install the version specified in the [Developer Toolchain](../dev_setup/dev_env.md) instructions.
|
||||
In this case, install the `gcc-arm-none-eabi` package from the current Ubuntu LTS as described in the [Developer Toolchain](../dev_setup/dev_env.md) instructions.
|
||||
|
||||
If building your own branch, it is possible that you have increased the firmware size over the 1MB limit.
|
||||
In this case you will need to remove any drivers/modules that you don't need from the build.
|
||||
@@ -204,7 +206,7 @@ The PX4 build system opens a large number of files, so you may exceed this numbe
|
||||
The build toolchain will then report `Too many open files` for many files, as shown below:
|
||||
|
||||
```sh
|
||||
/usr/local/Cellar/gcc-arm-none-eabi/20171218/bin/../lib/gcc/arm-none-eabi/7.2.1/../../../../arm-none-eabi/bin/ld: cannot find NuttX/nuttx/fs/libfs.a: Too many open files
|
||||
arm-none-eabi-ld: cannot find NuttX/nuttx/fs/libfs.a: Too many open files
|
||||
```
|
||||
|
||||
The solution is to increase the maximum allowed number of open files (e.g. to 300).
|
||||
@@ -227,34 +229,9 @@ xcode-select --install
|
||||
sudo ln -s /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/* /usr/local/include/
|
||||
```
|
||||
|
||||
### Ubuntu 18.04: Compile errors involving arm_none_eabi_gcc
|
||||
|
||||
Build issues related to `arm_none_eabi_gcc`may be due to a broken g++ toolchain installation.
|
||||
You can verify that this is the case by checking for missing dependencies using:
|
||||
|
||||
```sh
|
||||
arm-none-eabi-gcc --version
|
||||
arm-none-eabi-g++ --version
|
||||
arm-none-eabi-gdb --version
|
||||
arm-none-eabi-size --version
|
||||
```
|
||||
|
||||
Example of bash output with missing dependencies:
|
||||
|
||||
```sh
|
||||
arm-none-eabi-gdb --version
|
||||
arm-none-eabi-gdb: command not found
|
||||
```
|
||||
|
||||
This can be resolved by removing and [reinstalling the compiler](https://askubuntu.com/questions/1243252/how-to-install-arm-none-eabi-gdb-on-ubuntu-20-04-lts-focal-fossa).
|
||||
|
||||
### Ubuntu 18.04: Visual Studio Code is unable to watch for file changes in this large workspace
|
||||
|
||||
See [Visual Studio Code IDE (VSCode) > Troubleshooting](../dev_setup/vscode.md#troubleshooting).
|
||||
|
||||
### Failed to import Python packages
|
||||
|
||||
"Failed to import" errors when running the `make px4_sitl jmavsim` command indicates that some Python packages are not installed (where expected).
|
||||
"Failed to import" errors when running the `make px4_sitl gz_x500` command indicates that some Python packages are not installed (where expected).
|
||||
|
||||
```sh
|
||||
Failed to import jinja2: No module named 'jinja2'
|
||||
@@ -262,12 +239,12 @@ You may need to install it using:
|
||||
pip3 install --user jinja2
|
||||
```
|
||||
|
||||
If you have already installed these dependencies this may be because there is more than one Python version on the computer (e.g. Python 2.7.16 Python 3.8.3), and the module is not present in the version used by the build toolchain.
|
||||
If you have already installed these dependencies this may be because there is more than one Python version on the computer (e.g. Python 2.7.16 and Python 3.8.3), and the module is not present in the version used by the build toolchain.
|
||||
|
||||
You should be able to fix this by explicitly installing the dependencies as shown:
|
||||
You should be able to fix this by installing the dependencies from the repository's requirements file:
|
||||
|
||||
```sh
|
||||
pip3 install --user pyserial empty toml numpy pandas jinja2 pyyaml pyros-genmsg packaging
|
||||
pip3 install --user -r Tools/setup/requirements.txt
|
||||
```
|
||||
|
||||
## PX4 Make Build Targets
|
||||
|
||||
@@ -20,7 +20,7 @@ The equipment below is highly recommended:
|
||||
:::
|
||||
- Lenovo Thinkpad with i5-core running Windows 11
|
||||
- MacBook Pro (early 2015 and later) with macOS 10.15 or later
|
||||
- Lenovo Thinkpad i5 with Ubuntu Linux 20.04 or later
|
||||
- Lenovo Thinkpad i5 with Ubuntu Linux 22.04 or later
|
||||
|
||||
- **Ground control station** (computer or tablet):
|
||||
- iPad (may require Wifi telemetry adapter)
|
||||
@@ -39,9 +39,9 @@ Install the [QGroundControl Daily Build](../dev_setup/qgc_daily_build.md) for a
|
||||
To configure the vehicle:
|
||||
|
||||
1. [Install PX4 firmware](../config/firmware.md#installing-px4-main-beta-or-custom-firmware) (including "custom" firmware with your own changes).
|
||||
1. [Start with the airframe](../config/airframe.md) that best-matches your vehicle from the [airframe reference](../airframes/airframe_reference.md).
|
||||
1. [Basic Configuration](../config/index.md) explains how to perform basic configuration.
|
||||
1. [Parameter Configuration](../advanced_config/parameters.md) explains how you can find and modify individual parameters.
|
||||
2. [Start with the airframe](../config/airframe.md) that best-matches your vehicle from the [airframe reference](../airframes/airframe_reference.md).
|
||||
3. [Basic Configuration](../config/index.md) explains how to perform basic configuration.
|
||||
4. [Parameter Configuration](../advanced_config/parameters.md) explains how you can find and modify individual parameters.
|
||||
|
||||
::: info
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
The _supported platforms_ for PX4 development are:
|
||||
|
||||
- [Ubuntu Linux (24.04/22.04)](../dev_setup/dev_env_linux_ubuntu.md) — Recommended
|
||||
- [Ubuntu Linux (24.04/22.04)](../dev_setup/dev_env_linux_ubuntu.md)
|
||||
- [Windows (10/11)](../dev_setup/dev_env_windows_wsl.md) — via WSL2
|
||||
- [macOS](../dev_setup/dev_env_mac.md)
|
||||
|
||||
@@ -15,9 +15,9 @@ The table below shows what PX4 targets you can build on each OS.
|
||||
| **NuttX based hardware:** [Pixhawk Series](../flight_controller/pixhawk_series.md), [Crazyflie](../complete_vehicles_mc/crazyflie2.md) | ✓ | ✓ | ✓ |
|
||||
| **Linux-based hardware:** [Raspberry Pi 2/3](../flight_controller/raspberry_pi_navio2.md) | ✓ | | |
|
||||
| **Simulation:** [Gazebo SITL](../sim_gazebo_gz/index.md) | ✓ | ✓ | ✓ |
|
||||
| **Simulation:** [Gazebo Classic SITL](../sim_gazebo_classic/index.md) | ✓ | ✓ | ✓ |
|
||||
| **Simulation:** [ROS with Gazebo Classic](../simulation/ros_interface.md) | ✓ | | ✓ |
|
||||
| **Simulation:** ROS 2 with Gazebo | ✓ | | ✓ |
|
||||
| **Simulation:** [Gazebo Classic SITL](../sim_gazebo_classic/index.md) | | ✓ | ✓ |
|
||||
| **Simulation:** [ROS with Gazebo Classic](../simulation/ros_interface.md) | | | ✓ |
|
||||
|
||||
Experienced Docker users can also build with the containers used by our continuous integration system: [Docker Containers](../test_and_ci/docker.md)
|
||||
|
||||
|
||||
@@ -39,8 +39,9 @@ You may want to also install `python-pip` and `screen`.
|
||||
Execute the script below to install GCC 7-2017-q4:
|
||||
|
||||
:::warning
|
||||
This version of GCC is out of date.
|
||||
At time of writing the current version on Ubuntu is `9-2020-q2-update` (see [focal nuttx docker file](https://github.com/PX4/PX4-containers/blob/master/docker/Dockerfile_nuttx-focal#L28))
|
||||
This version of GCC is very outdated.
|
||||
PX4 now uses the `gcc-arm-none-eabi` package from the current Ubuntu LTS (GCC 13.2.1 on Ubuntu 24.04).
|
||||
This CentOS guide is community-maintained and may not produce working builds.
|
||||
:::
|
||||
|
||||
```sh
|
||||
|
||||
@@ -4,20 +4,14 @@ The following instructions use a bash script to set up the PX4 development envir
|
||||
|
||||
The environment includes:
|
||||
|
||||
- [Gazebo Simulator](../sim_gazebo_gz/index.md) ("Harmonic")
|
||||
- [Build toolchain for Pixhawk (and other NuttX-based hardware)](../dev_setup/building_px4.md#nuttx-pixhawk-based-boards).
|
||||
|
||||
On Ubuntu 22.04:
|
||||
|
||||
- [Gazebo Classic Simulator](../sim_gazebo_classic/index.md) can be used instead of Gazebo.
|
||||
Gazebo is nearing feature-parity with Gazebo-Classic on PX4, and will soon replace it for all use cases.
|
||||
- [Gazebo Simulator](../sim_gazebo_gz/index.md) (Gazebo Harmonic)
|
||||
- [Build toolchain for Pixhawk (and other NuttX-based hardware)](../dev_setup/building_px4.md#nuttx-pixhawk-based-boards) using the `gcc-arm-none-eabi` compiler from the Ubuntu package manager.
|
||||
|
||||
The build toolchain for other flight controllers, simulators, and working with ROS are discussed in the [Other Targets](#other-targets) section below.
|
||||
|
||||
::: details Can I use an older version of Ubuntu?
|
||||
PX4 supports the current and last Ubuntu LTS release where possible.
|
||||
Older releases are not supported (so you can't raise defects against them), but may still work.
|
||||
For example, Gazebo Classic setup is included in our standard build instructions for macOS, Ubuntu 18.04 and 20.04, and Windows on WSL2 for the same hosts.
|
||||
::: info
|
||||
PX4 targets the **current Ubuntu LTS** (24.04) for CI and release builds, with the **previous LTS** (22.04) also supported.
|
||||
Older Ubuntu versions are not supported and may not work.
|
||||
:::
|
||||
|
||||
## Simulation and NuttX (Pixhawk) Targets
|
||||
@@ -50,19 +44,18 @@ To install the toolchain:
|
||||
- Acknowledge any prompts as the script progress.
|
||||
- You can use the `--no-nuttx` and `--no-sim-tools` options to omit the NuttX and/or simulation tools.
|
||||
|
||||
3. If you need Gazebo Classic (Ubuntu 22.04 only) then you can manually remove Gazebo and install it by following the instructions in [Gazebo Classic > Installation](../sim_gazebo_classic/index.md#installation).
|
||||
|
||||
4. Restart the computer on completion.
|
||||
3. Restart the computer on completion.
|
||||
|
||||
:::details Additional notes
|
||||
These notes are provided "for information only":
|
||||
|
||||
- This setup is supported by the PX4 Dev Team.
|
||||
The instructions may also work on other Debian Linux based systems.
|
||||
- You can verify the NuttX installation by confirming the `gcc` version as shown:
|
||||
- You can verify the NuttX installation by confirming `gcc` is available.
|
||||
The version depends on your Ubuntu release (e.g. GCC 13.2.1 on Ubuntu 24.04):
|
||||
|
||||
```sh
|
||||
$arm-none-eabi-gcc --version
|
||||
$ arm-none-eabi-gcc --version
|
||||
|
||||
arm-none-eabi-gcc (15:13.2.rel1-2) 13.2.1 20231009
|
||||
Copyright (C) 2023 Free Software Foundation, Inc.
|
||||
|
||||
@@ -58,20 +58,20 @@ To install WSL2 with Ubuntu on a new installation of Windows 10 or 11:
|
||||
wsl --install
|
||||
```
|
||||
|
||||
- Ubuntu 20.04 ([Gazebo-Classic Simulation](../sim_gazebo_classic/index.md))
|
||||
|
||||
```sh
|
||||
wsl --install -d Ubuntu-20.04
|
||||
```
|
||||
|
||||
- Ubuntu 22.04 ([Gazebo Simulation](../sim_gazebo_gz/index.md))
|
||||
|
||||
```sh
|
||||
wsl --install -d Ubuntu-22.04
|
||||
```
|
||||
|
||||
- Ubuntu 24.04 ([Gazebo Simulation](../sim_gazebo_gz/index.md))
|
||||
|
||||
```sh
|
||||
wsl --install -d Ubuntu-24.04
|
||||
```
|
||||
|
||||
::: info
|
||||
You can also install[Ubuntu 20.04](https://www.microsoft.com/store/productId/9MTTCL66CPXJ) and [Ubuntu 22.04](https://www.microsoft.com/store/productId/9PN20MSR04DW) from the store, which allows you to delete the application using the normal Windows Add/Remove settings:
|
||||
You can also [Ubuntu 24.04](https://www.microsoft.com/store/productId/9nz3klhxdjp5) or [Ubuntu 22.04](https://www.microsoft.com/store/productId/9PN20MSR04DW) from Microsoft Store, which allows you to delete the application using the normal Windows Add/Remove settings.
|
||||
:::
|
||||
|
||||
1. WSL will prompt you for a user name and password for the Ubuntu installation.
|
||||
@@ -106,7 +106,7 @@ To open a WSL shell using a command prompt:
|
||||
```
|
||||
|
||||
```sh
|
||||
wsl -d Ubuntu-20.04
|
||||
wsl -d Ubuntu-24.04
|
||||
```
|
||||
|
||||
If you only have one version of Ubuntu, you can just use `wsl`.
|
||||
|
||||
@@ -124,10 +124,10 @@ Once that is done you don't need to do anything else; the toolchain will automat
|
||||
|
||||
This section includes guidance on setup and build errors.
|
||||
|
||||
### Ubuntu 18.04: "Visual Studio Code is unable to watch for file changes in this large workspace"
|
||||
### "Visual Studio Code is unable to watch for file changes in this large workspace"
|
||||
|
||||
This error surfaces on startup.
|
||||
On some systems, there is an upper-limit of 8192 file handles imposed on applications, which means that VSCode might not be able to detect file modifications in `/PX4-Autopilot`.
|
||||
On some systems, there is an upper-limit on file handles imposed on applications, which means that VSCode might not be able to detect file modifications in `/PX4-Autopilot`.
|
||||
|
||||
You can increase this limit to avoid the error, at the expense of memory consumption.
|
||||
Follow the [instructions here](https://code.visualstudio.com/docs/setup/linux#_visual-studio-code-is-unable-to-watch-for-file-changes-in-this-large-workspace-error-enospc).
|
||||
|
||||
@@ -281,6 +281,19 @@ PX4 DroneCAN parameters:
|
||||
Select the specific CAN interface(s) used for ESC data output using the [UAVCAN_ESC_IFACE](../advanced_config/parameter_reference.md#UAVCAN_ESC_IFACE) parameter (all that all interfaces are selected by default).
|
||||
Note that DroneCAN ESCs should be on their own dedicated CAN interface(s) because ESC messages can saturate the bus and starve other nodes of bandwidth.
|
||||
|
||||
### Lights
|
||||
|
||||
PX4 can control LEDs via DroneCAN [LightsCommand](https://dronecan.github.io/Specification/7._List_of_standard_data_types/#lightscommand) messages.
|
||||
|
||||
Configuration:
|
||||
|
||||
1. Set [UAVCAN_LGT_NUM](../advanced_config/parameter_reference.md#UAVCAN_LGT_NUM) to the number of lights (0 disables). You might need to reopen the ground station to have parameters for new instances available.
|
||||
2. For each light slot (0 to NUM-1), set:
|
||||
- `UAVCAN_LGT_IDx`: The `light_id` matching your peripheral.
|
||||
- `UAVCAN_LGT_FNx`: `Status` for system status colours, or `Anti-collision` for white beacon.
|
||||
3. For anti-collision lights, [UAVCAN_LGT_ANTCL](../advanced_config/parameter_reference.md#UAVCAN_LGT_ANTCL) controls when they illuminate (off, armed, prearmed, always on).
|
||||
4. Reboot for any changes to take effect.
|
||||
|
||||
## QGC CANNODE Parameter Configuration
|
||||
|
||||
QGroundControl can inspect and modify parameters belonging to CAN devices attached to the flight controller, provided the device are connected to the flight controller before QGC is started.
|
||||
|
||||
@@ -85,6 +85,7 @@ The vehicle always respects normal FW max/min throttle settings during takeoff (
|
||||
In _catapult/hand-launch mode_ the vehicle waits to detect launch (based on acceleration trigger).
|
||||
On launch it enables the motor(s) and climbs with the maximum climb rate [FW_T_CLMB_MAX](#FW_T_CLMB_MAX) while keeping the pitch setpoint above [FW_TKO_PITCH_MIN](#FW_TKO_PITCH_MIN).
|
||||
Once it reaches [MIS_TAKEOFF_ALT](#MIS_TAKEOFF_ALT) it will automatically switch to [Hold mode](../flight_modes_fw/hold.md) and loiter.
|
||||
It is possible to delay the activation of the motors and control surfaces separately, see parameters [FW_LAUN_MOT_DEL](#FW_LAUN_MOT_DEL), [FW_LAUN_CS_LK_DY](#FW_LAUN_CS_LK_DY) and [CA_CS_LAUN_LK](#CA_CS_LAUN_LK). The later is also exposed in the actuator configuration page under the advanced view.
|
||||
|
||||
All RC stick movement is ignored during the full takeoff sequence.
|
||||
|
||||
@@ -105,6 +106,8 @@ The _launch detector_ is affected by the following parameters:
|
||||
| <a id="FW_LAUN_AC_THLD"></a>[FW_LAUN_AC_THLD](../advanced_config/parameter_reference.md#FW_LAUN_AC_THLD) | Acceleration threshold (acceleration in body-forward direction must be above this value) |
|
||||
| <a id="FW_LAUN_AC_T"></a>[FW_LAUN_AC_T](../advanced_config/parameter_reference.md#FW_LAUN_AC_T) | Trigger time (acceleration must be above threshold for this amount of seconds) |
|
||||
| <a id="FW_LAUN_MOT_DEL"></a>[FW_LAUN_MOT_DEL](../advanced_config/parameter_reference.md#FW_LAUN_MOT_DEL) | Delay from launch detection to motor spin up |
|
||||
| <a id="FW_LAUN_CS_LK_DY"></a>[FW_LAUN_CS_LK_DY](../advanced_config/parameter_reference.md#FW_LAUN_CS_LK_DY) | Delay from launch detection to unlocking the control surfaces |
|
||||
| <a id="CA_CS_LAUN_LK"></a>[CA_CS_LAUN_LK](../advanced_config/parameter_reference.md#CA_CS_LAUN_LK) | Bitmask to select which control surfaces are to be locked during launch |
|
||||
|
||||
## Runway Takeoff {#runway_launch}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ This topic explains how to add new MAVLink messages and commands that are expect
|
||||
## Standard MAVLink Messages
|
||||
|
||||
The PX4/PX4-Autopilot source code uses only messages that have been standardized by MAVLink.
|
||||
That is to say, the standard definitions in [common.xml](https://mavlink.io/en/messages/common.html) in releases, and [development.xml](https://mavlink.io/en/messages/development.html) during development.
|
||||
That is to say, the definitions in [common.xml](https://mavlink.io/en/messages/common.html) or [development.xml](https://mavlink.io/en/messages/development.html) in releases, and [development.xml](https://mavlink.io/en/messages/development.html) during development.
|
||||
These messages are present in at least one significant flight stack, and members of other flight stacks have accepted them as a reasonable design that would likely be adopted if the same functionality was required.
|
||||
|
||||
::: tip
|
||||
|
||||
+186
-186
@@ -94,199 +94,199 @@ They are not build into the module, and hence are neither published or subscribe
|
||||
|
||||
::: details See messages
|
||||
|
||||
- [GpioIn](../msg_docs/GpioIn.md)
|
||||
- [SystemPower](../msg_docs/SystemPower.md)
|
||||
- [LandingTargetInnovations](../msg_docs/LandingTargetInnovations.md)
|
||||
- [VehicleOpticalFlow](../msg_docs/VehicleOpticalFlow.md)
|
||||
- [LandingTargetPose](../msg_docs/LandingTargetPose.md)
|
||||
- [EstimatorGpsStatus](../msg_docs/EstimatorGpsStatus.md)
|
||||
- [EstimatorBias](../msg_docs/EstimatorBias.md)
|
||||
- [ParameterSetValueResponse](../msg_docs/ParameterSetValueResponse.md)
|
||||
- [LogMessage](../msg_docs/LogMessage.md)
|
||||
- [PowerMonitor](../msg_docs/PowerMonitor.md)
|
||||
- [VehicleConstraints](../msg_docs/VehicleConstraints.md)
|
||||
- [SensorAirflow](../msg_docs/SensorAirflow.md)
|
||||
- [ArmingCheckRequestV0](../msg_docs/ArmingCheckRequestV0.md)
|
||||
- [ActuatorArmed](../msg_docs/ActuatorArmed.md)
|
||||
- [HoverThrustEstimate](../msg_docs/HoverThrustEstimate.md)
|
||||
- [LaunchDetectionStatus](../msg_docs/LaunchDetectionStatus.md)
|
||||
- [DifferentialPressure](../msg_docs/DifferentialPressure.md)
|
||||
- [Ekf2Timestamps](../msg_docs/Ekf2Timestamps.md)
|
||||
- [EstimatorAidSource2d](../msg_docs/EstimatorAidSource2d.md)
|
||||
- [OpenDroneIdOperatorId](../msg_docs/OpenDroneIdOperatorId.md)
|
||||
- [AutotuneAttitudeControlStatus](../msg_docs/AutotuneAttitudeControlStatus.md)
|
||||
- [EventV0](../msg_docs/EventV0.md)
|
||||
- [EscStatus](../msg_docs/EscStatus.md)
|
||||
- [VehicleAirData](../msg_docs/VehicleAirData.md)
|
||||
- [GpsDump](../msg_docs/GpsDump.md)
|
||||
- [IridiumsbdStatus](../msg_docs/IridiumsbdStatus.md)
|
||||
- [DebugValue](../msg_docs/DebugValue.md)
|
||||
- [SensorGyroFft](../msg_docs/SensorGyroFft.md)
|
||||
- [CameraStatus](../msg_docs/CameraStatus.md)
|
||||
- [GimbalManagerStatus](../msg_docs/GimbalManagerStatus.md)
|
||||
- [CameraCapture](../msg_docs/CameraCapture.md)
|
||||
- [GimbalControls](../msg_docs/GimbalControls.md)
|
||||
- [MagnetometerBiasEstimate](../msg_docs/MagnetometerBiasEstimate.md)
|
||||
- [PwmInput](../msg_docs/PwmInput.md)
|
||||
- [OrbTestMedium](../msg_docs/OrbTestMedium.md)
|
||||
- [QshellReq](../msg_docs/QshellReq.md)
|
||||
- [GeofenceStatus](../msg_docs/GeofenceStatus.md)
|
||||
- [RcChannels](../msg_docs/RcChannels.md)
|
||||
- [Cpuload](../msg_docs/Cpuload.md)
|
||||
- [DebugArray](../msg_docs/DebugArray.md)
|
||||
- [FlightPhaseEstimation](../msg_docs/FlightPhaseEstimation.md)
|
||||
- [Mission](../msg_docs/Mission.md)
|
||||
- [AirspeedValidatedV0](../msg_docs/AirspeedValidatedV0.md)
|
||||
- [BatteryStatusV0](../msg_docs/BatteryStatusV0.md)
|
||||
- [FollowTarget](../msg_docs/FollowTarget.md)
|
||||
- [LandingGearWheel](../msg_docs/LandingGearWheel.md)
|
||||
- [SensorGyroFifo](../msg_docs/SensorGyroFifo.md)
|
||||
- [ParameterSetUsedRequest](../msg_docs/ParameterSetUsedRequest.md)
|
||||
- [TrajectorySetpoint6dof](../msg_docs/TrajectorySetpoint6dof.md)
|
||||
- [CameraTrigger](../msg_docs/CameraTrigger.md)
|
||||
- [MavlinkTunnel](../msg_docs/MavlinkTunnel.md)
|
||||
- [RegisterExtComponentRequestV0](../msg_docs/RegisterExtComponentRequestV0.md)
|
||||
- [GimbalDeviceInformation](../msg_docs/GimbalDeviceInformation.md)
|
||||
- [ActuatorArmed](../msg_docs/ActuatorArmed.md)
|
||||
- [SensorUwb](../msg_docs/SensorUwb.md)
|
||||
- [MountOrientation](../msg_docs/MountOrientation.md)
|
||||
- [ArmingCheckRequestV0](../msg_docs/ArmingCheckRequestV0.md)
|
||||
- [UavcanParameterRequest](../msg_docs/UavcanParameterRequest.md)
|
||||
- [GpioOut](../msg_docs/GpioOut.md)
|
||||
- [FailureDetectorStatus](../msg_docs/FailureDetectorStatus.md)
|
||||
- [Airspeed](../msg_docs/Airspeed.md)
|
||||
- [LedControl](../msg_docs/LedControl.md)
|
||||
- [RoverSpeedStatus](../msg_docs/RoverSpeedStatus.md)
|
||||
- [RaptorStatus](../msg_docs/RaptorStatus.md)
|
||||
- [ActuatorOutputs](../msg_docs/ActuatorOutputs.md)
|
||||
- [GeneratorStatus](../msg_docs/GeneratorStatus.md)
|
||||
- [TaskStackInfo](../msg_docs/TaskStackInfo.md)
|
||||
- [EstimatorAidSource1d](../msg_docs/EstimatorAidSource1d.md)
|
||||
- [EstimatorSensorBias](../msg_docs/EstimatorSensorBias.md)
|
||||
- [FixedWingLateralStatus](../msg_docs/FixedWingLateralStatus.md)
|
||||
- [OrbTest](../msg_docs/OrbTest.md)
|
||||
- [ParameterSetValueRequest](../msg_docs/ParameterSetValueRequest.md)
|
||||
- [ParameterResetRequest](../msg_docs/ParameterResetRequest.md)
|
||||
- [RateCtrlStatus](../msg_docs/RateCtrlStatus.md)
|
||||
- [MissionResult](../msg_docs/MissionResult.md)
|
||||
- [QshellRetval](../msg_docs/QshellRetval.md)
|
||||
- [FlightPhaseEstimation](../msg_docs/FlightPhaseEstimation.md)
|
||||
- [BatteryInfo](../msg_docs/BatteryInfo.md)
|
||||
- [OpenDroneIdSelfId](../msg_docs/OpenDroneIdSelfId.md)
|
||||
- [UlogStreamAck](../msg_docs/UlogStreamAck.md)
|
||||
- [PwmInput](../msg_docs/PwmInput.md)
|
||||
- [YawEstimatorStatus](../msg_docs/YawEstimatorStatus.md)
|
||||
- [DatamanRequest](../msg_docs/DatamanRequest.md)
|
||||
- [InputRc](../msg_docs/InputRc.md)
|
||||
- [DatamanResponse](../msg_docs/DatamanResponse.md)
|
||||
- [DronecanNodeStatus](../msg_docs/DronecanNodeStatus.md)
|
||||
- [OpenDroneIdArmStatus](../msg_docs/OpenDroneIdArmStatus.md)
|
||||
- [SensorGyro](../msg_docs/SensorGyro.md)
|
||||
- [VehicleLocalPositionV0](../msg_docs/VehicleLocalPositionV0.md)
|
||||
- [DebugKeyValue](../msg_docs/DebugKeyValue.md)
|
||||
- [LandingTargetPose](../msg_docs/LandingTargetPose.md)
|
||||
- [EstimatorBias3d](../msg_docs/EstimatorBias3d.md)
|
||||
- [SensorBaro](../msg_docs/SensorBaro.md)
|
||||
- [CellularStatus](../msg_docs/CellularStatus.md)
|
||||
- [NavigatorMissionItem](../msg_docs/NavigatorMissionItem.md)
|
||||
- [NormalizedUnsignedSetpoint](../msg_docs/NormalizedUnsignedSetpoint.md)
|
||||
- [UlogStream](../msg_docs/UlogStream.md)
|
||||
- [VehicleStatusV0](../msg_docs/VehicleStatusV0.md)
|
||||
- [SensorGnssRelative](../msg_docs/SensorGnssRelative.md)
|
||||
- [RadioStatus](../msg_docs/RadioStatus.md)
|
||||
- [RoverAttitudeStatus](../msg_docs/RoverAttitudeStatus.md)
|
||||
- [SensorsStatusImu](../msg_docs/SensorsStatusImu.md)
|
||||
- [AdcReport](../msg_docs/AdcReport.md)
|
||||
- [RoverRateStatus](../msg_docs/RoverRateStatus.md)
|
||||
- [TuneControl](../msg_docs/TuneControl.md)
|
||||
- [PpsCapture](../msg_docs/PpsCapture.md)
|
||||
- [Cpuload](../msg_docs/Cpuload.md)
|
||||
- [GeofenceResult](../msg_docs/GeofenceResult.md)
|
||||
- [SensorHygrometer](../msg_docs/SensorHygrometer.md)
|
||||
- [NeuralControl](../msg_docs/NeuralControl.md)
|
||||
- [EstimatorStates](../msg_docs/EstimatorStates.md)
|
||||
- [Px4ioStatus](../msg_docs/Px4ioStatus.md)
|
||||
- [MagWorkerData](../msg_docs/MagWorkerData.md)
|
||||
- [VehicleMagnetometer](../msg_docs/VehicleMagnetometer.md)
|
||||
- [EstimatorBias](../msg_docs/EstimatorBias.md)
|
||||
- [DebugArray](../msg_docs/DebugArray.md)
|
||||
- [InternalCombustionEngineControl](../msg_docs/InternalCombustionEngineControl.md)
|
||||
- [HoverThrustEstimate](../msg_docs/HoverThrustEstimate.md)
|
||||
- [RtlStatus](../msg_docs/RtlStatus.md)
|
||||
- [SensorMag](../msg_docs/SensorMag.md)
|
||||
- [EstimatorSelectorStatus](../msg_docs/EstimatorSelectorStatus.md)
|
||||
- [HomePositionV0](../msg_docs/HomePositionV0.md)
|
||||
- [EstimatorStatus](../msg_docs/EstimatorStatus.md)
|
||||
- [ActuatorServosTrim](../msg_docs/ActuatorServosTrim.md)
|
||||
- [Rpm](../msg_docs/Rpm.md)
|
||||
- [GpioRequest](../msg_docs/GpioRequest.md)
|
||||
- [VehicleOpticalFlow](../msg_docs/VehicleOpticalFlow.md)
|
||||
- [InternalCombustionEngineStatus](../msg_docs/InternalCombustionEngineStatus.md)
|
||||
- [OrbTestLarge](../msg_docs/OrbTestLarge.md)
|
||||
- [IrlockReport](../msg_docs/IrlockReport.md)
|
||||
- [FixedWingRunwayControl](../msg_docs/FixedWingRunwayControl.md)
|
||||
- [QshellReq](../msg_docs/QshellReq.md)
|
||||
- [EstimatorAidSource3d](../msg_docs/EstimatorAidSource3d.md)
|
||||
- [TiltrotorExtraControls](../msg_docs/TiltrotorExtraControls.md)
|
||||
- [ControlAllocatorStatus](../msg_docs/ControlAllocatorStatus.md)
|
||||
- [VehicleOpticalFlowVel](../msg_docs/VehicleOpticalFlowVel.md)
|
||||
- [EstimatorGpsStatus](../msg_docs/EstimatorGpsStatus.md)
|
||||
- [PowerButtonState](../msg_docs/PowerButtonState.md)
|
||||
- [Mission](../msg_docs/Mission.md)
|
||||
- [RegisterExtComponentReplyV0](../msg_docs/RegisterExtComponentReplyV0.md)
|
||||
- [Ping](../msg_docs/Ping.md)
|
||||
- [LogMessage](../msg_docs/LogMessage.md)
|
||||
- [HealthReport](../msg_docs/HealthReport.md)
|
||||
- [RtlTimeEstimate](../msg_docs/RtlTimeEstimate.md)
|
||||
- [FollowTargetStatus](../msg_docs/FollowTargetStatus.md)
|
||||
- [ActuatorTest](../msg_docs/ActuatorTest.md)
|
||||
- [GimbalManagerSetManualControl](../msg_docs/GimbalManagerSetManualControl.md)
|
||||
- [Event](../msg_docs/Event.md)
|
||||
- [LedControl](../msg_docs/LedControl.md)
|
||||
- [NavigatorStatus](../msg_docs/NavigatorStatus.md)
|
||||
- [GpioIn](../msg_docs/GpioIn.md)
|
||||
- [OrbTestMedium](../msg_docs/OrbTestMedium.md)
|
||||
- [VehicleImuStatus](../msg_docs/VehicleImuStatus.md)
|
||||
- [SensorGnssStatus](../msg_docs/SensorGnssStatus.md)
|
||||
- [PurePursuitStatus](../msg_docs/PurePursuitStatus.md)
|
||||
- [PowerMonitor](../msg_docs/PowerMonitor.md)
|
||||
- [CanInterfaceStatus](../msg_docs/CanInterfaceStatus.md)
|
||||
- [TecsStatus](../msg_docs/TecsStatus.md)
|
||||
- [GeofenceStatus](../msg_docs/GeofenceStatus.md)
|
||||
- [LoggerStatus](../msg_docs/LoggerStatus.md)
|
||||
- [WheelEncoders](../msg_docs/WheelEncoders.md)
|
||||
- [RaptorInput](../msg_docs/RaptorInput.md)
|
||||
- [DifferentialPressure](../msg_docs/DifferentialPressure.md)
|
||||
- [UavcanParameterValue](../msg_docs/UavcanParameterValue.md)
|
||||
- [SatelliteInfo](../msg_docs/SatelliteInfo.md)
|
||||
- [FixedWingLateralGuidanceStatus](../msg_docs/FixedWingLateralGuidanceStatus.md)
|
||||
- [FigureEightStatus](../msg_docs/FigureEightStatus.md)
|
||||
- [EstimatorInnovations](../msg_docs/EstimatorInnovations.md)
|
||||
- [VehicleImuStatus](../msg_docs/VehicleImuStatus.md)
|
||||
- [VehicleLocalPositionSetpoint](../msg_docs/VehicleLocalPositionSetpoint.md)
|
||||
- [InputRc](../msg_docs/InputRc.md)
|
||||
- [UavcanParameterRequest](../msg_docs/UavcanParameterRequest.md)
|
||||
- [FixedWingRunwayControl](../msg_docs/FixedWingRunwayControl.md)
|
||||
- [SensorCorrection](../msg_docs/SensorCorrection.md)
|
||||
- [ControlAllocatorStatus](../msg_docs/ControlAllocatorStatus.md)
|
||||
- [AirspeedValidatedV0](../msg_docs/AirspeedValidatedV0.md)
|
||||
- [CanInterfaceStatus](../msg_docs/CanInterfaceStatus.md)
|
||||
- [SensorSelection](../msg_docs/SensorSelection.md)
|
||||
- [DeviceInformation](../msg_docs/DeviceInformation.md)
|
||||
- [CameraTrigger](../msg_docs/CameraTrigger.md)
|
||||
- [SensorAccel](../msg_docs/SensorAccel.md)
|
||||
- [ActuatorServosTrim](../msg_docs/ActuatorServosTrim.md)
|
||||
- [SensorsStatusImu](../msg_docs/SensorsStatusImu.md)
|
||||
- [EstimatorBias3d](../msg_docs/EstimatorBias3d.md)
|
||||
- [GimbalManagerStatus](../msg_docs/GimbalManagerStatus.md)
|
||||
- [BatteryStatusV0](../msg_docs/BatteryStatusV0.md)
|
||||
- [OpenDroneIdSelfId](../msg_docs/OpenDroneIdSelfId.md)
|
||||
- [VehicleImu](../msg_docs/VehicleImu.md)
|
||||
- [MissionResult](../msg_docs/MissionResult.md)
|
||||
- [SensorAccelFifo](../msg_docs/SensorAccelFifo.md)
|
||||
- [DistanceSensorModeChangeRequest](../msg_docs/DistanceSensorModeChangeRequest.md)
|
||||
- [SensorPreflightMag](../msg_docs/SensorPreflightMag.md)
|
||||
- [OrbTest](../msg_docs/OrbTest.md)
|
||||
- [PositionControllerLandingStatus](../msg_docs/PositionControllerLandingStatus.md)
|
||||
- [FuelTankStatus](../msg_docs/FuelTankStatus.md)
|
||||
- [OpenDroneIdSystem](../msg_docs/OpenDroneIdSystem.md)
|
||||
- [OrbitStatus](../msg_docs/OrbitStatus.md)
|
||||
- [Px4ioStatus](../msg_docs/Px4ioStatus.md)
|
||||
- [RtlStatus](../msg_docs/RtlStatus.md)
|
||||
- [ButtonEvent](../msg_docs/ButtonEvent.md)
|
||||
- [VehicleLocalPositionV0](../msg_docs/VehicleLocalPositionV0.md)
|
||||
- [DebugValue](../msg_docs/DebugValue.md)
|
||||
- [ParameterSetUsedRequest](../msg_docs/ParameterSetUsedRequest.md)
|
||||
- [RoverSpeedStatus](../msg_docs/RoverSpeedStatus.md)
|
||||
- [SensorHygrometer](../msg_docs/SensorHygrometer.md)
|
||||
- [OpenDroneIdOperatorId](../msg_docs/OpenDroneIdOperatorId.md)
|
||||
- [InternalCombustionEngineStatus](../msg_docs/InternalCombustionEngineStatus.md)
|
||||
- [GpioOut](../msg_docs/GpioOut.md)
|
||||
- [ActuatorTest](../msg_docs/ActuatorTest.md)
|
||||
- [SensorBaro](../msg_docs/SensorBaro.md)
|
||||
- [PositionControllerStatus](../msg_docs/PositionControllerStatus.md)
|
||||
- [PurePursuitStatus](../msg_docs/PurePursuitStatus.md)
|
||||
- [RoverRateStatus](../msg_docs/RoverRateStatus.md)
|
||||
- [TecsStatus](../msg_docs/TecsStatus.md)
|
||||
- [PpsCapture](../msg_docs/PpsCapture.md)
|
||||
- [RaptorStatus](../msg_docs/RaptorStatus.md)
|
||||
- [EventV0](../msg_docs/EventV0.md)
|
||||
- [GpioRequest](../msg_docs/GpioRequest.md)
|
||||
- [FollowTargetEstimator](../msg_docs/FollowTargetEstimator.md)
|
||||
- [MagWorkerData](../msg_docs/MagWorkerData.md)
|
||||
- [FollowTarget](../msg_docs/FollowTarget.md)
|
||||
- [EstimatorAidSource1d](../msg_docs/EstimatorAidSource1d.md)
|
||||
- [GimbalDeviceSetAttitude](../msg_docs/GimbalDeviceSetAttitude.md)
|
||||
- [SensorGnssRelative](../msg_docs/SensorGnssRelative.md)
|
||||
- [ActionRequest](../msg_docs/ActionRequest.md)
|
||||
- [NavigatorMissionItem](../msg_docs/NavigatorMissionItem.md)
|
||||
- [GpsInjectData](../msg_docs/GpsInjectData.md)
|
||||
- [VehicleStatusV0](../msg_docs/VehicleStatusV0.md)
|
||||
- [DronecanNodeStatus](../msg_docs/DronecanNodeStatus.md)
|
||||
- [UlogStream](../msg_docs/UlogStream.md)
|
||||
- [DebugKeyValue](../msg_docs/DebugKeyValue.md)
|
||||
- [NavigatorStatus](../msg_docs/NavigatorStatus.md)
|
||||
- [MountOrientation](../msg_docs/MountOrientation.md)
|
||||
- [RcParameterMap](../msg_docs/RcParameterMap.md)
|
||||
- [AdcReport](../msg_docs/AdcReport.md)
|
||||
- [EstimatorSensorBias](../msg_docs/EstimatorSensorBias.md)
|
||||
- [InternalCombustionEngineControl](../msg_docs/InternalCombustionEngineControl.md)
|
||||
- [MavlinkLog](../msg_docs/MavlinkLog.md)
|
||||
- [VehicleMagnetometer](../msg_docs/VehicleMagnetometer.md)
|
||||
- [GpioConfig](../msg_docs/GpioConfig.md)
|
||||
- [GainCompression](../msg_docs/GainCompression.md)
|
||||
- [DebugVect](../msg_docs/DebugVect.md)
|
||||
- [ArmingCheckReplyV0](../msg_docs/ArmingCheckReplyV0.md)
|
||||
- [VehicleAttitudeSetpointV0](../msg_docs/VehicleAttitudeSetpointV0.md)
|
||||
- [FollowTargetStatus](../msg_docs/FollowTargetStatus.md)
|
||||
- [RtlTimeEstimate](../msg_docs/RtlTimeEstimate.md)
|
||||
- [RoverAttitudeStatus](../msg_docs/RoverAttitudeStatus.md)
|
||||
- [SensorUwb](../msg_docs/SensorUwb.md)
|
||||
- [YawEstimatorStatus](../msg_docs/YawEstimatorStatus.md)
|
||||
- [VelocityLimits](../msg_docs/VelocityLimits.md)
|
||||
- [TrajectorySetpoint6dof](../msg_docs/TrajectorySetpoint6dof.md)
|
||||
- [OpenDroneIdArmStatus](../msg_docs/OpenDroneIdArmStatus.md)
|
||||
- [EscStatus](../msg_docs/EscStatus.md)
|
||||
- [GimbalManagerInformation](../msg_docs/GimbalManagerInformation.md)
|
||||
- [HeaterStatus](../msg_docs/HeaterStatus.md)
|
||||
- [EstimatorSelectorStatus](../msg_docs/EstimatorSelectorStatus.md)
|
||||
- [GeofenceResult](../msg_docs/GeofenceResult.md)
|
||||
- [PowerButtonState](../msg_docs/PowerButtonState.md)
|
||||
- [Rpm](../msg_docs/Rpm.md)
|
||||
- [WheelEncoders](../msg_docs/WheelEncoders.md)
|
||||
- [LoggerStatus](../msg_docs/LoggerStatus.md)
|
||||
- [CellularStatus](../msg_docs/CellularStatus.md)
|
||||
- [TuneControl](../msg_docs/TuneControl.md)
|
||||
- [ConfigOverridesV0](../msg_docs/ConfigOverridesV0.md)
|
||||
- [GimbalManagerSetAttitude](../msg_docs/GimbalManagerSetAttitude.md)
|
||||
- [OrbTestLarge](../msg_docs/OrbTestLarge.md)
|
||||
- [BatteryInfo](../msg_docs/BatteryInfo.md)
|
||||
- [CameraStatus](../msg_docs/CameraStatus.md)
|
||||
- [QshellRetval](../msg_docs/QshellRetval.md)
|
||||
- [SensorMag](../msg_docs/SensorMag.md)
|
||||
- [RateCtrlStatus](../msg_docs/RateCtrlStatus.md)
|
||||
- [TaskStackInfo](../msg_docs/TaskStackInfo.md)
|
||||
- [EstimatorAidSource2d](../msg_docs/EstimatorAidSource2d.md)
|
||||
- [AirspeedWind](../msg_docs/AirspeedWind.md)
|
||||
- [AutotuneAttitudeControlStatus](../msg_docs/AutotuneAttitudeControlStatus.md)
|
||||
- [GimbalDeviceInformation](../msg_docs/GimbalDeviceInformation.md)
|
||||
- [GpsDump](../msg_docs/GpsDump.md)
|
||||
- [SensorTemp](../msg_docs/SensorTemp.md)
|
||||
- [ParameterResetRequest](../msg_docs/ParameterResetRequest.md)
|
||||
- [TiltrotorExtraControls](../msg_docs/TiltrotorExtraControls.md)
|
||||
- [SensorsStatus](../msg_docs/SensorsStatus.md)
|
||||
- [EstimatorStatus](../msg_docs/EstimatorStatus.md)
|
||||
- [FailureDetectorStatus](../msg_docs/FailureDetectorStatus.md)
|
||||
- [VehicleAirData](../msg_docs/VehicleAirData.md)
|
||||
- [ActuatorControlsStatus](../msg_docs/ActuatorControlsStatus.md)
|
||||
- [TakeoffStatus](../msg_docs/TakeoffStatus.md)
|
||||
- [GeneratorStatus](../msg_docs/GeneratorStatus.md)
|
||||
- [SensorGyroFifo](../msg_docs/SensorGyroFifo.md)
|
||||
- [VehicleAngularVelocity](../msg_docs/VehicleAngularVelocity.md)
|
||||
- [LandingGearWheel](../msg_docs/LandingGearWheel.md)
|
||||
- [ParameterSetValueRequest](../msg_docs/ParameterSetValueRequest.md)
|
||||
- [RegisterExtComponentReplyV0](../msg_docs/RegisterExtComponentReplyV0.md)
|
||||
- [RaptorInput](../msg_docs/RaptorInput.md)
|
||||
- [SensorGyro](../msg_docs/SensorGyro.md)
|
||||
- [DebugVect](../msg_docs/DebugVect.md)
|
||||
- [PositionControllerLandingStatus](../msg_docs/PositionControllerLandingStatus.md)
|
||||
- [GimbalManagerSetAttitude](../msg_docs/GimbalManagerSetAttitude.md)
|
||||
- [ParameterUpdate](../msg_docs/ParameterUpdate.md)
|
||||
- [NormalizedUnsignedSetpoint](../msg_docs/NormalizedUnsignedSetpoint.md)
|
||||
- [PositionSetpoint](../msg_docs/PositionSetpoint.md)
|
||||
- [EstimatorStates](../msg_docs/EstimatorStates.md)
|
||||
- [ActuatorOutputs](../msg_docs/ActuatorOutputs.md)
|
||||
- [ManualControlSwitches](../msg_docs/ManualControlSwitches.md)
|
||||
- [UavcanParameterValue](../msg_docs/UavcanParameterValue.md)
|
||||
- [VehicleAngularAccelerationSetpoint](../msg_docs/VehicleAngularAccelerationSetpoint.md)
|
||||
- [EstimatorEventFlags](../msg_docs/EstimatorEventFlags.md)
|
||||
- [SensorGnssStatus](../msg_docs/SensorGnssStatus.md)
|
||||
- [GimbalManagerSetManualControl](../msg_docs/GimbalManagerSetManualControl.md)
|
||||
- [HomePositionV0](../msg_docs/HomePositionV0.md)
|
||||
- [FixedWingLateralStatus](../msg_docs/FixedWingLateralStatus.md)
|
||||
- [SatelliteInfo](../msg_docs/SatelliteInfo.md)
|
||||
- [IrlockReport](../msg_docs/IrlockReport.md)
|
||||
- [Ping](../msg_docs/Ping.md)
|
||||
- [CameraCapture](../msg_docs/CameraCapture.md)
|
||||
- [Vtx](../msg_docs/Vtx.md)
|
||||
- [Ekf2Timestamps](../msg_docs/Ekf2Timestamps.md)
|
||||
- [RegisterExtComponentRequestV0](../msg_docs/RegisterExtComponentRequestV0.md)
|
||||
- [EscReport](../msg_docs/EscReport.md)
|
||||
- [Gripper](../msg_docs/Gripper.md)
|
||||
- [UlogStreamAck](../msg_docs/UlogStreamAck.md)
|
||||
- [SensorGyroFft](../msg_docs/SensorGyroFft.md)
|
||||
- [PositionControllerStatus](../msg_docs/PositionControllerStatus.md)
|
||||
- [VehicleRoi](../msg_docs/VehicleRoi.md)
|
||||
- [ActuatorControlsStatus](../msg_docs/ActuatorControlsStatus.md)
|
||||
- [ActionRequest](../msg_docs/ActionRequest.md)
|
||||
- [VehicleLocalPositionSetpoint](../msg_docs/VehicleLocalPositionSetpoint.md)
|
||||
- [OpenDroneIdSystem](../msg_docs/OpenDroneIdSystem.md)
|
||||
- [EscReport](../msg_docs/EscReport.md)
|
||||
- [FollowTargetEstimator](../msg_docs/FollowTargetEstimator.md)
|
||||
- [GpioConfig](../msg_docs/GpioConfig.md)
|
||||
- [RcParameterMap](../msg_docs/RcParameterMap.md)
|
||||
- [ConfigOverridesV0](../msg_docs/ConfigOverridesV0.md)
|
||||
- [GimbalDeviceSetAttitude](../msg_docs/GimbalDeviceSetAttitude.md)
|
||||
- [LaunchDetectionStatus](../msg_docs/LaunchDetectionStatus.md)
|
||||
- [SensorAccel](../msg_docs/SensorAccel.md)
|
||||
- [VehicleAngularVelocity](../msg_docs/VehicleAngularVelocity.md)
|
||||
- [GainCompression](../msg_docs/GainCompression.md)
|
||||
- [GpsInjectData](../msg_docs/GpsInjectData.md)
|
||||
- [SensorPreflightMag](../msg_docs/SensorPreflightMag.md)
|
||||
- [Gripper](../msg_docs/Gripper.md)
|
||||
- [Vtx](../msg_docs/Vtx.md)
|
||||
- [PositionSetpoint](../msg_docs/PositionSetpoint.md)
|
||||
- [ParameterSetValueResponse](../msg_docs/ParameterSetValueResponse.md)
|
||||
- [DistanceSensorModeChangeRequest](../msg_docs/DistanceSensorModeChangeRequest.md)
|
||||
- [VehicleImu](../msg_docs/VehicleImu.md)
|
||||
- [SensorAirflow](../msg_docs/SensorAirflow.md)
|
||||
- [VehicleAngularAccelerationSetpoint](../msg_docs/VehicleAngularAccelerationSetpoint.md)
|
||||
- [VehicleConstraints](../msg_docs/VehicleConstraints.md)
|
||||
- [OrbitStatus](../msg_docs/OrbitStatus.md)
|
||||
- [LandingTargetInnovations](../msg_docs/LandingTargetInnovations.md)
|
||||
- [ButtonEvent](../msg_docs/ButtonEvent.md)
|
||||
- [SensorAccelFifo](../msg_docs/SensorAccelFifo.md)
|
||||
- [EstimatorEventFlags](../msg_docs/EstimatorEventFlags.md)
|
||||
- [ManualControlSwitches](../msg_docs/ManualControlSwitches.md)
|
||||
- [MavlinkLog](../msg_docs/MavlinkLog.md)
|
||||
- [SensorTemp](../msg_docs/SensorTemp.md)
|
||||
- [FuelTankStatus](../msg_docs/FuelTankStatus.md)
|
||||
- [DeviceInformation](../msg_docs/DeviceInformation.md)
|
||||
- [VehicleAcceleration](../msg_docs/VehicleAcceleration.md)
|
||||
- [NeuralControl](../msg_docs/NeuralControl.md)
|
||||
- [DatamanResponse](../msg_docs/DatamanResponse.md)
|
||||
- [GimbalControls](../msg_docs/GimbalControls.md)
|
||||
- [MavlinkTunnel](../msg_docs/MavlinkTunnel.md)
|
||||
- [EstimatorAidSource3d](../msg_docs/EstimatorAidSource3d.md)
|
||||
- [DatamanRequest](../msg_docs/DatamanRequest.md)
|
||||
- [Event](../msg_docs/Event.md)
|
||||
- [RadioStatus](../msg_docs/RadioStatus.md)
|
||||
- [VehicleOpticalFlowVel](../msg_docs/VehicleOpticalFlowVel.md)
|
||||
- [IridiumsbdStatus](../msg_docs/IridiumsbdStatus.md)
|
||||
- [SensorCorrection](../msg_docs/SensorCorrection.md)
|
||||
- [SystemPower](../msg_docs/SystemPower.md)
|
||||
- [GimbalManagerInformation](../msg_docs/GimbalManagerInformation.md)
|
||||
- [VehicleAttitudeSetpointV0](../msg_docs/VehicleAttitudeSetpointV0.md)
|
||||
- [ArmingCheckReplyV0](../msg_docs/ArmingCheckReplyV0.md)
|
||||
- [RcChannels](../msg_docs/RcChannels.md)
|
||||
- [EstimatorInnovations](../msg_docs/EstimatorInnovations.md)
|
||||
- [VelocityLimits](../msg_docs/VelocityLimits.md)
|
||||
- [TakeoffStatus](../msg_docs/TakeoffStatus.md)
|
||||
- [SensorSelection](../msg_docs/SensorSelection.md)
|
||||
- [AirspeedWind](../msg_docs/AirspeedWind.md)
|
||||
- [HeaterStatus](../msg_docs/HeaterStatus.md)
|
||||
:::
|
||||
|
||||
@@ -98,13 +98,56 @@ leddar_one <command> [arguments...]
|
||||
stop Stop driver
|
||||
```
|
||||
|
||||
## lightware_grf_serial
|
||||
|
||||
Source: [drivers/distance_sensor/lightware_grf_serial](https://github.com/PX4/PX4-Autopilot/tree/main/src/drivers/distance_sensor/lightware_grf_serial)
|
||||
|
||||
### Description
|
||||
|
||||
Serial bus driver for the Lightware GRF Laser rangefinder.
|
||||
|
||||
### Configuration
|
||||
|
||||
https://docs.px4.io/main/en/sensor/grf_lidar
|
||||
|
||||
### Parameters
|
||||
|
||||
https://docs.px4.io/main/en/advanced_config/parameter_reference#GRF_SENS_MODEL
|
||||
https://docs.px4.io/main/en/advanced_config/parameter_reference#GRF_RATE_CFG
|
||||
https://docs.px4.io/main/en/advanced_config/parameter_reference#SENS_EN_GRF_CFG
|
||||
|
||||
### Examples
|
||||
|
||||
Attempt to start driver on a specified serial device.
|
||||
|
||||
```
|
||||
lightware_grf_serial start -d /dev/ttyS1
|
||||
```
|
||||
|
||||
Stop driver
|
||||
|
||||
```
|
||||
lightware_grf_serial stop
|
||||
```
|
||||
|
||||
### Usage {#lightware_grf_serial_usage}
|
||||
|
||||
```
|
||||
lightware_grf_serial <command> [arguments...]
|
||||
Commands:
|
||||
start Start driver
|
||||
-d <val> Serial device
|
||||
|
||||
stop Stop driver
|
||||
```
|
||||
|
||||
## lightware_laser_i2c
|
||||
|
||||
Source: [drivers/distance_sensor/lightware_laser_i2c](https://github.com/PX4/PX4-Autopilot/tree/main/src/drivers/distance_sensor/lightware_laser_i2c)
|
||||
|
||||
### Description
|
||||
|
||||
I2C bus driver for Lightware SFxx series LIDAR rangefinders: SF10/a, SF10/b, SF10/c, SF11/c, SF/LW20, SF30/d.
|
||||
I2C bus driver for Lightware LIDAR rangefinders: SF10/a, SF10/b, SF10/c, SF11/c, SF/LW20, SF/LW30/d, GRF250, GRF500.
|
||||
|
||||
Setup/usage information: https://docs.px4.io/main/en/sensor/sfxx_lidar.html
|
||||
|
||||
@@ -122,8 +165,6 @@ lightware_laser_i2c <command> [arguments...]
|
||||
[-q] quiet startup (no message if no device found)
|
||||
[-a <val>] I2C address
|
||||
default: 102
|
||||
[-R <val>] Sensor rotation - downward facing by default
|
||||
default: 25
|
||||
|
||||
stop
|
||||
|
||||
|
||||
@@ -10,10 +10,11 @@ Status of the launch detection state machine (fixed-wing only).
|
||||
|
||||
## Fields
|
||||
|
||||
| Name | Type | Unit [Frame] | Range/Enum | Description |
|
||||
| ---------------------- | -------- | ------------ | ---------- | -------------------------------------- |
|
||||
| timestamp | `uint64` | | | time since system start (microseconds) |
|
||||
| launch_detection_state | `uint8` | | |
|
||||
| Name | Type | Unit [Frame] | Range/Enum | Description |
|
||||
| --------------------------------- | -------- | ------------ | ---------- | ------------------------------------------------------------------------------------------------------------- |
|
||||
| timestamp | `uint64` | | | time since system start (microseconds) |
|
||||
| launch_detection_state | `uint8` | | |
|
||||
| selected_control_surface_disarmed | `bool` | | | flag indicating whether selected actuators should kept disarmed (have to be configured in control allocation) |
|
||||
|
||||
## Constants
|
||||
|
||||
@@ -39,6 +40,8 @@ uint8 STATE_LAUNCH_DETECTED_DISABLED_MOTOR = 1 # launch detected, but keep moto
|
||||
uint8 STATE_FLYING = 2 # launch detected, use normal takeoff/flying configuration
|
||||
|
||||
uint8 launch_detection_state
|
||||
|
||||
bool selected_control_surface_disarmed # [-] flag indicating whether selected actuators should kept disarmed (have to be configured in control allocation)
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
@@ -38,6 +38,18 @@ Instructions for integrating the motor/ESC using with DroneCAN can be found in [
|
||||
|
||||
These instructions walk you through setting the correct parameters for enabling the flight controller's DroneCAN drivers, setting the correct configuration parameters for communication with Vertiq modules on the DroneCAN bus, ESC configuration, and testing that your flight controller can properly control your modules over DroneCAN.
|
||||
|
||||
#### LED Configuration for Vertiq Modules
|
||||
|
||||
::: info
|
||||
This configuration is only required if you have the optional [Vertiq LED module add-on](https://www.vertiq.co/add-ons).
|
||||
Standard Vertiq ESC modules do not include LEDs.
|
||||
:::
|
||||
|
||||
Vertiq LED Add-on modules have two LEDs per ESC (RGB for status, White for anti-collision).
|
||||
See [DroneCAN Lights](../dronecan/index.md#lights) for configuration instructions.
|
||||
|
||||
The `light_id` for each LED is calculated as: `esc_index × 3 + BASE_ID`, where `BASE_ID` is 1 for RGB and 2 for White.
|
||||
|
||||
### DShot/PWM Configuration
|
||||
|
||||
Instructions for integrating the motor/ESC using PWM and DShot can be found in [PWM and DShot Control with a Flight Controller](https://iqmotion.readthedocs.io/en/latest/tutorials/pwm_control_flight_controller.html).
|
||||
|
||||
@@ -26,7 +26,7 @@ They cover the _ROS Melodic and Noetic_ releases.
|
||||
|
||||
::: tab ROS Noetic (Ubuntu 20.04)
|
||||
|
||||
If you're working with [ROS Noetic](https://wiki.ros.org/noetic) on Ubuntu 20.04:
|
||||
If you're working with [ROS "Noetic"](https://wiki.ros.org/noetic) on Ubuntu 20.04:
|
||||
|
||||
1. Install PX4 without the simulator toolchain:
|
||||
1. [Download PX4 Source Code](../dev_setup/building_px4.md):
|
||||
@@ -57,7 +57,7 @@ If you're working with [ROS Noetic](https://wiki.ros.org/noetic) on Ubuntu 20.04
|
||||
|
||||
::: tab ROS Melodic (Ubuntu 18.04)
|
||||
|
||||
If you're working with ROS "Melodic on Ubuntu 18.04:
|
||||
If you're working with ROS "Melodic" on Ubuntu 18.04:
|
||||
|
||||
1. Download the [ubuntu_sim_ros_melodic.sh](https://raw.githubusercontent.com/PX4/Devguide/master/build_scripts/ubuntu_sim_ros_melodic.sh) script in a bash shell:
|
||||
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
# Lightware GRF250/GRF500 Gimbal Lidar
|
||||
|
||||
LightWare [GRF250](https://lightwarelidar.com/shop/grf-250/) and [GRF500](https://lightwarelidar.com/shop/grf-500/) are small and light Lidar modules with a range of 250m and 500m, respectively.
|
||||
|
||||

|
||||
|
||||
::: info
|
||||
The Lidar driver is not included in the default build of PX4.
|
||||
You will need to [create and use a custom build](#add-the-driver-to-the-px4-build).
|
||||
:::
|
||||
|
||||
## Where to Buy
|
||||
|
||||
Order these modules from:
|
||||
|
||||
- [GRF250](https://lightwarelidar.com/shop/grf-250/)
|
||||
- [GRF500](https://lightwarelidar.com/shop/grf-500/)
|
||||
|
||||
## Hardware Setup
|
||||
|
||||
The rangefinder can be connected to any unused serial port, such as `TELEM2`.
|
||||
[Parameter Configuration](#parameter-configuration) explains how to configure the port to use and the other properties of the rangefinder.
|
||||
|
||||
## PX4 Setup
|
||||
|
||||
### Add the Driver to the PX4 Build
|
||||
|
||||
The [lightware_grf_serial](../modules/modules_driver_distance_sensor.md#lightware-grf-serial) driver for this Lidar is not included in PX4 firmware by default.
|
||||
In order to use these modules you will first need to update the firmware configuration to add the driver, and then build the firmware.
|
||||
|
||||
1. Update the firmware configuration. You can use either of the following options:
|
||||
- Menuconfig:
|
||||
1. Install and open [menuconfig](../hardware/porting_guide_config.md#px4-menuconfig-setup)
|
||||
2. In [menuconfig](../hardware/porting_guide_config.md#px4-menuconfig-setup), navigate to **Drivers > Distance sensors**
|
||||
3. Select/Enable `lightware_grf_serial`
|
||||
4. Save the configuration
|
||||
|
||||
- Manually update `default.px4` to include the configuration key:
|
||||
1. Open the `default.px4board` config file that corresponds to the board you want to build for.
|
||||
For example, to add the driver to `fmu-v6x` boards you would update [/boards/px4/fmu-v6x/default.px4board ](https://github.com/PX4/PX4-Autopilot/blob/main/boards/px4/fmu-v6x/default.px4board)
|
||||
2. Add the following line and save the file:
|
||||
|
||||
```txt
|
||||
CONFIG_DRIVERS_DISTANCE_SENSOR_LIGHTWARE_GRF_SERIAL=y
|
||||
```
|
||||
|
||||
2. [Build PX4](../dev_setup/building_px4.md) for your flight controller target and upload the new firmware.
|
||||
|
||||
### Parameter Configuration
|
||||
|
||||
You will need to configure PX4 to indicate the serial port to which the sensor is connected (as per [Serial Port Configuration](../peripherals/serial_configuration.md)) and also the orientation and other properties of the sensor.
|
||||
|
||||
The [parameters to change](../advanced_config/parameters.md) are listed in the table.
|
||||
|
||||
| Parameter | Description |
|
||||
| -------------------------------------------------------------------------------------------------------- | -------------------------------------------------- |
|
||||
| <a id="SENS_EN_GRF_CFG"></a>[SENS_EN_GRF_CFG](../advanced_config/parameter_reference.md#SENS_EN_GRF_CFG) | Set to the serial port the sensor is connected to. |
|
||||
| <a id="GRF_UPDATE_CFG"></a>[GRF_UPDATE_CFG](../advanced_config/parameter_reference.md#GRF_UPDATE_CFG) | Set the update rate. |
|
||||
| <a id="GRF_SENS_MODEL"></a>[GRF_SENS_MODEL](../advanced_config/parameter_reference.md#GRF_SENS_MODEL) | Set the update rate. |
|
||||
|
||||
## Testing
|
||||
|
||||
You can confirm that the sensor is correctly configured by connecting QGroundControl, and observing that [DISTANCE_SENSOR](https://mavlink.io/en/messages/common.html#DISTANCE_SENSOR) is present in the [MAVLink Inspector](https://docs.qgroundcontrol.com/master/en/qgc-user-guide/analyze_view/mavlink_inspector.html).
|
||||
|
||||
Moving the sensor around at various distances from a surface will have the `current_distance` value change.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If you are having problems with connecting to the sensor you may need to unassign a the default serial port. [Unassign Default Serial Port](../peripherals/serial_configuration.md)
|
||||
@@ -15,8 +15,8 @@ The following models are supported by PX4, and can be connected to either the I2
|
||||
| [LW20/C](https://lightware.co.za/products/lw20-c-100-m) | 100 | I2C bus | Waterproofed (IP67) with servo for sense-and-avoid applications |
|
||||
| [SF30/D](https://lightwarelidar.com/shop/sf30-d-200-m/) | 200 | I2C bus | Waterproofed (IP67) |
|
||||
| [SF45/B](../sensor/sf45_rotating_lidar.md) | 50 | Serial | Rotary Lidar (Used for [Collision Prevention](../computer_vision/collision_prevention.md)) |
|
||||
| [GRF250](https://lightwarelidar.com/shop/grf-250/) | 250 | I2C | Gimbal Range Finder |
|
||||
| [GRF500](https://lightwarelidar.com/shop/grf-500/) | 500 | I2C | Gimbal Range Finder |
|
||||
| [GRF250](../sensor/grf_lidar.md) | 250 | Serial or I2C | Gimbal Range Finder |
|
||||
| [GRF500](../sensor/grf_lidar.md) | 500 | Serial or I2C | Gimbal Range Finder |
|
||||
|
||||
::: details Discontinued
|
||||
|
||||
@@ -69,6 +69,9 @@ VTOL vehicles may choose to also set [SF1XX_MODE](../advanced_config/parameter_r
|
||||
::: tip
|
||||
[SF45/B](../sensor/sf45_rotating_lidar.md) setup is covered in the linked document.
|
||||
:::
|
||||
::: tip
|
||||
[GRF250/GRF500](../sensor/grf_lidar.md) setup is covered in the linked document.
|
||||
:::
|
||||
|
||||
### Hardware
|
||||
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
# PX4 Docker Containers
|
||||
|
||||
Docker containers are provided for the complete [PX4 development toolchain](../dev_setup/dev_env.md#supported-targets) including NuttX and Linux based hardware, [Gazebo Classic](../sim_gazebo_classic/index.md) simulation, and [ROS](../simulation/ros_interface.md).
|
||||
Docker containers are provided for the complete [PX4 development toolchain](../dev_setup/dev_env.md#supported-targets) including NuttX and Linux based hardware, [Gazebo](../sim_gazebo_gz/index.md) simulation, and [ROS 2](../ros2/user_guide.md).
|
||||
|
||||
This topic shows how to use the [available docker containers](#px4_containers) to access the build environment in a local Linux computer.
|
||||
|
||||
::: info
|
||||
Dockerfiles and README can be found on [Github here](https://github.com/PX4/PX4-containers/tree/master?tab=readme-ov-file#container-hierarchy).
|
||||
They are built automatically on [Docker Hub](https://hub.docker.com/u/px4io/).
|
||||
The recommended `px4-dev` container is built from the [Dockerfile in the PX4-Autopilot source tree](https://github.com/PX4/PX4-Autopilot/blob/main/Tools/setup/Dockerfile) by the [Container build workflow](https://github.com/PX4/PX4-Autopilot/actions/workflows/dev_container.yml).
|
||||
:::
|
||||
|
||||
## Prerequisites
|
||||
@@ -35,33 +34,36 @@ sudo usermod -aG docker $USER
|
||||
# Log in/out again before using docker!
|
||||
```
|
||||
|
||||
## Container Hierarchy {#px4_containers}
|
||||
## px4-dev Container (Recommended) {#px4_containers}
|
||||
|
||||
The available containers are on [GitHub here](https://github.com/PX4/PX4-containers/tree/master?tab=readme-ov-file#container-hierarchy).
|
||||
The **`px4-dev`** container is the recommended container for building PX4 firmware.
|
||||
It is a single, multi-architecture container (linux/amd64 and linux/arm64) based on Ubuntu 24.04 that includes everything needed to build PX4 for NuttX hardware targets.
|
||||
|
||||
These allow testing of various build targets and configurations (the included tools can be inferred from their names).
|
||||
The containers are hierarchical, such that containers have the functionality of their parents.
|
||||
For example, the partial hierarchy below shows that the docker container with NuttX build tools (`px4-dev-nuttx-focal`) does not include ROS 2, while the simulation containers do:
|
||||
It is published to both registries simultaneously:
|
||||
|
||||
```plain
|
||||
- px4io/px4-dev-base-focal
|
||||
- px4io/px4-dev-nuttx-focal
|
||||
- px4io/px4-dev-simulation-focal
|
||||
- px4io/px4-dev-ros-noetic
|
||||
- px4io/px4-dev-ros2-foxy
|
||||
- px4io/px4-dev-ros2-rolling
|
||||
- px4io/px4-dev-base-jammy
|
||||
- px4io/px4-dev-nuttx-jammy
|
||||
```
|
||||
- **GitHub Container Registry:** [ghcr.io/px4/px4-dev](https://github.com/PX4/PX4-Autopilot/pkgs/container/px4-dev)
|
||||
- **Docker Hub:** [px4io/px4-dev](https://hub.docker.com/r/px4io/px4-dev)
|
||||
|
||||
The most recent version can be accessed using the `latest` tag: `px4io/px4-dev-nuttx-focal:latest`
|
||||
(available tags are listed for each container on _hub.docker.com_.
|
||||
For example, the `px4io/px4-dev-nuttx-focal` tags can be found on [hub.docker.com here](https://hub.docker.com/r/px4io/px4-dev-nuttx-focal/tags?page=1&ordering=last_updated)).
|
||||
The container includes:
|
||||
|
||||
- Ubuntu 24.04 base
|
||||
- ARM cross-compiler (`gcc-arm-none-eabi`) and Xtensa compiler (for ESP32 targets)
|
||||
- Build tools: `cmake`, `ninja`, `ccache`, `make`
|
||||
- Python 3 with PX4 build dependencies
|
||||
- NuttX toolchain libraries (`libnewlib-arm-none-eabi`, etc.)
|
||||
|
||||
The container is built from the [Dockerfile](https://github.com/PX4/PX4-Autopilot/blob/main/Tools/setup/Dockerfile) in the PX4 source tree using the [Container build workflow](https://github.com/PX4/PX4-Autopilot/actions/workflows/dev_container.yml).
|
||||
Images are tagged with the PX4 version (e.g. `px4io/px4-dev:v1.16.0`).
|
||||
|
||||
:::tip
|
||||
Typically you should use a recent container, but not necessarily the `latest` (as this changes too often).
|
||||
A `px4-sim` container with simulation tools (Gazebo Harmonic) is planned to complement `px4-dev` for simulation workflows.
|
||||
:::
|
||||
|
||||
### Legacy Containers
|
||||
|
||||
The older per-distro containers from [PX4/PX4-containers](https://github.com/PX4/PX4-containers) (e.g. `px4-dev-nuttx-jammy`, `px4-dev-ros2-humble`, etc.) are no longer recommended.
|
||||
They will be replaced by `px4-dev` (for builds) and the upcoming `px4-sim` (for simulation).
|
||||
|
||||
## Use the Docker Container
|
||||
|
||||
The following instructions show how to build PX4 source code on the host computer using a toolchain running in a docker container.
|
||||
@@ -121,7 +123,7 @@ Where,
|
||||
- `<host_src>`: The host computer directory to be mapped to `<container_src>` in the container. This should normally be the **PX4-Autopilot** directory.
|
||||
- `<container_src>`: The location of the shared (source) directory when inside the container.
|
||||
- `<local_container_name>`: A name for the docker container being created. This can later be used if we need to reference the container again.
|
||||
- `<container>:<tag>`: The container with version tag to start - e.g.: `px4io/px4-dev-ros:2017-10-23`.
|
||||
- `<container>:<tag>`: The container with version tag to start - e.g.: `px4io/px4-dev:v1.16.0`.
|
||||
- `<build_command>`: The command to invoke on the new container. E.g. `bash` is used to open a bash shell in the container.
|
||||
|
||||
The concrete example below shows how to open a bash shell and share the directory **~/src/PX4-Autopilot** on the host computer.
|
||||
@@ -137,7 +139,7 @@ docker run -it --privileged \
|
||||
-v /tmp/.X11-unix:/tmp/.X11-unix:ro \
|
||||
-e DISPLAY=:0 \
|
||||
--network host \
|
||||
--name=px4-ros px4io/px4-dev-ros2-foxy:2022-07-31 bash
|
||||
--name=px4-dev px4io/px4-dev:v1.16.0 bash
|
||||
```
|
||||
|
||||
::: info
|
||||
@@ -155,7 +157,7 @@ Verify if everything works by running, for example, SITL:
|
||||
|
||||
```sh
|
||||
cd src/PX4-Autopilot #This is <container_src>
|
||||
make px4_sitl_default gazebo-classic
|
||||
make px4_sitl gz_x500
|
||||
```
|
||||
|
||||
### Re-enter the Container
|
||||
@@ -219,7 +221,7 @@ This ensures that all files created within the container will be accessible on t
|
||||
|
||||
#### Graphics Driver Issues
|
||||
|
||||
It's possible that running Gazebo Classic will result in a similar error message like the following:
|
||||
It's possible that running Gazebo will result in a similar error message like the following:
|
||||
|
||||
```sh
|
||||
libGL error: failed to load driver: swrast
|
||||
@@ -239,7 +241,7 @@ Any recent Linux distribution should work.
|
||||
|
||||
The following configuration is tested:
|
||||
|
||||
- OS X with VMWare Fusion and Ubuntu 14.04 (Docker container with GUI support on Parallels make the X-Server crash).
|
||||
- OS X with VMWare Fusion and Ubuntu 22.04 (Docker container with GUI support on Parallels make the X-Server crash).
|
||||
|
||||
**Memory**
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
@@ -7,3 +7,5 @@ uint8 STATE_LAUNCH_DETECTED_DISABLED_MOTOR = 1 # launch detected, but keep moto
|
||||
uint8 STATE_FLYING = 2 # launch detected, use normal takeoff/flying configuration
|
||||
|
||||
uint8 launch_detection_state
|
||||
|
||||
bool selected_control_surface_disarmed # [-] flag indicating whether selected actuators should kept disarmed (have to be configured in control allocation)
|
||||
|
||||
@@ -598,6 +598,7 @@ if(NOT NUTTX_DIR MATCHES "external")
|
||||
add_custom_target(jlink-nuttx ALL
|
||||
DEPENDS ${NUTTX_DIR}/tools/jlink-nuttx.so
|
||||
)
|
||||
add_dependencies(jlink-nuttx nuttx_context)
|
||||
|
||||
# JLINK_RTOS_PATH used by launch.json.in
|
||||
set(JLINK_RTOS_PATH ${NUTTX_DIR}/tools/jlink-nuttx.so)
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
############################################################################
|
||||
#
|
||||
# Copyright (c) 2026 PX4 Development Team. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# 3. Neither the name PX4 nor the names of its contributors may be
|
||||
# used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
############################################################################
|
||||
px4_add_module(
|
||||
MODULE drivers__distance_sensor__lightware_grf_serial
|
||||
MAIN lightware_grf_serial
|
||||
COMPILE_FLAGS
|
||||
SRCS
|
||||
lightware_grf_serial.cpp
|
||||
lightware_grf_serial.hpp
|
||||
lightware_grf_serial_main.cpp
|
||||
DEPENDS
|
||||
drivers_rangefinder
|
||||
px4_work_queue
|
||||
MODULE_CONFIG
|
||||
module.yaml
|
||||
)
|
||||
@@ -0,0 +1,5 @@
|
||||
menuconfig DRIVERS_DISTANCE_SENSOR_LIGHTWARE_GRF_SERIAL
|
||||
bool "lightware_grf_serial"
|
||||
default n
|
||||
---help---
|
||||
Enable support for lightware_grf_serial
|
||||
@@ -0,0 +1,91 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2026 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file grf_commands.h
|
||||
* @author Aaron Porter
|
||||
*
|
||||
* Declarations of grf serial commands for the Lightware grf series
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#define GRF_MAX_PAYLOAD 256
|
||||
#define GRF_CRC_FIELDS 2
|
||||
|
||||
enum GRF_SERIAL_CMD {
|
||||
GRF_PRODUCT_NAME = 0,
|
||||
GRF_HARDWARE_VERSION = 1,
|
||||
GRF_FIRMWARE_VERSION = 2,
|
||||
GRF_SERIAL_NUMBER = 3,
|
||||
GRF_TEXT_MESSAGE = 7,
|
||||
GRF_USER_DATA = 9,
|
||||
GRF_TOKEN = 10,
|
||||
GRF_SAVE_PARAMETERS = 12,
|
||||
GRF_RESET = 14,
|
||||
GRF_STAGE_FIRMWARE = 16,
|
||||
GRF_COMMIT_FIRMWARE = 17,
|
||||
GRF_DISTANCE_OUTPUT = 27,
|
||||
GRF_STREAM = 30,
|
||||
GRF_DISTANCE_DATA_CM = 44,
|
||||
GRF_DISTANCE_DATA_MM = 45,
|
||||
GRF_LASER_FIRING = 50,
|
||||
GRF_TEMPERATURE = 55,
|
||||
GRF_AUTO_EXPOSURE = 70,
|
||||
GRF_UPDATE_RATE = 74,
|
||||
GRF_LOST_SIGNAL_COUNT = 78,
|
||||
GRF_GPIO_MODE = 83,
|
||||
GRF_GPIO_ALARM = 84,
|
||||
GRF_MEDIAN_FILTER_EN = 86,
|
||||
GRF_MEDIAN_FILETER_S = 87,
|
||||
GRF_SMOOTH_FILTER_EN = 88,
|
||||
GRF_SMOOTH_FACTOR = 89,
|
||||
GRF_BAUD_RATE = 91,
|
||||
GRF_I2C_ADDRESS = 92,
|
||||
GRF_ROLL_AVG_EN = 93,
|
||||
GRF_ROLL_AVG_SIZE = 94,
|
||||
GRF_SLEEP_COMMAND = 98,
|
||||
GRF_ZERO_OFFSET = 114
|
||||
};
|
||||
|
||||
// Store contents of rx'd frame
|
||||
struct {
|
||||
const uint8_t data_fields = 2; // useful for breaking crc's into byte separated fields
|
||||
uint16_t data_len{0}; // last message payload length (1+ bytes in payload)
|
||||
uint8_t data[GRF_MAX_PAYLOAD]; // payload size limited by posix serial
|
||||
uint8_t msg_id{0}; // latest message's message id
|
||||
uint8_t flags_lo{0}; // flags low byte
|
||||
uint8_t flags_hi{0}; // flags high byte
|
||||
uint16_t crc[GRF_CRC_FIELDS] = {0, 0};
|
||||
uint8_t crc_lo{0}; // crc low byte
|
||||
uint8_t crc_hi{0}; // crc high byte
|
||||
} rx_field;
|
||||
@@ -0,0 +1,633 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (c) 2026 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include "lightware_grf_serial.hpp"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <float.h>
|
||||
#include <inttypes.h>
|
||||
#include <termios.h>
|
||||
|
||||
#include <lib/crc/crc.h>
|
||||
|
||||
using namespace time_literals;
|
||||
|
||||
GRFLaserSerial::GRFLaserSerial(const char *port, uint8_t rotation) :
|
||||
ScheduledWorkItem(MODULE_NAME, px4::serial_port_to_wq(port)),
|
||||
_px4_rangefinder(0, rotation),
|
||||
_sample_perf(perf_alloc(PC_ELAPSED, MODULE_NAME": read")),
|
||||
_comms_errors(perf_alloc(PC_COUNT, MODULE_NAME": com_err"))
|
||||
{
|
||||
/* store port name */
|
||||
strncpy(_port, port, sizeof(_port) - 1);
|
||||
|
||||
/* enforce null termination */
|
||||
_port[sizeof(_port) - 1] = '\0';
|
||||
|
||||
device::Device::DeviceId device_id;
|
||||
device_id.devid_s.bus_type = device::Device::DeviceBusType_SERIAL;
|
||||
|
||||
uint8_t bus_num = atoi(&_port[strlen(_port) - 1]); // Assuming '/dev/ttySx'
|
||||
|
||||
if (bus_num < 10) {
|
||||
device_id.devid_s.bus = bus_num;
|
||||
}
|
||||
|
||||
_px4_rangefinder.set_device_id(device_id.devid);
|
||||
_px4_rangefinder.set_device_type(DRV_DIST_DEVTYPE_LIGHTWARE_LASER);
|
||||
|
||||
}
|
||||
|
||||
GRFLaserSerial::~GRFLaserSerial()
|
||||
{
|
||||
stop();
|
||||
|
||||
perf_free(_sample_perf);
|
||||
perf_free(_comms_errors);
|
||||
}
|
||||
|
||||
int GRFLaserSerial::init()
|
||||
{
|
||||
param_get(param_find("GRF_RATE_CFG"), &_update_rate);
|
||||
param_get(param_find("GRF_SENS_MODEL"), &_model_type);
|
||||
|
||||
start();
|
||||
return PX4_OK;
|
||||
}
|
||||
|
||||
int GRFLaserSerial::measure()
|
||||
{
|
||||
int32_t rate = (int32_t)_update_rate;
|
||||
_data_output = 0x01; // raw distance (last return)
|
||||
_stream_data = 5; // enable constant streaming
|
||||
|
||||
// send packets to the sensor depending on the state
|
||||
switch (_sensor_state) {
|
||||
|
||||
case STATE_UNINIT:
|
||||
// Used to probe if the sensor is alive
|
||||
grf_send(GRF_PRODUCT_NAME, false, &_product_name[0], 0);
|
||||
break;
|
||||
|
||||
case STATE_ACK_PRODUCT_NAME:
|
||||
// Update rate default to 5 readings/s
|
||||
grf_send(GRF_UPDATE_RATE, true, &rate, sizeof(uint8_t));
|
||||
ScheduleDelayed(100_ms);
|
||||
break;
|
||||
|
||||
case STATE_ACK_UPDATE_RATE:
|
||||
// Configure the data that the sensor shall output
|
||||
grf_send(GRF_DISTANCE_OUTPUT, true, &_data_output, sizeof(_data_output));
|
||||
break;
|
||||
|
||||
case STATE_ACK_DISTANCE_OUTPUT:
|
||||
// Configure the sensor to automatically output data at the configured update rate
|
||||
grf_send(GRF_STREAM, true, &_stream_data, sizeof(_stream_data));
|
||||
_sensor_state = STATE_SEND_STREAM;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return PX4_OK;
|
||||
}
|
||||
|
||||
int GRFLaserSerial::collect()
|
||||
{
|
||||
if (_sensor_state == STATE_UNINIT) {
|
||||
|
||||
perf_begin(_sample_perf);
|
||||
const int payload_length = 22;
|
||||
|
||||
_crc_valid = false;
|
||||
grf_get_and_handle_request(payload_length, GRF_PRODUCT_NAME);
|
||||
|
||||
if (_crc_valid) {
|
||||
_sensor_state = STATE_ACK_PRODUCT_NAME;
|
||||
perf_end(_sample_perf);
|
||||
return PX4_OK;
|
||||
}
|
||||
|
||||
perf_end(_sample_perf);
|
||||
return -EAGAIN;
|
||||
|
||||
} else if (_sensor_state == STATE_ACK_PRODUCT_NAME) {
|
||||
|
||||
perf_begin(_sample_perf);
|
||||
const int payload_length = 7;
|
||||
|
||||
_crc_valid = false;
|
||||
grf_get_and_handle_request(payload_length, GRF_UPDATE_RATE);
|
||||
|
||||
if (_crc_valid) {
|
||||
_sensor_state = STATE_ACK_UPDATE_RATE;
|
||||
perf_end(_sample_perf);
|
||||
return PX4_OK;
|
||||
}
|
||||
|
||||
perf_end(_sample_perf);
|
||||
return -EAGAIN;
|
||||
|
||||
} else if (_sensor_state == STATE_ACK_UPDATE_RATE) {
|
||||
|
||||
perf_begin(_sample_perf);
|
||||
const int payload_length = 10;
|
||||
|
||||
_crc_valid = false;
|
||||
grf_get_and_handle_request(payload_length, GRF_DISTANCE_OUTPUT);
|
||||
|
||||
if (_crc_valid) {
|
||||
_sensor_state = STATE_ACK_DISTANCE_OUTPUT;
|
||||
perf_end(_sample_perf);
|
||||
return PX4_OK;
|
||||
}
|
||||
|
||||
perf_end(_sample_perf);
|
||||
return -EAGAIN;
|
||||
|
||||
} else {
|
||||
|
||||
// Stream data from sensor
|
||||
perf_begin(_sample_perf);
|
||||
const int payload_length = 10;
|
||||
|
||||
_crc_valid = false;
|
||||
grf_get_and_handle_request(payload_length, GRF_DISTANCE_DATA_CM);
|
||||
|
||||
if (_crc_valid) {
|
||||
grf_process_replies();
|
||||
perf_end(_sample_perf);
|
||||
return PX4_OK;
|
||||
}
|
||||
|
||||
perf_end(_sample_perf);
|
||||
return -EAGAIN;
|
||||
}
|
||||
}
|
||||
|
||||
void GRFLaserSerial::start()
|
||||
{
|
||||
/* reset the sensor state */
|
||||
_sensor_state = STATE_UNINIT;
|
||||
|
||||
/* reset the report ring */
|
||||
_collect_phase = false;
|
||||
|
||||
/* reset the UART receive buffer size */
|
||||
_linebuf_size = 0;
|
||||
|
||||
/* reset the fail counter */
|
||||
_last_received_time = hrt_absolute_time();
|
||||
|
||||
/*Set Lidar Min/Max based on model*/
|
||||
switch (_model_type) {
|
||||
case GRF250: {
|
||||
_px4_rangefinder.set_min_distance(0.1f);
|
||||
_px4_rangefinder.set_max_distance(250.0f);
|
||||
break;
|
||||
}
|
||||
|
||||
case GRF500: {
|
||||
_px4_rangefinder.set_min_distance(0.1f);
|
||||
_px4_rangefinder.set_max_distance(500.0f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* schedule a cycle to start things */
|
||||
ScheduleNow();
|
||||
}
|
||||
|
||||
void GRFLaserSerial::stop()
|
||||
{
|
||||
ScheduleClear();
|
||||
}
|
||||
|
||||
void GRFLaserSerial::Run()
|
||||
{
|
||||
/* fds initialized? */
|
||||
if (_fd < 0) {
|
||||
/* open fd: non-blocking read mode*/
|
||||
_fd = ::open(_port, O_RDWR | O_NOCTTY | O_NONBLOCK);
|
||||
|
||||
if (_fd < 0) {
|
||||
PX4_ERR("serial open failed (%i)", errno);
|
||||
return;
|
||||
}
|
||||
|
||||
struct termios uart_config;
|
||||
|
||||
int termios_state;
|
||||
|
||||
/* fill the struct for the new configuration */
|
||||
tcgetattr(_fd, &uart_config);
|
||||
|
||||
/* clear ONLCR flag (which appends a CR for every LF) */
|
||||
uart_config.c_oflag &= ~ONLCR;
|
||||
|
||||
/* no parity, one stop bit */
|
||||
uart_config.c_cflag &= ~(CSTOPB | PARENB);
|
||||
|
||||
unsigned speed = B115200;
|
||||
|
||||
/* set baud rate */
|
||||
if ((termios_state = cfsetispeed(&uart_config, speed)) < 0) {
|
||||
PX4_ERR("CFG: %d ISPD", termios_state);
|
||||
}
|
||||
|
||||
if ((termios_state = cfsetospeed(&uart_config, speed)) < 0) {
|
||||
PX4_ERR("CFG: %d OSPD", termios_state);
|
||||
}
|
||||
|
||||
if ((termios_state = tcsetattr(_fd, TCSANOW, &uart_config)) < 0) {
|
||||
PX4_ERR("baud %d ATTR", termios_state);
|
||||
}
|
||||
}
|
||||
|
||||
if (_collect_phase) {
|
||||
if (hrt_absolute_time() - _last_received_time >= 1_s) {
|
||||
start();
|
||||
return;
|
||||
}
|
||||
|
||||
/* perform collection */
|
||||
if (collect() != PX4_OK && errno != EAGAIN) {
|
||||
PX4_DEBUG("collect error");
|
||||
}
|
||||
|
||||
if (_sensor_state != STATE_SEND_STREAM) {
|
||||
/* next phase is measurement */
|
||||
_collect_phase = false;
|
||||
}
|
||||
|
||||
} else {
|
||||
/* measurement phase */
|
||||
|
||||
if (measure() != PX4_OK) {
|
||||
PX4_DEBUG("measure error");
|
||||
}
|
||||
|
||||
/* next phase is collection */
|
||||
_collect_phase = true;
|
||||
}
|
||||
|
||||
/* schedule a fresh cycle call when the measurement is done */
|
||||
ScheduleDelayed(_interval);
|
||||
}
|
||||
|
||||
void GRFLaserSerial::print_info()
|
||||
{
|
||||
perf_print_counter(_sample_perf);
|
||||
perf_print_counter(_comms_errors);
|
||||
}
|
||||
|
||||
void GRFLaserSerial::grf_get_and_handle_request(const int payload_length, const GRF_SERIAL_CMD msg_id)
|
||||
{
|
||||
// GRF protocol
|
||||
// Start byte is 0xAA and is the start of packet
|
||||
// Payload length sanity check (0-1023) bytes
|
||||
// and represented by 16-bit integer (payload +
|
||||
// read/write status)
|
||||
// ID byte precedes the data in the payload
|
||||
// CRC comprised of 16-bit checksum (not included in checksum calc.)
|
||||
|
||||
int ret;
|
||||
size_t max_read = sizeof(_linebuf) - _linebuf_size;
|
||||
ret = ::read(_fd, &_linebuf[_linebuf_size], max_read);
|
||||
|
||||
if (ret < 0 && errno != EAGAIN) {
|
||||
PX4_ERR("ERROR (ack from streaming distance data): %d", ret);
|
||||
_linebuf_size = 0;
|
||||
perf_count(_comms_errors);
|
||||
perf_end(_sample_perf);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ret > 0) {
|
||||
_last_received_time = hrt_absolute_time();
|
||||
_linebuf_size += ret;
|
||||
}
|
||||
|
||||
// Not enough data to parse a complete packet. Gather more data in the next cycle.
|
||||
if (_linebuf_size < payload_length) {
|
||||
return;
|
||||
}
|
||||
|
||||
int index = 0;
|
||||
|
||||
while (index <= _linebuf_size - payload_length && _crc_valid == false) {
|
||||
bool restart_flag = false;
|
||||
|
||||
while (restart_flag != true) {
|
||||
switch (_parsed_state) {
|
||||
case GRF_PARSED_STATE::START: {
|
||||
if (_linebuf[index] == 0xAA) {
|
||||
// start of frame is valid, continue
|
||||
_calc_crc = grf_format_crc(_calc_crc, _start_of_frame);
|
||||
_parsed_state = GRF_PARSED_STATE::FLG_LOW;
|
||||
break;
|
||||
|
||||
} else {
|
||||
_crc_valid = false;
|
||||
_parsed_state = GRF_PARSED_STATE::START;
|
||||
restart_flag = true;
|
||||
_calc_crc = 0;
|
||||
PX4_DEBUG("Start of packet not valid: %d", _sensor_state);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
case GRF_PARSED_STATE::FLG_LOW: {
|
||||
rx_field.flags_lo = _linebuf[index + 1];
|
||||
_calc_crc = grf_format_crc(_calc_crc, rx_field.flags_lo);
|
||||
_parsed_state = GRF_PARSED_STATE::FLG_HIGH;
|
||||
break;
|
||||
}
|
||||
|
||||
case GRF_PARSED_STATE::FLG_HIGH: {
|
||||
rx_field.flags_hi = _linebuf[index + 2];
|
||||
rx_field.data_len = (rx_field.flags_hi << 2) | (rx_field.flags_lo >> 6);
|
||||
_calc_crc = grf_format_crc(_calc_crc, rx_field.flags_hi);
|
||||
|
||||
// Check payload length against known max value
|
||||
if (rx_field.data_len > 17) {
|
||||
_parsed_state = GRF_PARSED_STATE::START;
|
||||
restart_flag = true;
|
||||
_calc_crc = 0;
|
||||
PX4_DEBUG("Payload length error: %d", _sensor_state);
|
||||
break;
|
||||
|
||||
} else {
|
||||
_parsed_state = GRF_PARSED_STATE::ID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
case GRF_PARSED_STATE::ID: {
|
||||
rx_field.msg_id = _linebuf[index + 3];
|
||||
|
||||
if (rx_field.msg_id == msg_id) {
|
||||
_calc_crc = grf_format_crc(_calc_crc, rx_field.msg_id);
|
||||
_parsed_state = GRF_PARSED_STATE::DATA;
|
||||
break;
|
||||
}
|
||||
|
||||
// Ignore message ID's that aren't searched
|
||||
else {
|
||||
_parsed_state = GRF_PARSED_STATE::START;
|
||||
_calc_crc = 0;
|
||||
restart_flag = true;
|
||||
PX4_DEBUG("Non needed message ID: %d", _sensor_state);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
case GRF_PARSED_STATE::DATA: {
|
||||
// Process commands with & w/out data bytes
|
||||
if (rx_field.data_len > 1) {
|
||||
for (uint8_t i = 4; i < 3 + rx_field.data_len; ++i) {
|
||||
|
||||
rx_field.data[_data_bytes_recv] = _linebuf[index + i];
|
||||
_calc_crc = grf_format_crc(_calc_crc, rx_field.data[_data_bytes_recv]);
|
||||
_data_bytes_recv = _data_bytes_recv + 1;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
|
||||
_parsed_state = GRF_PARSED_STATE::CRC_LOW;
|
||||
_data_bytes_recv = 0;
|
||||
_calc_crc = grf_format_crc(_calc_crc, _data_bytes_recv);
|
||||
}
|
||||
|
||||
_parsed_state = GRF_PARSED_STATE::CRC_LOW;
|
||||
_data_bytes_recv = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case GRF_PARSED_STATE::CRC_LOW: {
|
||||
rx_field.crc[0] = _linebuf[index + 3 + rx_field.data_len];
|
||||
_parsed_state = GRF_PARSED_STATE::CRC_HIGH;
|
||||
break;
|
||||
}
|
||||
|
||||
case GRF_PARSED_STATE::CRC_HIGH: {
|
||||
rx_field.crc[1] = _linebuf[index + 4 + rx_field.data_len];
|
||||
uint16_t recv_crc = (rx_field.crc[1] << 8) | rx_field.crc[0];
|
||||
|
||||
// Check the received crc bytes from the grf against our own CRC calcuation
|
||||
// If it matches, we can check if sensor ready
|
||||
// Only if crc match is valid and sensor ready (transmitting distance data) do we flag _init_complete
|
||||
if (recv_crc == _calc_crc) {
|
||||
_crc_valid = true;
|
||||
_parsed_state = GRF_PARSED_STATE::START;
|
||||
_calc_crc = 0;
|
||||
restart_flag = true;
|
||||
break;
|
||||
|
||||
} else {
|
||||
|
||||
_crc_valid = false;
|
||||
_parsed_state = GRF_PARSED_STATE::START;
|
||||
_calc_crc = 0;
|
||||
restart_flag = true;
|
||||
perf_count(_comms_errors);
|
||||
PX4_DEBUG("CRC mismatch: %d", _sensor_state);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
// If we parsed successfully, remove the parsed part from the buffer if it is still large enough
|
||||
if (_crc_valid && index + payload_length < _linebuf_size) {
|
||||
unsigned next_after_index = index + payload_length;
|
||||
memmove(&_linebuf[0], &_linebuf[next_after_index], _linebuf_size - next_after_index);
|
||||
_linebuf_size -= next_after_index;
|
||||
}
|
||||
|
||||
// The buffer is filled. Either we can't keep up with the stream and/or it contains only invalid data. Reset to try again.
|
||||
if ((unsigned)_linebuf_size >= sizeof(_linebuf)) {
|
||||
_linebuf_size = 0;
|
||||
perf_count(_comms_errors);
|
||||
}
|
||||
}
|
||||
|
||||
void GRFLaserSerial::grf_send(uint8_t msg_id, bool write, int32_t *data, uint8_t data_len)
|
||||
{
|
||||
uint16_t crc_val = 0;
|
||||
uint8_t packet_buff[GRF_MAX_PAYLOAD];
|
||||
uint8_t data_inc = 4;
|
||||
int ret = 0;
|
||||
uint8_t packet_len = 0;
|
||||
// Include payload ID byte in payload len
|
||||
uint16_t flags = (data_len + 1) << 6;
|
||||
|
||||
// If writing to the device, lsb is 1
|
||||
if (write) {
|
||||
flags |= 0x01;
|
||||
}
|
||||
|
||||
else {
|
||||
flags |= 0x0;
|
||||
}
|
||||
|
||||
uint8_t flags_lo = flags & 0xFF;
|
||||
uint8_t flags_hi = (flags >> 8) & 0xFF;
|
||||
|
||||
// Add packet bytes to format into crc based on CRC-16-CCITT 0x1021/XMODEM
|
||||
crc_val = grf_format_crc(crc_val, _start_of_frame);
|
||||
crc_val = grf_format_crc(crc_val, flags_lo);
|
||||
crc_val = grf_format_crc(crc_val, flags_hi);
|
||||
crc_val = grf_format_crc(crc_val, msg_id);
|
||||
|
||||
// Write the packet header contents + payload msg ID to the output buffer
|
||||
packet_buff[0] = _start_of_frame;
|
||||
packet_buff[1] = flags_lo;
|
||||
packet_buff[2] = flags_hi;
|
||||
packet_buff[3] = msg_id;
|
||||
|
||||
if (msg_id == GRF_DISTANCE_OUTPUT) {
|
||||
uint8_t data_convert = data[0] & 0x00FF;
|
||||
// write data bytes to the output buffer
|
||||
packet_buff[data_inc] = data_convert;
|
||||
// Add data bytes to crc add function
|
||||
crc_val = grf_format_crc(crc_val, data_convert);
|
||||
data_inc = data_inc + 1;
|
||||
data_convert = data[0] >> 8;
|
||||
packet_buff[data_inc] = data_convert;
|
||||
crc_val = grf_format_crc(crc_val, data_convert);
|
||||
data_inc = data_inc + 1;
|
||||
packet_buff[data_inc] = 0;
|
||||
crc_val = grf_format_crc(crc_val, packet_buff[data_inc]);
|
||||
data_inc = data_inc + 1;
|
||||
packet_buff[data_inc] = 0;
|
||||
crc_val = grf_format_crc(crc_val, packet_buff[data_inc]);
|
||||
data_inc = data_inc + 1;
|
||||
}
|
||||
|
||||
else if (msg_id == GRF_STREAM) {
|
||||
packet_buff[data_inc] = data[0];
|
||||
//pad zeroes
|
||||
crc_val = grf_format_crc(crc_val, data[0]);
|
||||
data_inc = data_inc + 1;
|
||||
packet_buff[data_inc] = 0;
|
||||
crc_val = grf_format_crc(crc_val, packet_buff[data_inc]);
|
||||
data_inc = data_inc + 1;
|
||||
packet_buff[data_inc] = 0;
|
||||
crc_val = grf_format_crc(crc_val, packet_buff[data_inc]);
|
||||
data_inc = data_inc + 1;
|
||||
packet_buff[data_inc] = 0;
|
||||
crc_val = grf_format_crc(crc_val, packet_buff[data_inc]);
|
||||
data_inc = data_inc + 1;
|
||||
}
|
||||
|
||||
else if (msg_id == GRF_UPDATE_RATE) {
|
||||
// Update Rate
|
||||
packet_buff[data_inc] = (uint8_t)data[0];
|
||||
// Add data bytes to crc add function
|
||||
crc_val = grf_format_crc(crc_val, data[0]);
|
||||
data_inc = data_inc + 1;
|
||||
}
|
||||
|
||||
else {
|
||||
// Product Name
|
||||
PX4_DEBUG("DEBUG: Product name");
|
||||
}
|
||||
|
||||
uint8_t crc_lo = crc_val & 0xFF;
|
||||
uint8_t crc_hi = (crc_val >> 8) & 0xFF;
|
||||
|
||||
packet_buff[data_inc] = crc_lo;
|
||||
data_inc = data_inc + 1;
|
||||
packet_buff[data_inc] = crc_hi;
|
||||
|
||||
size_t len = sizeof(packet_buff[0]) * (data_inc + 1);
|
||||
packet_len = (uint8_t)len;
|
||||
|
||||
// DEBUG
|
||||
for (uint8_t i = 0; i < packet_len; ++i) {
|
||||
PX4_DEBUG("DEBUG: Send byte: %d", packet_buff[i]);
|
||||
}
|
||||
|
||||
ret = ::write(_fd, packet_buff, packet_len);
|
||||
|
||||
if (ret != packet_len) {
|
||||
perf_count(_comms_errors);
|
||||
PX4_ERR("serial write fail %d", ret);
|
||||
// Flush data written, not transmitted
|
||||
tcflush(_fd, TCOFLUSH);
|
||||
}
|
||||
}
|
||||
|
||||
void GRFLaserSerial::grf_process_replies()
|
||||
{
|
||||
float distance_m = -1.0f;
|
||||
hrt_abstime now = hrt_absolute_time();
|
||||
|
||||
switch (rx_field.msg_id) {
|
||||
case GRF_DISTANCE_DATA_CM: {
|
||||
const float raw_distance = (rx_field.data[0] << 0) | (rx_field.data[1] << 8) | (rx_field.data[2] << 16);
|
||||
distance_m = raw_distance * GRF_SCALE_FACTOR;
|
||||
_px4_rangefinder.update(now, distance_m);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
// add case for future use
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t GRFLaserSerial::grf_format_crc(uint16_t crc, uint8_t data_val)
|
||||
{
|
||||
uint32_t i;
|
||||
const uint16_t poly = 0x1021u;
|
||||
crc ^= (uint16_t)((uint16_t) data_val << 8u);
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (crc & (1u << 15u)) {
|
||||
crc = (uint16_t)((crc << 1u) ^ poly);
|
||||
|
||||
} else {
|
||||
crc = (uint16_t)(crc << 1u);
|
||||
}
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2026 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file lightware_grf_serial.hpp
|
||||
* @author Aaron Porter <aaron.porter@ascendengineer.com>
|
||||
*
|
||||
* Serial Protocol driver for the Lightware GRF rangefinder series
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <px4_platform_common/px4_config.h>
|
||||
#include <px4_platform_common/px4_work_queue/ScheduledWorkItem.hpp>
|
||||
#include <lib/drivers/rangefinder/PX4Rangefinder.hpp>
|
||||
#include <drivers/drv_hrt.h>
|
||||
#include <drivers/device/device.h>
|
||||
#include <lib/parameters/param.h>
|
||||
#include <lib/perf/perf_counter.h>
|
||||
|
||||
#include <uORB/Publication.hpp>
|
||||
#include <uORB/topics/distance_sensor.h>
|
||||
|
||||
#include "grf_commands.h"
|
||||
|
||||
enum GRF_SERIAL_STATE {
|
||||
STATE_UNINIT = 0,
|
||||
STATE_ACK_PRODUCT_NAME = 1,
|
||||
STATE_ACK_UPDATE_RATE = 2,
|
||||
STATE_ACK_DISTANCE_OUTPUT = 3,
|
||||
STATE_SEND_STREAM = 4,
|
||||
};
|
||||
|
||||
enum GRF_PARSED_STATE {
|
||||
START = 0,
|
||||
FLG_LOW,
|
||||
FLG_HIGH,
|
||||
ID,
|
||||
DATA,
|
||||
CRC_LOW,
|
||||
CRC_HIGH
|
||||
};
|
||||
|
||||
enum MODEL {
|
||||
Disable = 0,
|
||||
GRF250 = 1,
|
||||
GRF500 = 2
|
||||
};
|
||||
|
||||
using namespace time_literals;
|
||||
class GRFLaserSerial : public px4::ScheduledWorkItem
|
||||
{
|
||||
public:
|
||||
GRFLaserSerial(const char *port, uint8_t rotation = distance_sensor_s::ROTATION_DOWNWARD_FACING);
|
||||
~GRFLaserSerial() override;
|
||||
|
||||
int init();
|
||||
void print_info();
|
||||
void grf_get_and_handle_request(const int payload_length, const GRF_SERIAL_CMD msg_id);
|
||||
void grf_send(uint8_t msg_id, bool r_w, int32_t *data, uint8_t data_len);
|
||||
uint16_t grf_format_crc(uint16_t crc, uint8_t data_value);
|
||||
void grf_process_replies();
|
||||
|
||||
private:
|
||||
|
||||
distance_sensor_s _distance{};
|
||||
static constexpr uint64_t GRF_MEAS_TIMEOUT{100_ms};
|
||||
static constexpr float GRF_SCALE_FACTOR = 0.1f;
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
void Run() override;
|
||||
int measure();
|
||||
int collect();
|
||||
bool _crc_valid{false};
|
||||
|
||||
PX4Rangefinder _px4_rangefinder;
|
||||
char _port[20] {};
|
||||
int _interval{200000};
|
||||
bool _collect_phase{false};
|
||||
int _fd{-1};
|
||||
uint8_t _linebuf[GRF_MAX_PAYLOAD] {};
|
||||
int _linebuf_size{0};
|
||||
|
||||
// GRF uses a binary protocol to include header,flags
|
||||
// message ID, payload, and checksum
|
||||
GRF_SERIAL_STATE _sensor_state{STATE_UNINIT};
|
||||
int _baud_rate{0};
|
||||
int32_t _product_name[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
int32_t _stream_data{0};
|
||||
int32_t _update_rate{0};
|
||||
int32_t _model_type{0};
|
||||
int32_t _data_output{0};
|
||||
const uint8_t _start_of_frame{0xAA};
|
||||
uint16_t _data_bytes_recv{0};
|
||||
uint8_t _parsed_state{0};
|
||||
uint16_t _calc_crc{0};
|
||||
|
||||
// end of GRF data members
|
||||
|
||||
hrt_abstime _last_received_time{0};
|
||||
perf_counter_t _sample_perf;
|
||||
perf_counter_t _comms_errors;
|
||||
};
|
||||
+167
@@ -0,0 +1,167 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2026 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include "lightware_grf_serial.hpp"
|
||||
|
||||
#include <px4_platform_common/getopt.h>
|
||||
#include <px4_platform_common/module.h>
|
||||
|
||||
namespace lightware_grf
|
||||
{
|
||||
|
||||
GRFLaserSerial *g_dev{nullptr};
|
||||
|
||||
static int start(const char *port)
|
||||
{
|
||||
if (g_dev != nullptr) {
|
||||
PX4_WARN("already started");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (port == nullptr) {
|
||||
PX4_ERR("no device specified");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* create the driver */
|
||||
g_dev = new GRFLaserSerial(port);
|
||||
|
||||
if (g_dev == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (g_dev->init() != PX4_OK) {
|
||||
delete g_dev;
|
||||
g_dev = nullptr;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stop()
|
||||
{
|
||||
if (g_dev != nullptr) {
|
||||
delete g_dev;
|
||||
g_dev = nullptr;
|
||||
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int status()
|
||||
{
|
||||
if (g_dev == nullptr) {
|
||||
PX4_ERR("driver not running");
|
||||
return -1;
|
||||
}
|
||||
|
||||
g_dev->print_info();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usage()
|
||||
{
|
||||
PRINT_MODULE_DESCRIPTION(
|
||||
R"DESCR_STR(
|
||||
### Description
|
||||
|
||||
Serial bus driver for the Lightware GRF Laser rangefinder.
|
||||
|
||||
### Configuration
|
||||
https://docs.px4.io/main/en/sensor/grf_lidar
|
||||
|
||||
### Parameters
|
||||
https://docs.px4.io/main/en/advanced_config/parameter_reference#GRF_SENS_MODEL
|
||||
https://docs.px4.io/main/en/advanced_config/parameter_reference#GRF_RATE_CFG
|
||||
https://docs.px4.io/main/en/advanced_config/parameter_reference#SENS_EN_GRF_CFG
|
||||
|
||||
### Examples
|
||||
|
||||
Attempt to start driver on a specified serial device.
|
||||
$ lightware_grf_serial start -d /dev/ttyS1
|
||||
Stop driver
|
||||
$ lightware_grf_serial stop
|
||||
)DESCR_STR");
|
||||
|
||||
PRINT_MODULE_USAGE_NAME("lightware_grf_serial", "driver");
|
||||
PRINT_MODULE_USAGE_SUBCATEGORY("distance_sensor");
|
||||
PRINT_MODULE_USAGE_COMMAND_DESCR("start", "Start driver");
|
||||
PRINT_MODULE_USAGE_PARAM_STRING('d', nullptr, nullptr, "Serial device", false);
|
||||
PRINT_MODULE_USAGE_COMMAND_DESCR("stop", "Stop driver");
|
||||
return PX4_OK;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
extern "C" __EXPORT int lightware_grf_serial_main(int argc, char *argv[])
|
||||
{
|
||||
const char *device_path = nullptr;
|
||||
int ch;
|
||||
int myoptind = 1;
|
||||
const char *myoptarg = nullptr;
|
||||
|
||||
while ((ch = px4_getopt(argc, argv, "d:", &myoptind, &myoptarg)) != EOF) {
|
||||
switch (ch) {
|
||||
case 'd':
|
||||
device_path = myoptarg;
|
||||
break;
|
||||
|
||||
default:
|
||||
lightware_grf::usage();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (myoptind >= argc) {
|
||||
lightware_grf::usage();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!strcmp(argv[myoptind], "start")) {
|
||||
return lightware_grf::start(device_path);
|
||||
|
||||
} else if (!strcmp(argv[myoptind], "stop")) {
|
||||
return lightware_grf::stop();
|
||||
|
||||
} else if (!strcmp(argv[myoptind], "status")) {
|
||||
return lightware_grf::status();
|
||||
}
|
||||
|
||||
lightware_grf::usage();
|
||||
return -1;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
module_name: Lightware GRF Rangefinder (serial)
|
||||
serial_config:
|
||||
- command: lightware_grf_serial start -d ${SERIAL_DEV}
|
||||
port_config_param:
|
||||
name: SENS_EN_GRF_CFG
|
||||
group: Sensors
|
||||
num_instances: 1
|
||||
supports_networking: false
|
||||
|
||||
parameters:
|
||||
- group: Sensors
|
||||
definitions:
|
||||
GRF_RATE_CFG:
|
||||
description:
|
||||
short: Lightware GRF lidar update rate.
|
||||
long: |
|
||||
The Lightware GRF distance sensor can increase the update rate to enable greater resolution.
|
||||
type: enum
|
||||
values:
|
||||
1: 1 Hz
|
||||
2: 2 Hz
|
||||
3: 4 Hz
|
||||
4: 5 Hz
|
||||
5: 10 Hz
|
||||
6: 20 Hz
|
||||
7: 30 Hz
|
||||
8: 40 Hz
|
||||
9: 50 Hz
|
||||
reboot_required: true
|
||||
num_instances: 1
|
||||
default: 4
|
||||
GRF_SENS_MODEL:
|
||||
description:
|
||||
short: GRF Sensor model
|
||||
long: |
|
||||
GRF Sensor Model used to distinush between the GRF250 and GRF500 since both have different max distance range.
|
||||
type: enum
|
||||
values:
|
||||
0: disable
|
||||
1: GRF250
|
||||
2: GRF500
|
||||
reboot_required: true
|
||||
num_instances: 1
|
||||
default: 0
|
||||
@@ -162,7 +162,8 @@ private:
|
||||
|
||||
DEFINE_PARAMETERS(
|
||||
(ParamInt<px4::params::SENS_EN_SF1XX>) _param_sens_en_sf1xx,
|
||||
(ParamInt<px4::params::SF1XX_MODE>) _param_sf1xx_mode
|
||||
(ParamInt<px4::params::SF1XX_MODE>) _param_sf1xx_mode,
|
||||
(ParamInt<px4::params::SF1XX_ROT>) _param_sf1xx_rot
|
||||
)
|
||||
uORB::Subscription _parameter_update_sub{ORB_ID(parameter_update)};
|
||||
uORB::Subscription _vehicle_status_sub{ORB_ID(vehicle_status)};
|
||||
@@ -178,7 +179,7 @@ LightwareLaser::LightwareLaser(const I2CSPIDriverConfig &config) :
|
||||
I2C(config),
|
||||
I2CSPIDriver(config),
|
||||
ModuleParams(nullptr),
|
||||
_px4_rangefinder(get_device_id(), config.rotation)
|
||||
_px4_rangefinder(get_device_id())
|
||||
{
|
||||
_px4_rangefinder.set_device_type(DRV_DIST_DEVTYPE_LIGHTWARE_LASER);
|
||||
}
|
||||
@@ -194,6 +195,9 @@ int LightwareLaser::init()
|
||||
{
|
||||
int ret = PX4_ERROR;
|
||||
updateParams();
|
||||
|
||||
_px4_rangefinder.set_orientation(_param_sf1xx_rot.get());
|
||||
|
||||
const int32_t hw_model = _param_sens_en_sf1xx.get();
|
||||
|
||||
switch (hw_model) {
|
||||
@@ -630,7 +634,7 @@ void LightwareLaser::print_usage()
|
||||
R"DESCR_STR(
|
||||
### Description
|
||||
|
||||
I2C bus driver for Lightware SFxx series LIDAR rangefinders: SF10/a, SF10/b, SF10/c, SF11/c, SF/LW20, SF30/d.
|
||||
I2C bus driver for Lightware LIDAR rangefinders: SF10/a, SF10/b, SF10/c, SF11/c, SF/LW20, SF/LW30/d, GRF250, GRF500.
|
||||
|
||||
Setup/usage information: https://docs.px4.io/main/en/sensor/sfxx_lidar.html
|
||||
)DESCR_STR");
|
||||
@@ -640,28 +644,17 @@ Setup/usage information: https://docs.px4.io/main/en/sensor/sfxx_lidar.html
|
||||
PRINT_MODULE_USAGE_COMMAND("start");
|
||||
PRINT_MODULE_USAGE_PARAMS_I2C_SPI_DRIVER(true, false);
|
||||
PRINT_MODULE_USAGE_PARAMS_I2C_ADDRESS(0x66);
|
||||
PRINT_MODULE_USAGE_PARAM_INT('R', 25, 0, 25, "Sensor rotation - downward facing by default", true);
|
||||
PRINT_MODULE_USAGE_DEFAULT_COMMANDS();
|
||||
}
|
||||
|
||||
extern "C" __EXPORT int lightware_laser_i2c_main(int argc, char *argv[])
|
||||
{
|
||||
int ch;
|
||||
using ThisDriver = LightwareLaser;
|
||||
BusCLIArguments cli{true, false};
|
||||
cli.rotation = (Rotation)distance_sensor_s::ROTATION_DOWNWARD_FACING;
|
||||
cli.default_i2c_frequency = 400000;
|
||||
cli.i2c_address = LIGHTWARE_LASER_BASEADDR;
|
||||
|
||||
while ((ch = cli.getOpt(argc, argv, "R:")) != EOF) {
|
||||
switch (ch) {
|
||||
case 'R':
|
||||
cli.rotation = (Rotation)atoi(cli.optArg());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const char *verb = cli.optArg();
|
||||
const char *verb = cli.parseDefaultArguments(argc, argv);
|
||||
|
||||
if (!verb) {
|
||||
ThisDriver::print_usage();
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* Lightware SF1xx/SF20/LW20 laser rangefinder (i2c)
|
||||
* Lightware laser rangefinder (i2c)
|
||||
*
|
||||
* @reboot_required true
|
||||
* @min 0
|
||||
@@ -52,7 +52,7 @@
|
||||
PARAM_DEFINE_INT32(SENS_EN_SF1XX, 0);
|
||||
|
||||
/**
|
||||
* Lightware SF1xx/SF20/LW20 Operation Mode
|
||||
* Lightware laser rangefinder Operation Mode
|
||||
*
|
||||
* @value 0 Disabled
|
||||
* @value 1 Enabled
|
||||
@@ -62,3 +62,22 @@ PARAM_DEFINE_INT32(SENS_EN_SF1XX, 0);
|
||||
* @max 2
|
||||
*/
|
||||
PARAM_DEFINE_INT32(SF1XX_MODE, 1);
|
||||
|
||||
/**
|
||||
* Lightware laser rangefinder Rotation
|
||||
*
|
||||
* Distance sensor orientation as MAV_SENSOR_ORIENTATION enum.
|
||||
* Applies to all models supported by SENS_EN_SF1XX.
|
||||
*
|
||||
* @reboot_required true
|
||||
* @min 0
|
||||
* @max 25
|
||||
* @group Sensors
|
||||
* @value 0 Forward
|
||||
* @value 2 Right
|
||||
* @value 4 Backward
|
||||
* @value 6 Left
|
||||
* @value 24 Upward
|
||||
* @value 25 Downward
|
||||
*/
|
||||
PARAM_DEFINE_INT32(SF1XX_ROT, 25);
|
||||
|
||||
@@ -318,9 +318,13 @@ GPS::GPS(const char *path, gps_driver_mode_t mode, GPSHelper::Interface interfac
|
||||
_instance(instance)
|
||||
{
|
||||
/* store port name */
|
||||
strncpy(_port, path, sizeof(_port) - 1);
|
||||
/* enforce null termination */
|
||||
_port[sizeof(_port) - 1] = '\0';
|
||||
if (path != nullptr) {
|
||||
strncpy(_port, path, sizeof(_port) - 1);
|
||||
_port[sizeof(_port) - 1] = '\0';
|
||||
|
||||
} else {
|
||||
_port[0] = '\0';
|
||||
}
|
||||
|
||||
_sensor_gps.heading = NAN;
|
||||
_sensor_gps.heading_offset = NAN;
|
||||
|
||||
@@ -89,7 +89,7 @@ UavcanEscController::update_outputs(uint16_t outputs[MAX_ACTUATORS], uint8_t out
|
||||
|
||||
_prev_cmd_pub = timestamp;
|
||||
|
||||
uavcan::equipment::esc::RawCommand msg = {};
|
||||
uavcan::equipment::esc::RawCommand msg{};
|
||||
|
||||
for (unsigned i = 0; i < output_array_size; i++) {
|
||||
msg.cmd.push_back(static_cast<int>(outputs[i]));
|
||||
|
||||
@@ -97,7 +97,7 @@ private:
|
||||
typedef uavcan::MethodBinder<UavcanEscController *,
|
||||
void (UavcanEscController::*)(const uavcan::TimerEvent &)> TimerCbBinder;
|
||||
|
||||
bool _initialized{};
|
||||
bool _initialized = false;
|
||||
|
||||
esc_status_s _esc_status{};
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
__max_num_uavcan_lights: &max_num_uavcan_lights 3 # Needs to be equal to MAX_NUM_UAVCAN_LIGHTS constant
|
||||
|
||||
module_name: UAVCAN
|
||||
parameters:
|
||||
- group: UAVCAN
|
||||
@@ -24,6 +26,46 @@ parameters:
|
||||
min: 1
|
||||
max: 255
|
||||
reboot_required: true
|
||||
UAVCAN_LGT_NUM:
|
||||
description:
|
||||
short: Number of UAVCAN lights to configure
|
||||
long: |
|
||||
Number of lights to control via UAVCAN LightsCommand messages.
|
||||
Set to 0 to disable UAVCAN light control.
|
||||
Each light uses two parameters: LGT_IDx for the light_id and LGT_FNx for the function.
|
||||
type: int32
|
||||
min: 0
|
||||
max: *max_num_uavcan_lights
|
||||
default: 1
|
||||
reboot_required: true
|
||||
UAVCAN_LGT_ID${i}:
|
||||
description:
|
||||
short: Light ${i} ID
|
||||
long: |
|
||||
specifies the light_id value for light ${i} in UAVCAN LightsCommand messages.
|
||||
This determines which physical LED responds to commands for this light slot.
|
||||
type: int32
|
||||
num_instances: *max_num_uavcan_lights
|
||||
instance_start: 0
|
||||
min: 0
|
||||
max: 255
|
||||
default: 0
|
||||
UAVCAN_LGT_FN${i}:
|
||||
description:
|
||||
short: Light ${i} function
|
||||
long: |
|
||||
Function assigned to light ${i}.
|
||||
0: Status - displays system status colors
|
||||
1: Anti-collision - white beacon controlled by LGT_ANTCL parameter
|
||||
type: enum
|
||||
num_instances: *max_num_uavcan_lights
|
||||
instance_start: 0
|
||||
min: 0
|
||||
max: 1
|
||||
default: 0
|
||||
values:
|
||||
0: Status Light
|
||||
1: Anti-collision Light
|
||||
actuator_output:
|
||||
show_subgroups_if: 'UAVCAN_ENABLE>=3'
|
||||
config_parameters:
|
||||
|
||||
+119
-120
@@ -32,6 +32,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include "rgbled.hpp"
|
||||
#include <lib/mathlib/mathlib.h>
|
||||
|
||||
UavcanRGBController::UavcanRGBController(uavcan::INode &node) :
|
||||
ModuleParams(nullptr),
|
||||
@@ -44,6 +45,38 @@ UavcanRGBController::UavcanRGBController(uavcan::INode &node) :
|
||||
|
||||
int UavcanRGBController::init()
|
||||
{
|
||||
// Cache number of lights (0 disables the feature)
|
||||
_num_lights = math::min(static_cast<uint8_t>(_param_lgt_num.get()), MAX_NUM_UAVCAN_LIGHTS);
|
||||
|
||||
if (_num_lights == 0) {
|
||||
return 0; // Disabled, don't start timer
|
||||
}
|
||||
|
||||
// Cache parameter handles and values for each light
|
||||
for (uint8_t i = 0; i < _num_lights; i++) {
|
||||
char param_name[17];
|
||||
|
||||
// Light ID parameter
|
||||
snprintf(param_name, sizeof(param_name), "UAVCAN_LGT_ID%u", i);
|
||||
_light_id_params[i] = param_find(param_name);
|
||||
|
||||
if (_light_id_params[i] != PARAM_INVALID) {
|
||||
int32_t light_id = 0;
|
||||
param_get(_light_id_params[i], &light_id);
|
||||
_light_ids[i] = static_cast<uint8_t>(light_id);
|
||||
}
|
||||
|
||||
// Light function parameter
|
||||
snprintf(param_name, sizeof(param_name), "UAVCAN_LGT_FN%u", i);
|
||||
_light_fn_params[i] = param_find(param_name);
|
||||
|
||||
if (_light_fn_params[i] != PARAM_INVALID) {
|
||||
int32_t light_fn = 0;
|
||||
param_get(_light_fn_params[i], &light_fn);
|
||||
_light_functions[i] = static_cast<LightFunction>(light_fn);
|
||||
}
|
||||
}
|
||||
|
||||
// Setup timer and call back function for periodic updates
|
||||
_timer.setCallback(TimerCbBinder(this, &UavcanRGBController::periodic_update));
|
||||
_timer.startPeriodic(uavcan::MonotonicDuration::fromMSec(1000 / MAX_RATE_HZ));
|
||||
@@ -52,142 +85,108 @@ int UavcanRGBController::init()
|
||||
|
||||
void UavcanRGBController::periodic_update(const uavcan::TimerEvent &)
|
||||
{
|
||||
bool publish_lights = false;
|
||||
uavcan::equipment::indication::LightsCommand cmds;
|
||||
// Early return if disabled or no lights configured
|
||||
if (_num_lights == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for status color updates from led_controller
|
||||
LedControlData led_control_data;
|
||||
|
||||
if (_led_controller.update(led_control_data) == 1) {
|
||||
publish_lights = true;
|
||||
if (_led_controller.update(led_control_data) != 1) {
|
||||
return; // No update, nothing to do
|
||||
}
|
||||
|
||||
// RGB color in the standard 5-6-5 16-bit palette.
|
||||
// Monocolor lights should interpret this as brightness setpoint: from zero (0, 0, 0) to full brightness (31, 63, 31).
|
||||
// Compute status color from led_control_data
|
||||
uavcan::equipment::indication::RGB565 status_color{};
|
||||
uint8_t brightness = led_control_data.leds[0].brightness;
|
||||
|
||||
switch (led_control_data.leds[0].color) {
|
||||
case led_control_s::COLOR_RED:
|
||||
status_color = rgb888_to_rgb565(brightness, 0, 0);
|
||||
break;
|
||||
|
||||
case led_control_s::COLOR_GREEN:
|
||||
status_color = rgb888_to_rgb565(0, brightness, 0);
|
||||
break;
|
||||
|
||||
case led_control_s::COLOR_BLUE:
|
||||
status_color = rgb888_to_rgb565(0, 0, brightness);
|
||||
break;
|
||||
|
||||
case led_control_s::COLOR_AMBER: // make it the same as yellow
|
||||
case led_control_s::COLOR_YELLOW:
|
||||
status_color = rgb888_to_rgb565(brightness, brightness, 0);
|
||||
break;
|
||||
|
||||
case led_control_s::COLOR_PURPLE:
|
||||
status_color = rgb888_to_rgb565(brightness, 0, brightness);
|
||||
break;
|
||||
|
||||
case led_control_s::COLOR_CYAN:
|
||||
status_color = rgb888_to_rgb565(0, brightness, brightness);
|
||||
break;
|
||||
|
||||
case led_control_s::COLOR_WHITE:
|
||||
status_color = rgb888_to_rgb565(brightness, brightness, brightness);
|
||||
break;
|
||||
|
||||
default:
|
||||
case led_control_s::COLOR_OFF:
|
||||
break;
|
||||
}
|
||||
|
||||
// Build and send light commands for all configured lights
|
||||
uavcan::equipment::indication::LightsCommand light_command;
|
||||
|
||||
for (uint8_t i = 0; i < _num_lights; i++) {
|
||||
uavcan::equipment::indication::SingleLightCommand cmd;
|
||||
cmd.light_id = _light_ids[i];
|
||||
|
||||
uint8_t brightness = led_control_data.leds[0].brightness;
|
||||
|
||||
switch (led_control_data.leds[0].color) {
|
||||
case led_control_s::COLOR_RED:
|
||||
cmd.color.red = brightness >> 3;
|
||||
cmd.color.green = 0;
|
||||
cmd.color.blue = 0;
|
||||
switch (_light_functions[i]) {
|
||||
case LightFunction::Status:
|
||||
cmd.color = status_color;
|
||||
break;
|
||||
|
||||
case led_control_s::COLOR_GREEN:
|
||||
cmd.color.red = 0;
|
||||
cmd.color.green = brightness >> 2;
|
||||
cmd.color.blue = 0;
|
||||
break;
|
||||
|
||||
case led_control_s::COLOR_BLUE:
|
||||
cmd.color.red = 0;
|
||||
cmd.color.green = 0;
|
||||
cmd.color.blue = brightness >> 3;
|
||||
break;
|
||||
|
||||
case led_control_s::COLOR_AMBER: // make it the same as yellow
|
||||
|
||||
// FALLTHROUGH
|
||||
case led_control_s::COLOR_YELLOW:
|
||||
cmd.color.red = (brightness / 2) >> 3;
|
||||
cmd.color.green = (brightness / 2) >> 2;
|
||||
cmd.color.blue = 0;
|
||||
break;
|
||||
|
||||
case led_control_s::COLOR_PURPLE:
|
||||
cmd.color.red = (brightness / 2) >> 3;
|
||||
cmd.color.green = 0;
|
||||
cmd.color.blue = (brightness / 2) >> 3;
|
||||
break;
|
||||
|
||||
case led_control_s::COLOR_CYAN:
|
||||
cmd.color.red = 0;
|
||||
cmd.color.green = (brightness / 2) >> 2;
|
||||
cmd.color.blue = (brightness / 2) >> 3;
|
||||
break;
|
||||
|
||||
case led_control_s::COLOR_WHITE:
|
||||
cmd.color.red = (brightness / 3) >> 3;
|
||||
cmd.color.green = (brightness / 3) >> 2;
|
||||
cmd.color.blue = (brightness / 3) >> 3;
|
||||
break;
|
||||
|
||||
default: // led_control_s::COLOR_OFF
|
||||
cmd.color.red = 0;
|
||||
cmd.color.green = 0;
|
||||
cmd.color.blue = 0;
|
||||
case LightFunction::AntiCollision:
|
||||
uint8_t brigtness = is_anticolision_on() ? 255 : 0;
|
||||
cmd.color = rgb888_to_rgb565(brigtness, brigtness, brigtness);
|
||||
break;
|
||||
}
|
||||
|
||||
cmds.commands.push_back(cmd);
|
||||
|
||||
light_command.commands.push_back(cmd);
|
||||
}
|
||||
|
||||
if (_armed_sub.updated()) {
|
||||
publish_lights = true;
|
||||
|
||||
actuator_armed_s armed;
|
||||
|
||||
if (_armed_sub.copy(&armed)) {
|
||||
|
||||
/* Determine the current control mode
|
||||
* If a light's control mode config >= current control mode, the light will be enabled
|
||||
* Logic must match UAVCAN_LGT_* param values.
|
||||
* @value 0 Always off
|
||||
* @value 1 When autopilot is armed
|
||||
* @value 2 When autopilot is prearmed
|
||||
* @value 3 Always on
|
||||
*/
|
||||
uint8_t control_mode = 0;
|
||||
|
||||
if (armed.armed) {
|
||||
control_mode = 1;
|
||||
|
||||
} else if (armed.prearmed) {
|
||||
control_mode = 2;
|
||||
|
||||
} else {
|
||||
control_mode = 3;
|
||||
}
|
||||
|
||||
uavcan::equipment::indication::SingleLightCommand cmd;
|
||||
|
||||
// Beacons
|
||||
cmd.light_id = uavcan::equipment::indication::SingleLightCommand::LIGHT_ID_ANTI_COLLISION;
|
||||
cmd.color = brightness_to_rgb565(_param_mode_anti_col.get() >= control_mode ? 255 : 0);
|
||||
cmds.commands.push_back(cmd);
|
||||
|
||||
// Strobes
|
||||
cmd.light_id = uavcan::equipment::indication::SingleLightCommand::LIGHT_ID_STROBE;
|
||||
cmd.color = brightness_to_rgb565(_param_mode_strobe.get() >= control_mode ? 255 : 0);
|
||||
cmds.commands.push_back(cmd);
|
||||
|
||||
// Nav lights
|
||||
cmd.light_id = uavcan::equipment::indication::SingleLightCommand::LIGHT_ID_RIGHT_OF_WAY;
|
||||
cmd.color = brightness_to_rgb565(_param_mode_nav.get() >= control_mode ? 255 : 0);
|
||||
cmds.commands.push_back(cmd);
|
||||
|
||||
// Landing lights
|
||||
cmd.light_id = uavcan::equipment::indication::SingleLightCommand::LIGHT_ID_LANDING;
|
||||
cmd.color = brightness_to_rgb565(_param_mode_land.get() >= control_mode ? 255 : 0);
|
||||
cmds.commands.push_back(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
if (publish_lights) {
|
||||
_uavcan_pub_lights_cmd.broadcast(cmds);
|
||||
}
|
||||
_uavcan_pub_lights_cmd.broadcast(light_command);
|
||||
}
|
||||
|
||||
uavcan::equipment::indication::RGB565 UavcanRGBController::brightness_to_rgb565(uint8_t brightness)
|
||||
bool UavcanRGBController::is_anticolision_on()
|
||||
{
|
||||
// RGB color in the standard 5-6-5 16-bit palette.
|
||||
// Monocolor lights should interpret this as brightness setpoint: from zero (0, 0, 0) to full brightness (31, 63, 31).
|
||||
uavcan::equipment::indication::RGB565 color;
|
||||
actuator_armed_s actuator_armed{};
|
||||
_actuator_armed_sub.copy(&actuator_armed);
|
||||
|
||||
color.red = (31.0f * (float)brightness / 255.0f);
|
||||
color.green = (62.0f * (float)brightness / 255.0f);
|
||||
color.blue = (31.0f * (float)brightness / 255.0f);
|
||||
switch (_param_uavcan_lgt_antcl.get()) {
|
||||
case 3: // Always on
|
||||
return true;
|
||||
|
||||
return color;
|
||||
case 2: // When autopilot is prearmed
|
||||
return actuator_armed.armed || actuator_armed.prearmed;
|
||||
|
||||
case 1: // When autopilot is armed
|
||||
return actuator_armed.armed;
|
||||
|
||||
case 0: // Always off
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uavcan::equipment::indication::RGB565 UavcanRGBController::rgb888_to_rgb565(uint8_t red, uint8_t green, uint8_t blue)
|
||||
{
|
||||
// RGB565: Full brightness is (31, 63, 31), off is (0, 0, 0)
|
||||
uavcan::equipment::indication::RGB565 rgb565{};
|
||||
rgb565.red = (red * 31 + 127) / 255;
|
||||
rgb565.green = (green * 63 + 127) / 255;
|
||||
rgb565.blue = (blue * 31 + 127) / 255;
|
||||
return rgb565;
|
||||
}
|
||||
|
||||
@@ -54,9 +54,20 @@ private:
|
||||
// Max update rate to avoid excessive bus traffic
|
||||
static constexpr unsigned MAX_RATE_HZ = 20;
|
||||
|
||||
// Maximum number of configurable lights
|
||||
static constexpr uint8_t MAX_NUM_UAVCAN_LIGHTS = 3;
|
||||
|
||||
// Light function types
|
||||
enum class LightFunction : uint8_t {
|
||||
Status = 0, // System status colors from led_control
|
||||
AntiCollision = 1 // White beacon based on arm state
|
||||
};
|
||||
|
||||
void periodic_update(const uavcan::TimerEvent &);
|
||||
|
||||
uavcan::equipment::indication::RGB565 brightness_to_rgb565(uint8_t brightness);
|
||||
bool is_anticolision_on(); ///< Evaluates current on state of collision lights accordingt to UAVCAN_LGT_ANTCL
|
||||
|
||||
uavcan::equipment::indication::RGB565 rgb888_to_rgb565(uint8_t red, uint8_t green, uint8_t blue);
|
||||
|
||||
typedef uavcan::MethodBinder<UavcanRGBController *, void (UavcanRGBController::*)(const uavcan::TimerEvent &)>
|
||||
TimerCbBinder;
|
||||
@@ -65,14 +76,21 @@ private:
|
||||
uavcan::Publisher<uavcan::equipment::indication::LightsCommand> _uavcan_pub_lights_cmd;
|
||||
uavcan::TimerEventForwarder<TimerCbBinder> _timer;
|
||||
|
||||
uORB::Subscription _armed_sub{ORB_ID(actuator_armed)};
|
||||
uORB::Subscription _actuator_armed_sub{ORB_ID(actuator_armed)};
|
||||
|
||||
LedController _led_controller;
|
||||
|
||||
// Cached configuration (set during init, requires reboot to change)
|
||||
uint8_t _num_lights{0};
|
||||
uint8_t _light_ids[MAX_NUM_UAVCAN_LIGHTS] {};
|
||||
LightFunction _light_functions[MAX_NUM_UAVCAN_LIGHTS] {};
|
||||
|
||||
// Cached parameter handles
|
||||
param_t _light_id_params[MAX_NUM_UAVCAN_LIGHTS] {};
|
||||
param_t _light_fn_params[MAX_NUM_UAVCAN_LIGHTS] {};
|
||||
|
||||
DEFINE_PARAMETERS(
|
||||
(ParamInt<px4::params::UAVCAN_LGT_ANTCL>) _param_mode_anti_col,
|
||||
(ParamInt<px4::params::UAVCAN_LGT_STROB>) _param_mode_strobe,
|
||||
(ParamInt<px4::params::UAVCAN_LGT_NAV>) _param_mode_nav,
|
||||
(ParamInt<px4::params::UAVCAN_LGT_LAND>) _param_mode_land
|
||||
(ParamInt<px4::params::UAVCAN_LGT_NUM>) _param_lgt_num,
|
||||
(ParamInt<px4::params::UAVCAN_LGT_ANTCL>) _param_uavcan_lgt_antcl
|
||||
)
|
||||
};
|
||||
|
||||
@@ -1163,6 +1163,11 @@ UavcanNode::print_info()
|
||||
|
||||
printf("\n");
|
||||
|
||||
// See https://github.com/PX4/PX4-Autopilot/issues/22871
|
||||
printf("WARNING: CAN error counter values below may increase during this function call due to internal counter reading implementation.\n");
|
||||
printf("Do not fully trust these counters until this issue is fixed.\n");
|
||||
printf("\n");
|
||||
|
||||
// UAVCAN node perfcounters
|
||||
printf("UAVCAN node status:\n");
|
||||
printf("\tInternal failures: %" PRIu64 "\n", _node.getInternalFailureCount());
|
||||
|
||||
@@ -135,7 +135,7 @@ PARAM_DEFINE_INT32(UAVCAN_ECU_FUELT, 1);
|
||||
* UAVCAN ANTI_COLLISION light operating mode
|
||||
*
|
||||
* This parameter defines the minimum condition under which the system will command
|
||||
* the ANTI_COLLISION lights on
|
||||
* lights with anti-collision function to turn on (white).
|
||||
*
|
||||
* 0 - Always off
|
||||
* 1 - When autopilot is armed
|
||||
@@ -153,72 +153,6 @@ PARAM_DEFINE_INT32(UAVCAN_ECU_FUELT, 1);
|
||||
*/
|
||||
PARAM_DEFINE_INT32(UAVCAN_LGT_ANTCL, 2);
|
||||
|
||||
/**
|
||||
* UAVCAN STROBE light operating mode
|
||||
*
|
||||
* This parameter defines the minimum condition under which the system will command
|
||||
* the STROBE lights on
|
||||
*
|
||||
* 0 - Always off
|
||||
* 1 - When autopilot is armed
|
||||
* 2 - When autopilot is prearmed
|
||||
* 3 - Always on
|
||||
*
|
||||
* @min 0
|
||||
* @max 3
|
||||
* @value 0 Always off
|
||||
* @value 1 When autopilot is armed
|
||||
* @value 2 When autopilot is prearmed
|
||||
* @value 3 Always on
|
||||
* @reboot_required true
|
||||
* @group UAVCAN
|
||||
*/
|
||||
PARAM_DEFINE_INT32(UAVCAN_LGT_STROB, 1);
|
||||
|
||||
/**
|
||||
* UAVCAN RIGHT_OF_WAY light operating mode
|
||||
*
|
||||
* This parameter defines the minimum condition under which the system will command
|
||||
* the RIGHT_OF_WAY lights on
|
||||
*
|
||||
* 0 - Always off
|
||||
* 1 - When autopilot is armed
|
||||
* 2 - When autopilot is prearmed
|
||||
* 3 - Always on
|
||||
*
|
||||
* @min 0
|
||||
* @max 3
|
||||
* @value 0 Always off
|
||||
* @value 1 When autopilot is armed
|
||||
* @value 2 When autopilot is prearmed
|
||||
* @value 3 Always on
|
||||
* @reboot_required true
|
||||
* @group UAVCAN
|
||||
*/
|
||||
PARAM_DEFINE_INT32(UAVCAN_LGT_NAV, 3);
|
||||
|
||||
/**
|
||||
* UAVCAN LIGHT_ID_LANDING light operating mode
|
||||
*
|
||||
* This parameter defines the minimum condition under which the system will command
|
||||
* the LIGHT_ID_LANDING lights on
|
||||
*
|
||||
* 0 - Always off
|
||||
* 1 - When autopilot is armed
|
||||
* 2 - When autopilot is prearmed
|
||||
* 3 - Always on
|
||||
*
|
||||
* @min 0
|
||||
* @max 3
|
||||
* @value 0 Always off
|
||||
* @value 1 When autopilot is armed
|
||||
* @value 2 When autopilot is prearmed
|
||||
* @value 3 Always on
|
||||
* @reboot_required true
|
||||
* @group UAVCAN
|
||||
*/
|
||||
PARAM_DEFINE_INT32(UAVCAN_LGT_LAND, 0);
|
||||
|
||||
/**
|
||||
* publish Arming Status stream
|
||||
*
|
||||
|
||||
@@ -36,7 +36,11 @@ add_subdirectory(device)
|
||||
add_subdirectory(gyroscope)
|
||||
add_subdirectory(led)
|
||||
add_subdirectory(magnetometer)
|
||||
add_subdirectory(mcp_common)
|
||||
add_subdirectory(rangefinder)
|
||||
|
||||
add_subdirectory(smbus)
|
||||
add_subdirectory(smbus_sbs)
|
||||
|
||||
if (${PX4_PLATFORM} STREQUAL "nuttx")
|
||||
add_subdirectory(mcp_common)
|
||||
endif()
|
||||
|
||||
@@ -100,7 +100,7 @@ public:
|
||||
// Direct Form II implementation
|
||||
T delay_element_0{sample - _delay_element_1 *_a1 - _delay_element_2 * _a2};
|
||||
|
||||
const T output{delay_element_0 *_b0 + _delay_element_1 *_b1 + _delay_element_2 * _b2};
|
||||
T output{delay_element_0 *_b0 + _delay_element_1 *_b1 + _delay_element_2 * _b2};
|
||||
|
||||
_delay_element_2 = _delay_element_1;
|
||||
_delay_element_1 = delay_element_0;
|
||||
|
||||
@@ -75,7 +75,7 @@ Vector3f RateControl::update(const Vector3f &rate, const Vector3f &rate_sp, cons
|
||||
Vector3f rate_error = rate_sp - rate;
|
||||
|
||||
// PID control with feed forward
|
||||
const Vector3f torque = _gain_p.emult(rate_error) + _rate_int - _gain_d.emult(angular_accel) + _gain_ff.emult(rate_sp);
|
||||
Vector3f torque = _gain_p.emult(rate_error) + _rate_int - _gain_d.emult(angular_accel) + _gain_ff.emult(rate_sp);
|
||||
|
||||
// update integral only if we are not landed
|
||||
if (!landed) {
|
||||
|
||||
@@ -54,6 +54,7 @@ RtlTimeEstimator::RtlTimeEstimator() : ModuleParams(nullptr)
|
||||
_param_fw_climb_rate = param_find("FW_T_CLMB_R_SP");
|
||||
_param_fw_sink_rate = param_find("FW_T_SINK_R_SP");
|
||||
_param_fw_airspeed_trim = param_find("FW_AIRSPD_TRIM");
|
||||
_param_fw_gnd_spd_min = param_find("FW_GND_SPD_MIN");
|
||||
_param_mpc_xy_cruise = param_find("MPC_XY_CRUISE");
|
||||
_param_rover_cruise_speed = param_find("RO_SPEED_LIM");
|
||||
};
|
||||
@@ -142,7 +143,18 @@ float RtlTimeEstimator::getCruiseGroundSpeed(const matrix::Vector2f &direction_n
|
||||
const float ground_speed = sqrtf(cruise_speed * cruise_speed - wind_across_dir * wind_across_dir) + fminf(
|
||||
0.f, wind_along_dir);
|
||||
|
||||
cruise_speed = ground_speed;
|
||||
// Assume that minimum ground speed is always satisfied. If
|
||||
// windspeed < cas2tas(FW_AIRSPD_MAX) - FW_GND_SPD_MIN
|
||||
// the assumption always holds. Otherwise it breaks down when
|
||||
// flying upwind, and the RTL time estimate is optimistic.
|
||||
|
||||
float fw_gnd_spd_min = 5.0f;
|
||||
|
||||
if (_param_fw_gnd_spd_min != PARAM_INVALID) {
|
||||
param_get(_param_fw_gnd_spd_min, &fw_gnd_spd_min);
|
||||
}
|
||||
|
||||
cruise_speed = fmaxf(ground_speed, fw_gnd_spd_min);
|
||||
}
|
||||
|
||||
return cruise_speed;
|
||||
|
||||
@@ -129,6 +129,7 @@ private:
|
||||
param_t _param_fw_sink_rate{PARAM_INVALID}; /**< FW descend speed parameter */
|
||||
|
||||
param_t _param_fw_airspeed_trim{PARAM_INVALID}; /**< FW cruise airspeed parameter */
|
||||
param_t _param_fw_gnd_spd_min{PARAM_INVALID}; /**< FW min groundspeed parameter */
|
||||
param_t _param_mpc_xy_cruise{PARAM_INVALID}; /**< MC horizontal cruise speed parameter */
|
||||
param_t _param_rover_cruise_speed{PARAM_INVALID}; /**< Rover cruise speed parameter */
|
||||
|
||||
|
||||
@@ -590,7 +590,9 @@ void TECSControl::_calcThrottleControlUpdate(float dt, const STERateLimit &limit
|
||||
if (_throttle_setpoint >= param.throttle_max) {
|
||||
throttle_integ_input = math::min(0.f, throttle_integ_input);
|
||||
|
||||
} else if (_throttle_setpoint <= param.throttle_min) {
|
||||
}
|
||||
|
||||
if (_throttle_setpoint <= param.throttle_min) {
|
||||
throttle_integ_input = math::max(0.f, throttle_integ_input);
|
||||
}
|
||||
|
||||
|
||||
@@ -107,7 +107,7 @@ uint8_t Modes::addExternalMode(const Modes::Mode &mode)
|
||||
int matching_idx = -1;
|
||||
|
||||
for (int i = 0; i < MAX_NUM; ++i) {
|
||||
char hash_param_name[20];
|
||||
char hash_param_name[17];
|
||||
snprintf(hash_param_name, sizeof(hash_param_name), "COM_MODE%d_HASH", i);
|
||||
const param_t handle = param_find(hash_param_name);
|
||||
int32_t current_hash{};
|
||||
@@ -164,7 +164,7 @@ uint8_t Modes::addExternalMode(const Modes::Mode &mode)
|
||||
|
||||
if (new_mode_idx != -1 && !_modes[new_mode_idx].valid) {
|
||||
if (need_to_update_param) {
|
||||
char hash_param_name[20];
|
||||
char hash_param_name[17];
|
||||
snprintf(hash_param_name, sizeof(hash_param_name), "COM_MODE%d_HASH", new_mode_idx);
|
||||
const param_t handle = param_find(hash_param_name);
|
||||
|
||||
|
||||
+15
-1
@@ -63,6 +63,7 @@ ActuatorEffectivenessControlSurfaces::ActuatorEffectivenessControlSurfaces(Modul
|
||||
_spoilers_setpoint_with_slewrate.setSlewRate(kSpoilersSlewRate);
|
||||
|
||||
_count_handle = param_find("CA_SV_CS_COUNT");
|
||||
_param_handle_ca_cs_laun_lk = param_find("CA_CS_LAUN_LK");
|
||||
updateParams();
|
||||
}
|
||||
|
||||
@@ -80,7 +81,7 @@ void ActuatorEffectivenessControlSurfaces::updateParams()
|
||||
|
||||
// Helper to check if a PWM center parameter is enabled, and clamp it to valid range
|
||||
auto check_pwm_center = [](const char *prefix, int channel) -> bool {
|
||||
char param_name[20];
|
||||
char param_name[17];
|
||||
snprintf(param_name, sizeof(param_name), "%s_CENT%d", prefix, channel);
|
||||
param_t param = param_find(param_name);
|
||||
|
||||
@@ -112,6 +113,8 @@ void ActuatorEffectivenessControlSurfaces::updateParams()
|
||||
}
|
||||
}
|
||||
|
||||
param_get(_param_handle_ca_cs_laun_lk, &_param_ca_cs_laun_lk);
|
||||
|
||||
for (int i = 0; i < _count; i++) {
|
||||
param_get(_param_handles[i].type, (int32_t *)&_params[i].type);
|
||||
|
||||
@@ -234,3 +237,14 @@ void ActuatorEffectivenessControlSurfaces::applySpoilers(float spoilers_control,
|
||||
actuator_sp(i + first_actuator_idx) += _spoilers_setpoint_with_slewrate.getState() * _params[i].scale_spoiler;
|
||||
}
|
||||
}
|
||||
|
||||
void ActuatorEffectivenessControlSurfaces::applyLaunchLock(int first_actuator_idx,
|
||||
ActuatorVector &actuator_sp)
|
||||
{
|
||||
for (int i = 0; i < _count; ++i) {
|
||||
|
||||
if (_param_ca_cs_laun_lk & (1u << i)) {
|
||||
actuator_sp(i + first_actuator_idx) = NAN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
@@ -90,6 +90,7 @@ public:
|
||||
|
||||
void applyFlaps(float flaps_control, int first_actuator_idx, float dt, ActuatorVector &actuator_sp);
|
||||
void applySpoilers(float spoilers_control, int first_actuator_idx, float dt, ActuatorVector &actuator_sp);
|
||||
void applyLaunchLock(int first_actuator_idx, ActuatorVector &actuator_sp);
|
||||
|
||||
private:
|
||||
void updateParams() override;
|
||||
@@ -104,9 +105,11 @@ private:
|
||||
};
|
||||
ParamHandles _param_handles[MAX_COUNT];
|
||||
param_t _count_handle;
|
||||
param_t _param_handle_ca_cs_laun_lk;
|
||||
|
||||
Params _params[MAX_COUNT] {};
|
||||
int32_t _count{0};
|
||||
int32_t _param_ca_cs_laun_lk{0};
|
||||
|
||||
SlewRate<float> _flaps_setpoint_with_slewrate;
|
||||
SlewRate<float> _spoilers_setpoint_with_slewrate;
|
||||
|
||||
+12
@@ -65,6 +65,18 @@ void ActuatorEffectivenessFixedWing::updateSetpoint(const matrix::Vector<float,
|
||||
ActuatorVector &actuator_sp, const ActuatorVector &actuator_min, const ActuatorVector &actuator_max)
|
||||
{
|
||||
stopMaskedMotorsWithZeroThrust(_forwards_motors_mask, actuator_sp);
|
||||
|
||||
// disable selected control surfaces during launch
|
||||
launch_detection_status_s launch_detection_status;
|
||||
|
||||
if (_launch_detection_status_sub.copy(&launch_detection_status)) {
|
||||
if (launch_detection_status.selected_control_surface_disarmed
|
||||
&& hrt_elapsed_time(&launch_detection_status.timestamp) < 100_ms) {
|
||||
|
||||
_control_surfaces.applyLaunchLock(_first_control_surface_idx, actuator_sp);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ActuatorEffectivenessFixedWing::allocateAuxilaryControls(const float dt, int matrix_index,
|
||||
|
||||
+2
@@ -38,6 +38,7 @@
|
||||
#include "ActuatorEffectivenessControlSurfaces.hpp"
|
||||
|
||||
#include <uORB/topics/normalized_unsigned_setpoint.h>
|
||||
#include <uORB/topics/launch_detection_status.h>
|
||||
|
||||
class ActuatorEffectivenessFixedWing : public ModuleParams, public ActuatorEffectiveness
|
||||
{
|
||||
@@ -60,6 +61,7 @@ private:
|
||||
|
||||
uORB::Subscription _flaps_setpoint_sub{ORB_ID(flaps_setpoint)};
|
||||
uORB::Subscription _spoilers_setpoint_sub{ORB_ID(spoilers_setpoint)};
|
||||
uORB::Subscription _launch_detection_status_sub{ORB_ID(launch_detection_status)};
|
||||
|
||||
int _first_control_surface_idx{0}; ///< applies to matrix 1
|
||||
|
||||
|
||||
@@ -356,6 +356,22 @@ parameters:
|
||||
instance_start: 0
|
||||
default: 0
|
||||
|
||||
CA_CS_LAUN_LK:
|
||||
description:
|
||||
short: Control surface launch lock enabled
|
||||
long: If actuator launch lock is enabled, this surface is kept at the disarmed value.
|
||||
type: bitmask
|
||||
bit:
|
||||
0: Control Surface 1
|
||||
1: Control Surface 2
|
||||
2: Control Surface 3
|
||||
3: Control Surface 4
|
||||
4: Control Surface 5
|
||||
5: Control Surface 6
|
||||
6: Control Surface 7
|
||||
7: Control Surface 8
|
||||
default: 0
|
||||
|
||||
# Tilts
|
||||
CA_SV_TL_COUNT:
|
||||
description:
|
||||
@@ -659,7 +675,7 @@ mixer:
|
||||
|
||||
rules:
|
||||
- select_identifier: 'servo-type' # restrict torque based on servo type
|
||||
apply_identifiers: ['servo-torque-roll', 'servo-torque-pitch', 'servo-torque-yaw', 'servo-scale-flap', 'servo-scale-spoiler']
|
||||
apply_identifiers: ['servo-torque-roll', 'servo-torque-pitch', 'servo-torque-yaw', 'servo-scale-flap', 'servo-scale-spoiler', 'servo-launch-lock']
|
||||
items:
|
||||
# Convention: horizontal surfaces: up=positive, vertical: right=positive, mixed: up=positive.
|
||||
# By default the scale is set to 1/N, where N is the amount of actuators with an effect on
|
||||
@@ -858,6 +874,12 @@ mixer:
|
||||
label: 'Spoiler Scale'
|
||||
advanced: true
|
||||
identifier: 'servo-scale-spoiler'
|
||||
- name: 'CA_CS_LAUN_LK'
|
||||
label: 'Launch Lock'
|
||||
advanced: true
|
||||
identifier: 'servo-launch-lock'
|
||||
index_offset: 0
|
||||
show_as: 'bitset'
|
||||
|
||||
2: # Standard VTOL
|
||||
title: 'Standard VTOL'
|
||||
|
||||
@@ -75,7 +75,9 @@ void RangeFinderConsistencyCheck::update(float dist_bottom, float dist_bottom_va
|
||||
void RangeFinderConsistencyCheck::updateConsistency(float vz, uint64_t time_us)
|
||||
{
|
||||
if (fabsf(_signed_test_ratio_lpf.getState()) >= 1.f) {
|
||||
if ((time_us - _time_last_horizontal_motion) > _signed_test_ratio_tau) {
|
||||
uint64_t timeout_us = _signed_test_ratio_tau * 1e6f;
|
||||
|
||||
if ((time_us - _time_last_horizontal_motion) > timeout_us) {
|
||||
_is_kinematically_consistent = false;
|
||||
_time_last_inconsistent_us = time_us;
|
||||
}
|
||||
|
||||
@@ -35,7 +35,6 @@
|
||||
#include "EKF2.hpp"
|
||||
|
||||
using namespace time_literals;
|
||||
using math::constrain;
|
||||
using matrix::Eulerf;
|
||||
using matrix::Quatf;
|
||||
using matrix::Vector3f;
|
||||
|
||||
@@ -61,8 +61,8 @@ bool FlightTaskAuto::activate(const trajectory_setpoint_s &last_setpoint)
|
||||
// If the velocity setpoint is unknown, set to the current velocity
|
||||
if (!PX4_ISFINITE(vel_prev(i))) { vel_prev(i) = _velocity(i); }
|
||||
|
||||
// No acceleration estimate available, set to zero if the setpoint is NAN
|
||||
if (!PX4_ISFINITE(accel_prev(i))) { accel_prev(i) = 0.f; }
|
||||
// If accel setpoint unknown, set to the current accel
|
||||
if (!PX4_ISFINITE(accel_prev(i))) { accel_prev(i) = _acceleration(i); }
|
||||
}
|
||||
|
||||
_position_smoothing.reset(accel_prev, vel_prev, pos_prev);
|
||||
|
||||
@@ -153,6 +153,17 @@ void FlightTask::_evaluateVehicleLocalPosition()
|
||||
_velocity(2) = _sub_vehicle_local_position.get().vz;
|
||||
}
|
||||
|
||||
// acceleration is calculated as the velocity derivative in EKF2,
|
||||
// if velocity is available acceleration values are available
|
||||
if (_sub_vehicle_local_position.get().v_xy_valid) {
|
||||
_acceleration(0) = _sub_vehicle_local_position.get().ax;
|
||||
_acceleration(1) = _sub_vehicle_local_position.get().ay;
|
||||
}
|
||||
|
||||
if (_sub_vehicle_local_position.get().v_z_valid) {
|
||||
_acceleration(2) = _sub_vehicle_local_position.get().az;
|
||||
}
|
||||
|
||||
// distance to bottom
|
||||
if (_sub_vehicle_local_position.get().dist_bottom_valid
|
||||
&& PX4_ISFINITE(_sub_vehicle_local_position.get().dist_bottom)) {
|
||||
|
||||
@@ -201,6 +201,7 @@ protected:
|
||||
/* Current vehicle state */
|
||||
matrix::Vector3f _position; /**< current vehicle position */
|
||||
matrix::Vector3f _velocity; /**< current vehicle velocity */
|
||||
matrix::Vector3f _acceleration; /**< current vehicle acceleration (derivative of velocity) */
|
||||
|
||||
float _yaw{}; /**< current vehicle yaw heading */
|
||||
float _unaided_yaw{};
|
||||
|
||||
+1
-1
@@ -52,7 +52,7 @@ protected:
|
||||
StickAccelerationXY _stick_acceleration_xy{this};
|
||||
WeatherVane _weathervane{this}; /**< weathervane library, used to implement a yaw control law that turns the vehicle nose into the wind */
|
||||
|
||||
DEFINE_PARAMETERS_CUSTOM_PARENT(FlightTask,
|
||||
DEFINE_PARAMETERS_CUSTOM_PARENT(FlightTaskManualAltitudeSmoothVel,
|
||||
(ParamFloat<px4::params::MPC_VEL_MANUAL>) _param_mpc_vel_manual,
|
||||
(ParamFloat<px4::params::MPC_ACC_HOR>) _param_mpc_acc_hor
|
||||
)
|
||||
|
||||
@@ -173,7 +173,7 @@ void FlightTaskOrbit::_sanitizeParams(float &radius, float &velocity) const
|
||||
|
||||
bool FlightTaskOrbit::activate(const trajectory_setpoint_s &last_setpoint)
|
||||
{
|
||||
bool ret = FlightTaskManualAltitude::activate(last_setpoint);
|
||||
bool ret = FlightTaskManualAltitudeSmoothVel::activate(last_setpoint);
|
||||
_currently_orbiting = false;
|
||||
_orbit_radius = _radius_min;
|
||||
_orbit_velocity = 1.f;
|
||||
|
||||
@@ -36,9 +36,6 @@
|
||||
#include <px4_platform_common/events.h>
|
||||
#include <uORB/topics/longitudinal_control_configuration.h>
|
||||
|
||||
using math::constrain;
|
||||
using math::max;
|
||||
using math::min;
|
||||
using math::radians;
|
||||
|
||||
using matrix::Dcmf;
|
||||
@@ -1210,6 +1207,7 @@ FixedWingModeManager::control_auto_takeoff(const hrt_abstime &now, const float c
|
||||
_takeoff_init_position = global_position;
|
||||
_takeoff_ground_alt = _current_altitude;
|
||||
_launch_current_yaw = _yaw;
|
||||
_time_launch_detected = now;
|
||||
}
|
||||
|
||||
const Vector2f launch_local_position = _global_local_proj_ref.project(_takeoff_init_position(0),
|
||||
@@ -1285,6 +1283,9 @@ FixedWingModeManager::control_auto_takeoff(const hrt_abstime &now, const float c
|
||||
launch_detection_status_s launch_detection_status;
|
||||
launch_detection_status.timestamp = now;
|
||||
launch_detection_status.launch_detection_state = _launchDetector.getLaunchDetected();
|
||||
launch_detection_status.selected_control_surface_disarmed =
|
||||
hrt_elapsed_time(&_time_launch_detected) < _param_fw_laun_cs_lk_dy.get() * 1_s
|
||||
|| _time_launch_detected == 0;
|
||||
_launch_detection_status_pub.publish(launch_detection_status);
|
||||
}
|
||||
|
||||
@@ -1380,6 +1381,7 @@ FixedWingModeManager::control_auto_takeoff_no_nav(const hrt_abstime &now, const
|
||||
if (!_launch_detected && _launchDetector.getLaunchDetected() > launch_detection_status_s::STATE_WAITING_FOR_LAUNCH) {
|
||||
_launch_detected = true;
|
||||
_takeoff_ground_alt = _current_altitude;
|
||||
_time_launch_detected = now;
|
||||
}
|
||||
|
||||
/* Launch has been detected, hence we have to control the plane. */
|
||||
@@ -1411,6 +1413,9 @@ FixedWingModeManager::control_auto_takeoff_no_nav(const hrt_abstime &now, const
|
||||
launch_detection_status_s launch_detection_status;
|
||||
launch_detection_status.timestamp = now;
|
||||
launch_detection_status.launch_detection_state = _launchDetector.getLaunchDetected();
|
||||
launch_detection_status.selected_control_surface_disarmed =
|
||||
hrt_elapsed_time(&_time_launch_detected) < _param_fw_laun_cs_lk_dy.get() * 1_s
|
||||
|| _time_launch_detected == 0;
|
||||
_launch_detection_status_pub.publish(launch_detection_status);
|
||||
}
|
||||
|
||||
@@ -2315,6 +2320,8 @@ FixedWingModeManager::reset_takeoff_state()
|
||||
|
||||
_launch_detected = false;
|
||||
|
||||
_time_launch_detected = 0;
|
||||
|
||||
_takeoff_ground_alt = _current_altitude;
|
||||
}
|
||||
|
||||
|
||||
@@ -298,6 +298,9 @@ private:
|
||||
// true if a launch, specifically using the launch detector, has been detected
|
||||
bool _launch_detected{false};
|
||||
|
||||
// [us] time stamp of (runway/catapult) launch detection
|
||||
hrt_abstime _time_launch_detected{0};
|
||||
|
||||
// [deg] global position of the vehicle at the time launch is detected (using launch detector) or takeoff is started (runway)
|
||||
Vector2d _takeoff_init_position{0, 0};
|
||||
|
||||
@@ -865,6 +868,10 @@ private:
|
||||
(ParamFloat<px4::params::FW_GPSF_R>) _param_nav_gpsf_r,
|
||||
(ParamFloat<px4::params::FW_T_SPDWEIGHT>) _param_t_spdweight,
|
||||
|
||||
// Launch detection parameters
|
||||
(ParamBool<px4::params::FW_LAUN_DETCN_ON>) _param_fw_laun_detcn_on,
|
||||
(ParamFloat<px4::params::FW_LAUN_CS_LK_DY>) _param_fw_laun_cs_lk_dy,
|
||||
|
||||
// external parameters
|
||||
(ParamBool<px4::params::FW_USE_AIRSPD>) _param_fw_use_airspd,
|
||||
(ParamFloat<px4::params::NAV_LOITER_RAD>) _param_nav_loiter_rad,
|
||||
@@ -881,7 +888,6 @@ private:
|
||||
(ParamInt<px4::params::FW_LND_ABORT>) _param_fw_lnd_abort,
|
||||
(ParamFloat<px4::params::FW_TKO_AIRSPD>) _param_fw_tko_airspd,
|
||||
(ParamFloat<px4::params::RWTO_PSP>) _param_rwto_psp,
|
||||
(ParamBool<px4::params::FW_LAUN_DETCN_ON>) _param_fw_laun_detcn_on,
|
||||
(ParamFloat<px4::params::FW_AIRSPD_MAX>) _param_fw_airspd_max,
|
||||
(ParamFloat<px4::params::FW_AIRSPD_MIN>) _param_fw_airspd_min,
|
||||
(ParamFloat<px4::params::FW_AIRSPD_TRIM>) _param_fw_airspd_trim,
|
||||
|
||||
@@ -105,7 +105,7 @@ FigureEight::FigureEightPatternParameters FigureEight::sanitizeParameters(const
|
||||
}
|
||||
|
||||
void FigureEight::initializePattern(const matrix::Vector2f &curr_pos_local, const matrix::Vector2f &ground_speed,
|
||||
const FigureEightPatternParameters ¶meters, FigureEightPatternPoints pattern_points)
|
||||
const FigureEightPatternParameters ¶meters, const FigureEightPatternPoints &pattern_points)
|
||||
{
|
||||
// Initialize the currently active segment, if it hasn't been active yet, or the pattern has been changed.
|
||||
if ((_current_segment == FigureEightSegment::SEGMENT_UNDEFINED) || (_active_parameters != parameters)) {
|
||||
|
||||
@@ -140,7 +140,7 @@ private:
|
||||
* @param[in] pattern_points are the figure of eight pattern points.
|
||||
*/
|
||||
void initializePattern(const matrix::Vector2f &curr_pos_local, const matrix::Vector2f &ground_speed,
|
||||
const FigureEightPatternParameters ¶meters, FigureEightPatternPoints pattern_points);
|
||||
const FigureEightPatternParameters ¶meters, const FigureEightPatternPoints &pattern_points);
|
||||
|
||||
/**
|
||||
* @brief Calculate figure eight pattern points
|
||||
|
||||
@@ -580,6 +580,21 @@ PARAM_DEFINE_INT32(FW_LND_ABORT, 3);
|
||||
*/
|
||||
PARAM_DEFINE_INT32(FW_LAUN_DETCN_ON, 0);
|
||||
|
||||
/**
|
||||
* Control surface launch delay
|
||||
*
|
||||
* Locks control surfaces during pre-launch (armed) and until this time since launch has passed.
|
||||
* Only affects control surfaces that have corresponding flag set, and not active for runway takeoff.
|
||||
* Set to 0 to disable any surface locking after arming.
|
||||
*
|
||||
* @unit s
|
||||
* @min 0.0
|
||||
* @decimal 1
|
||||
* @increment 0.1
|
||||
* @group FW Auto Takeoff
|
||||
*/
|
||||
PARAM_DEFINE_FLOAT(FW_LAUN_CS_LK_DY, 0.f);
|
||||
|
||||
/**
|
||||
* Flaps setting during take-off
|
||||
*
|
||||
|
||||
@@ -36,7 +36,6 @@
|
||||
using namespace time_literals;
|
||||
using namespace matrix;
|
||||
|
||||
using math::constrain;
|
||||
using math::interpolate;
|
||||
using math::radians;
|
||||
|
||||
@@ -288,8 +287,18 @@ void FixedwingRateControl::Run()
|
||||
_rate_control.resetIntegral();
|
||||
}
|
||||
|
||||
launch_detection_status_s launch_detection_status{};
|
||||
_launch_detection_status_sub.copy(&launch_detection_status);
|
||||
|
||||
bool control_surfaces_locked = false;
|
||||
|
||||
if (hrt_elapsed_time(&launch_detection_status.timestamp) < 100_ms
|
||||
&& launch_detection_status.selected_control_surface_disarmed) {
|
||||
control_surfaces_locked = true;
|
||||
}
|
||||
|
||||
// Reset integrators if the aircraft is on ground or not in a state where the fw attitude controller is run
|
||||
if (_landed || !_in_fw_or_transition_wo_tailsitter_transition) {
|
||||
if (_landed || !_in_fw_or_transition_wo_tailsitter_transition || control_surfaces_locked) {
|
||||
|
||||
_gain_compression.reset();
|
||||
_rate_control.resetIntegral();
|
||||
|
||||
@@ -70,6 +70,7 @@
|
||||
#include <uORB/topics/vehicle_status.h>
|
||||
#include <uORB/topics/vehicle_thrust_setpoint.h>
|
||||
#include <uORB/topics/vehicle_torque_setpoint.h>
|
||||
#include <uORB/topics/launch_detection_status.h>
|
||||
|
||||
using matrix::Eulerf;
|
||||
using matrix::Quatf;
|
||||
@@ -110,6 +111,7 @@ private:
|
||||
uORB::Subscription _vehicle_land_detected_sub{ORB_ID(vehicle_land_detected)};
|
||||
uORB::Subscription _vehicle_status_sub{ORB_ID(vehicle_status)};
|
||||
uORB::Subscription _vehicle_rates_sub{ORB_ID(vehicle_angular_velocity)};
|
||||
uORB::Subscription _launch_detection_status_sub{ORB_ID(launch_detection_status)};
|
||||
|
||||
uORB::SubscriptionMultiArray<control_allocator_status_s, 2> _control_allocator_status_subs{ORB_ID::control_allocator_status};
|
||||
|
||||
|
||||
@@ -1,120 +0,0 @@
|
||||
---
|
||||
Checks: '*,
|
||||
-android*,
|
||||
-bugprone-integer-division,
|
||||
-cert-dcl50-cpp,
|
||||
-cert-env33-c,
|
||||
-cert-err34-c,
|
||||
-cert-err58-cpp,
|
||||
-cert-msc30-c,
|
||||
-cert-msc50-cpp,
|
||||
-cert-flp30-c,
|
||||
-clang-analyzer-core.CallAndMessage,
|
||||
-clang-analyzer-core.NullDereference,
|
||||
-clang-analyzer-core.UndefinedBinaryOperatorResult,
|
||||
-clang-analyzer-core.uninitialized.Assign,
|
||||
-clang-analyzer-core.VLASize,
|
||||
-clang-analyzer-cplusplus.NewDelete,
|
||||
-clang-analyzer-cplusplus.NewDeleteLeaks,
|
||||
-clang-analyzer-deadcode.DeadStores,
|
||||
-clang-analyzer-optin.cplusplus.VirtualCall,
|
||||
-clang-analyzer-optin.performance.Padding,
|
||||
-clang-analyzer-security.FloatLoopCounter,
|
||||
-clang-analyzer-security.insecureAPI.strcpy,
|
||||
-clang-analyzer-unix.API,
|
||||
-clang-analyzer-unix.cstring.BadSizeArg,
|
||||
-clang-analyzer-unix.Malloc,
|
||||
-clang-analyzer-unix.MallocSizeof,
|
||||
-cppcoreguidelines-c-copy-assignment-signature,
|
||||
-cppcoreguidelines-interfaces-global-init,
|
||||
-cppcoreguidelines-no-malloc,
|
||||
-cppcoreguidelines-owning-memory,
|
||||
-cppcoreguidelines-pro-bounds-array-to-pointer-decay,
|
||||
-cppcoreguidelines-pro-bounds-constant-array-index,
|
||||
-cppcoreguidelines-pro-bounds-pointer-arithmetic,
|
||||
-cppcoreguidelines-pro-type-const-cast,
|
||||
-cppcoreguidelines-pro-type-cstyle-cast,
|
||||
-cppcoreguidelines-pro-type-member-init,
|
||||
-cppcoreguidelines-pro-type-reinterpret-cast,
|
||||
-cppcoreguidelines-pro-type-union-access,
|
||||
-cppcoreguidelines-pro-type-vararg,
|
||||
-cppcoreguidelines-special-member-functions,
|
||||
-fuchsia-default-arguments,
|
||||
-fuchsia-overloaded-operator,
|
||||
-google-build-using-namespace,
|
||||
-google-explicit-constructor,
|
||||
-google-global-names-in-headers,
|
||||
-google-readability-braces-around-statements,
|
||||
-google-readability-casting,
|
||||
-google-readability-function-size,
|
||||
-google-readability-namespace-comments,
|
||||
-google-readability-todo,
|
||||
-google-runtime-int,
|
||||
-google-runtime-references,
|
||||
-hicpp-braces-around-statements,
|
||||
-hicpp-deprecated-headers,
|
||||
-hicpp-explicit-conversions,
|
||||
-hicpp-function-size,
|
||||
-hicpp-member-init,
|
||||
-hicpp-no-array-decay,
|
||||
-hicpp-no-assembler,
|
||||
-hicpp-no-malloc,
|
||||
-hicpp-signed-bitwise,
|
||||
-hicpp-special-member-functions,
|
||||
-hicpp-use-auto,
|
||||
-hicpp-use-equals-default,
|
||||
-hicpp-use-equals-delete,
|
||||
-hicpp-use-override,
|
||||
-hicpp-vararg,
|
||||
-llvm-header-guard,
|
||||
-llvm-include-order,
|
||||
-llvm-namespace-comment,
|
||||
-misc-incorrect-roundings,
|
||||
-misc-macro-parentheses,
|
||||
-misc-misplaced-widening-cast,
|
||||
-misc-redundant-expression,
|
||||
-misc-unconventional-assign-operator,
|
||||
-misc-unused-parameters,
|
||||
-modernize-deprecated-headers,
|
||||
-modernize-loop-convert,
|
||||
-modernize-pass-by-value,
|
||||
-modernize-return-braced-init-list,
|
||||
-modernize-use-auto,
|
||||
-modernize-use-bool-literals,
|
||||
-modernize-use-default-member-init,
|
||||
-modernize-use-emplace,
|
||||
-modernize-use-equals-default,
|
||||
-modernize-use-equals-delete,
|
||||
-modernize-use-override,
|
||||
-modernize-use-using,
|
||||
-performance-inefficient-string-concatenation,
|
||||
-performance-unnecessary-value-param,
|
||||
-readability-avoid-const-params-in-decls,
|
||||
-readability-braces-around-statements,
|
||||
-readability-container-size-empty,
|
||||
-readability-delete-null-pointer,
|
||||
-readability-else-after-return,
|
||||
-readability-function-size,
|
||||
-readability-implicit-bool-cast,
|
||||
-readability-implicit-bool-conversion,
|
||||
-readability-inconsistent-declaration-parameter-name,
|
||||
-readability-named-parameter,
|
||||
-readability-non-const-parameter,
|
||||
-readability-redundant-control-flow,
|
||||
-readability-redundant-declaration,
|
||||
-readability-redundant-member-init,
|
||||
-readability-simplify-boolean-expr,
|
||||
-readability-static-accessed-through-instance,
|
||||
-readability-static-definition-in-anonymous-namespace,
|
||||
'
|
||||
WarningsAsErrors: '*'
|
||||
CheckOptions:
|
||||
- key: google-readability-braces-around-statements.ShortStatementLines
|
||||
value: '1'
|
||||
- key: google-readability-function-size.BranchThreshold
|
||||
value: '600'
|
||||
- key: google-readability-function-size.LineThreshold
|
||||
value: '4000'
|
||||
- key: google-readability-function-size.StatementThreshold
|
||||
value: '4000'
|
||||
...
|
||||
@@ -38,8 +38,10 @@ if(${PX4_PLATFORM} MATCHES "NuttX")
|
||||
add_compile_options(-DARM_MATH_DSP)
|
||||
endif()
|
||||
|
||||
# Disable 32-bit assembly warnings on apple silicon. Triggered by unused code only.
|
||||
if(${PX4_PLATFORM} MATCHES "posix" AND APPLE AND ${CMAKE_HOST_SYSTEM_PROCESSOR} MATCHES "arm64")
|
||||
# Disable 32-bit assembly warnings on arm64 platforms (Apple Silicon, Linux aarch64).
|
||||
# CMSIS DSP contains ARM Cortex-M assembly that triggers clang warnings on 64-bit ARM.
|
||||
# This code is unused on POSIX platforms - only the C fallback implementations run.
|
||||
if(${PX4_PLATFORM} MATCHES "posix" AND ${CMAKE_HOST_SYSTEM_PROCESSOR} MATCHES "arm64|aarch64")
|
||||
add_compile_options(-Wno-asm-operand-widths)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -60,3 +60,5 @@ px4_add_module(
|
||||
version
|
||||
component_general_json # for checksums.h
|
||||
)
|
||||
|
||||
px4_add_unit_gtest(SRC ULogMessagesTest.cpp)
|
||||
|
||||
@@ -0,0 +1,666 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2025 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include "messages.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Header & constants
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
TEST(ULogMessages, HeaderLen)
|
||||
{
|
||||
EXPECT_EQ(ULOG_MSG_HEADER_LEN, 3u);
|
||||
}
|
||||
|
||||
TEST(ULogMessages, MessageHeaderSize)
|
||||
{
|
||||
EXPECT_EQ(sizeof(ulog_message_header_s), 3u);
|
||||
}
|
||||
|
||||
TEST(ULogMessages, MessageHeaderFieldOffsets)
|
||||
{
|
||||
ulog_message_header_s msg = {};
|
||||
uint8_t *base = reinterpret_cast<uint8_t *>(&msg);
|
||||
|
||||
EXPECT_EQ(reinterpret_cast<uint8_t *>(&msg.msg_size) - base, 0);
|
||||
EXPECT_EQ(reinterpret_cast<uint8_t *>(&msg.msg_type) - base, 2);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// File header (16 bytes: 8 magic + 8 timestamp)
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
TEST(ULogMessages, FileHeaderSize)
|
||||
{
|
||||
EXPECT_EQ(sizeof(ulog_file_header_s), 16u);
|
||||
}
|
||||
|
||||
TEST(ULogMessages, FileHeaderMagic)
|
||||
{
|
||||
ulog_file_header_s hdr = {};
|
||||
const uint8_t expected_magic[] = {'U', 'L', 'o', 'g', 0x01, 0x12, 0x35, 0x01};
|
||||
|
||||
memcpy(hdr.magic, expected_magic, sizeof(expected_magic));
|
||||
hdr.timestamp = 1000000ULL;
|
||||
|
||||
EXPECT_EQ(memcmp(hdr.magic, expected_magic, 7), 0);
|
||||
EXPECT_EQ(hdr.magic[7], 0x01);
|
||||
EXPECT_EQ(hdr.timestamp, 1000000ULL);
|
||||
}
|
||||
|
||||
TEST(ULogMessages, FileHeaderFieldOffsets)
|
||||
{
|
||||
ulog_file_header_s hdr = {};
|
||||
uint8_t *base = reinterpret_cast<uint8_t *>(&hdr);
|
||||
|
||||
EXPECT_EQ(reinterpret_cast<uint8_t *>(&hdr.magic) - base, 0);
|
||||
EXPECT_EQ(reinterpret_cast<uint8_t *>(&hdr.timestamp) - base, 8);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Flag Bits ('B') — must be first message after header
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
TEST(ULogMessages, FlagBitsSize)
|
||||
{
|
||||
// payload: 8 compat + 8 incompat + 24 appended_offsets = 40
|
||||
EXPECT_EQ(sizeof(ulog_message_flag_bits_s), ULOG_MSG_HEADER_LEN + 40u);
|
||||
}
|
||||
|
||||
TEST(ULogMessages, FlagBitsTypeCode)
|
||||
{
|
||||
ulog_message_flag_bits_s msg = {};
|
||||
EXPECT_EQ(msg.msg_type, static_cast<uint8_t>('B'));
|
||||
}
|
||||
|
||||
TEST(ULogMessages, FlagBitsFieldOffsets)
|
||||
{
|
||||
ulog_message_flag_bits_s msg = {};
|
||||
uint8_t *base = reinterpret_cast<uint8_t *>(&msg);
|
||||
|
||||
EXPECT_EQ(reinterpret_cast<uint8_t *>(&msg.compat_flags) - base, ULOG_MSG_HEADER_LEN);
|
||||
EXPECT_EQ(reinterpret_cast<uint8_t *>(&msg.incompat_flags) - base, ULOG_MSG_HEADER_LEN + 8);
|
||||
EXPECT_EQ(reinterpret_cast<uint8_t *>(&msg.appended_offsets) - base, ULOG_MSG_HEADER_LEN + 16);
|
||||
}
|
||||
|
||||
TEST(ULogMessages, FlagBitsDataAppendedMask)
|
||||
{
|
||||
EXPECT_EQ(ULOG_INCOMPAT_FLAG0_DATA_APPENDED_MASK, 1 << 0);
|
||||
EXPECT_EQ(ULOG_COMPAT_FLAG0_DEFAULT_PARAMETERS_MASK, 1 << 0);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Format Definition ('F')
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
TEST(ULogMessages, FormatSize)
|
||||
{
|
||||
EXPECT_EQ(sizeof(ulog_message_format_s), ULOG_MSG_HEADER_LEN + 1600u);
|
||||
}
|
||||
|
||||
TEST(ULogMessages, FormatTypeCode)
|
||||
{
|
||||
ulog_message_format_s msg = {};
|
||||
EXPECT_EQ(msg.msg_type, static_cast<uint8_t>('F'));
|
||||
}
|
||||
|
||||
TEST(ULogMessages, FormatSerialization)
|
||||
{
|
||||
ulog_message_format_s msg = {};
|
||||
const char *format_str = "test_topic:uint64_t timestamp;float value;";
|
||||
size_t len = strlen(format_str);
|
||||
|
||||
strncpy(msg.format, format_str, sizeof(msg.format));
|
||||
msg.msg_size = len;
|
||||
|
||||
EXPECT_EQ(msg.msg_size, len);
|
||||
EXPECT_EQ(memcmp(msg.format, format_str, len), 0);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Information ('I')
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
TEST(ULogMessages, InfoSize)
|
||||
{
|
||||
// header(3) + key_len(1) + key_value_str(255) = 259
|
||||
EXPECT_EQ(sizeof(ulog_message_info_s), ULOG_MSG_HEADER_LEN + 1u + 255u);
|
||||
}
|
||||
|
||||
TEST(ULogMessages, InfoTypeCode)
|
||||
{
|
||||
ulog_message_info_s msg = {};
|
||||
EXPECT_EQ(msg.msg_type, static_cast<uint8_t>('I'));
|
||||
}
|
||||
|
||||
TEST(ULogMessages, InfoStringLayout)
|
||||
{
|
||||
const char *name = "hello";
|
||||
const char *value = "world";
|
||||
const size_t vlen = strlen(value);
|
||||
|
||||
ulog_message_info_s msg = {};
|
||||
uint8_t *buffer = reinterpret_cast<uint8_t *>(&msg);
|
||||
msg.msg_type = static_cast<uint8_t>(ULogMessageType::INFO);
|
||||
|
||||
msg.key_len = snprintf(msg.key_value_str, sizeof(msg.key_value_str),
|
||||
"char[%zu] %s", vlen, name);
|
||||
size_t msg_size = sizeof(msg) - sizeof(msg.key_value_str) + msg.key_len;
|
||||
|
||||
ASSERT_LT(vlen, sizeof(msg) - msg_size);
|
||||
memcpy(&buffer[msg_size], value, vlen);
|
||||
msg_size += vlen;
|
||||
|
||||
msg.msg_size = msg_size - ULOG_MSG_HEADER_LEN;
|
||||
|
||||
// msg_size == key_len_field(1) + key_len + vlen
|
||||
EXPECT_EQ(msg.msg_size, msg.key_len + vlen + 1);
|
||||
|
||||
const char expected_key[] = "char[5] hello";
|
||||
EXPECT_EQ(msg.key_len, strlen(expected_key));
|
||||
|
||||
const size_t header_size = sizeof(msg) - sizeof(msg.key_value_str);
|
||||
const uint8_t *value_start = &buffer[header_size + msg.key_len];
|
||||
EXPECT_EQ(memcmp(value_start, "world", vlen), 0);
|
||||
|
||||
// no null terminator in msg_size
|
||||
EXPECT_EQ(msg_size, header_size + msg.key_len + vlen);
|
||||
}
|
||||
|
||||
TEST(ULogMessages, InfoInt32Layout)
|
||||
{
|
||||
const char *name = "sys_param";
|
||||
int32_t value = 42;
|
||||
|
||||
ulog_message_info_s msg = {};
|
||||
uint8_t *buffer = reinterpret_cast<uint8_t *>(&msg);
|
||||
msg.msg_type = static_cast<uint8_t>(ULogMessageType::INFO);
|
||||
|
||||
msg.key_len = snprintf(msg.key_value_str, sizeof(msg.key_value_str),
|
||||
"int32_t %s", name);
|
||||
size_t msg_size = sizeof(msg) - sizeof(msg.key_value_str) + msg.key_len;
|
||||
|
||||
ASSERT_LE(sizeof(value), sizeof(msg) - msg_size);
|
||||
memcpy(&buffer[msg_size], &value, sizeof(value));
|
||||
msg_size += sizeof(value);
|
||||
|
||||
msg.msg_size = msg_size - ULOG_MSG_HEADER_LEN;
|
||||
|
||||
EXPECT_EQ(msg.msg_size, msg.key_len + sizeof(int32_t) + 1);
|
||||
|
||||
const char expected_key[] = "int32_t sys_param";
|
||||
EXPECT_EQ(msg.key_len, strlen(expected_key));
|
||||
|
||||
const size_t header_size = sizeof(msg) - sizeof(msg.key_value_str);
|
||||
int32_t read_back = 0;
|
||||
memcpy(&read_back, &buffer[header_size + msg.key_len], sizeof(int32_t));
|
||||
EXPECT_EQ(read_back, 42);
|
||||
}
|
||||
|
||||
TEST(ULogMessages, InfoFloatLayout)
|
||||
{
|
||||
const char *name = "cal_offset";
|
||||
float value = 3.14f;
|
||||
|
||||
ulog_message_info_s msg = {};
|
||||
uint8_t *buffer = reinterpret_cast<uint8_t *>(&msg);
|
||||
msg.msg_type = static_cast<uint8_t>(ULogMessageType::INFO);
|
||||
|
||||
msg.key_len = snprintf(msg.key_value_str, sizeof(msg.key_value_str),
|
||||
"float %s", name);
|
||||
size_t msg_size = sizeof(msg) - sizeof(msg.key_value_str) + msg.key_len;
|
||||
|
||||
ASSERT_LE(sizeof(value), sizeof(msg) - msg_size);
|
||||
memcpy(&buffer[msg_size], &value, sizeof(value));
|
||||
msg_size += sizeof(value);
|
||||
|
||||
msg.msg_size = msg_size - ULOG_MSG_HEADER_LEN;
|
||||
|
||||
EXPECT_EQ(msg.msg_size, msg.key_len + sizeof(float) + 1);
|
||||
|
||||
const size_t header_size = sizeof(msg) - sizeof(msg.key_value_str);
|
||||
float read_back = 0.f;
|
||||
memcpy(&read_back, &buffer[header_size + msg.key_len], sizeof(float));
|
||||
EXPECT_FLOAT_EQ(read_back, 3.14f);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Information Multiple ('M')
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
TEST(ULogMessages, InfoMultipleSize)
|
||||
{
|
||||
// header(3) + is_continued(1) + key_len(1) + key_value_str(1200) = 1205
|
||||
EXPECT_EQ(sizeof(ulog_message_info_multiple_s), ULOG_MSG_HEADER_LEN + 1u + 1u + 1200u);
|
||||
}
|
||||
|
||||
TEST(ULogMessages, InfoMultipleTypeCode)
|
||||
{
|
||||
ulog_message_info_multiple_s msg = {};
|
||||
EXPECT_EQ(msg.msg_type, static_cast<uint8_t>('M'));
|
||||
}
|
||||
|
||||
TEST(ULogMessages, InfoMultipleStringLayout)
|
||||
{
|
||||
const char *name = "ver";
|
||||
const char *value = "1.0";
|
||||
const size_t vlen = strlen(value);
|
||||
|
||||
ulog_message_info_multiple_s msg = {};
|
||||
uint8_t *buffer = reinterpret_cast<uint8_t *>(&msg);
|
||||
msg.msg_type = static_cast<uint8_t>(ULogMessageType::INFO_MULTIPLE);
|
||||
msg.is_continued = false;
|
||||
|
||||
msg.key_len = snprintf(msg.key_value_str, sizeof(msg.key_value_str),
|
||||
"char[%zu] %s", vlen, name);
|
||||
size_t msg_size = sizeof(msg) - sizeof(msg.key_value_str) + msg.key_len;
|
||||
|
||||
ASSERT_LT(vlen, sizeof(msg) - msg_size);
|
||||
memcpy(&buffer[msg_size], value, vlen);
|
||||
msg_size += vlen;
|
||||
|
||||
msg.msg_size = msg_size - ULOG_MSG_HEADER_LEN;
|
||||
|
||||
const size_t header_size = sizeof(msg) - sizeof(msg.key_value_str);
|
||||
EXPECT_EQ(msg.msg_size, msg_size - ULOG_MSG_HEADER_LEN);
|
||||
EXPECT_EQ(msg.is_continued, 0);
|
||||
|
||||
const char expected_key[] = "char[3] ver";
|
||||
EXPECT_EQ(msg.key_len, strlen(expected_key));
|
||||
|
||||
const uint8_t *value_start = &buffer[header_size + msg.key_len];
|
||||
EXPECT_EQ(memcmp(value_start, "1.0", vlen), 0);
|
||||
|
||||
EXPECT_EQ(msg_size, header_size + msg.key_len + vlen);
|
||||
}
|
||||
|
||||
TEST(ULogMessages, InfoMultipleContinuation)
|
||||
{
|
||||
ulog_message_info_multiple_s msg = {};
|
||||
msg.is_continued = 1;
|
||||
|
||||
EXPECT_EQ(msg.is_continued, 1);
|
||||
EXPECT_EQ(msg.msg_type, static_cast<uint8_t>('M'));
|
||||
}
|
||||
|
||||
TEST(ULogMessages, InfoMultipleFieldOffsets)
|
||||
{
|
||||
ulog_message_info_multiple_s msg = {};
|
||||
uint8_t *base = reinterpret_cast<uint8_t *>(&msg);
|
||||
|
||||
EXPECT_EQ(reinterpret_cast<uint8_t *>(&msg.is_continued) - base, ULOG_MSG_HEADER_LEN);
|
||||
EXPECT_EQ(reinterpret_cast<uint8_t *>(&msg.key_len) - base, ULOG_MSG_HEADER_LEN + 1);
|
||||
EXPECT_EQ(reinterpret_cast<uint8_t *>(&msg.key_value_str) - base, ULOG_MSG_HEADER_LEN + 2);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Parameter ('P')
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
TEST(ULogMessages, ParameterSize)
|
||||
{
|
||||
EXPECT_EQ(sizeof(ulog_message_parameter_s), ULOG_MSG_HEADER_LEN + 1u + 255u);
|
||||
}
|
||||
|
||||
TEST(ULogMessages, ParameterTypeCode)
|
||||
{
|
||||
ulog_message_parameter_s msg = {};
|
||||
EXPECT_EQ(msg.msg_type, static_cast<uint8_t>('P'));
|
||||
}
|
||||
|
||||
TEST(ULogMessages, ParameterInt32Layout)
|
||||
{
|
||||
const char *name = "SYS_AUTOSTART";
|
||||
int32_t value = 4001;
|
||||
|
||||
ulog_message_parameter_s msg = {};
|
||||
uint8_t *buffer = reinterpret_cast<uint8_t *>(&msg);
|
||||
|
||||
msg.key_len = snprintf(msg.key_value_str, sizeof(msg.key_value_str),
|
||||
"int32_t %s", name);
|
||||
size_t msg_size = sizeof(msg) - sizeof(msg.key_value_str) + msg.key_len;
|
||||
|
||||
memcpy(&buffer[msg_size], &value, sizeof(value));
|
||||
msg_size += sizeof(value);
|
||||
|
||||
msg.msg_size = msg_size - ULOG_MSG_HEADER_LEN;
|
||||
|
||||
EXPECT_EQ(msg.msg_size, msg.key_len + sizeof(int32_t) + 1);
|
||||
|
||||
const size_t header_size = sizeof(msg) - sizeof(msg.key_value_str);
|
||||
int32_t read_back = 0;
|
||||
memcpy(&read_back, &buffer[header_size + msg.key_len], sizeof(int32_t));
|
||||
EXPECT_EQ(read_back, 4001);
|
||||
}
|
||||
|
||||
TEST(ULogMessages, ParameterFloatLayout)
|
||||
{
|
||||
const char *name = "MC_PITCHRATE_P";
|
||||
float value = 0.15f;
|
||||
|
||||
ulog_message_parameter_s msg = {};
|
||||
uint8_t *buffer = reinterpret_cast<uint8_t *>(&msg);
|
||||
|
||||
msg.key_len = snprintf(msg.key_value_str, sizeof(msg.key_value_str),
|
||||
"float %s", name);
|
||||
size_t msg_size = sizeof(msg) - sizeof(msg.key_value_str) + msg.key_len;
|
||||
|
||||
memcpy(&buffer[msg_size], &value, sizeof(value));
|
||||
msg_size += sizeof(value);
|
||||
|
||||
msg.msg_size = msg_size - ULOG_MSG_HEADER_LEN;
|
||||
|
||||
const size_t header_size = sizeof(msg) - sizeof(msg.key_value_str);
|
||||
float read_back = 0.f;
|
||||
memcpy(&read_back, &buffer[header_size + msg.key_len], sizeof(float));
|
||||
EXPECT_FLOAT_EQ(read_back, 0.15f);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Default Parameter ('Q')
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
TEST(ULogMessages, ParameterDefaultSize)
|
||||
{
|
||||
// header(3) + default_types(1) + key_len(1) + key_value_str(255) = 260
|
||||
EXPECT_EQ(sizeof(ulog_message_parameter_default_s), ULOG_MSG_HEADER_LEN + 1u + 1u + 255u);
|
||||
}
|
||||
|
||||
TEST(ULogMessages, ParameterDefaultTypeCode)
|
||||
{
|
||||
ulog_message_parameter_default_s msg = {};
|
||||
EXPECT_EQ(msg.msg_type, static_cast<uint8_t>('Q'));
|
||||
}
|
||||
|
||||
TEST(ULogMessages, ParameterDefaultTypeBits)
|
||||
{
|
||||
EXPECT_EQ(static_cast<uint8_t>(ulog_parameter_default_type_t::system), 1 << 0);
|
||||
EXPECT_EQ(static_cast<uint8_t>(ulog_parameter_default_type_t::current_setup), 1 << 1);
|
||||
|
||||
auto combined = ulog_parameter_default_type_t::system | ulog_parameter_default_type_t::current_setup;
|
||||
EXPECT_EQ(static_cast<uint8_t>(combined), 0x03);
|
||||
}
|
||||
|
||||
TEST(ULogMessages, ParameterDefaultFieldOffsets)
|
||||
{
|
||||
ulog_message_parameter_default_s msg = {};
|
||||
uint8_t *base = reinterpret_cast<uint8_t *>(&msg);
|
||||
|
||||
EXPECT_EQ(reinterpret_cast<uint8_t *>(&msg.default_types) - base, ULOG_MSG_HEADER_LEN);
|
||||
EXPECT_EQ(reinterpret_cast<uint8_t *>(&msg.key_len) - base, ULOG_MSG_HEADER_LEN + 1);
|
||||
EXPECT_EQ(reinterpret_cast<uint8_t *>(&msg.key_value_str) - base, ULOG_MSG_HEADER_LEN + 2);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Subscription ('A')
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
TEST(ULogMessages, AddLoggedSize)
|
||||
{
|
||||
// header(3) + multi_id(1) + msg_id(2) + message_name(255) = 261
|
||||
EXPECT_EQ(sizeof(ulog_message_add_logged_s), ULOG_MSG_HEADER_LEN + 1u + 2u + 255u);
|
||||
}
|
||||
|
||||
TEST(ULogMessages, AddLoggedTypeCode)
|
||||
{
|
||||
ulog_message_add_logged_s msg = {};
|
||||
EXPECT_EQ(msg.msg_type, static_cast<uint8_t>('A'));
|
||||
}
|
||||
|
||||
TEST(ULogMessages, AddLoggedFieldOffsets)
|
||||
{
|
||||
ulog_message_add_logged_s msg = {};
|
||||
uint8_t *base = reinterpret_cast<uint8_t *>(&msg);
|
||||
|
||||
EXPECT_EQ(reinterpret_cast<uint8_t *>(&msg.multi_id) - base, ULOG_MSG_HEADER_LEN);
|
||||
EXPECT_EQ(reinterpret_cast<uint8_t *>(&msg.msg_id) - base, ULOG_MSG_HEADER_LEN + 1);
|
||||
EXPECT_EQ(reinterpret_cast<uint8_t *>(&msg.message_name) - base, ULOG_MSG_HEADER_LEN + 3);
|
||||
}
|
||||
|
||||
TEST(ULogMessages, AddLoggedSerialization)
|
||||
{
|
||||
ulog_message_add_logged_s msg = {};
|
||||
msg.multi_id = 0;
|
||||
msg.msg_id = 7;
|
||||
const char *topic = "sensor_accel";
|
||||
size_t len = strlen(topic);
|
||||
|
||||
strncpy(msg.message_name, topic, sizeof(msg.message_name));
|
||||
msg.msg_size = sizeof(msg.multi_id) + sizeof(msg.msg_id) + len;
|
||||
|
||||
EXPECT_EQ(msg.multi_id, 0);
|
||||
EXPECT_EQ(msg.msg_id, 7);
|
||||
EXPECT_EQ(memcmp(msg.message_name, "sensor_accel", len), 0);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Unsubscription ('R')
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
TEST(ULogMessages, RemoveLoggedSize)
|
||||
{
|
||||
// header(3) + msg_id(2) = 5
|
||||
EXPECT_EQ(sizeof(ulog_message_remove_logged_s), ULOG_MSG_HEADER_LEN + 2u);
|
||||
}
|
||||
|
||||
TEST(ULogMessages, RemoveLoggedTypeCode)
|
||||
{
|
||||
ulog_message_remove_logged_s msg = {};
|
||||
EXPECT_EQ(msg.msg_type, static_cast<uint8_t>('R'));
|
||||
}
|
||||
|
||||
TEST(ULogMessages, RemoveLoggedSerialization)
|
||||
{
|
||||
ulog_message_remove_logged_s msg = {};
|
||||
msg.msg_id = 42;
|
||||
msg.msg_size = sizeof(msg.msg_id);
|
||||
|
||||
EXPECT_EQ(msg.msg_id, 42);
|
||||
EXPECT_EQ(msg.msg_size, 2);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Logged Data ('D')
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
TEST(ULogMessages, DataSize)
|
||||
{
|
||||
// header(3) + msg_id(2) = 5 (variable-length payload follows)
|
||||
EXPECT_EQ(sizeof(ulog_message_data_s), ULOG_MSG_HEADER_LEN + 2u);
|
||||
}
|
||||
|
||||
TEST(ULogMessages, DataTypeCode)
|
||||
{
|
||||
ulog_message_data_s msg = {};
|
||||
EXPECT_EQ(msg.msg_type, static_cast<uint8_t>('D'));
|
||||
}
|
||||
|
||||
TEST(ULogMessages, DataFieldOffset)
|
||||
{
|
||||
ulog_message_data_s msg = {};
|
||||
uint8_t *base = reinterpret_cast<uint8_t *>(&msg);
|
||||
|
||||
EXPECT_EQ(reinterpret_cast<uint8_t *>(&msg.msg_id) - base, ULOG_MSG_HEADER_LEN);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Logging ('L')
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
TEST(ULogMessages, LoggingSize)
|
||||
{
|
||||
// header(3) + log_level(1) + timestamp(8) + message(128) = 140
|
||||
EXPECT_EQ(sizeof(ulog_message_logging_s), ULOG_MSG_HEADER_LEN + 1u + 8u + 128u);
|
||||
}
|
||||
|
||||
TEST(ULogMessages, LoggingTypeCode)
|
||||
{
|
||||
ulog_message_logging_s msg = {};
|
||||
EXPECT_EQ(msg.msg_type, static_cast<uint8_t>('L'));
|
||||
}
|
||||
|
||||
TEST(ULogMessages, LoggingFieldOffsets)
|
||||
{
|
||||
ulog_message_logging_s msg = {};
|
||||
uint8_t *base = reinterpret_cast<uint8_t *>(&msg);
|
||||
|
||||
EXPECT_EQ(reinterpret_cast<uint8_t *>(&msg.log_level) - base, ULOG_MSG_HEADER_LEN);
|
||||
EXPECT_EQ(reinterpret_cast<uint8_t *>(&msg.timestamp) - base, ULOG_MSG_HEADER_LEN + 1);
|
||||
EXPECT_EQ(reinterpret_cast<uint8_t *>(&msg.message) - base, ULOG_MSG_HEADER_LEN + 9);
|
||||
}
|
||||
|
||||
TEST(ULogMessages, LoggingSerialization)
|
||||
{
|
||||
ulog_message_logging_s msg = {};
|
||||
msg.log_level = 6;
|
||||
msg.timestamp = 5000000ULL;
|
||||
const char *text = "test message";
|
||||
size_t len = strlen(text);
|
||||
|
||||
strncpy(msg.message, text, sizeof(msg.message));
|
||||
msg.msg_size = sizeof(msg.log_level) + sizeof(msg.timestamp) + len;
|
||||
|
||||
EXPECT_EQ(msg.log_level, 6);
|
||||
EXPECT_EQ(msg.timestamp, 5000000ULL);
|
||||
EXPECT_EQ(memcmp(msg.message, "test message", len), 0);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Logging Tagged ('C')
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
TEST(ULogMessages, LoggingTaggedSize)
|
||||
{
|
||||
// header(3) + log_level(1) + tag(2) + timestamp(8) + message(128) = 142
|
||||
EXPECT_EQ(sizeof(ulog_message_logging_tagged_s), ULOG_MSG_HEADER_LEN + 1u + 2u + 8u + 128u);
|
||||
}
|
||||
|
||||
TEST(ULogMessages, LoggingTaggedTypeCode)
|
||||
{
|
||||
ulog_message_logging_tagged_s msg = {};
|
||||
EXPECT_EQ(msg.msg_type, static_cast<uint8_t>('C'));
|
||||
}
|
||||
|
||||
TEST(ULogMessages, LoggingTaggedFieldOffsets)
|
||||
{
|
||||
ulog_message_logging_tagged_s msg = {};
|
||||
uint8_t *base = reinterpret_cast<uint8_t *>(&msg);
|
||||
|
||||
EXPECT_EQ(reinterpret_cast<uint8_t *>(&msg.log_level) - base, ULOG_MSG_HEADER_LEN);
|
||||
EXPECT_EQ(reinterpret_cast<uint8_t *>(&msg.tag) - base, ULOG_MSG_HEADER_LEN + 1);
|
||||
EXPECT_EQ(reinterpret_cast<uint8_t *>(&msg.timestamp) - base, ULOG_MSG_HEADER_LEN + 3);
|
||||
EXPECT_EQ(reinterpret_cast<uint8_t *>(&msg.message) - base, ULOG_MSG_HEADER_LEN + 11);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Sync ('S')
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
TEST(ULogMessages, SyncSize)
|
||||
{
|
||||
// header(3) + sync_magic(8) = 11
|
||||
EXPECT_EQ(sizeof(ulog_message_sync_s), ULOG_MSG_HEADER_LEN + 8u);
|
||||
}
|
||||
|
||||
TEST(ULogMessages, SyncTypeCode)
|
||||
{
|
||||
ulog_message_sync_s msg = {};
|
||||
EXPECT_EQ(msg.msg_type, static_cast<uint8_t>('S'));
|
||||
}
|
||||
|
||||
TEST(ULogMessages, SyncMagicBytes)
|
||||
{
|
||||
ulog_message_sync_s msg = {};
|
||||
const uint8_t expected_magic[] = {0x2F, 0x73, 0x13, 0x20, 0x25, 0x0C, 0xBB, 0x12};
|
||||
|
||||
memcpy(msg.sync_magic, expected_magic, sizeof(expected_magic));
|
||||
msg.msg_size = sizeof(msg.sync_magic);
|
||||
|
||||
EXPECT_EQ(memcmp(msg.sync_magic, expected_magic, 8), 0);
|
||||
EXPECT_EQ(msg.msg_size, 8);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Dropout ('O')
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
TEST(ULogMessages, DropoutSize)
|
||||
{
|
||||
// header(3) + duration(2) = 5
|
||||
EXPECT_EQ(sizeof(ulog_message_dropout_s), ULOG_MSG_HEADER_LEN + 2u);
|
||||
}
|
||||
|
||||
TEST(ULogMessages, DropoutTypeCode)
|
||||
{
|
||||
ulog_message_dropout_s msg = {};
|
||||
EXPECT_EQ(msg.msg_type, static_cast<uint8_t>('O'));
|
||||
}
|
||||
|
||||
TEST(ULogMessages, DropoutDefaultMsgSize)
|
||||
{
|
||||
ulog_message_dropout_s msg = {};
|
||||
EXPECT_EQ(msg.msg_size, sizeof(uint16_t));
|
||||
}
|
||||
|
||||
TEST(ULogMessages, DropoutSerialization)
|
||||
{
|
||||
ulog_message_dropout_s msg = {};
|
||||
msg.duration = 150;
|
||||
|
||||
EXPECT_EQ(msg.duration, 150);
|
||||
EXPECT_EQ(msg.msg_size, sizeof(uint16_t));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ULogMessageType enum values
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
TEST(ULogMessages, TypeEnumValues)
|
||||
{
|
||||
EXPECT_EQ(static_cast<uint8_t>(ULogMessageType::FORMAT), 'F');
|
||||
EXPECT_EQ(static_cast<uint8_t>(ULogMessageType::DATA), 'D');
|
||||
EXPECT_EQ(static_cast<uint8_t>(ULogMessageType::INFO), 'I');
|
||||
EXPECT_EQ(static_cast<uint8_t>(ULogMessageType::INFO_MULTIPLE), 'M');
|
||||
EXPECT_EQ(static_cast<uint8_t>(ULogMessageType::PARAMETER), 'P');
|
||||
EXPECT_EQ(static_cast<uint8_t>(ULogMessageType::PARAMETER_DEFAULT), 'Q');
|
||||
EXPECT_EQ(static_cast<uint8_t>(ULogMessageType::ADD_LOGGED_MSG), 'A');
|
||||
EXPECT_EQ(static_cast<uint8_t>(ULogMessageType::REMOVE_LOGGED_MSG), 'R');
|
||||
EXPECT_EQ(static_cast<uint8_t>(ULogMessageType::SYNC), 'S');
|
||||
EXPECT_EQ(static_cast<uint8_t>(ULogMessageType::DROPOUT), 'O');
|
||||
EXPECT_EQ(static_cast<uint8_t>(ULogMessageType::LOGGING), 'L');
|
||||
EXPECT_EQ(static_cast<uint8_t>(ULogMessageType::LOGGING_TAGGED), 'C');
|
||||
EXPECT_EQ(static_cast<uint8_t>(ULogMessageType::FLAG_BITS), 'B');
|
||||
}
|
||||
@@ -1890,7 +1890,7 @@ void Logger::write_info(LogType type, const char *name, const char *value)
|
||||
|
||||
/* copy string value directly to buffer */
|
||||
if (vlen < (sizeof(msg) - msg_size)) {
|
||||
memcpy(&buffer[msg_size], value, vlen);
|
||||
memcpy(&buffer[msg_size], value, vlen + 1);
|
||||
msg_size += vlen;
|
||||
|
||||
msg.msg_size = msg_size - ULOG_MSG_HEADER_LEN;
|
||||
@@ -1916,7 +1916,7 @@ void Logger::write_info_multiple(LogType type, const char *name, const char *val
|
||||
|
||||
/* copy string value directly to buffer */
|
||||
if (vlen < (sizeof(msg) - msg_size)) {
|
||||
memcpy(&buffer[msg_size], value, vlen);
|
||||
memcpy(&buffer[msg_size], value, vlen + 1);
|
||||
msg_size += vlen;
|
||||
|
||||
msg.msg_size = msg_size - ULOG_MSG_HEADER_LEN;
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#include <lib/mathlib/mathlib.h>
|
||||
|
||||
using namespace time_literals;
|
||||
using namespace matrix;
|
||||
|
||||
bool GotoControl::checkForSetpoint(const hrt_abstime &now, const bool enabled)
|
||||
{
|
||||
@@ -64,10 +65,11 @@ bool GotoControl::checkForSetpoint(const hrt_abstime &now, const bool enabled)
|
||||
return need_to_run;
|
||||
}
|
||||
|
||||
void GotoControl::update(const float dt, const matrix::Vector3f &position, const float heading)
|
||||
void GotoControl::update(const float dt, const Vector3f &position, const Vector3f &velocity, const Vector3f &acceleration,
|
||||
const float heading)
|
||||
{
|
||||
if (!_is_initialized) {
|
||||
resetPositionSmoother(position);
|
||||
resetPositionSmoother(position, velocity, acceleration);
|
||||
resetHeadingSmoother(heading);
|
||||
_is_initialized = true;
|
||||
}
|
||||
@@ -87,7 +89,7 @@ void GotoControl::update(const float dt, const matrix::Vector3f &position, const
|
||||
}
|
||||
|
||||
if (_need_smoother_reset) {
|
||||
resetPositionSmoother(position);
|
||||
resetPositionSmoother(position, velocity, acceleration);
|
||||
}
|
||||
|
||||
setPositionSmootherLimits(_goto_setpoint);
|
||||
@@ -138,7 +140,7 @@ void GotoControl::update(const float dt, const matrix::Vector3f &position, const
|
||||
_vehicle_constraints_pub.publish(vehicle_constraints);
|
||||
}
|
||||
|
||||
void GotoControl::resetPositionSmoother(const matrix::Vector3f &position)
|
||||
void GotoControl::resetPositionSmoother(const Vector3f &position, const Vector3f &velocity, const Vector3f &acceleration)
|
||||
{
|
||||
if (!position.isAllFinite()) {
|
||||
// TODO: error messaging
|
||||
@@ -146,9 +148,7 @@ void GotoControl::resetPositionSmoother(const matrix::Vector3f &position)
|
||||
return;
|
||||
}
|
||||
|
||||
const Vector3f initial_acceleration{};
|
||||
const Vector3f initial_velocity{};
|
||||
_position_smoothing.reset(initial_acceleration, initial_velocity, position);
|
||||
_position_smoothing.reset(acceleration, velocity, position);
|
||||
|
||||
_need_smoother_reset = false;
|
||||
}
|
||||
|
||||
@@ -64,9 +64,11 @@ public:
|
||||
/**
|
||||
* @brief resets the position smoother at the current position with zero velocity and acceleration.
|
||||
*
|
||||
* @param position [m] (NED) local vehicle position
|
||||
* @param position [m] vehicle position state NED local frame
|
||||
* @param velocity [m/s] vehicle velocity state
|
||||
* @param acceleration [m/s^2] vehicle acceleration state
|
||||
*/
|
||||
void resetPositionSmoother(const matrix::Vector3f &position);
|
||||
void resetPositionSmoother(const matrix::Vector3f &position, const matrix::Vector3f &velocity, const matrix::Vector3f &acceleration);
|
||||
|
||||
/**
|
||||
* @brief resets the heading smoother at the current heading with zero heading rate and acceleration.
|
||||
@@ -80,12 +82,15 @@ public:
|
||||
* loops to track.
|
||||
*
|
||||
* @param[in] dt [s] time since last control update
|
||||
* @param[in] position [m] (NED) local vehicle position
|
||||
* @param[in] position [m] vehicle position state NED local frame
|
||||
* @param[in] velocity [m/s] vehicle velocity state
|
||||
* @param[in] acceleration [m/s^2] vehicle acceleration state
|
||||
* @param[in] heading [rad] (from North) vehicle heading
|
||||
* @param[in] goto_setpoint struct containing current go-to setpoints
|
||||
* @param[out] trajectory_setpoint struct containing trajectory (tracking) setpoints
|
||||
*/
|
||||
void update(const float dt, const matrix::Vector3f &position, const float heading);
|
||||
void update(const float dt, const matrix::Vector3f &position, const matrix::Vector3f &velocity, const matrix::Vector3f &acceleration,
|
||||
const float heading);
|
||||
|
||||
// Setting all parameters from the outside saves 300bytes flash
|
||||
void setParamMpcAccHor(const float param_mpc_acc_hor) { _param_mpc_acc_hor = param_mpc_acc_hor; }
|
||||
|
||||
@@ -433,7 +433,7 @@ void MulticopterPositionControl::Run()
|
||||
&& !_trajectory_setpoint_sub.updated();
|
||||
|
||||
if (_goto_control.checkForSetpoint(vehicle_local_position.timestamp_sample, goto_setpoint_enable)) {
|
||||
_goto_control.update(dt, states.position, states.yaw);
|
||||
_goto_control.update(dt, states.position, states.velocity, states.acceleration, states.yaw);
|
||||
}
|
||||
|
||||
_trajectory_setpoint_sub.update(&_setpoint);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user