mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-06-06 06:20:05 +08:00
Compare commits
216 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 925c04d51a | |||
| 4880bd5d8c | |||
| 8f870a1346 | |||
| 9048a40277 | |||
| 9fb0ff0e80 | |||
| 7297364484 | |||
| 9e796daee8 | |||
| 17242bc1a4 | |||
| 8a9be9a8f0 | |||
| b346fcfa00 | |||
| 1d852907a2 | |||
| dd177ac8cf | |||
| 68b533f79f | |||
| 7daac63809 | |||
| 2ef5b0a20f | |||
| 2e2067173a | |||
| 93f06f6a23 | |||
| ca0dec5a33 | |||
| 790c2d3369 | |||
| 8478503349 | |||
| 6a18fd045f | |||
| 06942bbfcc | |||
| 89c4980e55 | |||
| e756574420 | |||
| df00901bfa | |||
| 918efc8f97 | |||
| 8602849847 | |||
| d564c5b4c2 | |||
| 245ae58264 | |||
| 996060f581 | |||
| a120773793 | |||
| 6cf8d80bdd | |||
| b4601278db | |||
| 0d66981dcc | |||
| 62f5f5267e | |||
| fd7edaa4fe | |||
| b343eb6a11 | |||
| b8877c4cfc | |||
| 64e996b475 | |||
| 1d45f699be | |||
| be126454c0 | |||
| ce3e62841f | |||
| 657854ae1b | |||
| 5613313107 | |||
| eafb6c396b | |||
| 2ebfd40bba | |||
| 368dd362c5 | |||
| 7332f264f0 | |||
| 06d6c31614 | |||
| d9448f3e99 | |||
| 50a42680d7 | |||
| 70a84a0c1b | |||
| 05de941399 | |||
| adc9a6d35d | |||
| fe91ace0bb | |||
| 977777f40a | |||
| 4afdf38378 | |||
| d0004403a3 | |||
| 2e651117e8 | |||
| 18c176beef | |||
| 602add3ec1 | |||
| 47d5971f42 | |||
| 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 | |||
| f518f87d0f | |||
| 6a123298e5 | |||
| a38b10c9d0 | |||
| d641cc3986 | |||
| 731d754a15 | |||
| 7edf21414e | |||
| ec278758ed | |||
| 53a14d10cd | |||
| d6c4dd22da | |||
| 4117912506 | |||
| e239c017d1 | |||
| 5f0e3f600f | |||
| 61da2505fe | |||
| 27d831fbcd | |||
| 71fbc63d67 | |||
| a6d50d02bc | |||
| c56bc4208d | |||
| 741892c30f | |||
| ad6ee2aadf | |||
| b3c05bf4da | |||
| 0134d7dd3b | |||
| 07d9167d66 | |||
| e945c91f88 | |||
| 8bb1e44c10 | |||
| 36b5e1e1bb | |||
| 01b348c86b | |||
| 907823f9c5 | |||
| d886db8aab | |||
| 1c929da8ba | |||
| 6362a44cc4 | |||
| 42b0061217 | |||
| caf9feba73 | |||
| f751974b41 | |||
| 3e1b7d4d0a | |||
| 6ef0e57eeb | |||
| 4c866fc9b2 | |||
| 93fd9d4bae | |||
| 2ec9937369 | |||
| 3c80be8e48 | |||
| 89b5a61f79 | |||
| 06bb7a6e1b | |||
| d63f47b5b3 | |||
| 61a67b3a09 | |||
| 0966e92e36 | |||
| 273d3cedac | |||
| 2290096e25 | |||
| 0efded2fa7 | |||
| 1c13f28121 | |||
| 94514bd811 | |||
| 85aa863c56 | |||
| 380ae3047d | |||
| ba72434fe4 | |||
| 60df456168 | |||
| f11ea548da | |||
| 3fdd3e3e43 | |||
| f50d8b258c | |||
| dfcde09899 | |||
| b3c27bc91b | |||
| c66584879c | |||
| 7aca05a531 | |||
| c032138a34 | |||
| bc75b5cc0d | |||
| b70da3968c | |||
| 853fa088de | |||
| e80abe4e29 | |||
| 593192df54 | |||
| 166e7a2fd7 | |||
| 57843adb48 | |||
| 7be82b08c4 | |||
| d530bd5a7f | |||
| b6ace98962 | |||
| 75e2a38a05 | |||
| f73ac7a257 | |||
| 1a46de3a25 | |||
| 239a7bc4f1 | |||
| c5c66ee261 | |||
| 87f1eb69b1 | |||
| 86c38ae384 | |||
| b43a842bc8 | |||
| d227cfc174 | |||
| 24ac02fbac | |||
| bc6cc5f82a | |||
| 90169b932b | |||
| 7f010c1430 | |||
| d018551047 | |||
| 509b4ba96d | |||
| 64e3cb16fa |
+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:
|
||||
|
||||
@@ -21,8 +21,10 @@ applyTo: "docs/en/**"
|
||||
- Do not apply bold or italic styling inside a heading.
|
||||
- **Formatting:**
|
||||
- **Bold:** Only for UI elements (buttons, menu items).
|
||||
- **Italics (Emphasis):** For tool names (e.g., *QGroundControl*).
|
||||
- **Inline Code:** Use backticks for file paths, parameters, and CLI commands (e.g., `prettier`).
|
||||
Backticks are optional for hyperlinked CLI commands and tool names.
|
||||
- **Italics (Emphasis):** Use for application names (e.g., *QGroundControl*).
|
||||
Emphasis is optional for hyperlinked applications.
|
||||
- **Structure:** End every line at the end of a sentence (Semantic Line Breaks).
|
||||
|
||||
## Linking & Navigation
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -29,6 +60,7 @@ concurrency:
|
||||
permissions:
|
||||
contents: write
|
||||
actions: read
|
||||
packages: read
|
||||
|
||||
jobs:
|
||||
group_targets:
|
||||
@@ -94,6 +126,9 @@ jobs:
|
||||
fail-fast: false
|
||||
container:
|
||||
image: ${{ matrix.container }}
|
||||
credentials:
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
steps:
|
||||
- uses: runs-on/action@v2
|
||||
- uses: actions/checkout@v4
|
||||
@@ -159,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
|
||||
@@ -177,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
|
||||
@@ -215,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 }}
|
||||
|
||||
@@ -42,7 +42,7 @@ jobs:
|
||||
shell: cmake -P {0}
|
||||
run: |
|
||||
string(TIMESTAMP current_date "%Y-%m-%d-%H;%M;%S" UTC)
|
||||
message("::set-output name=timestamp::${current_date}")
|
||||
file(APPEND "$ENV{GITHUB_OUTPUT}" "timestamp=${current_date}\n")
|
||||
- name: ccache cache files
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
|
||||
@@ -0,0 +1,416 @@
|
||||
# Docs - Orchestrator
|
||||
#
|
||||
# Trigger paths:
|
||||
# push (main, release/**) → metadata-regen → build-site → deploy-aws
|
||||
# pull_request → detect-changes → pr-metadata-regen → link-check → build-site (if docs/source changed)
|
||||
# workflow_dispatch → metadata-regen → build-site → deploy-aws
|
||||
#
|
||||
# Container jobs (pr-metadata-regen, metadata-regen) run in px4-dev image and
|
||||
# require safe.directory + fetch-depth: 0 for git operations.
|
||||
|
||||
name: Docs - Orchestrator
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "main"
|
||||
- "release/**"
|
||||
paths:
|
||||
- "docs/**"
|
||||
- "src/**"
|
||||
- "msg/**"
|
||||
- "ROMFS/**"
|
||||
- "Tools/module_config/**"
|
||||
- ".github/workflows/docs-orchestrator.yml"
|
||||
pull_request:
|
||||
paths:
|
||||
- "docs/**"
|
||||
- ".github/workflows/docs-orchestrator.yml"
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: docs-orchestrator-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
# =============================================================================
|
||||
# Detect Changes (PR only)
|
||||
# =============================================================================
|
||||
detect-changes:
|
||||
name: "T1: Detect Changes"
|
||||
if: github.event_name == 'pull_request'
|
||||
permissions:
|
||||
contents: read
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
source_changed: ${{ steps.changes.outputs.source }}
|
||||
docs_changed: ${{ steps.changes.outputs.docs }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dorny/paths-filter@v3
|
||||
id: changes
|
||||
with:
|
||||
filters: |
|
||||
source:
|
||||
- 'src/**'
|
||||
- 'msg/**'
|
||||
- 'ROMFS/**'
|
||||
- 'Tools/module_config/**'
|
||||
docs:
|
||||
- 'docs/**'
|
||||
|
||||
# =============================================================================
|
||||
# PR Metadata Regen (conditional - only when PR touches source files)
|
||||
# =============================================================================
|
||||
pr-metadata-regen:
|
||||
name: "T2: PR Metadata"
|
||||
needs: [detect-changes]
|
||||
if: github.event_name == 'pull_request' && needs.detect-changes.outputs.source_changed == 'true'
|
||||
permissions:
|
||||
contents: read
|
||||
runs-on: [runs-on,runner=4cpu-linux-x64,image=ubuntu24-full-x64,"run-id=${{ github.run_id }}",spot=false,extras=s3-cache]
|
||||
container:
|
||||
image: px4io/px4-dev:v1.17.0-beta1
|
||||
steps:
|
||||
- uses: runs-on/action@v1
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: recursive
|
||||
|
||||
- name: Git ownership workaround
|
||||
run: git config --system --add safe.directory '*'
|
||||
|
||||
- name: Cache Restore - ccache
|
||||
id: cache-ccache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-docs-metadata-${{ github.sha }}
|
||||
restore-keys: |
|
||||
ccache-docs-metadata-
|
||||
|
||||
- name: Setup ccache
|
||||
run: |
|
||||
mkdir -p ~/.ccache
|
||||
echo "max_size = 1G" > ~/.ccache/ccache.conf
|
||||
|
||||
- name: Build px4_sitl_default
|
||||
run: |
|
||||
make px4_sitl_default
|
||||
env:
|
||||
CCACHE_DIR: ~/.ccache
|
||||
|
||||
- name: Cache Save - ccache
|
||||
uses: actions/cache/save@v4
|
||||
if: always()
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-docs-metadata-${{ github.sha }}
|
||||
|
||||
- name: Generate and sync metadata
|
||||
run: Tools/ci/metadata_sync.sh --generate --sync parameters airframes modules msg_docs failsafe_web
|
||||
env:
|
||||
CCACHE_DIR: ~/.ccache
|
||||
|
||||
- name: Upload metadata artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: pr-metadata
|
||||
path: docs/
|
||||
retention-days: 1
|
||||
|
||||
# =============================================================================
|
||||
# Push Metadata Regen (main/release branches)
|
||||
# =============================================================================
|
||||
metadata-regen:
|
||||
name: "T2: Metadata Sync"
|
||||
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
|
||||
permissions:
|
||||
contents: write
|
||||
runs-on: [runs-on,runner=4cpu-linux-x64,image=ubuntu24-full-x64,"run-id=${{ github.run_id }}",spot=false,extras=s3-cache]
|
||||
container:
|
||||
image: px4io/px4-dev:v1.17.0-beta1
|
||||
steps:
|
||||
- uses: runs-on/action@v1
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: recursive
|
||||
token: ${{ secrets.PX4BUILTBOT_PERSONAL_ACCESS_TOKEN }}
|
||||
|
||||
- name: Git ownership workaround
|
||||
run: git config --system --add safe.directory '*'
|
||||
|
||||
- name: Cache Restore - ccache
|
||||
id: cache-ccache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-docs-metadata-${{ github.sha }}
|
||||
restore-keys: |
|
||||
ccache-docs-metadata-
|
||||
|
||||
- name: Setup ccache
|
||||
run: |
|
||||
mkdir -p ~/.ccache
|
||||
echo "max_size = 1G" > ~/.ccache/ccache.conf
|
||||
|
||||
- name: Build px4_sitl_default
|
||||
run: |
|
||||
make px4_sitl_default
|
||||
env:
|
||||
CCACHE_DIR: ~/.ccache
|
||||
|
||||
- name: Cache Save - ccache
|
||||
uses: actions/cache/save@v4
|
||||
if: always()
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-docs-metadata-${{ github.sha }}
|
||||
|
||||
- name: Generate and sync metadata
|
||||
run: Tools/ci/metadata_sync.sh --generate --sync parameters airframes modules msg_docs failsafe_web
|
||||
env:
|
||||
CCACHE_DIR: ~/.ccache
|
||||
|
||||
- name: Install Node.js and Yarn
|
||||
run: |
|
||||
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
|
||||
apt-get install -y nodejs
|
||||
corepack enable
|
||||
|
||||
- name: Format markdown with Prettier
|
||||
run: |
|
||||
cd docs
|
||||
yarn install --frozen-lockfile
|
||||
yarn prettier --write "en/**/*.md"
|
||||
|
||||
- name: Commit and push changes
|
||||
run: |
|
||||
git config --global user.name "${{ secrets.PX4BUILDBOT_USER }}"
|
||||
git config --global user.email "${{ secrets.PX4BUILDBOT_EMAIL }}"
|
||||
git add docs/
|
||||
if git diff --staged --quiet; then
|
||||
echo "No changes to commit"
|
||||
else
|
||||
git commit -m "docs: auto-sync metadata [skip ci]
|
||||
|
||||
Co-Authored-By: PX4 BuildBot <${{ secrets.PX4BUILDBOT_EMAIL }}>"
|
||||
git push
|
||||
fi
|
||||
|
||||
# =============================================================================
|
||||
# Link Check
|
||||
# =============================================================================
|
||||
link-check:
|
||||
name: "T2: Link Check"
|
||||
needs: [detect-changes, pr-metadata-regen]
|
||||
if: always() && (github.event_name == 'pull_request')
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Download metadata artifact
|
||||
if: needs.pr-metadata-regen.result == 'success'
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: pr-metadata
|
||||
path: docs/
|
||||
|
||||
- name: Get changed doc files
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@v46.0.5
|
||||
with:
|
||||
json: true
|
||||
write_output_files: true
|
||||
output_dir: ./logs
|
||||
base_sha: ${{ github.event.pull_request.base.sha }}
|
||||
sha: ${{ github.event.pull_request.head.sha }}
|
||||
files: |
|
||||
docs/en/**/*.md
|
||||
|
||||
- name: Save changed files list
|
||||
run: |
|
||||
mv ./logs/all_changed_files.json ./logs/prFiles.json
|
||||
echo "Changed files:"
|
||||
cat ./logs/prFiles.json
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- name: Run filtered link checker (changed files)
|
||||
run: |
|
||||
npm -g install markdown_link_checker_sc@0.0.138
|
||||
if [ "$(jq length ./logs/prFiles.json)" -gt 0 ]; then
|
||||
markdown_link_checker_sc \
|
||||
-r "$GITHUB_WORKSPACE" \
|
||||
-d docs \
|
||||
-e en \
|
||||
-f ./logs/prFiles.json \
|
||||
-i assets \
|
||||
-u docs.px4.io/main/ \
|
||||
> ./logs/filtered-link-check-results.md || true
|
||||
fi
|
||||
if [ ! -s ./logs/filtered-link-check-results.md ]; then
|
||||
echo "No broken links found in changed files." > ./logs/filtered-link-check-results.md
|
||||
fi
|
||||
cat ./logs/filtered-link-check-results.md
|
||||
|
||||
- name: Run full link checker
|
||||
run: |
|
||||
markdown_link_checker_sc \
|
||||
-r "$GITHUB_WORKSPACE" \
|
||||
-d docs \
|
||||
-e en \
|
||||
-i assets \
|
||||
-u docs.px4.io/main/ \
|
||||
> ./logs/link-check-results.md || true
|
||||
cat ./logs/link-check-results.md
|
||||
|
||||
- name: Post PR comment with link check results
|
||||
if: github.event.pull_request.head.repo.full_name == github.repository
|
||||
uses: marocchino/sticky-pull-request-comment@v2
|
||||
with:
|
||||
header: flaws
|
||||
path: ./logs/filtered-link-check-results.md
|
||||
|
||||
- name: Upload link check results
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: link-check-results
|
||||
path: logs/
|
||||
retention-days: 7
|
||||
|
||||
# =============================================================================
|
||||
# Build Site
|
||||
# =============================================================================
|
||||
build-site:
|
||||
name: "T3: Build Site"
|
||||
needs: [detect-changes, pr-metadata-regen, metadata-regen, link-check]
|
||||
if: >-
|
||||
always() &&
|
||||
(needs.metadata-regen.result == 'success' || needs.metadata-regen.result == 'skipped') &&
|
||||
(needs.link-check.result == 'success' || needs.link-check.result == 'skipped') &&
|
||||
(github.event_name != 'pull_request' || needs.detect-changes.outputs.docs_changed == 'true' || needs.detect-changes.outputs.source_changed == 'true')
|
||||
permissions:
|
||||
contents: read
|
||||
runs-on: [runs-on,runner=4cpu-linux-x64,image=ubuntu24-full-x64,"run-id=${{ github.run_id }}",spot=false,extras=s3-cache]
|
||||
outputs:
|
||||
branchname: ${{ steps.set-branch.outputs.branchname }}
|
||||
releaseversion: ${{ steps.set-version.outputs.releaseversion }}
|
||||
steps:
|
||||
- uses: runs-on/action@v1
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
|
||||
|
||||
- name: Download metadata artifact (PR)
|
||||
if: github.event_name == 'pull_request' && needs.pr-metadata-regen.result == 'success'
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: pr-metadata
|
||||
path: docs/
|
||||
|
||||
- id: set-branch
|
||||
run: echo "branchname=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" >> $GITHUB_OUTPUT
|
||||
|
||||
- id: set-version
|
||||
run: |
|
||||
branch="${{ steps.set-branch.outputs.branchname }}"
|
||||
if [[ "$branch" == "main" ]]; then
|
||||
version="main"
|
||||
elif [[ "$branch" =~ ^release/ ]]; then
|
||||
version="v${branch#release/}"
|
||||
elif [[ "${{ github.event_name }}" == "pull_request" ]]; then
|
||||
version="main"
|
||||
else
|
||||
echo "::error::Unsupported branch for docs deploy: $branch (expected main or release/*)"
|
||||
exit 1
|
||||
fi
|
||||
echo "releaseversion=$version" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
cache: npm
|
||||
cache-dependency-path: ./docs/yarn.lock
|
||||
|
||||
- name: Install dependencies
|
||||
run: yarn install --frozen-lockfile --cwd ./docs
|
||||
|
||||
- name: Build with VitePress
|
||||
working-directory: ./docs
|
||||
env:
|
||||
BRANCH_NAME: ${{ steps.set-version.outputs.releaseversion }}
|
||||
run: |
|
||||
npm run docs:build_ubuntu
|
||||
touch .vitepress/dist/.nojekyll
|
||||
npm run docs:sitemap
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: px4_docs_build
|
||||
path: docs/.vitepress/dist/
|
||||
retention-days: 1
|
||||
|
||||
# =============================================================================
|
||||
# Deploy to AWS (push + workflow_dispatch)
|
||||
# =============================================================================
|
||||
deploy-aws:
|
||||
name: "T4: Deploy"
|
||||
needs: [metadata-regen, build-site]
|
||||
if: >-
|
||||
always() &&
|
||||
needs.metadata-regen.result == 'success' &&
|
||||
needs.build-site.result == 'success' &&
|
||||
(github.event_name == 'push' || github.event_name == 'workflow_dispatch')
|
||||
permissions:
|
||||
id-token: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Download Artifact
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: px4_docs_build
|
||||
path: ~/_book
|
||||
|
||||
- name: Configure AWS from OIDC
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
|
||||
aws-region: us-west-2
|
||||
|
||||
- name: Sanity check AWS credentials
|
||||
run: aws sts get-caller-identity
|
||||
|
||||
- name: Upload HTML with short cache
|
||||
run: |
|
||||
aws s3 sync ~/_book/ s3://px4-docs/${{ needs.build-site.outputs.releaseversion }}/ \
|
||||
--delete \
|
||||
--exclude "*" --include "*.html" \
|
||||
--cache-control "public, max-age=60"
|
||||
|
||||
- name: Upload assets with long cache
|
||||
run: |
|
||||
aws s3 sync ~/_book/ s3://px4-docs/${{ needs.build-site.outputs.releaseversion }}/ \
|
||||
--delete \
|
||||
--exclude "*.html" \
|
||||
--cache-control "public, max-age=86400, immutable"
|
||||
@@ -1,116 +0,0 @@
|
||||
name: Docs - Deploy PX4 User Guide to AWS
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "main"
|
||||
- "release/**"
|
||||
paths:
|
||||
- "docs/en/**"
|
||||
- "docs/zh/**"
|
||||
- "docs/uk/**"
|
||||
- "docs/ko/**"
|
||||
pull_request:
|
||||
paths:
|
||||
- "docs/en/**"
|
||||
- "docs/zh/**"
|
||||
- "docs/uk/**"
|
||||
- "docs/ko/**"
|
||||
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
actions: read
|
||||
id-token: write # for AWS OIDC
|
||||
|
||||
concurrency:
|
||||
group: docs-deploy
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: [runs-on,runner=4cpu-linux-x64,image=ubuntu24-full-x64,"run-id=${{ github.run_id }}",spot=false,extras=s3-cache]
|
||||
outputs:
|
||||
branchname: ${{ steps.set-branch.outputs.branchname }}
|
||||
releaseversion: ${{ steps.set-version.outputs.releaseversion }}
|
||||
steps:
|
||||
- uses: runs-on/action@v1
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- id: set-branch
|
||||
run: echo "branchname=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" >> $GITHUB_OUTPUT
|
||||
|
||||
- id: set-version
|
||||
run: |
|
||||
branch="${{ steps.set-branch.outputs.branchname }}"
|
||||
if [[ "$branch" == "main" ]]; then
|
||||
version="main"
|
||||
else
|
||||
version="v${branch#release/}"
|
||||
fi
|
||||
echo "releaseversion=$version" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
cache: npm
|
||||
cache-dependency-path: ./docs/yarn.lock
|
||||
|
||||
- name: Install dependencies
|
||||
run: yarn install --frozen-lockfile --cwd ./docs
|
||||
|
||||
- name: Build with VitePress
|
||||
working-directory: ./docs
|
||||
env:
|
||||
BRANCH_NAME: ${{ steps.set-version.outputs.releaseversion }}
|
||||
run: |
|
||||
npm run docs:build_ubuntu
|
||||
touch .vitepress/dist/.nojekyll
|
||||
npm run docs:sitemap
|
||||
|
||||
- name: Upload artifact
|
||||
if: ${{ github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.merged) || github.event_name == 'workflow_dispatch' }}
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: px4_docs_build
|
||||
path: docs/.vitepress/dist/
|
||||
retention-days: 1
|
||||
|
||||
deploy:
|
||||
if: ${{ github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.merged) || github.event_name == 'workflow_dispatch' }}
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Download Artifact
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: px4_docs_build
|
||||
path: ~/_book
|
||||
|
||||
- name: Configure AWS from OIDC
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
|
||||
aws-region: us-west-2
|
||||
|
||||
- name: Sanity check AWS credentials
|
||||
run: aws sts get-caller-identity
|
||||
|
||||
- name: Upload HTML with short cache
|
||||
run: |
|
||||
aws s3 sync ~/_book/ s3://px4-docs/${{ needs.build.outputs.releaseversion }}/ \
|
||||
--delete \
|
||||
--exclude "*" --include "*.html" \
|
||||
--cache-control "public, max-age=60"
|
||||
|
||||
- name: Upload assets with long cache
|
||||
run: |
|
||||
aws s3 sync ~/_book/ s3://px4-docs/${{ needs.build.outputs.releaseversion }}/ \
|
||||
--delete \
|
||||
--exclude "*.html" \
|
||||
--cache-control "public, max-age=86400, immutable"
|
||||
@@ -1,85 +0,0 @@
|
||||
name: Docs - Check for flaws in PX4 Guide Source
|
||||
# So far:
|
||||
# Modifications of translations files
|
||||
# Broken internal links
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened, edited, synchronize]
|
||||
paths:
|
||||
- 'docs/en/**'
|
||||
|
||||
jobs:
|
||||
check_flaws:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '18'
|
||||
|
||||
- name: Create logs directory
|
||||
run: |
|
||||
mkdir logs
|
||||
|
||||
- name: Get changed english doc files
|
||||
id: get_changed_markdown_english
|
||||
uses: tj-actions/changed-files@v46.0.5
|
||||
with:
|
||||
json: true
|
||||
base_sha: "${{ github.event.pull_request.base.sha }}"
|
||||
sha: "${{ github.event.pull_request.head.sha }}"
|
||||
# Below are used to output files to a directory. May use in flaw checker.
|
||||
# write_output_files: true
|
||||
# output_dir: "./logs"
|
||||
files: |
|
||||
docs/en/**/*.md
|
||||
|
||||
- name: Save JSON file containing files to link check
|
||||
run: |
|
||||
echo "$ALL_CHANGED_FILES"
|
||||
# echo "$ALL_CHANGED_FILES" > ./logs/prFiles.json
|
||||
echo "$ALL_CHANGED_FILES" | sed 's/\\//g' | jq '.' > ./logs/prFiles.json
|
||||
env:
|
||||
ALL_CHANGED_FILES: ${{ steps.get_changed_markdown_english.outputs.all_changed_files }}
|
||||
|
||||
- name: Run link checker
|
||||
id: link-check
|
||||
run: |
|
||||
npm -g install markdown_link_checker_sc@0.0.138
|
||||
markdown_link_checker_sc \
|
||||
-r "$GITHUB_WORKSPACE" \
|
||||
-d docs \
|
||||
-e en \
|
||||
-f ./logs/prFiles.json \
|
||||
-i assets \
|
||||
-u docs.px4.io/main/ \
|
||||
> ./logs/errorsFilteredByPrPages.md
|
||||
mkdir -p ./pr
|
||||
cp ./logs/errorsFilteredByPrPages.md ./pr/errorsFilteredByPrPages.md
|
||||
|
||||
- name: Read errorsFilteredByPrPages.md file
|
||||
id: read-errors-by-page
|
||||
uses: juliangruber/read-file-action@v1
|
||||
with:
|
||||
path: ./logs/errorsFilteredByPrPages.md
|
||||
|
||||
- name: Echo Errors by Page
|
||||
run: echo "$ERRORS"
|
||||
env:
|
||||
ERRORS: ${{ steps.read-errors-by-page.outputs.content }}
|
||||
|
||||
- name: Save PR number
|
||||
run: echo "$PR_NUMBER" > ./pr/pr_number
|
||||
env:
|
||||
PR_NUMBER: ${{ github.event.number }}
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: pr_number
|
||||
path: pr/
|
||||
@@ -1,111 +0,0 @@
|
||||
name: Docs - Comment Workflow
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ["Docs - Check for flaws in PX4 Guide Source"]
|
||||
types:
|
||||
- completed
|
||||
|
||||
jobs:
|
||||
comment:
|
||||
permissions:
|
||||
pull-requests: write # for marocchino/sticky-pull-request-comment
|
||||
name: Comments
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: 'Download PR artifact'
|
||||
uses: actions/github-script@v6
|
||||
with:
|
||||
script: |
|
||||
let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
run_id: context.payload.workflow_run.id,
|
||||
});
|
||||
let matchArtifact = allArtifacts.data.artifacts.filter((artifact) => {
|
||||
return artifact.name == "pr_number"
|
||||
})[0];
|
||||
let download = await github.rest.actions.downloadArtifact({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
artifact_id: matchArtifact.id,
|
||||
archive_format: 'zip',
|
||||
});
|
||||
let fs = require('fs');
|
||||
fs.writeFileSync(`${process.env.GITHUB_WORKSPACE}/pr_number.zip`, Buffer.from(download.data));
|
||||
|
||||
- name: 'Unzip artifact'
|
||||
run: unzip pr_number.zip
|
||||
|
||||
# Doesn't work across workflows
|
||||
#- name: Get artifacts from flaw checker workflow
|
||||
# uses: actions/download-artifact@v3
|
||||
# with:
|
||||
# name: logs_and_errors
|
||||
# #path: ./logs
|
||||
|
||||
- name: Read errorsFilteredByPrPages.md file
|
||||
id: read-errors-by-page
|
||||
uses: juliangruber/read-file-action@v1
|
||||
with:
|
||||
path: ./errorsFilteredByPrPages.md
|
||||
|
||||
- name: Read PR number
|
||||
id: read-error-pr-number
|
||||
uses: juliangruber/read-file-action@v1
|
||||
with:
|
||||
path: ./pr_number
|
||||
|
||||
- name: File detail info
|
||||
run: |
|
||||
echo "$ERRORS"
|
||||
echo "$PRNUM"
|
||||
env:
|
||||
ERRORS: ${{ steps.read-errors-by-page.outputs.content }}
|
||||
PRNUM: ${{ steps.read-error-pr-number.outputs.content }}
|
||||
|
||||
- name: Create or update comment
|
||||
id: comment_to_pr
|
||||
uses: marocchino/sticky-pull-request-comment@v2
|
||||
with:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
recreate: true
|
||||
number: ${{ steps.read-error-pr-number.outputs.content }}
|
||||
header: flaws
|
||||
message: ${{ steps.read-errors-by-page.outputs.content || 'No flaws found' }}
|
||||
|
||||
#- name: Dump GitHub context
|
||||
# env:
|
||||
# GITHUB_CONTEXT: ${{ toJSON(github) }}
|
||||
# run: echo "$GITHUB_CONTEXT"
|
||||
|
||||
# Would like to do this, but it doesn't work (for me).
|
||||
# Moving to time-based, or triggering on workflow
|
||||
#- name: Wait for artifacts upload to succeed
|
||||
# uses: lewagon/wait-on-check-action@v1.3.1
|
||||
# with:
|
||||
# ref: ${{ github.ref }}
|
||||
# check-name: 'Archive production artifacts'
|
||||
# repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
# wait-interval: 80
|
||||
|
||||
# Not needed for now - trying to trigger off the workflow
|
||||
#- name: Sleep for 80 seconds
|
||||
# run: sleep 80s
|
||||
# shell: bash
|
||||
#- name: Find Comment
|
||||
# uses: peter-evans/find-comment@v2
|
||||
# id: fc
|
||||
# with:
|
||||
# issue-number: ${{ steps.read-error-pr-number.outputs.content }}
|
||||
# comment-author: 'github-actions[bot]'
|
||||
# body-includes: Flaws (may be none)
|
||||
|
||||
#- name: Create or update comment
|
||||
# uses: peter-evans/create-or-update-comment@v3
|
||||
# with:
|
||||
# comment-id: ${{ steps.fc.outputs.comment-id }}
|
||||
# issue-number: ${{ steps.read-error-pr-number.outputs.content }}
|
||||
# body: |
|
||||
# Flaws (may be none)
|
||||
# ${{ steps.read-errors-by-page.outputs.content }}
|
||||
# edit-mode: replace
|
||||
@@ -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
|
||||
|
||||
@@ -109,3 +109,6 @@ src/systemcmds/topic_listener/listener_generated.cpp
|
||||
# colcon
|
||||
log/
|
||||
keys/
|
||||
|
||||
# metadata
|
||||
_emscripten_sdk/
|
||||
|
||||
@@ -1,467 +0,0 @@
|
||||
# Bitbang DShot Prototype - Design Specification
|
||||
|
||||
## Goal
|
||||
|
||||
Implement bitbang DShot (including bidirectional) as an alternative to the existing DMA burst/capture approach in the STM32H7 platform layer. The implementation is generic - it works on any STM32H7 board by dynamically discovering port/pin groupings from `timer_io_channels[]` at init time. The **ARK FPV** board is the test target.
|
||||
|
||||
Bitbang DShot uses a pacer timer to trigger DMA transfers to/from GPIO registers (BSRR for output, IDR for input), instead of using timer PWM channels with DMA burst to CCR registers. This decouples motor signal generation from timer channel hardware and enables simultaneous capture of all motors on a GPIO port (eliminating round-robin).
|
||||
|
||||
## Key Advantage Over Current Approach
|
||||
|
||||
The current BDShot implementation captures **one motor per timer per cycle** (round-robin) because each capture channel needs its own DMA stream. At 200Hz update rate, each motor gets RPM updates at only 50Hz (200/4).
|
||||
|
||||
Bitbang capture reads the entire GPIO IDR register on every sample, capturing **all motors on a port simultaneously**. Every cycle produces RPM data for every motor - a 4x improvement in per-motor RPM update rate.
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
### Current (DMA Burst/Capture)
|
||||
```
|
||||
Timer (PWM mode) ──► CCR1-CCR4 (via DMA burst to DMAR) ──► Pin AF output
|
||||
Timer (Capture mode) ──► CCR edge timestamps (via per-channel DMA) ──► one channel at a time
|
||||
```
|
||||
|
||||
### Bitbang
|
||||
```
|
||||
Timer (counter mode) ──► Update event triggers DMA ──► writes BSRR words to GPIO port
|
||||
Timer (counter mode) ──► Update event triggers DMA ──► reads IDR from GPIO port (all pins)
|
||||
```
|
||||
|
||||
## Port Group Discovery
|
||||
|
||||
At init time, the implementation iterates `timer_io_channels[]` and groups channels by GPIO port. The port and pin are extracted from the existing `gpio_out` field using NuttX bit encoding:
|
||||
|
||||
```c
|
||||
#include <stm32_gpio.h> // GPIO_PORT_MASK, GPIO_PORT_SHIFT, GPIO_PIN_MASK, GPIO_PIN_SHIFT
|
||||
|
||||
// Extract port index and pin number from timer_io_channels[ch].gpio_out
|
||||
uint8_t port_index = (gpio_out & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT; // 0=A, 1=B, ... 7=H, 8=I
|
||||
uint8_t pin_number = (gpio_out & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT; // 0-15
|
||||
|
||||
// Get GPIO peripheral base address from NuttX lookup table
|
||||
uint32_t gpio_base = g_gpiobase[port_index]; // e.g., STM32_GPIOH_BASE = 0x58021C00
|
||||
```
|
||||
|
||||
### Port Group Init Algorithm
|
||||
|
||||
```c
|
||||
// Pseudocode for up_dshot_init()
|
||||
for (uint8_t ch = 0; ch < MAX_TIMER_IO_CHANNELS; ch++) {
|
||||
if (!(channel_mask & (1 << ch))) continue;
|
||||
|
||||
uint32_t gpio_out = timer_io_channels[ch].gpio_out;
|
||||
uint8_t port_index = (gpio_out & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT;
|
||||
uint8_t pin_num = (gpio_out & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT;
|
||||
uint8_t timer_index = timer_io_channels[ch].timer_index;
|
||||
|
||||
// Find or create port group for this GPIO port
|
||||
port_group_t *pg = find_or_create_port_group(port_index);
|
||||
pg->gpio_base = g_gpiobase[port_index];
|
||||
pg->pin_mask |= (1 << pin_num);
|
||||
pg->moder_mask |= (3 << (pin_num * 2));
|
||||
pg->moder_output |= (1 << (pin_num * 2)); // 01 = output mode
|
||||
pg->pin_numbers[pg->pin_count] = pin_num;
|
||||
pg->output_channels[pg->pin_count] = ch;
|
||||
pg->pin_count++;
|
||||
|
||||
// Assign a pacer timer - use the first timer associated with any motor on this port.
|
||||
// On H7 with DMAMUX the timer just needs a TIMx_UP DMA mapping; any timer works.
|
||||
if (pg->timer_index == UINT8_MAX) {
|
||||
pg->timer_index = timer_index;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This works on any board. Motors on the same GPIO port share a port group regardless of which timer they were originally assigned to.
|
||||
|
||||
### ARK FPV Example (test target)
|
||||
|
||||
On the ARK FPV, the above algorithm produces two port groups:
|
||||
|
||||
| Motor | GPIO | Pin | Port Group | Pacer Timer |
|
||||
|---------|-------|-----|------------|-------------|
|
||||
| FMU_CH1 | PI0 | 0 | Port I | TIM5 (first timer seen on Port I) |
|
||||
| FMU_CH2 | PH12 | 12 | Port H | TIM5 |
|
||||
| FMU_CH3 | PH11 | 11 | Port H | TIM5 |
|
||||
| FMU_CH4 | PH10 | 10 | Port H | TIM5 |
|
||||
| FMU_CH5 | PI5 | 5 | Port I | (already assigned) |
|
||||
| FMU_CH6 | PI6 | 6 | Port I | (already assigned) |
|
||||
| FMU_CH7 | PI7 | 7 | Port I | (already assigned) |
|
||||
| FMU_CH8 | PI2 | 2 | Port I | (already assigned) |
|
||||
|
||||
- **Port H group**: 3 motors, pin_mask=0x1C00, pacer=TIM5
|
||||
- **Port I group**: 5 motors, pin_mask=0xE5, pacer=TIM5 (first timer found; could also be TIM8)
|
||||
|
||||
Note: The pacer timer just needs a valid `dma_map_up` entry. The first timer encountered for a port group is used. Since DMAMUX on H7 can route any timer update event to any DMA stream, any timer with DMA configured works as a pacer.
|
||||
|
||||
## GPIO Registers (STM32H7)
|
||||
|
||||
```
|
||||
Offset 0x00: MODER - Mode register (2 bits/pin: 00=input, 01=output, 10=AF, 11=analog)
|
||||
Offset 0x10: IDR - Input data register (read-only, bits [15:0] = pin state)
|
||||
Offset 0x14: ODR - Output data register
|
||||
Offset 0x18: BSRR - Bit set/reset register (write-only, atomic)
|
||||
Bits [15:0] = SET (writing 1 sets pin HIGH)
|
||||
Bits [31:16] = RESET (writing 1 sets pin LOW)
|
||||
Writing 0 = no change
|
||||
```
|
||||
|
||||
GPIO base addresses are looked up at runtime via `g_gpiobase[port_index]` (NuttX global array).
|
||||
|
||||
### MODER Manipulation
|
||||
|
||||
Pin masks and MODER masks are computed dynamically during port group init from the discovered pin numbers:
|
||||
|
||||
```c
|
||||
// For each pin in the port group:
|
||||
pg->pin_mask |= (1 << pin_num); // for BSRR set/reset
|
||||
pg->moder_mask |= (3 << (pin_num * 2)); // which MODER bits to touch
|
||||
pg->moder_output |= (1 << (pin_num * 2)); // 01 = general purpose output
|
||||
// moder_input is always 0 (clear the bits = input mode)
|
||||
```
|
||||
|
||||
To switch to output: `modifyreg32(gpio_base + STM32_GPIO_MODER_OFFSET, pg->moder_mask, pg->moder_output)`
|
||||
To switch to input: `modifyreg32(gpio_base + STM32_GPIO_MODER_OFFSET, pg->moder_mask, 0)`
|
||||
|
||||
## DMA Configuration
|
||||
|
||||
The DMA request source (DMAMUX) stays the same as current - TIMx_UP triggers each DMA transfer. The only change is the **peripheral address** and **transfer direction**.
|
||||
|
||||
### Output DMA (Memory → GPIO BSRR)
|
||||
```c
|
||||
// Peripheral address is GPIO BSRR instead of TIM DMAR
|
||||
px4_stm32_dmasetup(pg->dma_handle,
|
||||
pg->gpio_base + STM32_GPIO_BSRR_OFFSET, // e.g., 0x58021C18 for Port H
|
||||
(uint32_t)bsrr_output_buffer[pg_index],
|
||||
SUBPERIODS_PER_BIT * DSHOT_FRAME_BITS, // 20 * 16 = 320 transfers (+ 1 trailing zero)
|
||||
DMA_SCR_PRIHI | DMA_SCR_MSIZE_32BITS | DMA_SCR_PSIZE_32BITS |
|
||||
DMA_SCR_MINC | DMA_SCR_DIR_M2P | DMA_SCR_TCIE);
|
||||
```
|
||||
|
||||
### Input DMA (GPIO IDR → Memory)
|
||||
```c
|
||||
px4_stm32_dmasetup(pg->dma_handle,
|
||||
pg->gpio_base + STM32_GPIO_IDR_OFFSET, // e.g., 0x58021C10 for Port H
|
||||
(uint32_t)idr_capture_buffer[pg_index],
|
||||
CAPTURE_SAMPLE_COUNT, // enough samples for GCR frame (~512)
|
||||
DMA_SCR_PRIHI | DMA_SCR_MSIZE_16BITS | DMA_SCR_PSIZE_16BITS |
|
||||
DMA_SCR_MINC | DMA_SCR_DIR_P2M | DMA_SCR_TCIE);
|
||||
```
|
||||
|
||||
### DMAMUX Routing (unchanged)
|
||||
|
||||
Each port group uses its pacer timer's `dma_map_up` for DMAMUX routing:
|
||||
```c
|
||||
pg->dma_handle = stm32_dmachannel(io_timers[pg->timer_index].dshot.dma_map_up);
|
||||
```
|
||||
|
||||
The DMAMUX determines **when** the DMA fires (on timer update events). The DMA stream registers determine **what** gets transferred (BSRR/IDR addresses). These are independent - the DMA request source and transfer target don't need to be the same peripheral.
|
||||
|
||||
## Timer Configuration
|
||||
|
||||
Each port group's pacer timer is configured as a simple upcounter. No PWM output, no capture-compare - just generate periodic update events.
|
||||
|
||||
```c
|
||||
// Same prescaler as current DShot implementation
|
||||
rPSC(timer) = ((timer_clock_freq / dshot_pwm_freq) / DSHOT_MOTOR_PWM_BIT_WIDTH) - 1;
|
||||
rARR(timer) = DSHOT_MOTOR_PWM_BIT_WIDTH - 1; // 19 (20 counts per sub-period)
|
||||
// Enable update DMA request
|
||||
rDIER(timer) |= ATIM_DIER_UDE;
|
||||
// Enable counter
|
||||
rCR1(timer) |= GTIM_CR1_CEN;
|
||||
```
|
||||
|
||||
With `DSHOT_MOTOR_PWM_BIT_WIDTH = 20`, each timer update fires DMA once per sub-period. One DShot bit = 20 sub-periods.
|
||||
|
||||
## Output Buffer Layout (BSRR Words)
|
||||
|
||||
Each DShot frame is 16 bits. Each bit has 20 sub-periods. The buffer contains one 32-bit BSRR word per sub-period.
|
||||
|
||||
**DShot bit waveform (sub-periods 0-19):**
|
||||
- Bit '1' (70% duty): SET at sub-period 0, RESET at sub-period 14, zeros elsewhere
|
||||
- Bit '0' (35% duty): SET at sub-period 0, RESET at sub-period 7, zeros elsewhere
|
||||
|
||||
**Buffer structure per port:**
|
||||
```
|
||||
[bit0_subperiod0] [bit0_subperiod1] ... [bit0_subperiod19]
|
||||
[bit1_subperiod0] [bit1_subperiod1] ... [bit1_subperiod19]
|
||||
...
|
||||
[bit15_subperiod0] [bit15_subperiod1] ... [bit15_subperiod19]
|
||||
[trailing_zero] ← ensures all pins return LOW at frame end
|
||||
```
|
||||
|
||||
Total: (16 * 20) + 1 = 321 BSRR words = 1284 bytes per port.
|
||||
|
||||
**Encoding example** (3 motors on pins 10, 11, 12 of some port, sending bits 1, 0, 1):
|
||||
```
|
||||
Sub-period 0: BSRR = (1<<10) | (1<<11) | (1<<12) = 0x00001C00 (SET all three)
|
||||
Sub-period 7: BSRR = (1<<(11+16)) = 0x00080000 (RESET pin11 only - it's '0')
|
||||
Sub-period 14: BSRR = (1<<(10+16)) | (1<<(12+16)) = 0x14000000 (RESET pin10, pin12 - they're '1')
|
||||
All other sub-periods: BSRR = 0x00000000 (no change)
|
||||
```
|
||||
|
||||
### Motor Data Set Function
|
||||
|
||||
The port group index and pin number for each output channel are determined at init time and stored in a lookup table. No per-frame discovery needed.
|
||||
|
||||
```c
|
||||
// Populated during up_dshot_init() from timer_io_channels[ch].gpio_out
|
||||
static uint8_t _channel_to_port_group[MAX_TIMER_IO_CHANNELS];
|
||||
static uint8_t _channel_to_pin[MAX_TIMER_IO_CHANNELS];
|
||||
|
||||
void dshot_motor_data_set(uint8_t output_channel, uint16_t packet)
|
||||
{
|
||||
uint8_t pg_index = _channel_to_port_group[output_channel];
|
||||
uint8_t pin_num = _channel_to_pin[output_channel];
|
||||
uint32_t set_mask = (1 << pin_num);
|
||||
uint32_t reset_mask = (1 << (pin_num + 16));
|
||||
|
||||
uint32_t *buffer = bsrr_output_buffer[pg_index];
|
||||
|
||||
for (int bit = 0; bit < 16; bit++) {
|
||||
int base = bit * SUBPERIODS_PER_BIT;
|
||||
bool is_one = (packet >> (15 - bit)) & 1; // MSB first
|
||||
int reset_point = is_one ? MOTOR_PWM_BIT_1 : MOTOR_PWM_BIT_0;
|
||||
|
||||
buffer[base + 0] |= set_mask; // SET at start of bit
|
||||
buffer[base + reset_point] |= reset_mask; // RESET at duty cycle end
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Note: Buffer must be zeroed before building each frame, then all motors OR their masks into the shared per-port buffer.
|
||||
|
||||
## Capture Buffer Layout (IDR Samples)
|
||||
|
||||
After transmitting, GPIO pins switch to input mode. DMA samples the IDR register at the same timer rate (20 sub-periods per DShot bit period).
|
||||
|
||||
**GCR response timing:**
|
||||
- GCR bit rate = DShot bit rate * 5/4 (750kHz for DShot600)
|
||||
- GCR bit period = 1.333us
|
||||
- Sample period = 83.3ns (at DShot600 with 20 sub-periods)
|
||||
- Samples per GCR bit = ~16 (heavy oversampling, good for edge detection)
|
||||
- GCR frame = 21 bits = ~336 samples minimum
|
||||
- Use 400-512 samples to be safe
|
||||
|
||||
**Buffer:** Array of uint16_t, one per IDR sample.
|
||||
```
|
||||
[idr_sample_0] [idr_sample_1] ... [idr_sample_N]
|
||||
```
|
||||
|
||||
Each sample contains all 16 pins of the port. Extract per-motor bitstream by masking:
|
||||
```c
|
||||
bool pin_state = (idr_sample >> pin_num) & 1;
|
||||
```
|
||||
|
||||
### Capture Processing
|
||||
|
||||
Convert IDR samples to edge intervals, then reuse existing GCR decoder:
|
||||
|
||||
```c
|
||||
void process_bitbang_capture(uint8_t port_group, uint8_t pin_num, uint8_t output_channel)
|
||||
{
|
||||
uint16_t *buffer = idr_capture_buffer[port_group];
|
||||
uint32_t intervals[32];
|
||||
unsigned interval_count = 0;
|
||||
|
||||
// Extract edges from IDR samples
|
||||
bool prev_state = (buffer[0] >> pin_num) & 1;
|
||||
unsigned last_edge = 0;
|
||||
|
||||
for (unsigned i = 1; i < CAPTURE_SAMPLE_COUNT; i++) {
|
||||
bool state = (buffer[i] >> pin_num) & 1;
|
||||
if (state != prev_state) {
|
||||
// Edge detected
|
||||
if (last_edge > 0 && interval_count < 32) {
|
||||
intervals[interval_count++] = i - last_edge;
|
||||
}
|
||||
last_edge = i;
|
||||
prev_state = state;
|
||||
}
|
||||
}
|
||||
|
||||
// Now decode using same GCR logic as existing code
|
||||
// intervals[] contains sample counts between edges
|
||||
// (equivalent to CCR timestamp differences in current impl)
|
||||
}
|
||||
```
|
||||
|
||||
The existing `convert_edge_intervals_to_bitstream()` logic (adaptive base interval, bit counting, RLL/GCR decode, CRC check) can be reused with minor adaptation since the interval units are now sample counts instead of timer ticks. The ratio math is identical.
|
||||
|
||||
## Sequence of Operations
|
||||
|
||||
### Per-cycle flow (called from `up_dshot_trigger()`):
|
||||
|
||||
```
|
||||
1. TRANSMIT PHASE
|
||||
a. Zero the BSRR output buffers for all port groups
|
||||
b. Build BSRR buffers (call dshot_motor_data_set for each motor)
|
||||
- Each motor ORs its pin masks into its port group's shared buffer
|
||||
c. Configure GPIO pins as output (MODER = 01) for each port group
|
||||
d. Flush dcache on output buffers
|
||||
e. For each port group:
|
||||
- Allocate DMA via stm32_dmachannel(io_timers[pg->timer_index].dshot.dma_map_up)
|
||||
- Setup DMA: memory→BSRR, 32-bit, 321 transfers
|
||||
- Enable timer UDE (update DMA request)
|
||||
- Start DMA with burst_finished_callback
|
||||
- Enable timer counter
|
||||
f. ~27us later (16 bits × 20 sub-periods × 83.3ns), DMA complete fires
|
||||
|
||||
2. TRANSITION PHASE (in burst_finished_callback, per port group)
|
||||
a. Stop DMA, free DMA handle
|
||||
b. Disable timer
|
||||
c. Switch GPIO pins to input mode (MODER = 00)
|
||||
d. Schedule capture start via hrt_call_after(30us)
|
||||
|
||||
3. CAPTURE PHASE (in capture_start_callback, per port group)
|
||||
a. Zero capture buffer for this port group
|
||||
b. Flush dcache
|
||||
c. Allocate DMA via stm32_dmachannel(dma_map_up) [reuse same DMAMUX route]
|
||||
d. Setup DMA: IDR→memory, 16-bit, 512 transfers
|
||||
e. Enable timer UDE, start DMA, enable timer
|
||||
f. Schedule capture_complete via hrt_call_after(frame_time + margin)
|
||||
|
||||
4. PROCESSING PHASE (in capture_complete_callback, per port group)
|
||||
a. Stop DMA, free DMA handle
|
||||
b. Disable timer
|
||||
c. Invalidate dcache on capture buffer
|
||||
d. For EACH motor on the port (not round-robin!):
|
||||
- Extract per-pin bitstream from IDR samples using pin_numbers[]
|
||||
- Detect edges, compute intervals
|
||||
- Decode GCR → eRPM/EDT
|
||||
e. Switch GPIO back to output mode (MODER = 01)
|
||||
f. Mark port group cycle complete
|
||||
|
||||
```
|
||||
|
||||
## File Structure
|
||||
|
||||
### New file: `platforms/nuttx/src/px4/stm/stm32_common/dshot/dshot_bitbang.c`
|
||||
|
||||
Implements the same `up_dshot_*` API as `dshot.c`:
|
||||
- `up_dshot_init()` - Initialize port groups, allocate DMA, configure timers
|
||||
- `up_dshot_trigger()` - Start the TX→wait→RX→process cycle
|
||||
- `dshot_motor_data_set()` - Build BSRR words into port group buffers
|
||||
- `up_dshot_arm()` - Enable/disable GPIO output
|
||||
- `up_bdshot_get_erpm()` - Return captured eRPM (unchanged)
|
||||
- `up_bdshot_channel_online()` - Return online status (unchanged)
|
||||
- `up_bdshot_status()` - Print diagnostics
|
||||
|
||||
### New/modified: `platforms/nuttx/src/px4/stm/stm32_common/dshot/CMakeLists.txt`
|
||||
|
||||
Add build option to select `dshot.c` vs `dshot_bitbang.c`.
|
||||
|
||||
### Board-level config
|
||||
|
||||
No board-specific changes needed. The bitbang implementation reads the same `io_timers[]` and `timer_io_channels[]` structures that every board already defines. It extracts GPIO port/pin from `timer_io_channels[].gpio_out` (which `initIOTimerChannel()` already populates with `getGPIOPort(pin.port) | getGPIOPin(pin.pin)`) and the DMA mapping from `io_timers[].dshot.dma_map_up`.
|
||||
|
||||
A board opts into bitbang mode via a build flag or Kconfig option that selects `dshot_bitbang.c` instead of `dshot.c`.
|
||||
|
||||
### What stays the same
|
||||
- `drv_dshot.h` API - no changes
|
||||
- `DShot.cpp` / `DShot.h` (the driver module) - no changes
|
||||
- `DShotTelemetry.cpp` / `DShotTelemetry.h` - no changes
|
||||
- GCR decoding logic - copied/adapted from dshot.c but the core algorithm is identical
|
||||
- All higher-level consumers of eRPM data
|
||||
|
||||
## Data Structures
|
||||
|
||||
```c
|
||||
#define MAX_PORT_GROUPS 4 // Max distinct GPIO ports with motor pins (typically 1-3)
|
||||
#define MAX_PINS_PER_GROUP 8
|
||||
|
||||
// Port group: one per GPIO port that has motor pins. Built dynamically at init.
|
||||
typedef struct port_group_t {
|
||||
uint32_t gpio_base; // GPIO port base address (from g_gpiobase[])
|
||||
uint8_t port_index; // NuttX port index (0=A, 7=H, 8=I, etc.)
|
||||
uint32_t pin_mask; // Bitmask of motor pins on this port
|
||||
uint32_t moder_mask; // MODER register mask for mode switching
|
||||
uint32_t moder_output; // MODER value for output mode (01 per pin)
|
||||
uint8_t pin_count; // Number of motor pins on this port
|
||||
uint8_t pin_numbers[MAX_PINS_PER_GROUP]; // Pin numbers (0-15)
|
||||
uint8_t output_channels[MAX_PINS_PER_GROUP]; // Corresponding output channel indices
|
||||
uint8_t timer_index; // Pacer timer index (into io_timers[])
|
||||
DMA_HANDLE dma_handle; // DMA stream handle (reused between TX/RX)
|
||||
bool bidirectional; // BDShot enabled for this group
|
||||
bool cycle_complete; // Ready for next trigger
|
||||
} port_group_t;
|
||||
|
||||
static port_group_t _port_groups[MAX_PORT_GROUPS] = {};
|
||||
static uint8_t _num_port_groups = 0;
|
||||
|
||||
// Per-channel lookup tables (populated at init from timer_io_channels[].gpio_out)
|
||||
static uint8_t _channel_to_port_group[MAX_TIMER_IO_CHANNELS];
|
||||
static uint8_t _channel_to_pin[MAX_TIMER_IO_CHANNELS];
|
||||
```
|
||||
|
||||
## DMA Resource Usage Comparison
|
||||
|
||||
### Current (DMA burst + capture)
|
||||
- **Output**: 1 DMA stream per timer = N_timers streams
|
||||
- **Capture**: 1 DMA stream per captured channel (round-robin, 1 at a time per timer)
|
||||
- DMA streams are freed/reallocated between burst and capture phases
|
||||
|
||||
### Bitbang
|
||||
- **Output**: 1 DMA stream per port group = N_ports streams
|
||||
- **Capture**: 1 DMA stream per port group (same streams, reconfigured)
|
||||
- DMA streams freed/reallocated between phases (same pattern as current)
|
||||
|
||||
DMA resource usage is equivalent (typically N_timers == N_ports or close). The DMAMUX routing uses the same timer update event mappings.
|
||||
|
||||
## Memory Usage
|
||||
|
||||
### Current
|
||||
- Output: ~272 bytes per timer (4 channels * 17 words * 4 bytes, cache-aligned)
|
||||
- Capture: ~256 bytes per timer (4 channels * 32 samples * 2 bytes)
|
||||
|
||||
### Bitbang
|
||||
- Output: ~1284 bytes per port group (321 words * 4 bytes, cache-aligned)
|
||||
- Capture: ~1024 bytes per port group (512 samples * 2 bytes, cache-aligned)
|
||||
- Scales with number of port groups, not number of motors
|
||||
- Higher per-group cost, but acceptable for H7 (1MB+ SRAM)
|
||||
|
||||
## Open Questions / Risks
|
||||
|
||||
1. **GPIO output speed**: BSRR writes through AHB4 bus on H7. At 83.3ns per DMA transfer (12MHz), is there enough bus bandwidth? Should be fine - AHB4 runs at 240MHz, and BSRR writes are single-cycle.
|
||||
|
||||
2. **DMA priority vs other peripherals**: SPI1 (IMU) is on DMA1. Timer DMA is already high priority. No change expected.
|
||||
|
||||
3. **GPIO input threshold**: When reading IDR for bidir, the input threshold depends on GPIO input configuration (Schmitt trigger, pull-up/down). The current capture approach uses timer input capture which has different input characteristics. May need to configure GPIO pull-up to match idle-high behavior.
|
||||
|
||||
4. **Signal integrity**: Timer PWM output has precise edge timing locked to the timer clock. BSRR writes via DMA may have slight jitter due to bus arbitration. This is likely negligible (< 10ns on H7) but should be verified.
|
||||
|
||||
5. **OTYPER configuration**: For bidirectional DShot, the pin needs to be open-drain (or at least not actively driven when in input mode). The MODER switch to input (00) handles this, but verify that switching MODER during/after a frame doesn't cause glitches.
|
||||
|
||||
6. **Cache coherency**: BSRR output buffers need dcache clean before DMA. IDR capture buffers need dcache invalidate after DMA. Same pattern as current code.
|
||||
|
||||
## Implementation Order
|
||||
|
||||
1. **Port group initialization**: Parse `timer_io_channels[]` to build `port_group_t` structures grouped by GPIO port instead of timer
|
||||
2. **Output-only DShot**: Implement BSRR buffer building and DMA output. Verify with logic analyzer that DShot frames are correct
|
||||
3. **Bidirectional capture**: Implement IDR sampling and per-pin edge extraction. Verify GCR decode produces valid eRPM
|
||||
4. **Integration**: Wire up to the existing `up_dshot_*` API so `DShot.cpp` works unchanged
|
||||
5. **Testing**: Compare eRPM data quality (CRC error rate, update rate) vs current implementation
|
||||
|
||||
## Reference: Betaflight Bitbang Implementation
|
||||
|
||||
- [Betaflight dshot_bitbang.c](https://github.com/betaflight/betaflight/blob/master/src/platform/STM32/dshot_bitbang.c)
|
||||
- [Betaflight dshot_bitbang_impl.h](https://github.com/betaflight/betaflight/blob/master/src/main/drivers/dshot_bitbang_impl.h)
|
||||
- [Original GPIO banging PR #7446](https://github.com/betaflight/betaflight/pull/7446)
|
||||
- [Bidirectional bitbang PR #8779](https://github.com/betaflight/betaflight/pull/8779)
|
||||
|
||||
## Reference: Current PX4 Implementation Files
|
||||
|
||||
- DShot platform layer: `platforms/nuttx/src/px4/stm/stm32_common/dshot/dshot.c`
|
||||
- IO timer layer: `platforms/nuttx/src/px4/stm/stm32_common/io_pins/io_timer.c`
|
||||
- IO timer struct defs: `platforms/nuttx/src/px4/stm/stm32_common/include/px4_arch/io_timer.h`
|
||||
- GPIO/pin helpers: `platforms/nuttx/src/px4/stm/stm32_common/include/px4_arch/hw_description.h`
|
||||
- H7 timer/DMA descriptions: `platforms/nuttx/src/px4/stm/stm32h7/include/px4_arch/io_timer_hw_description.h`
|
||||
- H7 GPIO register defs: NuttX `arch/arm/src/stm32h7/stm32_gpio.h` (GPIO_PORT_MASK, GPIO_PIN_MASK, g_gpiobase[])
|
||||
- H7 GPIO HW registers: NuttX `arch/arm/src/stm32h7/hardware/stm32h7x3xx_gpio.h` (STM32_GPIO_MODER_OFFSET, etc.)
|
||||
- DShot API header: `src/drivers/drv_dshot.h`
|
||||
- DShot driver module: `src/drivers/dshot/DShot.cpp`
|
||||
|
||||
## Reference: Test Target (ARK FPV)
|
||||
|
||||
- Timer config: `boards/ark/fpv/src/timer_config.cpp`
|
||||
- DMA map: `boards/ark/fpv/nuttx-config/include/board_dma_map.h`
|
||||
- Board config: `boards/ark/fpv/src/board_config.h`
|
||||
@@ -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
|
||||
@@ -598,3 +614,10 @@ failsafe_web:
|
||||
run_failsafe_web_server: failsafe_web
|
||||
@cd build/px4_sitl_default_failsafe_web && \
|
||||
python3 -m http.server
|
||||
|
||||
# Generate reference documentation for uORB messages
|
||||
.PHONY: msg_docs
|
||||
msg_docs:
|
||||
$(call colorecho,'Generating uORB message reference docs')
|
||||
@mkdir -p build/msg_docs
|
||||
@./Tools/msg/generate_msg_docs.py -d build/msg_docs
|
||||
|
||||
@@ -1,62 +1,109 @@
|
||||
# PX4 Drone Autopilot
|
||||
<p align="center">
|
||||
<a href="https://px4.io">
|
||||
<img src="docs/assets/site/px4_logo.svg" alt="PX4 Autopilot" width="240">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
[](https://github.com/PX4/PX4-Autopilot/releases) [](https://zenodo.org/badge/latestdoi/22634/PX4/PX4-Autopilot)
|
||||
<p align="center">
|
||||
<em>The autopilot stack the industry builds on.</em>
|
||||
</p>
|
||||
|
||||
[](https://github.com/PX4/PX4-Autopilot/actions/workflows/build_all_targets.yml) [](https://github.com/PX4/PX4-Autopilot/actions?query=workflow%3A%22SITL+Tests%22)
|
||||
<p align="center">
|
||||
<a href="https://github.com/PX4/PX4-Autopilot/releases"><img src="https://img.shields.io/github/release/PX4/PX4-Autopilot.svg" alt="Releases"></a>
|
||||
<a href="https://zenodo.org/badge/latestdoi/22634/PX4/PX4-Autopilot"><img src="https://zenodo.org/badge/22634/PX4/PX4-Autopilot.svg" alt="DOI"></a>
|
||||
<a href="https://github.com/PX4/PX4-Autopilot/actions/workflows/build_all_targets.yml"><img src="https://github.com/PX4/PX4-Autopilot/actions/workflows/build_all_targets.yml/badge.svg?branch=main" alt="Build Targets"></a>
|
||||
<a href="https://discord.gg/dronecode"><img src="https://discordapp.com/api/guilds/1022170275984457759/widget.png?style=shield" alt="Discord"></a>
|
||||
</p>
|
||||
|
||||
[](https://discord.gg/dronecode)
|
||||
---
|
||||
|
||||
This repository holds the [PX4](http://px4.io) flight control solution for drones, with the main applications located in the [src/modules](https://github.com/PX4/PX4-Autopilot/tree/main/src/modules) directory. It also contains the PX4 Drone Middleware Platform, which provides drivers and middleware to run drones.
|
||||
## About
|
||||
|
||||
PX4 is highly portable, OS-independent and supports Linux, NuttX and MacOS out of the box.
|
||||
PX4 is an open-source autopilot stack for drones and unmanned vehicles. It supports multirotors, fixed-wing, VTOL, rovers, and many more experimental platforms from racing quads to industrial survey aircraft. It runs on [NuttX](https://nuttx.apache.org/), Linux, and macOS. Licensed under [BSD 3-Clause](LICENSE).
|
||||
|
||||
* Official Website: http://px4.io (License: BSD 3-clause, [LICENSE](https://github.com/PX4/PX4-Autopilot/blob/main/LICENSE))
|
||||
* [Supported airframes](https://docs.px4.io/main/en/airframes/airframe_reference.html) ([portfolio](https://px4.io/ecosystem/commercial-systems/)):
|
||||
* [Multicopters](https://docs.px4.io/main/en/frames_multicopter/)
|
||||
* [Fixed wing](https://docs.px4.io/main/en/frames_plane/)
|
||||
* [VTOL](https://docs.px4.io/main/en/frames_vtol/)
|
||||
* [Autogyro](https://docs.px4.io/main/en/frames_autogyro/)
|
||||
* [Rover](https://docs.px4.io/main/en/frames_rover/)
|
||||
* many more experimental types (Blimps, Boats, Submarines, High Altitude Balloons, Spacecraft, etc)
|
||||
* Releases: [Downloads](https://github.com/PX4/PX4-Autopilot/releases)
|
||||
## Why PX4
|
||||
|
||||
## Releases
|
||||
**Modular architecture.** PX4 is built around [uORB](https://docs.px4.io/main/en/middleware/uorb.html), a [DDS](https://docs.px4.io/main/en/middleware/uxrce_dds.html)-compatible publish/subscribe middleware. Modules are fully parallelized and thread safe. You can build custom configurations and trim what you don't need.
|
||||
|
||||
Release notes and supporting information for PX4 releases can be found on the [Developer Guide](https://docs.px4.io/main/en/releases/).
|
||||
**Wide hardware support.** PX4 runs on a wide range of [autopilot boards](https://docs.px4.io/main/en/flight_controller/) and supports an extensive set of sensors, telemetry radios, and actuators through the [Pixhawk](https://pixhawk.org/) ecosystem.
|
||||
|
||||
## Building a PX4 based drone, rover, boat or robot
|
||||
**Developer friendly.** First-class support for [MAVLink](https://mavlink.io/) and [DDS / ROS 2](https://docs.px4.io/main/en/ros2/) integration. Comprehensive [SITL simulation](https://docs.px4.io/main/en/simulation/), hardware-in-the-loop testing, and [log analysis](https://docs.px4.io/main/en/log/flight_log_analysis.html) tools. An active developer community on [Discord](https://discord.gg/dronecode) and the [weekly dev call](https://docs.px4.io/main/en/contribute/).
|
||||
|
||||
The [PX4 User Guide](https://docs.px4.io/main/en/) explains how to assemble [supported vehicles](https://docs.px4.io/main/en/airframes/airframe_reference.html) and fly drones with PX4. See the [forum and chat](https://docs.px4.io/main/en/#getting-help) if you need help!
|
||||
**Vendor neutral governance.** PX4 is hosted under the [Dronecode Foundation](https://www.dronecode.org/), part of the Linux Foundation. Business-friendly BSD-3 license. No single vendor controls the roadmap.
|
||||
|
||||
## Supported Vehicles
|
||||
|
||||
## Changing Code and Contributing
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://docs.px4.io/main/en/frames_multicopter/">
|
||||
<img src="docs/assets/airframes/types/QuadRotorX.svg" width="50" alt="Multicopter"><br>
|
||||
<sub>Multicopter</sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://docs.px4.io/main/en/frames_plane/">
|
||||
<img src="docs/assets/airframes/types/Plane.svg" width="50" alt="Fixed Wing"><br>
|
||||
<sub>Fixed Wing</sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://docs.px4.io/main/en/frames_vtol/">
|
||||
<img src="docs/assets/airframes/types/VTOLPlane.svg" width="50" alt="VTOL"><br>
|
||||
<sub>VTOL</sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://docs.px4.io/main/en/frames_rover/">
|
||||
<img src="docs/assets/airframes/types/Rover.svg" width="50" alt="Rover"><br>
|
||||
<sub>Rover</sub>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
This [Developer Guide](https://docs.px4.io/main/en/development/development.html) is for software developers who want to modify the flight stack and middleware (e.g. to add new flight modes), hardware integrators who want to support new flight controller boards and peripherals, and anyone who wants to get PX4 working on a new (unsupported) airframe/vehicle.
|
||||
<sub>…and many more: helicopters, autogyros, airships, submarines, boats, and other experimental platforms. These frames have basic support but are not part of the regular flight-test program. See the <a href="https://docs.px4.io/main/en/airframes/airframe_reference.html">full airframe reference</a>.</sub>
|
||||
|
||||
Developers should read the [Guide for Contributions](https://docs.px4.io/main/en/contribute/).
|
||||
See the [forum and chat](https://docs.px4.io/main/en/#getting-help) if you need help!
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
git clone https://github.com/PX4/PX4-Autopilot.git --recursive
|
||||
cd PX4-Autopilot
|
||||
make px4_sitl
|
||||
```
|
||||
|
||||
## Weekly Dev Call
|
||||
> [!NOTE]
|
||||
> See the [Development Guide](https://docs.px4.io/main/en/development/development.html) for toolchain setup and build options.
|
||||
|
||||
The PX4 Dev Team syncs up on a [weekly dev call](https://docs.px4.io/main/en/contribute/).
|
||||
## Documentation & Resources
|
||||
|
||||
> **Note** The dev call is open to all interested developers (not just the core dev team). This is a great opportunity to meet the team and contribute to the ongoing development of the platform. It includes a QA session for newcomers. All regular calls are listed in the [Dronecode calendar](https://www.dronecode.org/calendar/).
|
||||
| Resource | Description |
|
||||
| --- | --- |
|
||||
| [User Guide](https://docs.px4.io/main/en/) | Build, configure, and fly with PX4 |
|
||||
| [Developer Guide](https://docs.px4.io/main/en/development/development.html) | Modify the flight stack, add peripherals, port to new hardware |
|
||||
| [Airframe Reference](https://docs.px4.io/main/en/airframes/airframe_reference.html) | Full list of supported frames |
|
||||
| [Autopilot Hardware](https://docs.px4.io/main/en/flight_controller/) | Compatible flight controllers |
|
||||
| [Release Notes](https://docs.px4.io/main/en/releases/) | What's new in each release |
|
||||
| [Contribution Guide](https://docs.px4.io/main/en/contribute/) | How to contribute to PX4 |
|
||||
|
||||
## Community
|
||||
|
||||
## Maintenance Team
|
||||
- **Weekly Dev Call** — open to all developers ([Dronecode calendar](https://www.dronecode.org/calendar/))
|
||||
- **Discord** — [Join the Dronecode server](https://discord.gg/dronecode)
|
||||
- **Discussion Forum** — [PX4 Discuss](https://discuss.px4.io/)
|
||||
- **Maintainers** — see [`MAINTAINERS.md`](MAINTAINERS.md)
|
||||
- **Contributor Stats** — [LFX Insights](https://insights.lfx.linuxfoundation.org/foundation/dronecode)
|
||||
|
||||
See the latest list of maintainers on [MAINTAINERS](MAINTAINERS.md) file at the root of the project.
|
||||
## Contributing
|
||||
|
||||
For the latest stats on contributors please see the latest stats for the Dronecode ecosystem in our project dashboard under [LFX Insights](https://insights.lfx.linuxfoundation.org/foundation/dronecode). For information on how to update your profile and affiliations please see the following support link on how to [Complete Your LFX Profile](https://docs.linuxfoundation.org/lfx/my-profile/complete-your-lfx-profile). Dronecode publishes a yearly snapshot of contributions and achievements on its [website under the Reports section](https://dronecode.org).
|
||||
We welcome contributions of all kinds — bug reports, documentation, new features, and code reviews. Please read the [Contribution Guide](https://docs.px4.io/main/en/contribute/) to get started.
|
||||
|
||||
## Supported Hardware
|
||||
## Governance
|
||||
|
||||
For the most up to date information, please visit [PX4 User Guide > Autopilot Hardware](https://docs.px4.io/main/en/flight_controller/).
|
||||
The PX4 Autopilot project is hosted by the [Dronecode Foundation](https://www.dronecode.org/), a [Linux Foundation](https://www.linuxfoundation.org/) Collaborative Project. Dronecode holds all PX4 trademarks and serves as the project's legal guardian, ensuring vendor-neutral stewardship — no single company owns the name or controls the roadmap. The source code is licensed under the [BSD 3-Clause](LICENSE) license, so you are free to use, modify, and distribute it in your own projects.
|
||||
|
||||
## Project Governance
|
||||
|
||||
The PX4 Autopilot project including all of its trademarks is hosted under [Dronecode](https://www.dronecode.org/), part of the Linux Foundation.
|
||||
|
||||
<a href="https://www.dronecode.org/" style="padding:20px" ><img src="https://dronecode.org/wp-content/uploads/sites/24/2020/08/dronecode_logo_default-1.png" alt="Dronecode Logo" width="110px"/></a>
|
||||
<div style="padding:10px"> </div>
|
||||
<p align="center">
|
||||
<a href="https://www.dronecode.org/">
|
||||
<img src="docs/assets/site/dronecode_logo.svg" alt="Dronecode Logo" width="180">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -42,23 +42,21 @@ param set-default FD_FAIL_R 0
|
||||
param set-default CA_ROTOR_COUNT 8
|
||||
param set-default CA_R_REV 255
|
||||
|
||||
param set-default CA_ROTOR0_AX -1
|
||||
param set-default CA_ROTOR0_AY 1
|
||||
param set-default CA_ROTOR0_AX 1
|
||||
param set-default CA_ROTOR0_AY -1
|
||||
param set-default CA_ROTOR0_AZ 0
|
||||
param set-default CA_ROTOR0_KM 0
|
||||
param set-default CA_ROTOR0_PX 0.14
|
||||
param set-default CA_ROTOR0_PY 0.10
|
||||
param set-default CA_ROTOR0_PZ 0.06
|
||||
#param set-default CA_ROTOR0_PZ 0.0
|
||||
|
||||
param set-default CA_ROTOR1_AX -1
|
||||
param set-default CA_ROTOR1_AY -1
|
||||
param set-default CA_ROTOR1_AX 1
|
||||
param set-default CA_ROTOR1_AY 1
|
||||
param set-default CA_ROTOR1_AZ 0
|
||||
param set-default CA_ROTOR1_KM 0
|
||||
param set-default CA_ROTOR1_PX 0.14
|
||||
param set-default CA_ROTOR1_PY -0.10
|
||||
param set-default CA_ROTOR1_PZ 0.06
|
||||
#param set-default CA_ROTOR1_PZ 0.0
|
||||
|
||||
param set-default CA_ROTOR2_AX 1
|
||||
param set-default CA_ROTOR2_AY 1
|
||||
@@ -67,7 +65,6 @@ param set-default CA_ROTOR2_KM 0
|
||||
param set-default CA_ROTOR2_PX -0.14
|
||||
param set-default CA_ROTOR2_PY 0.10
|
||||
param set-default CA_ROTOR2_PZ 0.06
|
||||
#param set-default CA_ROTOR2_PZ 0.0
|
||||
|
||||
param set-default CA_ROTOR3_AX 1
|
||||
param set-default CA_ROTOR3_AY -1
|
||||
@@ -79,7 +76,7 @@ param set-default CA_ROTOR3_PZ 0.06
|
||||
|
||||
param set-default CA_ROTOR4_AX 0
|
||||
param set-default CA_ROTOR4_AY 0
|
||||
param set-default CA_ROTOR4_AZ 1
|
||||
param set-default CA_ROTOR4_AZ -1
|
||||
param set-default CA_ROTOR4_KM 0
|
||||
param set-default CA_ROTOR4_PX 0.12
|
||||
param set-default CA_ROTOR4_PY 0.22
|
||||
@@ -103,7 +100,7 @@ param set-default CA_ROTOR6_PZ 0
|
||||
|
||||
param set-default CA_ROTOR7_AX 0
|
||||
param set-default CA_ROTOR7_AY 0
|
||||
param set-default CA_ROTOR7_AZ 1
|
||||
param set-default CA_ROTOR7_AZ -1
|
||||
param set-default CA_ROTOR7_KM 0
|
||||
param set-default CA_ROTOR7_PX -0.12
|
||||
param set-default CA_ROTOR7_PY -0.22
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,433 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
BDShot Timing Jitter Analyzer
|
||||
|
||||
Analyzes BDShot (Bidirectional DShot) signal timing from Saleae Logic Analyzer
|
||||
CSV exports. Measures scheduling consistency and jitter in PX4 flight controller
|
||||
DShot output timing.
|
||||
|
||||
Usage:
|
||||
python bdshot_analyzer.py capture.csv
|
||||
python bdshot_analyzer.py capture.csv --dshot-rate 300 --loop-rate 800
|
||||
python bdshot_analyzer.py capture.csv --channel-a 0 --channel-b 1
|
||||
|
||||
Arguments:
|
||||
input_file Path to Saleae CSV export
|
||||
--dshot-rate DShot variant: 150/300/600/1200 (default: 300)
|
||||
--loop-rate Expected loop rate in Hz (default: 800)
|
||||
--channel-a CSV column index for first channel (default: 0)
|
||||
--channel-b CSV column index for second channel (default: 1)
|
||||
--no-plots Disable histogram display
|
||||
--verbose Enable verbose debugging output
|
||||
|
||||
Capture Setup:
|
||||
1. Connect Saleae to two BDShot signals from different timers
|
||||
(e.g., Motor 1 from Timer1, Motor 5 from Timer2)
|
||||
2. Sample rate: 24+ MS/s for DShot300
|
||||
3. Export as CSV: File -> Export Raw Data -> CSV
|
||||
|
||||
Interpreting Results:
|
||||
- Frame Intervals: Should cluster tightly around expected loop period
|
||||
- Inter-Channel Gap: Measures sequential DMA scheduling overhead
|
||||
- Jitter: Small std dev is typical for well-behaved systems
|
||||
|
||||
Dependencies: numpy, matplotlib
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import csv
|
||||
import sys
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
|
||||
import numpy as np
|
||||
|
||||
# Try to import matplotlib, but allow running without it
|
||||
try:
|
||||
import matplotlib.pyplot as plt
|
||||
HAS_MATPLOTLIB = True
|
||||
except ImportError:
|
||||
HAS_MATPLOTLIB = False
|
||||
|
||||
|
||||
# DShot bit periods in microseconds
|
||||
DSHOT_BIT_PERIODS = {
|
||||
150: 6.67,
|
||||
300: 3.33,
|
||||
600: 1.67,
|
||||
1200: 0.83,
|
||||
}
|
||||
|
||||
|
||||
@dataclass
|
||||
class BDShotTransaction:
|
||||
"""Represents a single BDShot transaction (command + response)."""
|
||||
start: float # Timestamp of first falling edge (seconds)
|
||||
end: float # Timestamp of final rising edge before idle (seconds)
|
||||
|
||||
@property
|
||||
def duration_us(self) -> float:
|
||||
"""Transaction duration in microseconds."""
|
||||
return (self.end - self.start) * 1_000_000
|
||||
|
||||
|
||||
@dataclass
|
||||
class ChannelStats:
|
||||
"""Statistics for a single channel's frame intervals."""
|
||||
channel_name: str
|
||||
count: int
|
||||
min_us: float
|
||||
max_us: float
|
||||
mean_us: float
|
||||
std_us: float
|
||||
expected_us: float
|
||||
|
||||
@property
|
||||
def min_jitter_us(self) -> float:
|
||||
return self.min_us - self.expected_us
|
||||
|
||||
@property
|
||||
def max_jitter_us(self) -> float:
|
||||
return self.max_us - self.expected_us
|
||||
|
||||
@property
|
||||
def mean_jitter_us(self) -> float:
|
||||
return self.mean_us - self.expected_us
|
||||
|
||||
|
||||
@dataclass
|
||||
class GapStats:
|
||||
"""Statistics for inter-channel gaps."""
|
||||
count: int
|
||||
min_us: float
|
||||
max_us: float
|
||||
mean_us: float
|
||||
std_us: float
|
||||
|
||||
|
||||
def parse_csv(filepath: Path, channel_a_idx: int, channel_b_idx: int, verbose: bool = False):
|
||||
"""
|
||||
Parse Saleae CSV export and extract edges for each channel.
|
||||
|
||||
Returns:
|
||||
Tuple of (edges_a, edges_b) where each is a list of (timestamp, new_state) tuples.
|
||||
"""
|
||||
edges_a, edges_b = [], []
|
||||
prev_a, prev_b = None, None
|
||||
ch_a_col, ch_b_col = channel_a_idx + 1, channel_b_idx + 1 # +1 for time column
|
||||
|
||||
with open(filepath, 'r', newline='') as f:
|
||||
reader = csv.reader(f)
|
||||
header = next(reader)
|
||||
|
||||
if verbose:
|
||||
print(f"CSV Header: {header}")
|
||||
print(f"Using columns: time=0, ch_a={ch_a_col} ({header[ch_a_col]}), "
|
||||
f"ch_b={ch_b_col} ({header[ch_b_col]})")
|
||||
|
||||
if ch_a_col >= len(header) or ch_b_col >= len(header):
|
||||
raise ValueError(
|
||||
f"Channel indices out of range. CSV has {len(header)-1} channels. "
|
||||
f"Requested channel_a={channel_a_idx}, channel_b={channel_b_idx}"
|
||||
)
|
||||
|
||||
for row_num, row in enumerate(reader, start=2):
|
||||
try:
|
||||
timestamp = float(row[0])
|
||||
state_a, state_b = int(row[ch_a_col]), int(row[ch_b_col])
|
||||
|
||||
# Record edges (state changes) or initial LOW state
|
||||
if (prev_a is not None and state_a != prev_a) or (prev_a is None and state_a == 0):
|
||||
edges_a.append((timestamp, state_a))
|
||||
if (prev_b is not None and state_b != prev_b) or (prev_b is None and state_b == 0):
|
||||
edges_b.append((timestamp, state_b))
|
||||
|
||||
prev_a, prev_b = state_a, state_b
|
||||
|
||||
except (ValueError, IndexError) as e:
|
||||
if verbose:
|
||||
print(f"Warning: Skipping malformed row {row_num}: {e}")
|
||||
|
||||
if verbose:
|
||||
print(f"Parsed {len(edges_a)} edges for channel A, {len(edges_b)} edges for channel B")
|
||||
|
||||
return edges_a, edges_b
|
||||
|
||||
|
||||
def detect_transactions(edges, idle_threshold_us: float, verbose: bool = False):
|
||||
"""
|
||||
Detect BDShot transactions from edge list.
|
||||
|
||||
A transaction starts with a falling edge after an idle period and ends
|
||||
when the line returns HIGH and stays HIGH for > idle_threshold_us.
|
||||
"""
|
||||
if not edges:
|
||||
return []
|
||||
|
||||
idle_threshold_s = idle_threshold_us / 1_000_000
|
||||
transactions = []
|
||||
tx_start = None
|
||||
last_rising = None
|
||||
|
||||
for i, (timestamp, state) in enumerate(edges):
|
||||
if state == 0: # Falling edge - start transaction if idle
|
||||
if tx_start is None and (last_rising is None or timestamp - last_rising > idle_threshold_s):
|
||||
tx_start = timestamp
|
||||
elif tx_start is not None: # Rising edge with active transaction
|
||||
last_rising = timestamp
|
||||
# Complete transaction if next edge is far away or this is the last edge
|
||||
next_gap = edges[i + 1][0] - timestamp if i + 1 < len(edges) else float('inf')
|
||||
if next_gap > idle_threshold_s:
|
||||
transactions.append(BDShotTransaction(start=tx_start, end=timestamp))
|
||||
tx_start = None
|
||||
else:
|
||||
last_rising = timestamp
|
||||
|
||||
if verbose:
|
||||
print(f"Detected {len(transactions)} transactions")
|
||||
if transactions:
|
||||
durations = [tx.duration_us for tx in transactions]
|
||||
print(f" Duration range: {min(durations):.1f} - {max(durations):.1f} us")
|
||||
|
||||
return transactions
|
||||
|
||||
|
||||
def compute_channel_stats(transactions, channel_name: str, expected_interval_us: float):
|
||||
"""Compute frame interval statistics for a channel."""
|
||||
if len(transactions) < 2:
|
||||
raise ValueError(f"Need at least 2 transactions to compute intervals, got {len(transactions)}")
|
||||
|
||||
intervals_us = np.diff([tx.start for tx in transactions]) * 1_000_000
|
||||
|
||||
stats = ChannelStats(
|
||||
channel_name=channel_name,
|
||||
count=len(intervals_us),
|
||||
min_us=float(np.min(intervals_us)),
|
||||
max_us=float(np.max(intervals_us)),
|
||||
mean_us=float(np.mean(intervals_us)),
|
||||
std_us=float(np.std(intervals_us)),
|
||||
expected_us=expected_interval_us,
|
||||
)
|
||||
|
||||
return stats, intervals_us
|
||||
|
||||
|
||||
def compute_inter_channel_gaps(transactions_a, transactions_b, expected_interval_us: float,
|
||||
verbose: bool = False):
|
||||
"""Compute inter-channel gap statistics (CH_A end -> CH_B start)."""
|
||||
gaps = []
|
||||
max_reasonable_gap_us = expected_interval_us * 0.5
|
||||
b_idx = 0
|
||||
|
||||
for tx_a in transactions_a:
|
||||
# Find first CH_B transaction that starts after this CH_A ends
|
||||
while b_idx < len(transactions_b) and transactions_b[b_idx].start <= tx_a.end:
|
||||
b_idx += 1
|
||||
if b_idx >= len(transactions_b):
|
||||
break
|
||||
|
||||
gap_us = (transactions_b[b_idx].start - tx_a.end) * 1_000_000
|
||||
if 0 < gap_us < max_reasonable_gap_us:
|
||||
gaps.append(gap_us)
|
||||
|
||||
if verbose:
|
||||
print(f"Inter-channel gap matching: {len(gaps)} matched")
|
||||
|
||||
if not gaps:
|
||||
raise ValueError("No valid inter-channel gaps found")
|
||||
|
||||
gaps_arr = np.array(gaps)
|
||||
stats = GapStats(
|
||||
count=len(gaps_arr),
|
||||
min_us=float(np.min(gaps_arr)),
|
||||
max_us=float(np.max(gaps_arr)),
|
||||
mean_us=float(np.mean(gaps_arr)),
|
||||
std_us=float(np.std(gaps_arr)),
|
||||
)
|
||||
|
||||
return stats, gaps_arr
|
||||
|
||||
|
||||
def _plot_histogram(ax, data, title: str, xlabel: str, expected_value=None, stats_text=None):
|
||||
"""Plot a histogram on the given axes."""
|
||||
bin_count = min(100, max(20, len(data) // 100)) if np.ptp(data) > 0 else 20
|
||||
ax.hist(data, bins=bin_count, edgecolor='black', alpha=0.7)
|
||||
ax.set_title(title, fontsize=12, fontweight='bold')
|
||||
ax.set_xlabel(xlabel, fontsize=10)
|
||||
ax.set_ylabel('Count', fontsize=10)
|
||||
|
||||
if expected_value is not None:
|
||||
ax.axvline(expected_value, color='red', linestyle='--', linewidth=2,
|
||||
label=f'Expected: {expected_value:.2f} us')
|
||||
ax.axvline(np.mean(data), color='green', linestyle='-', linewidth=2,
|
||||
label=f'Mean: {np.mean(data):.2f} us')
|
||||
|
||||
if stats_text:
|
||||
ax.text(0.98, 0.97, stats_text, transform=ax.transAxes, fontsize=9,
|
||||
verticalalignment='top', horizontalalignment='right',
|
||||
bbox=dict(boxstyle='round', facecolor='wheat', alpha=0.8), family='monospace')
|
||||
|
||||
ax.legend(loc='upper left', fontsize=8)
|
||||
ax.grid(True, alpha=0.3)
|
||||
|
||||
|
||||
def generate_combined_histogram(intervals_a, intervals_b, gaps, stats_a, stats_b,
|
||||
gap_stats, expected_interval_us: float, dshot_rate: int):
|
||||
"""Generate a combined figure with all histograms."""
|
||||
if not HAS_MATPLOTLIB:
|
||||
return None
|
||||
|
||||
fig = plt.figure(figsize=(14, 10))
|
||||
gs = fig.add_gridspec(2, 2, height_ratios=[1, 1], hspace=0.3, wspace=0.25)
|
||||
ax_a, ax_b, ax_gap = fig.add_subplot(gs[0, 0]), fig.add_subplot(gs[0, 1]), fig.add_subplot(gs[1, :])
|
||||
|
||||
def stats_text(s):
|
||||
return format_stats_text(s.min_us, s.max_us, s.mean_us, s.std_us, s.count)
|
||||
|
||||
_plot_histogram(ax_a, intervals_a, "Channel A Frame Intervals", "Interval (us)",
|
||||
expected_value=expected_interval_us, stats_text=stats_text(stats_a))
|
||||
_plot_histogram(ax_b, intervals_b, "Channel B Frame Intervals", "Interval (us)",
|
||||
expected_value=expected_interval_us, stats_text=stats_text(stats_b))
|
||||
|
||||
if len(gaps) > 0:
|
||||
_plot_histogram(ax_gap, gaps, "Inter-Channel Gap (CH_A End -> CH_B Start)",
|
||||
"Gap (us)", stats_text=stats_text(gap_stats))
|
||||
else:
|
||||
ax_gap.text(0.5, 0.5, "No inter-channel gap data available",
|
||||
ha='center', va='center', transform=ax_gap.transAxes)
|
||||
ax_gap.set_title("Inter-Channel Gap (CH_A End -> CH_B Start)")
|
||||
|
||||
fig.suptitle(f"BDShot Timing Analysis (DShot{dshot_rate})", fontsize=14, fontweight='bold', y=0.98)
|
||||
return fig
|
||||
|
||||
|
||||
def format_stats_text(min_val: float, max_val: float, mean_val: float,
|
||||
std_val: float, count: int) -> str:
|
||||
"""Format statistics as a text block for histogram annotation."""
|
||||
return (f"Count: {count}\n"
|
||||
f"Min: {min_val:.2f} us\n"
|
||||
f"Max: {max_val:.2f} us\n"
|
||||
f"Mean: {mean_val:.2f} us\n"
|
||||
f"Std: {std_val:.2f} us")
|
||||
|
||||
|
||||
def print_report(input_file: Path, dshot_rate: int, loop_rate: float,
|
||||
capture_duration: float, tx_count_a: int, tx_count_b: int,
|
||||
stats_a: ChannelStats, stats_b: ChannelStats, gap_stats: GapStats):
|
||||
"""Print the analysis report to console."""
|
||||
bit_period = DSHOT_BIT_PERIODS.get(dshot_rate, 3.33)
|
||||
expected_interval = 1_000_000 / loop_rate
|
||||
|
||||
print(f"""
|
||||
BDShot Timing Analysis
|
||||
{"=" * 60}
|
||||
Input: {input_file}
|
||||
DShot Rate: {dshot_rate} (bit period: {bit_period:.2f} us)
|
||||
Expected Loop Rate: {loop_rate:.0f} Hz ({expected_interval:.2f} us interval)
|
||||
Capture Duration: {capture_duration:.2f} s
|
||||
Transactions Detected: CH_A={tx_count_a}, CH_B={tx_count_b}
|
||||
""")
|
||||
|
||||
def print_channel_stats(name: str, s: ChannelStats):
|
||||
print(f"{name} Frame Intervals")
|
||||
print("-" * 40)
|
||||
print(f" Count: {s.count}")
|
||||
print(f" Min: {s.min_us:.2f} us ({s.min_jitter_us:+.2f} us from nominal)")
|
||||
print(f" Max: {s.max_us:.2f} us ({s.max_jitter_us:+.2f} us from nominal)")
|
||||
print(f" Mean: {s.mean_us:.2f} us ({s.mean_jitter_us:+.2f} us from nominal)")
|
||||
print(f" Std Dev: {s.std_us:.2f} us\n")
|
||||
|
||||
print_channel_stats("Channel A", stats_a)
|
||||
print_channel_stats("Channel B", stats_b)
|
||||
|
||||
print(f"""Inter-Channel Gap (CH_A End -> CH_B Start)
|
||||
{"-" * 40}
|
||||
Count: {gap_stats.count}
|
||||
Min: {gap_stats.min_us:.2f} us
|
||||
Max: {gap_stats.max_us:.2f} us
|
||||
Mean: {gap_stats.mean_us:.2f} us
|
||||
Std Dev: {gap_stats.std_us:.2f} us
|
||||
""")
|
||||
|
||||
|
||||
def fatal(msg: str):
|
||||
"""Print error and exit."""
|
||||
print(f"Error: {msg}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Analyze BDShot timing from Saleae Logic Analyzer CSV exports",
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
epilog="Examples:\n %(prog)s capture.csv\n %(prog)s capture.csv --dshot-rate 300 --loop-rate 800"
|
||||
)
|
||||
parser.add_argument('input_file', type=Path, help='Path to Saleae CSV export')
|
||||
parser.add_argument('--dshot-rate', type=int, default=300, choices=[150, 300, 600, 1200],
|
||||
help='DShot variant (default: 300)')
|
||||
parser.add_argument('--loop-rate', type=float, default=800, help='Expected loop rate in Hz (default: 800)')
|
||||
parser.add_argument('--channel-a', type=int, default=0, help='CSV column index for first channel (default: 0)')
|
||||
parser.add_argument('--channel-b', type=int, default=1, help='CSV column index for second channel (default: 1)')
|
||||
parser.add_argument('--no-plots', action='store_true', help='Disable histogram display')
|
||||
parser.add_argument('--verbose', '-v', action='store_true', help='Enable verbose output for debugging')
|
||||
args = parser.parse_args()
|
||||
|
||||
if not args.input_file.exists():
|
||||
fatal(f"Input file not found: {args.input_file}")
|
||||
|
||||
# Calculate timing parameters
|
||||
bit_period_us = DSHOT_BIT_PERIODS.get(args.dshot_rate, 3.33)
|
||||
idle_threshold_us = max(50.0, bit_period_us * 15) # Must exceed turnaround gap (~25-30us)
|
||||
expected_interval_us = 1_000_000 / args.loop_rate
|
||||
|
||||
if args.verbose:
|
||||
print(f"Bit period: {bit_period_us:.2f} us\nIdle threshold: {idle_threshold_us:.2f} us\n"
|
||||
f"Expected interval: {expected_interval_us:.2f} us\n")
|
||||
|
||||
# Parse CSV
|
||||
print(f"Parsing {args.input_file}...")
|
||||
try:
|
||||
edges_a, edges_b = parse_csv(args.input_file, args.channel_a, args.channel_b, args.verbose)
|
||||
except Exception as e:
|
||||
fatal(f"parsing CSV: {e}")
|
||||
|
||||
if not edges_a or not edges_b:
|
||||
fatal("No edges found in one or both channels")
|
||||
|
||||
# Detect transactions
|
||||
print("Detecting transactions...")
|
||||
transactions_a = detect_transactions(edges_a, idle_threshold_us, args.verbose)
|
||||
transactions_b = detect_transactions(edges_b, idle_threshold_us, args.verbose)
|
||||
|
||||
for name, txns in [("A", transactions_a), ("B", transactions_b)]:
|
||||
if len(txns) < 2:
|
||||
fatal(f"Insufficient transactions in channel {name} ({len(txns)})")
|
||||
|
||||
# Calculate capture duration
|
||||
all_txns = transactions_a + transactions_b
|
||||
capture_duration = max(tx.end for tx in all_txns) - min(tx.start for tx in all_txns)
|
||||
|
||||
# Compute statistics
|
||||
print("Computing statistics...")
|
||||
stats_a, intervals_a = compute_channel_stats(transactions_a, "Channel A", expected_interval_us)
|
||||
stats_b, intervals_b = compute_channel_stats(transactions_b, "Channel B", expected_interval_us)
|
||||
|
||||
try:
|
||||
gap_stats, gaps = compute_inter_channel_gaps(transactions_a, transactions_b,
|
||||
expected_interval_us, args.verbose)
|
||||
except ValueError as e:
|
||||
print(f"Warning: {e}", file=sys.stderr)
|
||||
gap_stats = GapStats(count=0, min_us=0, max_us=0, mean_us=0, std_us=0)
|
||||
gaps = np.array([])
|
||||
|
||||
print_report(args.input_file, args.dshot_rate, args.loop_rate, capture_duration,
|
||||
len(transactions_a), len(transactions_b), stats_a, stats_b, gap_stats)
|
||||
|
||||
if not args.no_plots and HAS_MATPLOTLIB:
|
||||
generate_combined_histogram(intervals_a, intervals_b, gaps, stats_a, stats_b,
|
||||
gap_stats, expected_interval_us, args.dshot_rate)
|
||||
plt.show()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -36,11 +36,20 @@ if args.filter:
|
||||
target_filter.append(target)
|
||||
|
||||
default_container = 'ghcr.io/px4/px4-dev:v1.16.0-rc1-258-g0369abd556'
|
||||
voxl2_container = 'ghcr.io/px4/px4-dev-voxl2:v1.5'
|
||||
build_configs = []
|
||||
grouped_targets = {}
|
||||
excluded_boards = ['modalai_voxl2', 'px4_ros2', 'espressif_esp32'] # TODO: fix and enable
|
||||
excluded_boards = ['px4_ros2', 'espressif_esp32'] # TODO: fix and enable
|
||||
excluded_manufacturers = ['atlflight']
|
||||
excluded_platforms = ['qurt']
|
||||
excluded_platforms = []
|
||||
|
||||
# Container overrides for platforms/boards that need a non-default container
|
||||
platform_container_overrides = {
|
||||
'qurt': voxl2_container,
|
||||
}
|
||||
board_container_overrides = {
|
||||
'modalai_voxl2': voxl2_container,
|
||||
}
|
||||
excluded_labels = [
|
||||
'stackcheck',
|
||||
'nolockstep', 'replay', 'test',
|
||||
@@ -88,7 +97,20 @@ def process_target(px4board_file, target_name):
|
||||
|
||||
if platform not in excluded_platforms:
|
||||
container = default_container
|
||||
if platform == 'posix':
|
||||
|
||||
# Extract board name (manufacturer_board) from target name
|
||||
board_name = '_'.join(target_name.split('_')[:2])
|
||||
|
||||
# Apply container overrides for specific platforms or boards
|
||||
if platform in platform_container_overrides:
|
||||
container = platform_container_overrides[platform]
|
||||
if board_name in board_container_overrides:
|
||||
container = board_container_overrides[board_name]
|
||||
|
||||
# Boards with container overrides get their own group
|
||||
if board_name in board_container_overrides or platform in platform_container_overrides:
|
||||
group = 'voxl2'
|
||||
elif platform == 'posix':
|
||||
group = 'base'
|
||||
if toolchain:
|
||||
if toolchain.startswith('aarch64'):
|
||||
@@ -203,7 +225,7 @@ if (args.group):
|
||||
if(verbose):
|
||||
print(f'=:Architectures: [{grouped_targets.keys()}]')
|
||||
for arch in grouped_targets:
|
||||
runner = 'x64' if arch == 'nuttx' else 'arm64'
|
||||
runner = 'x64' if arch in ('nuttx', 'voxl2') else 'arm64'
|
||||
if(verbose):
|
||||
print(f'=:Processing: [{arch}]')
|
||||
temp_group = []
|
||||
|
||||
Executable
+431
@@ -0,0 +1,431 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# metadata_sync.sh - Unified metadata generation and synchronization for PX4 docs
|
||||
#
|
||||
# Usage:
|
||||
# Tools/ci/metadata_sync.sh [OPTIONS] [TYPES...]
|
||||
#
|
||||
# Types:
|
||||
# parameters - Parameter reference (docs/en/advanced_config/parameter_reference.md)
|
||||
# airframes - Airframe reference (docs/en/airframes/airframe_reference.md)
|
||||
# modules - Module documentation (docs/en/modules/*.md)
|
||||
# msg_docs - uORB message docs (docs/en/msg_docs/*.md + docs/en/middleware/dds_topics.md)
|
||||
# uorb_graphs - uORB graph JSONs (docs/public/middleware/*.json)
|
||||
# failsafe_web - Failsafe simulator (docs/public/config/failsafe/*.{js,wasm,json})
|
||||
# all - All of the above (default)
|
||||
#
|
||||
# Options:
|
||||
# --generate Build the make targets to generate fresh metadata
|
||||
# --sync Copy generated files to docs/
|
||||
# --verbose Show detailed output
|
||||
# --help Show this help
|
||||
#
|
||||
# Exit codes:
|
||||
# 0 - Success (files synced or already up-to-date)
|
||||
# 1 - Error (build failed, missing files, etc.)
|
||||
#
|
||||
# Examples:
|
||||
# # Full regeneration and sync (orchestrator use case)
|
||||
# Tools/ci/metadata_sync.sh --generate --sync all
|
||||
#
|
||||
# # Just sync specific type (assumes already built)
|
||||
# Tools/ci/metadata_sync.sh --sync parameters
|
||||
#
|
||||
# # Generate only, don't copy
|
||||
# Tools/ci/metadata_sync.sh --generate uorb_graphs
|
||||
#
|
||||
set -euo pipefail
|
||||
shopt -s nullglob
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
# Configuration
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
EMSCRIPTEN_VERSION="3.1.64"
|
||||
EMSDK_DIR="${EMSDK_DIR:-_emscripten_sdk}"
|
||||
|
||||
# All available metadata types
|
||||
ALL_TYPES=(parameters airframes modules msg_docs uorb_graphs failsafe_web)
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
# Logging
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
VERBOSE=false
|
||||
|
||||
log() {
|
||||
echo "[metadata_sync] $*"
|
||||
}
|
||||
|
||||
log_verbose() {
|
||||
if [[ "$VERBOSE" == "true" ]]; then
|
||||
echo "[metadata_sync] $*"
|
||||
fi
|
||||
}
|
||||
|
||||
die() {
|
||||
echo "[metadata_sync] ERROR: $*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
# Help
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
show_help() {
|
||||
head -n 35 "$0" | tail -n +2 | sed 's/^# \?//'
|
||||
exit 0
|
||||
}
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
# Emscripten Setup
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
ensure_emscripten() {
|
||||
if command -v emcc >/dev/null 2>&1; then
|
||||
log_verbose "Emscripten already available: $(emcc --version | head -1)"
|
||||
return 0
|
||||
fi
|
||||
|
||||
log "Setting up Emscripten ${EMSCRIPTEN_VERSION}..."
|
||||
|
||||
if [[ ! -d "$EMSDK_DIR" ]]; then
|
||||
log_verbose "Cloning emsdk to $EMSDK_DIR"
|
||||
if [[ "$VERBOSE" == "true" ]]; then
|
||||
git clone https://github.com/emscripten-core/emsdk.git "$EMSDK_DIR"
|
||||
else
|
||||
git clone https://github.com/emscripten-core/emsdk.git "$EMSDK_DIR" >/dev/null 2>&1
|
||||
fi
|
||||
fi
|
||||
|
||||
pushd "$EMSDK_DIR" >/dev/null
|
||||
if [[ "$VERBOSE" == "true" ]]; then
|
||||
./emsdk install "$EMSCRIPTEN_VERSION"
|
||||
./emsdk activate "$EMSCRIPTEN_VERSION"
|
||||
else
|
||||
./emsdk install "$EMSCRIPTEN_VERSION" >/dev/null 2>&1
|
||||
./emsdk activate "$EMSCRIPTEN_VERSION" >/dev/null 2>&1
|
||||
fi
|
||||
popd >/dev/null
|
||||
|
||||
# shellcheck source=/dev/null
|
||||
source "${EMSDK_DIR}/emsdk_env.sh" >/dev/null 2>&1
|
||||
|
||||
log_verbose "Emscripten ready: $(emcc --version | head -1)"
|
||||
}
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
# Generation Functions
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
generate_parameters() {
|
||||
log "Generating parameters metadata..."
|
||||
if [[ "$VERBOSE" == "true" ]]; then
|
||||
make parameters_metadata
|
||||
else
|
||||
make parameters_metadata >/dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
generate_airframes() {
|
||||
log "Generating airframes metadata..."
|
||||
if [[ "$VERBOSE" == "true" ]]; then
|
||||
make airframe_metadata
|
||||
else
|
||||
make airframe_metadata >/dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
generate_modules() {
|
||||
log "Generating modules documentation..."
|
||||
if [[ "$VERBOSE" == "true" ]]; then
|
||||
make module_documentation
|
||||
else
|
||||
make module_documentation >/dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
generate_msg_docs() {
|
||||
log "Generating message documentation..."
|
||||
if [[ "$VERBOSE" == "true" ]]; then
|
||||
make msg_docs
|
||||
else
|
||||
make msg_docs >/dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
generate_uorb_graphs() {
|
||||
log "Generating uORB graphs..."
|
||||
if [[ "$VERBOSE" == "true" ]]; then
|
||||
make uorb_graphs
|
||||
else
|
||||
make uorb_graphs >/dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
generate_failsafe_web() {
|
||||
ensure_emscripten
|
||||
log "Generating failsafe web..."
|
||||
if [[ "$VERBOSE" == "true" ]]; then
|
||||
make failsafe_web
|
||||
else
|
||||
make failsafe_web >/dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
# Sync Functions
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
sync_parameters() {
|
||||
local src="build/px4_sitl_default/docs/parameters.md"
|
||||
local dest="docs/en/advanced_config/parameter_reference.md"
|
||||
|
||||
log "Syncing parameters..."
|
||||
|
||||
if [[ ! -f "$src" ]]; then
|
||||
die "Source file not found: $src (did you run --generate?)"
|
||||
fi
|
||||
|
||||
mkdir -p "$(dirname "$dest")"
|
||||
cp "$src" "$dest"
|
||||
log_verbose " $src -> $dest"
|
||||
}
|
||||
|
||||
sync_airframes() {
|
||||
local src="build/px4_sitl_default/docs/airframes.md"
|
||||
local dest="docs/en/airframes/airframe_reference.md"
|
||||
|
||||
log "Syncing airframes..."
|
||||
|
||||
if [[ ! -f "$src" ]]; then
|
||||
die "Source file not found: $src (did you run --generate?)"
|
||||
fi
|
||||
|
||||
mkdir -p "$(dirname "$dest")"
|
||||
cp "$src" "$dest"
|
||||
log_verbose " $src -> $dest"
|
||||
}
|
||||
|
||||
sync_modules() {
|
||||
local src_dir="build/px4_sitl_default/docs/modules"
|
||||
local dest_dir="docs/en/modules"
|
||||
|
||||
log "Syncing modules..."
|
||||
|
||||
if [[ ! -d "$src_dir" ]]; then
|
||||
die "Source directory not found: $src_dir (did you run --generate?)"
|
||||
fi
|
||||
|
||||
local src_files=("$src_dir"/*.md)
|
||||
if [[ ${#src_files[@]} -eq 0 ]]; then
|
||||
die "No .md files found in $src_dir"
|
||||
fi
|
||||
|
||||
mkdir -p "$dest_dir"
|
||||
|
||||
for src in "${src_files[@]}"; do
|
||||
local name
|
||||
name=$(basename "$src")
|
||||
cp "$src" "$dest_dir/$name"
|
||||
log_verbose " $src -> $dest_dir/$name"
|
||||
done
|
||||
}
|
||||
|
||||
sync_msg_docs() {
|
||||
local src_dir="build/msg_docs"
|
||||
local dest_dir="docs/en/msg_docs"
|
||||
local middleware_dir="docs/en/middleware"
|
||||
|
||||
log "Syncing message docs..."
|
||||
|
||||
if [[ ! -d "$src_dir" ]]; then
|
||||
die "Source directory not found: $src_dir (did you run --generate?)"
|
||||
fi
|
||||
|
||||
local src_files=("$src_dir"/*.md)
|
||||
if [[ ${#src_files[@]} -eq 0 ]]; then
|
||||
die "No .md files found in $src_dir"
|
||||
fi
|
||||
|
||||
mkdir -p "$dest_dir"
|
||||
mkdir -p "$middleware_dir"
|
||||
|
||||
for src in "${src_files[@]}"; do
|
||||
local name
|
||||
name=$(basename "$src")
|
||||
|
||||
# dds_topics.md goes to middleware dir
|
||||
if [[ "$name" == "dds_topics.md" ]]; then
|
||||
cp "$src" "$middleware_dir/$name"
|
||||
log_verbose " $src -> $middleware_dir/$name"
|
||||
else
|
||||
cp "$src" "$dest_dir/$name"
|
||||
log_verbose " $src -> $dest_dir/$name"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
sync_uorb_graphs() {
|
||||
local src_dir="Tools/uorb_graph"
|
||||
local dest_dir="docs/public/middleware"
|
||||
|
||||
log "Syncing uORB graphs..."
|
||||
|
||||
local src_files=("$src_dir"/*.json)
|
||||
if [[ ${#src_files[@]} -eq 0 ]]; then
|
||||
die "No .json files found in $src_dir (did you run --generate?)"
|
||||
fi
|
||||
|
||||
mkdir -p "$dest_dir"
|
||||
|
||||
for src in "${src_files[@]}"; do
|
||||
local name
|
||||
name=$(basename "$src")
|
||||
cp "$src" "$dest_dir/$name"
|
||||
log_verbose " $src -> $dest_dir/$name"
|
||||
done
|
||||
}
|
||||
|
||||
sync_failsafe_web() {
|
||||
local src_dir="build/px4_sitl_default_failsafe_web"
|
||||
local dest_dir="docs/public/config/failsafe"
|
||||
|
||||
log "Syncing failsafe web..."
|
||||
|
||||
if [[ ! -d "$src_dir" ]]; then
|
||||
die "Source directory not found: $src_dir (did you run --generate?)"
|
||||
fi
|
||||
|
||||
# Gather js, wasm, json files
|
||||
local src_files=()
|
||||
for ext in js wasm json; do
|
||||
src_files+=("$src_dir"/*."$ext")
|
||||
done
|
||||
|
||||
if [[ ${#src_files[@]} -eq 0 ]]; then
|
||||
die "No .js/.wasm/.json files found in $src_dir"
|
||||
fi
|
||||
|
||||
mkdir -p "$dest_dir"
|
||||
|
||||
for src in "${src_files[@]}"; do
|
||||
local name
|
||||
name=$(basename "$src")
|
||||
cp "$src" "$dest_dir/$name"
|
||||
log_verbose " $src -> $dest_dir/$name"
|
||||
done
|
||||
}
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
# Main Logic
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
DO_GENERATE=false
|
||||
DO_SYNC=false
|
||||
SELECTED_TYPES=()
|
||||
|
||||
parse_args() {
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--generate)
|
||||
DO_GENERATE=true
|
||||
shift
|
||||
;;
|
||||
--sync)
|
||||
DO_SYNC=true
|
||||
shift
|
||||
;;
|
||||
--verbose)
|
||||
VERBOSE=true
|
||||
shift
|
||||
;;
|
||||
--help|-h)
|
||||
show_help
|
||||
;;
|
||||
-*)
|
||||
die "Unknown option: $1"
|
||||
;;
|
||||
*)
|
||||
# It's a type
|
||||
SELECTED_TYPES+=("$1")
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Default to all types if none specified
|
||||
if [[ ${#SELECTED_TYPES[@]} -eq 0 ]]; then
|
||||
SELECTED_TYPES=("all")
|
||||
fi
|
||||
|
||||
# Expand "all" to all types
|
||||
local expanded_types=()
|
||||
for t in "${SELECTED_TYPES[@]}"; do
|
||||
if [[ "$t" == "all" ]]; then
|
||||
expanded_types+=("${ALL_TYPES[@]}")
|
||||
else
|
||||
expanded_types+=("$t")
|
||||
fi
|
||||
done
|
||||
SELECTED_TYPES=("${expanded_types[@]}")
|
||||
|
||||
# Validate types
|
||||
for t in "${SELECTED_TYPES[@]}"; do
|
||||
local valid=false
|
||||
for valid_type in "${ALL_TYPES[@]}"; do
|
||||
if [[ "$t" == "$valid_type" ]]; then
|
||||
valid=true
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [[ "$valid" == "false" ]]; then
|
||||
die "Unknown type: $t (valid: ${ALL_TYPES[*]})"
|
||||
fi
|
||||
done
|
||||
|
||||
# Must specify at least one action
|
||||
if [[ "$DO_GENERATE" == "false" && "$DO_SYNC" == "false" ]]; then
|
||||
die "Must specify at least one of: --generate, --sync"
|
||||
fi
|
||||
}
|
||||
|
||||
main() {
|
||||
parse_args "$@"
|
||||
|
||||
log "Selected types: ${SELECTED_TYPES[*]}"
|
||||
[[ "$DO_GENERATE" == "true" ]] && log "Actions: generate"
|
||||
[[ "$DO_SYNC" == "true" ]] && log "Actions: sync"
|
||||
|
||||
# Remove duplicates from SELECTED_TYPES
|
||||
local -A seen
|
||||
local unique_types=()
|
||||
for t in "${SELECTED_TYPES[@]}"; do
|
||||
if [[ -z "${seen[$t]:-}" ]]; then
|
||||
seen[$t]=1
|
||||
unique_types+=("$t")
|
||||
fi
|
||||
done
|
||||
SELECTED_TYPES=("${unique_types[@]}")
|
||||
|
||||
# Generate phase
|
||||
if [[ "$DO_GENERATE" == "true" ]]; then
|
||||
log "=== Generation Phase ==="
|
||||
for t in "${SELECTED_TYPES[@]}"; do
|
||||
"generate_$t"
|
||||
done
|
||||
fi
|
||||
|
||||
# Sync phase
|
||||
if [[ "$DO_SYNC" == "true" ]]; then
|
||||
log "=== Sync Phase ==="
|
||||
for t in "${SELECTED_TYPES[@]}"; do
|
||||
"sync_$t"
|
||||
done
|
||||
fi
|
||||
|
||||
log "Done."
|
||||
exit 0
|
||||
}
|
||||
|
||||
main "$@"
|
||||
@@ -1,8 +1,8 @@
|
||||
#!/bin/bash
|
||||
|
||||
mkdir artifacts
|
||||
cp **/**/*.px4 artifacts/
|
||||
cp **/**/*.elf artifacts/
|
||||
cp **/**/*.px4 artifacts/ 2>/dev/null || true
|
||||
cp **/**/*.elf artifacts/ 2>/dev/null || true
|
||||
for build_dir_path in build/*/ ; do
|
||||
build_dir_path=${build_dir_path::${#build_dir_path}-1}
|
||||
build_dir=${build_dir_path#*/}
|
||||
|
||||
Executable
+163
@@ -0,0 +1,163 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# test_metadata_sync.sh - Test metadata_sync.sh locally using Docker
|
||||
#
|
||||
# Usage:
|
||||
# Tools/ci/test_metadata_sync.sh [OPTIONS] [TYPES...]
|
||||
#
|
||||
# Options:
|
||||
# --shell Drop into interactive shell instead of running sync
|
||||
# --verbose Pass --verbose to metadata_sync.sh
|
||||
# --skip-build Skip SITL build (use existing build artifacts)
|
||||
# --help Show this help
|
||||
#
|
||||
# Types:
|
||||
# Same as metadata_sync.sh: parameters, airframes, modules, msg_docs, uorb_graphs, failsafe_web, all
|
||||
#
|
||||
# Examples:
|
||||
# # Test full regeneration
|
||||
# Tools/ci/test_metadata_sync.sh all
|
||||
#
|
||||
# # Test just parameters (faster)
|
||||
# Tools/ci/test_metadata_sync.sh parameters
|
||||
#
|
||||
# # Drop into shell for debugging
|
||||
# Tools/ci/test_metadata_sync.sh --shell
|
||||
#
|
||||
# # Skip build if you already have artifacts
|
||||
# Tools/ci/test_metadata_sync.sh --skip-build --verbose all
|
||||
#
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
|
||||
DOCKER_IMAGE="px4io/px4-dev:v1.17.0-alpha1"
|
||||
CONTAINER_NAME="px4-metadata-test-$$"
|
||||
|
||||
SHELL_MODE=false
|
||||
VERBOSE=""
|
||||
SKIP_BUILD=false
|
||||
TYPES=()
|
||||
|
||||
show_help() {
|
||||
head -n 28 "$0" | tail -n +2 | sed 's/^# \?//'
|
||||
exit 0
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
echo "[test] Cleaning up container..."
|
||||
docker rm -f "$CONTAINER_NAME" 2>/dev/null || true
|
||||
}
|
||||
|
||||
parse_args() {
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--shell)
|
||||
SHELL_MODE=true
|
||||
shift
|
||||
;;
|
||||
--verbose)
|
||||
VERBOSE="--verbose"
|
||||
shift
|
||||
;;
|
||||
--skip-build)
|
||||
SKIP_BUILD=true
|
||||
shift
|
||||
;;
|
||||
--help|-h)
|
||||
show_help
|
||||
;;
|
||||
-*)
|
||||
echo "Unknown option: $1" >&2
|
||||
exit 1
|
||||
;;
|
||||
*)
|
||||
TYPES+=("$1")
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Default to all types
|
||||
if [[ ${#TYPES[@]} -eq 0 ]]; then
|
||||
TYPES=("all")
|
||||
fi
|
||||
}
|
||||
|
||||
main() {
|
||||
parse_args "$@"
|
||||
|
||||
cd "$REPO_ROOT"
|
||||
|
||||
echo "[test] Using Docker image: $DOCKER_IMAGE"
|
||||
echo "[test] Repository root: $REPO_ROOT"
|
||||
|
||||
# Pull image if not present
|
||||
if ! docker image inspect "$DOCKER_IMAGE" >/dev/null 2>&1; then
|
||||
echo "[test] Pulling Docker image..."
|
||||
docker pull "$DOCKER_IMAGE"
|
||||
fi
|
||||
|
||||
trap cleanup EXIT
|
||||
|
||||
# Handle git worktrees: the .git file points to the main repo's .git directory
|
||||
# We need to mount that directory too so git works inside the container
|
||||
local git_mounts=()
|
||||
if [[ -f "$REPO_ROOT/.git" ]]; then
|
||||
# It's a worktree - read the gitdir path and mount it
|
||||
local gitdir
|
||||
gitdir=$(grep '^gitdir:' "$REPO_ROOT/.git" | cut -d' ' -f2)
|
||||
if [[ -n "$gitdir" ]]; then
|
||||
# Mount the gitdir at the same path so the .git file reference works
|
||||
git_mounts+=("-v" "$gitdir:$gitdir:ro")
|
||||
# Also need the main .git directory (parent of worktrees/)
|
||||
local main_git_dir
|
||||
main_git_dir=$(dirname "$(dirname "$gitdir")")
|
||||
git_mounts+=("-v" "$main_git_dir:$main_git_dir:ro")
|
||||
echo "[test] Detected git worktree, mounting git directories"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$SHELL_MODE" == "true" ]]; then
|
||||
echo "[test] Starting interactive shell..."
|
||||
echo "[test] Run: Tools/ci/metadata_sync.sh --generate --sync all"
|
||||
docker run -it --rm \
|
||||
--name "$CONTAINER_NAME" \
|
||||
-v "$REPO_ROOT:/src" \
|
||||
"${git_mounts[@]}" \
|
||||
-w /src \
|
||||
"$DOCKER_IMAGE" \
|
||||
/bin/bash
|
||||
else
|
||||
echo "[test] Running metadata sync for: ${TYPES[*]}"
|
||||
|
||||
# Build the command
|
||||
local cmd=""
|
||||
|
||||
if [[ "$SKIP_BUILD" == "false" ]]; then
|
||||
cmd="Tools/ci/metadata_sync.sh --generate --sync $VERBOSE ${TYPES[*]}"
|
||||
else
|
||||
cmd="Tools/ci/metadata_sync.sh --sync $VERBOSE ${TYPES[*]}"
|
||||
fi
|
||||
|
||||
echo "[test] Command: $cmd"
|
||||
|
||||
docker run --rm \
|
||||
--name "$CONTAINER_NAME" \
|
||||
-v "$REPO_ROOT:/src" \
|
||||
"${git_mounts[@]}" \
|
||||
-w /src \
|
||||
"$DOCKER_IMAGE" \
|
||||
/bin/bash -c "$cmd"
|
||||
|
||||
echo ""
|
||||
echo "[test] Done! Check git status for changes:"
|
||||
echo " git status -s docs/"
|
||||
echo ""
|
||||
echo "[test] To see what changed:"
|
||||
echo " git diff docs/"
|
||||
fi
|
||||
}
|
||||
|
||||
main "$@"
|
||||
+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 "$@"
|
||||
|
||||
@@ -729,10 +729,10 @@ pageClass: is-wide-page
|
||||
|
||||
# Fix up topics if the topic is empty
|
||||
def camel_to_snake(name):
|
||||
# Match upper case not at start of string
|
||||
s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
|
||||
# Handle cases with multiple capital first letter
|
||||
return re.sub('([A-Z]+)([A-Z][a-z]*)', r'\1_\2', s1).lower()
|
||||
# Insert underscore between lowercase/digit and uppercase letter
|
||||
s1 = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name)
|
||||
# Insert underscore between consecutive uppercase and uppercase+lowercase
|
||||
return re.sub('([A-Z]+)([A-Z][a-z])', r'\1_\2', s1).lower()
|
||||
|
||||
defaultTopic = camel_to_snake(self.name)
|
||||
if len(self.topics) == 0:
|
||||
@@ -745,7 +745,7 @@ pageClass: is-wide-page
|
||||
error = Error("topic_error", self.filename, "", f"WARNING: TOPIC {defaultTopic} unnecessarily declared for {self.name}")
|
||||
else:
|
||||
# Declared topic is not default topic
|
||||
error = Error("topic_error", self.filename, "", f"NOTE: TOPIC {self.topics[1]}: Only Declared topic is not default topic {defaultTopic} for {self.name}")
|
||||
error = Error("topic_error", self.filename, "", f"NOTE: TOPIC {self.topics[0]}: Only Declared topic is not default topic {defaultTopic} for {self.name}")
|
||||
if not "topic_error" in self.errors:
|
||||
self.errors["topic_error"] = []
|
||||
self.errors["topic_error"].append(error)
|
||||
|
||||
@@ -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 "$@"
|
||||
|
||||
@@ -74,7 +74,7 @@ python3 -m pip install --user -r ${DIR}/requirements.txt
|
||||
|
||||
# Optional, but recommended additional simulation tools:
|
||||
if [[ $INSTALL_SIM == "--sim-tools" ]]; then
|
||||
if brew ls --versions px4-sim > /dev/null; then
|
||||
if ! brew ls --versions px4-sim > /dev/null; then
|
||||
brew install px4-sim
|
||||
elif [[ $REINSTALL_FORMULAS == "--reinstall" ]]; then
|
||||
brew reinstall px4-sim
|
||||
|
||||
+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 \
|
||||
|
||||
+1
-1
Submodule Tools/simulation/gz updated: fe3fe236e3...3eb05f716a
@@ -28,10 +28,16 @@ CONFIG_DRIVERS_IMU_INVENSENSE_IIM42653=y
|
||||
CONFIG_DRIVERS_IMU_MURATA_SCH16T=y
|
||||
CONFIG_COMMON_LIGHT=y
|
||||
CONFIG_DRIVERS_MAGNETOMETER_BOSCH_BMM150=y
|
||||
CONFIG_DRIVERS_MAGNETOMETER_HMC5883=y
|
||||
CONFIG_DRIVERS_MAGNETOMETER_QMC5883L=y
|
||||
CONFIG_DRIVERS_MAGNETOMETER_ISENTEK_IST8308=y
|
||||
CONFIG_DRIVERS_MAGNETOMETER_ISENTEK_IST8310=y
|
||||
CONFIG_DRIVERS_MAGNETOMETER_LIS3MDL=y
|
||||
CONFIG_DRIVERS_MAGNETOMETER_LSM303AGR=y
|
||||
CONFIG_DRIVERS_MAGNETOMETER_RM3100=y
|
||||
CONFIG_DRIVERS_MAGNETOMETER_ST_IIS2MDC=y
|
||||
CONFIG_DRIVERS_POWER_MONITOR_INA226=y
|
||||
CONFIG_DRIVERS_POWER_MONITOR_INA228=y
|
||||
CONFIG_DRIVERS_POWER_MONITOR_INA238=y
|
||||
CONFIG_DRIVERS_PCA9685_PWM_OUT=y
|
||||
CONFIG_DRIVERS_PWM_OUT=y
|
||||
|
||||
@@ -243,15 +243,6 @@
|
||||
*/
|
||||
#define DIRECT_PWM_OUTPUT_CHANNELS 9
|
||||
|
||||
#define GPIO_FMU_CH1 /* PI0 */ (GPIO_INPUT|GPIO_PULLDOWN|GPIO_PORTI|GPIO_PIN0)
|
||||
#define GPIO_FMU_CH2 /* PH12 */ (GPIO_INPUT|GPIO_PULLDOWN|GPIO_PORTH|GPIO_PIN12)
|
||||
#define GPIO_FMU_CH3 /* PH11 */ (GPIO_INPUT|GPIO_PULLDOWN|GPIO_PORTH|GPIO_PIN11)
|
||||
#define GPIO_FMU_CH4 /* PH10 */ (GPIO_INPUT|GPIO_PULLDOWN|GPIO_PORTH|GPIO_PIN10)
|
||||
#define GPIO_FMU_CH5 /* PD13 */ (GPIO_INPUT|GPIO_PULLDOWN|GPIO_PORTD|GPIO_PIN13)
|
||||
#define GPIO_FMU_CH6 /* PD14 */ (GPIO_INPUT|GPIO_PULLDOWN|GPIO_PORTD|GPIO_PIN14)
|
||||
#define GPIO_FMU_CH7 /* PH6 */ (GPIO_INPUT|GPIO_PULLDOWN|GPIO_PORTH|GPIO_PIN6)
|
||||
#define GPIO_FMU_CH8 /* PH9 */ (GPIO_INPUT|GPIO_PULLDOWN|GPIO_PORTH|GPIO_PIN9)
|
||||
|
||||
#define GPIO_FMU_CAP /* PE11 */ (GPIO_INPUT|GPIO_PULLDOWN|GPIO_PORTE|GPIO_PIN11)
|
||||
#define GPIO_SPIX_SYNC /* PE9 */ (GPIO_INPUT|GPIO_PULLDOWN|GPIO_PORTE|GPIO_PIN9)
|
||||
|
||||
@@ -419,6 +410,9 @@
|
||||
/* This board provides a DMA pool and APIs */
|
||||
#define BOARD_DMA_ALLOC_POOL_SIZE 5120
|
||||
|
||||
/* This board has 4 DMA channels available for bidirectional dshot */
|
||||
#define BOARD_DMA_NUM_DSHOT_CHANNELS 4
|
||||
|
||||
/* This board provides the board_on_reset interface */
|
||||
|
||||
#define BOARD_HAS_ON_RESET 1
|
||||
@@ -462,14 +456,6 @@
|
||||
GPIO_SAFETY_SWITCH_IN, \
|
||||
GPIO_PG6, \
|
||||
GPIO_nARMED_INIT, \
|
||||
GPIO_FMU_CH1, \
|
||||
GPIO_FMU_CH2, \
|
||||
GPIO_FMU_CH3, \
|
||||
GPIO_FMU_CH4, \
|
||||
GPIO_FMU_CH5, \
|
||||
GPIO_FMU_CH6, \
|
||||
GPIO_FMU_CH7, \
|
||||
GPIO_FMU_CH8, \
|
||||
GPIO_FMU_CAP, \
|
||||
GPIO_SPIX_SYNC \
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
# CONFIG_BOARD_UAVCAN_TIMER_OVERRIDE is not set
|
||||
CONFIG_BOARD_CONSTRAINED_FLASH=y
|
||||
CONFIG_BOARD_CONSTRAINED_MEMORY=y
|
||||
CONFIG_MODULES_UXRCE_DDS_CLIENT=n
|
||||
CONFIG_MODULES_ZENOH=y
|
||||
@@ -14,7 +14,6 @@ CONFIG_DRIVERS_CDCACM_AUTOSTART=y
|
||||
CONFIG_COMMON_DIFFERENTIAL_PRESSURE=y
|
||||
CONFIG_COMMON_DISTANCE_SENSOR=y
|
||||
CONFIG_DRIVERS_DSHOT=y
|
||||
CONFIG_DSHOT_BITBANG=y
|
||||
CONFIG_DRIVERS_GPS=y
|
||||
CONFIG_DRIVERS_HEATER=y
|
||||
CONFIG_DRIVERS_IMU_INVENSENSE_IIM42653=y
|
||||
@@ -60,7 +59,6 @@ CONFIG_MODULES_LOGGER=y
|
||||
CONFIG_MODULES_MAG_BIAS_ESTIMATOR=y
|
||||
CONFIG_MODULES_MANUAL_CONTROL=y
|
||||
CONFIG_MODULES_MAVLINK=y
|
||||
CONFIG_MAVLINK_DIALECT="development"
|
||||
CONFIG_MODULES_MC_ATT_CONTROL=y
|
||||
CONFIG_MODULES_MC_AUTOTUNE_ATTITUDE_CONTROL=y
|
||||
CONFIG_MODULES_MC_HOVER_THRUST_ESTIMATOR=y
|
||||
|
||||
Binary file not shown.
@@ -1,18 +0,0 @@
|
||||
4001_quad_x
|
||||
4050_generic_250
|
||||
6001_hexa_x
|
||||
12001_octo_cox
|
||||
13100_generic_vtol_tiltrotor
|
||||
5001_quad_+
|
||||
24001_dodeca_cox
|
||||
2100_standard_plane
|
||||
13000_generic_vtol_standard
|
||||
4601_droneblocks_dexi_5
|
||||
11001_hexa_cox
|
||||
14001_generic_mc_with_tilt
|
||||
16001_helicopter
|
||||
9001_octo_+
|
||||
7001_hexa_+
|
||||
3000_generic_wing
|
||||
13200_generic_vtol_tailsitter
|
||||
13030_generic_vtol_quad_tiltrotor
|
||||
@@ -26,6 +26,8 @@ then
|
||||
fi
|
||||
|
||||
param set-default BAT1_V_DIV 21.0
|
||||
param set-default BAT1_V_FILT 0.075
|
||||
param set-default BAT1_I_FILT 0.5
|
||||
|
||||
param set-default RC_CRSF_PRT_CFG 300
|
||||
param set-default RC_SBUS_PRT_CFG 0
|
||||
|
||||
@@ -176,9 +176,6 @@
|
||||
|
||||
#define BOARD_BATTERY1_V_DIV (21.0f) // (20k + 1k) / 1k = 21
|
||||
|
||||
#define BOARD_BATTERY_ADC_VOLTAGE_FILTER_S 0.075f
|
||||
#define BOARD_BATTERY_ADC_CURRENT_FILTER_S 0.125f
|
||||
|
||||
#define ADC_SCALED_PAYLOAD_SENSE ADC_SCALED_12V_CHANNEL
|
||||
|
||||
/* HW has to large of R termination on ADC todo:change when HW value is chosen */
|
||||
@@ -226,16 +223,6 @@
|
||||
*/
|
||||
#define DIRECT_PWM_OUTPUT_CHANNELS 9
|
||||
|
||||
#define GPIO_FMU_CH1 /* PI0 */ (GPIO_INPUT|GPIO_PULLDOWN|GPIO_PORTI|GPIO_PIN0)
|
||||
#define GPIO_FMU_CH2 /* PH12 */ (GPIO_INPUT|GPIO_PULLDOWN|GPIO_PORTH|GPIO_PIN12)
|
||||
#define GPIO_FMU_CH3 /* PH11 */ (GPIO_INPUT|GPIO_PULLDOWN|GPIO_PORTH|GPIO_PIN11)
|
||||
#define GPIO_FMU_CH4 /* PH10 */ (GPIO_INPUT|GPIO_PULLDOWN|GPIO_PORTH|GPIO_PIN10)
|
||||
#define GPIO_FMU_CH5 /* PI5 */ (GPIO_INPUT|GPIO_PULLDOWN|GPIO_PORTI|GPIO_PIN5)
|
||||
#define GPIO_FMU_CH6 /* PI6 */ (GPIO_INPUT|GPIO_PULLDOWN|GPIO_PORTI|GPIO_PIN6)
|
||||
#define GPIO_FMU_CH7 /* PI7 */ (GPIO_INPUT|GPIO_PULLDOWN|GPIO_PORTI|GPIO_PIN7)
|
||||
#define GPIO_FMU_CH8 /* PI2 */ (GPIO_INPUT|GPIO_PULLDOWN|GPIO_PORTI|GPIO_PIN2)
|
||||
#define GPIO_FMU_CH9 /* PD12 */ (GPIO_INPUT|GPIO_PULLDOWN|GPIO_PORTD|GPIO_PIN12)
|
||||
|
||||
#define GPIO_SPIX_SYNC /* PE9 */ (GPIO_INPUT|GPIO_PULLDOWN|GPIO_PORTE|GPIO_PIN9)
|
||||
|
||||
/* Power supply control and monitoring GPIOs */
|
||||
@@ -307,6 +294,9 @@
|
||||
/* This board provides a DMA pool and APIs */
|
||||
#define BOARD_DMA_ALLOC_POOL_SIZE 5120
|
||||
|
||||
/* This board has 3 DMA channels available for bidirectional dshot */
|
||||
#define BOARD_DMA_NUM_DSHOT_CHANNELS 3
|
||||
|
||||
/* This board provides the board_on_reset interface */
|
||||
|
||||
#define BOARD_HAS_ON_RESET 1
|
||||
@@ -336,15 +326,6 @@
|
||||
GPIO_VDD_3V3_SD_CARD_EN, \
|
||||
GPIO_nARMED_INIT, \
|
||||
SPI6_nRESET_EXTERNAL1, \
|
||||
GPIO_FMU_CH1, \
|
||||
GPIO_FMU_CH2, \
|
||||
GPIO_FMU_CH3, \
|
||||
GPIO_FMU_CH4, \
|
||||
GPIO_FMU_CH5, \
|
||||
GPIO_FMU_CH6, \
|
||||
GPIO_FMU_CH7, \
|
||||
GPIO_FMU_CH8, \
|
||||
GPIO_FMU_CH9, \
|
||||
GPIO_SPIX_SYNC \
|
||||
}
|
||||
|
||||
|
||||
@@ -206,15 +206,6 @@
|
||||
*/
|
||||
#define DIRECT_PWM_OUTPUT_CHANNELS 8
|
||||
|
||||
#define GPIO_FMU_CH1 /* PI0 */ (GPIO_INPUT|GPIO_PULLDOWN|GPIO_PORTI|GPIO_PIN0)
|
||||
#define GPIO_FMU_CH2 /* PH12 */ (GPIO_INPUT|GPIO_PULLDOWN|GPIO_PORTH|GPIO_PIN12)
|
||||
#define GPIO_FMU_CH3 /* PH11 */ (GPIO_INPUT|GPIO_PULLDOWN|GPIO_PORTH|GPIO_PIN11)
|
||||
#define GPIO_FMU_CH4 /* PH10 */ (GPIO_INPUT|GPIO_PULLDOWN|GPIO_PORTH|GPIO_PIN10)
|
||||
#define GPIO_FMU_CH5 /* PD13 */ (GPIO_INPUT|GPIO_PULLDOWN|GPIO_PORTD|GPIO_PIN13)
|
||||
#define GPIO_FMU_CH6 /* PD14 */ (GPIO_INPUT|GPIO_PULLDOWN|GPIO_PORTD|GPIO_PIN14)
|
||||
#define GPIO_FMU_CH7 /* PH6 */ (GPIO_INPUT|GPIO_PULLDOWN|GPIO_PORTH|GPIO_PIN6)
|
||||
#define GPIO_FMU_CH8 /* PH9 */ (GPIO_INPUT|GPIO_PULLDOWN|GPIO_PORTH|GPIO_PIN9)
|
||||
|
||||
#define GPIO_FMU_CAP /* PE11 */ (GPIO_INPUT|GPIO_PULLDOWN|GPIO_PORTE|GPIO_PIN11)
|
||||
#define GPIO_SPIX_SYNC /* PE9 */ (GPIO_INPUT|GPIO_PULLDOWN|GPIO_PORTE|GPIO_PIN9)
|
||||
|
||||
@@ -309,6 +300,9 @@
|
||||
/* This board provides a DMA pool and APIs */
|
||||
#define BOARD_DMA_ALLOC_POOL_SIZE 5120
|
||||
|
||||
/* This board has 4 DMA channels available for bidirectional dshot */
|
||||
#define BOARD_DMA_NUM_DSHOT_CHANNELS 4
|
||||
|
||||
/* This board provides the board_on_reset interface */
|
||||
|
||||
#define BOARD_HAS_ON_RESET 1
|
||||
@@ -338,14 +332,6 @@
|
||||
GPIO_NFC_GPIO, \
|
||||
GPIO_TONE_ALARM_IDLE, \
|
||||
GPIO_nARMED_INIT, \
|
||||
GPIO_FMU_CH1, \
|
||||
GPIO_FMU_CH2, \
|
||||
GPIO_FMU_CH3, \
|
||||
GPIO_FMU_CH4, \
|
||||
GPIO_FMU_CH5, \
|
||||
GPIO_FMU_CH6, \
|
||||
GPIO_FMU_CH7, \
|
||||
GPIO_FMU_CH8, \
|
||||
GPIO_FMU_CAP, \
|
||||
GPIO_SPIX_SYNC \
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -43,6 +43,8 @@
|
||||
#include <drivers/drv_hrt.h>
|
||||
#include <drivers/drv_io_heater.h>
|
||||
|
||||
ModuleBase::Descriptor Core_Heater::desc{task_spawn, custom_command, print_usage};
|
||||
|
||||
# ifndef GPIO_CORE_HEATER_OUTPUT
|
||||
# error "To use the heater driver, the board_config.h must define and initialize GPIO_CORE_HEATER_OUTPUT"
|
||||
# endif
|
||||
@@ -62,7 +64,7 @@ Core_Heater::~Core_Heater()
|
||||
int Core_Heater::custom_command(int argc, char *argv[])
|
||||
{
|
||||
// Check if the driver is running.
|
||||
if (!is_running()) {
|
||||
if (!is_running(desc)) {
|
||||
PX4_INFO("not running");
|
||||
return PX4_ERROR;
|
||||
}
|
||||
@@ -117,7 +119,7 @@ bool Core_Heater::initialize_topics()
|
||||
void Core_Heater::Run()
|
||||
{
|
||||
if (should_exit()) {
|
||||
exit_and_cleanup();
|
||||
exit_and_cleanup(desc);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -216,8 +218,8 @@ int Core_Heater::task_spawn(int argc, char *argv[])
|
||||
return PX4_ERROR;
|
||||
}
|
||||
|
||||
_object.store(core_heater);
|
||||
_task_id = task_id_is_work_queue;
|
||||
desc.object.store(core_heater);
|
||||
desc.task_id = task_id_is_work_queue;
|
||||
|
||||
core_heater->start();
|
||||
return 0;
|
||||
@@ -257,5 +259,5 @@ Background process running periodically on the LP work queue to regulate IMU tem
|
||||
|
||||
extern "C" __EXPORT int core_heater_main(int argc, char *argv[])
|
||||
{
|
||||
return Core_Heater::main(argc, argv);
|
||||
return ModuleBase::main(Core_Heater::desc, argc, argv);
|
||||
}
|
||||
|
||||
@@ -56,9 +56,11 @@ using namespace time_literals;
|
||||
#define CONTROLLER_PERIOD_DEFAULT 10000
|
||||
#define TEMPERATURE_TARGET_THRESHOLD 2.5f
|
||||
|
||||
class Core_Heater : public ModuleBase<Core_Heater>, public ModuleParams, public px4::ScheduledWorkItem
|
||||
class Core_Heater : public ModuleBase, public ModuleParams, public px4::ScheduledWorkItem
|
||||
{
|
||||
public:
|
||||
static Descriptor desc;
|
||||
|
||||
Core_Heater();
|
||||
|
||||
virtual ~Core_Heater();
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
|
||||
#include "NavioRGBLed.hpp"
|
||||
|
||||
ModuleBase::Descriptor NavioRGBLed::desc{task_spawn, custom_command, print_usage};
|
||||
|
||||
NavioRGBLed::NavioRGBLed() :
|
||||
ScheduledWorkItem(MODULE_NAME, px4::wq_configurations::lp_default)
|
||||
{
|
||||
@@ -130,8 +132,8 @@ int NavioRGBLed::task_spawn(int argc, char *argv[])
|
||||
NavioRGBLed *instance = new NavioRGBLed();
|
||||
|
||||
if (instance) {
|
||||
_object.store(instance);
|
||||
_task_id = task_id_is_work_queue;
|
||||
desc.object.store(instance);
|
||||
desc.task_id = task_id_is_work_queue;
|
||||
|
||||
if (instance->init() == PX4_OK) {
|
||||
return PX4_OK;
|
||||
@@ -142,8 +144,8 @@ int NavioRGBLed::task_spawn(int argc, char *argv[])
|
||||
}
|
||||
|
||||
delete instance;
|
||||
_object.store(nullptr);
|
||||
_task_id = -1;
|
||||
desc.object.store(nullptr);
|
||||
desc.task_id = -1;
|
||||
|
||||
return PX4_ERROR;
|
||||
}
|
||||
@@ -170,5 +172,5 @@ Emlid Navio2 RGB LED driver.
|
||||
|
||||
extern "C" __EXPORT int navio_rgbled_main(int argc, char *argv[])
|
||||
{
|
||||
return NavioRGBLed::main(argc, argv);
|
||||
return ModuleBase::main(NavioRGBLed::desc, argc, argv);
|
||||
}
|
||||
|
||||
@@ -40,9 +40,11 @@
|
||||
|
||||
#include <lib/led/led.h>
|
||||
|
||||
class NavioRGBLed : public ModuleBase<NavioRGBLed>, public px4::ScheduledWorkItem
|
||||
class NavioRGBLed : public ModuleBase, public px4::ScheduledWorkItem
|
||||
{
|
||||
public:
|
||||
static Descriptor desc;
|
||||
|
||||
NavioRGBLed();
|
||||
~NavioRGBLed() override;
|
||||
|
||||
|
||||
@@ -58,13 +58,11 @@
|
||||
//#define DMAMAP_USART6_RX DMAMAP_DMA12_USART6RX_0 /* 5 DMA1:71 PX4IO */
|
||||
//#define DMAMAP_USART6_TX DMAMAP_DMA12_USART6TX_0 /* 6 DMA1:72 PX4IO */
|
||||
|
||||
// Dynamically assigned in timer_config.cpp for DShot (allocated/freed per cycle):
|
||||
// Timer 1 TIM1UP (burst) + TIM1CH1-4 (capture)
|
||||
// Timer 2 TIM2UP (burst) + TIM2CH1-4 (capture)
|
||||
// Timer 3 TIM3UP (burst) + TIM3CH1-4 (capture)
|
||||
// Timer 4 TIM4UP (burst) + TIM4CH1-3 (capture, CH4 has no DMA)
|
||||
// Timer 5 TIM5UP (burst) + TIM5CH1-4 (capture)
|
||||
// Timer 15 - no TIM15UP DMA, cannot do DShot
|
||||
// Assigned in timer_config.cpp
|
||||
|
||||
// TODO
|
||||
// Timer 4 /* 7 DMA1:32 TIM4UP */
|
||||
// Timer 5 /* 8 DMA1:50 TIM5UP */
|
||||
|
||||
// DMAMUX2 Using at most 8 Channels on DMA2 -------- Assigned
|
||||
// V
|
||||
|
||||
@@ -38,20 +38,18 @@ constexpr io_timers_t io_timers[MAX_IO_TIMERS] = {
|
||||
initIOTimer(Timer::Timer1, DMA{DMA::Index1}),
|
||||
initIOTimer(Timer::Timer4, DMA{DMA::Index1}),
|
||||
initIOTimer(Timer::Timer5, DMA{DMA::Index1}),
|
||||
initIOTimer(Timer::Timer15), // Note: Timer15 has no TIM_UP DMA on STM32H7, cannot do DShot
|
||||
initIOTimer(Timer::Timer3, DMA{DMA::Index1}),
|
||||
initIOTimer(Timer::Timer2, DMA{DMA::Index1}),
|
||||
initIOTimer(Timer::Timer15),
|
||||
initIOTimer(Timer::Timer3),
|
||||
initIOTimer(Timer::Timer2),
|
||||
};
|
||||
|
||||
// Note: Timer4 Channel4 has no DMAMUX mapping on STM32H7, so BDShot telemetry capture
|
||||
// is not available on that channel. DShot output still works (uses TIM_UP DMA for burst).
|
||||
constexpr timer_io_channels_t timer_io_channels[MAX_TIMER_IO_CHANNELS] = {
|
||||
initIOTimerChannel(io_timers, {Timer::Timer1, Timer::Channel1}, {GPIO::PortA, GPIO::Pin8}),
|
||||
initIOTimerChannel(io_timers, {Timer::Timer1, Timer::Channel2}, {GPIO::PortE, GPIO::Pin11}),
|
||||
initIOTimerChannel(io_timers, {Timer::Timer1, Timer::Channel3}, {GPIO::PortE, GPIO::Pin13}),
|
||||
initIOTimerChannel(io_timers, {Timer::Timer1, Timer::Channel4}, {GPIO::PortE, GPIO::Pin14}),
|
||||
initIOTimerChannel(io_timers, {Timer::Timer4, Timer::Channel3}, {GPIO::PortD, GPIO::Pin14}),
|
||||
initIOTimerChannel(io_timers, {Timer::Timer4, Timer::Channel4}, {GPIO::PortD, GPIO::Pin15}), // no BDShot telemetry readback
|
||||
initIOTimerChannel(io_timers, {Timer::Timer4, Timer::Channel4}, {GPIO::PortD, GPIO::Pin15}),
|
||||
initIOTimerChannel(io_timers, {Timer::Timer5, Timer::Channel1}, {GPIO::PortA, GPIO::Pin0}),
|
||||
initIOTimerChannel(io_timers, {Timer::Timer5, Timer::Channel2}, {GPIO::PortA, GPIO::Pin1}),
|
||||
initIOTimerChannel(io_timers, {Timer::Timer15, Timer::Channel1}, {GPIO::PortE, GPIO::Pin5}),
|
||||
|
||||
@@ -49,6 +49,8 @@
|
||||
|
||||
using namespace time_literals;
|
||||
|
||||
ModuleBase::Descriptor GhstRc::desc{task_spawn, custom_command, print_usage};
|
||||
|
||||
uint32_t GhstRc::baudrate = GHST_BAUDRATE;
|
||||
|
||||
GhstRc::GhstRc(const char *device) :
|
||||
@@ -114,8 +116,8 @@ int GhstRc::task_spawn(int argc, char *argv[])
|
||||
return PX4_ERROR;
|
||||
}
|
||||
|
||||
_object.store(instance);
|
||||
_task_id = task_id_is_work_queue;
|
||||
desc.object.store(instance);
|
||||
desc.task_id = task_id_is_work_queue;
|
||||
|
||||
instance->ScheduleNow();
|
||||
|
||||
@@ -174,7 +176,7 @@ void GhstRc::Run()
|
||||
if (should_exit()) {
|
||||
ScheduleClear();
|
||||
_rc_fd = -1;
|
||||
exit_and_cleanup();
|
||||
exit_and_cleanup(desc);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -308,5 +310,5 @@ This module parses the GHST RC uplink protocol and can generate GHST downlink te
|
||||
|
||||
extern "C" __EXPORT int ghst_rc_main(int argc, char *argv[])
|
||||
{
|
||||
return GhstRc::main(argc, argv);
|
||||
return ModuleBase::main(GhstRc::desc, argc, argv);
|
||||
}
|
||||
|
||||
@@ -54,9 +54,11 @@
|
||||
|
||||
#define GHST_MAX_NUM_CHANNELS (16)
|
||||
|
||||
class GhstRc : public ModuleBase<GhstRc>, public ModuleParams, public px4::ScheduledWorkItem
|
||||
class GhstRc : public ModuleBase, public ModuleParams, public px4::ScheduledWorkItem
|
||||
{
|
||||
public:
|
||||
static Descriptor desc;
|
||||
|
||||
GhstRc(const char *device);
|
||||
~GhstRc() override;
|
||||
|
||||
|
||||
@@ -59,6 +59,8 @@
|
||||
|
||||
#include "rc_controller.hpp"
|
||||
|
||||
ModuleBase::Descriptor RC_ControllerModule::desc{task_spawn, custom_command, print_usage};
|
||||
|
||||
int RC_ControllerModule::print_status()
|
||||
{
|
||||
PX4_INFO("Running");
|
||||
@@ -69,35 +71,35 @@ int RC_ControllerModule::print_status()
|
||||
|
||||
int RC_ControllerModule::custom_command(int argc, char *argv[])
|
||||
{
|
||||
if (!is_running()) {
|
||||
if (!is_running(desc)) {
|
||||
print_usage("not running");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!strcmp(argv[0], "throttle")) {
|
||||
uint16_t val = atoi(argv[1]);
|
||||
get_instance()->set_throttle(val);
|
||||
get_instance<RC_ControllerModule>(desc)->set_throttle(val);
|
||||
PX4_INFO("Setting throttle to %u", val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!strcmp(argv[0], "yaw")) {
|
||||
uint16_t val = atoi(argv[1]);
|
||||
get_instance()->set_yaw(val);
|
||||
get_instance<RC_ControllerModule>(desc)->set_yaw(val);
|
||||
PX4_INFO("Setting yaw to %u", val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!strcmp(argv[0], "pitch")) {
|
||||
uint16_t val = atoi(argv[1]);
|
||||
get_instance()->set_pitch(val);
|
||||
get_instance<RC_ControllerModule>(desc)->set_pitch(val);
|
||||
PX4_INFO("Setting pitch to %u", val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!strcmp(argv[0], "roll")) {
|
||||
uint16_t val = atoi(argv[1]);
|
||||
get_instance()->set_roll(val);
|
||||
get_instance<RC_ControllerModule>(desc)->set_roll(val);
|
||||
PX4_INFO("Setting roll to %u", val);
|
||||
return 0;
|
||||
}
|
||||
@@ -106,17 +108,24 @@ int RC_ControllerModule::custom_command(int argc, char *argv[])
|
||||
}
|
||||
|
||||
|
||||
int RC_ControllerModule::run_trampoline(int argc, char *argv[])
|
||||
{
|
||||
return ModuleBase::run_trampoline_impl(desc, [](int ac, char *av[]) -> ModuleBase * {
|
||||
return RC_ControllerModule::instantiate(ac, av);
|
||||
}, argc, argv);
|
||||
}
|
||||
|
||||
int RC_ControllerModule::task_spawn(int argc, char *argv[])
|
||||
{
|
||||
_task_id = px4_task_spawn_cmd("RC_ControllerModule",
|
||||
SCHED_DEFAULT,
|
||||
SCHED_PRIORITY_MAX,
|
||||
1024,
|
||||
(px4_main_t)&run_trampoline,
|
||||
(char *const *)argv);
|
||||
desc.task_id = px4_task_spawn_cmd("RC_ControllerModule",
|
||||
SCHED_DEFAULT,
|
||||
SCHED_PRIORITY_MAX,
|
||||
1024,
|
||||
(px4_main_t)&run_trampoline,
|
||||
(char *const *)argv);
|
||||
|
||||
if (_task_id < 0) {
|
||||
_task_id = -1;
|
||||
if (desc.task_id < 0) {
|
||||
desc.task_id = -1;
|
||||
return -errno;
|
||||
}
|
||||
|
||||
@@ -252,5 +261,5 @@ int RC_ControllerModule::print_usage(const char *reason)
|
||||
|
||||
int rc_controller_main(int argc, char *argv[])
|
||||
{
|
||||
return RC_ControllerModule::main(argc, argv);
|
||||
return ModuleBase::main(RC_ControllerModule::desc, argc, argv);
|
||||
}
|
||||
|
||||
@@ -41,9 +41,11 @@
|
||||
|
||||
extern "C" __EXPORT int rc_controller_main(int argc, char *argv[]);
|
||||
|
||||
class RC_ControllerModule : public ModuleBase<RC_ControllerModule>, public ModuleParams
|
||||
class RC_ControllerModule : public ModuleBase, public ModuleParams
|
||||
{
|
||||
public:
|
||||
static Descriptor desc;
|
||||
|
||||
RC_ControllerModule();
|
||||
|
||||
virtual ~RC_ControllerModule() = default;
|
||||
@@ -51,6 +53,9 @@ public:
|
||||
/** @see ModuleBase */
|
||||
static int task_spawn(int argc, char *argv[]);
|
||||
|
||||
/** @see ModuleBase */
|
||||
static int run_trampoline(int argc, char *argv[]);
|
||||
|
||||
/** @see ModuleBase */
|
||||
static RC_ControllerModule *instantiate(int argc, char *argv[]);
|
||||
|
||||
|
||||
@@ -31,4 +31,34 @@
|
||||
#
|
||||
############################################################################
|
||||
|
||||
# Initialize libfc-sensor-api submodule (fetches from GitLab if not present)
|
||||
execute_process(
|
||||
COMMAND Tools/check_submodules.sh boards/modalai/voxl2/libfc-sensor-api
|
||||
WORKING_DIRECTORY ${PX4_SOURCE_DIR}
|
||||
)
|
||||
|
||||
include_directories(${PX4_BOARD_DIR}/libfc-sensor-api/inc)
|
||||
|
||||
# Build libfc_sensor.so stub library automatically if not already built
|
||||
set(FC_SENSOR_LIB ${PX4_BOARD_DIR}/libfc-sensor-api/build/libfc_sensor.so)
|
||||
if(NOT EXISTS ${FC_SENSOR_LIB})
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${PX4_BOARD_DIR}/libfc-sensor-api/build
|
||||
)
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} ..
|
||||
WORKING_DIRECTORY ${PX4_BOARD_DIR}/libfc-sensor-api/build
|
||||
RESULT_VARIABLE FC_SENSOR_CMAKE_RESULT
|
||||
)
|
||||
if(NOT FC_SENSOR_CMAKE_RESULT EQUAL 0)
|
||||
message(FATAL_ERROR "Failed to configure libfc_sensor stub library")
|
||||
endif()
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} --build .
|
||||
WORKING_DIRECTORY ${PX4_BOARD_DIR}/libfc-sensor-api/build
|
||||
RESULT_VARIABLE FC_SENSOR_BUILD_RESULT
|
||||
)
|
||||
if(NOT FC_SENSOR_BUILD_RESULT EQUAL 0)
|
||||
message(FATAL_ERROR "Failed to build libfc_sensor stub library")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -41,6 +41,8 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
ModuleBase::Descriptor VoxlSaveCalParams::desc{task_spawn, custom_command, print_usage};
|
||||
|
||||
static bool debug = false;
|
||||
|
||||
VoxlSaveCalParams::VoxlSaveCalParams() :
|
||||
@@ -145,7 +147,7 @@ VoxlSaveCalParams::Run()
|
||||
{
|
||||
if (should_exit()) {
|
||||
_parameter_primary_set_value_request_sub.unregisterCallback();
|
||||
exit_and_cleanup();
|
||||
exit_and_cleanup(desc);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -186,8 +188,8 @@ int VoxlSaveCalParams::task_spawn(int argc, char *argv[])
|
||||
VoxlSaveCalParams *instance = new VoxlSaveCalParams();
|
||||
|
||||
if (instance) {
|
||||
_object.store(instance);
|
||||
_task_id = task_id_is_work_queue;
|
||||
desc.object.store(instance);
|
||||
desc.task_id = task_id_is_work_queue;
|
||||
|
||||
if (instance->init()) {
|
||||
return PX4_OK;
|
||||
@@ -198,8 +200,8 @@ int VoxlSaveCalParams::task_spawn(int argc, char *argv[])
|
||||
}
|
||||
|
||||
delete instance;
|
||||
_object.store(nullptr);
|
||||
_task_id = -1;
|
||||
desc.object.store(nullptr);
|
||||
desc.task_id = -1;
|
||||
|
||||
return PX4_ERROR;
|
||||
}
|
||||
@@ -230,5 +232,5 @@ This implements autosaving of calibration parameters on VOXL2 platform.
|
||||
|
||||
extern "C" __EXPORT int voxl_save_cal_params_main(int argc, char *argv[])
|
||||
{
|
||||
return VoxlSaveCalParams::main(argc, argv);
|
||||
return ModuleBase::main(VoxlSaveCalParams::desc, argc, argv);
|
||||
}
|
||||
|
||||
@@ -46,10 +46,12 @@
|
||||
|
||||
using namespace time_literals;
|
||||
|
||||
class VoxlSaveCalParams : public ModuleBase<VoxlSaveCalParams>, public ModuleParams,
|
||||
class VoxlSaveCalParams : public ModuleBase, public ModuleParams,
|
||||
public px4::WorkItem
|
||||
{
|
||||
public:
|
||||
static Descriptor desc;
|
||||
|
||||
VoxlSaveCalParams();
|
||||
~VoxlSaveCalParams() = default;
|
||||
|
||||
|
||||
@@ -76,10 +76,10 @@ param load
|
||||
# IMU (accelerometer / gyroscope)
|
||||
if [ "$PLATFORM" == "M0104" ]; then
|
||||
/bin/echo "Starting IMU driver with rotation 12"
|
||||
qshell icm42688p start -s -R 12
|
||||
qshell icm42688p start -s -R 12 -C 32768
|
||||
else
|
||||
/bin/echo "Starting IMU driver with no rotation"
|
||||
qshell icm42688p start -s
|
||||
qshell icm42688p start -s -C 32768
|
||||
fi
|
||||
|
||||
# Start Invensense ICP 101xx barometer built on to VOXL 2
|
||||
|
||||
@@ -269,7 +269,6 @@
|
||||
*(.text.udp_pollsetup)
|
||||
*(.text._ZL14timer_callbackPv)
|
||||
*(.text._ZN3Ekf4fuseERKN6matrix6VectorIfLj24EEEf)
|
||||
*(.text._ZN13land_detector23MulticopterLandDetector22_set_hysteresis_factorEi)
|
||||
*(.text.nxsem_wait_irq)
|
||||
*(.text._ZN20MavlinkCommandSender4lockEv)
|
||||
*(.text.MEM_LongCopyEnd)
|
||||
@@ -432,7 +431,7 @@
|
||||
*(.text._ZN23MavlinkStreamStatustext8get_sizeEv)
|
||||
*(.text._ZN11calibration13Accelerometer13set_device_idEm)
|
||||
*(.text._ZN3px46logger6Logger18start_stop_loggingEv)
|
||||
*(.text._ZN14FlightTaskAuto17_evaluateTripletsEv)
|
||||
*(.text._ZN14FlightTaskAuto32_evaluatePositionSetpointTripletEv)
|
||||
*(.text._ZN11calibration9Gyroscope23SensorCorrectionsUpdateEb)
|
||||
*(.text._ZN25MavlinkStreamMagCalReport4sendEv)
|
||||
*(.text.imxrt_config_gpio)
|
||||
@@ -573,7 +572,6 @@
|
||||
*(.text._ZN4uORB12SubscriptionaSEOS0_)
|
||||
*(.text._ZN15TakeoffHandling18updateTakeoffStateEbbbfbRKy)
|
||||
*(.text._ZN10ModeChecks14checkAndReportERK7ContextR6Report)
|
||||
*(.text._ZN14FlightTaskAuto24_updateInternalWaypointsEv)
|
||||
*(.text._ZN8Failsafe17updateArmingStateERKybRK16failsafe_flags_s)
|
||||
*(.text.imxrt_lpi2c_modifyreg)
|
||||
*(.text.up_flush_dcache)
|
||||
|
||||
@@ -269,7 +269,6 @@
|
||||
*(.text.udp_pollsetup)
|
||||
*(.text._ZL14timer_callbackPv)
|
||||
*(.text._ZN3Ekf4fuseERKN6matrix6VectorIfLj24EEEf)
|
||||
*(.text._ZN13land_detector23MulticopterLandDetector22_set_hysteresis_factorEi)
|
||||
*(.text.nxsem_wait_irq)
|
||||
*(.text._ZN20MavlinkCommandSender4lockEv)
|
||||
*(.text.MEM_LongCopyEnd)
|
||||
@@ -432,7 +431,7 @@
|
||||
*(.text._ZN23MavlinkStreamStatustext8get_sizeEv)
|
||||
*(.text._ZN11calibration13Accelerometer13set_device_idEm)
|
||||
*(.text._ZN3px46logger6Logger18start_stop_loggingEv)
|
||||
*(.text._ZN14FlightTaskAuto17_evaluateTripletsEv)
|
||||
*(.text._ZN14FlightTaskAuto32_evaluatePositionSetpointTripletEv)
|
||||
*(.text._ZN11calibration9Gyroscope23SensorCorrectionsUpdateEb)
|
||||
*(.text._ZN25MavlinkStreamMagCalReport4sendEv)
|
||||
*(.text.imxrt_config_gpio)
|
||||
@@ -573,7 +572,6 @@
|
||||
*(.text._ZN4uORB12SubscriptionaSEOS0_)
|
||||
*(.text._ZN15TakeoffHandling18updateTakeoffStateEbbbfbRKy)
|
||||
*(.text._ZN10ModeChecks14checkAndReportERK7ContextR6Report)
|
||||
*(.text._ZN14FlightTaskAuto24_updateInternalWaypointsEv)
|
||||
*(.text._ZN8Failsafe17updateArmingStateERKybRK16failsafe_flags_s)
|
||||
*(.text.imxrt_lpi2c_modifyreg)
|
||||
*(.text.up_flush_dcache)
|
||||
|
||||
@@ -23,9 +23,7 @@ CONFIG_DRIVERS_GPS=y
|
||||
CONFIG_DRIVERS_HEATER=y
|
||||
CONFIG_DRIVERS_IMU_ANALOG_DEVICES_ADIS16470=y
|
||||
CONFIG_DRIVERS_IMU_BOSCH_BMI088=y
|
||||
CONFIG_DRIVERS_IMU_INVENSENSE_ICM20602=y
|
||||
CONFIG_DRIVERS_IMU_INVENSENSE_ICM20649=y
|
||||
CONFIG_DRIVERS_IMU_INVENSENSE_ICM20948=y
|
||||
CONFIG_DRIVERS_IMU_INVENSENSE_ICM42670P=y
|
||||
CONFIG_DRIVERS_IMU_INVENSENSE_ICM42688P=y
|
||||
CONFIG_DRIVERS_IMU_INVENSENSE_ICM45686=y
|
||||
|
||||
@@ -180,7 +180,6 @@ constexpr px4_spi_bus_all_hw_t px4_spi_buses_all_hw[BOARD_NUM_SPI_CFG_HW_VERSION
|
||||
|
||||
initSPIFmumID(V6X_16, {
|
||||
initSPIBus(SPI::Bus::SPI1, {
|
||||
initSPIDevice(DRV_IMU_DEVTYPE_ICM20602, SPI::CS{GPIO::PortI, GPIO::Pin9}, SPI::DRDY{GPIO::PortF, GPIO::Pin2}),
|
||||
}, {GPIO::PortI, GPIO::Pin11}),
|
||||
initSPIBus(SPI::Bus::SPI2, {
|
||||
initSPIDevice(DRV_IMU_DEVTYPE_ICM42688P, SPI::CS{GPIO::PortH, GPIO::Pin5}, SPI::DRDY{GPIO::PortA, GPIO::Pin10}),
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -273,7 +273,6 @@
|
||||
*(.text.udp_pollsetup)
|
||||
*(.text._ZL14timer_callbackPv)
|
||||
*(.text._ZN3Ekf4fuseERKN6matrix6VectorIfLj24EEEf)
|
||||
*(.text._ZN13land_detector23MulticopterLandDetector22_set_hysteresis_factorEi)
|
||||
*(.text.nxsem_wait_irq)
|
||||
*(.text._ZN20MavlinkCommandSender4lockEv)
|
||||
*(.text.MEM_LongCopyEnd)
|
||||
@@ -440,7 +439,7 @@
|
||||
*(.text._ZN23MavlinkStreamStatustext8get_sizeEv)
|
||||
*(.text._ZN11calibration13Accelerometer13set_device_idEm)
|
||||
*(.text._ZN3px46logger6Logger18start_stop_loggingEv)
|
||||
*(.text._ZN14FlightTaskAuto17_evaluateTripletsEv)
|
||||
*(.text._ZN14FlightTaskAuto32_evaluatePositionSetpointTripletEv)
|
||||
*(.text._ZN11calibration9Gyroscope23SensorCorrectionsUpdateEb)
|
||||
*(.text._ZN25MavlinkStreamMagCalReport4sendEv)
|
||||
*(.text.imxrt_config_gpio)
|
||||
@@ -586,7 +585,6 @@
|
||||
*(.text._ZN4uORB12SubscriptionaSEOS0_)
|
||||
*(.text._ZN15TakeoffHandling18updateTakeoffStateEbbbfbRKy)
|
||||
*(.text._ZN10ModeChecks14checkAndReportERK7ContextR6Report)
|
||||
*(.text._ZN14FlightTaskAuto24_updateInternalWaypointsEv)
|
||||
*(.text._ZN8Failsafe17updateArmingStateERKybRK16failsafe_flags_s)
|
||||
*(.text.imxrt_lpi2c_modifyreg)
|
||||
*(.text.up_flush_dcache)
|
||||
|
||||
@@ -16,6 +16,9 @@ logs
|
||||
#Yarn log
|
||||
yarn-error.log
|
||||
|
||||
# npm lockfile (project uses yarn)
|
||||
package-lock.json
|
||||
|
||||
|
||||
# Generated alternative _summary.md
|
||||
# **/*/_summary.md
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"proseWrap": "preserve",
|
||||
"tabWidth": 2,
|
||||
"useTabs": false,
|
||||
"printWidth": 9999,
|
||||
"endOfLine": "lf",
|
||||
"embeddedLanguageFormatting": "off"
|
||||
}
|
||||
@@ -254,7 +254,63 @@ export default defineConfig({
|
||||
head.push(["link", { rel: "canonical", href: canonicalUrlToAdd }]);
|
||||
}
|
||||
|
||||
// Add any other custom head tags you might want later
|
||||
// Build version-aware site URL for OG tags
|
||||
const branch = process.env.BRANCH_NAME || "main";
|
||||
const siteUrl = `https://docs.px4.io/${branch}`;
|
||||
|
||||
// OG image — same image for all pages, but URL includes version base
|
||||
const ogImage =
|
||||
pageData.frontmatter.ogImage || `${siteUrl}/og-image.png`;
|
||||
|
||||
// Build the actual page URL (version-aware, includes locale prefix)
|
||||
let ogPath = pageData.relativePath.replace(/\.md$/, "");
|
||||
if (ogPath === "index") ogPath = "";
|
||||
else if (ogPath.endsWith("/index"))
|
||||
ogPath = ogPath.slice(0, -"/index".length);
|
||||
const ogUrl = `${siteUrl}/${ogPath}`;
|
||||
|
||||
// Open Graph
|
||||
head.push(
|
||||
[
|
||||
"meta",
|
||||
{
|
||||
property: "og:title",
|
||||
content: pageData.title || "PX4 Autopilot",
|
||||
},
|
||||
],
|
||||
[
|
||||
"meta",
|
||||
{
|
||||
property: "og:description",
|
||||
content:
|
||||
pageData.description ||
|
||||
"Open-source flight stack for drones and autonomous vehicles.",
|
||||
},
|
||||
],
|
||||
["meta", { property: "og:url", content: ogUrl }],
|
||||
["meta", { property: "og:image", content: ogImage }],
|
||||
);
|
||||
|
||||
// Twitter Card
|
||||
head.push(
|
||||
[
|
||||
"meta",
|
||||
{
|
||||
name: "twitter:title",
|
||||
content: pageData.title || "PX4 Autopilot",
|
||||
},
|
||||
],
|
||||
[
|
||||
"meta",
|
||||
{
|
||||
name: "twitter:description",
|
||||
content:
|
||||
pageData.description ||
|
||||
"Open-source flight stack for drones and autonomous vehicles.",
|
||||
},
|
||||
],
|
||||
["meta", { name: "twitter:image", content: ogImage }],
|
||||
);
|
||||
|
||||
// Return head that will be merged.
|
||||
return head;
|
||||
@@ -276,6 +332,14 @@ export default defineConfig({
|
||||
gtag('js', new Date());
|
||||
gtag('config', 'G-91EWVWRQ93');`,
|
||||
],
|
||||
// Open Graph
|
||||
["meta", { property: "og:site_name", content: "PX4 Autopilot" }],
|
||||
["meta", { property: "og:type", content: "website" }],
|
||||
["meta", { property: "og:image:width", content: "1200" }],
|
||||
["meta", { property: "og:image:height", content: "630" }],
|
||||
["meta", { property: "og:image:type", content: "image/png" }],
|
||||
// Twitter Card
|
||||
["meta", { name: "twitter:card", content: "summary_large_image" }],
|
||||
],
|
||||
|
||||
vue: {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# Onboard parameters for Vehicle 1
|
||||
#
|
||||
# Stack: PX4 Pro
|
||||
# Vehicle: Multi-Rotor
|
||||
# Version: 1.15.4
|
||||
# Vehicle: Amovlab F410
|
||||
# Version: 1.15.4
|
||||
# Git Revision: 99c40407ff000000
|
||||
#
|
||||
# Vehicle-Id Component-Id Name Value Type
|
||||
@@ -546,7 +546,6 @@
|
||||
1 1 IMU_INTEG_RATE 200 6
|
||||
1 1 LNDMC_ALT_GND 2.000000000000000000 9
|
||||
1 1 LNDMC_ROT_MAX 20.000000000000000000 9
|
||||
1 1 LNDMC_TRIG_TIME 1.000000000000000000 9
|
||||
1 1 LNDMC_XY_VEL_MAX 1.500000000000000000 9
|
||||
1 1 LNDMC_Z_VEL_MAX 0.250000000000000000 9
|
||||
1 1 LND_FLIGHT_T_HI 5 6
|
||||
@@ -1056,9 +1055,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 |
@@ -653,7 +653,7 @@
|
||||
id="tspan2761"
|
||||
x="-83.335098"
|
||||
y="147.11555"
|
||||
style="font-size:3.88056px;writing-mode:lr-tb;stroke-width:0.264583px">simulator_mavlink.cpp</tspan></text>
|
||||
style="font-size:3.88056px;writing-mode:lr-tb;stroke-width:0.264583px">SimulatorMavlink.cpp</tspan></text>
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.79375;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1.5875, 0.79375;stroke-dashoffset:2.46063;stroke-opacity:1;marker-start:url(#marker3113)"
|
||||
d="m -42.713286,146.11223 h 8.466662"
|
||||
|
||||
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
@@ -0,0 +1,86 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.2.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 612 335.8" style="enable-background:new 0 0 612 335.8;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#4D4E4E;}
|
||||
.st1{fill:#27B373;}
|
||||
.st2{fill:#5DC4CD;}
|
||||
.st3{fill:#1E8756;}
|
||||
</style>
|
||||
<g>
|
||||
<g>
|
||||
<path class="st0" d="M66.1,232.6l-0.4-95.9h24c16.3,0,25.6,6.5,28,19.4c0.6,3,0.9,12.3,1,27.9c0.1,16.7-0.3,27-1.4,30.7
|
||||
c-1.8,6.3-4.8,10.8-9.1,13.6c-4.2,2.8-10.2,4.2-18.1,4.2H66.1z M72.5,226h17.7c6.8,0,11.8-1.1,15-3.3c2.7-1.9,4.6-5.1,5.9-9.8
|
||||
c0.9-2.9,1.3-12.2,1.3-27.9c0-15.1-0.3-24.4-1-27.7c-0.9-5-3.1-8.6-6.5-10.8c-3.4-2.2-8.5-3.3-15.2-3.3H72.2L72.5,226z"/>
|
||||
<path class="st0" d="M129.1,232.6v-63.2h6.5v1c0,0.7,0.2,1.3,0.7,1.8c0.4,0.4,0.9,0.7,1.5,0.7c0.5,0,1-0.1,1.5-0.4
|
||||
c3.9-1.9,7.2-3.1,9.9-3.7c1.4-0.3,2.7-0.4,4.1-0.4c4.9,0,9.3,2.2,13.4,6.6l-4.9,4.2c-2.7-2.9-5.5-4.3-8.5-4.3
|
||||
c-0.8,0-1.6,0.1-2.6,0.3c-4,0.9-8.8,3.1-14.5,6.5l-0.7,0.4v50.6H129.1z"/>
|
||||
<path class="st0" d="M176.4,229.2c-4.2-3.2-7.1-7.5-8.6-13c-2.3-8.2-2.4-17.9-0.4-29c1.2-6.3,3.7-11.1,7.7-14.4
|
||||
c3.9-3.3,9-5,15.3-5c6,0,11.2,1.8,15.6,5.4c4.4,3.6,7.1,8.3,8.2,14.1c2.1,11.1,2,20.7-0.4,29c-1.6,5.6-4.4,9.9-8.5,13.1
|
||||
c-4,3.1-8.8,4.7-14.4,4.7C185.4,234.1,180.5,232.5,176.4,229.2z M173.7,188.5c-1.9,10.1-1.8,18.7,0.3,25.9
|
||||
c1.1,4.1,3.2,7.3,6.2,9.6c3,2.3,6.6,3.5,10.6,3.5c8.6,0,14.1-4.4,16.6-13.1c2.1-7.2,2.2-15.8,0.3-25.9c-0.8-4.3-2.8-7.7-5.9-10.3
|
||||
c-3.1-2.5-7-3.8-11.5-3.8C181,174.5,175.5,179.1,173.7,188.5z"/>
|
||||
<path class="st0" d="M262.2,232.6V189c0-5.9-1.2-9.9-3.5-12.1c-1.7-1.6-4.3-2.5-7.7-2.5c-0.4,0-0.9,0-1.4,0.1
|
||||
c-6.1,0.3-12,2.3-17.8,6l-0.7,0.4v51.7h-6.5v-63.2h6.7c0.1,0.5,0.4,0.9,0.7,1.3c0.5,0.6,1.2,0.9,2.1,0.9c0.4,0,0.9-0.1,1.5-0.3
|
||||
c5.6-1.9,10.2-3,13.6-3.2c0.6,0,1.2-0.1,1.8-0.1c5.2,0,9.2,1.4,12.2,4.2c3.6,3.5,5.5,9.1,5.5,16.8v43.5H262.2z"/>
|
||||
<path class="st0" d="M289.4,229.2c-4.1-3.2-6.9-7.6-8.2-13c-2.6-10.4-2.7-19.8-0.3-28.1c1.8-6.5,4.9-11.5,9.1-15
|
||||
c4.3-3.6,9.4-5.4,15.3-5.4c5.5,0,10,1.7,13.6,5c3.6,3.3,5.9,7.9,6.9,13.8c0.6,3.5,0.7,6.4,0.4,8.7l-0.3,2.3l-40,7.5l0.1,1.3
|
||||
c0.2,2.8,0.7,5.6,1.4,8.3c1,4,2.9,7.2,5.9,9.5c2.9,2.3,6.5,3.5,10.6,3.5c5.9,0,10.7-1.9,14.5-5.6l4.9,4.2
|
||||
c-5,5.3-11.5,7.9-19.4,7.9C298.4,234.1,293.5,232.4,289.4,229.2z M287.1,189.8c-0.5,2-0.9,4.2-1.1,6.7l-0.1,1.9l34.1-6.4l-0.1-1.3
|
||||
c-0.1-1-0.2-2.1-0.4-3.2c-1.5-8.9-6.2-13.4-14.2-13.4C296.2,174.1,290.1,179.3,287.1,189.8z"/>
|
||||
<path class="st0" d="M345.2,229.2c-4.2-3.2-7.1-7.5-8.6-13c-2.3-8.2-2.4-17.9-0.4-29c1.2-6.3,3.7-11.1,7.7-14.4
|
||||
c3.9-3.3,9-5,15.3-5c8.4,0,14.9,3.2,19.5,9.5l-5.5,3.6c-3.3-4.3-8-6.5-14.1-6.5c-9.3,0-14.8,4.7-16.6,14.1
|
||||
c-1.9,10.1-1.8,18.7,0.3,25.9c1.1,4.1,3.2,7.3,6.2,9.6c3,2.3,6.6,3.5,10.6,3.5c5.7,0,10.1-2.1,13.3-6.3l5.5,3.6
|
||||
c-4.5,6.2-10.7,9.2-18.7,9.2C354.1,234.1,349.3,232.5,345.2,229.2z"/>
|
||||
<path class="st0" d="M394.9,229.2c-4.2-3.2-7.1-7.5-8.6-13c-2.3-8.2-2.4-17.9-0.4-29c1.2-6.3,3.7-11.1,7.7-14.4
|
||||
c3.9-3.3,9-5,15.3-5c6,0,11.2,1.8,15.6,5.4c4.4,3.6,7.1,8.3,8.2,14.1c2.1,11.1,2,20.7-0.4,29c-1.6,5.6-4.4,9.9-8.5,13.1
|
||||
c-4,3.1-8.8,4.7-14.4,4.7C403.9,234.1,399.1,232.5,394.9,229.2z M392.3,188.5c-1.9,10.1-1.8,18.7,0.3,25.9
|
||||
c1.1,4.1,3.2,7.3,6.2,9.6c3,2.3,6.6,3.5,10.6,3.5c8.6,0,14.1-4.4,16.6-13.1c2.1-7.2,2.2-15.8,0.3-25.9c-0.8-4.3-2.8-7.7-5.9-10.3
|
||||
c-3.1-2.5-7-3.8-11.5-3.8C399.6,174.5,394,179.1,392.3,188.5z"/>
|
||||
<path class="st0" d="M452.2,228.6c-3.9-3.7-6.5-8.6-7.6-14.6c-2.1-10.9-1.8-20.7,0.7-29.5c2.9-10.1,10.1-15.6,21.5-16.5
|
||||
c0.8,0,1.7-0.1,2.6-0.1c4.3,0,8.3,0.8,12.1,2.4l1.9,0.8v-39h6.5v100.4h-6.7c-0.4-0.9-1.2-1.4-2.3-1.4c-0.4,0-0.9,0.1-1.3,0.2
|
||||
c-4.6,1.9-9.1,2.8-13.5,2.8C460.7,234.1,456.1,232.2,452.2,228.6z M467.3,174.5c-8.5,0.6-13.7,4.6-15.8,11.8
|
||||
c-2.3,7.8-2.5,16.7-0.6,26.6c0.8,4.5,2.6,8,5.4,10.7c2.8,2.7,6,4,9.7,4c5.9,0,11.5-1.8,16.7-5.4l0.6-0.4v-42.9l-0.6-0.4
|
||||
c-3.9-2.6-8.4-3.9-13.4-3.9C468.6,174.4,468,174.4,467.3,174.5z"/>
|
||||
<path class="st0" d="M508.6,229.2c-4.1-3.2-6.9-7.6-8.2-13c-2.6-10.4-2.7-19.8-0.3-28.1c1.8-6.5,4.9-11.5,9.1-15
|
||||
c4.3-3.6,9.4-5.4,15.3-5.4c5.5,0,10,1.7,13.6,5c3.6,3.3,5.9,7.9,6.9,13.8c0.6,3.5,0.7,6.4,0.4,8.7l-0.3,2.3l-40,7.5l0.1,1.3
|
||||
c0.2,2.8,0.7,5.6,1.4,8.3c1,4,2.9,7.2,5.9,9.5c2.9,2.3,6.5,3.5,10.6,3.5c5.9,0,10.7-1.9,14.5-5.6l4.9,4.2
|
||||
c-5,5.3-11.5,7.9-19.4,7.9C517.6,234.1,512.7,232.4,508.6,229.2z M506.3,189.8c-0.5,2-0.9,4.2-1.1,6.7l-0.1,1.9l34.1-6.4l-0.1-1.3
|
||||
c-0.1-1-0.2-2.1-0.4-3.2c-1.5-8.9-6.2-13.4-14.2-13.4C515.3,174.1,509.2,179.3,506.3,189.8z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st1" d="M387.5,38.8c-1.5-2.3-6.1-3.2-10.6-1.4c0,0-58.1,21.9-58.3,22c-1.2,0.3-1.6,1.4-1.6,1.4l-13.8,28.2
|
||||
c0,0-0.1,0.3-0.3,0.3c-0.2,0-0.3-0.3-0.3-0.3l-14-28.5c0,0-0.3-0.9-1.5-1.2c-0.3-0.1-58.3-22-58.3-22c-4.5-1.8-9.1-0.9-10.6,1.4
|
||||
c-2.8,4.4,1.9,9,2.4,9.6l70.7,77.2c0,0,0,0.1,0.1,0.1l0,0c0,0,4.5,6.3,11.5,6.2c7,0.1,11.5-6.2,11.5-6.2l70.7-77.2
|
||||
C385.5,47.7,390.3,43.2,387.5,38.8z"/>
|
||||
<path class="st2" d="M287.5,121.3c0,0,1.6,2,3.8,4.2c1.8,2.6,5.9,6.2,11.5,6.3c7,0.1,11.5-6.2,11.5-6.2L385,48.4
|
||||
c0.5-0.7,5.2-5.3,2.4-9.6c-1.5-2.3-6.1-3.2-10.6-1.4c0,0-58.1,21.9-58.3,22c-1.2,0.3-1.6,1.4-1.6,1.4L303.2,89
|
||||
c0,0-0.1,0.3-0.4,0.3"/>
|
||||
<path class="st3" d="M302.6,88.9c0,0,0.1,0.3,0.2,0.3s-15.3,32.1-15.3,32.1l-19.8-21.6l20.7-39.6L302.6,88.9z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st3" d="M75.5,299h-6.8v-42.1h23.8v5.8H75.5v13.2h15.9v5.8H75.5V299z"/>
|
||||
<path class="st3" d="M148,277.8c0,6.9-1.7,12.2-5.1,16c-3.4,3.8-8.3,5.7-14.6,5.7c-6.4,0-11.2-1.9-14.6-5.7
|
||||
c-3.4-3.8-5.1-9.1-5.1-16.1s1.7-12.3,5.1-16c3.4-3.7,8.3-5.6,14.7-5.6c6.3,0,11.1,1.9,14.5,5.7C146.3,265.6,148,271,148,277.8z
|
||||
M115.8,277.8c0,5.2,1,9.1,3.1,11.8c2.1,2.7,5.2,4,9.3,4c4.1,0,7.2-1.3,9.3-4s3.1-6.6,3.1-11.8c0-5.2-1-9.1-3.1-11.8s-5.1-4-9.2-4
|
||||
c-4.1,0-7.2,1.3-9.3,4C116.9,268.8,115.8,272.7,115.8,277.8z"/>
|
||||
<path class="st3" d="M200.5,256.8v27.3c0,3.1-0.7,5.8-2,8.2c-1.3,2.3-3.3,4.1-5.8,5.4s-5.5,1.9-9.1,1.9c-5.2,0-9.3-1.4-12.2-4.1
|
||||
c-2.9-2.8-4.4-6.6-4.4-11.4v-27.1h6.9v26.6c0,3.5,0.8,6,2.4,7.7c1.6,1.7,4.1,2.5,7.4,2.5c6.5,0,9.7-3.4,9.7-10.2v-26.6H200.5z"/>
|
||||
<path class="st3" d="M256.9,299h-8.4l-20.7-33.6h-0.2l0.1,1.9c0.3,3.6,0.4,6.8,0.4,9.8V299h-6.3v-42.1h8.4l20.7,33.4h0.2
|
||||
c0-0.4-0.1-2-0.2-4.8c-0.1-2.8-0.2-4.9-0.2-6.5v-22.1h6.3V299z"/>
|
||||
<path class="st3" d="M312.8,277.5c0,7-1.9,12.3-5.8,15.9c-3.9,3.7-9.4,5.5-16.7,5.5h-11.8v-42.1h13c6.7,0,11.9,1.8,15.6,5.4
|
||||
C310.9,265.9,312.8,271,312.8,277.5z M305.5,277.7c0-10.1-4.7-15.1-14.1-15.1h-6v30.6h4.9C300.4,293.2,305.5,288,305.5,277.7z"/>
|
||||
<path class="st3" d="M358.5,299l-4.2-11.7h-16.1L334,299h-7.3l15.8-42.3h7.5l15.8,42.3H358.5z M352.4,281.3l-3.9-11.5
|
||||
c-0.3-0.8-0.7-2-1.2-3.6c-0.5-1.7-0.9-2.9-1.1-3.6c-0.5,2.4-1.3,4.9-2.3,7.8l-3.8,11H352.4z"/>
|
||||
<path class="st3" d="M396.4,299h-6.9v-36.2h-12.4v-5.9h31.7v5.9h-12.4V299z"/>
|
||||
<path class="st3" d="M425.7,299v-42.1h6.9V299H425.7z"/>
|
||||
<path class="st3" d="M491.6,277.8c0,6.9-1.7,12.2-5.1,16c-3.4,3.8-8.3,5.7-14.6,5.7c-6.4,0-11.2-1.9-14.6-5.7
|
||||
c-3.4-3.8-5.1-9.1-5.1-16.1s1.7-12.3,5.1-16c3.4-3.7,8.3-5.6,14.7-5.6c6.3,0,11.1,1.9,14.5,5.7C489.9,265.6,491.6,271,491.6,277.8
|
||||
z M459.5,277.8c0,5.2,1,9.1,3.1,11.8c2.1,2.7,5.2,4,9.3,4c4.1,0,7.2-1.3,9.3-4c2.1-2.7,3.1-6.6,3.1-11.8c0-5.2-1-9.1-3.1-11.8
|
||||
s-5.1-4-9.2-4c-4.1,0-7.2,1.3-9.3,4C460.5,268.8,459.5,272.7,459.5,277.8z"/>
|
||||
<path class="st3" d="M546.3,299h-8.4l-20.7-33.6h-0.2l0.1,1.9c0.3,3.6,0.4,6.8,0.4,9.8V299h-6.3v-42.1h8.4l20.7,33.4h0.2
|
||||
c0-0.4-0.1-2-0.2-4.8c-0.1-2.8-0.2-4.9-0.2-6.5v-22.1h6.3V299z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.4 KiB |
@@ -0,0 +1,163 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 25.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 650 500" style="enable-background:new 0 0 650 500;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFFFFF;}
|
||||
</style>
|
||||
<g>
|
||||
<path class="st0" d="M294.82,401.96c79.74,0,159.48,0.01,239.23-0.02c6.4,0,12.77-0.41,19.02-1.96
|
||||
c11.51-2.86,21.12-8.67,28.49-18.07c6.12-7.8,10.16-16.62,12.59-26.13c4.11-16.08,7.95-32.24,11.87-48.37
|
||||
c6.04-24.86,12.03-49.73,18.07-74.59c5.79-23.87,11.56-47.75,17.43-71.6c2.28-9.24,3.48-18.47,1.43-27.91
|
||||
c-2.17-9.98-6.96-18.42-14.89-24.93c-8.8-7.22-19.09-10.24-30.31-10.24C436.83,98.12,275.92,98.12,115,98.13
|
||||
c-5.72,0-11.38,0.69-16.93,2.1c-9.92,2.52-18.51,7.36-25.46,14.93c-6.72,7.32-11.33,15.91-14.11,25.36
|
||||
c-2.76,9.38-5.02,18.91-7.39,28.4c-7.21,28.91-14.37,57.83-21.54,86.75c-6.83,27.54-13.6,55.09-20.52,82.61
|
||||
c-2.3,9.16-3.73,18.31-1.82,27.71c2.34,11.58,8.11,20.96,17.84,27.77c8.69,6.08,18.54,8.21,28.97,8.21
|
||||
C134.31,401.96,214.56,401.96,294.82,401.96z"/>
|
||||
<path d="M294.82,401.96c-80.26,0-160.52,0-240.77,0c-10.43,0-20.28-2.14-28.97-8.21c-9.73-6.8-15.5-16.19-17.84-27.77
|
||||
c-1.91-9.41-0.48-18.55,1.82-27.71c6.92-27.52,13.69-55.07,20.52-82.61c7.17-28.92,14.33-57.84,21.54-86.75
|
||||
c2.37-9.49,4.63-19.02,7.39-28.4c2.79-9.45,7.39-18.04,14.11-25.36c6.95-7.57,15.54-12.41,25.46-14.93
|
||||
c5.55-1.41,11.21-2.1,16.93-2.1c160.92-0.01,321.83-0.02,482.75,0.01c11.22,0,21.51,3.02,30.31,10.24
|
||||
c7.93,6.51,12.72,14.95,14.89,24.93c2.05,9.43,0.84,18.67-1.43,27.91c-5.88,23.85-11.64,47.73-17.43,71.6
|
||||
c-6.03,24.86-12.03,49.73-18.07,74.59c-3.92,16.13-7.75,32.29-11.87,48.37c-2.43,9.51-6.47,18.33-12.59,26.13
|
||||
c-7.37,9.4-16.98,15.21-28.49,18.07c-6.25,1.55-12.63,1.96-19.02,1.96C454.31,401.97,374.56,401.96,294.82,401.96z M347.77,220.94
|
||||
c0.2-0.26,0.25-0.37,0.33-0.44c21.16-16.45,42.32-32.89,63.48-49.34c1.51-1.17,2.99-2.45,2.37-4.68c-0.67-2.39-2.7-2.47-4.68-2.56
|
||||
c-0.11,0-0.23-0.01-0.34-0.01c-6.75,0-13.51-0.14-20.26,0.09c-1.88,0.06-4.05,0.75-5.53,1.89c-12.16,9.41-24.18,18.99-36.25,28.52
|
||||
c-3.71,2.93-7.42,5.85-11.18,8.81c-0.33-0.44-0.58-0.74-0.8-1.07c-7.85-11.51-15.75-22.98-23.48-34.56
|
||||
c-1.81-2.71-4.04-3.73-7.14-3.7c-8.64,0.06-17.29,0.02-25.93,0.03c-1.03,0-2.07,0.01-3.09,0.13c-4.3,0.51-5.95,4.08-3.52,7.56
|
||||
c8.94,12.84,17.89,25.67,26.84,38.51c3.42,4.91,6.83,9.83,10.3,14.82c-0.51,0.43-0.93,0.82-1.38,1.16
|
||||
c-15.71,12-31.42,24-47.17,35.95c-0.75,0.57-1.84,0.96-2.77,0.97c-7.9,0.08-15.8,0.05-23.7,0.04c-0.47,0-0.95-0.07-1.31-0.1
|
||||
c1.17-3.58,2.5-6.98,3.38-10.49c4.3-17.27,8.52-34.56,12.69-51.87c1.41-5.86,3.06-11.67,3.26-17.78
|
||||
c0.28-8.53-3.37-14.09-11.46-16.73c-6.09-1.99-12.43-2.36-18.77-2.37c-34.34-0.04-68.69-0.03-103.03-0.03
|
||||
c-0.52,0-1.03-0.02-1.54,0.02c-2.8,0.2-5.09,2.01-5.74,4.6c-0.73,2.92-1.44,5.85-2.09,8.8c-0.61,2.76,0.6,4.42,3.42,4.77
|
||||
c0.62,0.08,1.26,0.03,1.89,0.03c32.97,0,65.94,0,98.91,0c0.92,0,1.84-0.04,2.75,0.03c2.51,0.19,3.34,1.1,3.22,3.62
|
||||
c-0.05,1.01-0.26,2.03-0.5,3.03c-4.87,20.06-9.74,40.12-14.65,60.17c-0.84,3.42-1.74,6.83-2.72,10.21
|
||||
c-0.64,2.21-2.08,3.64-4.54,3.74c-0.91,0.04-1.82,0.21-2.73,0.21c-6.3,0.02-12.59,0.01-18.89,0.01c-11.28,0-22.55-0.01-33.83,0.01
|
||||
c-3.53,0.01-5.66,1.69-6.51,5.1c-0.71,2.87-1.39,5.75-2.06,8.63c-0.47,2.05,0.45,3.63,2.51,4.15c0.87,0.22,1.8,0.32,2.71,0.32
|
||||
c18.15,0.02,36.29,0.08,54.44-0.03c4.56-0.03,9.13-0.42,13.66-0.98c3.45-0.43,6.84-1.38,10.27-2.11c0.63,2.3,1.8,3.2,4.43,3.2
|
||||
c15.68-0.01,31.37,0.01,47.05-0.14c1.7-0.02,3.68-0.68,5.05-1.69c13.71-10.09,27.33-20.31,40.97-30.49
|
||||
c3.09-2.31,6.18-4.6,9.32-6.94c0.34,0.49,0.58,0.81,0.79,1.14c7.53,11.71,15.09,23.4,22.54,35.17c1.34,2.11,3.02,2.9,5.38,2.89
|
||||
c8.76-0.03,17.52,0,26.27-0.03c1.08,0,2.18-0.1,3.22-0.36c3.8-0.93,4.96-4.06,2.75-7.25c-6.1-8.77-12.21-17.52-18.31-26.28
|
||||
C359.98,238.49,353.89,229.73,347.77,220.94z M489.13,228.49c-0.09,0.67-0.1,1.12-0.21,1.55c-3.7,15.25-7.4,30.5-11.1,45.75
|
||||
c-0.84,3.47,0.48,5.31,4.08,5.35c7.38,0.07,14.77,0.07,22.15,0c3.47-0.03,5.87-2.13,6.68-5.49c3.63-15.03,7.31-30.05,10.85-45.11
|
||||
c0.41-1.76,1.13-2.08,2.73-2.08c16.2,0.05,32.4,0.03,48.59,0.02c1.03,0,2.06-0.04,3.08-0.19c2.4-0.34,4.29-2.22,4.87-4.58
|
||||
c0.73-2.98,1.67-5.91,2.25-8.91c0.19-0.96-0.15-2.5-0.82-3.03c-1.02-0.8-2.56-1.3-3.88-1.3c-16.6-0.08-33.2-0.05-49.8-0.05
|
||||
c-0.68,0-1.36,0-2.11,0c0.05-0.55,0.05-0.95,0.14-1.33c3.21-13.09,6.42-26.18,9.65-39.26c0.9-3.67-0.67-5.86-4.43-5.89
|
||||
c-7.1-0.06-14.2-0.05-21.29,0c-3.76,0.03-6.17,2.09-7.06,5.74c-3.2,13.15-6.43,26.29-9.64,39.44c-0.18,0.74-0.33,1.33-1.39,1.33
|
||||
c-12.99-0.04-25.99-0.02-38.98-0.05c-2.14,0-3.59-1.27-3.84-3.4c-0.14-1.17-0.13-2.43,0.14-3.57c2.68-11.29,5.42-22.56,8.15-33.83
|
||||
c0.84-3.47-0.73-5.64-4.29-5.67c-7.1-0.06-14.2-0.05-21.29,0c-3.65,0.02-5.98,1.87-6.87,5.46c-2.88,11.59-5.78,23.17-8.51,34.8
|
||||
c-0.93,3.97-1.82,8.03-1.99,12.08c-0.26,6.08,3.83,10.83,9.68,11.89c1.95,0.35,3.99,0.31,5.99,0.32
|
||||
c18.72,0.02,37.43,0.01,56.15,0.01C487.55,228.49,488.27,228.49,489.13,228.49z M89.55,322.76c3.72,0,7.44,0.02,11.16-0.01
|
||||
c2.91-0.02,5.42-2.04,6.1-4.81c8.58-35.29,17.16-70.58,25.74-105.88c0.93-3.81-0.89-6.08-4.85-6.09c-6.52-0.01-13.04-0.01-19.57,0
|
||||
c-4.38,0-6.83,2.01-7.87,6.29c-5.09,20.99-10.21,41.97-15.32,62.96c-3.46,14.19-6.92,28.38-10.36,42.58
|
||||
c-0.77,3.18,0.65,4.93,3.98,4.95C82.23,322.78,85.89,322.76,89.55,322.76z M345.36,342.26c0.77,0,1.45,0,2.13,0
|
||||
c9.78,0,19.57,0.02,29.35-0.01c4.94-0.01,8.85-3.05,9.86-7.62c1.73-7.83,3.44-15.66,5.13-23.5c1.01-4.66-1.4-7.83-6.17-7.86
|
||||
c-11.38-0.07-22.77-0.08-34.15,0c-4.84,0.04-8.44,3.17-9.46,7.83c-1.91,8.72-3.84,17.44-5.74,26.16
|
||||
c-1.05,4.82-2.06,9.65-3.08,14.48C339.59,352.7,343.88,349.37,345.36,342.26z M178.96,303.44c-0.38-0.09-0.54-0.17-0.7-0.17
|
||||
c-13.84-0.01-27.68-0.09-41.52,0.03c-4.83,0.04-8.29,3.27-9.31,8.02c-1.65,7.67-3.3,15.34-4.99,23c-1.03,4.66,1.32,7.89,6.07,7.92
|
||||
c13.56,0.07,27.11,0.01,40.67,0.05c1.08,0,1.42-0.36,1.64-1.42c0.98-4.85,2.1-9.66,3.16-14.49
|
||||
C175.63,318.77,177.28,311.17,178.96,303.44z M308.09,303.25c-5.55,0-11.1,0-16.65,0c-0.06,0-0.11,0-0.17,0
|
||||
c-5.2,0.07-8.89,3.09-9.96,8.13c-1.63,7.68-3.28,15.35-4.95,23.02c-1,4.58,1.32,7.8,5.98,7.83c11.45,0.08,22.89,0.07,34.34,0
|
||||
c4.63-0.03,8.34-3.13,9.33-7.57c1.8-8.05,3.58-16.1,5.3-24.16c0.21-0.96,0.16-2.07-0.1-3.03c-0.74-2.8-2.94-4.2-6.46-4.21
|
||||
C319.19,303.23,313.64,303.25,308.09,303.25z M473.33,342.26c5.55,0,11.1,0.02,16.65-0.01c5.04-0.02,8.77-2.91,9.87-7.79
|
||||
c1.75-7.77,3.42-15.55,5.09-23.34c1.02-4.76-1.27-7.82-6.09-7.85c-11.39-0.08-22.78-0.08-34.17,0c-4.85,0.03-8.45,3.06-9.51,7.8
|
||||
c-1.55,6.94-3.03,13.89-4.54,20.84c-0.17,0.78-0.29,1.57-0.46,2.34c-1.09,4.82,1.36,7.95,6.33,7.99
|
||||
C462.11,342.29,467.72,342.26,473.33,342.26z M192.74,332.26c0-0.42-0.06-0.77,0.01-1.1c1.31-5.94,2.64-11.87,3.97-17.81
|
||||
c0.12-0.55,0.24-1.11,0.37-1.67c1.23-5.49-1.4-8.62-7.03-8.45c-0.95,0.03-1.35,0.27-1.57,1.3c-2.12,10.01-4.34,20-6.48,30.01
|
||||
c-0.98,4.58,1.42,7.66,6.12,7.69c11.38,0.07,22.77,0.07,34.15,0c4.81-0.03,8.56-3.33,9.56-7.99c1.65-7.73,3.37-15.44,5.04-23.16
|
||||
c0.55-2.53,1.06-5.07,1.59-7.62c-5.73-0.93-10.51,2.17-11.71,7.47c-0.88,3.88-1.66,7.78-2.51,11.67c-0.71,3.25-1.45,6.49-2.15,9.65
|
||||
C212.16,332.26,202.45,332.26,192.74,332.26z M525.75,303.27c0.14-1.77,0.54-3.38,0.33-4.91c-0.43-3.22-3.32-4.94-7.39-4.81
|
||||
c-0.92,0.03-1.28,0.33-1.47,1.23c-2.88,13.45-5.79,26.9-8.69,40.34c-0.73,3.4,1.19,6.56,4.64,6.84c4.08,0.33,8.24,0.44,12.31,0.05
|
||||
c4.97-0.47,8.23-4.55,8.31-9.7c-4.79,0-9.58,0-14.41,0c-0.02-0.35-0.08-0.58-0.03-0.79c1.26-5.83,2.5-11.67,3.84-17.49
|
||||
c0.09-0.38,0.86-0.84,1.33-0.87c2.05-0.1,4.12-0.03,6.18-0.04c5.14-0.03,9.45-4.43,9.48-9.87
|
||||
C535.34,303.27,530.51,303.27,525.75,303.27z M255.24,313.14c2.68,0,5.19,0.03,7.71-0.01c4.88-0.07,9.22-4.75,9.02-9.91
|
||||
c-4.76,0-9.54,0-14.47,0c0.15-0.83,0.26-1.44,0.38-2.04c0.64-3.29-0.58-6.14-3.37-7.03c-1.52-0.49-3.3-0.64-4.83-0.3
|
||||
c-0.55,0.12-0.7,2.09-1.02,3.22c-0.05,0.16-0.06,0.34-0.09,0.5c-2.69,12.28-5.4,24.55-8.07,36.83c-0.93,4.31,1.01,7.39,5.2,7.72
|
||||
c3.81,0.3,7.68,0.33,11.48-0.04c5.08-0.5,8.69-4.86,8.49-9.78c-4.82,0-9.66,0-14.61,0C252.47,325.81,253.85,319.5,255.24,313.14z
|
||||
M425.9,332.34c1.58-7.21,3.12-14.26,4.67-21.3c0.72-3.28-0.39-6.1-3.13-7.16c-1.24-0.48-2.67-0.42-4.02-0.64
|
||||
c-1.06-0.17-1.41,0.44-1.6,1.31c-2.18,10.05-4.42,20.1-6.54,30.17c-0.88,4.17,1.23,7.15,5.38,7.44c3.64,0.25,7.33,0.29,10.97,0
|
||||
c5.27-0.42,8.89-4.55,8.91-9.81C435.7,332.34,430.86,332.34,425.9,332.34z M401.48,317.9c-2.43-0.01-2.46-0.02-2.96,2.31
|
||||
c-0.99,4.6-1.94,9.22-2.93,13.82c-1.13,5.22,1.23,8.17,6.53,8.27c1.35,0.03,1.89-0.41,2.16-1.7c1.03-5.06,2.12-10.11,3.24-15.15
|
||||
C408.48,321.04,406,317.91,401.48,317.9z M400.15,312.96c0.26,0.08,0.37,0.15,0.48,0.15c1.94,0.01,3.89,0.03,5.83,0.03
|
||||
c3.78,0,3.8,0.01,4.59-3.66c0.43-2.01,0.79-4.04,1.21-6.15c-3.51,0-6.69,0-9.99,0C401.56,306.55,400.87,309.7,400.15,312.96z"/>
|
||||
<path class="st0" d="M347.77,220.94c6.11,8.79,12.21,17.55,18.31,26.31c6.1,8.76,12.21,17.52,18.31,26.28
|
||||
c2.22,3.19,1.05,6.31-2.75,7.25c-1.04,0.26-2.15,0.35-3.22,0.36c-8.76,0.03-17.52,0-26.27,0.03c-2.36,0.01-4.04-0.78-5.38-2.89
|
||||
c-7.45-11.77-15.01-23.46-22.54-35.17c-0.21-0.33-0.45-0.65-0.79-1.14c-3.14,2.34-6.24,4.63-9.32,6.94
|
||||
c-13.64,10.18-27.26,20.4-40.97,30.49c-1.37,1.01-3.35,1.67-5.05,1.69c-15.68,0.15-31.37,0.13-47.05,0.14
|
||||
c-2.63,0-3.79-0.9-4.43-3.2c-3.43,0.72-6.82,1.68-10.27,2.11c-4.53,0.56-9.1,0.96-13.66,0.98c-18.14,0.11-36.29,0.05-54.44,0.03
|
||||
c-0.9,0-1.83-0.09-2.71-0.32c-2.05-0.52-2.98-2.1-2.51-4.15c0.67-2.88,1.34-5.76,2.06-8.63c0.84-3.4,2.98-5.09,6.51-5.1
|
||||
c11.28-0.02,22.55-0.01,33.83-0.01c6.3,0,12.59,0.01,18.89-0.01c0.91,0,1.82-0.17,2.73-0.21c2.47-0.1,3.9-1.52,4.54-3.74
|
||||
c0.98-3.38,1.89-6.79,2.72-10.21c4.9-20.05,9.78-40.11,14.65-60.17c0.24-0.99,0.45-2.01,0.5-3.03c0.12-2.52-0.71-3.43-3.22-3.62
|
||||
c-0.91-0.07-1.83-0.03-2.75-0.03c-32.97,0-65.94,0-98.91,0c-0.63,0-1.27,0.04-1.89-0.03c-2.82-0.34-4.03-2-3.42-4.77
|
||||
c0.65-2.94,1.36-5.87,2.09-8.8c0.65-2.59,2.93-4.39,5.74-4.6c0.51-0.04,1.03-0.02,1.54-0.02c34.34,0,68.69-0.01,103.03,0.03
|
||||
c6.34,0.01,12.68,0.38,18.77,2.37c8.09,2.65,11.74,8.2,11.46,16.73c-0.2,6.11-1.85,11.92-3.26,17.78
|
||||
c-4.17,17.3-8.39,34.6-12.69,51.87c-0.88,3.51-2.21,6.91-3.38,10.49c0.36,0.03,0.84,0.1,1.31,0.1c7.9,0.01,15.8,0.04,23.7-0.04
|
||||
c0.94-0.01,2.02-0.4,2.77-0.97c15.75-11.95,31.46-23.95,47.17-35.95c0.45-0.34,0.86-0.72,1.38-1.16
|
||||
c-3.47-4.99-6.88-9.91-10.3-14.82c-8.94-12.84-17.89-25.67-26.84-38.51c-2.43-3.48-0.77-7.05,3.52-7.56
|
||||
c1.02-0.12,2.06-0.13,3.09-0.13c8.64-0.01,17.29,0.04,25.93-0.03c3.1-0.02,5.33,0.99,7.14,3.7c7.73,11.59,15.64,23.05,23.48,34.56
|
||||
c0.22,0.33,0.47,0.63,0.8,1.07c3.76-2.96,7.47-5.88,11.18-8.81c12.07-9.53,24.09-19.11,36.25-28.52c1.47-1.14,3.65-1.83,5.53-1.89
|
||||
c6.75-0.22,13.51-0.09,20.26-0.09c0.11,0,0.23,0,0.34,0.01c1.98,0.08,4.01,0.17,4.68,2.56c0.62,2.22-0.86,3.5-2.37,4.68
|
||||
c-21.16,16.45-42.32,32.9-63.48,49.34C348.02,220.57,347.97,220.68,347.77,220.94z"/>
|
||||
<path class="st0" d="M489.13,228.49c-0.86,0-1.59,0-2.32,0c-18.72,0-37.43,0.01-56.15-0.01c-2,0-4.04,0.04-5.99-0.32
|
||||
c-5.85-1.06-9.94-5.81-9.68-11.89c0.17-4.05,1.06-8.11,1.99-12.08c2.73-11.62,5.63-23.21,8.51-34.8c0.89-3.59,3.22-5.44,6.87-5.46
|
||||
c7.1-0.05,14.2-0.05,21.29,0c3.56,0.03,5.13,2.2,4.29,5.67c-2.73,11.27-5.47,22.55-8.15,33.83c-0.27,1.14-0.28,2.4-0.14,3.57
|
||||
c0.26,2.13,1.7,3.39,3.84,3.4c12.99,0.03,25.99,0,38.98,0.05c1.05,0,1.2-0.58,1.39-1.33c3.21-13.15,6.43-26.29,9.64-39.44
|
||||
c0.89-3.65,3.3-5.71,7.06-5.74c7.1-0.05,14.2-0.05,21.29,0c3.76,0.03,5.34,2.22,4.43,5.89c-3.22,13.09-6.44,26.17-9.65,39.26
|
||||
c-0.09,0.38-0.09,0.79-0.14,1.33c0.75,0,1.43,0,2.11,0c16.6,0,33.2-0.03,49.8,0.05c1.32,0.01,2.85,0.51,3.88,1.3
|
||||
c0.68,0.53,1.01,2.07,0.82,3.03c-0.58,3-1.52,5.93-2.25,8.91c-0.58,2.36-2.47,4.24-4.87,4.58c-1.01,0.15-2.05,0.19-3.08,0.19
|
||||
c-16.2,0.01-32.4,0.03-48.59-0.02c-1.6-0.01-2.32,0.32-2.73,2.08c-3.54,15.06-7.22,30.08-10.85,45.11
|
||||
c-0.81,3.36-3.21,5.46-6.68,5.49c-7.38,0.07-14.77,0.07-22.15,0c-3.6-0.03-4.92-1.88-4.08-5.35c3.7-15.25,7.41-30.5,11.1-45.75
|
||||
C489.03,229.6,489.05,229.15,489.13,228.49z"/>
|
||||
<path class="st0" d="M89.55,322.76c-3.66,0-7.32,0.02-10.98,0c-3.33-0.02-4.75-1.77-3.98-4.95c3.44-14.2,6.9-28.39,10.36-42.58
|
||||
c5.11-20.99,10.23-41.97,15.32-62.96c1.04-4.29,3.49-6.29,7.87-6.29c6.52,0,13.04-0.01,19.57,0c3.96,0.01,5.77,2.28,4.85,6.09
|
||||
c-8.58,35.29-17.16,70.59-25.74,105.88c-0.67,2.77-3.19,4.79-6.1,4.81C96.99,322.78,93.27,322.76,89.55,322.76z"/>
|
||||
<path class="st0" d="M345.36,342.26c-1.47,7.11-5.76,10.44-12.14,9.48c1.03-4.83,2.03-9.66,3.08-14.48
|
||||
c1.9-8.72,3.83-17.44,5.74-26.16c1.02-4.67,4.62-7.8,9.46-7.83c11.38-0.08,22.77-0.08,34.15,0c4.77,0.03,7.18,3.2,6.17,7.86
|
||||
c-1.69,7.84-3.4,15.67-5.13,23.5c-1.01,4.57-4.92,7.61-9.86,7.62c-9.78,0.02-19.57,0.01-29.35,0.01
|
||||
C346.81,342.26,346.13,342.26,345.36,342.26z M381.26,313.22c-9.88,0-19.63,0-29.58,0c-1.37,6.28-2.75,12.59-4.16,19.03
|
||||
c9.9,0,19.66,0,29.58,0C378.48,325.96,379.86,319.65,381.26,313.22z"/>
|
||||
<path class="st0" d="M178.96,303.44c-1.68,7.73-3.33,15.33-4.99,22.93c-1.06,4.83-2.17,9.65-3.16,14.49
|
||||
c-0.21,1.06-0.56,1.42-1.64,1.42c-13.56-0.03-27.11,0.02-40.67-0.05c-4.76-0.02-7.1-3.25-6.07-7.92c1.69-7.66,3.34-15.33,4.99-23
|
||||
c1.02-4.75,4.48-7.98,9.31-8.02c13.84-0.11,27.68-0.03,41.52-0.03C178.42,303.27,178.58,303.35,178.96,303.44z M132.95,332.35
|
||||
c9.64,0,19.14,0.01,28.63-0.05c0.4,0,1.05-0.61,1.15-1.04c0.88-3.71,1.66-7.44,2.47-11.16c0.49-2.26,1-4.52,1.52-6.88
|
||||
c-9.99,0-19.76,0-29.56,0C135.77,319.55,134.39,325.82,132.95,332.35z"/>
|
||||
<path class="st0" d="M308.09,303.25c5.55,0,11.1-0.02,16.65,0.01c3.52,0.02,5.72,1.41,6.46,4.21c0.25,0.96,0.3,2.06,0.1,3.03
|
||||
c-1.72,8.07-3.5,16.12-5.3,24.16c-0.99,4.44-4.7,7.54-9.33,7.57c-11.45,0.07-22.89,0.08-34.34,0c-4.66-0.03-6.98-3.26-5.98-7.83
|
||||
c1.68-7.67,3.32-15.34,4.95-23.02c1.07-5.03,4.76-8.06,9.96-8.13c0.06,0,0.11,0,0.17,0C296.99,303.25,302.54,303.25,308.09,303.25z
|
||||
M286.85,332.35c9.64,0,19.08,0.02,28.52-0.05c0.44,0,1.14-0.64,1.26-1.1c0.76-2.97,1.41-5.98,2.07-8.98
|
||||
c0.65-2.97,1.27-5.95,1.9-8.97c-9.98,0-19.74,0-29.52,0C289.66,319.61,288.28,325.88,286.85,332.35z"/>
|
||||
<path class="st0" d="M473.33,342.26c-5.61,0-11.22,0.03-16.83-0.01c-4.98-0.04-7.42-3.17-6.33-7.99c0.17-0.78,0.3-1.57,0.46-2.34
|
||||
c1.51-6.95,2.99-13.9,4.54-20.84c1.06-4.74,4.66-7.76,9.51-7.8c11.39-0.08,22.78-0.08,34.17,0c4.82,0.03,7.11,3.09,6.09,7.85
|
||||
c-1.67,7.78-3.33,15.57-5.09,23.34c-1.1,4.88-4.82,7.76-9.87,7.79C484.43,342.28,478.88,342.26,473.33,342.26z M460.65,332.34
|
||||
c9.65,0,19.19,0.01,28.73-0.05c0.36,0,0.93-0.68,1.05-1.14c0.74-2.92,1.39-5.86,2.03-8.8c0.66-3.02,1.28-6.05,1.94-9.14
|
||||
c-9.97,0-19.73,0-29.54,0C463.46,319.59,462.07,325.9,460.65,332.34z"/>
|
||||
<path class="st0" d="M192.74,332.26c9.71,0,19.42,0,29.36,0c0.71-3.16,1.45-6.4,2.15-9.65c0.85-3.89,1.63-7.79,2.51-11.67
|
||||
c1.21-5.3,5.98-8.4,11.71-7.47c-0.53,2.54-1.04,5.08-1.59,7.62c-1.68,7.72-3.39,15.43-5.04,23.16c-1,4.66-4.75,7.96-9.56,7.99
|
||||
c-11.38,0.07-22.77,0.07-34.15,0c-4.71-0.03-7.1-3.1-6.12-7.69c2.14-10.01,4.36-20,6.48-30.01c0.22-1.03,0.62-1.27,1.57-1.3
|
||||
c5.63-0.16,8.25,2.97,7.03,8.45c-0.12,0.55-0.24,1.11-0.37,1.67c-1.33,5.94-2.66,11.87-3.97,17.81
|
||||
C192.68,331.49,192.74,331.84,192.74,332.26z"/>
|
||||
<path class="st0" d="M525.75,303.27c4.76,0,9.59,0,14.42,0c-0.03,5.44-4.33,9.84-9.48,9.87c-2.06,0.01-4.12-0.05-6.18,0.04
|
||||
c-0.47,0.02-1.24,0.48-1.33,0.87c-1.33,5.82-2.58,11.65-3.84,17.49c-0.04,0.21,0.02,0.44,0.03,0.79c4.83,0,9.62,0,14.41,0
|
||||
c-0.08,5.15-3.33,9.23-8.31,9.7c-4.07,0.38-8.23,0.27-12.31-0.05c-3.45-0.28-5.38-3.43-4.64-6.84c2.9-13.45,5.81-26.89,8.69-40.34
|
||||
c0.19-0.9,0.55-1.2,1.47-1.23c4.07-0.13,6.95,1.59,7.39,4.81C526.29,299.89,525.89,301.5,525.75,303.27z"/>
|
||||
<path class="st0" d="M255.24,313.14c-1.39,6.36-2.77,12.67-4.19,19.16c4.95,0,9.78,0,14.61,0c0.2,4.92-3.41,9.28-8.49,9.78
|
||||
c-3.8,0.37-7.67,0.33-11.48,0.04c-4.2-0.33-6.14-3.42-5.2-7.72c2.66-12.28,5.37-24.56,8.07-36.83c0.04-0.17,0.05-0.34,0.09-0.5
|
||||
c0.33-1.13,0.48-3.1,1.02-3.22c1.53-0.33,3.32-0.18,4.83,0.3c2.79,0.89,4.01,3.75,3.37,7.03c-0.12,0.6-0.22,1.21-0.38,2.04
|
||||
c4.93,0,9.71,0,14.47,0c0.21,5.16-4.13,9.84-9.02,9.91C260.43,313.16,257.92,313.14,255.24,313.14z"/>
|
||||
<path class="st0" d="M425.9,332.34c4.97,0,9.81,0,14.65,0c-0.02,5.26-3.64,9.39-8.91,9.81c-3.64,0.29-7.33,0.26-10.97,0
|
||||
c-4.15-0.29-6.26-3.27-5.38-7.44c2.12-10.07,4.35-20.11,6.54-30.17c0.19-0.87,0.54-1.49,1.6-1.31c1.34,0.22,2.78,0.17,4.02,0.64
|
||||
c2.74,1.06,3.85,3.88,3.13,7.16C429.01,318.09,427.47,325.13,425.9,332.34z"/>
|
||||
<path class="st0" d="M401.48,317.9c4.53,0.02,7.01,3.15,6.03,7.55c-1.11,5.04-2.21,10.09-3.24,15.15c-0.26,1.29-0.81,1.73-2.16,1.7
|
||||
c-5.3-0.1-7.66-3.05-6.53-8.27c1-4.6,1.94-9.22,2.93-13.82C399.02,317.88,399.05,317.89,401.48,317.9z"/>
|
||||
<path class="st0" d="M400.15,312.96c0.71-3.26,1.41-6.41,2.11-9.62c3.3,0,6.49,0,9.99,0c-0.41,2.11-0.77,4.14-1.21,6.15
|
||||
c-0.79,3.66-0.81,3.66-4.59,3.66c-1.94,0-3.89-0.01-5.83-0.03C400.52,313.11,400.41,313.04,400.15,312.96z"/>
|
||||
<path d="M381.26,313.22c-1.4,6.42-2.78,12.73-4.15,19.03c-9.92,0-19.68,0-29.58,0c1.41-6.43,2.78-12.74,4.16-19.03
|
||||
C361.63,313.22,371.38,313.22,381.26,313.22z"/>
|
||||
<path d="M132.95,332.35c1.44-6.52,2.82-12.79,4.22-19.13c9.8,0,19.57,0,29.56,0c-0.52,2.36-1.03,4.62-1.52,6.88
|
||||
c-0.81,3.72-1.59,7.45-2.47,11.16c-0.1,0.43-0.75,1.04-1.15,1.04C152.09,332.36,142.6,332.35,132.95,332.35z"/>
|
||||
<path d="M286.85,332.35c1.43-6.47,2.82-12.74,4.23-19.1c9.78,0,19.55,0,29.52,0c-0.64,3.02-1.25,6-1.9,8.97
|
||||
c-0.66,3-1.31,6.01-2.07,8.98c-0.12,0.46-0.82,1.1-1.26,1.1C305.93,332.36,296.49,332.35,286.85,332.35z"/>
|
||||
<path d="M460.65,332.34c1.42-6.44,2.81-12.75,4.21-19.13c9.82,0,19.58,0,29.54,0c-0.65,3.08-1.27,6.11-1.94,9.14
|
||||
c-0.64,2.94-1.3,5.88-2.03,8.8c-0.11,0.46-0.69,1.14-1.05,1.14C479.85,332.36,470.3,332.34,460.65,332.34z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 17 KiB |
+4
-1
@@ -253,8 +253,9 @@
|
||||
- [Benewake TFmini Lidar](sensor/tfmini.md)
|
||||
- [LeddarOne Lidar](sensor/leddar_one.md)
|
||||
- [Lidar-Lite](sensor/lidar_lite.md)
|
||||
- [Lightware Lidars (SF/LW)](sensor/sfxx_lidar.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)
|
||||
@@ -417,6 +418,7 @@
|
||||
- [Standard Configuration](config/index.md)
|
||||
- [Advanced Configuration](advanced_config/index.md)
|
||||
- [Using PX4's Navigation Filter (EKF2)](advanced_config/tuning_the_ecl_ekf.md)
|
||||
- [GNSS-Denied & Degraded Flight](advanced_config/gnss_degraded_or_denied_flight.md)
|
||||
- [Finding/Updating Parameters](advanced_config/parameters.md)
|
||||
- [Full Parameter Reference](advanced_config/parameter_reference.md)
|
||||
|
||||
@@ -908,6 +910,7 @@
|
||||
- [Terminology/Notation](contribute/notation.md)
|
||||
- [Licenses](contribute/licenses.md)
|
||||
- [Releases](releases/index.md)
|
||||
- [Release Process](releases/release_process.md)
|
||||
- [main (alpha)](releases/main.md)
|
||||
- [1.17 (alpha)](releases/1.17.md)
|
||||
- [1.16 (stable)](releases/1.16.md)
|
||||
|
||||
@@ -31,6 +31,7 @@ For more information see the topics for each data type:
|
||||
- [Parameters & Configurations > Creating/Defining Parameters](../advanced/parameters_and_configurations.md#creating-defining-parameters)
|
||||
- [Events Interface](../concept/events_interface.md)
|
||||
- [Actuator Metadata](#actuator-metadata) (below)
|
||||
|
||||
## Metadata Toolchain
|
||||
|
||||
The process for handling metadata is the same for all metadata types.
|
||||
@@ -69,6 +70,7 @@ The parameter XML file of the main branch is copied into the QGC source tree via
|
||||
The following diagram shows how actuator metadata is assembled from the source code and used by QGroundControl:
|
||||
|
||||

|
||||
|
||||
<!-- Source: https://docs.google.com/drawings/d/1hMQmIijdFjr21rREcXj50qz0C1b47JW0OEa6p5P231k/edit -->
|
||||
|
||||
- **Left**: the metadata is defined in `module.yml` files in different modules.
|
||||
|
||||
@@ -34,4 +34,3 @@ You can locate the parameters in QGroundControl as shown below:
|
||||
Positive angles increase in CCW direction, negative angles increase in CW direction.
|
||||
- [SENS_BOARD_Z_OFF](../advanced_config/parameter_reference.md#SENS_BOARD_Z_OFF): Rotation, in degrees, around PX4FMU's Z axis Yaw axis.
|
||||
Positive angles increase in CCW direction, negative angles increase in CW direction.
|
||||
|
||||
|
||||
@@ -63,7 +63,6 @@ The tool is available for Windows, Linux and macOS.
|
||||

|
||||
|
||||
To get the Pixhawk V6X-RT into "ISP bootloader mode" there are 2 options:
|
||||
|
||||
1. Launch QGC connect the Pixhawk select **Analayze Tools** and then **MAVLINK Console**.
|
||||
On the console type `reboot -i`.
|
||||
This will put the Pixhawk V6X-RT into "ISP bootloader mode"
|
||||
|
||||
@@ -89,7 +89,6 @@ To calibrate the ESCs:
|
||||
:::
|
||||
|
||||
Verify the following values:
|
||||
|
||||
- The minimum value for a motor (default: `1100us`) should make the motor spin slowly but reliably, and also spin up reliably after it was stopped.
|
||||
|
||||
You can confirm that a motor spins at minimum (still without propellers) in [Actuator Testing](../config/actuators.md#actuator-testing), by enabling the sliders, and then moving the test output slider for the motor to the first snap position from the bottom.
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
# GNSS-Degraded & Denied Flight ("Dead-Reckoning" Mode)
|
||||
|
||||
<Badge type="tip" text="PX4 v1.17" /> <Badge type="warning" text="Experimental" />
|
||||
|
||||
::: warning Experimental
|
||||
This is a new feature with limited real-world testing.
|
||||
It is intended for GNSS dropout scenarios (not pure GNSS-denied from takeoff), and requires that alternative velocity/position sensors are available.
|
||||
|
||||
Please [share your related test logs](../getting_started/flight_reporting.md#sharing-the-log-files-for-review-by-px4-developers) to help us verify and harden it.
|
||||
:::
|
||||
|
||||
PX4 is default-configured for outdoor flight with a reliable GNSS signal, but it can also be set up in "dead-reckoning mode" to more gracefully handle environments where GNSS is intermittently degraded or denied during flight.
|
||||
|
||||
This section describes the differences between automatic and dead-reckoning modes, the circumstances in which each should be used, and how dead-reckoning is configured.
|
||||
|
||||
## Overview
|
||||
|
||||
PX4's EKF2 navigation has two modes for handling when GNSS data is determined to be unreliable:
|
||||
|
||||
- **Automatic mode** (the default): Used for flying outdoors in environments where a GNSS signal is expected to be largely reliable.
|
||||
- **Dead-reckoning mode**: Recommended when you want to fly missions or other position controlled modes when there is intermittent GNSS loss, such as when flying under a bridge, from outdoors into an indoor setting, or when there is GNSS jamming (it is not suitable for pure-indoor use, as a GNSS signal is required before arming).
|
||||
|
||||
::: info
|
||||
Dead-reckoning mode helps for both Fixed-Wing and Multicopter vehicles.
|
||||
MC vehicles benefit more because they can hover when transitioning between sensor regimes.
|
||||
FW needs continuous accurate velocity/position during the entire mission arc, making sensor transitions trickier.
|
||||
:::
|
||||
|
||||
## Mode Comparison
|
||||
|
||||
The following sections provide more detail about each of the modes and when they should be used.
|
||||
|
||||
### Automatic Mode
|
||||
|
||||
In Automatic mode the EKF2 resets if GNSS is lost and no other sources of position are available.
|
||||
This can result in a [position loss failsafe](../config/safety.md#position-loss-failsafe) and may trigger a shift into a mode that does not require global position, including stopping missions.
|
||||
|
||||
This is desirable if the GNSS signal is likely to be recovered quickly and there are no mechanisms to estimate position when GNSS is unavailable.
|
||||
|
||||
Use Automatic (default) when:
|
||||
|
||||
- Flying in open sky with reliable GNSS throughout the mission.
|
||||
- You want the EKF to reset to GNSS when it becomes available again.
|
||||
- Operating in environments where GNSS is either good or completely unavailable (binary state).
|
||||
|
||||
### Dead-Reckoning Mode
|
||||
|
||||
In dead-reckoning mode, EKF2 stops fusing GNSS data when it becomes unreliable and prevents EKF2 resets — provided there are other sources of position or velocity data that can be fused.
|
||||
This ensures that the vehicle can continue flying missions and other position controlled modes when GNSS is lost.
|
||||
|
||||
When GNSS is recovered it will be fused with other measurements when tests indicate it can be trusted.
|
||||
This may cause jerky movements in position controlled modes if the estimate has drifted.
|
||||
This mode relies on having additional position or velocity sensors and must also have a reliable GNSS signal at boot.
|
||||
|
||||
Use Dead-Reckoning when:
|
||||
|
||||
- **Transitioning between GNSS and non-GNSS environments** (flying into buildings, under bridges, through tree cover).
|
||||
- You have **redundant sensors** (optical flow, VIO, rangefinder, quality baro) that can maintain position estimation.
|
||||
- Flying **missions that cross GPS-denied areas** where you want continuous operation rather than failsafe.
|
||||
- **Urban environments** or other areas with intermittent GNSS quality.
|
||||
- You want to **avoid EKF resets and jumps** when GNSS recovers (smoother transitions).
|
||||
|
||||
## Configuration
|
||||
|
||||
To use dead-reckoning mode, the vehicle must have an alternative source of position or velocity information, such as an [Optical Flow](../sensor/optical_flow.md) sensor or [VIO](../computer_vision/visual_inertial_odometry.md) setup.
|
||||
|
||||
To enable the mode:
|
||||
|
||||
1. Set [EKF2_GPS_MODE](../advanced_config/parameter_reference.md#EKF2_GPS_MODE) to `1`.
|
||||
2. Ensure that GNSS arming checks are enabled (a reliable GNSS signal is required before arming):
|
||||
- [COM_ARM_WO_GPS](../advanced_config/parameter_reference.md#COM_ARM_WO_GPS) - set to `0`
|
||||
- [EKF2_GPS_CHECK](../advanced_config/parameter_reference.md#EKF2_GPS_CHECK) - set to default.
|
||||
|
||||
## See Also
|
||||
|
||||
- [GNSS Fault Detection](../advanced_config/tuning_the_ecl_ekf.md#gnss-fault-detection) in _Using PX4's Navigation Filter (EKF2)_
|
||||
- [Fuse, Reset, or Reject? Handling Various Data-sources in EKF2](https://www.youtube.com/watch?v=CMGQJNPiTJg) - _PX4 Developer Summit 2025_, Marco Hauswirth, Auterion AG
|
||||
@@ -10,6 +10,7 @@ This topic lists configuration topics that are not particularly vehicle specific
|
||||
## Feature configuration
|
||||
|
||||
- [Using PX4's Navigation Filter (EKF2)](../advanced_config/tuning_the_ecl_ekf.md)
|
||||
- [GNSS-Denied and Degraded Flight](../advanced_config/gnss_degraded_or_denied_flight.md)
|
||||
- [Flight Termination Configuration](../advanced_config/flight_termination.md)
|
||||
- [Land Detector Configuration](../advanced_config/land_detector.md)
|
||||
- [Prearm/Arm/Disarm Configuration](../advanced_config/prearm_arm_disarm.md)
|
||||
|
||||
@@ -38,7 +38,7 @@ In order to detect landing, the multicopter first has to go through three differ
|
||||
If a condition cannot be reached because of missing sensors, then the condition is true by default.
|
||||
For instance, in [Acro mode](../flight_modes_mc/acro.md) and no sensor is active except for the gyro sensor, then the detection solely relies on thrust output and time.
|
||||
|
||||
In order to proceed to the next state, each condition has to be true for a third of the configured total land detector trigger time [LNDMC_TRIG_TIME](../advanced_config/parameter_reference.md#LNDMC_TRIG_TIME).
|
||||
In order to proceed to the next state, each condition has to be true for 300ms.
|
||||
If the vehicle is equipped with a distance sensor, but the distance to ground is currently not measurable (usually because it is too large), the trigger time is increased by a factor of 3.
|
||||
|
||||
If one condition fails, the land detector drops out of the current state immediately.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -361,6 +361,10 @@ The mode is set using the [EKF2_GPS_MODE](../advanced_config/parameter_reference
|
||||
EKF2 may reset if no other sources of position or velocity are available.
|
||||
If GNSS altitude OR horizontal position data drifts, the system disables fusion of both measurements simultaneously (even if one would still pass validation) and avoids performing resets.
|
||||
|
||||
::: tip
|
||||
See also [Fault Detection](https://youtu.be/CMGQJNPiTJg?si=sFtdf4AQbcOH8-u8) in "Fuse, Reset, or Reject? Handling Various Data-sources in EKF2" _PX4 Developer Summit 2025_, Marco Hauswirth, Auterion AG
|
||||
:::
|
||||
|
||||
##### Detection Logic
|
||||
|
||||
Horizontal Position:
|
||||
@@ -892,3 +896,4 @@ If no terrain estimate is available this parameter will have no effect and the s
|
||||
## Further Information
|
||||
|
||||
- [PX4 State Estimation Overview](https://youtu.be/HkYRJJoyBwQ), _PX4 Developer Summit 2019_, Dr. Paul Riseborough): Overview of the estimator, and major changes from 2018/19, and the expected improvements through 2019/20.
|
||||
- [Fuse, Reset, or Reject? Handling Various Data-sources in EKF2](https://www.youtube.com/watch?v=CMGQJNPiTJg) - _PX4 Developer Summit 2025_, Marco Hauswirth, Auterion AG
|
||||
|
||||
@@ -12,19 +12,16 @@ The [ARK Jetson Pixhawk Autopilot Bus (PAB) Carrier](https://arkelectron.gitbook
|
||||
## Specifications
|
||||
|
||||
- **Power Requirements**
|
||||
|
||||
- 5V
|
||||
- 4A minimum (dependent on usage and peripherals)
|
||||
|
||||
- **Additional Features**
|
||||
|
||||
- Pixhawk Autopilot Bus (PAB) Form Factor ([PAB Standard](https://github.com/pixhawk/Pixhawk-Standards/blob/master/DS-010%20Pixhawk%20Autopilot%20Bus%20Standard.pdf))
|
||||
- MicroSD Slot
|
||||
- USA-built, NDAA compliant
|
||||
- Integrated 1W heater for sensor stability in extreme conditions
|
||||
|
||||
- **Physical Details**
|
||||
|
||||
- Weight:
|
||||
- Without Jetson and Flight Controller – 80g
|
||||
- With Jetson, no heatsink or Flight Controller – 108g
|
||||
|
||||
@@ -18,7 +18,6 @@ The board follows the [Pixhawk Connector Standard](https://github.com/pixhawk/Pi
|
||||
- [Holybro Pixhawk RPi CM4 Baseboard](https://holybro.com/products/pixhawk-rpi-cm4-baseboard) (www.holybro.com)
|
||||
|
||||
The baseboard can be purchased with or without an RPi CM4 and/or flight controller:
|
||||
|
||||
- The Raspberry Pi CM4 (CM4008032) supplied by Holybro has the following specification:
|
||||
- RAM: 8GB
|
||||
- eMMC: 32GB
|
||||
@@ -167,7 +166,6 @@ To enable this MAVLink instance on the FC:
|
||||

|
||||
|
||||
1. [Set the parameters](../advanced_config/parameters.md):
|
||||
|
||||
- `MAV_1_CONFIG` = `102`
|
||||
- `MAV_1_MODE = 2`
|
||||
- `SER_TEL2_BAUD` = `921600`
|
||||
@@ -180,7 +178,6 @@ On the RPi side:
|
||||
|
||||
1. Connect to the RPi (using WiFi, a router, or a WiFi Dongle).
|
||||
1. Enable the RPi serial port by running `RPi-config`
|
||||
|
||||
- Go to `3 Interface Options`, then `I6 Serial Port`.
|
||||
Then choose:
|
||||
- `login shell accessible over serial → No`
|
||||
|
||||
@@ -91,7 +91,7 @@ During PX4 setup and configuration the USB connection with your ground station l
|
||||
|
||||
These instructions work on PX4 v1.14 and later.
|
||||
|
||||
If you need to update the firmware then connect the Pixhawk to your laptop/desktop via the `USB` port and use QGroundControl to update the firmware as described [Firmware > Install Stable PX4](../config/firmware.md#install-stable-px4).
|
||||
If you need to update the firmware then connect the Pixhawk to your laptop/desktop via the `USB` port and use QGroundControl to update the firmware as described [Firmware > Install Stable PX4](../config/firmware.md#install-stable-px4).
|
||||
If you want the latest developer version then update the firmware to the "main" as described in [Firmware > Installing PX4 Master, Beta or Custom Firmware](../config/firmware.md#installing-px4-main-beta-or-custom-firmware).
|
||||
|
||||
::: info
|
||||
@@ -143,7 +143,6 @@ Enter the following commands (in sequence) a terminal to configure Ubuntu for RP
|
||||
```
|
||||
|
||||
1. Go to the **Interface Option** and then click **Serial Port**.
|
||||
|
||||
- Select **No** to disable serial login shell.
|
||||
- Select **Yes** to enable the serial interface.
|
||||
- Click **Finish** and restart the RPi.
|
||||
@@ -162,7 +161,6 @@ Enter the following commands (in sequence) a terminal to configure Ubuntu for RP
|
||||
```
|
||||
|
||||
1. Then save the file and restart the RPi.
|
||||
|
||||
- In `nano` you can save the file using the following sequence of keyboard shortcuts: **ctrl+x**, **ctrl+y**, **Enter**.
|
||||
|
||||
1. Check that the serial port is available.
|
||||
|
||||
@@ -60,7 +60,7 @@ Configure collision prevention by [setting the following parameters](../advanced
|
||||
| <a id="CP_DELAY"></a>[CP_DELAY](../advanced_config/parameter_reference.md#CP_DELAY) | Set the sensor and velocity setpoint tracking delay. See [Delay Tuning](#delay_tuning) below. |
|
||||
| <a id="CP_GUIDE_ANG"></a>[CP_GUIDE_ANG](../advanced_config/parameter_reference.md#CP_GUIDE_ANG) | Set the angle (to both sides of the commanded direction) within which the vehicle may deviate if it finds fewer obstacles in that direction. See [Guidance Tuning](#angle_change_tuning) below. |
|
||||
| <a id="CP_GO_NO_DATA"></a>[CP_GO_NO_DATA](../advanced_config/parameter_reference.md#CP_GO_NO_DATA) | Set to 1 to allow the vehicle to move in directions where there is no sensor coverage (default is 0/`False`). |
|
||||
| <a id="MPC_POS_MODE"></a>[MPC_POS_MODE](../advanced_config/parameter_reference.md#MPC_POS_MODE) | Must be set to `Acceleration based`. |
|
||||
| <a id="MPC_POS_MODE"></a>[MPC_POS_MODE](../advanced_config/parameter_reference.md#MPC_POS_MODE) | Must be set to `Acceleration based`. |
|
||||
|
||||
## Algorithm Description
|
||||
|
||||
@@ -213,7 +213,6 @@ The steps are:
|
||||
|
||||
3. Open PlotJuggler and navigate to the **Tools > Reactive Script Editor** section.
|
||||
In the **Script Editor** tab, add following scripts in the appropriate sections:
|
||||
|
||||
- **Global code, executed once:**
|
||||
|
||||
```lua
|
||||
|
||||
@@ -32,7 +32,6 @@ The instructions below might be used to create a task named _MyTask_:
|
||||
- FlightTaskMyTask.hpp
|
||||
- FlightTaskMyTask.cpp
|
||||
3. Update **CMakeLists.txt** for the new task
|
||||
|
||||
- Copy the contents of the **CMakeLists.txt** for another task - e.g. [Orbit/CMakeLists.txt](https://github.com/PX4/PX4-Autopilot/blob/main/src/modules/flight_mode_manager/tasks/Orbit/CMakeLists.txt)
|
||||
- Update the copyright to the current year
|
||||
|
||||
@@ -135,7 +134,6 @@ The instructions below might be used to create a task named _MyTask_:
|
||||
Usually a parameter is used to select when a particular flight task should be used.
|
||||
|
||||
For example, to enable our new `MyTask` in multicopter Position mode:
|
||||
|
||||
- Update `MPC_POS_MODE` ([multicopter_position_mode_params.c](https://github.com/PX4/PX4-Autopilot/blob/main/src/modules/mc_pos_control/multicopter_position_mode_params.c)) to add an option for selecting "MyTask" if the parameter has a previously unused value like 5:
|
||||
|
||||
```c
|
||||
|
||||
@@ -14,7 +14,7 @@ The directory structure/layout is shown below.
|
||||
| `/etc/` | Extra config. See [System Startup > Replacing the System Startup][replace system start]. |
|
||||
| `/log/` | Full [flight logs](../dev_log/logging.md) |
|
||||
| `/mission_log/` | Reduced flight logs |
|
||||
| `/fw/` | [DroneCAN](../dronecan/index.md) firmware |
|
||||
| `/fw/` | [DroneCAN](../dronecan/index.md) firmware |
|
||||
| `/uavcan.db/` | DroneCAN DNA server DB + logs |
|
||||
| `/params` | Parameters (if not in FRAM/FLASH) |
|
||||
| `/dataman` | Mission storage file |
|
||||
|
||||
@@ -82,14 +82,9 @@ The test steps are:
|
||||
If an [Enable/Disable Autotune Switch](#enable-disable-autotune-switch) is configured you can just toggle the switch to the "enabled" position.
|
||||
|
||||
</div></div>
|
||||
|
||||
1. In QGroundControl, open the menu **Vehicle setup > PID Tuning**:
|
||||
|
||||

|
||||
|
||||
2. Select either the _Rate Controller_ or _Attitude Controller_ tabs.
|
||||
3. Ensure that the **Autotune enabled** button is enabled (this will display the **Autotune** button and remove the manual tuning selectors).
|
||||
4. Read the warning popup and click on **OK** to start tuning.
|
||||
 2. Select either the _Rate Controller_ or _Attitude Controller_ tabs. 3. Ensure that the **Autotune enabled** button is enabled (this will display the **Autotune** button and remove the manual tuning selectors). 4. Read the warning popup and click on **OK** to start tuning.
|
||||
|
||||
<div style="display: inline;" v-if="$frontmatter.frame === 'Multicopter'">
|
||||
|
||||
@@ -197,11 +192,8 @@ By default, the autotune maneuvers ensure that a sufficient angular rate is reac
|
||||
|
||||
If the signal-to-noise ratio of the vehicle is low, the system identification algorithm might have issues finding the correct coefficients. Ensure that there is no excessive noise and/or platform vibration.
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
### The drone oscillates after auto-tuning
|
||||
|
||||
Due to effects not included in the mathematical model such as delays, saturation, slew-rate, airframe flexibility, the loop gain can be too high.
|
||||
|
||||
@@ -4,15 +4,15 @@ This topic explains how to map [flight modes](../getting_started/px4_basic_conce
|
||||
|
||||
:::tip
|
||||
In order to set up flight modes you must already have:
|
||||
|
||||
- [Configured your radio](../config/radio.md)
|
||||
- [Setup your transmitter](#rc-transmitter-setup) to encode the physical positions of your mode switch(es) into a single channel.
|
||||
We provide examples for the popular *Taranis* transmitter [below](#taranis-setup-3-way-switch-configuration-for-single-channel-mode) (check your documentation if you use a different transmitter).
|
||||
:::
|
||||
|
||||
We provide examples for the popular _Taranis_ transmitter [below](#taranis-setup-3-way-switch-configuration-for-single-channel-mode) (check your documentation if you use a different transmitter).
|
||||
:::
|
||||
|
||||
## What Flight Modes and Switches Should I Set?
|
||||
|
||||
Flight Modes provide different types of *autopilot-assisted flight*, and *fully autonomous flight*.
|
||||
Flight Modes provide different types of _autopilot-assisted flight_, and _fully autonomous flight_.
|
||||
You can set any (or none) of the flight modes [available to your vehicle](../flight_modes/index.md#flight-modes).
|
||||
|
||||
Most users should set the following modes and functions, as these make the vehicle easier and safer to fly:
|
||||
@@ -33,26 +33,25 @@ You can also separately specify channels for mapping a kill switch, return to la
|
||||
|
||||
To configure single-channel flight mode selection:
|
||||
|
||||
1. Start *QGroundControl* and connect the vehicle.
|
||||
1. Start _QGroundControl_ and connect the vehicle.
|
||||
1. Turn on your RC transmitter.
|
||||
1. Select **"Q" icon > Vehicle Setup > Flight Modes** (sidebar) to open _Flight Modes Setup_.
|
||||
|
||||

|
||||
|
||||
1. Specify *Flight Mode Settings*:
|
||||
* Select the **Mode channel** (above this shown as Channel 5, but this will depend on your transmitter configuration).
|
||||
* Move the transmitter switch (or switches) that you have set up for mode selection through the available positions.
|
||||
The mode slot matching your current switch position will be highlighted (above this is *Flight Mode 1*).
|
||||
1. Specify _Flight Mode Settings_:
|
||||
- Select the **Mode channel** (above this shown as Channel 5, but this will depend on your transmitter configuration).
|
||||
- Move the transmitter switch (or switches) that you have set up for mode selection through the available positions.
|
||||
The mode slot matching your current switch position will be highlighted (above this is _Flight Mode 1_).
|
||||
::: info
|
||||
While you can set flight modes in any of the 6 slots, only the channels that are mapped to switch positions will be highlighted/used.
|
||||
:::
|
||||
* Select the flight mode that you want triggered for each switch position.
|
||||
1. Specify *Switch Settings*:
|
||||
* Select the channels that you want to map to specific actions - e.g.: *Return* mode, *Kill switch*, *offboard* mode, etc. (if you have spare switches and channels on your transmitter).
|
||||
|
||||
- Select the flight mode that you want triggered for each switch position.
|
||||
1. Specify _Switch Settings_:
|
||||
- Select the channels that you want to map to specific actions - e.g.: _Return_ mode, _Kill switch_, _offboard_ mode, etc. (if you have spare switches and channels on your transmitter).
|
||||
1. Test that the modes are mapped to the right transmitter switches:
|
||||
* Check the *Channel Monitor* to confirm that the expected channel is changed by each switch.
|
||||
* Select each mode switch on your transmitter in turn, and check that the desired flight mode is activated (the text turns yellow on *QGroundControl* for the active mode).
|
||||
- Check the _Channel Monitor_ to confirm that the expected channel is changed by each switch.
|
||||
- Select each mode switch on your transmitter in turn, and check that the desired flight mode is activated (the text turns yellow on _QGroundControl_ for the active mode).
|
||||
|
||||
All values are automatically saved as they are changed.
|
||||
|
||||
@@ -61,7 +60,6 @@ All values are automatically saved as they are changed.
|
||||
This section contains a small number of possible setup configurations for taranis.
|
||||
QGroundControl _may_ have [setup information for other transmitters here](https://docs.qgroundcontrol.com/master/en/qgc-user-guide/setup_view/flight_modes.html#transmitter-setup).
|
||||
|
||||
|
||||
<a id="taranis_setup"></a>
|
||||
|
||||
### Taranis Setup: 3-way Switch Configuration for Single-Channel Mode
|
||||
@@ -70,7 +68,7 @@ If you only need to support selecting between two or three modes then you can ma
|
||||
Below we show how to map the Taranis 3-way "SD" switch to channel 5.
|
||||
|
||||
::: info
|
||||
This example shows how to set up the popular *FrSky Taranis* transmitter.
|
||||
This example shows how to set up the popular _FrSky Taranis_ transmitter.
|
||||
Transmitter setup will be different on other transmitters.
|
||||
:::
|
||||
|
||||
@@ -78,15 +76,14 @@ Open the Taranis UI **MIXER** page and scroll down to **CH5**, as shown below:
|
||||
|
||||

|
||||
|
||||
Press **ENT(ER)** to edit the **CH5** configuration then change the **Source** to be the *SD* button.
|
||||
Press **ENT(ER)** to edit the **CH5** configuration then change the **Source** to be the _SD_ button.
|
||||
|
||||

|
||||
|
||||
That's it!
|
||||
Channel 5 will now output 3 different PWM values for the three different **SD** switch positions.
|
||||
|
||||
The *QGroundControl* configuration is then as described in the previous section.
|
||||
|
||||
The _QGroundControl_ configuration is then as described in the previous section.
|
||||
|
||||
### Taranis Setup: Multi-Switch Configuration for Single-Channel Mode
|
||||
|
||||
@@ -96,19 +93,18 @@ Commonly this is done by encoding the positions of a 2- and a 3-position switch
|
||||
On the FrSky Taranis this process involves assigning a "logical switch" to each combination of positions of the two real switches.
|
||||
Each logical switch is then assigned to a different PWM value on the same channel.
|
||||
|
||||
The video below shows how this is done with the *FrSky Taranis* transmitter.
|
||||
The video below shows how this is done with the _FrSky Taranis_ transmitter.
|
||||
|
||||
<!-- [youtube](https://youtu.be/scqO7vbH2jo) Video has gone private and is no longer available -->
|
||||
<!-- @[youtube](https://youtu.be/BNzeVGD8IZI?t=427) - video showing how to set the QGC side - at about 7mins and 3 secs -->
|
||||
|
||||
<lite-youtube videoid="TFEjEQZqdVA" title="Taranis Mode Switches"/>
|
||||
|
||||
The *QGroundControl* configuration is then [as described above](#flight-mode-selection).
|
||||
|
||||
The _QGroundControl_ configuration is then [as described above](#flight-mode-selection).
|
||||
|
||||
## Further Information
|
||||
|
||||
* [Flight Modes Overview](../flight_modes/index.md)
|
||||
* [QGroundControl > Flight Modes](https://docs.qgroundcontrol.com/master/en/qgc-user-guide/setup_view/flight_modes.html#px4-pro-flight-mode-setup)
|
||||
* [PX4 Setup Video - @6m53s](https://youtu.be/91VGmdSlbo4?t=6m53s) (Youtube)
|
||||
* [Radio switch parameters](../advanced_config/parameter_reference.md#radio-switches) - Can be used to set mappings via parameters
|
||||
- [Flight Modes Overview](../flight_modes/index.md)
|
||||
- [QGroundControl > Flight Modes](https://docs.qgroundcontrol.com/master/en/qgc-user-guide/setup_view/flight_modes.html#px4-pro-flight-mode-setup)
|
||||
- [PX4 Setup Video - @6m53s](https://youtu.be/91VGmdSlbo4?t=6m53s) (Youtube)
|
||||
- [Radio switch parameters](../advanced_config/parameter_reference.md#radio-switches) - Can be used to set mappings via parameters
|
||||
|
||||
@@ -18,7 +18,6 @@ To level the horizon:
|
||||
You should already have set the [Autopilot Orientation](../config/flight_controller_orientation.md). If not, you can also set it here.
|
||||
:::
|
||||
1. Place the vehicle in its level flight orientation on a level surface:
|
||||
|
||||
- For planes this is the position during level flight (planes tend to have their wings slightly pitched up!)
|
||||
- For copters this is the hover position.
|
||||
|
||||
|
||||
+33
-18
@@ -128,10 +128,10 @@ Additional (and underlying) parameter settings are shown below.
|
||||
|
||||
| Parameter | Setting | Description |
|
||||
| ----------------------------------------------------------------------------------------------------- | --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| <a id="COM_RC_LOSS_T"></a>[COM_RC_LOSS_T](../advanced_config/parameter_reference.md#COM_RC_LOSS_T) | Manual Control Loss Timeout | Time after last setpoint received from the selected manual control source after which manual control is considered lost. This must be kept short because the vehicle will continue to fly using the last known stick position until the timeout triggers. |
|
||||
| <a id="COM_RC_LOSS_T"></a>[COM_RC_LOSS_T](../advanced_config/parameter_reference.md#COM_RC_LOSS_T) | Manual Control Loss Timeout | Time after last setpoint received from the selected manual control source after which manual control is considered lost. This must be kept short because the vehicle will continue to fly using the last known stick position until the timeout triggers. |
|
||||
| <a id="COM_FAIL_ACT_T"></a>[COM_FAIL_ACT_T](../advanced_config/parameter_reference.md#COM_FAIL_ACT_T) | Failsafe Reaction Delay | Delay in seconds between failsafe condition being triggered (`COM_RC_LOSS_T`) and failsafe action (RTL, Land, Hold). In this state the vehicle waits in hold mode for the manual control source to reconnect. This might be set longer for long-range flights so that intermittent connection loss doesn't immediately invoke the failsafe. It can be to zero so that the failsafe triggers immediately. |
|
||||
| <a id="NAV_RCL_ACT"></a>[NAV_RCL_ACT](../advanced_config/parameter_reference.md#NAV_RCL_ACT) | Failsafe Action | Disabled, Loiter, Return, Land, Disarm, Terminate. |
|
||||
| <a id="COM_RCL_EXCEPT"></a>[COM_RCL_EXCEPT](../advanced_config/parameter_reference.md#COM_RCL_EXCEPT) | RC Loss Exceptions | Set modes in which manual control loss is ignored. |
|
||||
| <a id="COM_RCL_EXCEPT"></a>[COM_RCL_EXCEPT](../advanced_config/parameter_reference.md#COM_RCL_EXCEPT) | RC Loss Exceptions | Set modes in which manual control loss is ignored. |
|
||||
|
||||
## Data Link Loss Failsafe
|
||||
|
||||
@@ -142,11 +142,11 @@ Users that want to disable this failsafe in specific modes can do so using the p
|
||||
|
||||
The settings and underlying parameters are shown below.
|
||||
|
||||
| Setting | Parameter | Description |
|
||||
| ---------------------- | ------------------------------------------------------------------------ | --------------------------------------------------------------------------------- |
|
||||
| Data Link Loss Timeout | [COM_DL_LOSS_T](../advanced_config/parameter_reference.md#COM_DL_LOSS_T) | Amount of time after losing the data connection before the failsafe will trigger. |
|
||||
| Failsafe Action | [NAV_DLL_ACT](../advanced_config/parameter_reference.md#NAV_DLL_ACT) | Disabled, Hold mode, Return mode, Land mode, Disarm, Terminate. |
|
||||
| <a id="COM_DLL_EXCEPT"></a>Mode exceptions for DLL failsafe | [COM_DLL_EXCEPT](../advanced_config/parameter_reference.md#COM_DLL_EXCEPT) | Set modes in which data link loss is ignored. |
|
||||
| Setting | Parameter | Description |
|
||||
| ----------------------------------------------------------- | -------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
|
||||
| Data Link Loss Timeout | [COM_DL_LOSS_T](../advanced_config/parameter_reference.md#COM_DL_LOSS_T) | Amount of time after losing the data connection before the failsafe will trigger. |
|
||||
| Failsafe Action | [NAV_DLL_ACT](../advanced_config/parameter_reference.md#NAV_DLL_ACT) | Disabled, Hold mode, Return mode, Land mode, Disarm, Terminate. |
|
||||
| <a id="COM_DLL_EXCEPT"></a>Mode exceptions for DLL failsafe | [COM_DLL_EXCEPT](../advanced_config/parameter_reference.md#COM_DLL_EXCEPT) | Set modes in which data link loss is ignored. |
|
||||
|
||||
## Geofence Failsafe
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ These are covered in the following topics:
|
||||
- [Safe Points (Rally)](../flying/plan_safety_points.md)
|
||||
- [Prearm/Arm/Disarm Configuration](../advanced_config/prearm_arm_disarm.md)
|
||||
- [Flight Termination Configuration](../advanced_config/flight_termination.md)
|
||||
- [First Flight Guidelines](../flying/first_flight_guidelines.md)
|
||||
- [First Flight Guidelines](../flying/first_flight_guidelines.md)
|
||||
|
||||
::: tip
|
||||
Note that the [First Flight Guidelines](../flying/first_flight_guidelines.md) are listed _last_.
|
||||
|
||||
@@ -42,14 +42,12 @@ To setup and configure a helicopter:
|
||||

|
||||
|
||||
The motors have no configurable geometry:
|
||||
|
||||
- `Rotor (Motor 1)`: The main rotor
|
||||
- `Yaw tail motor (Motor 2)`: The tail rotor
|
||||
|
||||
Swash plate servos: `3` | `4` <!-- 4 provides additional stability -->
|
||||
|
||||
For each servo set:
|
||||
|
||||
- `Angle`: Clockwise angle in degree on the swash plate circle at which the servo arm is attached starting from `0` pointing forwards.
|
||||
Example for a typical setup where three servos are controlling the swash plate equally distributed over the circle (360° / 3 =) 120° apart each which results in the angles:
|
||||
|
||||
@@ -65,7 +63,6 @@ To setup and configure a helicopter:
|
||||
- `Trim`: Offset individual servo positions. This is only needed in rare case when the swash plate is not level even though all servos are centered.
|
||||
|
||||
Additional settings:
|
||||
|
||||
- `Yaw compensation scale based on collective pitch`: How much yaw is feed forward compensated based on the current collective pitch.
|
||||
- `Main rotor turns counter-clockwise`: `Disabled` (clockwise rotation) | `Enabled`
|
||||
- `Throttle spoolup time`: Set value (in seconds) greater than the achievable minimum motor spool up time.
|
||||
@@ -73,12 +70,10 @@ To setup and configure a helicopter:
|
||||
|
||||
1. Remove the rotor blades and propellers
|
||||
1. Assign motors and servos to outputs and test (also in [Actuator configuration](../config/actuators.md)):
|
||||
|
||||
1. Assign the [motors and servos to the outputs](../config/actuators.md#actuator-outputs).
|
||||
1. Power the vehicle with a battery and use the [actuator testing sliders](../config/actuators.md#actuator-testing) to validate correct servo and motor assignment and direction.
|
||||
|
||||
1. Using an RC in [Acro mode](../flight_modes_mc/acro.md), verify the correct movement of the swash-plate. With most airframes you need to see the following:
|
||||
|
||||
- Moving the roll stick to the right should tilt the swash-plate to the right.
|
||||
- Moving the pitch stick forward should tilt the swash-plate forward.
|
||||
|
||||
@@ -144,7 +139,6 @@ The rate controller should be tuned in [Acro mode](../flight_modes_mc/acro.md),
|
||||
|
||||
3. Then enable the PID gains.
|
||||
Start off with following values:
|
||||
|
||||
- [MC_ROLLRATE_P](../advanced_config/parameter_reference.md#MC_ROLLRATE_P), [MC_PITCHRATE_P](../advanced_config/parameter_reference.md#MC_PITCHRATE_P) a quarter of the value you found to work well as the corresponding feed forward value in the previous step. `P = FF / 4`
|
||||
|
||||
```sh
|
||||
|
||||
@@ -123,14 +123,12 @@ Tuning is the final step, carried out only after most other setup and configurat
|
||||
::: info
|
||||
Automatic tuning works on frames that have reasonable authority and dynamics around all the body axes.
|
||||
It has primarily been tested on racing quads and X500, and is expected to be less effective on tricopters with a tiltable rotor.
|
||||
|
||||
|
||||
Manual tuning using these guides are only needed if there is a problem with autotune:
|
||||
|
||||
- [MC PID Tuning (Manual/Basic)](../config_mc/pid_tuning_guide_multicopter_basic.md) — Manual tuning basic how to.
|
||||
- [MC PID Tuning Guide (Manual/Detailed)](../config_mc/pid_tuning_guide_multicopter.md) — Manual tuning with detailed explanation.
|
||||
|
||||
:::
|
||||
|
||||
:::
|
||||
|
||||
- [MC Filter/Control Latency Tuning](../config_mc/filter_tuning.md) — Trade off control latency and noise filtering.
|
||||
- [MC Setpoint Tuning (Trajectory Generator)](../config_mc/mc_trajectory_tuning.md)
|
||||
|
||||
@@ -46,7 +46,6 @@ Then adjust the sliders (as discussed below) to improve the tracking of the resp
|
||||
These need to be set low, but such that the **motors never stop** when the vehicle is armed.
|
||||
|
||||
This can be tested in [Acro mode](../flight_modes_mc/acro.md) or in [Stabilized mode](../flight_modes_mc/manual_stabilized.md):
|
||||
|
||||
- Remove propellers
|
||||
- Arm the vehicle and lower the throttle to the minimum
|
||||
- Tilt the vehicle to all directions, about 60 degrees
|
||||
@@ -77,7 +76,6 @@ The tuning procedure is:
|
||||
As a result, the optimal tuning at hover thrust may not be ideal when the vehicle is operating at higher thrust.
|
||||
|
||||
The thrust curve value can be used to compensate for this non-linearity:
|
||||
|
||||
- For PWM controllers, 0.3 is a good default (which may benefit from [further tuning](../config_mc/pid_tuning_guide_multicopter.md#thrust-curve)).
|
||||
- For RPM-based controllers, use 1 (no further tuning is required as these have a quadratic thrust curve).
|
||||
|
||||
@@ -120,7 +118,6 @@ The tuning procedure is:
|
||||
:::
|
||||
1. Repeat the tuning process for the attitude controller on all the axes.
|
||||
1. Repeat the tuning process for the velocity and positions controllers (on all the axes).
|
||||
|
||||
- Use Position mode when tuning these controllers
|
||||
- Select the **Simple position control** option in the _Position control mode ..._ selector (this allows direct control for the generation of step inputs)
|
||||
|
||||
|
||||
@@ -18,27 +18,37 @@ A drive mode will only work properly if all the configuration for the preceding
|
||||
|
||||
## Flashing the Rover Build
|
||||
|
||||
Rovers use a custom build that must be flashed onto your flight controller instead of the default PX4 build:
|
||||
Rover is built as a [firmware variant](../dev_setup/building_px4.md#px4-make-build-targets), and must be installed as "Custom Firmware" in QGC (other vehicles are present in the default variant).
|
||||
|
||||
1. First build the rover firmware for your flight controller from the `main` branch (there is no release build, so you can't just select this build from QGroundControl).
|
||||
The release versions of Rover firmware for different boards are attached to the associated GitHub release tag.
|
||||
For example, you can find `px4_fmu-v5x_rover.px4` on [PX4-Autopilot/releases/tag/v1.16.1](https://github.com/PX4/PX4-Autopilot/releases/tag/v1.16.1).
|
||||
For the `main` branch version of Rover you will need to [build the firmware](#building-rover).
|
||||
|
||||
To build for rover with the `make` command, replace the `_default` suffix with `_rover`.
|
||||
For example, to build rover for px4_fmu-v6x boards, you would use the command:
|
||||
Load the firmware onto your flight controller as "Custom Firmware" (see [Loading Firmware > Installing PX4 Main, Beta or Custom Firmware](../config/firmware.md#installing-px4-main-beta-or-custom-firmware)).
|
||||
|
||||
```sh
|
||||
make px4_fmu-v6x_rover
|
||||
```
|
||||
## Building Rover
|
||||
|
||||
::: info
|
||||
You can also enable the modules in default builds by adding these lines to your [board configuration](../hardware/porting_guide_config.md) (e.g. for fmu-v6x you might add them to [`main/boards/px4/fmu-v6x/default.px4board`](https://github.com/PX4/PX4-Autopilot/blob/main/boards/px4/fmu-v6x/default.px4board)):
|
||||
Rover is built as the `rover` [firmware variant](../dev_setup/building_px4.md#px4-make-build-targets).
|
||||
What this means is that when building the firmware with the `make` command, you replace the `_default` suffix in the configuration target with `_rover`.
|
||||
|
||||
```sh
|
||||
CONFIG_MODULES_ROVER_ACKERMANN=y
|
||||
CONFIG_MODULES_ROVER_DIFFERENTIAL=y
|
||||
CONFIG_MODULES_ROVER_MECANUM=y
|
||||
```
|
||||
For example, to build rover for `px4_fmu-v6x` boards, you would use the following command:
|
||||
|
||||
Note that adding the rover modules may lead to flash overflow, in which case you will need to disable modules that you do not plan to use (such as those related to multicopter or fixed wing).
|
||||
:::
|
||||
```sh
|
||||
make px4_fmu-v6x_rover
|
||||
```
|
||||
|
||||
2. Load the **custom firmware** that you just built onto your flight controller (see [Loading Firmware > Installing PX4 Main, Beta or Custom Firmware](../config/firmware.md#installing-px4-main-beta-or-custom-firmware)).
|
||||
Note that configuration targets are constructed with the format "VENDOR_MODEL_VARIANT".
|
||||
|
||||
The built firmware can be installed as custom firmware, as shown above in in [Flashing the Rover Build](#flashing-the-rover-build).
|
||||
|
||||
::: info
|
||||
You can also enable the modules in default builds by adding these lines to your [board configuration](../hardware/porting_guide_config.md) (e.g. for fmu-v6x you might add them to [`main/boards/px4/fmu-v6x/default.px4board`](https://github.com/PX4/PX4-Autopilot/blob/main/boards/px4/fmu-v6x/default.px4board)):
|
||||
|
||||
```sh
|
||||
CONFIG_MODULES_ROVER_ACKERMANN=y
|
||||
CONFIG_MODULES_ROVER_DIFFERENTIAL=y
|
||||
CONFIG_MODULES_ROVER_MECANUM=y
|
||||
```
|
||||
|
||||
Adding the rover modules may lead to flash overflow, in which case you will need to disable modules that you do not plan to use (such as those related to multicopter or fixed wing).
|
||||
:::
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user