mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-06-10 00:10:04 +08:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0087ea1ee8 |
@@ -141,15 +141,20 @@ Checks: '*,
|
||||
-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,
|
||||
-readability-convert-member-functions-to-static,
|
||||
-readability-make-member-function-const,
|
||||
-bugprone-assignment-in-if-condition,
|
||||
-bugprone-implicit-widening-of-multiplication-result,
|
||||
-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,
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
---
|
||||
name: commit
|
||||
description: Create a conventional commit for PX4 changes
|
||||
disable-model-invocation: true
|
||||
argument-hint: "[optional: description of changes]"
|
||||
allowed-tools: Bash, Read, Glob, Grep
|
||||
---
|
||||
|
||||
# PX4 Conventional Commit
|
||||
|
||||
Create a git commit: `type(scope): description`
|
||||
|
||||
**NEVER add Co-Authored-By lines. No Claude attribution in commits.**
|
||||
|
||||
Follow [CONTRIBUTING.md](../../CONTRIBUTING.md) for full project conventions.
|
||||
|
||||
## Steps
|
||||
|
||||
1. **Read [CONTRIBUTING.md](../../CONTRIBUTING.md)** for commit message format, types, scopes, and conventions.
|
||||
2. Check branch (`git branch --show-current`). If on `main`, create a feature branch. Use `<username>/<description>` format where `<username>` comes from `gh api user --jq .login`. If unavailable, just use `<description>`.
|
||||
3. Run `git status` and `git diff --staged`. If nothing staged, ask what to stage.
|
||||
4. Follow the commit message convention from CONTRIBUTING.md: pick the correct **type** and **scope**, write a concise imperative description.
|
||||
5. Body (if needed): explain **why**, not what.
|
||||
6. Run `make format` or `./Tools/astyle/fix_code_style.sh <file>` on changed C/C++ files before committing.
|
||||
7. Check if GPG signing is available: `git config --get user.signingkey`. If set, use `git commit -S -s`. Otherwise, use `git commit -s`.
|
||||
8. Stage and commit. No `Co-Authored-By`.
|
||||
|
||||
If the user provided arguments, use them as context: $ARGUMENTS
|
||||
@@ -1,24 +0,0 @@
|
||||
---
|
||||
name: pr
|
||||
description: Create a pull request with conventional commit title and description
|
||||
disable-model-invocation: true
|
||||
argument-hint: "[optional: target branch or description]"
|
||||
allowed-tools: Bash, Read, Glob, Grep
|
||||
---
|
||||
|
||||
# PX4 Pull Request
|
||||
|
||||
**No Claude attribution anywhere (no Co-Authored-By, no "Generated with Claude").**
|
||||
|
||||
Follow [CONTRIBUTING.md](../../CONTRIBUTING.md) for full project conventions.
|
||||
|
||||
## Steps
|
||||
|
||||
1. Check branch. If on `main`, create a feature branch. Use `<username>/<description>` format where `<username>` comes from `gh api user --jq .login`. If unavailable, just use `<description>`.
|
||||
2. Gather context: `git status`, `git log --oneline main..HEAD`, `git diff main...HEAD --stat`, check if remote tracking branch exists.
|
||||
3. PR **title**: `type(scope): description` — under 72 chars, describes the overall change across all commits. This becomes the squash-merge commit message.
|
||||
4. PR **body**: brief summary + bullet points for key changes. No filler.
|
||||
5. Push with `-u` if needed, then `gh pr create`. Default base is `main` unless user says otherwise.
|
||||
6. Return the PR URL.
|
||||
|
||||
If the user provided arguments, use them as context: $ARGUMENTS
|
||||
@@ -1,73 +0,0 @@
|
||||
---
|
||||
name: rebase-onto-main
|
||||
description: Rebase a branch onto main, handling squash-merged parent branches cleanly
|
||||
argument-hint: "[optional: branch name, defaults to current branch]"
|
||||
allowed-tools: Bash, Read, Glob, Grep, Agent
|
||||
---
|
||||
|
||||
# Rebase Branch onto Main
|
||||
|
||||
Rebase the current (or specified) branch onto `main`, correctly handling the case where the branch was built on top of another branch that has since been squash-merged into `main`.
|
||||
|
||||
## Background
|
||||
|
||||
When a parent branch is squash-merged, its individual commits become a single new commit on `main` with a different hash. A normal `git rebase main` will try to replay the parent's original commits, causing messy conflicts. The fix is to **cherry-pick only the commits unique to this branch** onto a fresh branch from `main`.
|
||||
|
||||
## Steps
|
||||
|
||||
1. **Identify the branch.** Use `$ARGUMENTS` if provided, otherwise use the current branch.
|
||||
|
||||
2. **Fetch and update main:**
|
||||
```
|
||||
git fetch origin main:main
|
||||
```
|
||||
|
||||
3. **Find the merge base** between the branch and `main`:
|
||||
```
|
||||
git merge-base <branch> main
|
||||
```
|
||||
|
||||
4. **List all commits** on the branch since the merge base:
|
||||
```
|
||||
git log --oneline <merge-base>..<branch>
|
||||
```
|
||||
|
||||
5. **Identify which commits are unique to this branch** vs. inherited from a parent branch. Look for:
|
||||
- Squash-merged commits on `main` that correspond to a group of commits at the bottom of the branch's history (check PR titles, commit message keywords).
|
||||
- The boundary commit: the first commit that belongs to *this* branch's work, not the parent's.
|
||||
- If ALL commits are unique (no parent branch), just do a normal `git rebase main` and skip the rest.
|
||||
|
||||
6. **Create a fresh branch from `main`:**
|
||||
```
|
||||
git checkout -b <branch>-rebase main
|
||||
```
|
||||
|
||||
7. **Cherry-pick only the unique commits** (oldest first):
|
||||
```
|
||||
git cherry-pick <first-unique-commit>^..<branch>
|
||||
```
|
||||
The `A^..B` range means "from the parent of A through B inclusive."
|
||||
|
||||
8. **Handle conflicts** if any arise during cherry-pick. Resolve and `git cherry-pick --continue`.
|
||||
|
||||
9. **Replace the old branch:**
|
||||
```
|
||||
git branch -m <branch> <branch>-old
|
||||
git branch -m <branch>-rebase <branch>
|
||||
```
|
||||
|
||||
10. **Verify** the result:
|
||||
```
|
||||
git log --oneline main..<branch>
|
||||
```
|
||||
Confirm only the expected commits are present.
|
||||
|
||||
11. **Ask the user** before force-pushing. When approved:
|
||||
```
|
||||
git push origin <branch> --force-with-lease
|
||||
```
|
||||
|
||||
12. **Clean up** the old branch:
|
||||
```
|
||||
git branch -D <branch>-old
|
||||
```
|
||||
@@ -265,7 +265,5 @@ jobs:
|
||||
with:
|
||||
draft: true
|
||||
prerelease: ${{ steps.upload-location.outputs.is_prerelease == 'true' }}
|
||||
files: |
|
||||
artifacts/*.px4
|
||||
artifacts/*.deb
|
||||
files: artifacts/*.px4
|
||||
name: ${{ steps.upload-location.outputs.uploadlocation }}
|
||||
|
||||
@@ -1,148 +0,0 @@
|
||||
name: Commit Quality
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, edited, synchronize, reopened]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
issues: write
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||
IS_FORK: ${{ github.event.pull_request.head.repo.full_name != github.repository }}
|
||||
|
||||
jobs:
|
||||
pr-title:
|
||||
name: PR Title
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
sparse-checkout: Tools/ci
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Check PR title
|
||||
id: check
|
||||
run: |
|
||||
python3 Tools/ci/check_pr_title.py "${{ github.event.pull_request.title }}" --markdown-file comment.md && rc=0 || rc=$?
|
||||
echo "exit_code=$rc" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Post or clear comment
|
||||
if: env.IS_FORK == 'false'
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
if [ "${{ steps.check.outputs.exit_code }}" != "0" ]; then
|
||||
python3 Tools/ci/pr_comment.py --marker pr-title --pr "$PR_NUMBER" --result fail < comment.md
|
||||
else
|
||||
python3 Tools/ci/pr_comment.py --marker pr-title --pr "$PR_NUMBER" --result pass
|
||||
fi
|
||||
|
||||
- name: Result
|
||||
if: steps.check.outputs.exit_code != '0'
|
||||
run: |
|
||||
echo "::error::PR title does not follow conventional commits format. See the PR comment for details."
|
||||
exit 1
|
||||
|
||||
commit-messages:
|
||||
name: Commit Messages
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
sparse-checkout: Tools/ci
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Check commit messages
|
||||
id: check
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
gh api \
|
||||
"repos/${{ github.repository }}/pulls/${PR_NUMBER}/commits?per_page=100" \
|
||||
| python3 Tools/ci/check_commit_messages.py --markdown-file comment.md && rc=0 || rc=$?
|
||||
echo "exit_code=$rc" >> "$GITHUB_OUTPUT"
|
||||
# Check for warnings (non-empty markdown on exit 0)
|
||||
if [ "$rc" -eq 0 ] && [ -s comment.md ]; then
|
||||
echo "has_warnings=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "has_warnings=false" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
- name: Post or clear comment
|
||||
if: env.IS_FORK == 'false'
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
if [ "${{ steps.check.outputs.exit_code }}" != "0" ]; then
|
||||
python3 Tools/ci/pr_comment.py --marker commit-msgs --pr "$PR_NUMBER" --result fail < comment.md
|
||||
elif [ "${{ steps.check.outputs.has_warnings }}" == "true" ]; then
|
||||
python3 Tools/ci/pr_comment.py --marker commit-msgs --pr "$PR_NUMBER" --result warn < comment.md
|
||||
else
|
||||
python3 Tools/ci/pr_comment.py --marker commit-msgs --pr "$PR_NUMBER" --result pass
|
||||
fi
|
||||
|
||||
- name: Result
|
||||
if: steps.check.outputs.exit_code != '0'
|
||||
run: |
|
||||
echo "::error::Commit message errors found. See the PR comment for details."
|
||||
exit 1
|
||||
|
||||
pr-body:
|
||||
name: PR Description
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
if: env.IS_FORK == 'false'
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
sparse-checkout: Tools/ci
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Check PR body
|
||||
id: check
|
||||
env:
|
||||
PR_BODY: ${{ github.event.pull_request.body }}
|
||||
run: |
|
||||
message=""
|
||||
if [ -z "$PR_BODY" ]; then
|
||||
message="PR description is empty. Please add a summary of the changes."
|
||||
echo "::warning::PR description is empty."
|
||||
else
|
||||
cleaned=$(echo "$PR_BODY" | sed 's/<!--.*-->//g' | tr -d '[:space:]')
|
||||
if [ -z "$cleaned" ]; then
|
||||
message="PR description contains only template comments. Please fill in the details."
|
||||
echo "::warning::PR description contains only template comments."
|
||||
fi
|
||||
fi
|
||||
echo "message=$message" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Post or clear comment
|
||||
if: env.IS_FORK == 'false'
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
if [ -n "${{ steps.check.outputs.message }}" ]; then
|
||||
printf '%s\n' \
|
||||
"## PR Description (advisory)" \
|
||||
"" \
|
||||
"This is **not blocking**, but your PR description appears to be empty or incomplete." \
|
||||
"" \
|
||||
"${{ steps.check.outputs.message }}" \
|
||||
"" \
|
||||
"A good PR description helps reviewers understand what changed and why." \
|
||||
"" \
|
||||
"---" \
|
||||
"*This comment will be automatically removed once the issue is resolved.*" \
|
||||
| python3 Tools/ci/pr_comment.py --marker pr-body --pr "$PR_NUMBER" --result warn
|
||||
else
|
||||
python3 Tools/ci/pr_comment.py --marker pr-body --pr "$PR_NUMBER" --result pass
|
||||
fi
|
||||
@@ -130,8 +130,8 @@ jobs:
|
||||
load: false
|
||||
push: ${{ startsWith(github.ref, 'refs/tags/') || (github.event_name == 'workflow_dispatch' && github.event.inputs.deploy_to_registry) }}
|
||||
provenance: false
|
||||
cache-from: type=gha,scope=${{ matrix.arch }}
|
||||
cache-to: type=gha,mode=max,scope=${{ matrix.arch }}
|
||||
cache-from: type=gha,version=1,scope=${{ matrix.arch }}
|
||||
cache-to: type=gha,version=1,mode=max,scope=${{ matrix.arch }}
|
||||
|
||||
deploy:
|
||||
name: Deploy To Registry
|
||||
|
||||
@@ -34,13 +34,13 @@ jobs:
|
||||
upload_sources: false
|
||||
upload_translations: false
|
||||
download_translations: true
|
||||
commit_message: 'docs(i18n): PX4 guide translations (Crowdin) - ${{ matrix.lc }}'
|
||||
commit_message: New Crowdin translations - ${{ matrix.lc }}
|
||||
localization_branch_name: l10n_crowdin_docs_translations_${{ matrix.lc }}
|
||||
crowdin_branch_name: main
|
||||
create_pull_request: true
|
||||
pull_request_base_branch_name: 'main'
|
||||
pull_request_title: 'docs(i18n): PX4 guide translations (Crowdin) - ${{ matrix.lc }}'
|
||||
pull_request_body: 'docs(i18n): PX4 guide Crowdin translations by [Crowdin GH Action](https://github.com/crowdin/github-action) for ${{ matrix.lc }}'
|
||||
pull_request_title: New PX4 guide translations (Crowdin) - ${{ matrix.lc }}
|
||||
pull_request_body: 'New PX4 guide Crowdin translations by [Crowdin GH Action](https://github.com/crowdin/github-action) for ${{ matrix.lc }}'
|
||||
pull_request_labels: 'Documentation 📑'
|
||||
pull_request_reviewers: hamishwillee
|
||||
download_language: ${{ matrix.lc }}
|
||||
|
||||
@@ -89,15 +89,7 @@ jobs:
|
||||
. /opt/ros/galactic/setup.bash
|
||||
mkdir -p /opt/px4_ws/src
|
||||
cd /opt/px4_ws/src
|
||||
BRANCH="${GITHUB_HEAD_REF:-$GITHUB_REF_NAME}"
|
||||
REPO_URL="https://github.com/Auterion/px4-ros2-interface-lib.git"
|
||||
if git ls-remote --heads "$REPO_URL" "$BRANCH" | grep -q "$BRANCH"; then
|
||||
echo "Cloning px4-ros2-interface-lib with matching branch: $BRANCH"
|
||||
git clone --recursive --branch "$BRANCH" "$REPO_URL"
|
||||
else
|
||||
echo "Branch '$BRANCH' not found in px4-ros2-interface-lib, using default (main)"
|
||||
git clone --recursive "$REPO_URL"
|
||||
fi
|
||||
git clone --recursive https://github.com/Auterion/px4-ros2-interface-lib.git
|
||||
# Ignore python packages due to compilation issue (can be enabled when updating ROS)
|
||||
touch px4-ros2-interface-lib/px4_ros2_py/COLCON_IGNORE || true
|
||||
touch px4-ros2-interface-lib/examples/python/COLCON_IGNORE || true
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
name: Sync release branch to px4-ros2-interface-lib
|
||||
|
||||
on:
|
||||
create:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
branch:
|
||||
description: 'Release branch name (e.g. release/1.18)'
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
notify-interface-lib:
|
||||
if: >-
|
||||
github.repository == 'PX4/PX4-Autopilot' &&
|
||||
(
|
||||
(github.event_name == 'create' && github.ref_type == 'branch' && startsWith(github.ref_name, 'release/')) ||
|
||||
github.event_name == 'workflow_dispatch'
|
||||
)
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Determine branch name
|
||||
id: params
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
||||
BRANCH="${{ inputs.branch }}"
|
||||
else
|
||||
BRANCH="${{ github.ref_name }}"
|
||||
fi
|
||||
echo "branch=$BRANCH" >> "$GITHUB_OUTPUT"
|
||||
echo "Dispatching for branch: $BRANCH"
|
||||
|
||||
- name: Dispatch release branch creation
|
||||
run: |
|
||||
BRANCH="${{ steps.params.outputs.branch }}"
|
||||
curl -s -f -X POST \
|
||||
-H "Authorization: token ${{ secrets.PX4BUILTBOT_PERSONAL_ACCESS_TOKEN }}" \
|
||||
-H "Accept: application/vnd.github.v3+json" \
|
||||
https://api.github.com/repos/Auterion/px4-ros2-interface-lib/dispatches \
|
||||
-d "{\"event_type\":\"px4_release_branch\",\"client_payload\":{\"branch\":\"$BRANCH\"}}"
|
||||
echo "Dispatched px4_release_branch event for $BRANCH"
|
||||
Vendored
-5
@@ -336,11 +336,6 @@ CONFIG:
|
||||
buildType: MinSizeRel
|
||||
settings:
|
||||
CONFIG: cuav_x25-evo_default
|
||||
cuav_x25-super_default:
|
||||
short: cuav_x25-super
|
||||
buildType: MinSizeRel
|
||||
settings:
|
||||
CONFIG: cuav_x25-super_default
|
||||
cubepilot_cubeorange_test:
|
||||
short: cubepilot_cubeorange
|
||||
buildType: MinSizeRel
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
cff-version: 1.2.0
|
||||
title: "PX4 Autopilot"
|
||||
message: "If you use PX4 in your research, please cite it using this metadata."
|
||||
type: software
|
||||
authors:
|
||||
- family-names: Meier
|
||||
given-names: Lorenz
|
||||
- name: "The PX4 Contributors"
|
||||
repository-code: "https://github.com/PX4/PX4-Autopilot"
|
||||
url: "https://px4.io"
|
||||
abstract: >-
|
||||
PX4 is an open-source autopilot stack for drones and
|
||||
unmanned vehicles. It supports multirotors, fixed-wing,
|
||||
VTOL, rovers, and many more platforms. PX4 runs on both
|
||||
RTOS and POSIX-compatible operating systems.
|
||||
keywords:
|
||||
- autopilot
|
||||
- drone
|
||||
- uav
|
||||
- flight-controller
|
||||
- robotics
|
||||
- ros2
|
||||
license: BSD-3-Clause
|
||||
identifiers:
|
||||
- type: doi
|
||||
value: "10.5281/zenodo.595432"
|
||||
description: "Zenodo concept DOI (resolves to latest version)"
|
||||
+21
-147
@@ -1,170 +1,44 @@
|
||||
# Contributing to PX4-Autopilot
|
||||
# Contributing to PX4 Firmware
|
||||
|
||||
We follow the [GitHub flow](https://guides.github.com/introduction/flow/) development model.
|
||||
We follow the [Github flow](https://guides.github.com/introduction/flow/) development model.
|
||||
|
||||
## Fork the project, then clone your repo
|
||||
### Fork the project, then clone your repo
|
||||
|
||||
First [fork and clone](https://help.github.com/articles/fork-a-repo) the project.
|
||||
First [fork and clone](https://help.github.com/articles/fork-a-repo) the project project.
|
||||
|
||||
## Create a feature branch
|
||||
### Create a feature branch
|
||||
|
||||
Always branch off `main` for new features.
|
||||
*Always* branch off main for new features.
|
||||
|
||||
```
|
||||
git checkout -b mydescriptivebranchname
|
||||
```
|
||||
|
||||
## Edit and build the code
|
||||
### Edit and build the code
|
||||
|
||||
The [developer guide](https://docs.px4.io/main/en/development/development.html) explains how to set up the development environment on Mac OS, Linux or Windows.
|
||||
The [developer guide](https://docs.px4.io/main/en/development/development.html) explains how to set up the development environment on Mac OS, Linux or Windows. Please take note of our [coding style](https://docs.px4.io/main/en/contribute/code.html) when editing files.
|
||||
|
||||
### Coding standards
|
||||
### Commit your changes
|
||||
|
||||
All C/C++ code must follow the [PX4 coding style](https://docs.px4.io/main/en/contribute/code.html). Formatting is enforced by [astyle](http://astyle.sourceforge.net/) in CI (`make check_format`). Code quality checks run via [clang-tidy](https://clang.llvm.org/extra/clang-tidy/). Pull requests that fail either check will not be merged.
|
||||
Always write descriptive commit messages and add a fixes or relates note to them with an [issue number](https://github.com/px4/Firmware/issues) (Github will link these then conveniently)
|
||||
|
||||
Python code is checked with [mypy](https://mypy-lang.org/) and [flake8](https://flake8.pycqa.org/).
|
||||
|
||||
## Commit message convention
|
||||
|
||||
PX4 uses [conventional commits](https://www.conventionalcommits.org/) for all commit messages and PR titles.
|
||||
|
||||
### Format
|
||||
**Example:**
|
||||
|
||||
```
|
||||
type(scope): short description of the change
|
||||
Change how the attitude controller works
|
||||
|
||||
- Fixes rate feed forward
|
||||
- Allows a local body rate override
|
||||
|
||||
Fixes issue #123
|
||||
```
|
||||
|
||||
| Part | Rule |
|
||||
|------|------|
|
||||
| **type** | Category of change (see types table below) |
|
||||
| **scope** | The module, driver, board, or area of PX4 affected |
|
||||
| **`!`** (optional) | Append before `:` to mark a breaking change |
|
||||
| **description** | What the change does, at least 5 characters, written in imperative form |
|
||||
### Test your changes
|
||||
|
||||
### Types
|
||||
Since we care about safety, we will regularly ask you for test results. Best is to do a test flight (or bench test where it applies) and upload the logfile from it (on the microSD card in the logs directory) to Google Drive or Dropbox and share the link.
|
||||
|
||||
| Type | Description |
|
||||
|------|-------------|
|
||||
| `feat` | A new feature |
|
||||
| `fix` | A bug fix |
|
||||
| `docs` | Documentation only changes |
|
||||
| `style` | Formatting, whitespace, no code change |
|
||||
| `refactor` | Code change that neither fixes a bug nor adds a feature |
|
||||
| `perf` | Performance improvement |
|
||||
| `test` | Adding or correcting tests |
|
||||
| `build` | Build system or external dependencies |
|
||||
| `ci` | CI configuration files and scripts |
|
||||
| `chore` | Other changes that don't modify src or test files |
|
||||
| `revert` | Reverts a previous commit |
|
||||
### Push your changes
|
||||
|
||||
### Scopes
|
||||
|
||||
The scope identifies which part of PX4 is affected. Common scopes:
|
||||
|
||||
| Scope | Area |
|
||||
|-------|------|
|
||||
| `ekf2` | Extended Kalman Filter (state estimation) |
|
||||
| `mavlink` | MAVLink messaging protocol |
|
||||
| `commander` | Commander and mode management |
|
||||
| `navigator` | Mission, RTL, Land, and other navigation modes |
|
||||
| `sensors` | Sensor drivers and processing |
|
||||
| `drivers` | Hardware drivers |
|
||||
| `boards/px4_fmu-v6x` | Board-specific changes (use the board name) |
|
||||
| `mc_att_control` | Multicopter attitude control |
|
||||
| `mc_pos_control` | Multicopter position control |
|
||||
| `fw_att_control` | Fixed-wing attitude control |
|
||||
| `vtol` | VTOL-specific logic |
|
||||
| `actuators` | Mixer and actuator output |
|
||||
| `battery` | Battery monitoring and estimation |
|
||||
| `logger` | On-board logging |
|
||||
| `param` | Parameter system |
|
||||
| `simulation` | SITL, Gazebo, SIH |
|
||||
| `ci` | Continuous integration and workflows |
|
||||
| `docs` | Documentation |
|
||||
| `build` | CMake, toolchain, build system |
|
||||
| `uorb` | Inter-module messaging |
|
||||
|
||||
For changes spanning multiple subsystems, use the primary one affected. Look at the directory path of the files you changed to find the right scope: `src/modules/ekf2/` uses `ekf2`, `src/drivers/imu/` uses `drivers/imu`, `.github/workflows/` uses `ci`.
|
||||
|
||||
### Breaking changes
|
||||
|
||||
Append `!` before the colon to indicate a breaking change:
|
||||
|
||||
```
|
||||
feat(ekf2)!: remove deprecated height fusion API
|
||||
```
|
||||
|
||||
### Good commit messages
|
||||
|
||||
```
|
||||
feat(ekf2): add height fusion timeout
|
||||
fix(mavlink): correct BATTERY_STATUS_V2 parsing
|
||||
refactor(navigator): simplify RTL altitude logic
|
||||
ci(workflows): migrate to reusable workflows
|
||||
docs(ekf2): update tuning guide
|
||||
feat(boards/px4_fmu-v6x)!: remove deprecated driver API
|
||||
perf(mc_rate_control): reduce loop latency
|
||||
```
|
||||
|
||||
### Commits to avoid
|
||||
|
||||
These will be flagged by CI and should be squashed or reworded before merging:
|
||||
|
||||
```
|
||||
fix # too vague, no type or scope
|
||||
update # too vague, no type or scope
|
||||
ekf2: fix something # missing type prefix
|
||||
apply suggestions from code review # squash into parent commit
|
||||
do make format # squash into parent commit
|
||||
WIP: trying something # not ready for main
|
||||
oops # not descriptive
|
||||
```
|
||||
|
||||
### PR titles
|
||||
|
||||
The PR title follows the same `type(scope): description` format. This is enforced by CI and is especially important because the PR title becomes the commit message when a PR is squash-merged.
|
||||
|
||||
### Merge policy
|
||||
|
||||
Commits should be atomic and independently revertable. Squash at reviewer discretion for obvious cases (multiple WIP commits, messy review-response history). When your commits are clean and logical, they will be preserved as individual commits on `main`.
|
||||
|
||||
### Cleaning up commits
|
||||
|
||||
If CI flags your commit messages, you can fix them with an interactive rebase:
|
||||
|
||||
```bash
|
||||
# Squash all commits into one:
|
||||
git rebase -i HEAD~N # replace N with the number of commits
|
||||
# mark all commits except the first as 'squash' or 'fixup'
|
||||
# reword the remaining commit to follow the format
|
||||
git push --force-with-lease
|
||||
|
||||
# Or reword specific commits:
|
||||
git rebase -i HEAD~N
|
||||
# mark the bad commits as 'reword'
|
||||
git push --force-with-lease
|
||||
```
|
||||
|
||||
## Test your changes
|
||||
|
||||
PX4 is safety-critical software. All contributions must include adequate testing where practical:
|
||||
|
||||
- **New features** must include unit tests and/or integration tests that exercise the new functionality, where practical. Hardware-dependent changes that cannot be tested in SITL should include bench test or flight test evidence.
|
||||
- **Bug fixes** must include a regression test where practical. When automated testing is not feasible (hardware-specific issues, race conditions, etc.), provide a link to a flight log demonstrating the fix and the reproduction steps for the original bug.
|
||||
- **Reviewers** will verify that tests or test evidence exist before approving a pull request.
|
||||
|
||||
### Types of tests
|
||||
|
||||
| Test type | When to use | How to run |
|
||||
|-----------|-------------|------------|
|
||||
| **Unit tests** (gtest) | Module-level logic, math, parsing | `make tests` |
|
||||
| **SITL integration tests** (MAVSDK) | Flight behavior, failsafes, missions | `test/mavsdk_tests/` |
|
||||
| **Bench tests / flight logs** | Hardware-dependent changes | Upload logs to [Flight Review](https://logs.px4.io) |
|
||||
|
||||
Since we care about safety, we will regularly ask you for test results. Best is to do a test flight (or bench test where it applies) and upload the log file from it (on the microSD card in the logs directory) to Google Drive or Dropbox and share the link.
|
||||
|
||||
## Push your changes
|
||||
|
||||
Push changes to your repo and send a [pull request](https://github.com/PX4/PX4-Autopilot/compare/).
|
||||
Push changes to your repo and send a [pull request](https://github.com/PX4/Firmware/compare/).
|
||||
|
||||
Make sure to provide some testing feedback and if possible the link to a flight log file. Upload flight log files to [Flight Review](http://logs.px4.io) and link the resulting report.
|
||||
|
||||
@@ -226,22 +226,9 @@ CONFIG_TARGETS_DEFAULT := $(patsubst %_default,%,$(filter %_default,$(ALL_CONFIG
|
||||
$(CONFIG_TARGETS_DEFAULT):
|
||||
@$(call cmake-build,$@_default$(BUILD_DIR_SUFFIX))
|
||||
|
||||
# Multi-processor boards: build all processor targets together
|
||||
# VOXL2 apps processor (default) depends on SLPI DSP being built first
|
||||
modalai_voxl2_default: modalai_voxl2_slpi
|
||||
modalai_voxl2: modalai_voxl2_slpi
|
||||
modalai_voxl2_deb: modalai_voxl2_slpi
|
||||
|
||||
all_config_targets: $(ALL_CONFIG_TARGETS)
|
||||
all_default_targets: $(CONFIG_TARGETS_DEFAULT)
|
||||
|
||||
# DEB package targets: builds _default config, then runs cpack.
|
||||
# Multi-processor boards (e.g. VOXL2) chain companion builds automatically
|
||||
# via existing cmake prerequisites.
|
||||
%_deb:
|
||||
@$(call cmake-build,$(subst _deb,_default,$@)$(BUILD_DIR_SUFFIX))
|
||||
@cd "$(SRC_DIR)/build/$(subst _deb,_default,$@)" && cpack -G DEB
|
||||
|
||||
updateconfig:
|
||||
@./Tools/kconfig/updateconfig.py
|
||||
|
||||
@@ -345,7 +332,6 @@ bootloaders_update: \
|
||||
cuav_7-nano_bootloader \
|
||||
cuav_fmu-v6x_bootloader \
|
||||
cuav_x25-evo_bootloader \
|
||||
cuav_x25-super_bootloader \
|
||||
cubepilot_cubeorange_bootloader \
|
||||
cubepilot_cubeorangeplus_bootloader \
|
||||
hkust_nxt-dual_bootloader \
|
||||
@@ -548,8 +534,7 @@ validate_module_configs:
|
||||
-not -path "$(SRC_DIR)/src/modules/zenoh/zenoh-pico/*" \
|
||||
-not -path "$(SRC_DIR)/src/lib/events/libevents/*" \
|
||||
-not -path "$(SRC_DIR)/src/lib/cdrstream/*" \
|
||||
-not -path "$(SRC_DIR)/src/lib/crypto/libtommath/*" \
|
||||
-not -path "$(SRC_DIR)/src/lib/tensorflow_lite_micro/*" -print0 | \
|
||||
-not -path "$(SRC_DIR)/src/lib/crypto/libtommath/*" -print0 | \
|
||||
xargs -0 "$(SRC_DIR)"/Tools/validate_yaml.py --schema-file "$(SRC_DIR)"/validation/module_schema.yaml
|
||||
|
||||
# Cleanup
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
|
||||
<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://www.bestpractices.dev/projects/6520"><img src="https://www.bestpractices.dev/projects/6520/badge" alt="OpenSSF Best Practices"></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>
|
||||
|
||||
@@ -34,7 +34,6 @@ param set-default PWM_MAIN_FUNC2 102
|
||||
param set-default PWM_MAIN_FUNC3 103
|
||||
param set-default PWM_MAIN_FUNC4 104
|
||||
|
||||
param set-default SENS_GPS0_DELAY 0
|
||||
param set-default SENS_GPS1_DELAY 0
|
||||
param set-default EKF2_GPS_DELAY 0
|
||||
|
||||
param set SIH_VEHICLE_TYPE 0
|
||||
|
||||
@@ -44,8 +44,7 @@ param set-default PWM_MAIN_FUNC2 202
|
||||
param set-default PWM_MAIN_FUNC3 203
|
||||
param set-default PWM_MAIN_FUNC4 101
|
||||
|
||||
param set-default SENS_GPS0_DELAY 0
|
||||
param set-default SENS_GPS1_DELAY 0
|
||||
param set-default EKF2_GPS_DELAY 0
|
||||
|
||||
# Rate controllers
|
||||
param set-default FW_RR_P 0.0500
|
||||
|
||||
@@ -11,8 +11,7 @@
|
||||
PX4_SIMULATOR=${PX4_SIMULATOR:=sihsim}
|
||||
PX4_SIM_MODEL=${PX4_SIM_MODEL:=xvert}
|
||||
|
||||
param set-default SENS_GPS0_DELAY 0
|
||||
param set-default SENS_GPS1_DELAY 0
|
||||
param set-default EKF2_GPS_DELAY 0
|
||||
param set-default EKF2_FUSE_BETA 0 # side slip fusion is currently not supported for tailsitters
|
||||
|
||||
param set-default SENS_EN_GPSSIM 1
|
||||
|
||||
@@ -27,8 +27,7 @@ param set-default SENS_EN_BAROSIM 1
|
||||
param set-default SENS_EN_MAGSIM 1
|
||||
param set-default SENS_EN_ARSPDSIM 1
|
||||
|
||||
param set-default SENS_GPS0_DELAY 0
|
||||
param set-default SENS_GPS1_DELAY 0
|
||||
param set-default EKF2_GPS_DELAY 0
|
||||
|
||||
param set-default VT_TYPE 2
|
||||
param set-default MPC_MAN_Y_MAX 60
|
||||
|
||||
@@ -44,5 +44,4 @@ param set-default PWM_MAIN_FUNC4 104
|
||||
param set-default PWM_MAIN_FUNC5 105
|
||||
param set-default PWM_MAIN_FUNC6 106
|
||||
|
||||
param set-default SENS_GPS0_DELAY 0
|
||||
param set-default SENS_GPS1_DELAY 0
|
||||
param set-default EKF2_GPS_DELAY 0
|
||||
|
||||
@@ -44,6 +44,8 @@ param set-default FW_T_SINK_MIN 3
|
||||
|
||||
param set-default FW_W_EN 1
|
||||
|
||||
param set-default FD_ESCS_EN 0
|
||||
|
||||
param set-default MIS_TAKEOFF_ALT 30
|
||||
|
||||
param set-default NAV_ACC_RAD 15
|
||||
|
||||
@@ -104,3 +104,4 @@ 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
|
||||
|
||||
@@ -20,8 +20,8 @@ param set-default COM_DISARM_LAND 0.5
|
||||
# EKF2 parameters
|
||||
param set-default EKF2_DRAG_CTRL 1
|
||||
param set-default EKF2_IMU_POS_X 0.02
|
||||
param set-default SENS_GPS0_OFFX 0.055
|
||||
param set-default SENS_GPS0_OFFZ -0.15
|
||||
param set-default EKF2_GPS_POS_X 0.055
|
||||
param set-default EKF2_GPS_POS_Z -0.15
|
||||
param set-default EKF2_MIN_RNG 0.03
|
||||
param set-default EKF2_OF_CTRL 1
|
||||
param set-default EKF2_OF_POS_X 0.055
|
||||
|
||||
@@ -26,6 +26,7 @@ param set-default SENS_EN_GPSSIM 1
|
||||
param set-default SENS_EN_BAROSIM 1
|
||||
param set-default SENS_EN_MAGSIM 1
|
||||
param set-default COM_ARM_CHK_ESCS 0 # We don't have ESCs
|
||||
param set-default FD_ESCS_EN 0 # We don't have ESCs - but maybe we need this later?
|
||||
|
||||
# Set proper failsafes
|
||||
param set-default COM_ACT_FAIL_ACT 0
|
||||
|
||||
@@ -28,6 +28,7 @@ param set-default SIM_GZ_EN 1
|
||||
|
||||
param set-default SENS_EN_MAGSIM 1
|
||||
param set-default COM_ARM_CHK_ESCS 0 # We don't have ESCs
|
||||
param set-default FD_ESCS_EN 0
|
||||
|
||||
param set-default CA_AIRFRAME 14
|
||||
param set-default MAV_TYPE 45
|
||||
|
||||
@@ -28,6 +28,7 @@ param set-default SIM_GZ_EN 1
|
||||
|
||||
param set-default SENS_EN_MAGSIM 1
|
||||
param set-default COM_ARM_CHK_ESCS 0 # We don't have ESCs
|
||||
param set-default FD_ESCS_EN 0
|
||||
|
||||
param set-default CA_AIRFRAME 14
|
||||
param set-default MAV_TYPE 45
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
# shellcheck disable=SC2154
|
||||
|
||||
# EKF2 specifics
|
||||
param set-default SENS_GPS0_DELAY 10
|
||||
param set-default SENS_GPS1_DELAY 10
|
||||
param set-default EKF2_GPS_DELAY 10
|
||||
param set-default EKF2_MULTI_IMU 3
|
||||
param set-default SENS_IMU_MODE 0
|
||||
|
||||
|
||||
@@ -119,11 +119,10 @@ else
|
||||
param set SYS_AUTOCONFIG 1
|
||||
fi
|
||||
|
||||
# To trigger a parameter reset during boot SYS_AUTOCONFIG was set to 1 before
|
||||
if param greater SYS_AUTOCONFIG 0
|
||||
if param compare SYS_AUTOCONFIG 1
|
||||
then
|
||||
# Reset parameters except airframe, parameter version, sensor calibration, total flight time, flight UUID
|
||||
param reset_all SYS_AUTOSTART SYS_PARAM_VER CAL_* LND_FLIGHT* TC_* COM_FLIGHT*
|
||||
# Reset params except Airframe, RC calibration, sensor calibration, flight modes, total flight time, and next flight UUID.
|
||||
param reset_all SYS_AUTOSTART RC* CAL_* COM_FLTMODE* LND_FLIGHT* TC_* COM_FLIGHT*
|
||||
set AUTOCNF yes
|
||||
fi
|
||||
|
||||
|
||||
@@ -19,8 +19,8 @@ param set-default COM_DISARM_LAND 0.5
|
||||
# EKF2 parameters
|
||||
param set-default EKF2_DRAG_CTRL 1
|
||||
param set-default EKF2_IMU_POS_X 0.02
|
||||
param set-default SENS_GPS0_OFFX 0.055
|
||||
param set-default SENS_GPS0_OFFZ -0.15
|
||||
param set-default EKF2_GPS_POS_X 0.055
|
||||
param set-default EKF2_GPS_POS_Z -0.15
|
||||
param set-default EKF2_MIN_RNG 0.03
|
||||
param set-default EKF2_OF_CTRL 1
|
||||
param set-default EKF2_OF_POS_X 0.055
|
||||
|
||||
@@ -19,8 +19,8 @@ param set-default COM_DISARM_LAND 0.5
|
||||
# EKF2 parameters
|
||||
param set-default EKF2_DRAG_CTRL 1
|
||||
param set-default EKF2_IMU_POS_X 0.02
|
||||
param set-default SENS_GPS0_OFFX 0.055
|
||||
param set-default SENS_GPS0_OFFZ -0.15
|
||||
param set-default EKF2_GPS_POS_X 0.055
|
||||
param set-default EKF2_GPS_POS_Z -0.15
|
||||
param set-default EKF2_MIN_RNG 0.03
|
||||
param set-default EKF2_OF_CTRL 1
|
||||
param set-default EKF2_OF_POS_X 0.055
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#
|
||||
# @name HolyBro QAV250
|
||||
#
|
||||
# @url https://docs.px4.io/main/en/frames_multicopter/holybro_qav250_pixhawk4_mini
|
||||
# @url https://docs.px4.io/main/en/frames_multicopter/holybro_qav250_pixhawk4_mini.html
|
||||
#
|
||||
# @type Quadrotor x
|
||||
# @class Copter
|
||||
|
||||
@@ -47,9 +47,8 @@ param set-default EKF2_BCOEF_Y 25.5
|
||||
|
||||
param set-default EKF2_DRAG_CTRL 1
|
||||
|
||||
param set-default SENS_GPS0_DELAY 100
|
||||
param set-default SENS_GPS1_DELAY 100
|
||||
param set-default SENS_GPS0_OFFX 0.06
|
||||
param set-default EKF2_GPS_DELAY 100
|
||||
param set-default EKF2_GPS_POS_X 0.06
|
||||
param set-default EKF2_GPS_V_NOISE 0.5
|
||||
|
||||
param set-default EKF2_IMU_POS_X 0.06
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#
|
||||
# @name Aion Robotics R1 UGV
|
||||
#
|
||||
# @url https://docs.px4.io/main/en/complete_vehicles_rover/aion_r1
|
||||
# @url https://docs.px4.io/main/en/complete_vehicles_rover/aion_r1.html
|
||||
#
|
||||
# @type Rover
|
||||
# @class Rover
|
||||
|
||||
@@ -238,7 +238,7 @@ then
|
||||
fi
|
||||
|
||||
# Start TMP102 temperature sensor
|
||||
if param compare -s SENS_EN_TMP102 1
|
||||
if param compare SENS_EN_TMP102 1
|
||||
then
|
||||
tmp102 start -X
|
||||
fi
|
||||
|
||||
@@ -188,11 +188,11 @@ else
|
||||
netman update -i eth0
|
||||
fi
|
||||
|
||||
# To trigger a parameter reset during boot SYS_AUTOCONFIG was set to 1 before
|
||||
# To trigger a parameter reset during boot SYS_AUTCONFIG was set to 1 before
|
||||
if param greater SYS_AUTOCONFIG 0
|
||||
then
|
||||
# Reset parameters except airframe, parameter version, sensor calibration, total flight time, flight UUID
|
||||
param reset_all SYS_AUTOSTART SYS_PARAM_VER CAL_* LND_FLIGHT* TC_* COM_FLIGHT*
|
||||
# Reset parameters except airframe, parameter version, RC calibration, sensor calibration, flight modes, total flight time, flight UUID
|
||||
param reset_all SYS_AUTOSTART SYS_PARAM_VER RC* CAL_* COM_FLTMODE* LND_FLIGHT* TC_* COM_FLIGHT*
|
||||
fi
|
||||
|
||||
#
|
||||
@@ -633,15 +633,12 @@ else
|
||||
#
|
||||
# Start the VTX services.
|
||||
#
|
||||
if ! param compare VTX_SER_CFG 0
|
||||
set RC_VTXTABLE ${R}etc/init.d/rc.vtxtable
|
||||
if [ -f ${RC_VTXTABLE} ]
|
||||
then
|
||||
set RC_VTXTABLE ${R}etc/init.d/rc.vtxtable
|
||||
if [ -f ${RC_VTXTABLE} ]
|
||||
then
|
||||
. ${RC_VTXTABLE}
|
||||
fi
|
||||
unset RC_VTXTABLE
|
||||
. ${RC_VTXTABLE}
|
||||
fi
|
||||
unset RC_VTXTABLE
|
||||
|
||||
#
|
||||
# Set additional parameters and env variables for selected AUTOSTART.
|
||||
|
||||
+12
-28
@@ -2,40 +2,24 @@
|
||||
|
||||
## Supported Versions
|
||||
|
||||
The following versions receive security updates:
|
||||
The following is a list of versions the development team is currently supporting.
|
||||
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| 1.16.x | :white_check_mark: |
|
||||
| < 1.16 | :x: |
|
||||
| 1.4.x | :white_check_mark: |
|
||||
| 1.3.3 | :white_check_mark: |
|
||||
| < 1.3 | :x: |
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
We receive security vulnerability reports through GitHub Security Advisories.
|
||||
We currently only receive security vulnerability reports through GitHub.
|
||||
|
||||
To begin a report, go to the [PX4/PX4-Autopilot](https://github.com/PX4/PX4-Autopilot) repository
|
||||
and click on the **Security** tab. If you are on mobile, click the **...** dropdown menu, then click **Security**.
|
||||
To begin a report, please go to the top-level repository, for example, PX4/PX4-Autopilot,
|
||||
and click on the Security tab. If you are on mobile, click the ... dropdown menu, and then click Security.
|
||||
|
||||
Click **Report a Vulnerability** to open the advisory form. Fill in the advisory details form.
|
||||
Make sure your title is descriptive and the description contains all relevant details needed
|
||||
to verify the issue. We welcome logs, screenshots, photos, and videos.
|
||||
Click Report a Vulnerability to open the advisory form. Fill in the advisory details form.
|
||||
Make sure your title is descriptive, and the development team can find all of the relevant details needed
|
||||
to verify on the description box. We recommend you add as much data as possible. We welcome logs,
|
||||
screenshots, photos, and videos, anything that can help us verify and identify the issues being reported.
|
||||
|
||||
At the bottom of the form, click **Submit report**.
|
||||
|
||||
## Response Process
|
||||
|
||||
1. **Acknowledgment**: The maintainer team will acknowledge your report within **7 days**.
|
||||
2. **Triage**: We will assess severity and impact and communicate next steps.
|
||||
3. **Disclosure**: We coordinate disclosure with the reporter. We follow responsible disclosure practices and will credit reporters in the advisory unless they request anonymity.
|
||||
|
||||
If you do not receive acknowledgment within 7 days, please follow up by emailing the [release managers](MAINTAINERS.md).
|
||||
|
||||
## Secure Development Practices
|
||||
|
||||
The PX4 development team applies the following practices to reduce security risk:
|
||||
|
||||
- **Code review**: All changes require peer review before merging.
|
||||
- **Static analysis**: [clang-tidy](https://clang.llvm.org/extra/clang-tidy/) runs on every pull request with warnings treated as errors.
|
||||
- **Fuzzing**: A daily fuzzing pipeline using [Google fuzztest](https://github.com/google/fuzztest) tests MAVLink message handling and GNSS driver protocol parsing.
|
||||
- **Input validation**: All external inputs (MAVLink messages, RC signals, sensor data) are validated against expected ranges before use.
|
||||
- **Compiler hardening**: Builds use `-Wall -Werror`, stack protectors, and other hardening flags where supported by the target platform.
|
||||
At the bottom of the form, click Submit report. The maintainer team will be notified and will get back to you ASAP.
|
||||
|
||||
@@ -1,331 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Validate commit messages in a PR against conventional commits format.
|
||||
|
||||
Reads a JSON array of GitHub commit objects from stdin (as returned by the
|
||||
GitHub API's /pulls/{n}/commits endpoint) and checks each message for
|
||||
blocking errors and advisory warnings.
|
||||
|
||||
With --markdown, outputs a formatted PR comment body instead of plain text.
|
||||
"""
|
||||
|
||||
import json
|
||||
import sys
|
||||
|
||||
from conventional_commits import (
|
||||
EXEMPT_PREFIXES,
|
||||
parse_header,
|
||||
)
|
||||
|
||||
# Blocking: prefixes that indicate unsquashed fixup commits
|
||||
FIXUP_PREFIXES = ('fixup!', 'squash!', 'amend!')
|
||||
|
||||
# Blocking: single-word throwaway messages (case-insensitive exact match)
|
||||
THROWAWAY_WORDS = frozenset({
|
||||
'fix', 'fixed', 'fixes',
|
||||
'update', 'updated', 'updates',
|
||||
'test', 'tests', 'testing',
|
||||
'tmp', 'temp',
|
||||
'oops', 'wip',
|
||||
'debug', 'cleanup',
|
||||
})
|
||||
|
||||
# Blocking: debug session leftovers
|
||||
DEBUG_KEYWORDS = ('tmate',)
|
||||
|
||||
# Warning: review-response messages (case-insensitive substring match)
|
||||
REVIEW_RESPONSE_PATTERNS = (
|
||||
'address review',
|
||||
'apply suggestions from code review',
|
||||
'code review',
|
||||
)
|
||||
|
||||
# Warning: formatter-only commits
|
||||
FORMATTER_PATTERNS = (
|
||||
'do make format',
|
||||
'make format',
|
||||
'run formatter',
|
||||
'apply format',
|
||||
)
|
||||
|
||||
MIN_MESSAGE_LENGTH = 5
|
||||
|
||||
|
||||
def check_commit(message: str) -> tuple[list[str], list[str]]:
|
||||
"""Return (errors, warnings) for a single commit message."""
|
||||
errors: list[str] = []
|
||||
warnings: list[str] = []
|
||||
|
||||
first_line = message.split('\n', 1)[0].strip()
|
||||
lower = first_line.lower()
|
||||
|
||||
# --- Blocking checks ---
|
||||
|
||||
for prefix in FIXUP_PREFIXES:
|
||||
if lower.startswith(prefix):
|
||||
errors.append(f'Unsquashed commit: starts with "{prefix}"')
|
||||
|
||||
if lower == 'wip' or lower.startswith('wip ') or lower.startswith('wip:'):
|
||||
errors.append('WIP commit should not be merged')
|
||||
|
||||
if len(first_line) < MIN_MESSAGE_LENGTH:
|
||||
errors.append(f'Message too short ({len(first_line)} chars, minimum {MIN_MESSAGE_LENGTH})')
|
||||
|
||||
if first_line.strip() and first_line.strip().lower() in THROWAWAY_WORDS:
|
||||
errors.append(f'Single-word throwaway message: "{first_line.strip()}"')
|
||||
|
||||
for kw in DEBUG_KEYWORDS:
|
||||
if kw in lower:
|
||||
errors.append(f'Debug session leftover: contains "{kw}"')
|
||||
|
||||
# --- Warning checks ---
|
||||
|
||||
for pattern in REVIEW_RESPONSE_PATTERNS:
|
||||
if pattern in lower:
|
||||
warnings.append('Review-response commit')
|
||||
break
|
||||
|
||||
for pattern in FORMATTER_PATTERNS:
|
||||
if pattern in lower:
|
||||
warnings.append('Formatter-only commit')
|
||||
break
|
||||
|
||||
if not parse_header(first_line):
|
||||
# Exempt merge commits
|
||||
for prefix in EXEMPT_PREFIXES:
|
||||
if first_line.startswith(prefix):
|
||||
break
|
||||
else:
|
||||
warnings.append(
|
||||
'Missing conventional commit format '
|
||||
'(e.g. "feat(ekf2): add something")'
|
||||
)
|
||||
|
||||
return errors, warnings
|
||||
|
||||
|
||||
def suggest_commit(message: str) -> str | None:
|
||||
"""Suggest how to fix a bad commit message."""
|
||||
first_line = message.split('\n', 1)[0].strip()
|
||||
lower = first_line.lower()
|
||||
|
||||
for prefix in FIXUP_PREFIXES:
|
||||
if lower.startswith(prefix):
|
||||
return 'Squash this into the commit it fixes'
|
||||
|
||||
if lower == 'wip' or lower.startswith('wip ') or lower.startswith('wip:'):
|
||||
return 'Reword with a descriptive message (e.g. "feat(scope): what changed")'
|
||||
|
||||
if len(first_line) < MIN_MESSAGE_LENGTH:
|
||||
return 'Reword with a descriptive message (e.g. "feat(ekf2): what changed")'
|
||||
|
||||
if first_line.strip().lower() in THROWAWAY_WORDS:
|
||||
return 'Reword with a descriptive message (e.g. "fix(scope): what changed")'
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def format_plain(data: list) -> tuple[bool, bool]:
|
||||
"""Print plain text output. Returns (has_blocking, has_warnings)."""
|
||||
has_blocking = False
|
||||
has_warnings = False
|
||||
|
||||
for commit in data:
|
||||
sha = commit.get('sha', '?')[:10]
|
||||
message = commit.get('commit', {}).get('message', '')
|
||||
first_line = message.split('\n', 1)[0].strip()
|
||||
|
||||
errors, warnings = check_commit(message)
|
||||
|
||||
if errors or warnings:
|
||||
print(f"\n {sha} {first_line}")
|
||||
|
||||
for err in errors:
|
||||
print(f" ERROR: {err}")
|
||||
has_blocking = True
|
||||
|
||||
for warn in warnings:
|
||||
print(f" WARNING: {warn}")
|
||||
has_warnings = True
|
||||
|
||||
if has_blocking:
|
||||
print(
|
||||
"\n"
|
||||
"ERROR = must fix before merging (CI will block the PR)\n"
|
||||
"WARNING = advisory, not blocking, but recommended to fix\n"
|
||||
"\n"
|
||||
"See the contributing guide for details:\n"
|
||||
" https://github.com/PX4/PX4-Autopilot/blob/main/CONTRIBUTING.md#commit-message-convention\n",
|
||||
)
|
||||
|
||||
elif has_warnings:
|
||||
print(
|
||||
"\n"
|
||||
"WARNING = advisory, not blocking, but recommended to fix\n"
|
||||
"\n"
|
||||
"See the contributing guide for details:\n"
|
||||
" https://github.com/PX4/PX4-Autopilot/blob/main/CONTRIBUTING.md#commit-message-convention\n",
|
||||
)
|
||||
|
||||
return has_blocking, has_warnings
|
||||
|
||||
|
||||
def format_markdown_blocking(data: list) -> str:
|
||||
"""Format a blocking error markdown comment."""
|
||||
error_groups: dict[str, list[str]] = {}
|
||||
unique_commits: list[tuple[str, str, list[str], str]] = []
|
||||
|
||||
for commit in data:
|
||||
sha = commit.get('sha', '?')[:10]
|
||||
message = commit.get('commit', {}).get('message', '')
|
||||
first_line = message.split('\n', 1)[0].strip()
|
||||
|
||||
errors, _ = check_commit(message)
|
||||
if not errors:
|
||||
continue
|
||||
|
||||
suggestion = suggest_commit(message) or ''
|
||||
unique_commits.append((sha, first_line, errors, suggestion))
|
||||
|
||||
for err in errors:
|
||||
error_groups.setdefault(err, []).append(sha)
|
||||
|
||||
lines = [
|
||||
"## \u274c Commit messages need attention before merging",
|
||||
"",
|
||||
]
|
||||
|
||||
has_large_group = any(len(shas) > 3 for shas in error_groups.values())
|
||||
|
||||
if has_large_group:
|
||||
lines.extend([
|
||||
"**Issues found:**",
|
||||
"",
|
||||
])
|
||||
for err_msg, shas in error_groups.items():
|
||||
if len(shas) > 3:
|
||||
lines.append(f"- **{len(shas)} commits**: {err_msg} "
|
||||
f"(`{shas[0]}`, `{shas[1]}`, ... `{shas[-1]}`)")
|
||||
else:
|
||||
sha_list = ', '.join(f'`{s}`' for s in shas)
|
||||
lines.append(f"- {err_msg}: {sha_list}")
|
||||
|
||||
distinct_messages = {msg for _, msg, _, _ in unique_commits}
|
||||
if len(distinct_messages) <= 5:
|
||||
lines.extend(["", "**Affected commits:**", ""])
|
||||
for sha, msg, errors, suggestion in unique_commits:
|
||||
safe_msg = msg.replace('|', '\\|')
|
||||
lines.append(f"- `{sha}` {safe_msg}")
|
||||
else:
|
||||
lines.extend([
|
||||
"| Commit | Message | Issue | Suggested fix |",
|
||||
"|--------|---------|-------|---------------|",
|
||||
])
|
||||
for sha, msg, errors, suggestion in unique_commits:
|
||||
issues = '; '.join(errors)
|
||||
safe_msg = msg.replace('|', '\\|')
|
||||
lines.append(f"| `{sha}` | {safe_msg} | {issues} | {suggestion} |")
|
||||
|
||||
lines.extend([
|
||||
"",
|
||||
"See [CONTRIBUTING.md](https://github.com/PX4/PX4-Autopilot/blob/main/CONTRIBUTING.md#commit-message-convention) "
|
||||
"for how to clean up commits.",
|
||||
"",
|
||||
"---",
|
||||
"*This comment will be automatically removed once the issues are resolved.*",
|
||||
])
|
||||
|
||||
return '\n'.join(lines)
|
||||
|
||||
|
||||
def format_markdown_advisory(data: list) -> str:
|
||||
"""Format an advisory warning markdown comment."""
|
||||
lines = [
|
||||
"## \U0001f4a1 Commit messages could be improved",
|
||||
"",
|
||||
"Not blocking, but these commit messages could use some cleanup.",
|
||||
"",
|
||||
"| Commit | Message | Suggestion |",
|
||||
"|--------|---------|------------|",
|
||||
]
|
||||
|
||||
for commit in data:
|
||||
sha = commit.get('sha', '?')[:10]
|
||||
message = commit.get('commit', {}).get('message', '')
|
||||
first_line = message.split('\n', 1)[0].strip()
|
||||
|
||||
_, warnings = check_commit(message)
|
||||
if not warnings:
|
||||
continue
|
||||
|
||||
suggestion = '; '.join(warnings)
|
||||
safe_msg = first_line.replace('|', '\\|')
|
||||
lines.append(f"| `{sha}` | {safe_msg} | {suggestion} |")
|
||||
|
||||
lines.extend([
|
||||
"",
|
||||
"See the [commit message convention](https://github.com/PX4/PX4-Autopilot/blob/main/CONTRIBUTING.md#commit-message-convention) "
|
||||
"for details.",
|
||||
"",
|
||||
"---",
|
||||
"*This comment will be automatically removed once the issues are resolved.*",
|
||||
])
|
||||
|
||||
return '\n'.join(lines)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
markdown_stdout = '--markdown' in sys.argv
|
||||
markdown_file = None
|
||||
for i, a in enumerate(sys.argv):
|
||||
if a == '--markdown-file' and i + 1 < len(sys.argv):
|
||||
markdown_file = sys.argv[i + 1]
|
||||
elif a.startswith('--markdown-file='):
|
||||
markdown_file = a.split('=', 1)[1]
|
||||
|
||||
try:
|
||||
data = json.load(sys.stdin)
|
||||
except json.JSONDecodeError as exc:
|
||||
print(f"Failed to parse JSON input: {exc}", file=sys.stderr)
|
||||
sys.exit(2)
|
||||
|
||||
if not isinstance(data, list):
|
||||
print("Expected a JSON array of commit objects.", file=sys.stderr)
|
||||
sys.exit(2)
|
||||
|
||||
# Always compute blocking/warning state
|
||||
has_blocking = False
|
||||
has_warnings = False
|
||||
for commit in data:
|
||||
message = commit.get('commit', {}).get('message', '')
|
||||
errors, warnings = check_commit(message)
|
||||
if errors:
|
||||
has_blocking = True
|
||||
if warnings:
|
||||
has_warnings = True
|
||||
|
||||
# Generate markdown if needed
|
||||
md = None
|
||||
if has_blocking:
|
||||
md = format_markdown_blocking(data)
|
||||
elif has_warnings:
|
||||
md = format_markdown_advisory(data)
|
||||
|
||||
if md:
|
||||
if markdown_stdout:
|
||||
print(md)
|
||||
if markdown_file:
|
||||
with open(markdown_file, 'w') as f:
|
||||
f.write(md + '\n')
|
||||
elif markdown_file:
|
||||
with open(markdown_file, 'w') as f:
|
||||
pass
|
||||
|
||||
# Plain text output to stderr for CI logs (always, unless --markdown only)
|
||||
if not markdown_stdout:
|
||||
has_blocking, _ = format_plain(data)
|
||||
|
||||
sys.exit(1 if has_blocking else 0)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1,163 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Validate that a PR title follows conventional commits format.
|
||||
|
||||
Format: type(scope): description
|
||||
|
||||
Can output plain text for CI logs or markdown for PR comments.
|
||||
"""
|
||||
|
||||
import re
|
||||
import sys
|
||||
|
||||
from conventional_commits import (
|
||||
CONVENTIONAL_TYPES,
|
||||
EXEMPT_PREFIXES,
|
||||
parse_header,
|
||||
suggest_scope,
|
||||
suggest_type,
|
||||
)
|
||||
|
||||
|
||||
def suggest_title(title: str) -> str | None:
|
||||
"""Try to suggest a corrected title in conventional commits format."""
|
||||
stripped = title.strip()
|
||||
|
||||
# Remove common bracket prefixes like [docs], [CI], etc.
|
||||
bracket_match = re.match(r'^\[([^\]]+)\]\s*(.+)', stripped)
|
||||
if bracket_match:
|
||||
prefix = bracket_match.group(1).strip().lower()
|
||||
rest = bracket_match.group(2).strip()
|
||||
rest = re.sub(r'^[\-:]\s*', '', rest).strip()
|
||||
if len(rest) >= 5:
|
||||
# Try to map bracket content to a type
|
||||
commit_type = prefix if prefix in CONVENTIONAL_TYPES else suggest_type(rest)
|
||||
scope = suggest_scope(rest)
|
||||
if scope:
|
||||
return f"{commit_type}({scope}): {rest}"
|
||||
|
||||
# Already has old-style "subsystem: description" format - convert it
|
||||
colon_match = re.match(r'^([a-zA-Z][a-zA-Z0-9_/\-\. ]*): (.+)$', stripped)
|
||||
if colon_match:
|
||||
old_subsystem = colon_match.group(1).strip()
|
||||
desc = colon_match.group(2).strip()
|
||||
if len(desc) >= 5:
|
||||
commit_type = suggest_type(desc)
|
||||
# Use the old subsystem as scope (clean it up)
|
||||
scope = old_subsystem.lower().replace(' ', '_')
|
||||
return f"{commit_type}({scope}): {desc}"
|
||||
|
||||
# No format at all - try to guess both type and scope
|
||||
commit_type = suggest_type(stripped)
|
||||
scope = suggest_scope(stripped)
|
||||
if scope:
|
||||
desc = stripped[0].lower() + stripped[1:] if stripped else stripped
|
||||
return f"{commit_type}({scope}): {desc}"
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def check_title(title: str) -> bool:
|
||||
title = title.strip()
|
||||
|
||||
if not title:
|
||||
print("PR title is empty.", file=sys.stderr)
|
||||
return False
|
||||
|
||||
for prefix in EXEMPT_PREFIXES:
|
||||
if title.startswith(prefix):
|
||||
return True
|
||||
|
||||
if parse_header(title):
|
||||
return True
|
||||
|
||||
types_str = ', '.join(f'`{t}`' for t in CONVENTIONAL_TYPES.keys())
|
||||
print(
|
||||
f"PR title does not match conventional commits format.\n"
|
||||
f"\n"
|
||||
f" Title: {title}\n"
|
||||
f"\n"
|
||||
f"Expected format: type(scope): description\n"
|
||||
f"\n"
|
||||
f"Valid types: {types_str}\n"
|
||||
f"\n"
|
||||
f"Good examples:\n"
|
||||
f" feat(ekf2): add height fusion timeout\n"
|
||||
f" fix(mavlink): correct BATTERY_STATUS_V2 parsing\n"
|
||||
f" ci(workflows): migrate to reusable workflows\n"
|
||||
f" feat(boards/px4_fmu-v6x)!: remove deprecated driver API\n"
|
||||
f"\n"
|
||||
f"Bad examples:\n"
|
||||
f" fix stuff\n"
|
||||
f" Update file\n"
|
||||
f" ekf2: fix something (missing type prefix)\n"
|
||||
f"\n"
|
||||
f"See the contributing guide for details:\n"
|
||||
f" https://github.com/PX4/PX4-Autopilot/blob/main/CONTRIBUTING.md#commit-message-convention\n",
|
||||
file=sys.stderr,
|
||||
)
|
||||
return False
|
||||
|
||||
|
||||
def format_markdown(title: str) -> str:
|
||||
"""Format a markdown PR comment body for a bad title."""
|
||||
lines = [
|
||||
"## \u274c PR title needs conventional commit format",
|
||||
"",
|
||||
"Expected format: `type(scope): description` "
|
||||
"([conventional commits](https://www.conventionalcommits.org/)).",
|
||||
"",
|
||||
"**Your title:**",
|
||||
f"> {title}",
|
||||
"",
|
||||
]
|
||||
|
||||
suggestion = suggest_title(title)
|
||||
if suggestion:
|
||||
lines.extend([
|
||||
"**Suggested fix:**",
|
||||
f"> {suggestion}",
|
||||
"",
|
||||
])
|
||||
|
||||
lines.extend([
|
||||
"**To fix this:** click the ✏️ next to the PR title at the top "
|
||||
"of this page and update it.",
|
||||
"",
|
||||
"See [CONTRIBUTING.md](https://github.com/PX4/PX4-Autopilot/blob/main/CONTRIBUTING.md#commit-message-convention) "
|
||||
"for details.",
|
||||
"",
|
||||
"---",
|
||||
"*This comment will be automatically removed once the issue is resolved.*",
|
||||
])
|
||||
|
||||
return '\n'.join(lines)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
import argparse
|
||||
parser = argparse.ArgumentParser(description='Check PR title format')
|
||||
parser.add_argument('title', help='The PR title to validate')
|
||||
parser.add_argument('--markdown', action='store_true',
|
||||
help='Output markdown to stdout on failure')
|
||||
parser.add_argument('--markdown-file', metavar='FILE',
|
||||
help='Write markdown to FILE on failure')
|
||||
args = parser.parse_args()
|
||||
|
||||
passed = check_title(args.title)
|
||||
|
||||
if not passed:
|
||||
md = format_markdown(args.title)
|
||||
if args.markdown:
|
||||
print(md)
|
||||
if args.markdown_file:
|
||||
with open(args.markdown_file, 'w') as f:
|
||||
f.write(md + '\n')
|
||||
elif args.markdown_file:
|
||||
with open(args.markdown_file, 'w') as f:
|
||||
pass
|
||||
|
||||
sys.exit(0 if passed else 1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1,146 +0,0 @@
|
||||
"""Shared constants and helpers for conventional commit validation.
|
||||
|
||||
Format: type(scope): description
|
||||
Optional breaking change marker: type(scope)!: description
|
||||
"""
|
||||
|
||||
import re
|
||||
|
||||
CONVENTIONAL_TYPES = {
|
||||
'feat': 'A new feature',
|
||||
'fix': 'A bug fix',
|
||||
'docs': 'Documentation only changes',
|
||||
'style': 'Formatting, whitespace, no code change',
|
||||
'refactor': 'Code change that neither fixes a bug nor adds a feature',
|
||||
'perf': 'Performance improvement',
|
||||
'test': 'Adding or correcting tests',
|
||||
'build': 'Build system or external dependencies',
|
||||
'ci': 'CI configuration files and scripts',
|
||||
'chore': 'Other changes that don\'t modify src or test files',
|
||||
'revert': 'Reverts a previous commit',
|
||||
}
|
||||
|
||||
# type(scope)[!]: description
|
||||
# - type: one of CONVENTIONAL_TYPES keys
|
||||
# - scope: required, alphanumeric with _/-/.
|
||||
# - !: optional breaking change marker
|
||||
# - description: at least 5 chars
|
||||
HEADER_PATTERN = re.compile(
|
||||
r'^(' + '|'.join(CONVENTIONAL_TYPES.keys()) + r')'
|
||||
r'\(([a-zA-Z0-9_/\-\.]+)\)'
|
||||
r'(!)?'
|
||||
r': (.{5,})$'
|
||||
)
|
||||
|
||||
EXEMPT_PREFIXES = ('Merge ',)
|
||||
|
||||
# Common PX4 subsystem scopes for suggestions
|
||||
KNOWN_SCOPES = [
|
||||
'ekf2', 'mavlink', 'commander', 'navigator', 'sensors',
|
||||
'mc_att_control', 'mc_pos_control', 'mc_rate_control',
|
||||
'fw_att_control', 'fw_pos_control', 'fw_rate_control',
|
||||
'vtol', 'actuators', 'battery', 'param', 'logger',
|
||||
'uorb', 'drivers', 'boards', 'simulation', 'sitl',
|
||||
'gps', 'rc', 'safety', 'can', 'serial',
|
||||
'ci', 'docs', 'build', 'cmake', 'tools',
|
||||
'mixer', 'land_detector', 'airspeed', 'gyroscope',
|
||||
'accelerometer', 'magnetometer', 'barometer',
|
||||
]
|
||||
|
||||
# Keyword patterns to suggest scopes from description text
|
||||
KEYWORD_SCOPES = [
|
||||
(r'\b(ekf|estimator|height|fusion|imu|baro)\b', 'ekf2'),
|
||||
(r'\b(mavlink|MAVLink|MAVLINK|command_int|heartbeat)\b', 'mavlink'),
|
||||
(r'\b(uorb|orb|pub|sub|topic)\b', 'uorb'),
|
||||
(r'\b(board|fmu|nuttx|stm32)\b', 'boards'),
|
||||
(r'\b(mixer|actuator|motor|servo|pwm|dshot)\b', 'actuators'),
|
||||
(r'\b(battery|power)\b', 'battery'),
|
||||
(r'\b(param|parameter)\b', 'param'),
|
||||
(r'\b(log|logger|sdlog)\b', 'logger'),
|
||||
(r'\b(sensor|accel|gyro)\b', 'sensors'),
|
||||
(r'\b(land|takeoff|rtl|mission|navigator|geofence)\b', 'navigator'),
|
||||
(r'\b(position|velocity|attitude|rate)\s*(control|ctrl)\b', 'mc_att_control'),
|
||||
(r'\b(mc|multicopter|quad)\b', 'mc_att_control'),
|
||||
(r'\b(fw|fixedwing|fixed.wing|plane)\b', 'fw_att_control'),
|
||||
(r'\b(vtol|transition)\b', 'vtol'),
|
||||
(r'\b(ci|workflow|github.action|pipeline)\b', 'ci'),
|
||||
(r'\b(doc|docs|documentation|readme)\b', 'docs'),
|
||||
(r'\b(cmake|make|toolchain|compiler)\b', 'build'),
|
||||
(r'\b(sitl|simulation|gazebo|jmavsim|sih)\b', 'simulation'),
|
||||
(r'\b(can|uavcan|cyphal|dronecan)\b', 'can'),
|
||||
(r'\b(serial|uart|spi|i2c)\b', 'serial'),
|
||||
(r'\b(safety|failsafe|arm|disarm|kill)\b', 'safety'),
|
||||
(r'\b(rc|radio|sbus|crsf|elrs|dsm)\b', 'rc'),
|
||||
(r'\b(gps|gnss|rtk|ubx)\b', 'gps'),
|
||||
(r'\b(optical.flow|flow|rangefinder|lidar|distance)\b', 'sensors'),
|
||||
(r'\b(orbit|follow|offboard)\b', 'commander'),
|
||||
(r'\b(driver)\b', 'drivers'),
|
||||
]
|
||||
|
||||
# Verb patterns to suggest conventional commit type
|
||||
VERB_TYPE_MAP = [
|
||||
(r'^fix(e[ds])?[\s:]', 'fix'),
|
||||
(r'^bug[\s:]', 'fix'),
|
||||
(r'^add(s|ed|ing)?[\s:]', 'feat'),
|
||||
(r'^implement', 'feat'),
|
||||
(r'^introduce', 'feat'),
|
||||
(r'^support', 'feat'),
|
||||
(r'^enable', 'feat'),
|
||||
(r'^update[ds]?[\s:]', 'feat'),
|
||||
(r'^improv(e[ds]?|ing)', 'perf'),
|
||||
(r'^optimi[zs](e[ds]?|ing)', 'perf'),
|
||||
(r'^refactor', 'refactor'),
|
||||
(r'^clean\s*up', 'refactor'),
|
||||
(r'^restructure', 'refactor'),
|
||||
(r'^simplif(y|ied)', 'refactor'),
|
||||
(r'^remov(e[ds]?|ing)', 'refactor'),
|
||||
(r'^delet(e[ds]?|ing)', 'refactor'),
|
||||
(r'^deprecat', 'refactor'),
|
||||
(r'^replac(e[ds]?|ing)', 'refactor'),
|
||||
(r'^renam(e[ds]?|ing)', 'refactor'),
|
||||
(r'^migrat', 'refactor'),
|
||||
(r'^revert', 'revert'),
|
||||
(r'^doc(s|ument)', 'docs'),
|
||||
(r'^test', 'test'),
|
||||
(r'^format', 'style'),
|
||||
(r'^lint', 'style'),
|
||||
(r'^whitespace', 'style'),
|
||||
(r'^build', 'build'),
|
||||
(r'^ci[\s:]', 'ci'),
|
||||
]
|
||||
|
||||
|
||||
def parse_header(text: str) -> dict | None:
|
||||
"""Parse a conventional commit header into components.
|
||||
|
||||
Returns dict with keys {type, scope, breaking, subject} or None if
|
||||
the text doesn't match conventional commits format.
|
||||
"""
|
||||
text = text.strip()
|
||||
m = HEADER_PATTERN.match(text)
|
||||
if not m:
|
||||
return None
|
||||
return {
|
||||
'type': m.group(1),
|
||||
'scope': m.group(2),
|
||||
'breaking': m.group(3) == '!',
|
||||
'subject': m.group(4),
|
||||
}
|
||||
|
||||
|
||||
def suggest_type(text: str) -> str:
|
||||
"""Infer a conventional commit type from description text."""
|
||||
lower = text.strip().lower()
|
||||
for pattern, commit_type in VERB_TYPE_MAP:
|
||||
if re.search(pattern, lower):
|
||||
return commit_type
|
||||
return 'feat'
|
||||
|
||||
|
||||
def suggest_scope(text: str) -> str | None:
|
||||
"""Infer a scope from keywords in the text."""
|
||||
lower = text.strip().lower()
|
||||
for pattern, scope in KEYWORD_SCOPES:
|
||||
if re.search(pattern, lower, re.IGNORECASE):
|
||||
return scope
|
||||
return None
|
||||
@@ -148,18 +148,18 @@ grouped_targets['base']['manufacturers'] = {}
|
||||
grouped_targets['base']['manufacturers']['px4'] = []
|
||||
grouped_targets['base']['manufacturers']['px4'] += metadata_targets
|
||||
|
||||
for manufacturer in sorted(os.scandir(os.path.join(source_dir, '../boards')), key=lambda e: e.name):
|
||||
for manufacturer in os.scandir(os.path.join(source_dir, '../boards')):
|
||||
if not manufacturer.is_dir():
|
||||
continue
|
||||
if manufacturer.name in excluded_manufacturers:
|
||||
if verbose: print(f'excluding manufacturer {manufacturer.name}')
|
||||
continue
|
||||
|
||||
for board in sorted(os.scandir(manufacturer.path), key=lambda e: e.name):
|
||||
for board in os.scandir(manufacturer.path):
|
||||
if not board.is_dir():
|
||||
continue
|
||||
|
||||
for files in sorted(os.scandir(board.path), key=lambda e: e.name):
|
||||
for files in os.scandir(board.path):
|
||||
if files.is_file() and files.name.endswith('.px4board'):
|
||||
|
||||
board_name = manufacturer.name + '_' + board.name
|
||||
@@ -189,65 +189,6 @@ for manufacturer in sorted(os.scandir(os.path.join(source_dir, '../boards')), ke
|
||||
if target is not None:
|
||||
build_configs.append(target)
|
||||
|
||||
# Remove companion targets from CI groups (parent target builds them via Make prerequisite)
|
||||
for manufacturer in sorted(os.scandir(os.path.join(source_dir, '../boards')), key=lambda e: e.name):
|
||||
if not manufacturer.is_dir():
|
||||
continue
|
||||
for board in sorted(os.scandir(manufacturer.path), key=lambda e: e.name):
|
||||
if not board.is_dir():
|
||||
continue
|
||||
companion_file = os.path.join(board.path, 'companion_targets')
|
||||
if os.path.exists(companion_file):
|
||||
with open(companion_file) as f:
|
||||
companions = {l.strip() for l in f if l.strip() and not l.startswith('#')}
|
||||
for arch in grouped_targets:
|
||||
for man in grouped_targets[arch]['manufacturers']:
|
||||
grouped_targets[arch]['manufacturers'][man] = [
|
||||
t for t in grouped_targets[arch]['manufacturers'][man]
|
||||
if t not in companions
|
||||
]
|
||||
|
||||
# Append _deb targets for boards that have cmake/package.cmake
|
||||
for manufacturer in sorted(os.scandir(os.path.join(source_dir, '../boards')), key=lambda e: e.name):
|
||||
if not manufacturer.is_dir():
|
||||
continue
|
||||
if manufacturer.name in excluded_manufacturers:
|
||||
continue
|
||||
for board in sorted(os.scandir(manufacturer.path), key=lambda e: e.name):
|
||||
if not board.is_dir():
|
||||
continue
|
||||
board_name = manufacturer.name + '_' + board.name
|
||||
if board_name in excluded_boards:
|
||||
continue
|
||||
package_cmake = os.path.join(board.path, 'cmake', 'package.cmake')
|
||||
if os.path.exists(package_cmake):
|
||||
deb_target = board_name + '_deb'
|
||||
if target_filter and not any(deb_target.startswith(f) for f in target_filter):
|
||||
continue
|
||||
# Determine the container and group for this board
|
||||
container = default_container
|
||||
if board_name in board_container_overrides:
|
||||
container = board_container_overrides[board_name]
|
||||
target_entry = {'target': deb_target, 'container': container}
|
||||
if args.group:
|
||||
# Find the group where this board's _default target already lives
|
||||
default_target = board_name + '_default'
|
||||
group = None
|
||||
for g in grouped_targets:
|
||||
targets_in_group = grouped_targets[g].get('manufacturers', {}).get(manufacturer.name, [])
|
||||
if default_target in targets_in_group:
|
||||
group = g
|
||||
break
|
||||
if group is None:
|
||||
group = 'base'
|
||||
target_entry['arch'] = group
|
||||
if group not in grouped_targets:
|
||||
grouped_targets[group] = {'container': container, 'manufacturers': {}}
|
||||
if manufacturer.name not in grouped_targets[group]['manufacturers']:
|
||||
grouped_targets[group]['manufacturers'][manufacturer.name] = []
|
||||
grouped_targets[group]['manufacturers'][manufacturer.name].append(deb_target)
|
||||
build_configs.append(target_entry)
|
||||
|
||||
if(verbose):
|
||||
import pprint
|
||||
print("============================")
|
||||
|
||||
@@ -3,46 +3,35 @@
|
||||
mkdir artifacts
|
||||
cp **/**/*.px4 artifacts/ 2>/dev/null || true
|
||||
cp **/**/*.elf artifacts/ 2>/dev/null || true
|
||||
cp **/**/*.deb 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#*/}
|
||||
mkdir -p artifacts/$build_dir
|
||||
mkdir artifacts/$build_dir
|
||||
find artifacts/ -maxdepth 1 -type f -name "*$build_dir*"
|
||||
# Airframe (NuttX: build root, SITL: docs/ subdirectory)
|
||||
airframes_src=""
|
||||
if [ -f "$build_dir_path/airframes.xml" ]; then
|
||||
airframes_src="$build_dir_path/airframes.xml"
|
||||
elif [ -f "$build_dir_path/docs/airframes.xml" ]; then
|
||||
airframes_src="$build_dir_path/docs/airframes.xml"
|
||||
fi
|
||||
if [ -n "$airframes_src" ]; then
|
||||
cp "$airframes_src" "artifacts/$build_dir/"
|
||||
fi
|
||||
# Airframe
|
||||
cp $build_dir_path/airframes.xml artifacts/$build_dir/
|
||||
# Parameters
|
||||
cp $build_dir_path/parameters.xml artifacts/$build_dir/ 2>/dev/null || true
|
||||
cp $build_dir_path/parameters.json artifacts/$build_dir/ 2>/dev/null || true
|
||||
cp $build_dir_path/parameters.json.xz artifacts/$build_dir/ 2>/dev/null || true
|
||||
cp $build_dir_path/parameters.xml artifacts/$build_dir/
|
||||
cp $build_dir_path/parameters.json artifacts/$build_dir/
|
||||
cp $build_dir_path/parameters.json.xz artifacts/$build_dir/
|
||||
# Actuators
|
||||
cp $build_dir_path/actuators.json artifacts/$build_dir/ 2>/dev/null || true
|
||||
cp $build_dir_path/actuators.json.xz artifacts/$build_dir/ 2>/dev/null || true
|
||||
cp $build_dir_path/actuators.json artifacts/$build_dir/
|
||||
cp $build_dir_path/actuators.json.xz artifacts/$build_dir/
|
||||
# Events
|
||||
mkdir -p artifacts/$build_dir/events/
|
||||
cp $build_dir_path/events/all_events.json.xz artifacts/$build_dir/events/ 2>/dev/null || true
|
||||
cp $build_dir_path/events/all_events.json.xz artifacts/$build_dir/
|
||||
# ROS 2 msgs
|
||||
cp $build_dir_path/events/all_events.json.xz artifacts/$build_dir/
|
||||
# Module Docs
|
||||
ls -la artifacts/$build_dir
|
||||
echo "----------"
|
||||
done
|
||||
|
||||
if [ -d artifacts/px4_sitl_default ]; then
|
||||
# general metadata (used by Flight Review and other downstream consumers)
|
||||
mkdir -p artifacts/_general/
|
||||
# general metadata
|
||||
mkdir artifacts/_general/
|
||||
cp artifacts/px4_sitl_default/airframes.xml artifacts/_general/
|
||||
# Airframe
|
||||
if [ -f artifacts/px4_sitl_default/airframes.xml ]; then
|
||||
cp artifacts/px4_sitl_default/airframes.xml artifacts/_general/
|
||||
else
|
||||
echo "Error: expected 'artifacts/px4_sitl_default/airframes.xml' not found." >&2
|
||||
exit 1
|
||||
fi
|
||||
cp artifacts/px4_sitl_default/airframes.xml artifacts/_general/
|
||||
# Parameters
|
||||
cp artifacts/px4_sitl_default/parameters.xml artifacts/_general/
|
||||
cp artifacts/px4_sitl_default/parameters.json artifacts/_general/
|
||||
@@ -51,11 +40,9 @@ if [ -d artifacts/px4_sitl_default ]; then
|
||||
cp artifacts/px4_sitl_default/actuators.json artifacts/_general/
|
||||
cp artifacts/px4_sitl_default/actuators.json.xz artifacts/_general/
|
||||
# Events
|
||||
if [ -f artifacts/px4_sitl_default/events/all_events.json.xz ]; then
|
||||
cp artifacts/px4_sitl_default/events/all_events.json.xz artifacts/_general/
|
||||
else
|
||||
echo "Error: expected 'artifacts/px4_sitl_default/events/all_events.json.xz' not found." >&2
|
||||
exit 1
|
||||
fi
|
||||
cp artifacts/px4_sitl_default/events/all_events.json.xz artifacts/_general/
|
||||
# ROS 2 msgs
|
||||
cp artifacts/px4_sitl_default/events/all_events.json.xz artifacts/_general/
|
||||
# Module Docs
|
||||
ls -la artifacts/_general/
|
||||
fi
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Post, update, or delete a PR comment with deduplication.
|
||||
|
||||
Uses hidden HTML markers to find existing comments and avoid duplicates.
|
||||
Reads comment body from stdin when posting or updating.
|
||||
|
||||
Usage:
|
||||
echo "comment body" | python3 pr_comment.py --marker pr-title --pr 123 --result fail
|
||||
python3 pr_comment.py --marker pr-title --pr 123 --result pass
|
||||
|
||||
Results:
|
||||
fail - post/update comment with body from stdin
|
||||
warn - post/update comment with body from stdin
|
||||
pass - delete existing comment if any
|
||||
|
||||
Requires GH_TOKEN and GITHUB_REPOSITORY environment variables.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
|
||||
def gh_api(endpoint: str, method: str = 'GET', body: dict | None = None) -> str:
|
||||
"""Call the GitHub API via gh cli."""
|
||||
cmd = ['gh', 'api', endpoint, '-X', method]
|
||||
if body:
|
||||
for key, value in body.items():
|
||||
cmd.extend(['-f', f'{key}={value}'])
|
||||
result = subprocess.run(cmd, capture_output=True, text=True)
|
||||
if result.returncode != 0 and method != 'DELETE':
|
||||
print(f"gh api error: {result.stderr}", file=sys.stderr)
|
||||
return result.stdout
|
||||
|
||||
|
||||
def find_comment(repo: str, pr: int, marker: str) -> str | None:
|
||||
"""Find an existing comment by its hidden marker. Returns comment ID or None."""
|
||||
response = gh_api(f"repos/{repo}/issues/{pr}/comments?per_page=100")
|
||||
try:
|
||||
comments = json.loads(response)
|
||||
except json.JSONDecodeError:
|
||||
return None
|
||||
|
||||
if not isinstance(comments, list):
|
||||
return None
|
||||
|
||||
for comment in comments:
|
||||
if isinstance(comment, dict) and comment.get('body', '').startswith(marker):
|
||||
return str(comment['id'])
|
||||
return None
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser(description='Manage PR quality comments')
|
||||
parser.add_argument('--marker', required=True,
|
||||
help='Marker name (e.g. pr-title, commit-msgs, pr-body)')
|
||||
parser.add_argument('--pr', required=True, type=int,
|
||||
help='Pull request number')
|
||||
parser.add_argument('--result', required=True, choices=['pass', 'fail', 'warn'],
|
||||
help='Check result: pass deletes comment, fail/warn posts it')
|
||||
args = parser.parse_args()
|
||||
|
||||
repo = os.environ.get('GITHUB_REPOSITORY', '')
|
||||
if not repo:
|
||||
print("GITHUB_REPOSITORY not set", file=sys.stderr)
|
||||
sys.exit(2)
|
||||
|
||||
marker = f"<!-- commit-quality-{args.marker} -->"
|
||||
existing_id = find_comment(repo, args.pr, marker)
|
||||
|
||||
if args.result == 'pass':
|
||||
if existing_id:
|
||||
gh_api(f"repos/{repo}/issues/comments/{existing_id}", method='DELETE')
|
||||
return
|
||||
|
||||
# Read comment body from stdin
|
||||
body_content = sys.stdin.read().strip()
|
||||
if not body_content:
|
||||
print("No comment body provided on stdin", file=sys.stderr)
|
||||
sys.exit(2)
|
||||
|
||||
full_body = f"{marker}\n{body_content}"
|
||||
|
||||
if existing_id:
|
||||
gh_api(f"repos/{repo}/issues/comments/{existing_id}", method='PATCH',
|
||||
body={'body': full_body})
|
||||
else:
|
||||
gh_api(f"repos/{repo}/issues/{args.pr}/comments", method='POST',
|
||||
body={'body': full_body})
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -128,9 +128,6 @@ class SourceParser:
|
||||
# start waiting for the next part - long comment.
|
||||
if state == "wait-short-end":
|
||||
state = "wait-long"
|
||||
elif state == "wait-long-end":
|
||||
# Preserve paragraph breaks in long description
|
||||
long_desc += "\n"
|
||||
else:
|
||||
m = self.re_comment_tag.match(comment_content)
|
||||
if m:
|
||||
@@ -211,7 +208,8 @@ class SourceParser:
|
||||
raise Exception('short description too long (150 max, is {:}, parameter: {:})'.format(len(short_desc), name))
|
||||
param.fields["short_desc"] = self.re_remove_dots.sub('', short_desc)
|
||||
if long_desc is not None:
|
||||
param.fields["long_desc"] = long_desc.rstrip('\n')
|
||||
long_desc = self.re_remove_carriage_return.sub(' ', long_desc)
|
||||
param.fields["long_desc"] = long_desc
|
||||
for tag in tags:
|
||||
if tag == "group":
|
||||
group = tags[tag]
|
||||
@@ -409,15 +407,7 @@ def generate_yaml(filename: str, groups: list[ParameterGroup]) -> str:
|
||||
g["definitions"][parameter.name] = p
|
||||
data["parameters"].append(g)
|
||||
|
||||
# Use block scalar style for multi-line strings
|
||||
class BlockStyleDumper(yaml.SafeDumper):
|
||||
pass
|
||||
def str_representer(dumper, data):
|
||||
if '\n' in data:
|
||||
return dumper.represent_scalar('tag:yaml.org,2002:str', data, style='|')
|
||||
return dumper.represent_scalar('tag:yaml.org,2002:str', data)
|
||||
BlockStyleDumper.add_representer(str, str_representer)
|
||||
return yaml.dump(data, Dumper=BlockStyleDumper, sort_keys=False)
|
||||
return yaml.dump(data, sort_keys=False)
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
@@ -234,14 +234,14 @@ def get_actuator_output(yaml_config, output_functions, timer_config_file, verbos
|
||||
param_prefix = process_param_prefix(group['param_prefix'])
|
||||
standard_params = group.get('standard_params', {})
|
||||
standard_params_array = [
|
||||
( 'function', 'Function', 'FUNC', False, True ),
|
||||
( 'disarmed', 'Disarmed', 'DIS', False, True ),
|
||||
( 'min', 'Minimum', 'MIN', False, True ),
|
||||
( 'center', 'Center\n(for Servos)', 'CENT', False, False ),
|
||||
( 'max', 'Maximum', 'MAX', False, True ),
|
||||
( 'failsafe', 'Failsafe', 'FAIL', True, True ),
|
||||
( 'function', 'Function', 'FUNC', False ),
|
||||
( 'disarmed', 'Disarmed', 'DIS', False ),
|
||||
( 'min', 'Minimum', 'MIN', False ),
|
||||
( 'max', 'Maximum', 'MAX', False ),
|
||||
( 'center', 'Center\n(for Servos)', 'CENT', False ),
|
||||
( 'failsafe', 'Failsafe', 'FAIL', True ),
|
||||
]
|
||||
for key, label, param_suffix, advanced, has_function in standard_params_array:
|
||||
for key, label, param_suffix, advanced in standard_params_array:
|
||||
show_if = None
|
||||
if key in standard_params and 'show_if' in standard_params[key]:
|
||||
show_if = standard_params[key]['show_if']
|
||||
@@ -250,12 +250,13 @@ def get_actuator_output(yaml_config, output_functions, timer_config_file, verbos
|
||||
param = {
|
||||
'label': label,
|
||||
'name': param_prefix+'_'+param_suffix+'${i}',
|
||||
'function': key,
|
||||
}
|
||||
if has_function: param['function'] = key
|
||||
if advanced: param['advanced'] = True
|
||||
if show_if: param['show-if'] = show_if
|
||||
per_channel_params.append(param)
|
||||
|
||||
|
||||
param = {
|
||||
'label': 'Rev Range\n(for Servos)',
|
||||
'name': param_prefix+'_REV',
|
||||
|
||||
@@ -108,7 +108,7 @@ def parse_yaml_parameters_config(yaml_config, ethernet_supported):
|
||||
tags = '@group {:}'.format(param_group)
|
||||
if param['type'] == 'enum':
|
||||
param_type = 'INT32'
|
||||
for key in sorted(param['values'], key=float):
|
||||
for key in param['values']:
|
||||
tags += '\n * @value {:} {:}'.format(key, param['values'][key])
|
||||
elif param['type'] == 'bitmask':
|
||||
param_type = 'INT32'
|
||||
@@ -124,9 +124,6 @@ def parse_yaml_parameters_config(yaml_config, ethernet_supported):
|
||||
param_type = 'INT32'
|
||||
elif param['type'] == 'float':
|
||||
param_type = 'FLOAT'
|
||||
if 'values' in param:
|
||||
for key in sorted(param['values'], key=float):
|
||||
tags += '\n * @value {:} {:}'.format(key, param['values'][key])
|
||||
else:
|
||||
raise Exception("unknown param type {:}".format(param['type']))
|
||||
|
||||
@@ -315,7 +312,11 @@ When set to -1 (default), the value depends on the function (see {:}).
|
||||
if standard_params[key]['max'] >= 1<<16:
|
||||
raise Exception('maximum value for {:} expected <= {:} (got {:})'.format(key, 1<<16, standard_params[key]['max']))
|
||||
|
||||
if key == 'failsafe' or key == 'center':
|
||||
if key == 'failsafe':
|
||||
standard_params[key]['default'] = -1
|
||||
standard_params[key]['min'] = -1
|
||||
|
||||
if key == 'center':
|
||||
standard_params[key]['default'] = -1
|
||||
standard_params[key]['min'] = -1
|
||||
|
||||
|
||||
@@ -17,10 +17,10 @@ VALID_FIELDS = { #Note, also have to add the message types as those can be field
|
||||
'uint32'
|
||||
}
|
||||
|
||||
ALLOWED_UNITS = set(["m", "m/s", "m/s^2", "(m/s)^2", "deg", "deg/s", "rad", "rad/s", "rad^2", "rpm" ,"V", "A", "mA", "mAh", "W", "Wh", "dBm", "h", "minutes", "s", "ms", "us", "Ohm", "MB", "Kb/s", "degC","Pa", "%", "norm", "-"])
|
||||
ALLOWED_UNITS = set(["m", "m/s", "m/s^2", "(m/s)^2", "deg", "deg/s", "rad", "rad/s", "rad^2", "rpm" ,"V", "A", "mA", "mAh", "W", "dBm", "h", "s", "ms", "us", "Ohm", "MB", "Kb/s", "degC","Pa","%","-"])
|
||||
invalid_units = set()
|
||||
ALLOWED_FRAMES = set(["NED", "Body", "FRD", "ENU"])
|
||||
ALLOWED_INVALID_VALUES = set(["NaN", "0", "-1"])
|
||||
ALLOWED_FRAMES = set(["NED","Body"])
|
||||
ALLOWED_INVALID_VALUES = set(["NaN", "0"])
|
||||
ALLOWED_CONSTANTS_NOT_IN_ENUM = set(["ORB_QUEUE_LENGTH","MESSAGE_VERSION"])
|
||||
|
||||
class Error:
|
||||
@@ -36,14 +36,14 @@ class Error:
|
||||
|
||||
|
||||
if 'trailing_whitespace' == self.type:
|
||||
if self.issueString.strip():
|
||||
if self.issueString.strip():
|
||||
print(f"NOTE: Line has trailing whitespace ({self.message}: {self.linenumber}): {self.issueString}")
|
||||
else:
|
||||
print(f"NOTE: Line has trailing whitespace ({self.message}: {self.linenumber})")
|
||||
elif 'leading_whitespace_field_or_constant' == self.type:
|
||||
print(f"NOTE: Whitespace before field or constant ({self.message}: {self.linenumber}): {self.issueString}")
|
||||
print(f"NOTE: Whitespace before field or constant ({self.message}: {self.linenumber}): {self.issueString}")
|
||||
elif 'field_or_constant_has_multiple_whitepsace' == self.type:
|
||||
print(f"NOTE: Field/constant has more than one sequential whitespace character ({self.message}: {self.linenumber}): {self.issueString}")
|
||||
print(f"NOTE: Field/constant has more than one sequential whitespace character ({self.message}: {self.linenumber}): {self.issueString}")
|
||||
elif 'empty_start_line' == self.type:
|
||||
print(f"NOTE: Empty line at start of file ({self.message}: {self.linenumber})")
|
||||
elif 'internal_comment' == self.type:
|
||||
@@ -191,7 +191,7 @@ class CommandParam:
|
||||
if not "unknown_frame" in self.parent.errors:
|
||||
self.parent.errors["unknown_frame"] = []
|
||||
self.parent.errors["unknown_frame"].append(error)
|
||||
"""
|
||||
"""
|
||||
else:
|
||||
print(f"WARNING: Unhandled metadata in message comment: {item}")
|
||||
# TODO - report errors for different kinds of metadata
|
||||
@@ -202,9 +202,9 @@ class CommandParam:
|
||||
|
||||
if item == "-":
|
||||
unit = ""
|
||||
|
||||
|
||||
if unit and unit not in self.units:
|
||||
self.units.append(unit)
|
||||
self.units.append(unit)
|
||||
|
||||
if unit not in ALLOWED_UNITS:
|
||||
invalid_units.add(unit)
|
||||
@@ -221,7 +221,7 @@ class CommandParam:
|
||||
print(f" paramText: {self.paramText}\n unit: {self.units}\n enums: {self.enums}\n lineNumber: {self.lineNumber}\n range: {self.range}\n minValue: {self.minValue}\n maxValue: {self.maxValue}\n invalidValue: {self.invalidValue}\n frameValue: {self.frameValue}\n parent: {self.parent}\n ")
|
||||
|
||||
|
||||
|
||||
|
||||
class CommandConstant:
|
||||
"""
|
||||
Represents a constant that is a command definition.
|
||||
@@ -252,9 +252,9 @@ class CommandConstant:
|
||||
if not self.comment: # This is an bug for a command
|
||||
#print(f"Debug WARNING: NO COMMENT in CommandConstant: {self.name}") ## TODO make into ERROR
|
||||
return
|
||||
|
||||
|
||||
# Parse command comment to get the description and parameters.
|
||||
# print(f"Debug CommandConstant: {self.comment}")
|
||||
# print(f"Debug CommandConstant: {self.comment}")
|
||||
if not "|" in self.comment:
|
||||
# This is an error for a command constant
|
||||
error = Error("command_no_params_pipes", self.parent.filename, self.line_number, self.comment, self.name)
|
||||
@@ -263,7 +263,7 @@ class CommandConstant:
|
||||
self.parent.errors["command_no_params_pipes"] = []
|
||||
self.parent.errors["command_no_params_pipes"].append(error)
|
||||
return
|
||||
|
||||
|
||||
# Split on pipes
|
||||
commandSplit = self.comment.split("|")
|
||||
if len(commandSplit) < 9:
|
||||
@@ -316,11 +316,9 @@ Param | Units | Range/Enum | Description
|
||||
if val.minValue or val.maxValue:
|
||||
rangeVal = f"[{val.minValue if val.minValue else '-'} : {val.maxValue if val.maxValue else '-' }]"
|
||||
|
||||
units_str = ", ".join(val.units)
|
||||
enums_str = ', '.join("[{}](#{})".format(e, e) for e in val.enums)
|
||||
output+=f"{i} | {units_str}|{enums_str}{rangeVal} | {val.description}\n"
|
||||
output+=f"{i} | {", ".join(val.units)}|{', '.join(f"[{e}](#{e})" for e in val.enums)}{rangeVal} | {val.description}\n"
|
||||
else:
|
||||
output+=f"{i} | | | ?\n"
|
||||
output+=f"{i} | | | ?\n"
|
||||
|
||||
output+=f"\n"
|
||||
return output
|
||||
@@ -421,7 +419,7 @@ class MessageField:
|
||||
class UORBMessage:
|
||||
"""
|
||||
Represents a whole message, including fields, enums, commands, constants.
|
||||
The parser function delegates the parsing of each part of the message to
|
||||
The parser function delegates the parsing of each part of the message to
|
||||
more appropriate classes, once the specific type of line has been identified.
|
||||
"""
|
||||
|
||||
@@ -513,11 +511,11 @@ pageClass: is-wide-page
|
||||
markdown += "--- | --- | --- |---\n"
|
||||
for name, command in self.commandConstants.items():
|
||||
description = f" {command.comment} " if enum.comment else " "
|
||||
markdown += f'<a id="#{name}"></a> {name} | `{command.type}` | {command.value} |{description}\n'
|
||||
markdown += f'<a id="#{name}"></a> {name} | `{command.type}` | {command.value} |{description}\n'
|
||||
"""
|
||||
for commandConstant in self.commandConstants.values():
|
||||
#print(commandConstant)
|
||||
markdown += commandConstant.markdown_out()
|
||||
markdown += commandConstant.markdown_out()
|
||||
|
||||
# Generate enum docs
|
||||
if len(self.enums) > 0:
|
||||
@@ -710,7 +708,7 @@ pageClass: is-wide-page
|
||||
if stripped_line.startswith("#"):
|
||||
# Its an internal comment
|
||||
stripped_line=stripped_line[1:].strip()
|
||||
|
||||
|
||||
if stripped_line:
|
||||
#print(f"{self.filename}: Internal comment: [{line_number}]\n {line}")
|
||||
error = Error("internal_comment", self.filename, line_number, line)
|
||||
@@ -725,7 +723,7 @@ pageClass: is-wide-page
|
||||
self.errors["internal_comment_empty"].append(error)
|
||||
#pass # Empty comment
|
||||
continue
|
||||
|
||||
|
||||
# Must be a field or a comment.
|
||||
self.handleField(line, line_number, parentMessage=self)
|
||||
|
||||
@@ -835,9 +833,11 @@ def generate_dds_yaml_doc(allMessageFiles, output_file = 'dds_topics.md'):
|
||||
for message in data["subscriptions"]:
|
||||
all_message_types.add(message['type'].split("::")[-1])
|
||||
all_topics.add(message['topic'].split('/')[-1])
|
||||
for message in (data.get("subscriptions_multi") or []):
|
||||
all_message_types.add(message['type'].split("::")[-1])
|
||||
all_topics.add(message['topic'].split('/')[-1])
|
||||
if data["subscriptions_multi"]: # There is none now
|
||||
dds_markdown += "None\n"
|
||||
for message in data["subscriptions_multi"]:
|
||||
all_message_types.add(message['type'].split("::")[-1])
|
||||
all_topics.add(message['topic'].split('/')[-1])
|
||||
for message in allMessageFiles:
|
||||
all_messages_in_source.add(message.split('/')[-1].split('.')[0])
|
||||
messagesNotExported = all_messages_in_source - all_message_types
|
||||
@@ -874,17 +874,13 @@ Topic | Type| Rate Limit
|
||||
|
||||
dds_markdown += "\n## Subscriptions Multi\n\n"
|
||||
|
||||
subscriptions_multi = data.get("subscriptions_multi") or []
|
||||
if not subscriptions_multi:
|
||||
if not data["subscriptions_multi"]: # There is none now
|
||||
dds_markdown += "None\n"
|
||||
else:
|
||||
dds_markdown += "Topic | Type | Route Field | Max Instances\n--- | --- | --- | ---\n"
|
||||
for message in subscriptions_multi:
|
||||
type = message['type']
|
||||
px4Type = type.split("::")[-1]
|
||||
route_field = f"`{message['route_field']}`" if 'route_field' in message else "-"
|
||||
max_instances = message.get('max_instances', '-')
|
||||
dds_markdown += f"{message['topic']} | [{type}](../msg_docs/{px4Type}.md) | {route_field} | {max_instances}\n"
|
||||
print("Warning - we now have subscription_multi data - check format")
|
||||
dds_markdown += "Topic | Type\n--- | ---\n"
|
||||
for message in data["subscriptions_multi"]:
|
||||
dds_markdown += f"{message['topic']} | {message['type']}\n"
|
||||
|
||||
if messagesNotExported:
|
||||
# Print the topics that are not exported to DDS
|
||||
|
||||
+8
-8
@@ -42,7 +42,6 @@
|
||||
import argparse
|
||||
import json
|
||||
import base64
|
||||
import os
|
||||
import zlib
|
||||
import time
|
||||
import subprocess
|
||||
@@ -100,13 +99,14 @@ if args.summary != None:
|
||||
if args.description != None:
|
||||
desc['description'] = str(args.description)
|
||||
if args.git_identity != None:
|
||||
git_dir = os.path.join(args.git_identity, '.git')
|
||||
p = subprocess.run(["git", "--git-dir", git_dir, "describe", "--exclude", "ext/*", "--always", "--tags"],
|
||||
stdout=subprocess.PIPE, text=True)
|
||||
desc['git_identity'] = p.stdout.strip()
|
||||
p = subprocess.run(["git", "--git-dir", git_dir, "rev-parse", "--verify", "HEAD"],
|
||||
stdout=subprocess.PIPE, text=True)
|
||||
desc['git_hash'] = p.stdout.strip()
|
||||
cmd = "git --git-dir '{:}/.git' describe --exclude ext/* --always --tags".format(args.git_identity)
|
||||
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE).stdout
|
||||
desc['git_identity'] = p.read().strip().decode('utf-8')
|
||||
p.close()
|
||||
cmd = "git --git-dir '{:}/.git' rev-parse --verify HEAD".format(args.git_identity)
|
||||
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE).stdout
|
||||
desc['git_hash'] = p.read().strip().decode('utf-8')
|
||||
p.close()
|
||||
if args.parameter_xml != None:
|
||||
f = open(args.parameter_xml, "rb")
|
||||
bytes = f.read()
|
||||
|
||||
@@ -196,11 +196,6 @@ if [[ $INSTALL_NUTTX == "true" ]]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "${UBUNTU_RELEASE}" == "25.10" ]]; then
|
||||
echo "[ubuntu.sh] Gazebo binaries are not available for 25.10, skipping installation"
|
||||
INSTALL_SIM="false"
|
||||
fi
|
||||
|
||||
# Simulation tools
|
||||
if [[ $INSTALL_SIM == "true" ]]; then
|
||||
|
||||
|
||||
@@ -221,10 +221,8 @@
|
||||
/* HEATER
|
||||
* PWM in future
|
||||
*/
|
||||
#define GPIO_HEATER_OUTPUT
|
||||
#define HEATER_NUM 1
|
||||
#define GPIO_HEATER1_OUTPUT /* PB10 T2CH3 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTB|GPIO_PIN10)
|
||||
#define HEATER1_OUTPUT_EN(on_true) px4_arch_gpiowrite(GPIO_HEATER1_OUTPUT, (on_true))
|
||||
#define GPIO_HEATER_OUTPUT /* PB10 T2CH3 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTB|GPIO_PIN10)
|
||||
#define HEATER_OUTPUT_EN(on_true) px4_arch_gpiowrite(GPIO_HEATER_OUTPUT, (on_true))
|
||||
|
||||
/* PE6 is nARMED
|
||||
* The GPIO will be set as input while not armed HW will have external HW Pull UP.
|
||||
@@ -259,7 +257,7 @@
|
||||
#define GPIO_VDD_5V_PERIPH_nOC /* PE15 */ (GPIO_INPUT |GPIO_FLOAT|GPIO_PORTE|GPIO_PIN15)
|
||||
#define GPIO_VDD_5V_HIPOWER_nEN /* PG10 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_SET|GPIO_PORTG|GPIO_PIN10)
|
||||
#define GPIO_VDD_5V_HIPOWER_nOC /* PF13 */ (GPIO_INPUT |GPIO_FLOAT|GPIO_PORTF|GPIO_PIN13)
|
||||
#define GPIO_VDD_3V3_SENSORS_EN /* PG8 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTG|GPIO_PIN8)
|
||||
#define GPIO_VDD_3V3_SENSORS4_EN /* PG8 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTG|GPIO_PIN8)
|
||||
#define GPIO_VDD_3V3_SPEKTRUM_POWER_EN /* PH2 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTH|GPIO_PIN2)
|
||||
#define GPIO_VDD_3V3_SD_CARD_EN /* PC13 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTC|GPIO_PIN13)
|
||||
|
||||
@@ -286,7 +284,7 @@
|
||||
|
||||
#define VDD_5V_PERIPH_EN(on_true) px4_arch_gpiowrite(GPIO_VDD_5V_PERIPH_nEN, !(on_true))
|
||||
#define VDD_5V_HIPOWER_EN(on_true) px4_arch_gpiowrite(GPIO_VDD_5V_HIPOWER_nEN, !(on_true))
|
||||
#define VDD_3V3_SENSORS_EN(on_true) px4_arch_gpiowrite(GPIO_VDD_3V3_SENSORS_EN, (on_true))
|
||||
#define VDD_3V3_SENSORS4_EN(on_true) px4_arch_gpiowrite(GPIO_VDD_3V3_SENSORS4_EN, (on_true))
|
||||
#define VDD_3V3_SPEKTRUM_POWER_EN(on_true) px4_arch_gpiowrite(GPIO_VDD_3V3_SPEKTRUM_POWER_EN, (on_true))
|
||||
#define READ_VDD_3V3_SPEKTRUM_POWER_EN() px4_arch_gpioread(GPIO_VDD_3V3_SPEKTRUM_POWER_EN)
|
||||
#define VDD_3V3_SD_CARD_EN(on_true) px4_arch_gpiowrite(GPIO_VDD_3V3_SD_CARD_EN, (on_true))
|
||||
@@ -444,7 +442,7 @@
|
||||
GPIO_CAN1_RX, \
|
||||
GPIO_CAN2_TX, \
|
||||
GPIO_CAN2_RX, \
|
||||
GPIO_HEATER1_OUTPUT, \
|
||||
GPIO_HEATER_OUTPUT, \
|
||||
GPIO_nPOWER_IN_A, \
|
||||
GPIO_nPOWER_IN_B, \
|
||||
GPIO_nPOWER_IN_C, \
|
||||
@@ -452,7 +450,7 @@
|
||||
GPIO_VDD_5V_PERIPH_nOC, \
|
||||
GPIO_VDD_5V_HIPOWER_nEN, \
|
||||
GPIO_VDD_5V_HIPOWER_nOC, \
|
||||
GPIO_VDD_3V3_SENSORS_EN, \
|
||||
GPIO_VDD_3V3_SENSORS4_EN, \
|
||||
GPIO_VDD_3V3_SPEKTRUM_POWER_EN, \
|
||||
GPIO_VDD_3V3_SD_CARD_EN, \
|
||||
GPIO_PD15, \
|
||||
|
||||
@@ -107,7 +107,7 @@ __EXPORT void board_peripheral_reset(int ms)
|
||||
|
||||
VDD_5V_PERIPH_EN(false);
|
||||
board_control_spi_sensors_power(false, 0xffff);
|
||||
VDD_3V3_SENSORS_EN(false);
|
||||
VDD_3V3_SENSORS4_EN(false);
|
||||
|
||||
bool last = READ_VDD_3V3_SPEKTRUM_POWER_EN();
|
||||
/* Keep Spektum on to discharge rail*/
|
||||
@@ -122,7 +122,7 @@ __EXPORT void board_peripheral_reset(int ms)
|
||||
/* switch the peripheral rail back on */
|
||||
VDD_3V3_SPEKTRUM_POWER_EN(last);
|
||||
board_control_spi_sensors_power(true, 0xffff);
|
||||
VDD_3V3_SENSORS_EN(true);
|
||||
VDD_3V3_SENSORS4_EN(true);
|
||||
VDD_5V_PERIPH_EN(true);
|
||||
|
||||
}
|
||||
@@ -219,7 +219,7 @@ __EXPORT int board_app_initialize(uintptr_t arg)
|
||||
VDD_3V3_SD_CARD_EN(true);
|
||||
VDD_5V_PERIPH_EN(true);
|
||||
VDD_5V_HIPOWER_EN(true);
|
||||
VDD_3V3_SENSORS_EN(true);
|
||||
VDD_3V3_SENSORS4_EN(true);
|
||||
VDD_3V3_SPEKTRUM_POWER_EN(true);
|
||||
|
||||
/* Need hrt running before using the ADC */
|
||||
|
||||
@@ -48,7 +48,7 @@ constexpr px4_spi_bus_t px4_spi_buses[SPI_BUS_MAX_BUS_ITEMS] = {
|
||||
}, {GPIO::PortE, GPIO::Pin7}),
|
||||
// initSPIBus(SPI::Bus::SPI4, {
|
||||
// // no devices
|
||||
// TODO: if enabled, remove GPIO_VDD_3V3_SENSORS_EN from board_config.h
|
||||
// TODO: if enabled, remove GPIO_VDD_3V3_SENSORS4_EN from board_config.h
|
||||
// }, {GPIO::PortG, GPIO::Pin8}),
|
||||
initSPIBus(SPI::Bus::SPI5, {
|
||||
initSPIDevice(SPIDEV_FLASH(0), SPI::CS{GPIO::PortG, GPIO::Pin7})
|
||||
|
||||
@@ -28,8 +28,12 @@ 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
|
||||
|
||||
@@ -17,21 +17,21 @@ param set-default MAV_2_UDP_PRT 14550
|
||||
param set-default SENS_EN_INA226 1
|
||||
param set-default SENS_EN_THERMAL 1
|
||||
param set-default SENS_IMU_MODE 1
|
||||
param set-default HEATER1_TEMP 10.0
|
||||
#param set-default HEATER1_TEMP_FF 0.0
|
||||
#param set-default HEATER1_TEMP_I 0.025
|
||||
#param set-default HEATER1_TEMP_P 1.0
|
||||
param set-default SENS_IMU_TEMP 10.0
|
||||
#param set-default SENS_IMU_TEMP_FF 0.0
|
||||
#param set-default SENS_IMU_TEMP_I 0.025
|
||||
#param set-default SENS_IMU_TEMP_P 1.0
|
||||
|
||||
param set-default UAVCAN_ESC_IFACE 2
|
||||
|
||||
if ver hwtypecmp ARKV6X000
|
||||
then
|
||||
param set-default HEATER1_IMU_ID 2818058
|
||||
param set-default SENS_TEMP_ID 2818058
|
||||
fi
|
||||
|
||||
if ver hwtypecmp ARKV6X001
|
||||
then
|
||||
param set-default HEATER1_IMU_ID 3014666
|
||||
param set-default SENS_TEMP_ID 3014666
|
||||
fi
|
||||
|
||||
safety_button start
|
||||
|
||||
@@ -100,7 +100,7 @@ bmp388 -I start
|
||||
# Start an external PWM generator
|
||||
if param greater PCA9685_EN_BUS 0
|
||||
then
|
||||
pca9685_pwm_out start -X
|
||||
pca9685_pwm_out start
|
||||
fi
|
||||
|
||||
unset HAVE_PM2
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
CONFIG_MAVLINK_DIALECT="development"
|
||||
@@ -224,10 +224,8 @@
|
||||
/* HEATER
|
||||
* PWM in future
|
||||
*/
|
||||
#define GPIO_HEATER_OUTPUT
|
||||
#define HEATER_NUM 1
|
||||
#define GPIO_HEATER1_OUTPUT /* PB10 T2CH3 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTB|GPIO_PIN10)
|
||||
#define HEATER1_OUTPUT_EN(on_true) px4_arch_gpiowrite(GPIO_HEATER1_OUTPUT, (on_true))
|
||||
#define GPIO_HEATER_OUTPUT /* PB10 T2CH3 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTB|GPIO_PIN10)
|
||||
#define HEATER_OUTPUT_EN(on_true) px4_arch_gpiowrite(GPIO_HEATER_OUTPUT, (on_true))
|
||||
|
||||
/* PE6 is nARMED
|
||||
* The GPIO will be set as input while not armed HW will have external HW Pull UP.
|
||||
@@ -245,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)
|
||||
|
||||
@@ -273,7 +262,7 @@
|
||||
#define GPIO_VDD_5V_PERIPH_nOC /* PE15 */ (GPIO_INPUT |GPIO_FLOAT|GPIO_PORTE|GPIO_PIN15)
|
||||
#define GPIO_VDD_5V_HIPOWER_nEN /* PG10 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_SET|GPIO_PORTG|GPIO_PIN10)
|
||||
#define GPIO_VDD_5V_HIPOWER_nOC /* PF13 */ (GPIO_INPUT |GPIO_FLOAT|GPIO_PORTF|GPIO_PIN13)
|
||||
#define GPIO_VDD_3V3_SENSORS_EN /* PG8 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTG|GPIO_PIN8)
|
||||
#define GPIO_VDD_3V3_SENSORS4_EN /* PG8 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTG|GPIO_PIN8)
|
||||
#define GPIO_VDD_3V3_SPEKTRUM_POWER_EN /* PH2 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTH|GPIO_PIN2)
|
||||
#define GPIO_VDD_3V3_SD_CARD_EN /* PC13 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTC|GPIO_PIN13)
|
||||
|
||||
@@ -295,7 +284,7 @@
|
||||
|
||||
#define VDD_5V_PERIPH_EN(on_true) px4_arch_gpiowrite(GPIO_VDD_5V_PERIPH_nEN, !(on_true))
|
||||
#define VDD_5V_HIPOWER_EN(on_true) px4_arch_gpiowrite(GPIO_VDD_5V_HIPOWER_nEN, !(on_true))
|
||||
#define VDD_3V3_SENSORS_EN(on_true) px4_arch_gpiowrite(GPIO_VDD_3V3_SENSORS_EN, (on_true))
|
||||
#define VDD_3V3_SENSORS4_EN(on_true) px4_arch_gpiowrite(GPIO_VDD_3V3_SENSORS4_EN, (on_true))
|
||||
#define VDD_3V3_SPEKTRUM_POWER_EN(on_true) px4_arch_gpiowrite(GPIO_VDD_3V3_SPEKTRUM_POWER_EN, (on_true))
|
||||
#define READ_VDD_3V3_SPEKTRUM_POWER_EN() px4_arch_gpioread(GPIO_VDD_3V3_SPEKTRUM_POWER_EN)
|
||||
#define VDD_3V3_SD_CARD_EN(on_true) px4_arch_gpiowrite(GPIO_VDD_3V3_SD_CARD_EN, (on_true))
|
||||
@@ -421,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
|
||||
@@ -444,7 +436,7 @@
|
||||
GPIO_CAN1_RX, \
|
||||
GPIO_CAN2_TX, \
|
||||
GPIO_CAN2_RX, \
|
||||
GPIO_HEATER1_OUTPUT, \
|
||||
GPIO_HEATER_OUTPUT, \
|
||||
GPIO_nPOWER_IN_A, \
|
||||
GPIO_nPOWER_IN_B, \
|
||||
GPIO_nPOWER_IN_C, \
|
||||
@@ -452,7 +444,7 @@
|
||||
GPIO_VDD_5V_PERIPH_nOC, \
|
||||
GPIO_VDD_5V_HIPOWER_nEN, \
|
||||
GPIO_VDD_5V_HIPOWER_nOC, \
|
||||
GPIO_VDD_3V3_SENSORS_EN, \
|
||||
GPIO_VDD_3V3_SENSORS4_EN, \
|
||||
GPIO_VDD_3V3_SPEKTRUM_POWER_EN, \
|
||||
GPIO_VDD_3V3_SD_CARD_EN, \
|
||||
GPIO_PD15, \
|
||||
@@ -464,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 \
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@ __EXPORT void board_peripheral_reset(int ms)
|
||||
VDD_5V_HIPOWER_EN(false);
|
||||
VDD_5V_PERIPH_EN(false);
|
||||
board_control_spi_sensors_power(false, 0xffff);
|
||||
VDD_3V3_SENSORS_EN(false);
|
||||
VDD_3V3_SENSORS4_EN(false);
|
||||
SPI6_RESET(true);
|
||||
|
||||
bool last = READ_VDD_3V3_SPEKTRUM_POWER_EN();
|
||||
@@ -124,7 +124,7 @@ __EXPORT void board_peripheral_reset(int ms)
|
||||
/* switch the peripheral rail back on */
|
||||
VDD_3V3_SPEKTRUM_POWER_EN(last);
|
||||
board_control_spi_sensors_power(true, 0xffff);
|
||||
VDD_3V3_SENSORS_EN(true);
|
||||
VDD_3V3_SENSORS4_EN(true);
|
||||
VDD_5V_HIPOWER_EN(true);
|
||||
VDD_5V_PERIPH_EN(true);
|
||||
|
||||
@@ -221,7 +221,7 @@ __EXPORT int board_app_initialize(uintptr_t arg)
|
||||
/* Power on Interfaces */
|
||||
VDD_5V_PERIPH_EN(true);
|
||||
VDD_5V_HIPOWER_EN(true);
|
||||
VDD_3V3_SENSORS_EN(true);
|
||||
VDD_3V3_SENSORS4_EN(true);
|
||||
VDD_3V3_SPEKTRUM_POWER_EN(true);
|
||||
|
||||
SPI6_RESET(false);
|
||||
|
||||
@@ -48,7 +48,7 @@ constexpr px4_spi_bus_all_hw_t px4_spi_buses_all_hw[BOARD_NUM_SPI_CFG_HW_VERSION
|
||||
}, {GPIO::PortE, GPIO::Pin7}),
|
||||
// initSPIBus(SPI::Bus::SPI4, {
|
||||
// // no devices
|
||||
// TODO: if enabled, remove GPIO_VDD_3V3_SENSORS_EN from board_config.h
|
||||
// TODO: if enabled, remove GPIO_VDD_3V3_SENSORS4_EN from board_config.h
|
||||
// }, {GPIO::PortG, GPIO::Pin8}),
|
||||
initSPIBus(SPI::Bus::SPI5, {
|
||||
initSPIDevice(SPIDEV_FLASH(0), SPI::CS{GPIO::PortG, GPIO::Pin7})
|
||||
@@ -71,7 +71,7 @@ constexpr px4_spi_bus_all_hw_t px4_spi_buses_all_hw[BOARD_NUM_SPI_CFG_HW_VERSION
|
||||
}, {GPIO::PortE, GPIO::Pin7}),
|
||||
// initSPIBus(SPI::Bus::SPI4, {
|
||||
// // no devices
|
||||
// TODO: if enabled, remove GPIO_VDD_3V3_SENSORS_EN from board_config.h
|
||||
// TODO: if enabled, remove GPIO_VDD_3V3_SENSORS4_EN from board_config.h
|
||||
// }, {GPIO::PortG, GPIO::Pin8}),
|
||||
initSPIBus(SPI::Bus::SPI5, {
|
||||
initSPIDevice(SPIDEV_FLASH(0), SPI::CS{GPIO::PortG, GPIO::Pin7})
|
||||
|
||||
@@ -1,19 +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
|
||||
2106_albatross
|
||||
13200_generic_vtol_tailsitter
|
||||
13030_generic_vtol_quad_tiltrotor
|
||||
@@ -15,14 +15,14 @@ fi
|
||||
|
||||
# TODO: Tune the following parameters
|
||||
param set-default SENS_EN_THERMAL 1
|
||||
param set-default HEATER1_TEMP 10.0
|
||||
#param set-default HEATER1_TEMP_FF 0.0
|
||||
#param set-default HEATER1_TEMP_I 0.025
|
||||
#param set-default HEATER1_TEMP_P 1.0
|
||||
param set-default SENS_IMU_TEMP 10.0
|
||||
#param set-default SENS_IMU_TEMP_FF 0.0
|
||||
#param set-default SENS_IMU_TEMP_I 0.025
|
||||
#param set-default SENS_IMU_TEMP_P 1.0
|
||||
|
||||
if ver hwtypecmp ARKFPV000
|
||||
then
|
||||
param set-default HEATER1_IMU_ID 3014666
|
||||
param set-default SENS_TEMP_ID 3014666
|
||||
fi
|
||||
|
||||
param set-default BAT1_V_DIV 21.0
|
||||
|
||||
@@ -20,5 +20,5 @@ bmp388 -I -b 2 start
|
||||
# Start an external PWM generator
|
||||
if param greater PCA9685_EN_BUS 0
|
||||
then
|
||||
pca9685_pwm_out start -X
|
||||
pca9685_pwm_out start
|
||||
fi
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
CONFIG_MAVLINK_DIALECT="development"
|
||||
@@ -205,10 +205,8 @@
|
||||
/* HEATER
|
||||
* PWM in future
|
||||
*/
|
||||
#define GPIO_HEATER_OUTPUT
|
||||
#define HEATER_NUM 1
|
||||
#define GPIO_HEATER1_OUTPUT /* PB10 T2CH3 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTB|GPIO_PIN10)
|
||||
#define HEATER1_OUTPUT_EN(on_true) px4_arch_gpiowrite(GPIO_HEATER1_OUTPUT, (on_true))
|
||||
#define GPIO_HEATER_OUTPUT /* PB10 T2CH3 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTB|GPIO_PIN10)
|
||||
#define HEATER_OUTPUT_EN(on_true) px4_arch_gpiowrite(GPIO_HEATER_OUTPUT, (on_true))
|
||||
|
||||
/* PE6 is nARMED
|
||||
* The GPIO will be set as input while not armed HW will have external HW Pull UP.
|
||||
@@ -225,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 */
|
||||
@@ -306,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
|
||||
@@ -327,7 +318,7 @@
|
||||
GPIO_HW_VER_REV_DRIVE, \
|
||||
GPIO_CAN1_TX, \
|
||||
GPIO_CAN1_RX, \
|
||||
GPIO_HEATER1_OUTPUT, \
|
||||
GPIO_HEATER_OUTPUT, \
|
||||
GPIO_VDD_5V_PGOOD, \
|
||||
GPIO_VDD_12V_PGOOD, \
|
||||
GPIO_VDD_12V_EN, \
|
||||
@@ -335,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 \
|
||||
}
|
||||
|
||||
|
||||
@@ -21,17 +21,17 @@ param set-default SENS_EN_INA226 1
|
||||
|
||||
# TODO: Tune the following parameters
|
||||
param set-default SENS_EN_THERMAL 1
|
||||
param set-default HEATER1_TEMP 10.0
|
||||
#param set-default HEATER1_TEMP_FF 0.0
|
||||
#param set-default HEATER1_TEMP_I 0.025
|
||||
#param set-default HEATER1_TEMP_P 1.0
|
||||
param set-default SENS_IMU_TEMP 10.0
|
||||
#param set-default SENS_IMU_TEMP_FF 0.0
|
||||
#param set-default SENS_IMU_TEMP_I 0.025
|
||||
#param set-default SENS_IMU_TEMP_P 1.0
|
||||
|
||||
param set-default UAVCAN_ESC_IFACE 1
|
||||
|
||||
if ver hwtypecmp ARKPI6X000
|
||||
then
|
||||
# TODO: Add the correct sensor ID
|
||||
param set-default HEATER1_IMU_ID 2490378
|
||||
param set-default SENS_TEMP_ID 2490378
|
||||
fi
|
||||
|
||||
param set-default EKF2_MULTI_IMU 0
|
||||
|
||||
@@ -38,5 +38,5 @@ afbrs50 start
|
||||
# Start an external PWM generator
|
||||
if param greater PCA9685_EN_BUS 0
|
||||
then
|
||||
pca9685_pwm_out start -X
|
||||
pca9685_pwm_out start
|
||||
fi
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
CONFIG_MAVLINK_DIALECT="development"
|
||||
@@ -188,10 +188,8 @@
|
||||
/* HEATER
|
||||
* PWM in future
|
||||
*/
|
||||
#define GPIO_HEATER_OUTPUT
|
||||
#define HEATER_NUM 1
|
||||
#define GPIO_HEATER1_OUTPUT /* PB10 T2CH3 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTB|GPIO_PIN10)
|
||||
#define HEATER1_OUTPUT_EN(on_true) px4_arch_gpiowrite(GPIO_HEATER1_OUTPUT, (on_true))
|
||||
#define GPIO_HEATER_OUTPUT /* PB10 T2CH3 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTB|GPIO_PIN10)
|
||||
#define HEATER_OUTPUT_EN(on_true) px4_arch_gpiowrite(GPIO_HEATER_OUTPUT, (on_true))
|
||||
|
||||
/* PE6 is nARMED
|
||||
* The GPIO will be set as input while not armed HW will have external HW Pull UP.
|
||||
@@ -208,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)
|
||||
|
||||
@@ -311,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
|
||||
@@ -332,7 +324,7 @@
|
||||
GPIO_HW_VER_REV_DRIVE, \
|
||||
GPIO_CAN1_TX, \
|
||||
GPIO_CAN1_RX, \
|
||||
GPIO_HEATER1_OUTPUT, \
|
||||
GPIO_HEATER_OUTPUT, \
|
||||
GPIO_VDD_5V_HIPOWER_nEN, \
|
||||
GPIO_VDD_5V_HIPOWER_nOC, \
|
||||
GPIO_VDD_3V3_SD_CARD_EN, \
|
||||
@@ -340,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 \
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ constexpr px4_spi_bus_all_hw_t px4_spi_buses_all_hw[BOARD_NUM_SPI_CFG_HW_VERSION
|
||||
}),
|
||||
// initSPIBus(SPI::Bus::SPI4, {
|
||||
// // no devices
|
||||
// TODO: if enabled, remove GPIO_VDD_3V3_SENSORS_EN from board_config.h
|
||||
// TODO: if enabled, remove GPIO_VDD_3V3_SENSORS4_EN from board_config.h
|
||||
// }, {GPIO::PortG, GPIO::Pin8}),
|
||||
// initSPIBus(SPI::Bus::SPI5, {
|
||||
// initSPIDevice(SPIDEV_FLASH(0), SPI::CS{GPIO::PortG, GPIO::Pin7})
|
||||
@@ -69,7 +69,7 @@ constexpr px4_spi_bus_all_hw_t px4_spi_buses_all_hw[BOARD_NUM_SPI_CFG_HW_VERSION
|
||||
}),
|
||||
// initSPIBus(SPI::Bus::SPI4, {
|
||||
// // no devices
|
||||
// TODO: if enabled, remove GPIO_VDD_3V3_SENSORS_EN from board_config.h
|
||||
// TODO: if enabled, remove GPIO_VDD_3V3_SENSORS4_EN from board_config.h
|
||||
// }, {GPIO::PortG, GPIO::Pin8}),
|
||||
// initSPIBus(SPI::Bus::SPI5, {
|
||||
// initSPIDevice(SPIDEV_FLASH(0), SPI::CS{GPIO::PortG, GPIO::Pin7})
|
||||
|
||||
@@ -121,9 +121,7 @@
|
||||
#define BOARD_REAR_LED_MASK (1 << 1) | (1 << 2)
|
||||
|
||||
/* HEATER */
|
||||
#define GPIO_HEATER_OUTPUT
|
||||
#define HEATER_NUM 1
|
||||
#define GPIO_HEATER1_OUTPUT /* PA7 T14CH1 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTA|GPIO_PIN7)
|
||||
#define GPIO_HEATER_OUTPUT /* PA7 T14CH1 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTA|GPIO_PIN7)
|
||||
|
||||
#define BOARD_HAS_LED_PWM 1
|
||||
#define BOARD_LED_PWM_DRIVE_ACTIVE_LOW 1
|
||||
@@ -184,7 +182,7 @@
|
||||
PX4_ADC_GPIO, \
|
||||
GPIO_HW_REV_DRIVE, \
|
||||
GPIO_HW_VER_DRIVE, \
|
||||
GPIO_HEATER1_OUTPUT, \
|
||||
GPIO_HEATER_OUTPUT, \
|
||||
GPIO_VDD_3V3_SD_CARD_EN, \
|
||||
GPIO_OTGFS_VBUS \
|
||||
}
|
||||
|
||||
@@ -55,7 +55,6 @@ CONFIG_MODULES_HARDFAULT_STREAM=y
|
||||
CONFIG_MODULES_LAND_DETECTOR=y
|
||||
CONFIG_MODULES_LANDING_TARGET_ESTIMATOR=y
|
||||
CONFIG_MODULES_LOAD_MON=y
|
||||
CONFIG_MODULES_TASK_WATCHDOG=y
|
||||
CONFIG_MODULES_LOGGER=y
|
||||
CONFIG_LOGGER_STACK_SIZE=4100
|
||||
CONFIG_MODULES_MAG_BIAS_ESTIMATOR=y
|
||||
|
||||
@@ -34,8 +34,5 @@ nshterm /dev/ttyS3 &
|
||||
# Start the time_persistor to cyclically store the RTC in FRAM
|
||||
time_persistor start
|
||||
|
||||
# Start the task_watchdog as we do not have the logger watchdog
|
||||
task_watchdog start
|
||||
|
||||
# Start the ESC telemetry
|
||||
dshot telemetry -d /dev/ttyS5 -x
|
||||
|
||||
@@ -77,5 +77,5 @@ ist8310 -X -b 1 -R 10 start
|
||||
# Start an external PWM generator
|
||||
if param greater PCA9685_EN_BUS 0
|
||||
then
|
||||
pca9685_pwm_out start -X
|
||||
pca9685_pwm_out start
|
||||
fi
|
||||
|
||||
@@ -224,10 +224,8 @@
|
||||
/* HEATER
|
||||
* PWM in future
|
||||
*/
|
||||
#define GPIO_HEATER_OUTPUT
|
||||
#define HEATER_NUM 1
|
||||
#define GPIO_HEATER1_OUTPUT /* PB10 T2CH3 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTB|GPIO_PIN10)
|
||||
#define HEATER1_OUTPUT_EN(on_true) px4_arch_gpiowrite(GPIO_HEATER1_OUTPUT, (on_true))
|
||||
#define GPIO_HEATER_OUTPUT /* PB10 T2CH3 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTB|GPIO_PIN10)
|
||||
#define HEATER_OUTPUT_EN(on_true) px4_arch_gpiowrite(GPIO_HEATER_OUTPUT, (on_true))
|
||||
|
||||
/* PE6 is nARMED
|
||||
* The GPIO will be set as input while not armed HW will have external HW Pull UP.
|
||||
@@ -262,7 +260,7 @@
|
||||
#define GPIO_VDD_5V_PERIPH_nOC /* PE15 */ (GPIO_INPUT |GPIO_FLOAT|GPIO_PORTE|GPIO_PIN15)
|
||||
#define GPIO_VDD_5V_HIPOWER_nEN /* PG10 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_SET|GPIO_PORTG|GPIO_PIN10)
|
||||
#define GPIO_VDD_5V_HIPOWER_nOC /* PF13 */ (GPIO_INPUT |GPIO_FLOAT|GPIO_PORTF|GPIO_PIN13)
|
||||
#define GPIO_VDD_3V3_SENSORS_EN /* PG8 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTG|GPIO_PIN8)
|
||||
#define GPIO_VDD_3V3_SENSORS4_EN /* PG8 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTG|GPIO_PIN8)
|
||||
#define GPIO_VDD_3V3_SPEKTRUM_POWER_EN /* PH2 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTH|GPIO_PIN2)
|
||||
#define GPIO_VDD_3V3_SD_CARD_EN /* PC13 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTC|GPIO_PIN13)
|
||||
|
||||
@@ -289,7 +287,7 @@
|
||||
|
||||
#define VDD_5V_PERIPH_EN(on_true) px4_arch_gpiowrite(GPIO_VDD_5V_PERIPH_nEN, !(on_true))
|
||||
#define VDD_5V_HIPOWER_EN(on_true) px4_arch_gpiowrite(GPIO_VDD_5V_HIPOWER_nEN, !(on_true))
|
||||
#define VDD_3V3_SENSORS_EN(on_true) px4_arch_gpiowrite(GPIO_VDD_3V3_SENSORS_EN, (on_true))
|
||||
#define VDD_3V3_SENSORS4_EN(on_true) px4_arch_gpiowrite(GPIO_VDD_3V3_SENSORS4_EN, (on_true))
|
||||
#define VDD_3V3_SPEKTRUM_POWER_EN(on_true) px4_arch_gpiowrite(GPIO_VDD_3V3_SPEKTRUM_POWER_EN, (on_true))
|
||||
#define READ_VDD_3V3_SPEKTRUM_POWER_EN() px4_arch_gpioread(GPIO_VDD_3V3_SPEKTRUM_POWER_EN)
|
||||
#define VDD_3V3_SD_CARD_EN(on_true) px4_arch_gpiowrite(GPIO_VDD_3V3_SD_CARD_EN, (on_true))
|
||||
@@ -445,7 +443,7 @@
|
||||
GPIO_CAN1_RX, \
|
||||
GPIO_CAN2_TX, \
|
||||
GPIO_CAN2_RX, \
|
||||
GPIO_HEATER1_OUTPUT, \
|
||||
GPIO_HEATER_OUTPUT, \
|
||||
GPIO_nPOWER_IN_A, \
|
||||
GPIO_nPOWER_IN_B, \
|
||||
GPIO_nPOWER_IN_C, \
|
||||
@@ -453,7 +451,7 @@
|
||||
GPIO_VDD_5V_PERIPH_nOC, \
|
||||
GPIO_VDD_5V_HIPOWER_nEN, \
|
||||
GPIO_VDD_5V_HIPOWER_nOC, \
|
||||
GPIO_VDD_3V3_SENSORS_EN, \
|
||||
GPIO_VDD_3V3_SENSORS4_EN, \
|
||||
GPIO_VDD_3V3_SPEKTRUM_POWER_EN, \
|
||||
GPIO_VDD_3V3_SD_CARD_EN, \
|
||||
GPIO_PD15, \
|
||||
|
||||
@@ -107,7 +107,7 @@ __EXPORT void board_peripheral_reset(int ms)
|
||||
|
||||
VDD_5V_PERIPH_EN(false);
|
||||
board_control_spi_sensors_power(false, 0xffff);
|
||||
VDD_3V3_SENSORS_EN(false);
|
||||
VDD_3V3_SENSORS4_EN(false);
|
||||
|
||||
bool last = READ_VDD_3V3_SPEKTRUM_POWER_EN();
|
||||
/* Keep Spektum on to discharge rail*/
|
||||
@@ -122,7 +122,7 @@ __EXPORT void board_peripheral_reset(int ms)
|
||||
/* switch the peripheral rail back on */
|
||||
VDD_3V3_SPEKTRUM_POWER_EN(last);
|
||||
board_control_spi_sensors_power(true, 0xffff);
|
||||
VDD_3V3_SENSORS_EN(true);
|
||||
VDD_3V3_SENSORS4_EN(true);
|
||||
VDD_5V_PERIPH_EN(true);
|
||||
|
||||
}
|
||||
@@ -215,7 +215,7 @@ __EXPORT int board_app_initialize(uintptr_t arg)
|
||||
VDD_3V3_SD_CARD_EN(true);
|
||||
VDD_5V_PERIPH_EN(true);
|
||||
VDD_5V_HIPOWER_EN(true);
|
||||
VDD_3V3_SENSORS_EN(true);
|
||||
VDD_3V3_SENSORS4_EN(true);
|
||||
VDD_3V3_SPEKTRUM_POWER_EN(true);
|
||||
|
||||
/* Need hrt running before using the ADC */
|
||||
|
||||
@@ -48,7 +48,7 @@ constexpr px4_spi_bus_t px4_spi_buses[SPI_BUS_MAX_BUS_ITEMS] = {
|
||||
}, {GPIO::PortE, GPIO::Pin7}),
|
||||
// initSPIBus(SPI::Bus::SPI4, {
|
||||
// // no devices
|
||||
// TODO: if enabled, remove GPIO_VDD_3V3_SENSORS_EN from board_config.h
|
||||
// TODO: if enabled, remove GPIO_VDD_3V3_SENSORS4_EN from board_config.h
|
||||
// }, {GPIO::PortG, GPIO::Pin8}),
|
||||
initSPIBus(SPI::Bus::SPI5, {
|
||||
initSPIDevice(SPIDEV_FLASH(0), SPI::CS{GPIO::PortG, GPIO::Pin7})
|
||||
|
||||
@@ -42,8 +42,6 @@ px4_add_module(
|
||||
syslink_bridge.cpp
|
||||
syslink_memory.cpp
|
||||
syslink.c
|
||||
MODULE_CONFIG
|
||||
syslink_params.yaml
|
||||
DEPENDS
|
||||
battery
|
||||
)
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2016 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file syslink_params.c
|
||||
*
|
||||
* Parameters defined by the syslink module and the exposed NRF51 radio
|
||||
*
|
||||
* @author Dennis Shtatnov <densht@gmail.com>
|
||||
*/
|
||||
|
||||
/**
|
||||
* Operating channel of the NRF51
|
||||
*
|
||||
* @min 0
|
||||
* @max 125
|
||||
* @group Syslink
|
||||
*/
|
||||
PARAM_DEFINE_INT32(SLNK_RADIO_CHAN, 80);
|
||||
|
||||
/**
|
||||
* Operating datarate of the NRF51
|
||||
*
|
||||
* @min 0
|
||||
* @max 2
|
||||
* @group Syslink
|
||||
*/
|
||||
PARAM_DEFINE_INT32(SLNK_RADIO_RATE, 2);
|
||||
|
||||
/**
|
||||
* Operating address of the NRF51 (most significant byte)
|
||||
*
|
||||
* @group Syslink
|
||||
*/
|
||||
PARAM_DEFINE_INT32(SLNK_RADIO_ADDR1, 231); // 0xE7
|
||||
|
||||
/**
|
||||
* Operating address of the NRF51 (least significant 4 bytes)
|
||||
*
|
||||
* @group Syslink
|
||||
*/
|
||||
PARAM_DEFINE_INT32(SLNK_RADIO_ADDR2, 3890735079); // 0xE7E7E7E7
|
||||
@@ -1,28 +0,0 @@
|
||||
module_name: syslink
|
||||
parameters:
|
||||
- group: Syslink
|
||||
definitions:
|
||||
SLNK_RADIO_CHAN:
|
||||
description:
|
||||
short: Operating channel of the NRF51
|
||||
type: int32
|
||||
default: 80
|
||||
min: 0
|
||||
max: 125
|
||||
SLNK_RADIO_RATE:
|
||||
description:
|
||||
short: Operating datarate of the NRF51
|
||||
type: int32
|
||||
default: 2
|
||||
min: 0
|
||||
max: 2
|
||||
SLNK_RADIO_ADDR1:
|
||||
description:
|
||||
short: Operating address of the NRF51 (most significant byte)
|
||||
type: int32
|
||||
default: 231
|
||||
SLNK_RADIO_ADDR2:
|
||||
description:
|
||||
short: Operating address of the NRF51 (least significant 4 bytes)
|
||||
type: int32
|
||||
default: -404232217
|
||||
@@ -28,7 +28,7 @@ then
|
||||
echo "ads1115 not found."
|
||||
fi
|
||||
|
||||
if ! pca9685_pwm_out start -X
|
||||
if ! pca9685_pwm_out start
|
||||
then
|
||||
echo "pca9685_pwm_out not found."
|
||||
fi
|
||||
|
||||
Executable → Regular
BIN
Binary file not shown.
@@ -104,7 +104,7 @@
|
||||
#define OSC_FREQ 8
|
||||
|
||||
#define BOARD_PIN_LED_ACTIVITY GPIO_nLED_BLUE // BLUE
|
||||
#define BOARD_PIN_LED_BOOTLOADER GPIO_nLED_RED // RED
|
||||
#define BOARD_PIN_LED_BOOTLOADER GPIO_nLED_GREEN // GREEN
|
||||
#define BOARD_LED_ON 0
|
||||
#define BOARD_LED_OFF 1
|
||||
|
||||
|
||||
@@ -169,7 +169,6 @@ __EXPORT int board_app_initialize(uintptr_t arg)
|
||||
drv_led_start();
|
||||
led_off(LED_RED);
|
||||
led_off(LED_BLUE);
|
||||
led_off(LED_GREEN);
|
||||
|
||||
if (board_hardfault_init(2, true) != 0) {
|
||||
led_on(LED_BLUE);
|
||||
|
||||
@@ -63,23 +63,12 @@ extern void led_toggle(int led);
|
||||
__END_DECLS
|
||||
|
||||
# define xlat(p) (p)
|
||||
// index: 0=BLUE, 1=RED, 2=SAFETY, 3=GREEN
|
||||
static uint32_t g_ledmap[] = {
|
||||
GPIO_nLED_BLUE, // LED_BLUE (0)
|
||||
GPIO_nLED_RED, // LED_RED (1)
|
||||
0, // LED_SAFETY (2) - no independent safety LED, use 0 placeholder
|
||||
GPIO_nLED_GREEN, // LED_GREEN (3)
|
||||
GPIO_nLED_GREEN, // Indexed by BOARD_LED_GREEN
|
||||
GPIO_nLED_BLUE, // Indexed by BOARD_LED_BLUE
|
||||
GPIO_nLED_RED, // Indexed by BOARD_LED_RED
|
||||
};
|
||||
|
||||
#ifndef arraySize
|
||||
#define arraySize(a) (sizeof((a))/sizeof(((a)[0])))
|
||||
#endif
|
||||
|
||||
static inline bool valid_led_index(int led)
|
||||
{
|
||||
return (led >= 0) && ((size_t)led < arraySize(g_ledmap));
|
||||
}
|
||||
|
||||
__EXPORT void led_init(void)
|
||||
{
|
||||
/* Configure LED GPIOs for output */
|
||||
@@ -92,10 +81,6 @@ __EXPORT void led_init(void)
|
||||
|
||||
static void phy_set_led(int led, bool state)
|
||||
{
|
||||
if (!valid_led_index(led)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Drive Low to switch on */
|
||||
if (g_ledmap[led] != 0) {
|
||||
stm32_gpiowrite(g_ledmap[led], !state);
|
||||
@@ -104,10 +89,6 @@ static void phy_set_led(int led, bool state)
|
||||
|
||||
static bool phy_get_led(int led)
|
||||
{
|
||||
if (!valid_led_index(led)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* If Low it is on */
|
||||
if (g_ledmap[led] != 0) {
|
||||
return !stm32_gpioread(g_ledmap[led]);
|
||||
|
||||
@@ -37,8 +37,6 @@ px4_add_module(
|
||||
|
||||
SRCS
|
||||
pwm_voltage.cpp
|
||||
MODULE_CONFIG
|
||||
parameters.yaml
|
||||
DEPENDS
|
||||
px4_work_queue
|
||||
)
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2024 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* Control PWM output voltage
|
||||
*
|
||||
* Enable: PWM output voltage 5V
|
||||
* Disable: PWM output voltage 3.3V
|
||||
*
|
||||
* @boolean
|
||||
* @reboot_required true
|
||||
* @group PWM Outputs
|
||||
*/
|
||||
PARAM_DEFINE_INT32(PWM_LEVEL_CONT, 0);
|
||||
@@ -1,13 +0,0 @@
|
||||
module_name: pwm_voltage
|
||||
parameters:
|
||||
- group: PWM Outputs
|
||||
definitions:
|
||||
PWM_LEVEL_CONT:
|
||||
description:
|
||||
short: Control PWM output voltage
|
||||
long: |-
|
||||
Enable: PWM output voltage 5V
|
||||
Disable: PWM output voltage 3.3V
|
||||
type: boolean
|
||||
default: 0
|
||||
reboot_required: true
|
||||
@@ -37,8 +37,6 @@ px4_add_module(
|
||||
|
||||
SRCS
|
||||
pwm_voltage.cpp
|
||||
MODULE_CONFIG
|
||||
parameters.yaml
|
||||
DEPENDS
|
||||
px4_work_queue
|
||||
)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2026 PX4 Development Team. All rights reserved.
|
||||
* Copyright (c) 2025 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -31,11 +31,13 @@
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <px4_arch/i2c_hw_description.h>
|
||||
|
||||
constexpr px4_i2c_bus_t px4_i2c_buses[I2C_BUS_MAX_BUS_ITEMS] = {
|
||||
initI2CBusExternal(1),
|
||||
initI2CBusExternal(2),
|
||||
initI2CBusExternal(3),
|
||||
initI2CBusInternal(4),
|
||||
};
|
||||
/**
|
||||
* Control PWM output voltage
|
||||
*
|
||||
* @value 0 3.3V
|
||||
* @value 1 5.0V
|
||||
*
|
||||
* @reboot_required true
|
||||
* @group PWM Outputs
|
||||
*/
|
||||
PARAM_DEFINE_INT32(PWM_VOLT_SEL, 0);
|
||||
@@ -1,13 +0,0 @@
|
||||
module_name: pwm_voltage
|
||||
parameters:
|
||||
- group: PWM Outputs
|
||||
definitions:
|
||||
PWM_VOLT_SEL:
|
||||
description:
|
||||
short: Control PWM output voltage
|
||||
type: enum
|
||||
values:
|
||||
0: 3.3V
|
||||
1: 5.0V
|
||||
default: 0
|
||||
reboot_required: true
|
||||
@@ -230,10 +230,8 @@
|
||||
/* HEATER
|
||||
* PWM in future
|
||||
*/
|
||||
#define GPIO_HEATER_OUTPUT
|
||||
#define HEATER_NUM 1
|
||||
#define GPIO_HEATER1_OUTPUT /* PB10 T2CH3 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTB|GPIO_PIN10)
|
||||
#define HEATER1_OUTPUT_EN(on_true) px4_arch_gpiowrite(GPIO_HEATER1_OUTPUT, (on_true))
|
||||
#define GPIO_HEATER_OUTPUT /* PB10 T2CH3 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTB|GPIO_PIN10)
|
||||
#define HEATER_OUTPUT_EN(on_true) px4_arch_gpiowrite(GPIO_HEATER_OUTPUT, (on_true))
|
||||
|
||||
/* PE6 is nARMED
|
||||
* The GPIO will be set as input while not armed HW will have external HW Pull UP.
|
||||
@@ -271,7 +269,7 @@
|
||||
#define GPIO_VDD_5V_PERIPH_nOC /* PE15 */ (GPIO_INPUT |GPIO_FLOAT|GPIO_PORTE|GPIO_PIN15)
|
||||
#define GPIO_VDD_5V_HIPOWER_nEN /* PG10 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_SET|GPIO_PORTG|GPIO_PIN10)
|
||||
#define GPIO_VDD_5V_HIPOWER_nOC /* PF13 */ (GPIO_INPUT |GPIO_FLOAT|GPIO_PORTF|GPIO_PIN13)
|
||||
#define GPIO_VDD_3V3_SENSORS_EN /* PG8 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTG|GPIO_PIN8)
|
||||
#define GPIO_VDD_3V3_SENSORS4_EN /* PG8 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTG|GPIO_PIN8)
|
||||
#define GPIO_VDD_3V3_SPEKTRUM_POWER_EN /* PH2 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTH|GPIO_PIN2)
|
||||
#define GPIO_VDD_3V3_SD_CARD_EN /* PC13 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTC|GPIO_PIN13)
|
||||
|
||||
@@ -297,7 +295,7 @@
|
||||
|
||||
#define VDD_5V_PERIPH_EN(on_true) px4_arch_gpiowrite(GPIO_VDD_5V_PERIPH_nEN, !(on_true))
|
||||
#define VDD_5V_HIPOWER_EN(on_true) px4_arch_gpiowrite(GPIO_VDD_5V_HIPOWER_nEN, !(on_true))
|
||||
#define VDD_3V3_SENSORS_EN(on_true) px4_arch_gpiowrite(GPIO_VDD_3V3_SENSORS_EN, (on_true))
|
||||
#define VDD_3V3_SENSORS4_EN(on_true) px4_arch_gpiowrite(GPIO_VDD_3V3_SENSORS4_EN, (on_true))
|
||||
#define VDD_3V3_SPEKTRUM_POWER_EN(on_true) px4_arch_gpiowrite(GPIO_VDD_3V3_SPEKTRUM_POWER_EN, (on_true))
|
||||
#define READ_VDD_3V3_SPEKTRUM_POWER_EN() px4_arch_gpioread(GPIO_VDD_3V3_SPEKTRUM_POWER_EN)
|
||||
#define VDD_3V3_SD_CARD_EN(on_true) px4_arch_gpiowrite(GPIO_VDD_3V3_SD_CARD_EN, (on_true))
|
||||
@@ -455,7 +453,7 @@
|
||||
GPIO_CAN1_RX, \
|
||||
GPIO_CAN2_TX, \
|
||||
GPIO_CAN2_RX, \
|
||||
GPIO_HEATER1_OUTPUT, \
|
||||
GPIO_HEATER_OUTPUT, \
|
||||
GPIO_nPOWER_IN_A, \
|
||||
GPIO_nPOWER_IN_B, \
|
||||
GPIO_nPOWER_IN_C, \
|
||||
@@ -463,7 +461,7 @@
|
||||
GPIO_VDD_5V_PERIPH_nOC, \
|
||||
GPIO_VDD_5V_HIPOWER_nEN, \
|
||||
GPIO_VDD_5V_HIPOWER_nOC, \
|
||||
GPIO_VDD_3V3_SENSORS_EN, \
|
||||
GPIO_VDD_3V3_SENSORS4_EN, \
|
||||
GPIO_VDD_3V3_SPEKTRUM_POWER_EN, \
|
||||
GPIO_VDD_3V3_SD_CARD_EN, \
|
||||
GPIO_SYNC, \
|
||||
|
||||
@@ -107,7 +107,7 @@ __EXPORT void board_peripheral_reset(int ms)
|
||||
|
||||
VDD_5V_PERIPH_EN(false);
|
||||
board_control_spi_sensors_power(false, 0xffff);
|
||||
VDD_3V3_SENSORS_EN(false);
|
||||
VDD_3V3_SENSORS4_EN(false);
|
||||
|
||||
bool last = READ_VDD_3V3_SPEKTRUM_POWER_EN();
|
||||
/* Keep Spektum on to discharge rail*/
|
||||
@@ -122,7 +122,7 @@ __EXPORT void board_peripheral_reset(int ms)
|
||||
/* switch the peripheral rail back on */
|
||||
VDD_3V3_SPEKTRUM_POWER_EN(last);
|
||||
board_control_spi_sensors_power(true, 0xffff);
|
||||
VDD_3V3_SENSORS_EN(true);
|
||||
VDD_3V3_SENSORS4_EN(true);
|
||||
VDD_5V_PERIPH_EN(true);
|
||||
|
||||
}
|
||||
@@ -219,7 +219,7 @@ __EXPORT int board_app_initialize(uintptr_t arg)
|
||||
VDD_3V3_SD_CARD_EN(true);
|
||||
VDD_5V_PERIPH_EN(true);
|
||||
VDD_5V_HIPOWER_EN(true);
|
||||
VDD_3V3_SENSORS_EN(true);
|
||||
VDD_3V3_SENSORS4_EN(true);
|
||||
VDD_3V3_SPEKTRUM_POWER_EN(true);
|
||||
|
||||
/* Need hrt running before using the ADC */
|
||||
|
||||
@@ -49,7 +49,7 @@ constexpr px4_spi_bus_t px4_spi_buses[SPI_BUS_MAX_BUS_ITEMS] = {
|
||||
}, {GPIO::PortE, GPIO::Pin7}),
|
||||
// initSPIBus(SPI::Bus::SPI4, {
|
||||
// // no devices
|
||||
// TODO: if enabled, remove GPIO_VDD_3V3_SENSORS_EN from board_config.h
|
||||
// TODO: if enabled, remove GPIO_VDD_3V3_SENSORS4_EN from board_config.h
|
||||
// }, {GPIO::PortG, GPIO::Pin8}),
|
||||
initSPIBus(SPI::Bus::SPI5, {
|
||||
initSPIDevice(SPIDEV_FLASH(0), SPI::CS{GPIO::PortG, GPIO::Pin7})
|
||||
|
||||
@@ -104,10 +104,8 @@
|
||||
#define GPIO_CAN2_SILENT_S1 /* PH3 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTH|GPIO_PIN3)
|
||||
|
||||
/* HEATER */
|
||||
#define GPIO_HEATER_OUTPUT
|
||||
#define HEATER_NUM 1
|
||||
#define GPIO_HEATER1_OUTPUT /* PA8 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTA|GPIO_PIN8)
|
||||
#define HEATER1_OUTPUT_EN(on_true) px4_arch_gpiowrite(GPIO_HEATER1_OUTPUT, (on_true))
|
||||
#define GPIO_HEATER_OUTPUT /* PA8 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTA|GPIO_PIN8)
|
||||
#define HEATER_OUTPUT_EN(on_true) px4_arch_gpiowrite(GPIO_HEATER_OUTPUT, (on_true))
|
||||
|
||||
/* PWM */
|
||||
#define DIRECT_PWM_OUTPUT_CHANNELS 14
|
||||
@@ -214,7 +212,7 @@
|
||||
GPIO_CAN2_RX, \
|
||||
GPIO_CAN1_SILENT_S0, \
|
||||
GPIO_CAN2_SILENT_S1, \
|
||||
GPIO_HEATER1_OUTPUT, \
|
||||
GPIO_HEATER_OUTPUT, \
|
||||
GPIO_nPOWER_IN_CAN, \
|
||||
GPIO_nPOWER_IN_ADC, \
|
||||
GPIO_nPOWER_IN_C, \
|
||||
|
||||
@@ -31,4 +31,5 @@
|
||||
#
|
||||
############################################################################
|
||||
|
||||
add_subdirectory(core_heater)
|
||||
add_subdirectory(pwm_voltage)
|
||||
|
||||
+6
-8
@@ -1,6 +1,6 @@
|
||||
############################################################################
|
||||
#
|
||||
# Copyright (c) 2026 PX4 Development Team. All rights reserved.
|
||||
# Copyright (c) 2025 PX4 Development Team. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
@@ -30,12 +30,10 @@
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
px4_add_module(
|
||||
MODULE modules__task_watchdog
|
||||
MAIN task_watchdog
|
||||
MODULE drivers__core_heater
|
||||
MAIN core_heater
|
||||
COMPILE_FLAGS
|
||||
SRCS
|
||||
TaskWatchdog.cpp
|
||||
DEPENDS
|
||||
version
|
||||
)
|
||||
core_heater.cpp
|
||||
)
|
||||
@@ -0,0 +1,263 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2025 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file core_heater.cpp
|
||||
*
|
||||
*/
|
||||
|
||||
#include "core_heater.h"
|
||||
|
||||
#include <px4_platform_common/getopt.h>
|
||||
#include <px4_platform_common/log.h>
|
||||
#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
|
||||
|
||||
Core_Heater::Core_Heater() :
|
||||
ModuleParams(nullptr),
|
||||
ScheduledWorkItem(MODULE_NAME, px4::wq_configurations::lp_default)
|
||||
{
|
||||
_heater_status_pub.advertise();
|
||||
}
|
||||
|
||||
Core_Heater::~Core_Heater()
|
||||
{
|
||||
disable_core_heater();
|
||||
}
|
||||
|
||||
int Core_Heater::custom_command(int argc, char *argv[])
|
||||
{
|
||||
// Check if the driver is running.
|
||||
if (!is_running(desc)) {
|
||||
PX4_INFO("not running");
|
||||
return PX4_ERROR;
|
||||
}
|
||||
|
||||
return print_usage("Unrecognized command.");
|
||||
}
|
||||
|
||||
void Core_Heater::disable_core_heater()
|
||||
{
|
||||
// Reset heater to off state.
|
||||
px4_arch_unconfiggpio(GPIO_CORE_HEATER_OUTPUT);
|
||||
}
|
||||
|
||||
void Core_Heater::initialize_core_heater_io()
|
||||
{
|
||||
// Initialize heater to off state.
|
||||
px4_arch_configgpio(GPIO_CORE_HEATER_OUTPUT);
|
||||
}
|
||||
|
||||
void Core_Heater::core_heater_off()
|
||||
{
|
||||
CORE_HEATER_OUTPUT_EN(false);
|
||||
}
|
||||
|
||||
void Core_Heater::core_heater_on()
|
||||
{
|
||||
CORE_HEATER_OUTPUT_EN(true);
|
||||
}
|
||||
|
||||
bool Core_Heater::initialize_topics()
|
||||
{
|
||||
for (uint8_t i = 0; i < ORB_MULTI_MAX_INSTANCES; i++) {
|
||||
uORB::SubscriptionData<sensor_accel_s> sensor_accel_sub{ORB_ID(sensor_accel), i};
|
||||
|
||||
if (sensor_accel_sub.get().timestamp != 0 &&
|
||||
sensor_accel_sub.get().device_id != 0 &&
|
||||
PX4_ISFINITE(sensor_accel_sub.get().temperature)) {
|
||||
|
||||
// If the correct ID is found, exit the for-loop with _sensor_accel_sub pointing to the correct instance.
|
||||
if (sensor_accel_sub.get().device_id == (uint32_t)_param_core_temp_id.get()) {
|
||||
_sensor_accel_sub.ChangeInstance(i);
|
||||
_sensor_device_id = sensor_accel_sub.get().device_id;
|
||||
initialize_core_heater_io();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Core_Heater::Run()
|
||||
{
|
||||
if (should_exit()) {
|
||||
exit_and_cleanup(desc);
|
||||
return;
|
||||
}
|
||||
|
||||
update_params();
|
||||
|
||||
if (_sensor_device_id == 0) {
|
||||
if (!initialize_topics()) {
|
||||
// if sensor still not found try again in 1 second
|
||||
ScheduleDelayed(1_s);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
sensor_accel_s sensor_accel;
|
||||
float temperature_delta {0.f};
|
||||
|
||||
if (_core_heater_on) {
|
||||
// Turn the heater off.
|
||||
_core_heater_on = false;
|
||||
core_heater_off();
|
||||
ScheduleDelayed(_controller_period_usec - _controller_time_on_usec);
|
||||
|
||||
} else if (_sensor_accel_sub.update(&sensor_accel)) {
|
||||
// Update the current IMU sensor temperature if valid.
|
||||
if (PX4_ISFINITE(sensor_accel.temperature)) {
|
||||
temperature_delta = _param_core_imu_temp.get() - sensor_accel.temperature;
|
||||
_temperature_last = sensor_accel.temperature;
|
||||
}
|
||||
|
||||
_proportional_value = temperature_delta * _param_core_imu_temp_p.get();
|
||||
_integrator_value += temperature_delta * _param_core_imu_temp_i.get();
|
||||
|
||||
_integrator_value = math::constrain(_integrator_value, -0.25f, 0.25f);
|
||||
|
||||
_controller_time_on_usec = static_cast<int>((_param_core_imu_temp_ff.get() + _proportional_value +
|
||||
_integrator_value) * static_cast<float>(_controller_period_usec));
|
||||
|
||||
_controller_time_on_usec = math::constrain(_controller_time_on_usec, 0, _controller_period_usec);
|
||||
|
||||
if (fabsf(temperature_delta) < TEMPERATURE_TARGET_THRESHOLD) {
|
||||
_temperature_target_met = true;
|
||||
|
||||
} else {
|
||||
|
||||
_temperature_target_met = false;
|
||||
}
|
||||
|
||||
_core_heater_on = true;
|
||||
core_heater_on();
|
||||
ScheduleDelayed(_controller_time_on_usec);
|
||||
}
|
||||
|
||||
publish_status();
|
||||
}
|
||||
|
||||
void Core_Heater::publish_status()
|
||||
{
|
||||
heater_status_s status{};
|
||||
status.device_id = _sensor_device_id;
|
||||
status.heater_on = _core_heater_on;
|
||||
status.temperature_sensor = _temperature_last;
|
||||
status.temperature_target = _param_core_imu_temp.get();
|
||||
status.temperature_target_met = _temperature_target_met;
|
||||
status.controller_period_usec = _controller_period_usec;
|
||||
status.controller_time_on_usec = _controller_time_on_usec;
|
||||
status.proportional_value = _proportional_value;
|
||||
status.integrator_value = _integrator_value;
|
||||
status.feed_forward_value = _param_core_imu_temp_ff.get();
|
||||
|
||||
status.mode = heater_status_s::MODE_GPIO;
|
||||
|
||||
status.timestamp = hrt_absolute_time();
|
||||
_heater_status_pub.publish(status);
|
||||
}
|
||||
|
||||
int Core_Heater::start()
|
||||
{
|
||||
// Exit the driver if the sensor ID does not match the desired sensor.
|
||||
if (_param_core_temp_id.get() == 0) {
|
||||
PX4_ERR("Valid CORE_TEMP_ID required");
|
||||
request_stop();
|
||||
return PX4_ERROR;
|
||||
}
|
||||
|
||||
update_params(true);
|
||||
ScheduleNow();
|
||||
return PX4_OK;
|
||||
}
|
||||
|
||||
int Core_Heater::task_spawn(int argc, char *argv[])
|
||||
{
|
||||
Core_Heater *core_heater = new Core_Heater();
|
||||
|
||||
if (!core_heater) {
|
||||
PX4_ERR("driver allocation failed");
|
||||
return PX4_ERROR;
|
||||
}
|
||||
|
||||
desc.object.store(core_heater);
|
||||
desc.task_id = task_id_is_work_queue;
|
||||
|
||||
core_heater->start();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Core_Heater::update_params(const bool force)
|
||||
{
|
||||
if (_parameter_update_sub.updated() || force) {
|
||||
// clear update
|
||||
parameter_update_s param_update;
|
||||
_parameter_update_sub.copy(¶m_update);
|
||||
|
||||
// update parameters from storage
|
||||
ModuleParams::updateParams();
|
||||
}
|
||||
}
|
||||
|
||||
int Core_Heater::print_usage(const char *reason)
|
||||
{
|
||||
if (reason) {
|
||||
printf("%s\n\n", reason);
|
||||
}
|
||||
|
||||
PRINT_MODULE_DESCRIPTION(
|
||||
R"DESCR_STR(
|
||||
### Description
|
||||
Background process running periodically on the LP work queue to regulate IMU temperature at a setpoint.
|
||||
|
||||
)DESCR_STR");
|
||||
|
||||
PRINT_MODULE_USAGE_NAME("core_heater", "system");
|
||||
PRINT_MODULE_USAGE_COMMAND("start");
|
||||
PRINT_MODULE_USAGE_DEFAULT_COMMANDS();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" __EXPORT int core_heater_main(int argc, char *argv[])
|
||||
{
|
||||
return ModuleBase::main(Core_Heater::desc, argc, argv);
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2025 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file core_heater.h
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <px4_platform_common/px4_config.h>
|
||||
#include <px4_platform_common/getopt.h>
|
||||
#include <px4_platform_common/module.h>
|
||||
#include <px4_platform_common/module_params.h>
|
||||
#include <px4_platform_common/px4_work_queue/ScheduledWorkItem.hpp>
|
||||
#include <uORB/Publication.hpp>
|
||||
#include <uORB/SubscriptionInterval.hpp>
|
||||
#include <uORB/topics/heater_status.h>
|
||||
#include <uORB/topics/parameter_update.h>
|
||||
#include <uORB/topics/sensor_accel.h>
|
||||
|
||||
#include <mathlib/mathlib.h>
|
||||
|
||||
using namespace time_literals;
|
||||
|
||||
#define CONTROLLER_PERIOD_DEFAULT 10000
|
||||
#define TEMPERATURE_TARGET_THRESHOLD 2.5f
|
||||
|
||||
class Core_Heater : public ModuleBase, public ModuleParams, public px4::ScheduledWorkItem
|
||||
{
|
||||
public:
|
||||
static Descriptor desc;
|
||||
|
||||
Core_Heater();
|
||||
|
||||
virtual ~Core_Heater();
|
||||
|
||||
/**
|
||||
* @see ModuleBase::custom_command().
|
||||
* @brief main Main entry point to the module that should be
|
||||
* called directly from the module's main method.
|
||||
* @param argc The input argument count.
|
||||
* @param argv Pointer to the input argument array.
|
||||
* @return Returns 0 iff successful, -1 otherwise.
|
||||
*/
|
||||
static int custom_command(int argc, char *argv[]);
|
||||
|
||||
/**
|
||||
* @see ModuleBase::print_usage().
|
||||
* @brief Prints the module usage to the nuttshell console.
|
||||
* @param reason The requested reason for printing to console.
|
||||
*/
|
||||
static int print_usage(const char *reason = nullptr);
|
||||
|
||||
/**
|
||||
* @see ModuleBase::task_spawn().
|
||||
* @brief Initializes the class in the same context as the work queue
|
||||
* and starts the background listener.
|
||||
* @param argv Pointer to the input argument array.
|
||||
* @return Returns 0 iff successful, -1 otherwise.
|
||||
*/
|
||||
static int task_spawn(int argc, char *argv[]);
|
||||
|
||||
/**
|
||||
* @brief Initiates the heater driver work queue, starts a new background task,
|
||||
* and fails if it is already running.
|
||||
* @return Returns 1 iff start was successful.
|
||||
*/
|
||||
int start();
|
||||
|
||||
private:
|
||||
|
||||
/** Disables the heater (either by GPIO). */
|
||||
void disable_core_heater();
|
||||
|
||||
/** Turns the heater on (either by GPIO). */
|
||||
void core_heater_on();
|
||||
|
||||
/** Turns the heater off (either by GPIO). */
|
||||
void core_heater_off();
|
||||
|
||||
void initialize();
|
||||
|
||||
/** Enables / configures the heater (either by GPIO). */
|
||||
void initialize_core_heater_io();
|
||||
|
||||
/** @brief Called once to initialize uORB topics. */
|
||||
bool initialize_topics();
|
||||
|
||||
void publish_status();
|
||||
|
||||
/** @brief Calculates the heater element on/off time and schedules the next cycle. */
|
||||
void Run() override;
|
||||
|
||||
/**
|
||||
* @brief Updates and checks for updated uORB parameters.
|
||||
* @param force Boolean to determine if an update check should be forced.
|
||||
*/
|
||||
void update_params(const bool force = false);
|
||||
|
||||
/** Work queue struct for the scheduler. */
|
||||
static struct work_s _work;
|
||||
|
||||
bool _core_heater_initialized = false;
|
||||
bool _core_heater_on = false;
|
||||
bool _temperature_target_met = false;
|
||||
|
||||
int _controller_period_usec = CONTROLLER_PERIOD_DEFAULT;
|
||||
int _controller_time_on_usec = 0;
|
||||
|
||||
float _integrator_value = 0.0f;
|
||||
float _proportional_value = 0.0f;
|
||||
|
||||
uORB::Publication<heater_status_s> _heater_status_pub{ORB_ID(heater_status)};
|
||||
|
||||
uORB::SubscriptionInterval _parameter_update_sub{ORB_ID(parameter_update), 1_s};
|
||||
|
||||
uORB::Subscription _sensor_accel_sub{ORB_ID(sensor_accel)};
|
||||
|
||||
uint32_t _sensor_device_id{0};
|
||||
|
||||
float _temperature_last{NAN};
|
||||
|
||||
DEFINE_PARAMETERS(
|
||||
(ParamFloat<px4::params::CORE_IMU_TEMP_FF>) _param_core_imu_temp_ff,
|
||||
(ParamFloat<px4::params::CORE_IMU_TEMP_I>) _param_core_imu_temp_i,
|
||||
(ParamFloat<px4::params::CORE_IMU_TEMP_P>) _param_core_imu_temp_p,
|
||||
(ParamFloat<px4::params::CORE_IMU_TEMP>) _param_core_imu_temp,
|
||||
(ParamInt<px4::params::CORE_TEMP_ID>) _param_core_temp_id
|
||||
)
|
||||
};
|
||||
@@ -0,0 +1,94 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2025 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file core_heater_params.c
|
||||
* Core Heater parameters.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Target IMU device ID to regulate temperature.
|
||||
*
|
||||
* @category system
|
||||
* @group Sensors
|
||||
*/
|
||||
PARAM_DEFINE_INT32(CORE_TEMP_ID, 0);
|
||||
|
||||
/**
|
||||
* Target IMU temperature.
|
||||
*
|
||||
* @category system
|
||||
* @group Sensors
|
||||
* @unit celcius
|
||||
* @min 0
|
||||
* @max 85.0
|
||||
* @decimal 3
|
||||
*/
|
||||
PARAM_DEFINE_FLOAT(CORE_IMU_TEMP, 55.0f);
|
||||
|
||||
/**
|
||||
* IMU heater controller feedforward value.
|
||||
*
|
||||
* @category system
|
||||
* @group Sensors
|
||||
* @unit %
|
||||
* @min 0
|
||||
* @max 1.0
|
||||
* @decimal 3
|
||||
*/
|
||||
PARAM_DEFINE_FLOAT(CORE_IMU_TEMP_FF, 0.05f);
|
||||
|
||||
/**
|
||||
* IMU heater controller integrator gain value.
|
||||
*
|
||||
* @category system
|
||||
* @group Sensors
|
||||
* @unit us/C
|
||||
* @min 0
|
||||
* @max 1.0
|
||||
* @decimal 3
|
||||
*/
|
||||
PARAM_DEFINE_FLOAT(CORE_IMU_TEMP_I, 0.025f);
|
||||
|
||||
/**
|
||||
* IMU heater controller proportional gain value.
|
||||
*
|
||||
* @category system
|
||||
* @group Sensors
|
||||
* @unit us/C
|
||||
* @min 0
|
||||
* @max 2.0
|
||||
* @decimal 3
|
||||
*/
|
||||
PARAM_DEFINE_FLOAT(CORE_IMU_TEMP_P, 1.0f);
|
||||
@@ -20,14 +20,15 @@ param set-default USB_MAV_MODE 5
|
||||
param set-default UAVCAN_SUB_GPS 1
|
||||
param set-default UAVCAN_SUB_BAT 1
|
||||
|
||||
# IMU thermal control (multi-instance heater)
|
||||
# HEATER1_IMU_ID: 2818058(IIM42652 SPI1)
|
||||
# HEATER2_IMU_ID: 3014698(IIM42653 SPI5)
|
||||
# Enable IMU thermal control
|
||||
param set-default SENS_EN_THERMAL 1
|
||||
param set-default HEATER1_IMU_ID 2818058
|
||||
param set-default HEATER1_TEMP 45
|
||||
param set-default HEATER2_IMU_ID 3014698
|
||||
param set-default HEATER2_TEMP 45
|
||||
param set-default SENS_IMU_TEMP 45
|
||||
param set-default SENS_TEMP_ID 2818058
|
||||
|
||||
# CUAV core board IMU thermal control
|
||||
param set-default CORE_IMU_TEMP 45
|
||||
param set-default CORE_TEMP_ID 3014698
|
||||
core_heater start
|
||||
|
||||
# CUAV pwm voltage 3.3V/5V switch
|
||||
pwm_voltage_apply start
|
||||
|
||||
@@ -37,8 +37,6 @@ px4_add_module(
|
||||
|
||||
SRCS
|
||||
pwm_voltage.cpp
|
||||
MODULE_CONFIG
|
||||
parameters.yaml
|
||||
DEPENDS
|
||||
px4_work_queue
|
||||
)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user