Compare commits

..

5 Commits

Author SHA1 Message Date
Jacob Dahl d4bf6216e3 fix(rc): warn and deny invalid Spektrum bind sub-type
Previously, an unrecognized param2 sub-type would silently leave
dsm_bind_pulses at 0 and return the generic UNSUPPORTED ACK. Add an
explicit else-branch that logs a PX4_WARN and returns DENIED so users
get clear feedback in QGC.
2026-03-19 16:56:36 -08:00
Jacob Dahl c47fcf7390 fix(rc): check write return value in BindCRSF, guard Spektrum bind against invalid sub-type 2026-03-17 20:06:53 -08:00
Jacob Dahl 3d92ca5edf style(crsf_rc): zero-init vcmd, remove noisy comments, drop unused enum value 2026-03-17 19:16:57 -08:00
Jacob Dahl 0478395ada style(crsf_rc): use C++ style comment 2026-03-17 19:15:02 -08:00
Jacob Dahl 2bf50badf4 feat(crsf_rc): add CRSF receiver bind command
Add ability to initiate CRSF receiver binding from QGroundControl or
the NSH console. When MAV_CMD_START_RX_PAIR is received with
RC_TYPE_CRSF, the driver sends the CRSF bind command frame over UART.

Binding is rejected when armed or on singlewire configurations.

Also adds RC_TYPE and RC_SUB_TYPE constants to VehicleCommand.msg and
replaces magic numbers in DsmRc and RCInput drivers.

Based on PX4/PX4-Autopilot#23294.
2026-03-17 19:11:33 -08:00
1272 changed files with 31425 additions and 88059 deletions
-28
View File
@@ -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
-24
View File
@@ -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
-73
View File
@@ -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
```
+1 -4
View File
@@ -265,8 +265,5 @@ jobs:
with:
draft: true
prerelease: ${{ steps.upload-location.outputs.is_prerelease == 'true' }}
files: |
artifacts/*.px4
artifacts/*.deb
artifacts/**/*.sbom.spdx.json
files: artifacts/*.px4
name: ${{ steps.upload-location.outputs.uploadlocation }}
-2
View File
@@ -46,8 +46,6 @@ jobs:
fetch-depth: 0
- name: Building [${{ matrix.check }}]
env:
PX4_SBOM_DISABLE: 1
run: |
cd "$GITHUB_WORKSPACE"
git config --global --add safe.directory "$GITHUB_WORKSPACE"
+2 -2
View File
@@ -36,8 +36,8 @@ jobs:
px4io/px4-dev-ros-melodic:2021-09-08 \
bash -c '
git config --global --add safe.directory /workspace
PX4_SBOM_DISABLE=1 make px4_sitl_default
PX4_SBOM_DISABLE=1 make px4_sitl_default sitl_gazebo-classic
make px4_sitl_default
make px4_sitl_default sitl_gazebo-classic
./test/rostest_px4_run.sh \
mavros_posix_test_mission.test \
mission:=MC_mission_box \
+2 -2
View File
@@ -36,8 +36,8 @@ jobs:
px4io/px4-dev-ros-melodic:2021-09-08 \
bash -c '
git config --global --add safe.directory /workspace
PX4_SBOM_DISABLE=1 make px4_sitl_default
PX4_SBOM_DISABLE=1 make px4_sitl_default sitl_gazebo-classic
make px4_sitl_default
make px4_sitl_default sitl_gazebo-classic
./test/rostest_px4_run.sh \
mavros_posix_tests_offboard_posctl.test \
vehicle:=iris
+1 -11
View File
@@ -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
@@ -110,8 +102,6 @@ jobs:
run: ccache -s
- name: Build PX4
env:
PX4_SBOM_DISABLE: 1
run: make px4_sitl_default
- name: ccache post-run px4/firmware
run: ccache -s
-42
View File
@@ -1,42 +0,0 @@
name: SBOM License Check
on:
push:
branches:
- 'main'
- 'release/**'
- 'stable'
paths:
- '.gitmodules'
- 'Tools/ci/license-overrides.yaml'
- 'Tools/ci/generate_sbom.py'
pull_request:
branches:
- '**'
paths:
- '.gitmodules'
- 'Tools/ci/license-overrides.yaml'
- 'Tools/ci/generate_sbom.py'
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
verify-licenses:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 1
submodules: false
- name: Install PyYAML
run: pip install pyyaml --break-system-packages
- name: Verify submodule licenses
run: python3 Tools/ci/generate_sbom.py --verify-licenses --source-dir .
-132
View File
@@ -1,132 +0,0 @@
name: SBOM Monthly Audit
on:
schedule:
# First Monday of each month at 09:00 UTC
- cron: '0 9 1-7 * 1'
workflow_dispatch:
inputs:
branch:
description: 'Branch to audit (leave empty for current)'
required: false
type: string
permissions:
contents: read
issues: write
jobs:
audit:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
with:
ref: ${{ inputs.branch || github.ref }}
fetch-depth: 1
submodules: recursive
- name: Install PyYAML
run: pip install pyyaml --break-system-packages
- name: Run license verification
id: verify
continue-on-error: true
run: |
python3 Tools/ci/generate_sbom.py --verify-licenses --source-dir . 2>&1 | tee /tmp/sbom-verify.txt
echo "exit_code=$?" >> "$GITHUB_OUTPUT"
- name: Check for issues
id: check
run: |
if grep -q "NOASSERTION" /tmp/sbom-verify.txt; then
echo "has_issues=true" >> "$GITHUB_OUTPUT"
# Extract NOASSERTION lines
grep "NOASSERTION" /tmp/sbom-verify.txt | grep -v "skipped" > /tmp/sbom-issues.txt || true
# Extract copyleft lines
sed -n '/Copyleft licenses detected/,/^$/p' /tmp/sbom-verify.txt > /tmp/sbom-copyleft.txt || true
else
echo "has_issues=false" >> "$GITHUB_OUTPUT"
fi
- name: Create issue if problems found
if: steps.check.outputs.has_issues == 'true'
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const fullOutput = fs.readFileSync('/tmp/sbom-verify.txt', 'utf8');
let issueLines = '';
try {
issueLines = fs.readFileSync('/tmp/sbom-issues.txt', 'utf8');
} catch (e) {
issueLines = 'No specific NOASSERTION lines captured.';
}
let copyleftLines = '';
try {
copyleftLines = fs.readFileSync('/tmp/sbom-copyleft.txt', 'utf8');
} catch (e) {
copyleftLines = '';
}
const date = new Date().toISOString().split('T')[0];
const branch = '${{ inputs.branch || github.ref_name }}';
// Check for existing open issue to avoid duplicates
const existing = await github.rest.issues.listForRepo({
owner: context.repo.owner,
repo: context.repo.repo,
labels: 'sbom-audit',
state: 'open',
});
if (existing.data.length > 0) {
// Update existing issue with new findings
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: existing.data[0].number,
body: `## Monthly audit update (${date})\n\nIssues still present:\n\n\`\`\`\n${issueLines}\n\`\`\`\n${copyleftLines ? `\n### Copyleft warnings\n\`\`\`\n${copyleftLines}\n\`\`\`` : ''}`,
});
return;
}
await github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: `chore(sbom): license audit found NOASSERTION entries on ${branch} (${date})`,
labels: ['sbom-audit'],
assignees: ['mrpollo'],
body: [
`## SBOM Monthly Audit -- ${branch} -- ${date}`,
'',
'The automated SBOM license audit found submodules with unresolved licenses.',
'',
'### NOASSERTION entries',
'',
'```',
issueLines,
'```',
'',
copyleftLines ? `### Copyleft warnings\n\n\`\`\`\n${copyleftLines}\n\`\`\`\n` : '',
'### How to fix',
'',
'1. Check the submodule repo for a LICENSE file',
'2. Add an override to `Tools/ci/license-overrides.yaml`',
'3. Run `python3 Tools/ci/generate_sbom.py --verify-licenses --source-dir .` to confirm',
'',
'### Full output',
'',
'<details>',
'<summary>Click to expand</summary>',
'',
'```',
fullOutput,
'```',
'',
'</details>',
'',
'cc @mrpollo',
].join('\n'),
});
-1
View File
@@ -71,7 +71,6 @@ jobs:
- name: Build PX4
env:
PX4_CMAKE_BUILD_TYPE: ${{matrix.config.build_type}}
PX4_SBOM_DISABLE: 1
run: make px4_sitl_default
- name: Cache Post-Run [px4_sitl_default]
@@ -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"
@@ -1,135 +0,0 @@
name: Tag px4_msgs from PX4 release tags
on:
push:
tags:
- 'v*.*.*'
workflow_dispatch:
inputs:
tag_name:
description: 'PX4 tag to propagate (example: v1.17.0)'
required: true
type: string
permissions:
contents: read
jobs:
tag_px4_msgs:
if: github.repository == 'PX4/PX4-Autopilot'
runs-on: [runs-on,runner=4cpu-linux-x64,image=ubuntu22-full-x64,"run-id=${{ github.run_id }}",spot=false]
env:
TAG_NAME: ${{ github.event_name == 'workflow_dispatch' && inputs.tag_name || github.ref_name }}
steps:
- name: Checkout PX4 repo
uses: actions/checkout@v4
with:
fetch-depth: 0
fetch-tags: true
- name: Setup git credentials
run: |
git config --global user.name "${{ secrets.PX4BUILDBOT_USER }}"
git config --global user.email "${{ secrets.PX4BUILDBOT_EMAIL }}"
- name: Resolve release branch from tag
id: tag_info
shell: bash
run: |
set -euo pipefail
if [[ ! "${TAG_NAME}" =~ ^v([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then
echo "Tag format is not stable vX.Y.Z, skipping: ${TAG_NAME}"
echo "should_run=false" >> "$GITHUB_OUTPUT"
exit 0
fi
echo "should_run=true" >> "$GITHUB_OUTPUT"
major="${BASH_REMATCH[1]}"
minor="${BASH_REMATCH[2]}"
release_branch="release/${major}.${minor}"
git show-ref --verify --quiet "refs/heads/${release_branch}" || {
echo "PX4 branch ${release_branch} not found"
exit 1
}
tag_date="$(git for-each-ref --format='%(creatordate:iso8601)' "refs/tags/${TAG_NAME}")"
if [[ -z "${tag_date}" ]]; then
echo "Unable to resolve tag date for ${TAG_NAME}"
exit 1
fi
echo "release_branch=${release_branch}" >> "$GITHUB_OUTPUT"
echo "tag_date=${tag_date}" >> "$GITHUB_OUTPUT"
- name: Clone px4_msgs repo
if: steps.tag_info.outputs.should_run == 'true'
run: |
git clone https://${{ secrets.PX4BUILTBOT_PERSONAL_ACCESS_TOKEN }}@github.com/PX4/px4_msgs.git
- name: Checkout matching px4_msgs release branch
if: steps.tag_info.outputs.should_run == 'true'
shell: bash
run: |
set -euo pipefail
cd px4_msgs
release_branch="${{ steps.tag_info.outputs.release_branch }}"
if git show-ref --verify --quiet "refs/remotes/origin/${release_branch}"; then
git checkout -B "${release_branch}" "origin/${release_branch}"
else
echo "px4_msgs branch ${release_branch} does not exist"
exit 1
fi
- name: Verify msg and srv trees are identical
if: steps.tag_info.outputs.should_run == 'true'
shell: bash
run: |
set -euo pipefail
release_branch="${{ steps.tag_info.outputs.release_branch }}"
git checkout "${release_branch}"
# Use the same synchronization logic as sync_to_px4_msgs.yml,
# then verify there are no changes in px4_msgs.
rm -f px4_msgs/msg/*.msg
rm -f px4_msgs/msg/versioned/*.msg
rm -f px4_msgs/srv/*.srv
rm -f px4_msgs/srv/versioned/*.srv
cp msg/*.msg px4_msgs/msg/
cp msg/versioned/*.msg px4_msgs/msg/ || true
cp srv/*.srv px4_msgs/srv/
cp srv/versioned/*.srv px4_msgs/srv/ || true
if ! git -C px4_msgs diff --exit-code -- msg srv; then
echo "Message/service definitions differ between PX4 ${release_branch} and px4_msgs ${release_branch}"
exit 1
fi
- name: Create and push tag in px4_msgs
if: steps.tag_info.outputs.should_run == 'true'
shell: bash
run: |
set -euo pipefail
cd px4_msgs
target="$(git rev-parse HEAD)"
existing_target="$(git rev-parse "refs/tags/${TAG_NAME}^{}" 2>/dev/null || true)"
if [[ -n "${existing_target}" ]]; then
if [[ "${existing_target}" == "${target}" ]]; then
echo "Tag ${TAG_NAME} already exists on ${target}; nothing to do"
exit 0
fi
echo "Tag ${TAG_NAME} already exists on ${existing_target}, expected ${target}"
exit 1
fi
GIT_COMMITTER_DATE="${{ steps.tag_info.outputs.tag_date }}" \
git tag -a "${TAG_NAME}" "${target}" \
-m "PX4 msgs and srvs definitions matching PX4 stable release ${TAG_NAME#v}"
git push origin "refs/tags/${TAG_NAME}"
-3
View File
@@ -112,6 +112,3 @@ keys/
# metadata
_emscripten_sdk/
# virtual Python environment
.venv
+1 -9
View File
@@ -240,15 +240,8 @@ if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE ${PX4_BUILD_TYPE} CACHE STRING "Build type" FORCE)
endif()
if(CONFIG_BOARD_SUPPORT_FORTIFIED_TOOLCHAIN)
set(PX4_DEBUG_OPT_LEVEL -Og)
message(STATUS "fortified toolchain support enabled: PX4_DEBUG_OPT_LEVEL=${PX4_DEBUG_OPT_LEVEL}")
else()
set(PX4_DEBUG_OPT_LEVEL -O0)
endif()
if((CMAKE_BUILD_TYPE STREQUAL "Debug") OR (CMAKE_BUILD_TYPE STREQUAL "Coverage"))
set(MAX_CUSTOM_OPT_LEVEL ${PX4_DEBUG_OPT_LEVEL})
set(MAX_CUSTOM_OPT_LEVEL -O0)
elseif(CMAKE_BUILD_TYPE MATCHES "Sanitizer")
set(MAX_CUSTOM_OPT_LEVEL -O1)
elseif(CMAKE_BUILD_TYPE MATCHES "Release")
@@ -491,7 +484,6 @@ include(bloaty)
include(metadata)
include(package)
include(sbom)
# install python requirements using configured python
add_custom_target(install_python_requirements
-10
View File
@@ -67,16 +67,6 @@ menu "Toolchain"
help
Enables Cmake Release for -O3 optimization
config BOARD_SUPPORT_FORTIFIED_TOOLCHAIN
bool "Fortified toolchain support"
default n
help
Enable compatibility with toolchains that define
_FORTIFY_SOURCE.
This switches PX4_DEBUG_OPT_LEVEL from -O0 to -Og. Keep this
disabled unless the fortified toolchain requires optimization.
config BOARD_ROMFSROOT
string "ROMFSROOT"
default "px4fmu_common"
+1 -21
View File
@@ -162,12 +162,6 @@ else
endif
# Prefer the interpreter from an active Python virtual environment.
# Otherwise leave PYTHON_EXECUTABLE unset and let CMake resolve Python.
ifneq ($(strip $(VIRTUAL_ENV)),)
PYTHON_EXECUTABLE ?= $(VIRTUAL_ENV)/bin/python
endif
# Pick up specific Python path if set
ifdef PYTHON_EXECUTABLE
override CMAKE_ARGS += -DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE}
@@ -232,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
@@ -554,8 +535,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
@@ -18,7 +18,6 @@ param set-default SENS_EN_BAROSIM 1
param set-default SENS_EN_MAGSIM 1
param set SIH_VEHICLE_TYPE 4
param set-default MAV_TYPE 13
# Symmetric hexacopter X clockwise motor numbering
param set-default CA_ROTOR_COUNT 6
+3 -3
View File
@@ -119,11 +119,11 @@ else
param set SYS_AUTOCONFIG 1
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, total flight time, flight UUID
param reset_all SYS_AUTOSTART SYS_PARAM_VER RC* CAL_* LND_FLIGHT* TC_* COM_FLIGHT*
set AUTOCNF yes
fi
+1 -1
View File
@@ -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
+7 -10
View File
@@ -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, total flight time, flight UUID
param reset_all SYS_AUTOSTART SYS_PARAM_VER RC* CAL_* LND_FLIGHT* TC_* COM_FLIGHT*
fi
#
@@ -633,15 +633,12 @@ else
#
# Start the VTX services.
#
if ! param compare -s 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.
+1 -1
View File
@@ -1,4 +1,4 @@
#!/usr/bin/env bash
#! /bin/bash
# exit when any command fails
set -e
+1 -1
View File
@@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/bin/bash
if [[ $# -eq 0 ]] ; then
exit 0
+1 -1
View File
@@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/bin/bash
# Flash PX4 to a device running AuterionOS in the local network
if [ "$1" == "-h" ] || [ "$1" == "--help" ] || [ $# -lt 2 ]; then
echo "Usage: $0 -f <firmware.px4|.elf> [-c <configuration_dir>] -d <IP/Device> [-u <user>] [-p <ssh_port>] [--revert]"
+1 -1
View File
@@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/bin/bash
# This script is meant to be used by the build_all.yml workflow in a github runner
# Please only modify if you know what you are doing
set -e
+1 -1
View File
@@ -1,4 +1,4 @@
#!/usr/bin/env bash
#! /bin/bash
# Copy a git diff between two commits if msg versioning is added
DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
-59
View File
@@ -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("============================")
-603
View File
@@ -1,603 +0,0 @@
#!/usr/bin/env python3
"""Generate SPDX 2.3 JSON SBOM for a PX4 firmware build.
Produces one SBOM per board target containing:
- PX4 firmware as the primary package
- Git submodules as CONTAINS dependencies
- Python build requirements as BUILD_DEPENDENCY_OF packages
- Board-specific modules as CONTAINS packages
Requires PyYAML (pyyaml) for loading license overrides.
"""
import argparse
import configparser
import json
import re
import subprocess
import uuid
from datetime import datetime, timezone
from pathlib import Path
import yaml
# Ordered most-specific first: all keywords must appear for a match.
LICENSE_PATTERNS = [
# Copyleft licenses first (more specific keywords prevent false matches)
("GPL-3.0-only", ["GNU GENERAL PUBLIC LICENSE", "Version 3"]),
("GPL-2.0-only", ["GNU GENERAL PUBLIC LICENSE", "Version 2"]),
("LGPL-3.0-only", ["GNU LESSER GENERAL PUBLIC LICENSE", "Version 3"]),
("LGPL-2.1-only", ["GNU Lesser General Public License", "Version 2.1"]),
("AGPL-3.0-only", ["GNU AFFERO GENERAL PUBLIC LICENSE", "Version 3"]),
# Permissive licenses
("Apache-2.0", ["Apache License", "Version 2.0"]),
("MIT", ["Permission is hereby granted"]),
("BSD-3-Clause", ["Redistribution and use", "Neither the name"]),
("BSD-2-Clause", ["Redistribution and use", "THIS SOFTWARE IS PROVIDED"]),
("ISC", ["Permission to use, copy, modify, and/or distribute"]),
("EPL-2.0", ["Eclipse Public License", "2.0"]),
("Unlicense", ["The Unlicense", "unlicense.org"]),
]
COPYLEFT_LICENSES = {
"GPL-2.0-only", "GPL-3.0-only",
"LGPL-2.1-only", "LGPL-3.0-only",
"AGPL-3.0-only",
}
def load_license_overrides(source_dir):
"""Load license overrides and comments from YAML config file.
Returns (overrides, comments) dicts mapping submodule path to values.
Falls back to empty dicts if the file is missing.
"""
yaml_path = source_dir / "Tools" / "ci" / "license-overrides.yaml"
if not yaml_path.exists():
return {}, {}
with open(yaml_path) as f:
data = yaml.safe_load(f)
overrides = {}
comments = {}
for path, entry in (data.get("overrides") or {}).items():
overrides[path] = entry["license"]
if "comment" in entry:
comments[path] = entry["comment"]
return overrides, comments
LICENSE_FILENAMES = ["LICENSE", "LICENSE.md", "LICENSE.txt", "LICENCE", "LICENCE.md", "COPYING", "COPYING.md"]
def detect_license(submodule_dir):
"""Auto-detect SPDX license ID from LICENSE/COPYING file in a directory.
Reads the first 100 lines of the first license file found and matches
keywords against LICENSE_PATTERNS. Returns 'NOASSERTION' if no file
is found or no pattern matches.
"""
for fname in LICENSE_FILENAMES:
license_file = submodule_dir / fname
if license_file.is_file():
try:
lines = license_file.read_text(errors="replace").splitlines()[:100]
text = "\n".join(lines)
except OSError:
continue
text_upper = text.upper()
for spdx_id_val, keywords in LICENSE_PATTERNS:
if all(kw.upper() in text_upper for kw in keywords):
return spdx_id_val
return "NOASSERTION"
return "NOASSERTION"
def get_submodule_license(source_dir, sub_path, license_overrides):
"""Return the SPDX license for a submodule: override > auto-detect."""
if sub_path in license_overrides:
return license_overrides[sub_path]
return detect_license(source_dir / sub_path)
def spdx_id(name: str) -> str:
"""Convert a name to a valid SPDX identifier (letters, digits, dots, hyphens)."""
return re.sub(r"[^a-zA-Z0-9.\-]", "-", name)
def parse_gitmodules(source_dir):
"""Parse .gitmodules and return list of {name, path, url}."""
gitmodules_path = source_dir / ".gitmodules"
if not gitmodules_path.exists():
return []
config = configparser.ConfigParser()
config.read(str(gitmodules_path))
submodules = []
for section in config.sections():
if section.startswith("submodule "):
name = section.split('"')[1] if '"' in section else section.split(" ", 1)[1]
path = config.get(section, "path", fallback="")
url = config.get(section, "url", fallback="")
submodules.append({"name": name, "path": path, "url": url})
return submodules
def get_submodule_commits(source_dir):
"""Get commit hashes for all submodules via git ls-tree -r (works without init)."""
try:
result = subprocess.run(
["git", "ls-tree", "-r", "HEAD"],
cwd=str(source_dir),
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
check=True,
)
except (subprocess.CalledProcessError, FileNotFoundError):
return {}
commits = {}
for line in result.stdout.splitlines():
parts = line.split()
if len(parts) >= 4 and parts[1] == "commit":
commits[parts[3]] = parts[2]
return commits
def get_git_info(source_dir: Path) -> dict:
"""Get PX4 git version and hash."""
info = {"version": "unknown", "hash": "unknown"}
try:
result = subprocess.run(
["git", "describe", "--always", "--tags", "--dirty"],
cwd=str(source_dir),
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
check=True,
)
info["version"] = result.stdout.strip()
except (subprocess.CalledProcessError, FileNotFoundError):
pass
try:
result = subprocess.run(
["git", "rev-parse", "HEAD"],
cwd=str(source_dir),
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
check=True,
)
info["hash"] = result.stdout.strip()
except (subprocess.CalledProcessError, FileNotFoundError):
pass
return info
def parse_requirements(requirements_path):
"""Parse pip requirements.txt into list of {name, version_spec}."""
if not requirements_path.exists():
return []
deps = []
for line in requirements_path.read_text().splitlines():
line = line.strip()
if not line or line.startswith("#") or line.startswith("-"):
continue
# Split on version specifiers
match = re.match(r"^([a-zA-Z0-9_\-]+)(.*)?$", line)
if match:
deps.append({
"name": match.group(1),
"version_spec": match.group(2).strip() if match.group(2) else "",
})
return deps
def read_module_list(modules_file, source_dir):
"""Read board-specific module list from file.
Paths may be absolute; they are converted to relative paths under src/.
Duplicates are removed while preserving order.
"""
if not modules_file or not modules_file.exists():
return []
seen = set()
modules = []
source_str = str(source_dir.resolve()) + "/"
for line in modules_file.read_text().splitlines():
path = line.strip()
if not path or path.startswith("#"):
continue
# Convert absolute path to relative
if path.startswith(source_str):
path = path[len(source_str):]
if path not in seen:
seen.add(path)
modules.append(path)
return modules
def make_purl(pkg_type: str, namespace: str, name: str, version: str = "") -> str:
"""Construct a Package URL (purl)."""
purl = f"pkg:{pkg_type}/{namespace}/{name}"
if version:
purl += f"@{version}"
return purl
def extract_git_host_org_repo(url):
"""Extract host type, org, and repo from a git URL.
Returns (host, org, repo) where host is 'github', 'gitlab', or ''.
"""
match = re.search(r"github\.com[:/]([^/]+)/([^/]+?)(?:\.git)?$", url)
if match:
return "github", match.group(1), match.group(2)
match = re.search(r"gitlab\.com[:/](.+?)/([^/]+?)(?:\.git)?$", url)
if match:
return "gitlab", match.group(1), match.group(2)
return "", "", ""
def generate_sbom(source_dir, board, modules_file, compiler, platform=""):
"""Generate a complete SPDX 2.3 JSON document."""
license_overrides, license_comments = load_license_overrides(source_dir)
git_info = get_git_info(source_dir)
timestamp = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
# Deterministic namespace using UUID5 from git hash + board
ns_seed = f"{git_info['hash']}:{board}"
doc_namespace = f"https://spdx.org/spdxdocs/{board}-{uuid.uuid5(uuid.NAMESPACE_URL, ns_seed)}"
doc = {
"spdxVersion": "SPDX-2.3",
"dataLicense": "CC0-1.0",
"SPDXID": "SPDXRef-DOCUMENT",
"name": f"PX4 Firmware SBOM for {board}",
"documentNamespace": doc_namespace,
"creationInfo": {
"created": timestamp,
"creators": [
"Tool: px4-generate-sbom",
"Organization: Dronecode Foundation",
],
"licenseListVersion": "3.22",
},
"packages": [],
"relationships": [],
}
# Primary package: PX4 firmware
primary_spdx_id = f"SPDXRef-PX4-{spdx_id(board)}"
doc["packages"].append({
"SPDXID": primary_spdx_id,
"name": board,
"versionInfo": git_info["version"],
"packageFileName": f"{board}.px4",
"supplier": "Organization: Dronecode Foundation",
"downloadLocation": "https://github.com/PX4/PX4-Autopilot",
"filesAnalyzed": False,
"primaryPackagePurpose": "FIRMWARE",
"licenseConcluded": "BSD-3-Clause",
"licenseDeclared": "BSD-3-Clause",
"copyrightText": "Copyright (c) PX4 Development Team",
"externalRefs": [
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceType": "purl",
"referenceLocator": make_purl(
"github", "PX4", "PX4-Autopilot", git_info["version"]
),
}
],
})
doc["relationships"].append({
"spdxElementId": "SPDXRef-DOCUMENT",
"relationshipType": "DESCRIBES",
"relatedSpdxElement": primary_spdx_id,
})
# Git submodules (filtered to those relevant to this board's modules)
submodules = parse_gitmodules(source_dir)
submodule_commits = get_submodule_commits(source_dir)
modules = read_module_list(modules_file, source_dir)
def submodule_is_relevant(sub_path):
"""A submodule is relevant if any board module path overlaps with it."""
# NuttX platform submodules are only relevant for NuttX builds
if sub_path.startswith("platforms/nuttx/"):
return platform in ("nuttx", "")
if not modules:
return True # no module list means include all
# Other platform submodules are always relevant
if sub_path.startswith("platforms/"):
return True
for mod in modules:
# Module is under this submodule, or submodule is under a module
if mod.startswith(sub_path + "/") or sub_path.startswith(mod + "/"):
return True
return False
for sub in submodules:
if not submodule_is_relevant(sub["path"]):
continue
sub_path = sub["path"]
sub_path_id = sub_path.replace("/", "-")
sub_spdx_id = f"SPDXRef-Submodule-{spdx_id(sub_path_id)}"
commit = submodule_commits.get(sub_path, "unknown")
license_id = get_submodule_license(source_dir, sub_path, license_overrides)
host, org, repo = extract_git_host_org_repo(sub["url"])
download = sub["url"] if sub["url"] else "NOASSERTION"
# Use repo name from URL for human-readable name, fall back to last path component
display_name = repo if repo else sub_path.rsplit("/", 1)[-1]
pkg = {
"SPDXID": sub_spdx_id,
"name": display_name,
"versionInfo": commit,
"supplier": f"Organization: {org}" if org else "NOASSERTION",
"downloadLocation": download,
"filesAnalyzed": False,
"licenseConcluded": license_id,
"licenseDeclared": license_id,
"copyrightText": "NOASSERTION",
}
comment = license_comments.get(sub_path)
if comment:
pkg["licenseComments"] = comment
if host and org and repo:
pkg["externalRefs"] = [
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceType": "purl",
"referenceLocator": make_purl(host, org, repo, commit),
}
]
doc["packages"].append(pkg)
doc["relationships"].append({
"spdxElementId": primary_spdx_id,
"relationshipType": "CONTAINS",
"relatedSpdxElement": sub_spdx_id,
})
# Python build dependencies
requirements_path = source_dir / "Tools" / "setup" / "requirements.txt"
py_deps = parse_requirements(requirements_path)
for dep in py_deps:
dep_name = dep["name"]
dep_spdx_id = f"SPDXRef-PyDep-{spdx_id(dep_name)}"
version_str = dep["version_spec"] if dep["version_spec"] else "NOASSERTION"
doc["packages"].append({
"SPDXID": dep_spdx_id,
"name": dep_name,
"versionInfo": version_str,
"supplier": "NOASSERTION",
"downloadLocation": f"https://pypi.org/project/{dep_name}/",
"filesAnalyzed": False,
"primaryPackagePurpose": "APPLICATION",
"licenseConcluded": "NOASSERTION",
"licenseDeclared": "NOASSERTION",
"copyrightText": "NOASSERTION",
"externalRefs": [
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceType": "purl",
"referenceLocator": f"pkg:pypi/{dep_name}",
}
],
})
doc["relationships"].append({
"spdxElementId": dep_spdx_id,
"relationshipType": "BUILD_DEPENDENCY_OF",
"relatedSpdxElement": primary_spdx_id,
})
# Board-specific modules (already read above for submodule filtering)
for mod in modules:
mod_path_id = mod.replace("/", "-")
mod_spdx_id = f"SPDXRef-Module-{spdx_id(mod_path_id)}"
# Derive short name: strip leading src/ for readability
display_name = mod
if display_name.startswith("src/"):
display_name = display_name[4:]
doc["packages"].append({
"SPDXID": mod_spdx_id,
"name": display_name,
"versionInfo": git_info["version"],
"supplier": "Organization: Dronecode Foundation",
"downloadLocation": "https://github.com/PX4/PX4-Autopilot",
"filesAnalyzed": False,
"licenseConcluded": "BSD-3-Clause",
"licenseDeclared": "BSD-3-Clause",
"copyrightText": "NOASSERTION",
})
doc["relationships"].append({
"spdxElementId": primary_spdx_id,
"relationshipType": "CONTAINS",
"relatedSpdxElement": mod_spdx_id,
})
# Compiler as a build tool
if compiler:
compiler_spdx_id = f"SPDXRef-Compiler-{spdx_id(compiler)}"
doc["packages"].append({
"SPDXID": compiler_spdx_id,
"name": compiler,
"versionInfo": "NOASSERTION",
"supplier": "NOASSERTION",
"downloadLocation": "NOASSERTION",
"filesAnalyzed": False,
"primaryPackagePurpose": "APPLICATION",
"licenseConcluded": "NOASSERTION",
"licenseDeclared": "NOASSERTION",
"copyrightText": "NOASSERTION",
})
doc["relationships"].append({
"spdxElementId": compiler_spdx_id,
"relationshipType": "BUILD_TOOL_OF",
"relatedSpdxElement": primary_spdx_id,
})
return doc
def verify_licenses(source_dir):
"""Verify license detection for all submodules. Returns exit code."""
license_overrides, _ = load_license_overrides(source_dir)
submodules = parse_gitmodules(source_dir)
if not submodules:
print("No submodules found in .gitmodules")
return 1
has_noassertion = False
print(f"{'Submodule Path':<65} {'Detected':<16} {'Override':<16} {'Final'}")
print("-" * 115)
for sub in submodules:
sub_path = sub["path"]
sub_dir = source_dir / sub_path
checked_out = sub_dir.is_dir() and any(sub_dir.iterdir())
if not checked_out:
detected = "(not checked out)"
override = license_overrides.get(sub_path, "")
final = override if override else "NOASSERTION"
else:
detected = detect_license(sub_dir)
override = license_overrides.get(sub_path, "")
final = override if override else detected
if final == "NOASSERTION" and checked_out:
has_noassertion = True
marker = " <-- NOASSERTION"
elif final == "NOASSERTION" and not checked_out:
marker = " (skipped)"
else:
marker = ""
print(f"{sub_path:<65} {str(detected):<16} {str(override) if override else '':<16} {final}{marker}")
# Copyleft warning (informational, not a failure)
copyleft_found = []
for sub in submodules:
sub_path = sub["path"]
sub_dir = source_dir / sub_path
checked_out = sub_dir.is_dir() and any(sub_dir.iterdir())
override = license_overrides.get(sub_path, "")
if checked_out:
final_lic = override if override else detect_license(sub_dir)
else:
final_lic = override if override else "NOASSERTION"
for cl in COPYLEFT_LICENSES:
if cl in final_lic:
copyleft_found.append((sub_path, final_lic))
break
print()
if copyleft_found:
print("Copyleft licenses detected (informational):")
for path, lic in copyleft_found:
print(f" {path}: {lic}")
print()
if has_noassertion:
print("FAIL: Some submodules resolved to NOASSERTION. "
"Add an entry to Tools/ci/license-overrides.yaml or check the LICENSE file.")
return 1
print("OK: All submodules have a resolved license.")
return 0
def main():
parser = argparse.ArgumentParser(
description="Generate SPDX 2.3 JSON SBOM for PX4 firmware"
)
parser.add_argument(
"--source-dir",
type=Path,
default=Path.cwd(),
help="PX4 source directory (default: cwd)",
)
parser.add_argument(
"--verify-licenses",
action="store_true",
help="Verify license detection for all submodules and exit",
)
parser.add_argument(
"--board",
default=None,
help="Board target name (e.g. px4_fmu-v5x_default)",
)
parser.add_argument(
"--modules-file",
type=Path,
default=None,
help="Path to config_module_list.txt",
)
parser.add_argument(
"--compiler",
default="",
help="Compiler identifier (e.g. arm-none-eabi-gcc)",
)
parser.add_argument(
"--platform",
default="",
help="PX4 platform (nuttx, posix, qurt). Filters platform-specific submodules.",
)
parser.add_argument(
"--output",
type=Path,
default=None,
help="Output SBOM file path",
)
args = parser.parse_args()
if args.verify_licenses:
raise SystemExit(verify_licenses(args.source_dir))
if not args.board:
parser.error("--board is required when not using --verify-licenses")
if not args.output:
parser.error("--output is required when not using --verify-licenses")
sbom = generate_sbom(
source_dir=args.source_dir,
board=args.board,
modules_file=args.modules_file,
compiler=args.compiler,
platform=args.platform,
)
args.output.parent.mkdir(parents=True, exist_ok=True)
with open(args.output, "w") as f:
json.dump(sbom, f, indent=2)
f.write("\n")
pkg_count = len(sbom["packages"])
print(f"SBOM generated: {args.output} ({pkg_count} packages)")
if __name__ == "__main__":
main()
-163
View File
@@ -1,163 +0,0 @@
#!/usr/bin/env python3
"""Inspect a PX4 SPDX SBOM file.
Usage:
inspect_sbom.py <sbom.spdx.json> # full summary
inspect_sbom.py <sbom.spdx.json> search <term> # search packages by name
inspect_sbom.py <sbom.spdx.json> ntia # NTIA minimum elements check
inspect_sbom.py <sbom.spdx.json> licenses # license summary
inspect_sbom.py <sbom.spdx.json> list <type> # list packages (Submodule|PyDep|Module|all)
"""
import json
import sys
from collections import Counter
from pathlib import Path
def load(path):
return json.loads(Path(path).read_text())
def pkg_type(pkg):
spdx_id = pkg["SPDXID"]
for prefix in ("Submodule", "PyDep", "Module", "Compiler", "PX4"):
if f"-{prefix}-" in spdx_id or spdx_id.startswith(f"SPDXRef-{prefix}"):
return prefix
return "Other"
def summary(doc):
print(f"spdxVersion: {doc['spdxVersion']}")
print(f"name: {doc['name']}")
print(f"namespace: {doc['documentNamespace']}")
print(f"created: {doc['creationInfo']['created']}")
print(f"creators: {', '.join(doc['creationInfo']['creators'])}")
print()
types = Counter(pkg_type(p) for p in doc["packages"])
print(f"Packages: {len(doc['packages'])}")
for t, c in types.most_common():
print(f" {t}: {c}")
print()
rc = Counter(r["relationshipType"] for r in doc["relationships"])
print(f"Relationships: {len(doc['relationships'])}")
for t, n in rc.most_common():
print(f" {t}: {n}")
print()
primary = doc["packages"][0]
print(f"Primary package:")
print(f" name: {primary['name']}")
print(f" version: {primary['versionInfo']}")
print(f" purpose: {primary.get('primaryPackagePurpose', 'N/A')}")
print(f" license: {primary['licenseDeclared']}")
print()
noassert = [
p["name"]
for p in doc["packages"]
if pkg_type(p) == "Submodule" and p["licenseDeclared"] == "NOASSERTION"
]
if noassert:
print(f"WARNING: {len(noassert)} submodules with NOASSERTION license:")
for n in noassert:
print(f" - {n}")
else:
print("All submodule licenses mapped")
print(f"\nFile size: {Path(sys.argv[1]).stat().st_size // 1024}KB")
def search(doc, term):
term = term.lower()
found = [p for p in doc["packages"] if term in p["name"].lower()]
if not found:
print(f"No packages matching '{term}'")
return
print(f"Found {len(found)} packages matching '{term}':\n")
for p in found:
print(json.dumps(p, indent=2))
print()
def ntia_check(doc):
required = ["SPDXID", "name", "versionInfo", "supplier", "downloadLocation"]
missing = []
for p in doc["packages"]:
for f in required:
if f not in p or p[f] in ("", None):
missing.append((p["name"], f))
if missing:
print(f"FAIL: {len(missing)} missing fields:")
for name, field in missing:
print(f" {name}: missing {field}")
else:
print(f"PASS: All {len(doc['packages'])} packages have required fields")
print(f"\nCreators: {doc['creationInfo']['creators']}")
print(f"Timestamp: {doc['creationInfo']['created']}")
rels = [r for r in doc["relationships"] if r["relationshipType"] == "DESCRIBES"]
print(f"DESCRIBES relationships: {len(rels)}")
return len(missing) == 0
def licenses(doc):
by_license = {}
for p in doc["packages"]:
lic = p.get("licenseDeclared", "NOASSERTION")
by_license.setdefault(lic, []).append(p["name"])
for lic in sorted(by_license.keys()):
names = by_license[lic]
print(f"\n{lic} ({len(names)}):")
for n in sorted(names):
print(f" {n}")
def list_packages(doc, filter_type):
filter_type = filter_type.lower()
for p in sorted(doc["packages"], key=lambda x: x["name"]):
t = pkg_type(p)
if filter_type != "all" and t.lower() != filter_type:
continue
lic = p.get("licenseDeclared", "?")
ver = p["versionInfo"][:20] if len(p["versionInfo"]) > 20 else p["versionInfo"]
print(f" {t:10s} {p['name']:50s} {ver:20s} {lic}")
def main():
if len(sys.argv) < 2:
print(__doc__)
sys.exit(1)
doc = load(sys.argv[1])
cmd = sys.argv[2] if len(sys.argv) > 2 else "summary"
if cmd == "summary":
summary(doc)
elif cmd == "search":
if len(sys.argv) < 4:
print("Usage: inspect_sbom.py <file> search <term>")
sys.exit(1)
search(doc, sys.argv[3])
elif cmd == "ntia":
if not ntia_check(doc):
sys.exit(1)
elif cmd == "licenses":
licenses(doc)
elif cmd == "list":
filter_type = sys.argv[3] if len(sys.argv) > 3 else "all"
list_packages(doc, filter_type)
else:
print(f"Unknown command: {cmd}")
print(__doc__)
sys.exit(1)
if __name__ == "__main__":
main()
-56
View File
@@ -1,56 +0,0 @@
# SPDX license overrides for submodules where auto-detection fails or is wrong.
# Each entry maps a submodule path to its SPDX license identifier and an
# optional comment explaining why the override exists.
#
# Run `python3 Tools/ci/generate_sbom.py --verify-licenses` to validate.
overrides:
src/modules/mavlink/mavlink:
license: "LGPL-3.0-only AND MIT"
comment: "Generator is LGPL-3.0; PX4 ships only MIT-licensed generated headers."
src/lib/cdrstream/cyclonedds:
license: "EPL-2.0 OR BSD-3-Clause"
comment: >-
Dual-licensed. PX4 elects BSD-3-Clause.
No board currently enables CONFIG_LIB_CDRSTREAM.
src/lib/cdrstream/rosidl:
license: "Apache-2.0"
src/lib/crypto/monocypher:
license: "BSD-2-Clause OR CC0-1.0"
comment: >-
Dual-licensed. LICENCE.md offers BSD-2-Clause with CC0-1.0 as
public domain fallback.
src/lib/crypto/libtomcrypt:
license: "Unlicense"
comment: "Public domain dedication. Functionally equivalent to Unlicense."
src/lib/crypto/libtommath:
license: "Unlicense"
comment: "Public domain dedication. Functionally equivalent to Unlicense."
platforms/nuttx/NuttX/nuttx:
license: "Apache-2.0"
comment: >-
Composite LICENSE (6652 lines) includes BSD/MIT/ISC sub-components.
Primary license is Apache-2.0. NOTICE file contains FAT LFN patent warnings.
platforms/nuttx/NuttX/apps:
license: "Apache-2.0"
boards/modalai/voxl2/libfc-sensor-api:
license: "NOASSERTION"
comment: >-
No LICENSE file in repo. README describes it as public interface
for proprietary sensor library.
boards/modalai/voxl2/src/lib/mpa/libmodal-json:
license: "LGPL-3.0-only"
comment: "LGPL-3.0 weak copyleft. Used via header includes in VOXL2 mpa library."
boards/modalai/voxl2/src/lib/mpa/libmodal-pipe:
license: "LGPL-3.0-only"
comment: "LGPL-3.0 weak copyleft. Used via header includes in VOXL2 mpa library."
+1 -4
View File
@@ -1,9 +1,8 @@
#!/usr/bin/env bash
#!/bin/bash
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#*/}
@@ -29,8 +28,6 @@ for build_dir_path in build/*/ ; do
# Events
mkdir -p artifacts/$build_dir/events/
cp $build_dir_path/events/all_events.json.xz artifacts/$build_dir/events/ 2>/dev/null || true
# SBOM
cp $build_dir_path/*.sbom.spdx.json artifacts/$build_dir/ 2>/dev/null || true
ls -la artifacts/$build_dir
echo "----------"
done
+1 -1
View File
@@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/bin/bash
# This script runs the fuzz tests from a given binary for a certain amount of time
set -e
+1 -1
View File
@@ -1,4 +1,4 @@
#!/usr/bin/env bash
#! /bin/bash
# Copy msgs and the message translation node into a ROS workspace directory
DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
+1 -1
View File
@@ -1,4 +1,4 @@
#!/usr/bin/env bash
#! /bin/bash
if [ -z ${PX4_DOCKER_REPO+x} ]; then
PX4_DOCKER_REPO="px4io/px4-dev:v1.17.0-beta1"
+3 -13
View File
@@ -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():
+1 -4
View File
@@ -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']))
+1 -3
View File
@@ -316,9 +316,7 @@ 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"
+1 -1
View File
@@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/bin/bash
# Script to run ShellCheck (a static analysis tool for shell scripts) over a
# script directory
+1 -1
View File
@@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/bin/bash
GREEN='\033[0;32m'
NO_COLOR='\033[0m' # No Color
-7
View File
@@ -79,13 +79,6 @@ if [[ $INSTALL_SIM == "--sim-tools" ]]; then
elif [[ $REINSTALL_FORMULAS == "--reinstall" ]]; then
brew reinstall px4-sim
fi
# jMAVSim requires a JDK (Java 17 LTS recommended)
if ! brew ls --versions openjdk@17 > /dev/null; then
echo "[macos.sh] Installing OpenJDK 17 (required for jMAVSim)"
brew install openjdk@17
sudo ln -sfn $(brew --prefix openjdk@17)/libexec/openjdk.jdk /Library/Java/JavaVirtualMachines/openjdk-17.jdk
fi
fi
echo "[macos.sh] All set! The PX4 Autopilot toolchain was installed."
@@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/bin/bash
#
# Setup environment to make PX4 visible to Gazebo.
#
@@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/bin/bash
# run multiple instances of the 'px4' binary, with the gazebo SITL simulation
# It assumes px4 is already built, with 'make px4_sitl_default sitl_gazebo-classic'
+11 -14
View File
@@ -1,28 +1,25 @@
#!/usr/bin/env bash
# Run multiple instances of the 'px4' binary, without starting an external simulator.
# It assumes px4 is already built with the specified build target.
#
# Usage: ./Tools/simulation/sitl_multiple_run.sh [num_instances] [model] [build_target]
# Examples:
# ./Tools/simulation/sitl_multiple_run.sh 3 sihsim_quadx px4_sitl_sih
# ./Tools/simulation/sitl_multiple_run.sh 2 gazebo-classic_iris px4_sitl_default
# ./Tools/simulation/sitl_multiple_run.sh # defaults: 2 instances, gazebo-classic_iris, px4_sitl_default
#!/bin/bash
# run multiple instances of the 'px4' binary, but w/o starting the simulator.
# It assumes px4 is already built, with 'make px4_sitl_default'
sitl_num=${1:-2}
sim_model=${2:-gazebo-classic_iris}
build_target=${3:-px4_sitl_default}
# The simulator is expected to send to TCP port 4560+i for i in [0, N-1]
# For example jmavsim can be run like this:
#./Tools/simulation/jmavsim/jmavsim_run.sh -p 4561 -l
sitl_num=2
[ -n "$1" ] && sitl_num="$1"
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
src_path="$SCRIPT_DIR/../../"
build_path=${src_path}/build/${build_target}
build_path=${src_path}/build/px4_sitl_default
echo "killing running instances"
pkill -x px4 || true
sleep 1
export PX4_SIM_MODEL=${sim_model}
export PX4_SIM_MODEL=gazebo-classic_iris
n=0
while [ $n -lt $sitl_num ]; do
@@ -42,8 +42,6 @@ px4_add_module(
syslink_bridge.cpp
syslink_memory.cpp
syslink.c
MODULE_CONFIG
syslink_params.yaml
DEPENDS
battery
)
@@ -1,6 +1,6 @@
/****************************************************************************
*
* Copyright (c) 2026 PX4 Development Team. All rights reserved.
* 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
@@ -10,7 +10,8 @@
* 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 distribution.
* 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.
@@ -30,39 +31,42 @@
*
****************************************************************************/
#include "rallyPointCheck.hpp"
/**
* @file syslink_params.c
*
* Parameters defined by the syslink module and the exposed NRF51 radio
*
* @author Dennis Shtatnov <densht@gmail.com>
*/
RallyPointChecks::RallyPointChecks()
: _param_rtl_type_handle(param_find("RTL_TYPE"))
{
}
/**
* Operating channel of the NRF51
*
* @min 0
* @max 125
* @group Syslink
*/
PARAM_DEFINE_INT32(SLNK_RADIO_CHAN, 80);
void RallyPointChecks::checkAndReport(const Context &context, Report &reporter)
{
int32_t rtl_type = 0;
/**
* Operating datarate of the NRF51
*
* @min 0
* @max 2
* @group Syslink
*/
PARAM_DEFINE_INT32(SLNK_RADIO_RATE, 2);
if (param_get(_param_rtl_type_handle, &rtl_type) != 0 || rtl_type != 5) {
// Only enforce rally point requirement when RTL_TYPE == 5 (safe points only)
return;
}
/**
* Operating address of the NRF51 (most significant byte)
*
* @group Syslink
*/
PARAM_DEFINE_INT32(SLNK_RADIO_ADDR1, 231); // 0xE7
rtl_status_s rtl_status;
if (!_rtl_status_sub.copy(&rtl_status) || rtl_status.safe_point_index == UINT8_MAX) {
/* EVENT
* @description
* Upload at least one rally point before arming, or change <param>RTL_TYPE</param>.
*
* <profile name="dev">
* This check is active when RTL_TYPE is set to 5 (safe points only).
* </profile>
*/
reporter.armingCheckFailure(NavModes::All, health_component_t::system,
events::ID("check_rally_point_missing"),
events::Log::Error, "No rally point available");
if (reporter.mavlink_log_pub()) {
mavlink_log_critical(reporter.mavlink_log_pub(), "Preflight Fail: No rally point available\t");
}
}
}
/**
* 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
Binary file not shown.
+1 -1
View File
@@ -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
-1
View File
@@ -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);
+3 -22
View File
@@ -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
)
@@ -0,0 +1,43 @@
/****************************************************************************
*
* 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.
*
****************************************************************************/
/**
* 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
@@ -37,8 +37,6 @@ px4_add_module(
SRCS
pwm_voltage.cpp
MODULE_CONFIG
parameters.yaml
DEPENDS
px4_work_queue
)
@@ -0,0 +1,43 @@
/****************************************************************************
*
* 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.
*
****************************************************************************/
/**
* 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
@@ -37,8 +37,6 @@ px4_add_module(
SRCS
pwm_voltage.cpp
MODULE_CONFIG
parameters.yaml
DEPENDS
px4_work_queue
)
@@ -10,7 +10,8 @@
* 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 distribution.
* 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.
@@ -30,24 +31,13 @@
*
****************************************************************************/
#pragma once
#include "../Common.hpp"
#include <uORB/Subscription.hpp>
#include <uORB/topics/rtl_status.h>
#include <parameters/param.h>
class RallyPointChecks : public HealthAndArmingCheckBase
{
public:
RallyPointChecks();
~RallyPointChecks() = default;
void checkAndReport(const Context &context, Report &reporter) override;
private:
uORB::Subscription _rtl_status_sub{ORB_ID(rtl_status)};
const param_t _param_rtl_type_handle;
};
/**
* 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
@@ -25,14 +25,7 @@ CONFIG_MODULES_COMMANDER=y
CONFIG_MODULES_CONTROL_ALLOCATOR=y
CONFIG_MODULES_DATAMAN=y
CONFIG_MODULES_EKF2=y
# CONFIG_EKF2_AUX_GLOBAL_POSITION is not set
# CONFIG_EKF2_AUXVEL is not set
# CONFIG_EKF2_BARO_COMPENSATION is not set
# CONFIG_EKF2_DRAG_FUSION is not set
# CONFIG_EKF2_EXTERNAL_VISION is not set
# CONFIG_EKF2_GNSS_YAW is not set
# CONFIG_EKF2_OPTICAL_FLOW is not set
# CONFIG_EKF2_RANGE_FINDER is not set
# CONFIG_EKF2_SIDESLIP is not set
CONFIG_MODULES_FLIGHT_MODE_MANAGER=y
CONFIG_MODULES_LAND_DETECTOR=y
+1 -1
View File
@@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/bin/bash
# Run this from the px4 project top level directory
docker run -it --rm --privileged -v `pwd`:/usr/local/workspace px4io/px4-dev-nuttx-focal:2022-08-12
@@ -1,23 +1,5 @@
CONFIG_PLATFORM_QURT=y
CONFIG_BOARD_TOOLCHAIN="qurt"
# Disable modules from default.px4board that are apps-only
CONFIG_BOARD_LINUX_TARGET=n
CONFIG_DRIVERS_OSD_MSP_OSD=n
CONFIG_DRIVERS_QSHELL_POSIX=n
CONFIG_DRIVERS_RC_INPUT=n
CONFIG_MODULES_DATAMAN=n
CONFIG_MODULES_LOGGER=n
CONFIG_MODULES_MAVLINK=n
CONFIG_MODULES_MUORB_APPS=n
CONFIG_MODULES_NAVIGATOR=n
CONFIG_MODULES_UXRCE_DDS_CLIENT=n
CONFIG_SYSTEMCMDS_ACTUATOR_TEST=n
CONFIG_SYSTEMCMDS_BSONDUMP=n
CONFIG_SYSTEMCMDS_PERF=n
CONFIG_SYSTEMCMDS_TOPIC_LISTENER=n
CONFIG_SYSTEMCMDS_VER=n
CONFIG_SYSTEMCMDS_REBOOT=n
CONFIG_PARAM_PRIMARY=n
CONFIG_DRIVERS_ACTUATORS_VOXL_ESC=y
CONFIG_DRIVERS_BAROMETER_INVENSENSE_ICP101XX=y
CONFIG_DRIVERS_BAROMETER_MS5611=y
@@ -37,8 +19,6 @@ CONFIG_DRIVERS_MAGNETOMETER_ISENTEK_IST8310=y
CONFIG_DRIVERS_MAGNETOMETER_QMC5883L=y
CONFIG_DRIVERS_MAGNETOMETER_ST_IIS2MDC=y
CONFIG_DRIVERS_POWER_MONITOR_VOXLPM=y
CONFIG_DRIVERS_POWER_MONITOR_INA226=y
CONFIG_DRIVERS_POWER_MONITOR_INA228=y
CONFIG_DRIVERS_QSHELL_QURT=y
CONFIG_DRIVERS_RC_CRSF_RC=y
CONFIG_DRIVERS_VOXL2_IO=y
@@ -0,0 +1,84 @@
############################################################################
#
# Copyright (c) 2022 ModalAI, Inc. 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.
#
############################################################################
# Need to make sure that the DSP processor on VOXL2
# knows about all parameters since some modules need parameters
# from other modules that are not running on the DSP.
set(DISABLE_PARAMS_MODULE_SCOPING TRUE PARENT_SCOPE)
add_library(drivers_board
board_config.h
i2c.cpp
init.c
spi.cpp
)
# Generate MAVLink common headers for SLPI drivers (dsp_hitl, mavlink_rc_in)
# Replicates the generation from src/modules/mavlink/CMakeLists.txt so the
# SLPI build is self-contained and does not depend on voxl2-default.
set(MAVLINK_GIT_DIR "${PX4_SOURCE_DIR}/src/modules/mavlink/mavlink")
set(MAVLINK_LIBRARY_DIR "${CMAKE_BINARY_DIR}/mavlink")
px4_add_git_submodule(TARGET git_mavlink_v2 PATH "${MAVLINK_GIT_DIR}")
add_custom_command(
OUTPUT ${MAVLINK_LIBRARY_DIR}/common/common.h
COMMAND ${PYTHON_EXECUTABLE} ${MAVLINK_GIT_DIR}/pymavlink/tools/mavgen.py
--lang C --wire-protocol 2.0
--output ${MAVLINK_LIBRARY_DIR}
${MAVLINK_GIT_DIR}/message_definitions/v1.0/common.xml
> ${CMAKE_BINARY_DIR}/mavgen_common.log
DEPENDS
git_mavlink_v2
${MAVLINK_GIT_DIR}/pymavlink/tools/mavgen.py
${MAVLINK_GIT_DIR}/message_definitions/v1.0/common.xml
COMMENT "Generating MAVLink common headers for SLPI"
)
add_custom_target(mavlink_common_generate DEPENDS ${MAVLINK_LIBRARY_DIR}/common/common.h)
add_library(mavlink_common_headers INTERFACE)
add_dependencies(mavlink_common_headers mavlink_common_generate)
target_compile_options(mavlink_common_headers INTERFACE -Wno-address-of-packed-member -Wno-cast-align)
target_include_directories(mavlink_common_headers INTERFACE
${MAVLINK_LIBRARY_DIR}
${MAVLINK_LIBRARY_DIR}/common
)
# Add custom drivers for SLPI
add_subdirectory(${PX4_BOARD_DIR}/src/drivers/rc_controller)
add_subdirectory(${PX4_BOARD_DIR}/src/drivers/mavlink_rc_in)
add_subdirectory(${PX4_BOARD_DIR}/src/drivers/spektrum_rc)
add_subdirectory(${PX4_BOARD_DIR}/src/drivers/ghst_rc)
add_subdirectory(${PX4_BOARD_DIR}/src/drivers/dsp_hitl)
add_subdirectory(${PX4_BOARD_DIR}/src/drivers/dsp_sbus)
add_subdirectory(${PX4_BOARD_DIR}/src/drivers/elrs_led)
@@ -0,0 +1,82 @@
/****************************************************************************
*
* Copyright (c) 2022-2026 ModalAI, Inc. 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 board_config.h
*
* VOXL2 internal definitions
*/
#pragma once
#define CONFIG_BOARDCTL_RESET
#define BOARD_HAS_NO_BOOTLOADER
/*
* I2C buses
*/
#define CONFIG_I2C 1
#define PX4_NUMBER_I2C_BUSES 4
/*
* SPI buses
*/
#define CONFIG_SPI 1
#define BOARD_SPI_BUS_MAX_BUS_ITEMS 1
/*
* Include these last to make use of the definitions above
*/
#include <system_config.h>
#include <px4_platform_common/board_common.h>
/*
* Default port for the ESC
*/
#define VOXL_ESC_DEFAULT_PORT "2"
/*
* Default port for the GHST RC
*/
#define GHST_RC_DEFAULT_PORT "7"
/*
* Default port for M0065
*/
#define VOXL2_IO_DEFAULT_PORT "2"
/*
* M0065 PWM
*/
#define DIRECT_PWM_OUTPUT_CHANNELS 4
#define MAX_IO_TIMERS 3
+35
View File
@@ -0,0 +1,35 @@
/****************************************************************************
*
* Copyright (C) 2022 ModalAI, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#include "board_config.h"
// Place holder for VOXL2-specific early startup code
+2 -10
View File
@@ -13,10 +13,6 @@ critical applications such as Mavlink, and logging are running on the
ARM CPU cluster (aka apps proc). The DSP and ARM CPU cluster communicate via a
Qualcomm proprietary shared memory interface.
Both processors are built from this single board directory:
- `default.px4board` - POSIX apps processor (ARM64)
- `slpi.px4board` - QURT DSP (Hexagon)
## Build environment
In order to build for this platform both the Qualcomm Hexagon (DSP) toolchain and the Linaro ARM64 toolchain need to be installed. The (nearly) complete setup including the ARM64 toolchain is provided in the base Docker image provided by ModalAI, but since ModalAI is not allowed to redistribute the Qualcomm Hexagon DSP SDK this must be added by the end user.
@@ -26,21 +22,17 @@ The full instructions are available here:
## Build overview
A single `make modalai_voxl2` command builds both the DSP and apps processor
firmware. The Makefile chains the SLPI build as a prerequisite of the default
(apps) build.
- Clone the repo (Don't forget to update and initialize all submodules)
- In the top level directory
```
px4$ boards/modalai/voxl2/scripts/run-docker.sh
root@9373fa1401b8:/usr/local/workspace# boards/modalai/voxl2/scripts/clean.sh
root@9373fa1401b8:/usr/local/workspace# boards/modalai/voxl2/scripts/build-deps.sh
root@9373fa1401b8:/usr/local/workspace# boards/modalai/voxl2/scripts/build-apps.sh
root@9373fa1401b8:/usr/local/workspace# boards/modalai/voxl2/scripts/build-slpi.sh
root@9373fa1401b8:/usr/local/workspace# exit
```
For DSP-only rebuilds: `make modalai_voxl2_slpi`
## Install and run on VOXL 2
Once the DSP and Linux images have been built they can be installed on a VOXL 2
-4
View File
@@ -31,10 +31,6 @@
#
############################################################################
if(NOT "${PX4_PLATFORM}" STREQUAL "posix")
return()
endif()
# Initialize libfc-sensor-api submodule (fetches from GitLab if not present)
execute_process(
COMMAND Tools/check_submodules.sh boards/modalai/voxl2/libfc-sensor-api
-84
View File
@@ -1,84 +0,0 @@
############################################################################
#
# 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.
#
############################################################################
# VOXL2 board-specific install rules for .deb packaging
# Included from platforms/posix/CMakeLists.txt where the px4 target exists
# SLPI companion build output directory
set(VOXL2_SLPI_BUILD_DIR "${PX4_SOURCE_DIR}/build/modalai_voxl2_slpi")
# Apps processor binary
install(TARGETS px4 RUNTIME DESTINATION bin)
# px4-alias.sh (generated during build into bin/ subdirectory)
install(PROGRAMS ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/px4-alias.sh DESTINATION bin)
# Startup scripts from board target directory
install(PROGRAMS
${PX4_BOARD_DIR}/target/voxl-px4
${PX4_BOARD_DIR}/target/voxl-px4-start
${PX4_BOARD_DIR}/target/voxl-px4-hitl
${PX4_BOARD_DIR}/target/voxl-px4-hitl-start
${PX4_BOARD_DIR}/scripts/voxl-configure-px4
DESTINATION bin
)
# DSP firmware blob from companion SLPI build
install(FILES ${VOXL2_SLPI_BUILD_DIR}/platforms/qurt/libpx4.so
DESTINATION lib/rfsa/adsp
)
# Configuration files
install(FILES
${PX4_BOARD_DIR}/target/voxl-px4-fake-imu-calibration.config
${PX4_BOARD_DIR}/target/voxl-px4-hitl-set-default-parameters.config
DESTINATION ../etc/modalai
)
# Systemd service file
install(FILES ${PX4_BOARD_DIR}/debian/voxl-px4.service
DESTINATION ../etc/systemd/system
)
# Component metadata JSON files
install(FILES
${PX4_BINARY_DIR}/actuators.json.xz
${PX4_BINARY_DIR}/component_general.json.xz
${PX4_BINARY_DIR}/parameters.json.xz
DESTINATION ../data/px4/etc/extras
OPTIONAL
)
install(FILES ${PX4_BINARY_DIR}/events/all_events.json.xz
DESTINATION ../data/px4/etc/extras
OPTIONAL
)
@@ -1,6 +1,3 @@
if(NOT "${PX4_PLATFORM}" STREQUAL "posix")
return()
endif()
# Link against the public stub version of the proprietary fc sensor library
target_link_libraries(px4 PRIVATE
-63
View File
@@ -1,63 +0,0 @@
############################################################################
#
# 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.
#
############################################################################
# VOXL2 board-specific CPack overrides
# Loaded after cmake/package.cmake sets up CPack defaults
# Derive Debian-compatible version from git tag (e.g. v1.17.0-alpha1-42-gabcdef -> 1.17.0~alpha1.42.gabcdef)
string(REGEX REPLACE "^v" "" _deb_ver "${PX4_GIT_TAG}")
string(REGEX REPLACE "-" "~" _deb_ver "${_deb_ver}" )
string(REGEX REPLACE "~([0-9]+)~" ".\\1." _deb_ver "${_deb_ver}")
# VOXL2 is always aarch64 regardless of build host
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "arm64")
set(CPACK_DEBIAN_PACKAGE_NAME "voxl-px4")
set(CPACK_DEBIAN_FILE_NAME "voxl-px4_${_deb_ver}_arm64.deb")
set(CPACK_PACKAGING_INSTALL_PREFIX "/usr")
set(CPACK_INSTALL_PREFIX "/usr")
set(CPACK_SET_DESTDIR true)
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libfc-sensor (>=1.0.10), voxl-px4-params (>=0.3.10), voxl3-system-image(>=0.0.2) | voxl2-system-image(>=1.5.4) | rb5-system-image(>=1.6.2), modalai-slpi(>=1.2.2) | modalai-adsp(>=1.0.5)")
set(CPACK_DEBIAN_PACKAGE_CONFLICTS "px4-rb5-flight")
set(CPACK_DEBIAN_PACKAGE_REPLACES "px4-rb5-flight")
set(CPACK_DEBIAN_PACKAGE_DESCRIPTION "PX4 Autopilot for ModalAI VOXL2")
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "ModalAI <support@modalai.com>")
# Disable shlibdeps for cross-compiled boards
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS OFF)
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA
"${PX4_BOARD_DIR}/debian/postinst;${PX4_BOARD_DIR}/debian/prerm")
# Install rules are in boards/modalai/voxl2/cmake/install.cmake,
# included from platforms/posix/CMakeLists.txt where the px4 target exists.
-3
View File
@@ -1,3 +0,0 @@
# Companion processor targets - built automatically by the parent (default) target
# These are excluded from CI target lists to avoid redundant builds
modalai_voxl2_slpi
-36
View File
@@ -1,36 +0,0 @@
#!/usr/bin/env bash
set -e
# Create px4-* symlinks from px4-alias.sh
# The alias format is: alias <module>='px4-<module> --instance $px4_instance'
# We extract the px4-<module> command name and symlink it to the px4 binary
if [ -f /usr/bin/px4-alias.sh ]; then
grep "^alias " /usr/bin/px4-alias.sh | \
sed -n "s/.*'\(px4-[a-zA-Z0-9_]*\).*/\1/p" | while read cmd; do
ln -sf px4 "/usr/bin/${cmd}"
done
fi
# Detect platform and generate DSP test signature if needed
if ! /bin/ls /usr/lib/rfsa/adsp/testsig-*.so &> /dev/null; then
echo "[INFO] Generating DSP test signature..."
if [ -f /share/modalai/qcs6490-slpi-test-sig/generate-test-sig.sh ]; then
/share/modalai/qcs6490-slpi-test-sig/generate-test-sig.sh || true
elif [ -f /share/modalai/qrb5165-slpi-test-sig/generate-test-sig.sh ]; then
/share/modalai/qrb5165-slpi-test-sig/generate-test-sig.sh || true
else
echo "[WARNING] Could not find DSP signature generation script"
fi
fi
# Create required data directories
mkdir -p /data/px4/param
mkdir -p /data/px4/etc/extras
chown -R root:root /data/px4
# Reload systemd if available
if command -v systemctl > /dev/null 2>&1; then
systemctl daemon-reload
fi
echo "voxl-px4 installed successfully"
-14
View File
@@ -1,14 +0,0 @@
#!/usr/bin/env bash
set -e
# Stop voxl-px4 service if running
if command -v systemctl > /dev/null 2>&1; then
systemctl stop voxl-px4 2>/dev/null || true
fi
# Remove px4-* symlinks
for f in /usr/bin/px4-*; do
if [ -L "$f" ] && [ "$(readlink "$f")" = "px4" ]; then
rm -f "$f"
fi
done

Some files were not shown because too many files have changed in this diff Show More