mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-06-05 03:20:04 +08:00
Compare commits
100 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7b902efdca | |||
| a3657c1396 | |||
| 5d3083ec00 | |||
| 845d65fe9b | |||
| 648e730c4a | |||
| 6fcfd5fac1 | |||
| ba35ca461c | |||
| 0e4c794674 | |||
| 3d6056411f | |||
| abb80ae71e | |||
| a954ec4d55 | |||
| 7c14a63855 | |||
| d78af5436e | |||
| 45285a57ad | |||
| bbcd153e94 | |||
| 3bde706cb3 | |||
| dbe57fad08 | |||
| f7740bdfd2 | |||
| 74a8d897b2 | |||
| 1ee3b7e77d | |||
| cc492bbf6e | |||
| 9cc1e01bd8 | |||
| 724987d59e | |||
| 27ff547e07 | |||
| db97dd471d | |||
| 5509061803 | |||
| f2026343d7 | |||
| fee81a5c88 | |||
| d06e9cc302 | |||
| e35c1f430c | |||
| 1928758fbc | |||
| f73c7977dd | |||
| 53bdceb895 | |||
| cdab0cb6e4 | |||
| 82ea544e8c | |||
| ddb9a5d0b9 | |||
| 2c8ef05c2d | |||
| 72454c4fd2 | |||
| 69b7a21f02 | |||
| 7cb7977263 | |||
| 8acf273917 | |||
| 3870992bac | |||
| 550bbd9051 | |||
| 19d3e6285b | |||
| 898d631b24 | |||
| e7eca72d02 | |||
| 9f4e642e9f | |||
| 6f026f35b1 | |||
| 46d1489d36 | |||
| 4710366862 | |||
| 82a482ec0b | |||
| 49624a6457 | |||
| 7acd2e93eb | |||
| 9e99bd3b7a | |||
| a2341c29f4 | |||
| f608a10ed4 | |||
| 5cb3fd1c9f | |||
| 9e8b530ad9 | |||
| c2706f5406 | |||
| 735777862d | |||
| 4184cf67d3 | |||
| 71554af8fa | |||
| f67027f066 | |||
| dfc66993b6 | |||
| ca2ed655b8 | |||
| fdebdc447d | |||
| 283a69dedf | |||
| 451b0a3db8 | |||
| 4c0a63f679 | |||
| a048a8e8a0 | |||
| 80ea3a09bb | |||
| b35753ded9 | |||
| 18b6a61788 | |||
| b91e1cd482 | |||
| d1eff16ad7 | |||
| 895afea0a7 | |||
| 1afa098c90 | |||
| 12988c94f5 | |||
| 19230aa369 | |||
| 950f2272bf | |||
| 440d76b839 | |||
| 7c444828f3 | |||
| 3d7bc4a558 | |||
| d04e6695ac | |||
| bd0a59eb1f | |||
| e63b09da63 | |||
| 5e1df797e0 | |||
| d699adb308 | |||
| 58282c5292 | |||
| bcd609ce51 | |||
| 497efb9665 | |||
| 029060264e | |||
| cba54fc59d | |||
| 3d48ba4c19 | |||
| 7c6abf2237 | |||
| bd4aad0796 | |||
| c909611149 | |||
| 77df2c97ec | |||
| c77f3887aa | |||
| 6cab668270 |
@@ -19,7 +19,7 @@ jobs:
|
||||
fail-fast: false
|
||||
max-parallel: 1 # Should be 1 to avoid parallel builds
|
||||
matrix:
|
||||
lc: [ko, uk, zh] # Target languages https://developer.crowdin.com/language-codes/
|
||||
lc: [ko, uk, zh-CN] # Target languages https://developer.crowdin.com/language-codes/
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
@@ -41,6 +41,8 @@ jobs:
|
||||
pull_request_base_branch_name: 'main'
|
||||
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 }}
|
||||
env:
|
||||
# A classic GitHub Personal Access Token with the 'repo' scope selected (the user should have write access to the repository).
|
||||
|
||||
@@ -8,18 +8,18 @@ on:
|
||||
- main
|
||||
paths:
|
||||
- 'docs/en/**'
|
||||
pull_request:
|
||||
types:
|
||||
- closed
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- 'docs/en/**'
|
||||
#pull_request:
|
||||
# types:
|
||||
# - closed
|
||||
# branches:
|
||||
# - main
|
||||
# paths:
|
||||
# - 'docs/en/**'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
upload-to-crowdin:
|
||||
if: github.event.pull_request.merged == true || github.event_name == 'push'
|
||||
#if: github.event.pull_request.merged == true || github.event_name == 'push' || github.event_name == 'workflow_dispatch'
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
@@ -28,7 +28,7 @@ jobs:
|
||||
- name: crowdin push
|
||||
uses: crowdin/github-action@v2
|
||||
with:
|
||||
config: 'docs/crowdin.yml'
|
||||
config: 'docs/crowdin_docs.yml'
|
||||
upload_sources: true
|
||||
upload_translations: false
|
||||
download_translations: false
|
||||
|
||||
@@ -5,8 +5,6 @@ on:
|
||||
branches:
|
||||
- 'main'
|
||||
- 'release/**'
|
||||
tags:
|
||||
- 'v*'
|
||||
paths:
|
||||
- 'docs/en/**'
|
||||
pull_request:
|
||||
@@ -70,7 +68,7 @@ jobs:
|
||||
deploy:
|
||||
if: ${{ github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.merged) || github.event_name == 'workflow_dispatch' }}
|
||||
needs: build
|
||||
runs-on: [runs-on,runner=2cpu-linux-x64,image=ubuntu24-full-x64,"run-id=${{ github.run_id }}",spot=false]
|
||||
runs-on: [runs-on,runner=8cpu-linux-x64,image=ubuntu24-full-x64,"run-id=${{ github.run_id }}",spot=false]
|
||||
|
||||
steps:
|
||||
- name: Download Artifact
|
||||
|
||||
@@ -21,13 +21,13 @@ jobs:
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '16'
|
||||
node-version: '18'
|
||||
|
||||
- name: Create logs directory
|
||||
run: |
|
||||
mkdir logs
|
||||
|
||||
- name: Get changed english files
|
||||
- name: Get changed english doc files
|
||||
id: get_changed_markdown_english
|
||||
uses: tj-actions/changed-files@v35.9.2
|
||||
with:
|
||||
@@ -48,10 +48,10 @@ jobs:
|
||||
- name: Run link checker
|
||||
id: link-check
|
||||
run: |
|
||||
npm -g install markdown_link_checker_sc@0.0.134
|
||||
markdown_link_checker_sc -r ${{ github.workspace }} -d en -f ./docs/logs/prFiles.json -i assets -u docs.px4.io/main/ > ./docs/logs/errorsFilteredByPrPages.md
|
||||
npm -g install markdown_link_checker_sc@0.0.138
|
||||
markdown_link_checker_sc -r ${{ github.workspace }} -d docs -e en -f ./logs/prFiles.json -i assets -u docs.px4.io/main/ > ./logs/errorsFilteredByPrPages.md
|
||||
mkdir -p ./pr
|
||||
cp ./docs/logs/errorsFilteredByPrPages.md ./pr/errorsFilteredByPrPages.md
|
||||
cp ./logs/errorsFilteredByPrPages.md ./pr/errorsFilteredByPrPages.md
|
||||
|
||||
- name: Read errorsFilteredByPrPages.md file
|
||||
id: read-errors-by-page
|
||||
|
||||
@@ -95,62 +95,61 @@ jobs:
|
||||
echo "$EOF" >> $GITHUB_OUTPUT
|
||||
|
||||
# TODO:
|
||||
# This part of the workflow is causing errors, we should find a way to fix this and enable this test again
|
||||
# This part of the workflow is causing errors for forks. We should find a way to fix this and enable it again for forks.
|
||||
# Track this issue https://github.com/PX4/PX4-Autopilot/issues/24408
|
||||
#
|
||||
#post_pr_comment:
|
||||
#name: Publish Results
|
||||
#runs-on: [runs-on,runner=1cpu-linux-x64,image=ubuntu24-full-x64,"run-id=${{ github.run_id }}",spot=false]
|
||||
#needs: [analyze_flash]
|
||||
#env:
|
||||
#V5X-SUMMARY-MAP-ABS: ${{ fromJSON(fromJSON(needs.analyze_flash.outputs.px4_fmu-v5x-bloaty-summary-map).vm-absolute) }}
|
||||
#V5X-SUMMARY-MAP-PERC: ${{ fromJSON(fromJSON(needs.analyze_flash.outputs.px4_fmu-v5x-bloaty-summary-map).vm-percentage) }}
|
||||
#V6X-SUMMARY-MAP-ABS: ${{ fromJSON(fromJSON(needs.analyze_flash.outputs.px4_fmu-v6x-bloaty-summary-map).vm-absolute) }}
|
||||
#V6X-SUMMARY-MAP-PERC: ${{ fromJSON(fromJSON(needs.analyze_flash.outputs.px4_fmu-v6x-bloaty-summary-map).vm-percentage) }}
|
||||
#if: ${{ github.event.pull_request }}
|
||||
#steps:
|
||||
#- name: Find Comment
|
||||
#uses: peter-evans/find-comment@v3
|
||||
#id: fc
|
||||
#with:
|
||||
#issue-number: ${{ github.event.pull_request.number }}
|
||||
#comment-author: 'github-actions[bot]'
|
||||
#body-includes: FLASH Analysis
|
||||
post_pr_comment:
|
||||
name: Publish Results
|
||||
runs-on: [runs-on,runner=1cpu-linux-x64,image=ubuntu24-full-x64,"run-id=${{ github.run_id }}",spot=false]
|
||||
needs: [analyze_flash]
|
||||
env:
|
||||
V5X-SUMMARY-MAP-ABS: ${{ fromJSON(fromJSON(needs.analyze_flash.outputs.px4_fmu-v5x-bloaty-summary-map).vm-absolute) }}
|
||||
V5X-SUMMARY-MAP-PERC: ${{ fromJSON(fromJSON(needs.analyze_flash.outputs.px4_fmu-v5x-bloaty-summary-map).vm-percentage) }}
|
||||
V6X-SUMMARY-MAP-ABS: ${{ fromJSON(fromJSON(needs.analyze_flash.outputs.px4_fmu-v6x-bloaty-summary-map).vm-absolute) }}
|
||||
V6X-SUMMARY-MAP-PERC: ${{ fromJSON(fromJSON(needs.analyze_flash.outputs.px4_fmu-v6x-bloaty-summary-map).vm-percentage) }}
|
||||
if: github.event.pull_request && github.event.pull_request.head.repo.full_name == github.repository
|
||||
steps:
|
||||
- name: Find Comment
|
||||
uses: peter-evans/find-comment@v3
|
||||
id: fc
|
||||
with:
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
comment-author: 'github-actions[bot]'
|
||||
body-includes: FLASH Analysis
|
||||
|
||||
#- name: Set Build Time
|
||||
#id: bt
|
||||
#run: |
|
||||
#echo "timestamp=$(date +'%Y-%m-%dT%H:%M:%S')" >> $GITHUB_OUTPUT
|
||||
- name: Set Build Time
|
||||
id: bt
|
||||
run: |
|
||||
echo "timestamp=$(date +'%Y-%m-%dT%H:%M:%S')" >> $GITHUB_OUTPUT
|
||||
|
||||
#- name: Create or update comment
|
||||
## This can't be moved to the job-level conditions, as GH actions don't allow a job-level if condition to access the env.
|
||||
#if: |
|
||||
#steps.fc.outputs.comment-id != '' ||
|
||||
#env.V5X-SUMMARY-MAP-ABS >= fromJSON(env.MIN_FLASH_POS_DIFF_FOR_COMMENT) ||
|
||||
#env.V5X-SUMMARY-MAP-ABS <= fromJSON(env.MIN_FLASH_NEG_DIFF_FOR_COMMENT) ||
|
||||
#env.V6X-SUMMARY-MAP-ABS >= fromJSON(env.MIN_FLASH_POS_DIFF_FOR_COMMENT) ||
|
||||
#env.V6X-SUMMARY-MAP-ABS <= fromJSON(env.MIN_FLASH_NEG_DIFF_FOR_COMMENT)
|
||||
#uses: peter-evans/create-or-update-comment@v4
|
||||
#with:
|
||||
#comment-id: ${{ steps.fc.outputs.comment-id }}
|
||||
#issue-number: ${{ github.event.pull_request.number }}
|
||||
#body: |
|
||||
### 🔎 FLASH Analysis
|
||||
#<details>
|
||||
#<summary>px4_fmu-v5x [Total VM Diff: ${{ env.V5X-SUMMARY-MAP-ABS }} byte (${{ env.V5X-SUMMARY-MAP-PERC}} %)]</summary>
|
||||
- name: Create or update comment
|
||||
# This can't be moved to the job-level conditions, as GH actions don't allow a job-level if condition to access the env.
|
||||
if: |
|
||||
steps.fc.outputs.comment-id != '' ||
|
||||
env.V5X-SUMMARY-MAP-ABS >= fromJSON(env.MIN_FLASH_POS_DIFF_FOR_COMMENT) ||
|
||||
env.V5X-SUMMARY-MAP-ABS <= fromJSON(env.MIN_FLASH_NEG_DIFF_FOR_COMMENT) ||
|
||||
env.V6X-SUMMARY-MAP-ABS >= fromJSON(env.MIN_FLASH_POS_DIFF_FOR_COMMENT) ||
|
||||
env.V6X-SUMMARY-MAP-ABS <= fromJSON(env.MIN_FLASH_NEG_DIFF_FOR_COMMENT)
|
||||
uses: peter-evans/create-or-update-comment@v4
|
||||
with:
|
||||
comment-id: ${{ steps.fc.outputs.comment-id }}
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
body: |
|
||||
## 🔎 FLASH Analysis
|
||||
<details>
|
||||
<summary>px4_fmu-v5x [Total VM Diff: ${{ env.V5X-SUMMARY-MAP-ABS }} byte (${{ env.V5X-SUMMARY-MAP-PERC}} %)]</summary>
|
||||
|
||||
#```
|
||||
#${{ needs.analyze_flash.outputs.px4_fmu-v5x-bloaty-output }}
|
||||
#```
|
||||
#</details>
|
||||
```
|
||||
${{ needs.analyze_flash.outputs.px4_fmu-v5x-bloaty-output }}
|
||||
```
|
||||
</details>
|
||||
|
||||
#<details>
|
||||
#<summary>px4_fmu-v6x [Total VM Diff: ${{ env.V6X-SUMMARY-MAP-ABS }} byte (${{ env.V6X-SUMMARY-MAP-PERC }} %)]</summary>
|
||||
<details>
|
||||
<summary>px4_fmu-v6x [Total VM Diff: ${{ env.V6X-SUMMARY-MAP-ABS }} byte (${{ env.V6X-SUMMARY-MAP-PERC }} %)]</summary>
|
||||
|
||||
#```
|
||||
#${{ needs.analyze_flash.outputs.px4_fmu-v6x-bloaty-output }}
|
||||
#```
|
||||
#</details>
|
||||
```
|
||||
${{ needs.analyze_flash.outputs.px4_fmu-v6x-bloaty-output }}
|
||||
```
|
||||
</details>
|
||||
|
||||
#**Updated: _${{ steps.bt.outputs.timestamp }}_**
|
||||
#edit-mode: replace
|
||||
**Updated: _${{ steps.bt.outputs.timestamp }}_**
|
||||
edit-mode: replace
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
# NOTE: this workflow is now running on Dronecode / PX4 AWS account.
|
||||
# - If you want to keep the tests running in GitHub Actions you need to uncomment the "runs-on: ubuntu-latest" lines
|
||||
# and comment the "runs-on: [runs-on,runner=..." lines.
|
||||
# - If you would like to duplicate this setup try setting up "RunsOn" on your own AWS account try https://runs-on.com
|
||||
|
||||
name: ROS Integration Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'main'
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
- '.github/**'
|
||||
pull_request:
|
||||
branches:
|
||||
- '*'
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
- '.github/**'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: [runs-on,runner=16cpu-linux-x64,image=ubuntu22-full-x64,"run-id=${{ github.run_id }}",spot=false]
|
||||
container:
|
||||
image: px4io/px4-dev-ros2-galactic:2021-09-08
|
||||
options: --privileged --ulimit core=-1 --security-opt seccomp=unconfined
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Git Ownership Workaround
|
||||
run: git config --system --add safe.directory '*'
|
||||
|
||||
- name: Install gazebo
|
||||
run: |
|
||||
apt update && apt install -y gazebo11 libgazebo11-dev gstreamer1.0-plugins-bad gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-ugly libgstreamer-plugins-base1.0-dev
|
||||
|
||||
- name: Prepare ccache timestamp
|
||||
id: ccache_cache_timestamp
|
||||
shell: cmake -P {0}
|
||||
run: |
|
||||
string(TIMESTAMP current_date "%Y-%m-%d-%H;%M;%S" UTC)
|
||||
message("::set-output name=timestamp::${current_date}")
|
||||
- name: ccache cache files
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ros_integration_tests-${{matrix.config.build_type}}-ccache-${{steps.ccache_cache_timestamp.outputs.timestamp}}
|
||||
restore-keys: ros_integration_tests-${{matrix.config.build_type}}-ccache-
|
||||
- name: setup ccache
|
||||
run: |
|
||||
mkdir -p ~/.ccache
|
||||
echo "base_dir = ${GITHUB_WORKSPACE}" > ~/.ccache/ccache.conf
|
||||
echo "compression = true" >> ~/.ccache/ccache.conf
|
||||
echo "compression_level = 6" >> ~/.ccache/ccache.conf
|
||||
echo "max_size = 300M" >> ~/.ccache/ccache.conf
|
||||
echo "hash_dir = false" >> ~/.ccache/ccache.conf
|
||||
ccache -s
|
||||
ccache -z
|
||||
|
||||
- name: Get and build micro-xrce-dds-agent
|
||||
run: |
|
||||
cd /opt
|
||||
git clone --recursive https://github.com/eProsima/Micro-XRCE-DDS-Agent.git
|
||||
cd Micro-XRCE-DDS-Agent
|
||||
git checkout v2.2.1 # recent versions require cmake 3.22, but px4-dev-ros2-galactic:2021-09-08 is on 3.16
|
||||
sed -i 's/_fastdds_tag 2.8.x/_fastdds_tag 2.8.2/g' CMakeLists.txt
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
make -j2
|
||||
- name: ccache post-run micro-xrce-dds-agent
|
||||
run: ccache -s
|
||||
|
||||
- name: Get and build the ros2 interface library
|
||||
shell: bash
|
||||
run: |
|
||||
PX4_DIR="$(pwd)"
|
||||
. /opt/ros/galactic/setup.bash
|
||||
mkdir -p /opt/px4_ws/src
|
||||
cd /opt/px4_ws/src
|
||||
git clone --recursive https://github.com/Auterion/px4-ros2-interface-lib.git
|
||||
cd ..
|
||||
# Copy messages to ROS workspace
|
||||
"${PX4_DIR}/Tools/copy_to_ros_ws.sh" "$(pwd)"
|
||||
rm -rf src/translation_node src/px4_msgs_old
|
||||
colcon build --symlink-install
|
||||
- name: ccache post-run ros workspace
|
||||
run: ccache -s
|
||||
|
||||
- name: Build PX4
|
||||
run: make px4_sitl_default
|
||||
- name: ccache post-run px4/firmware
|
||||
run: ccache -s
|
||||
- name: Build SITL Gazebo
|
||||
run: make px4_sitl_default sitl_gazebo-classic
|
||||
- name: ccache post-run sitl_gazebo-classic
|
||||
run: ccache -s
|
||||
|
||||
- name: Core dump settings
|
||||
run: |
|
||||
ulimit -c unlimited
|
||||
echo "`pwd`/%e.core" > /proc/sys/kernel/core_pattern
|
||||
|
||||
- name: Run tests
|
||||
shell: bash
|
||||
run: |
|
||||
. /opt/px4_ws/install/setup.bash
|
||||
/opt/Micro-XRCE-DDS-Agent/build/MicroXRCEAgent udp4 localhost -p 8888 -v 0 &
|
||||
test/ros_test_runner.py --verbose --model iris --upload --force-color
|
||||
timeout-minutes: 45
|
||||
|
||||
- name: Upload failed logs
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: failed-logs.zip
|
||||
path: |
|
||||
logs/**/**/**/*.log
|
||||
logs/**/**/**/*.ulg
|
||||
build/px4_sitl_default/tmp_ros_tests/rootfs/log/**/*.ulg
|
||||
@@ -116,7 +116,7 @@ jobs:
|
||||
PX4_HOME_LON: ${{matrix.config.longitude}}
|
||||
PX4_HOME_ALT: ${{matrix.config.altitude}}
|
||||
PX4_CMAKE_BUILD_TYPE: ${{matrix.config.build_type}}
|
||||
run: test/mavsdk_tests/mavsdk_test_runner.py --speed-factor 10 --abort-early --model ${{matrix.config.model}} --upload test/mavsdk_tests/configs/sitl.json --verbose
|
||||
run: test/mavsdk_tests/mavsdk_test_runner.py --speed-factor 10 --abort-early --model ${{matrix.config.model}} --upload test/mavsdk_tests/configs/sitl.json --verbose --force-color
|
||||
timeout-minutes: 45
|
||||
|
||||
- name: Upload failed logs
|
||||
@@ -127,7 +127,7 @@ jobs:
|
||||
path: |
|
||||
logs/**/**/**/*.log
|
||||
logs/**/**/**/*.ulg
|
||||
build/px4_sitl_default/tmp_mavsdk_tests/rootfs/*.ulg
|
||||
build/px4_sitl_default/tmp_mavsdk_tests/rootfs/log/**/*.ulg
|
||||
|
||||
- name: Look at Core files
|
||||
if: failure() && ${{ hashFiles('px4.core') != '' }}
|
||||
|
||||
@@ -108,3 +108,4 @@ src/systemcmds/topic_listener/listener_generated.cpp
|
||||
|
||||
# colcon
|
||||
log/
|
||||
keys/
|
||||
|
||||
@@ -35,8 +35,11 @@ add_subdirectory(airframes)
|
||||
|
||||
px4_add_romfs_files(
|
||||
px4-rc.mavlink
|
||||
px4-rc.params
|
||||
px4-rc.simulator
|
||||
px4-rc.gzsim
|
||||
px4-rc.jmavsim
|
||||
px4-rc.mavlinksim
|
||||
px4-rc.sihsim
|
||||
rc.replay
|
||||
rcS
|
||||
)
|
||||
|
||||
@@ -0,0 +1,180 @@
|
||||
#!/bin/sh
|
||||
# shellcheck disable=SC2154
|
||||
|
||||
echo "INFO [init] Gazebo simulator"
|
||||
|
||||
# Enforce minimum gz version as Harmonic (gz-sim8)
|
||||
MIN_GZ_VERSION="8.0.0"
|
||||
GZ_SIM_VERSION=$(gz sim --versions 2>/dev/null | head -n 1 | tr -d ' ')
|
||||
|
||||
if [ -z "$GZ_SIM_VERSION" ]; then
|
||||
echo "ERROR [init] Gazebo gz sim not found. Please install gz-harmonic"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Use sort compare, check that MIN_GZ_VERSION is ordered last
|
||||
if [ "$(printf '%s\n' "$GZ_SIM_VERSION" "$MIN_GZ_VERSION" | sort -V | head -n1)" = "$MIN_GZ_VERSION" ]; then
|
||||
gz_command="gz"
|
||||
gz_sub_command="sim"
|
||||
|
||||
# Specify render engine if `GZ_SIM_RENDER_ENGINE` is set
|
||||
# (for example, if you want to use Ogre 1.x instead of Ogre 2.x):
|
||||
if [ -n "${PX4_GZ_SIM_RENDER_ENGINE}" ]; then
|
||||
echo "INFO [init] Setting Gazebo render engine to '${PX4_GZ_SIM_RENDER_ENGINE}'!"
|
||||
gz_sub_command="${gz_sub_command} --render-engine ${PX4_GZ_SIM_RENDER_ENGINE}"
|
||||
fi
|
||||
else
|
||||
echo "ERROR [init] Gazebo gz sim version is too old ($GZ_SIM_VERSION). Minimum required version is $MIN_GZ_VERSION"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# If not standalone
|
||||
if [ -z "${PX4_GZ_STANDALONE}" ]; then
|
||||
|
||||
# Look for an already running world
|
||||
gz_world=$( ${gz_command} topic -l | grep -m 1 -e "^/world/.*/clock" | sed 's/\/world\///g; s/\/clock//g' )
|
||||
|
||||
# shellcheck disable=SC2153
|
||||
if [ -z "${gz_world}" ] && [ -n "${PX4_GZ_WORLD}" ]; then
|
||||
|
||||
# Setup gz environment variables
|
||||
if [ -f ./gz_env.sh ]; then
|
||||
. ./gz_env.sh
|
||||
|
||||
elif [ -f ../gz_env.sh ]; then
|
||||
. ../gz_env.sh
|
||||
fi
|
||||
|
||||
echo "INFO [init] Starting gazebo with world: ${PX4_GZ_WORLDS}/${PX4_GZ_WORLD}.sdf"
|
||||
|
||||
${gz_command} ${gz_sub_command} --verbose=${GZ_VERBOSE:=1} -r -s "${PX4_GZ_WORLDS}/${PX4_GZ_WORLD}.sdf" &
|
||||
|
||||
if [ -z "${HEADLESS}" ]; then
|
||||
echo "INFO [init] Starting gz gui"
|
||||
${gz_command} ${gz_sub_command} -g > /dev/null 2>&1 &
|
||||
fi
|
||||
|
||||
else
|
||||
# Gazebo is already running
|
||||
echo "INFO [init] gazebo already running world: ${gz_world}"
|
||||
PX4_GZ_WORLD=${gz_world}
|
||||
fi
|
||||
|
||||
else
|
||||
echo "INFO [init] Standalone PX4 launch, waiting for Gazebo"
|
||||
fi
|
||||
|
||||
# Wait for Gazebo world to be ready before proceeding
|
||||
check_scene_info() {
|
||||
SERVICE_INFO=$(${gz_command} service -i --service "/world/${PX4_GZ_WORLD}/scene/info" 2>&1)
|
||||
if echo "$SERVICE_INFO" | grep -q "Service providers"; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
ATTEMPTS=30
|
||||
while [ $ATTEMPTS -gt 0 ]; do
|
||||
if check_scene_info; then
|
||||
echo "INFO [init] Gazebo world is ready"
|
||||
break
|
||||
fi
|
||||
ATTEMPTS=$((ATTEMPTS-1))
|
||||
if [ $ATTEMPTS -eq 0 ]; then
|
||||
echo "ERROR [init] Timed out waiting for Gazebo world"
|
||||
exit 1
|
||||
fi
|
||||
echo "INFO [init] Waiting for Gazebo world..."
|
||||
sleep 1
|
||||
done
|
||||
|
||||
# Start gz_bridge - either spawn a model or connect to existing one
|
||||
if [ -n "${PX4_SIM_MODEL#*gz_}" ] && [ -z "${PX4_GZ_MODEL_NAME}" ]; then
|
||||
# Spawn a model
|
||||
MODEL_NAME="${PX4_SIM_MODEL#*gz_}"
|
||||
MODEL_NAME_INSTANCE="${MODEL_NAME}_${px4_instance}"
|
||||
|
||||
POSE_ARG=""
|
||||
if [ -n "${PX4_GZ_MODEL_POSE}" ]; then
|
||||
pos_x=$(echo "${PX4_GZ_MODEL_POSE}" | awk -F',' '{print $1}')
|
||||
pos_y=$(echo "${PX4_GZ_MODEL_POSE}" | awk -F',' '{print $2}')
|
||||
pos_z=$(echo "${PX4_GZ_MODEL_POSE}" | awk -F',' '{print $3}')
|
||||
pos_x=${pos_x:-0}
|
||||
pos_y=${pos_y:-0}
|
||||
pos_z=${pos_z:-0}
|
||||
|
||||
POSE_ARG=", pose: { position: { x: ${pos_x}, y: ${pos_y}, z: ${pos_z} } }"
|
||||
echo "INFO [init] Spawning model at position: ${pos_x} ${pos_y} ${pos_z}"
|
||||
fi
|
||||
|
||||
echo "INFO [init] Spawning model"
|
||||
|
||||
# Spawn model
|
||||
${gz_command} service -s "/world/${PX4_GZ_WORLD}/create" --reqtype gz.msgs.EntityFactory \
|
||||
--reptype gz.msgs.Boolean --timeout 5000 \
|
||||
--req "sdf_filename: \"${PX4_GZ_MODELS}/${MODEL_NAME}/model.sdf\", name: \"${MODEL_NAME_INSTANCE}\", allow_renaming: false${POSE_ARG}" > /dev/null 2>&1
|
||||
|
||||
# Wait for model to spawn
|
||||
sleep 1
|
||||
|
||||
# Start gz_bridge
|
||||
if ! gz_bridge start -w "${PX4_GZ_WORLD}" -n "${MODEL_NAME_INSTANCE}"; then
|
||||
echo "ERROR [init] gz_bridge failed to start and spawn model"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Set physics parameters for faster-than-realtime simulation if needed
|
||||
if [ -n "${PX4_SIM_SPEED_FACTOR}" ]; then
|
||||
echo "INFO [init] Setting simulation speed factor: ${PX4_SIM_SPEED_FACTOR}"
|
||||
${gz_command} service -s "/world/${PX4_GZ_WORLD}/set_physics" --reqtype gz.msgs.Physics \
|
||||
--reptype gz.msgs.Boolean --timeout 5000 \
|
||||
--req "real_time_factor: ${PX4_SIM_SPEED_FACTOR}" > /dev/null 2>&1
|
||||
fi
|
||||
|
||||
# Set up camera to follow the model if requested
|
||||
if [ -n "${PX4_GZ_FOLLOW}" ]; then
|
||||
|
||||
echo "INFO [init] Setting camera to follow ${MODEL_NAME_INSTANCE}"
|
||||
|
||||
# Set camera to follow the model
|
||||
${gz_command} service -s "/gui/follow" --reqtype gz.msgs.StringMsg \
|
||||
--reptype gz.msgs.Boolean --timeout 5000 \
|
||||
--req "data: \"${MODEL_NAME_INSTANCE}\"" > /dev/null 2>&1
|
||||
|
||||
# Set default camera offset if not specified
|
||||
follow_x=${PX4_GZ_FOLLOW_OFFSET_X:--2.0}
|
||||
follow_y=${PX4_GZ_FOLLOW_OFFSET_Y:--2.0}
|
||||
follow_z=${PX4_GZ_FOLLOW_OFFSET_Z:-2.0}
|
||||
|
||||
# Set camera offset
|
||||
${gz_command} service -s "/gui/follow/offset" --reqtype gz.msgs.Vector3d \
|
||||
--reptype gz.msgs.Boolean --timeout 5000 \
|
||||
--req "x: ${follow_x}, y: ${follow_y}, z: ${follow_z}" > /dev/null 2>&1
|
||||
|
||||
echo "INFO [init] Camera follow offset set to ${follow_x}, ${follow_y}, ${follow_z}"
|
||||
fi
|
||||
|
||||
elif [ -n "${PX4_GZ_MODEL_NAME}" ]; then
|
||||
# Connect to existing model
|
||||
echo "INFO [init] PX4_GZ_MODEL_NAME set, PX4 will attach to existing model"
|
||||
if ! gz_bridge start -w "${PX4_GZ_WORLD}" -n "${PX4_GZ_MODEL_NAME}"; then
|
||||
echo "ERROR [init] gz_bridge failed to start and attach to existing model"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "ERROR [init] failed to pass either PX4_GZ_MODEL_NAME or PX4_SIM_MODEL"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# NOTE: Only for rover_mecanum and spacecraft_2d. All other models have
|
||||
# the magnetometer sensor in the model.sdf.
|
||||
if param compare -s SENS_EN_MAGSIM 1
|
||||
then
|
||||
sensor_mag_sim start
|
||||
fi
|
||||
# NOTE: new gz has airspeed sensor, remove once added
|
||||
if param compare -s SENS_EN_ARSPDSIM 1
|
||||
then
|
||||
sensor_airspeed_sim start
|
||||
fi
|
||||
@@ -0,0 +1,14 @@
|
||||
#!/bin/sh
|
||||
# shellcheck disable=SC2154
|
||||
|
||||
echo "INFO [init] jMAVSim simulator"
|
||||
|
||||
if jps | grep -i jmavsim; then
|
||||
kill "$(jps | grep -i jmavsim | awk '{print $1}')" || true
|
||||
sleep 1
|
||||
fi
|
||||
|
||||
param set IMU_INTEG_RATE 250
|
||||
./jmavsim_run.sh -l -r 250 &
|
||||
|
||||
simulator_mavlink start -h localhost $((4560+px4_instance))
|
||||
@@ -0,0 +1,27 @@
|
||||
#!/bin/sh
|
||||
# shellcheck disable=SC2154
|
||||
|
||||
# EKF2 specifics
|
||||
param set-default EKF2_GPS_DELAY 10
|
||||
param set-default EKF2_MULTI_IMU 3
|
||||
param set-default SENS_IMU_MODE 0
|
||||
|
||||
simulator_tcp_port=$((4560+px4_instance))
|
||||
|
||||
# Check if PX4_SIM_HOSTNAME environment variable is empty
|
||||
# If empty check if PX4_SIM_HOST_ADDR environment variable is empty
|
||||
# If both are empty use localhost for simulator
|
||||
if [ -z "${PX4_SIM_HOSTNAME}" ]; then
|
||||
|
||||
if [ -z "${PX4_SIM_HOST_ADDR}" ]; then
|
||||
echo "INFO [init] PX4_SIM_HOSTNAME: localhost"
|
||||
simulator_mavlink start -c $simulator_tcp_port
|
||||
else
|
||||
echo "INFO [init] PX4_SIM_HOSTNAME: ${PX4_SIM_HOST_ADDR}"
|
||||
simulator_mavlink start -t "${PX4_SIM_HOST_ADDR}" "${simulator_tcp_port}"
|
||||
fi
|
||||
|
||||
else
|
||||
echo "INFO [init] PX4_SIM_HOSTNAME: ${PX4_SIM_HOSTNAME}"
|
||||
simulator_mavlink start -h "${PX4_SIM_HOSTNAME}" "${simulator_tcp_port}"
|
||||
fi
|
||||
@@ -1,5 +0,0 @@
|
||||
#!/bin/sh
|
||||
# shellcheck disable=SC2154
|
||||
|
||||
#param set-default MAV_SYS_ID $((px4_instance+1))
|
||||
#param set-default IMU_INTEG_RATE 250
|
||||
@@ -0,0 +1,38 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo "INFO [init] SIH simulator"
|
||||
|
||||
if [ -n "${PX4_HOME_LAT}" ]; then
|
||||
param set SIH_LOC_LAT0 ${PX4_HOME_LAT}
|
||||
fi
|
||||
|
||||
if [ -n "${PX4_HOME_LON}" ]; then
|
||||
param set SIH_LOC_LON0 ${PX4_HOME_LON}
|
||||
fi
|
||||
if [ -n "${PX4_HOME_ALT}" ]; then
|
||||
param set SIH_LOC_H0 ${PX4_HOME_ALT}
|
||||
fi
|
||||
|
||||
if simulator_sih start; then
|
||||
|
||||
if param compare -s SENS_EN_BAROSIM 1
|
||||
then
|
||||
sensor_baro_sim start
|
||||
fi
|
||||
if param compare -s SENS_EN_GPSSIM 1
|
||||
then
|
||||
sensor_gps_sim start
|
||||
fi
|
||||
if param compare -s SENS_EN_MAGSIM 1
|
||||
then
|
||||
sensor_mag_sim start
|
||||
fi
|
||||
if param compare -s SENS_EN_AGPSIM 1
|
||||
then
|
||||
sensor_agp_sim start
|
||||
fi
|
||||
|
||||
else
|
||||
echo "ERROR [init] simulator_sih failed to start"
|
||||
exit 1
|
||||
fi
|
||||
@@ -8,268 +8,18 @@ param set-default IMU_INTEG_RATE 250
|
||||
param set-default COM_MODE_ARM_CHK 1
|
||||
|
||||
if [ "$PX4_SIMULATOR" = "sihsim" ] || [ "$(param show -q SYS_AUTOSTART)" -eq "0" ]; then
|
||||
|
||||
echo "INFO [init] SIH simulator"
|
||||
|
||||
if [ -n "${PX4_HOME_LAT}" ]; then
|
||||
param set SIH_LOC_LAT0 ${PX4_HOME_LAT}
|
||||
fi
|
||||
|
||||
if [ -n "${PX4_HOME_LON}" ]; then
|
||||
param set SIH_LOC_LON0 ${PX4_HOME_LON}
|
||||
fi
|
||||
if [ -n "${PX4_HOME_ALT}" ]; then
|
||||
param set SIH_LOC_H0 ${PX4_HOME_ALT}
|
||||
fi
|
||||
|
||||
if simulator_sih start; then
|
||||
|
||||
if param compare -s SENS_EN_BAROSIM 1
|
||||
then
|
||||
sensor_baro_sim start
|
||||
fi
|
||||
if param compare -s SENS_EN_GPSSIM 1
|
||||
then
|
||||
sensor_gps_sim start
|
||||
fi
|
||||
if param compare -s SENS_EN_MAGSIM 1
|
||||
then
|
||||
sensor_mag_sim start
|
||||
fi
|
||||
if param compare -s SENS_EN_AGPSIM 1
|
||||
then
|
||||
sensor_agp_sim start
|
||||
fi
|
||||
|
||||
else
|
||||
echo "ERROR [init] simulator_sih failed to start"
|
||||
exit 1
|
||||
fi
|
||||
# Run SIH
|
||||
. px4-rc.sihsim
|
||||
|
||||
elif [ "$PX4_SIMULATOR" = "gz" ] || [ "$(param show -q SIM_GZ_EN)" = "1" ]; then
|
||||
# Use Gazebo
|
||||
|
||||
echo "INFO [init] Gazebo simulator"
|
||||
|
||||
# Only start up Gazebo if PX4_GZ_STANDALONE is not set.
|
||||
if [ -z "${PX4_GZ_STANDALONE}" ]; then
|
||||
|
||||
# "gz sim" only available in Garden and later
|
||||
GZ_SIM_VERSIONS=$(gz sim --versions 2>&1)
|
||||
if [ $? -eq 0 ] && [ "${GZ_SIM_VERSIONS}" != "" ]
|
||||
then
|
||||
# "gz sim" from Garden on
|
||||
gz_command="gz"
|
||||
gz_sub_command="sim"
|
||||
|
||||
# Specify render engine if `GZ_SIM_RENDER_ENGINE` is set
|
||||
# (for example, if you want to use Ogre 1.x instead of Ogre 2.x):
|
||||
if [ -n "${PX4_GZ_SIM_RENDER_ENGINE}" ]; then
|
||||
echo "INFO [init] Setting Gazebo render engine to '${PX4_GZ_SIM_RENDER_ENGINE}'!"
|
||||
gz_sub_command="${gz_sub_command} --render-engine ${PX4_GZ_SIM_RENDER_ENGINE}"
|
||||
fi
|
||||
else
|
||||
echo "ERROR [init] Gazebo gz please install gz-garden"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Look for an already running world
|
||||
gz_world=$( ${gz_command} topic -l | grep -m 1 -e "^/world/.*/clock" | sed 's/\/world\///g; s/\/clock//g' )
|
||||
|
||||
# shellcheck disable=SC2153
|
||||
if [ -z "${gz_world}" ] && [ -n "${PX4_GZ_WORLD}" ]; then
|
||||
|
||||
# Setup gz environment variables
|
||||
if [ -f ./gz_env.sh ]; then
|
||||
. ./gz_env.sh
|
||||
|
||||
elif [ -f ../gz_env.sh ]; then
|
||||
. ../gz_env.sh
|
||||
fi
|
||||
|
||||
echo "INFO [init] Starting gazebo with world: ${PX4_GZ_WORLDS}/${PX4_GZ_WORLD}.sdf"
|
||||
|
||||
${gz_command} ${gz_sub_command} --verbose=${GZ_VERBOSE:=1} -r -s "${PX4_GZ_WORLDS}/${PX4_GZ_WORLD}.sdf" &
|
||||
|
||||
if [ -z "${HEADLESS}" ]; then
|
||||
echo "INFO [init] Starting gz gui"
|
||||
${gz_command} ${gz_sub_command} -g > /dev/null 2>&1 &
|
||||
fi
|
||||
|
||||
# Wait for Gazebo world to be ready before proceeding
|
||||
check_scene_info() {
|
||||
SERVICE_INFO=$(${gz_command} service -i --service "/world/${PX4_GZ_WORLD}/scene/info" 2>&1)
|
||||
if echo "$SERVICE_INFO" | grep -q "Service providers"; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
ATTEMPTS=30
|
||||
while [ $ATTEMPTS -gt 0 ]; do
|
||||
if check_scene_info; then
|
||||
echo "INFO [init] Gazebo world is ready"
|
||||
break
|
||||
fi
|
||||
ATTEMPTS=$((ATTEMPTS-1))
|
||||
if [ $ATTEMPTS -eq 0 ]; then
|
||||
echo "ERROR [init] Timed out waiting for Gazebo world"
|
||||
exit 1
|
||||
fi
|
||||
echo "INFO [init] Waiting for Gazebo world..."
|
||||
sleep 1
|
||||
done
|
||||
|
||||
else
|
||||
# Gazebo is already running
|
||||
echo "INFO [init] gazebo already running world: ${gz_world}"
|
||||
PX4_GZ_WORLD=${gz_world}
|
||||
fi
|
||||
|
||||
else
|
||||
echo "INFO [init] Standalone PX4 launch, waiting for Gazebo"
|
||||
fi
|
||||
|
||||
# Start gz_bridge - either spawn a model or connect to existing one
|
||||
if [ -n "${PX4_SIM_MODEL#*gz_}" ] && [ -z "${PX4_GZ_MODEL_NAME}" ]; then
|
||||
# Spawn a model
|
||||
MODEL_NAME="${PX4_SIM_MODEL#*gz_}"
|
||||
MODEL_NAME_INSTANCE="${MODEL_NAME}_${px4_instance}"
|
||||
|
||||
POSE_ARG=""
|
||||
if [ -n "${PX4_GZ_MODEL_POSE}" ]; then
|
||||
pos_x=$(echo "${PX4_GZ_MODEL_POSE}" | awk -F',' '{print $1}')
|
||||
pos_y=$(echo "${PX4_GZ_MODEL_POSE}" | awk -F',' '{print $2}')
|
||||
pos_z=$(echo "${PX4_GZ_MODEL_POSE}" | awk -F',' '{print $3}')
|
||||
pos_x=${pos_x:-0}
|
||||
pos_y=${pos_y:-0}
|
||||
pos_z=${pos_z:-0}
|
||||
|
||||
POSE_ARG=", pose: { position: { x: ${pos_x}, y: ${pos_y}, z: ${pos_z} } }"
|
||||
echo "INFO [init] Spawning model at position: ${pos_x} ${pos_y} ${pos_z}"
|
||||
fi
|
||||
|
||||
echo "INFO [init] Spawning model"
|
||||
|
||||
# Spawn model
|
||||
${gz_command} service -s "/world/${PX4_GZ_WORLD}/create" --reqtype gz.msgs.EntityFactory \
|
||||
--reptype gz.msgs.Boolean --timeout 5000 \
|
||||
--req "sdf_filename: \"${PX4_GZ_MODELS}/${MODEL_NAME}/model.sdf\", name: \"${MODEL_NAME_INSTANCE}\", allow_renaming: false${POSE_ARG}" > /dev/null 2>&1
|
||||
|
||||
# Wait for model to spawn
|
||||
sleep 1
|
||||
|
||||
# Start gz_bridge
|
||||
if ! gz_bridge start -w "${PX4_GZ_WORLD}" -n "${MODEL_NAME_INSTANCE}"; then
|
||||
echo "ERROR [init] gz_bridge failed to start and spawn model"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Set physics parameters for faster-than-realtime simulation if needed
|
||||
if [ -n "${PX4_SIM_SPEED_FACTOR}" ]; then
|
||||
echo "INFO [init] Setting simulation speed factor: ${PX4_SIM_SPEED_FACTOR}"
|
||||
${gz_command} service -s "/world/${PX4_GZ_WORLD}/set_physics" --reqtype gz.msgs.Physics \
|
||||
--reptype gz.msgs.Boolean --timeout 5000 \
|
||||
--req "real_time_factor: ${PX4_SIM_SPEED_FACTOR}" > /dev/null 2>&1
|
||||
fi
|
||||
|
||||
# Set up camera to follow the model if requested
|
||||
if [ -n "${PX4_GZ_FOLLOW}" ]; then
|
||||
|
||||
echo "INFO [init] Setting camera to follow ${MODEL_NAME_INSTANCE}"
|
||||
|
||||
# Set camera to follow the model
|
||||
${gz_command} service -s "/gui/follow" --reqtype gz.msgs.StringMsg \
|
||||
--reptype gz.msgs.Boolean --timeout 5000 \
|
||||
--req "data: \"${MODEL_NAME_INSTANCE}\"" > /dev/null 2>&1
|
||||
|
||||
# Set default camera offset if not specified
|
||||
follow_x=${PX4_GZ_FOLLOW_OFFSET_X:--2.0}
|
||||
follow_y=${PX4_GZ_FOLLOW_OFFSET_Y:--2.0}
|
||||
follow_z=${PX4_GZ_FOLLOW_OFFSET_Z:-2.0}
|
||||
|
||||
# Set camera offset
|
||||
${gz_command} service -s "/gui/follow/offset" --reqtype gz.msgs.Vector3d \
|
||||
--reptype gz.msgs.Boolean --timeout 5000 \
|
||||
--req "x: ${follow_x}, y: ${follow_y}, z: ${follow_z}" > /dev/null 2>&1
|
||||
|
||||
echo "INFO [init] Camera follow offset set to ${follow_x}, ${follow_y}, ${follow_z}"
|
||||
fi
|
||||
|
||||
elif [ -n "${PX4_GZ_MODEL_NAME}" ]; then
|
||||
# Connect to existing model
|
||||
echo "INFO [init] PX4_GZ_MODEL_NAME set, PX4 will attach to existing model"
|
||||
if ! gz_bridge start -w "${PX4_GZ_WORLD}" -n "${PX4_GZ_MODEL_NAME}"; then
|
||||
echo "ERROR [init] gz_bridge failed to start and attach to existing model"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "ERROR [init] failed to pass either PX4_GZ_MODEL_NAME or PX4_SIM_MODEL"
|
||||
exit 1
|
||||
fi
|
||||
# Start the sensor simulator modules
|
||||
if param compare -s SENS_EN_BAROSIM 1
|
||||
then
|
||||
sensor_baro_sim start
|
||||
fi
|
||||
if param compare -s SENS_EN_GPSSIM 1
|
||||
then
|
||||
sensor_gps_sim start
|
||||
fi
|
||||
if param compare -s SENS_EN_MAGSIM 1
|
||||
then
|
||||
sensor_mag_sim start
|
||||
fi
|
||||
if param compare -s SENS_EN_ARSPDSIM 1
|
||||
then
|
||||
sensor_airspeed_sim start
|
||||
fi
|
||||
if param compare -s SENS_EN_AGPSIM 1
|
||||
then
|
||||
sensor_agp_sim start
|
||||
fi
|
||||
# Run Gazebo (gz)
|
||||
. px4-rc.gzsim
|
||||
|
||||
elif [ "$PX4_SIM_MODEL" = "jmavsim_iris" ] || [ "$(param show -q SYS_AUTOSTART)" -eq "10017" ]; then
|
||||
|
||||
echo "INFO [init] jMAVSim simulator"
|
||||
|
||||
if jps | grep -i jmavsim; then
|
||||
kill "$(jps | grep -i jmavsim | awk '{print $1}')" || true
|
||||
sleep 1
|
||||
fi
|
||||
|
||||
param set IMU_INTEG_RATE 250
|
||||
./jmavsim_run.sh -l -r 250 &
|
||||
|
||||
simulator_mavlink start -h localhost $((4560+px4_instance))
|
||||
# Run jMAVSim
|
||||
. px4-rc.jmavsim
|
||||
|
||||
else
|
||||
# otherwise start simulator (mavlink) module
|
||||
|
||||
# EKF2 specifics
|
||||
param set-default EKF2_GPS_DELAY 10
|
||||
param set-default EKF2_MULTI_IMU 3
|
||||
param set-default SENS_IMU_MODE 0
|
||||
|
||||
simulator_tcp_port=$((4560+px4_instance))
|
||||
|
||||
# Check if PX4_SIM_HOSTNAME environment variable is empty
|
||||
# If empty check if PX4_SIM_HOST_ADDR environment variable is empty
|
||||
# If both are empty use localhost for simulator
|
||||
if [ -z "${PX4_SIM_HOSTNAME}" ]; then
|
||||
|
||||
if [ -z "${PX4_SIM_HOST_ADDR}" ]; then
|
||||
echo "INFO [init] PX4_SIM_HOSTNAME: localhost"
|
||||
simulator_mavlink start -c $simulator_tcp_port
|
||||
else
|
||||
echo "INFO [init] PX4_SIM_HOSTNAME: ${PX4_SIM_HOST_ADDR}"
|
||||
simulator_mavlink start -t "${PX4_SIM_HOST_ADDR}" "${simulator_tcp_port}"
|
||||
fi
|
||||
|
||||
else
|
||||
echo "INFO [init] PX4_SIM_HOSTNAME: ${PX4_SIM_HOSTNAME}"
|
||||
simulator_mavlink start -h "${PX4_SIM_HOSTNAME}" "${simulator_tcp_port}"
|
||||
fi
|
||||
|
||||
# Run simulator_mavlink module for interface with gazebo-classic
|
||||
. px4-rc.mavlinksim
|
||||
fi
|
||||
|
||||
@@ -126,6 +126,15 @@ then
|
||||
set AUTOCNF yes
|
||||
fi
|
||||
|
||||
# Allow overriding parameters via env variables: export PX4_PARAM_{name}={value}
|
||||
env | while IFS='=' read -r line; do
|
||||
value=${line#*=}
|
||||
name=${line%%=*}
|
||||
case $name in
|
||||
"PX4_PARAM_"*) param set "${name#PX4_PARAM_}" "$value" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# multi-instance setup
|
||||
# shellcheck disable=SC2154
|
||||
param set MAV_SYS_ID $((px4_instance+1))
|
||||
@@ -227,9 +236,6 @@ then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#user defined params for instances can be in PATH
|
||||
. px4-rc.params
|
||||
|
||||
dataman start
|
||||
|
||||
# only start the simulator if not in replay mode, as both control the lockstep time
|
||||
|
||||
@@ -71,12 +71,6 @@ then
|
||||
fi
|
||||
|
||||
|
||||
# Heater driver for temperature regulated IMUs.
|
||||
if param compare -s SENS_EN_THERMAL 1
|
||||
then
|
||||
heater start
|
||||
fi
|
||||
|
||||
# Teraranger one tof sensor
|
||||
if param greater -s SENS_EN_TRANGER 0
|
||||
then
|
||||
|
||||
@@ -404,6 +404,14 @@ else
|
||||
fi
|
||||
fi
|
||||
|
||||
# Heater driver for temperature regulated IMUs.
|
||||
# The heater needs to start after px4io.
|
||||
if param compare -s SENS_EN_THERMAL 1
|
||||
then
|
||||
heater start
|
||||
fi
|
||||
|
||||
|
||||
#
|
||||
# RC update (map raw RC input to calibrate manual control)
|
||||
# start before commander
|
||||
|
||||
@@ -1,172 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import nacl.encoding
|
||||
import nacl.signing
|
||||
import nacl.hash
|
||||
import struct
|
||||
import binascii
|
||||
import json
|
||||
import time
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
import sys
|
||||
|
||||
def make_public_key_h_file(signing_key,key_name):
|
||||
"""
|
||||
This file generate the public key header file
|
||||
to be included into the bootloader build.
|
||||
"""
|
||||
public_key_c='\n'
|
||||
for i,c in enumerate(signing_key.verify_key.encode(encoder=nacl.encoding.RawEncoder)):
|
||||
public_key_c+= hex(c)
|
||||
public_key_c+= ', '
|
||||
if((i+1)%8==0):
|
||||
public_key_c+= '\n'
|
||||
with open(key_name+'.pub' ,mode='w') as f:
|
||||
f.write("//Public key to verify signed binaries")
|
||||
f.write(public_key_c)
|
||||
|
||||
def make_key_file(signing_key, key_name):
|
||||
"""
|
||||
Writes the key.json file.
|
||||
Attention do not override your existing key files.
|
||||
Do not publish your private key!!
|
||||
"""
|
||||
|
||||
key_file = Path(key_name+'.json')
|
||||
if key_file.is_file():
|
||||
print("ATTENTION: key.json already exists, are you sure you want to overwrite it?")
|
||||
print("Remove file and run script again.")
|
||||
print("Script aborted!")
|
||||
sys.exit(1)
|
||||
|
||||
keys={}
|
||||
keys["date"] = time.asctime()
|
||||
keys["public"] = (signing_key.verify_key.encode(encoder=nacl.encoding.HexEncoder)).decode()
|
||||
keys["private"] = binascii.hexlify(signing_key._seed).decode()
|
||||
#print (keys)
|
||||
with open(key_name+'.json', "w") as write_file:
|
||||
json.dump(keys, write_file)
|
||||
return keys
|
||||
|
||||
def ed25519_sign(private_key, signee_bin):
|
||||
"""
|
||||
This function creates the signature. It takes the private key and the binary file
|
||||
and returns the tuple (signature, public key)
|
||||
"""
|
||||
|
||||
signing_key = nacl.signing.SigningKey(private_key, encoder=nacl.encoding.HexEncoder)
|
||||
|
||||
# Sign a message with the signing key
|
||||
signed = signing_key.sign(signee_bin,encoder=nacl.encoding.RawEncoder)
|
||||
|
||||
# Obtain the verify key for a given signing key
|
||||
verify_key = signing_key.verify_key
|
||||
|
||||
# Serialize the verify key to send it to a third party
|
||||
verify_key_hex = verify_key.encode(encoder=nacl.encoding.HexEncoder)
|
||||
|
||||
return signed.signature, verify_key_hex
|
||||
|
||||
|
||||
def sign(bin_file_path, key_file_path=None, generated_key_file=None):
|
||||
"""
|
||||
reads the binary file and the key file.
|
||||
If the key file does not exist, it generates a
|
||||
new key file.
|
||||
"""
|
||||
|
||||
with open(bin_file_path,mode='rb') as f:
|
||||
signee_bin = f.read()
|
||||
# Align to 4 bytes. Signature always starts at
|
||||
# 4 byte aligned address, but the signee size
|
||||
# might not be aligned
|
||||
if len(signee_bin)%4 != 0:
|
||||
signee_bin += bytearray(b'\xff')*(4-len(signee_bin)%4)
|
||||
|
||||
try:
|
||||
with open(key_file_path,mode='r') as f:
|
||||
keys = json.load(f)
|
||||
#print(keys)
|
||||
except:
|
||||
print('ERROR: Key file',key_file_path,'not found')
|
||||
sys.exit(1)
|
||||
|
||||
signature, public_key = ed25519_sign(keys["private"], signee_bin)
|
||||
|
||||
# Do a sanity check. This type of signature is always 64 bytes long
|
||||
assert len(signature) == 64
|
||||
|
||||
# Print out the signing information
|
||||
print("Binary \"%s\" signed."%bin_file_path)
|
||||
print("Signature:",binascii.hexlify(signature))
|
||||
print("Public key:",binascii.hexlify(public_key))
|
||||
|
||||
return signee_bin + signature, public_key
|
||||
|
||||
def generate_key(key_file):
|
||||
"""
|
||||
Generate two files:
|
||||
"key_file.pub" containing the public key in C-format to be included in the bootloader build
|
||||
"key_file.json, containt both private and public key.
|
||||
Do not leak or loose the key file. This is mandatory for signing
|
||||
all future binaries you want to deploy!
|
||||
"""
|
||||
|
||||
# Generate a new random signing key
|
||||
signing_key = nacl.signing.SigningKey.generate()
|
||||
# Serialize the verify key to send it to a third party
|
||||
verify_key_hex = signing_key.verify_key.encode(encoder=nacl.encoding.HexEncoder)
|
||||
print("public key :",verify_key_hex)
|
||||
|
||||
private_key_hex=binascii.hexlify(signing_key._seed)
|
||||
print("private key :",private_key_hex)
|
||||
|
||||
keys = make_key_file(signing_key,key_file)
|
||||
make_public_key_h_file(signing_key,key_file)
|
||||
return keys
|
||||
|
||||
if(__name__ == "__main__"):
|
||||
|
||||
parser = argparse.ArgumentParser(description="""CLI tool to calculate and add signature to px4. bin files\n
|
||||
if given it takes an existing key file, else it generate new keys""",
|
||||
epilog="Output: SignedBin.bin and a key.json file")
|
||||
parser.add_argument("signee", help=".bin file to add signature", nargs='?', default=None)
|
||||
parser.add_argument("signed", help="signed output .bin", nargs='?', default=None)
|
||||
|
||||
parser.add_argument("--key", help="key.json file", default="Tools/test_keys/test_keys.json")
|
||||
parser.add_argument("--rdct", help="binary R&D certificate file", default=None)
|
||||
parser.add_argument("--genkey", help="new generated key", default=None)
|
||||
args = parser.parse_args()
|
||||
|
||||
# Only generate a key pair, don't sign
|
||||
if args.genkey:
|
||||
# Only create a key file, don't sign
|
||||
generate_key(args.genkey)
|
||||
print('New key file generated:',args.genkey)
|
||||
sys.exit(0);
|
||||
|
||||
# Check that both signee and signed exist
|
||||
if not args.signee or not args.signed:
|
||||
print("ERROR: Must either provide file names for both signee and signed")
|
||||
print(" or --genkey [key] to generate a new key pair")
|
||||
sys.exit(1)
|
||||
|
||||
# Issue a warning when signing with testing key
|
||||
if args.key=='Tools/test_keys/test_keys.json':
|
||||
print("WARNING: Signing with PX4 test key")
|
||||
|
||||
# Sign the binary
|
||||
signed, public_key = sign(args.signee, args.key, args.genkey)
|
||||
|
||||
with open(args.signed, mode='wb') as fs:
|
||||
# Write signed binary
|
||||
fs.write(signed)
|
||||
|
||||
# Append rdcert if given
|
||||
try:
|
||||
with open(args.rdct ,mode='rb') as f:
|
||||
with open(args.signed, mode='ab') as fs:
|
||||
fs.write(f.read())
|
||||
except:
|
||||
pass
|
||||
@@ -1,91 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
|
||||
try:
|
||||
from Crypto.Cipher import ChaCha20
|
||||
except ImportError as e:
|
||||
print("Failed to import crypto: " + str(e))
|
||||
print("")
|
||||
print("You may need to install it using:")
|
||||
print(" pip3 install --user pycryptodome")
|
||||
print("")
|
||||
sys.exit(1)
|
||||
|
||||
from Crypto.PublicKey import RSA
|
||||
from Crypto.Cipher import PKCS1_OAEP
|
||||
from Crypto.Hash import SHA256
|
||||
from pathlib import Path
|
||||
import argparse
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
parser = argparse.ArgumentParser(description="""CLI tool to decrypt an ulog file\n""")
|
||||
parser.add_argument("ulog_file", help=".ulge/.ulgc, encrypted log file", nargs='?', default=None)
|
||||
parser.add_argument("ulog_key", help=".ulgk, legacy encrypted key (give empty string '' to ignore for .ulge)", nargs='?', default=None)
|
||||
parser.add_argument("rsa_key", help=".pem format key for decrypting the ulog key", nargs='?', default=None)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Check all arguments are given
|
||||
if not args.rsa_key:
|
||||
print('Need all arguments, the encrypted ulog file, key file (or empty string if not needed) and the key decryption key (.pem)')
|
||||
sys.exit(1)
|
||||
|
||||
# Read the private RSA key to decrypt the cahcha key
|
||||
with open(args.rsa_key, 'rb') as f:
|
||||
r = RSA.importKey(f.read(), passphrase='')
|
||||
|
||||
if args.ulog_key == "":
|
||||
key_data_filename = args.ulog_file
|
||||
magic = "ULogEnc"
|
||||
else:
|
||||
key_data_filename = args.ulog_key
|
||||
magic = "ULogKey"
|
||||
|
||||
with open(key_data_filename, 'rb') as f:
|
||||
# Read the encrypted xchacha key and the nonce
|
||||
ulog_key_header = f.read(22)
|
||||
|
||||
# Parse the header
|
||||
try:
|
||||
# magic
|
||||
if not ulog_key_header.startswith(bytearray(magic.encode())):
|
||||
print("Incorrect header magic")
|
||||
raise Exception()
|
||||
# version
|
||||
if ulog_key_header[7] != 1:
|
||||
print("Unsupported header version")
|
||||
raise Exception()
|
||||
# expected key exchange algorithm (RSA_OAEP)
|
||||
if ulog_key_header[16] != 4:
|
||||
print("Unsupported key algorithm")
|
||||
raise Exception()
|
||||
key_size = ulog_key_header[19] << 8 | ulog_key_header[18]
|
||||
nonce_size = ulog_key_header[21] << 8 | ulog_key_header[20]
|
||||
ulog_key_cipher = f.read(key_size)
|
||||
nonce = f.read(nonce_size)
|
||||
except:
|
||||
print("Keydata format error")
|
||||
sys.exit(1)
|
||||
|
||||
if magic == "ULogEnc":
|
||||
data_offset = 22 + key_size + nonce_size
|
||||
else:
|
||||
data_offset = 0
|
||||
|
||||
# Decrypt the xchacha key
|
||||
cipher_rsa = PKCS1_OAEP.new(r,SHA256)
|
||||
ulog_key = cipher_rsa.decrypt(ulog_key_cipher)
|
||||
#print(binascii.hexlify(ulog_key))
|
||||
|
||||
# Read and decrypt the ulog data
|
||||
cipher = ChaCha20.new(key=ulog_key, nonce=nonce)
|
||||
|
||||
outfilename = Path(args.ulog_file).stem + ".ulog"
|
||||
with open(args.ulog_file, 'rb') as f:
|
||||
if data_offset > 0:
|
||||
f.seek(data_offset)
|
||||
with open(outfilename, 'wb') as out:
|
||||
out.write(cipher.decrypt(f.read()))
|
||||
@@ -0,0 +1,86 @@
|
||||
# PX4 Log Encryption Tools
|
||||
|
||||
Tools for generating encryption keys, building PX4 firmware with encrypted logs, downloading logs, and decrypting them.
|
||||
|
||||
For more information see: https://docs.px4.io/main/en/dev_log/log_encryption.html
|
||||
|
||||
## Usage
|
||||
|
||||
1. **Get the board file**:
|
||||
In order to use these tools you need to create an `encrypted_logs` target in your target board directory. For example:
|
||||
```bash
|
||||
encrypted_logs.px4board
|
||||
```
|
||||
Using `make menuconfig` you should enable these settings: `Blake2s hash algorithm`, `entropy pool` and `strong random number generator` and select `use interrupts` to feed timing randomness to the entropy pool.
|
||||
Once you have generated the keys make sure you add them to the boardconfig.
|
||||
|
||||
```bash
|
||||
make <your_board_name>_encrypted_logs menuconfig
|
||||
```
|
||||
|
||||
2. **Generate Keys**:
|
||||
```bash
|
||||
cd PX4-Autopilot/Tools/log_encryption
|
||||
python3 generate_keys.py
|
||||
```
|
||||
|
||||
Make sure you have the right key in your board file
|
||||
```CONFIG_PUBLIC_KEY1="../../../keys/public/public_key.pub"```
|
||||
|
||||
3. **Build Firmware**:
|
||||
```bash
|
||||
cd PX4-Autopilot
|
||||
|
||||
AND
|
||||
|
||||
make <your_board_name>_encrypted_logs
|
||||
|
||||
FOR INSTANCE
|
||||
make_ark_fpv_encrypted_logs
|
||||
|
||||
Upload the custom firmware on your flight controller and record some logs
|
||||
```
|
||||
|
||||
4. **Download Logs**:
|
||||
```bash
|
||||
cd PX4-Autopilot/Tools/log_encryption
|
||||
|
||||
python3 download_logs.py /dev/ttyACM0 --baudrate 57600
|
||||
|
||||
OR
|
||||
|
||||
python3 download_logs.py udp:0.0.0.0:14550
|
||||
```
|
||||
|
||||
Addresses might need to be adjusted
|
||||
|
||||
5. **Decrypt Logs**:
|
||||
The easiest way to run this is to have your private key and encrypted logs in the following folders respectively:
|
||||
```bash
|
||||
PX4-Autopilot/keys/private
|
||||
PX4-Autopilot/logs/encrypted
|
||||
```
|
||||
Then run:
|
||||
```bash
|
||||
cd PX4-Autopilot/Tools/log_encryption
|
||||
|
||||
AND
|
||||
# Uses default key + default folder
|
||||
python3 decrypt_logs.py
|
||||
|
||||
OR
|
||||
# Use --help to get all the options
|
||||
python3 decrypt_logs.py --help
|
||||
```
|
||||
|
||||
Your decrypted logs can be found in:
|
||||
```bash
|
||||
PX4-Autopilot/logs/decrypted
|
||||
```
|
||||
Otherwise
|
||||
|
||||
## Directory Structure
|
||||
|
||||
- **`keys/`**: Encryption keys.
|
||||
- **`logs/encrypted/`**: Downloaded encrypted logs.
|
||||
- **`logs/decrypted/`**: Decrypted logs.
|
||||
@@ -0,0 +1,135 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import sys
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
|
||||
try:
|
||||
from Crypto.Cipher import ChaCha20
|
||||
from Crypto.PublicKey import RSA
|
||||
from Crypto.Cipher import PKCS1_OAEP
|
||||
from Crypto.Hash import SHA256
|
||||
except ImportError as e:
|
||||
print("Failed to import crypto: " + str(e))
|
||||
print("You may need to install it using:")
|
||||
print(" pip3 install --user pycryptodome")
|
||||
sys.exit(1)
|
||||
|
||||
PX4_MAIN_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), "../.."))
|
||||
ENCRYPTED_LOGS_DIR = os.path.join(PX4_MAIN_DIR, "logs/encrypted")
|
||||
DECRYPTED_LOGS_DIR = os.path.join(PX4_MAIN_DIR, "logs/decrypted")
|
||||
DEFAULT_PRIVATE_KEY = os.path.join(PX4_MAIN_DIR, "keys/private/private_key.pem")
|
||||
|
||||
def decrypt_log_file(ulog_file, private_key, output_folder):
|
||||
"""Decrypts a single encrypted log file (.ulge) and saves it as .ulg in the output folder."""
|
||||
|
||||
try:
|
||||
# Read the private RSA key
|
||||
with open(private_key, 'rb') as f:
|
||||
key = RSA.import_key(f.read())
|
||||
|
||||
magic = "ULogEnc"
|
||||
header_size = 22
|
||||
|
||||
with open(ulog_file, 'rb') as f:
|
||||
# Encrypted .ulge file contains following sections:
|
||||
# -------------------------
|
||||
# | Header |
|
||||
# -------------------------
|
||||
# | Wrapped symmetric key |
|
||||
# -------------------------
|
||||
# | Encrypted ulog data |
|
||||
# -------------------------
|
||||
header = f.read(header_size)
|
||||
|
||||
# Parse the header
|
||||
if not header.startswith(bytearray(magic.encode())):
|
||||
print(f"Skipping {ulog_file}: Incorrect header magic")
|
||||
return
|
||||
if header[7] != 1:
|
||||
print(f"Skipping {ulog_file}: Unsupported header version")
|
||||
return
|
||||
if header[16] != 4:
|
||||
print(f"Skipping {ulog_file}: Unsupported key algorithm")
|
||||
return
|
||||
|
||||
key_size = header[19] << 8 | header[18]
|
||||
nonce_size = header[21] << 8 | header[20]
|
||||
cipher = f.read(key_size)
|
||||
nonce = f.read(nonce_size)
|
||||
|
||||
data_offset = header_size + key_size + nonce_size
|
||||
|
||||
# Try to decrypt the ChaCha key
|
||||
cipher_rsa = PKCS1_OAEP.new(key, SHA256)
|
||||
try:
|
||||
ulog_key = cipher_rsa.decrypt(cipher)
|
||||
except ValueError:
|
||||
print(f"Skipping {ulog_file}: Incorrect decryption (wrong key)")
|
||||
return
|
||||
|
||||
# Read and decrypt the log data
|
||||
cipher = ChaCha20.new(key=ulog_key, nonce=nonce)
|
||||
|
||||
# Save decrypted log with .ulg extension
|
||||
output_path = os.path.join(output_folder, Path(ulog_file).stem + ".ulg")
|
||||
with open(ulog_file, 'rb') as f:
|
||||
if data_offset > 0:
|
||||
f.seek(data_offset)
|
||||
with open(output_path, 'wb') as out:
|
||||
out.write(cipher.decrypt(f.read()))
|
||||
|
||||
print(f"{output_path}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"Skipping {ulog_file}: Error occurred - {e}")
|
||||
|
||||
|
||||
def decrypt_all_logs(private_key_path, log_source_path=None):
|
||||
"""Decrypts all logs in the given folder or a single file."""
|
||||
|
||||
if log_source_path and os.path.isfile(log_source_path):
|
||||
logs = [log_source_path]
|
||||
else:
|
||||
# Use default encrypted logs directory if not provided
|
||||
folder = log_source_path if log_source_path else ENCRYPTED_LOGS_DIR
|
||||
logs = [os.path.join(folder, f) for f in os.listdir(folder) if f.endswith(".ulge")]
|
||||
|
||||
if not logs:
|
||||
print("No encrypted logs found.")
|
||||
return
|
||||
|
||||
print(f"Found {len(logs)} encrypted log(s). Decrypting...")
|
||||
|
||||
os.makedirs(DECRYPTED_LOGS_DIR, exist_ok=True)
|
||||
|
||||
for log_path in logs:
|
||||
decrypt_log_file(log_path, private_key_path, DECRYPTED_LOGS_DIR)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Decrypt PX4 encrypted log files (.ulge) using a ChaCha20+RSA scheme.\n\n"
|
||||
"Usage examples:\n"
|
||||
" python3 decrypt_logs.py /path/to/private_key.pem /path/to/custom_log.ulge\n"
|
||||
" python3 decrypt_logs.py /path/to/private_key.pem /path/to/folder_with_ulge_files\n"
|
||||
" python3 decrypt_logs.py # Uses default key + default log folder\n",
|
||||
formatter_class=argparse.RawTextHelpFormatter
|
||||
)
|
||||
|
||||
parser.add_argument("private_key", nargs="?", default=None,
|
||||
help="Path to the private RSA key (.pem). If omitted, uses default key.")
|
||||
parser.add_argument("log_file_or_folder", nargs="?", default=None,
|
||||
help="Path to a single .ulge file or folder containing them. If omitted, uses default encrypted log folder.")
|
||||
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
private_key_path = args.private_key if args.private_key else DEFAULT_PRIVATE_KEY
|
||||
|
||||
if not os.path.exists(private_key_path):
|
||||
print(f"Error: Private key file not found at {private_key_path}")
|
||||
sys.exit(1)
|
||||
|
||||
decrypt_all_logs(private_key_path, args.log_file_or_folder)
|
||||
@@ -0,0 +1,190 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import shutil
|
||||
import threading
|
||||
from pymavlink import mavutil
|
||||
from argparse import ArgumentParser
|
||||
|
||||
class MavlinkLogDownloader:
|
||||
def __init__(self, connection_url, output_dir, baudrate=57600, source_system=254):
|
||||
self.connection_url = connection_url
|
||||
self.output_dir = output_dir
|
||||
self.encrypted_dir = os.path.join(output_dir, "encrypted")
|
||||
self.running = True
|
||||
|
||||
# Ensure directories exist
|
||||
os.makedirs(self.output_dir, exist_ok=True)
|
||||
os.makedirs(self.encrypted_dir, exist_ok=True)
|
||||
|
||||
# # Handle serial or UDP connections
|
||||
if os.path.exists(connection_url): # likely a serial device
|
||||
self.mav = mavutil.mavlink_connection(connection_url, baud=baudrate, source_system=source_system)
|
||||
else:
|
||||
self.mav = mavutil.mavlink_connection(connection_url, source_system=source_system)
|
||||
|
||||
|
||||
self.mav.WIRE_PROTOCOL_VERSION = "2.0"
|
||||
|
||||
# Start heartbeat thread
|
||||
self.heartbeat_thread = threading.Thread(target=self.send_heartbeat_thread)
|
||||
self.heartbeat_thread.daemon = True
|
||||
self.heartbeat_thread.start()
|
||||
|
||||
self.mav.wait_heartbeat()
|
||||
print(f"Heartbeat received from system {self.mav.target_system}, component {self.mav.target_component}")
|
||||
|
||||
# Waking up the autopilot, it is needed to ensure we get answer for log request
|
||||
self.mav.mav.command_long_send(
|
||||
self.mav.target_system,
|
||||
self.mav.target_component,
|
||||
mavutil.mavlink.MAV_CMD_REQUEST_MESSAGE, # Command ID 512
|
||||
0, # Confirmation
|
||||
mavutil.mavlink.MAVLINK_MSG_ID_AUTOPILOT_VERSION, # param1: Message ID 148
|
||||
0, 0, 0, 0, 0, 0 # params 2–7 are not used for this message
|
||||
)
|
||||
|
||||
# Allow heartbeats to establish connection
|
||||
time.sleep(3)
|
||||
|
||||
|
||||
def send_heartbeat_thread(self):
|
||||
while self.running:
|
||||
self.mav.mav.heartbeat_send(
|
||||
mavutil.mavlink.MAV_TYPE_GCS,
|
||||
mavutil.mavlink.MAV_AUTOPILOT_GENERIC,
|
||||
0, 0, 0
|
||||
)
|
||||
time.sleep(1)
|
||||
|
||||
|
||||
def download_logs(self):
|
||||
"""Downloads logs to the output_dir."""
|
||||
print("Request logs...")
|
||||
self.mav.mav.log_request_list_send(self.mav.target_system, self.mav.target_component, 0, 0xFFFF)
|
||||
|
||||
log_entries = {}
|
||||
total_logs = None
|
||||
start_time = time.time()
|
||||
last_entry_time = None
|
||||
|
||||
while True:
|
||||
current_time = time.time()
|
||||
|
||||
# Case 1: If we haven't received any entries yet and we've waited more than 5 seconds
|
||||
if not log_entries and current_time > start_time + 5:
|
||||
print("Timed out waiting for first log entry (5s)")
|
||||
break
|
||||
|
||||
# Case 2: If we have received at least one entry and it's been more than 3 seconds since the last one
|
||||
if last_entry_time and current_time - last_entry_time > 3:
|
||||
print(f"No new log entries received for 3 seconds. Moving on.")
|
||||
break
|
||||
|
||||
# Case 3: If we've received all expected logs
|
||||
if total_logs is not None and len(log_entries) >= total_logs:
|
||||
print(f"Received all {total_logs} log entries.")
|
||||
break
|
||||
|
||||
msg = self.mav.recv_match(type='LOG_ENTRY', blocking=True, timeout=1)
|
||||
|
||||
if msg and msg.id not in log_entries:
|
||||
last_entry_time = time.time()
|
||||
log_entries[msg.id] = msg
|
||||
|
||||
if total_logs is None:
|
||||
total_logs = msg.num_logs
|
||||
|
||||
print(f"Log ID: {msg.id}, Size: {msg.size} bytes, Date: {msg.time_utc} ({len(log_entries)}/{total_logs})")
|
||||
|
||||
if not log_entries:
|
||||
print("No log entries found.")
|
||||
return
|
||||
|
||||
for entry in log_entries.values():
|
||||
self.download_log_file(entry)
|
||||
|
||||
self.classify_logs()
|
||||
|
||||
|
||||
def download_log_file(self, log_entry):
|
||||
"""Downloads a log file to the output_dir."""
|
||||
log_id = log_entry.id
|
||||
log_size = log_entry.size
|
||||
log_date = time.strftime("%Y-%m-%d_%H-%M-%S", time.gmtime(log_entry.time_utc))
|
||||
output_filename = os.path.join(self.output_dir, f"log-{log_date}_{log_id}.ulg")
|
||||
|
||||
print(f"Downloading log {log_id} ({log_size} bytes) to {output_filename}...")
|
||||
|
||||
with open(output_filename, 'wb') as f:
|
||||
self.mav.mav.log_request_data_send(self.mav.target_system, self.mav.target_component, log_id, 0, 0xFFFFFFFF)
|
||||
|
||||
bytes_received = 0
|
||||
while bytes_received < log_size:
|
||||
msg = self.mav.recv_match(type='LOG_DATA', blocking=True, timeout=5)
|
||||
if msg:
|
||||
data_bytes = bytes(msg.data[:msg.count])
|
||||
f.write(data_bytes)
|
||||
bytes_received += msg.count
|
||||
else:
|
||||
print("Timeout waiting for log data.")
|
||||
break
|
||||
|
||||
print(f"Finished downloading log {log_id}.")
|
||||
|
||||
def classify_logs(self):
|
||||
"""Classifies logs as encrypted (.ulge) based on file content."""
|
||||
for log_file in os.listdir(self.output_dir):
|
||||
log_path = os.path.join(self.output_dir, log_file)
|
||||
|
||||
if not os.path.isfile(log_path):
|
||||
continue
|
||||
|
||||
# Read first 10 bytes to check for "ULogEnc"
|
||||
with open(log_path, 'rb') as f:
|
||||
first_bytes = f.read(10)
|
||||
|
||||
if b'ULogEnc' in first_bytes:
|
||||
new_filename = log_file.replace(".ulg", ".ulge")
|
||||
new_path = os.path.join(self.encrypted_dir, new_filename)
|
||||
print(f"Found encrypted log: {new_path}")
|
||||
shutil.move(log_path, new_path)
|
||||
|
||||
|
||||
def cleanup(self):
|
||||
"""Stop the heartbeat thread and clean up resources."""
|
||||
self.running = False
|
||||
if self.heartbeat_thread.is_alive():
|
||||
self.heartbeat_thread.join(timeout=2.0)
|
||||
|
||||
|
||||
def main():
|
||||
parser = ArgumentParser(description="Download PX4 log files over MAVLink.")
|
||||
parser.add_argument('connection_url', help="MAVLink connection URL (e.g., udp:0.0.0.0:14550, /dev/ttyACM0 --baudrate 57600)")
|
||||
parser.add_argument('--output', '-o', default=os.path.join(os.path.dirname(__file__), "../..", "logs"), help="Output directory for log files (default: ../../logs)")
|
||||
parser.add_argument('--baudrate', type=int, default=57600, help="Baudrate for serial connection (default: 57600)")
|
||||
parser.add_argument('--source-system', type=int, default=254, help="MAVLink source system ID (default: 254)")
|
||||
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
output_dir = os.path.abspath(args.output)
|
||||
|
||||
print(f"Connecting to {args.connection_url}...")
|
||||
log_downloader = MavlinkLogDownloader(
|
||||
args.connection_url,
|
||||
output_dir,
|
||||
baudrate=args.baudrate,
|
||||
source_system=args.source_system
|
||||
)
|
||||
|
||||
|
||||
try:
|
||||
log_downloader.download_logs()
|
||||
finally:
|
||||
log_downloader.cleanup()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,59 @@
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
# Define the main PX4 directory (one level up from Tools)
|
||||
PX4_MAIN_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), "../.."))
|
||||
|
||||
# Define the key folder paths
|
||||
KEY_FOLDER = os.path.join(PX4_MAIN_DIR, "keys")
|
||||
PUBLIC_KEY_FOLDER = os.path.join(KEY_FOLDER, "public")
|
||||
PRIVATE_KEY_FOLDER = os.path.join(KEY_FOLDER, "private")
|
||||
|
||||
# Define the key file paths
|
||||
PRIVATE_KEY_PATH = os.path.join(PRIVATE_KEY_FOLDER, "private_key.pem")
|
||||
PUBLIC_KEY_DER_PATH = os.path.join(PUBLIC_KEY_FOLDER, "public_key.der")
|
||||
PUBLIC_KEY_PUB_PATH = os.path.join(PUBLIC_KEY_FOLDER, "public_key.pub")
|
||||
|
||||
def create_key_folders():
|
||||
"""Creates key, public, and private folders if they do not exist."""
|
||||
for folder in [KEY_FOLDER, PUBLIC_KEY_FOLDER, PRIVATE_KEY_FOLDER]:
|
||||
if not os.path.exists(folder):
|
||||
os.makedirs(folder)
|
||||
print(f"Created '{folder}' directory.")
|
||||
else:
|
||||
print(f"'{folder}' directory already exists.")
|
||||
|
||||
def generate_private_key():
|
||||
"""Generates a private key if it does not exist."""
|
||||
if not os.path.exists(PRIVATE_KEY_PATH):
|
||||
print("Generating private key...")
|
||||
subprocess.run(["openssl", "genpkey", "-algorithm", "RSA", "-out", PRIVATE_KEY_PATH, "-pkeyopt", "rsa_keygen_bits:2048"])
|
||||
print(f"Private key generated at: {PRIVATE_KEY_PATH}")
|
||||
else:
|
||||
print("Private key already exists.")
|
||||
|
||||
def generate_public_key():
|
||||
"""Generates a public key in DER and PUB formats if they do not exist."""
|
||||
if not os.path.exists(PUBLIC_KEY_DER_PATH):
|
||||
print("Generating public key in DER format...")
|
||||
subprocess.run(["openssl", "rsa", "-pubout", "-in", PRIVATE_KEY_PATH, "-outform", "DER", "-out", PUBLIC_KEY_DER_PATH])
|
||||
print(f"Public key (DER) generated at: {PUBLIC_KEY_DER_PATH}")
|
||||
else:
|
||||
print("Public key (DER) already exists.")
|
||||
|
||||
if not os.path.exists(PUBLIC_KEY_PUB_PATH):
|
||||
print("Generating public key in hex format...")
|
||||
with open(PUBLIC_KEY_PUB_PATH, "w") as pub_file:
|
||||
process = subprocess.Popen(["xxd", "-p", PUBLIC_KEY_DER_PATH], stdout=subprocess.PIPE)
|
||||
output, _ = process.communicate()
|
||||
hex_string = output.decode().strip().replace("\n", "")
|
||||
formatted_hex = ", ".join(f"0x{hex_string[i:i+2]}" for i in range(0, len(hex_string), 2))
|
||||
pub_file.write(formatted_hex)
|
||||
print(f"Public key (hex) generated at: {PUBLIC_KEY_PUB_PATH}")
|
||||
else:
|
||||
print("Public key (hex) already exists.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
create_key_folders()
|
||||
generate_private_key()
|
||||
generate_public_key()
|
||||
@@ -30,12 +30,12 @@ def find_matching_brackets(brackets, s, verbose):
|
||||
|
||||
def extract_timer(line):
|
||||
# Try format: initIOTimer(Timer::Timer5, DMA{DMA::Index1, DMA::Stream0, DMA::Channel6}),
|
||||
search = re.search('Timer::([0-9a-zA-Z_]+)[,\)]', line, re.IGNORECASE)
|
||||
search = re.search('Timer::([0-9a-zA-Z_]+)[,)]', line, re.IGNORECASE)
|
||||
if search:
|
||||
return search.group(1), 'generic'
|
||||
|
||||
# NXP FlexPWM format format: initIOPWM(PWM::FlexPWM2),
|
||||
search = re.search('PWM::Flex([0-9a-zA-Z_]+)..PWM::Submodule([0-9])[,\)]', line, re.IGNORECASE)
|
||||
search = re.search('PWM::Flex([0-9a-zA-Z_]+)..PWM::Submodule([0-9])[,)]', line, re.IGNORECASE)
|
||||
if search:
|
||||
return (search.group(1) + '_' + search.group(2)), 'imxrt'
|
||||
|
||||
|
||||
+3
-3
@@ -59,7 +59,7 @@ from sys import platform as _platform
|
||||
|
||||
def get_version():
|
||||
"""
|
||||
Get PX4 Firmware latest Git tag.
|
||||
Get PX4-Autopilot Latest Git Tag.
|
||||
"""
|
||||
px4_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
@@ -74,7 +74,7 @@ def get_version():
|
||||
exit(1)
|
||||
else:
|
||||
# Else, get it from remote repo tags (requires network access)
|
||||
cmd = "git ls-remote --tags git://github.com/PX4/Firmware.git | cut -d/ -f3- | sort -n -t. -k1,1 -k2,2 -k3,3 | awk '/^v[^{]*$/{version=$1}END{print version}'"
|
||||
cmd = "git ls-remote --tags git@github.com:PX4/PX4-Autopilot.git | cut -d/ -f3- | sort -n -t. -k1,1 -k2,2 -k3,3 | awk '/^v[^{]*$/{version=$1}END{print version}'"
|
||||
|
||||
try:
|
||||
version = subprocess.check_output(
|
||||
@@ -94,7 +94,7 @@ else:
|
||||
|
||||
|
||||
def main():
|
||||
print("PX4 release", get_version())
|
||||
print("PX4 Release", get_version())
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -26,3 +26,4 @@ setuptools>=39.2.0
|
||||
six>=1.12.0
|
||||
toml>=0.9
|
||||
sympy>=1.10.1
|
||||
pycryptodome
|
||||
|
||||
+1
-1
Submodule Tools/simulation/gz updated: 6c18846a4c...6caa6d54fa
@@ -70,7 +70,7 @@ export JSBSIM_AIRCRAFT_MODEL="$MODEL_NAME"
|
||||
if [[ -n "$HEADLESS" ]]; then
|
||||
echo "not running flightgear gui"
|
||||
else
|
||||
export FG_AIRCRAFT="${SRC_DIR}/Tools/simulation/jsbsim/jsbsim_bridge/models"
|
||||
export FG_AIRCRAFT="${src_path}/Tools/simulation/jsbsim/jsbsim_bridge/models"
|
||||
|
||||
$FG_BINARY --fdm=null \
|
||||
--native-fdm=socket,in,60,,5550,udp \
|
||||
|
||||
@@ -15,6 +15,7 @@ CONFIG_BOARD_UAVCAN_INTERFACES=1
|
||||
CONFIG_DRIVERS_UAVCANNODE=y
|
||||
CONFIG_UAVCANNODE_FLOW_MEASUREMENT=y
|
||||
CONFIG_UAVCANNODE_RANGE_SENSOR_MEASUREMENT=y
|
||||
CONFIG_UAVCANNODE_RAW_IMU=y
|
||||
CONFIG_MODULES_GYRO_CALIBRATION=y
|
||||
CONFIG_MODULES_SENSORS=y
|
||||
# CONFIG_SENSORS_VEHICLE_AIRSPEED is not set
|
||||
|
||||
@@ -20,6 +20,7 @@ CONFIG_UAVCANNODE_MAGNETIC_FIELD_STRENGTH=y
|
||||
CONFIG_UAVCANNODE_SAFETY_BUTTON=y
|
||||
CONFIG_UAVCANNODE_STATIC_PRESSURE=y
|
||||
CONFIG_UAVCANNODE_STATIC_TEMPERATURE=y
|
||||
CONFIG_UAVCANNODE_RAW_IMU=y
|
||||
CONFIG_MODULES_GYRO_CALIBRATION=y
|
||||
CONFIG_MODULES_MAG_BIAS_ESTIMATOR=y
|
||||
CONFIG_MODULES_SENSORS=y
|
||||
|
||||
@@ -21,6 +21,7 @@ CONFIG_UAVCANNODE_RTK_DATA=y
|
||||
CONFIG_UAVCANNODE_SAFETY_BUTTON=y
|
||||
CONFIG_UAVCANNODE_STATIC_PRESSURE=y
|
||||
CONFIG_UAVCANNODE_STATIC_TEMPERATURE=y
|
||||
CONFIG_UAVCANNODE_RAW_IMU=y
|
||||
CONFIG_MODULES_GYRO_CALIBRATION=y
|
||||
CONFIG_MODULES_MAG_BIAS_ESTIMATOR=y
|
||||
CONFIG_MODULES_SENSORS=y
|
||||
|
||||
@@ -36,6 +36,7 @@ CONFIG_UAVCANNODE_LIGHTS_COMMAND=y
|
||||
CONFIG_UAVCANNODE_MAGNETIC_FIELD_STRENGTH=y
|
||||
CONFIG_UAVCANNODE_RANGE_SENSOR_MEASUREMENT=y
|
||||
CONFIG_UAVCANNODE_RAW_AIR_DATA=y
|
||||
CONFIG_UAVCANNODE_RAW_IMU=y
|
||||
CONFIG_UAVCANNODE_RTK_DATA=y
|
||||
CONFIG_UAVCANNODE_SERVO_ARRAY_COMMAND=y
|
||||
CONFIG_UAVCANNODE_STATIC_PRESSURE=y
|
||||
|
||||
@@ -25,7 +25,16 @@ CONFIG_DRIVERS_IMU_INVENSENSE_IIM42652=y
|
||||
CONFIG_DRIVERS_IMU_INVENSENSE_IIM42653=y
|
||||
CONFIG_DRIVERS_IMU_MURATA_SCH16T=y
|
||||
CONFIG_COMMON_LIGHT=y
|
||||
CONFIG_COMMON_MAGNETOMETER=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_MEMSIC_MMC5983MA=y
|
||||
CONFIG_DRIVERS_MAGNETOMETER_ST_IIS2MDC=y
|
||||
CONFIG_DRIVERS_POWER_MONITOR_INA226=y
|
||||
CONFIG_DRIVERS_POWER_MONITOR_INA228=y
|
||||
CONFIG_DRIVERS_POWER_MONITOR_INA238=y
|
||||
@@ -66,6 +75,7 @@ CONFIG_MODULES_MC_HOVER_THRUST_ESTIMATOR=y
|
||||
CONFIG_MODULES_MC_POS_CONTROL=y
|
||||
CONFIG_MODULES_MC_RATE_CONTROL=y
|
||||
CONFIG_MODULES_NAVIGATOR=y
|
||||
CONFIG_NUM_MISSION_ITMES_SUPPORTED=1000
|
||||
CONFIG_MODULES_RC_UPDATE=y
|
||||
CONFIG_MODULES_ROVER_POS_CONTROL=y
|
||||
CONFIG_MODULES_SENSORS=y
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
CONFIG_DRIVERS_BATT_SMBUS=n
|
||||
CONFIG_DRIVERS_PX4IO=n
|
||||
CONFIG_BOARD_CRYPTO=y
|
||||
CONFIG_DRIVERS_STUB_KEYSTORE=y
|
||||
CONFIG_DRIVERS_SW_CRYPTO=y
|
||||
# CONFIG_EKF2_AUX_GLOBAL_POSITION is not set
|
||||
CONFIG_PUBLIC_KEY0="../../../Tools/test_keys/key0.pub"
|
||||
CONFIG_PUBLIC_KEY1="../../../Tools/test_keys/rsa2048.pub"
|
||||
@@ -84,6 +84,8 @@ CONFIG_CDCACM_RXBUFSIZE=600
|
||||
CONFIG_CDCACM_TXBUFSIZE=12000
|
||||
CONFIG_CDCACM_VENDORID=0x3185
|
||||
CONFIG_CDCACM_VENDORSTR="ARK"
|
||||
CONFIG_CRYPTO=y
|
||||
CONFIG_CRYPTO_RANDOM_POOL=y
|
||||
CONFIG_DEBUG_FULLOPT=y
|
||||
CONFIG_DEBUG_HARDFAULT_ALERT=y
|
||||
CONFIG_DEBUG_MEMFAULT=y
|
||||
|
||||
@@ -8,6 +8,8 @@ CONFIG_BOARD_SERIAL_TEL4="/dev/ttyS3"
|
||||
CONFIG_BOARD_SERIAL_RC="/dev/ttyS5"
|
||||
CONFIG_DRIVERS_ADC_BOARD_ADC=y
|
||||
CONFIG_DRIVERS_BAROMETER_BMP388=y
|
||||
CONFIG_DRIVERS_CAMERA_CAPTURE=y
|
||||
CONFIG_DRIVERS_CAMERA_TRIGGER=y
|
||||
CONFIG_DRIVERS_CDCACM_AUTOSTART=y
|
||||
CONFIG_COMMON_DIFFERENTIAL_PRESSURE=y
|
||||
CONFIG_COMMON_DISTANCE_SENSOR=y
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
CONFIG_BOARD_CRYPTO=y
|
||||
CONFIG_DRIVERS_STUB_KEYSTORE=y
|
||||
CONFIG_DRIVERS_SW_CRYPTO=y
|
||||
# CONFIG_EKF2_AUX_GLOBAL_POSITION is not set
|
||||
CONFIG_PUBLIC_KEY0="../../../Tools/test_keys/key0.pub"
|
||||
CONFIG_PUBLIC_KEY1="../../../Tools/test_keys/rsa2048.pub"
|
||||
@@ -82,6 +82,8 @@ CONFIG_CDCACM_RXBUFSIZE=600
|
||||
CONFIG_CDCACM_TXBUFSIZE=12000
|
||||
CONFIG_CDCACM_VENDORID=0x3185
|
||||
CONFIG_CDCACM_VENDORSTR="ARK"
|
||||
CONFIG_CRYPTO=y
|
||||
CONFIG_CRYPTO_RANDOM_POOL=y
|
||||
CONFIG_DEBUG_FULLOPT=y
|
||||
CONFIG_DEBUG_HARDFAULT_ALERT=y
|
||||
CONFIG_DEBUG_MEMFAULT=y
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
CONFIG_BOARD_CRYPTO=y
|
||||
CONFIG_DRIVERS_STUB_KEYSTORE=y
|
||||
CONFIG_DRIVERS_SW_CRYPTO=y
|
||||
# CONFIG_EKF2_AUX_GLOBAL_POSITION is not set
|
||||
CONFIG_PUBLIC_KEY0="../../../Tools/test_keys/key0.pub"
|
||||
CONFIG_PUBLIC_KEY1="../../../Tools/test_keys/rsa2048.pub"
|
||||
@@ -82,6 +82,8 @@ CONFIG_CDCACM_RXBUFSIZE=600
|
||||
CONFIG_CDCACM_TXBUFSIZE=12000
|
||||
CONFIG_CDCACM_VENDORID=0x3185
|
||||
CONFIG_CDCACM_VENDORSTR="ARK"
|
||||
CONFIG_CRYPTO=y
|
||||
CONFIG_CRYPTO_RANDOM_POOL=y
|
||||
CONFIG_DEBUG_FULLOPT=y
|
||||
CONFIG_DEBUG_HARDFAULT_ALERT=y
|
||||
CONFIG_DEBUG_MEMFAULT=y
|
||||
|
||||
@@ -17,6 +17,7 @@ CONFIG_UAVCANNODE_GNSS_FIX=y
|
||||
CONFIG_UAVCANNODE_LIGHTS_COMMAND=y
|
||||
CONFIG_UAVCANNODE_MAGNETIC_FIELD_STRENGTH=y
|
||||
CONFIG_UAVCANNODE_RTK_DATA=y
|
||||
CONFIG_UAVCANNODE_RAW_IMU=y
|
||||
CONFIG_UAVCANNODE_SAFETY_BUTTON=y
|
||||
CONFIG_UAVCANNODE_STATIC_PRESSURE=y
|
||||
CONFIG_UAVCANNODE_STATIC_TEMPERATURE=y
|
||||
|
||||
@@ -59,7 +59,6 @@
|
||||
#define BOARD_ARMED_STATE_LED LED_BLUE
|
||||
|
||||
#define FLASH_BASED_PARAMS
|
||||
#define RAM_BASED_MISSIONS
|
||||
|
||||
// Hacks for MAVLink RC button input
|
||||
#define ATL_MANTIS_RC_INPUT_HACKS
|
||||
|
||||
@@ -31,6 +31,7 @@ CONFIG_DRIVERS_POWER_MONITOR_INA226=y
|
||||
CONFIG_DRIVERS_PWM_INPUT=y
|
||||
CONFIG_DRIVERS_PWM_OUT=y
|
||||
CONFIG_DRIVERS_PX4IO=y
|
||||
CONFIG_DRIVERS_HEATER=y
|
||||
CONFIG_DRIVERS_SMART_BATTERY_BATMON=y
|
||||
CONFIG_COMMON_TELEMETRY=y
|
||||
CONFIG_DRIVERS_TONE_ALARM=y
|
||||
@@ -65,6 +66,7 @@ CONFIG_MODULES_MC_HOVER_THRUST_ESTIMATOR=y
|
||||
CONFIG_MODULES_MC_POS_CONTROL=y
|
||||
CONFIG_MODULES_MC_RATE_CONTROL=y
|
||||
CONFIG_MODULES_NAVIGATOR=y
|
||||
CONFIG_NUM_MISSION_ITMES_SUPPORTED=1000
|
||||
CONFIG_MODULES_RC_UPDATE=y
|
||||
CONFIG_MODULES_SENSORS=y
|
||||
CONFIG_MODULES_TEMPERATURE_COMPENSATION=y
|
||||
|
||||
@@ -58,6 +58,8 @@
|
||||
#define PX4IO_SERIAL_CLOCK STM32_PCLK2_FREQUENCY
|
||||
#define PX4IO_SERIAL_BITRATE 1500000 /* 1.5Mbps -> max rate for IO */
|
||||
|
||||
#define PX4IO_HEATER_ENABLED
|
||||
|
||||
/* LEDs */
|
||||
#define GPIO_nLED_AMBER /* PE12 */ (GPIO_OUTPUT|GPIO_OPENDRAIN|GPIO_SPEED_50MHz|GPIO_OUTPUT_SET|GPIO_PORTE|GPIO_PIN12)
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ CONFIG_DRIVERS_POWER_MONITOR_INA226=y
|
||||
CONFIG_DRIVERS_PWM_INPUT=y
|
||||
CONFIG_DRIVERS_PWM_OUT=y
|
||||
CONFIG_DRIVERS_PX4IO=y
|
||||
CONFIG_DRIVERS_HEATER=y
|
||||
CONFIG_DRIVERS_SMART_BATTERY_BATMON=y
|
||||
CONFIG_COMMON_TELEMETRY=y
|
||||
CONFIG_DRIVERS_TONE_ALARM=y
|
||||
@@ -66,6 +67,7 @@ CONFIG_MODULES_MC_HOVER_THRUST_ESTIMATOR=y
|
||||
CONFIG_MODULES_MC_POS_CONTROL=y
|
||||
CONFIG_MODULES_MC_RATE_CONTROL=y
|
||||
CONFIG_MODULES_NAVIGATOR=y
|
||||
CONFIG_NUM_MISSION_ITMES_SUPPORTED=1000
|
||||
CONFIG_MODULES_RC_UPDATE=y
|
||||
CONFIG_MODULES_SENSORS=y
|
||||
CONFIG_MODULES_TEMPERATURE_COMPENSATION=y
|
||||
|
||||
@@ -12,6 +12,4 @@ param set-default BAT2_A_PER_V 17
|
||||
# Disable IMU thermal control
|
||||
param set-default SENS_EN_THERMAL 0
|
||||
|
||||
param set-default -s SENS_TEMP_ID 2621474
|
||||
|
||||
set IOFW "/etc/extras/cubepilot_io-v2_default.bin"
|
||||
|
||||
@@ -17,6 +17,9 @@ ms5611 -s -b 4 start
|
||||
|
||||
if icm42688p -s -b 4 -R 10 -q start -c 15
|
||||
then
|
||||
# We need to use the temperature of the first isolated IMU for heater control.
|
||||
param set-default SENS_TEMP_ID 2490402
|
||||
|
||||
if ! icm20948 -s -b 4 -R 10 -M -q start
|
||||
then
|
||||
icm42688p -s -b 4 -R 6 start -c 13
|
||||
@@ -24,6 +27,8 @@ then
|
||||
else
|
||||
icm45686 -s -b 4 -R 10 start -c 15
|
||||
icm45686 -s -b 4 -R 6 start -c 13
|
||||
|
||||
param set-default SENS_TEMP_ID 3407906
|
||||
fi
|
||||
|
||||
# SPI1, body-fixed
|
||||
@@ -33,7 +38,6 @@ then
|
||||
ak09916 start -I -R 13
|
||||
else
|
||||
icm20649 -s -b 1 start
|
||||
|
||||
fi
|
||||
|
||||
ms5611 -s -b 1 start
|
||||
|
||||
@@ -68,6 +68,8 @@
|
||||
#define PX4IO_SERIAL_CLOCK STM32_PCLK2_FREQUENCY
|
||||
#define PX4IO_SERIAL_BITRATE 1500000 /* 1.5Mbps -> max rate for IO */
|
||||
|
||||
#define PX4IO_HEATER_ENABLED
|
||||
|
||||
/* LEDs */
|
||||
#define GPIO_nLED_AMBER /* PE12 */ (GPIO_OUTPUT|GPIO_OPENDRAIN|GPIO_SPEED_50MHz|GPIO_OUTPUT_SET|GPIO_PORTE|GPIO_PIN12)
|
||||
|
||||
|
||||
@@ -63,6 +63,7 @@ CONFIG_MODULES_MC_HOVER_THRUST_ESTIMATOR=y
|
||||
CONFIG_MODULES_MC_POS_CONTROL=y
|
||||
CONFIG_MODULES_MC_RATE_CONTROL=y
|
||||
CONFIG_MODULES_NAVIGATOR=y
|
||||
CONFIG_NUM_MISSION_ITMES_SUPPORTED=1000
|
||||
CONFIG_MODULES_RC_UPDATE=y
|
||||
CONFIG_MODULES_ROVER_POS_CONTROL=y
|
||||
CONFIG_MODULES_SENSORS=y
|
||||
|
||||
@@ -63,6 +63,7 @@ CONFIG_MODULES_MC_HOVER_THRUST_ESTIMATOR=y
|
||||
CONFIG_MODULES_MC_POS_CONTROL=y
|
||||
CONFIG_MODULES_MC_RATE_CONTROL=y
|
||||
CONFIG_MODULES_NAVIGATOR=y
|
||||
CONFIG_NUM_MISSION_ITMES_SUPPORTED=1000
|
||||
CONFIG_MODULES_RC_UPDATE=y
|
||||
CONFIG_MODULES_ROVER_POS_CONTROL=y
|
||||
CONFIG_MODULES_SENSORS=y
|
||||
|
||||
@@ -63,6 +63,7 @@ CONFIG_MODULES_MC_HOVER_THRUST_ESTIMATOR=y
|
||||
CONFIG_MODULES_MC_POS_CONTROL=y
|
||||
CONFIG_MODULES_MC_RATE_CONTROL=y
|
||||
CONFIG_MODULES_NAVIGATOR=y
|
||||
CONFIG_NUM_MISSION_ITMES_SUPPORTED=1000
|
||||
CONFIG_MODULES_RC_UPDATE=y
|
||||
CONFIG_MODULES_ROVER_POS_CONTROL=y
|
||||
CONFIG_MODULES_SENSORS=y
|
||||
|
||||
@@ -152,16 +152,11 @@ void task_main(int argc, char *argv[])
|
||||
newbytes = read(uart_fd, &rx_buf[0], sizeof(rx_buf));
|
||||
#endif
|
||||
|
||||
uint8_t protocol_version = rx_buf[1] & 0x0F;
|
||||
|
||||
if (newbytes <= 0) {
|
||||
if (print_msg) { PX4_INFO("Spektrum RC: Read no bytes from UART"); }
|
||||
|
||||
} else if (((newbytes != DSM_FRAME_SIZE) ||
|
||||
((protocol_version != 0x02) && (protocol_version != 0x01))) &&
|
||||
(! first_correct_frame_received)) {
|
||||
PX4_ERR("Spektrum RC: Invalid DSM frame. %d bytes. Protocol byte 0x%.2x",
|
||||
newbytes, rx_buf[1]);
|
||||
} else if ((newbytes != DSM_FRAME_SIZE) && (! first_correct_frame_received)) {
|
||||
PX4_ERR("Invalid DSM frame size: %d bytes", newbytes);
|
||||
|
||||
} else {
|
||||
if (print_msg) { PX4_INFO("Spektrum RC: Read %d bytes from UART", newbytes); }
|
||||
|
||||
@@ -62,6 +62,10 @@ param select /data/px4/param/parameters
|
||||
# Load in all of the parameters that have been saved in the file
|
||||
param load
|
||||
|
||||
# This was the default pre-v1.16.0 and for folks relying on that
|
||||
# we set it up here
|
||||
param set-default EKF2_EV_CTRL 15
|
||||
|
||||
# IMU (accelerometer / gyroscope)
|
||||
if [ "$PLATFORM" == "M0104" ]; then
|
||||
/bin/echo "Starting IMU driver with rotation 12"
|
||||
|
||||
@@ -12,6 +12,7 @@ CONFIG_MODULES_CONTROL_ALLOCATOR=y
|
||||
CONFIG_MODULES_DATAMAN=y
|
||||
CONFIG_MODULES_EKF2=y
|
||||
CONFIG_MODULES_MAVLINK=y
|
||||
CONFIG_MODULES_NAVIGATOR=y
|
||||
CONFIG_MODULES_SENSORS=y
|
||||
CONFIG_SYSTEMCMDS_I2CDETECT=y
|
||||
CONFIG_SYSTEMCMDS_LED_CONTROL=y
|
||||
|
||||
@@ -64,6 +64,7 @@ CONFIG_MODULES_MC_HOVER_THRUST_ESTIMATOR=y
|
||||
CONFIG_MODULES_MC_POS_CONTROL=y
|
||||
CONFIG_MODULES_MC_RATE_CONTROL=y
|
||||
CONFIG_MODULES_NAVIGATOR=y
|
||||
CONFIG_NUM_MISSION_ITMES_SUPPORTED=1000
|
||||
CONFIG_MODULES_RC_UPDATE=y
|
||||
CONFIG_MODULES_ROVER_POS_CONTROL=y
|
||||
CONFIG_MODULES_SENSORS=y
|
||||
|
||||
@@ -65,6 +65,7 @@ CONFIG_MODULES_MC_HOVER_THRUST_ESTIMATOR=y
|
||||
CONFIG_MODULES_MC_POS_CONTROL=y
|
||||
CONFIG_MODULES_MC_RATE_CONTROL=y
|
||||
CONFIG_MODULES_NAVIGATOR=y
|
||||
CONFIG_NUM_MISSION_ITMES_SUPPORTED=1000
|
||||
CONFIG_MODULES_RC_UPDATE=y
|
||||
CONFIG_MODULES_ROVER_POS_CONTROL=y
|
||||
CONFIG_MODULES_SENSORS=y
|
||||
|
||||
@@ -76,6 +76,7 @@ CONFIG_MODULES_MC_POS_CONTROL=y
|
||||
CONFIG_MODULES_MC_RATE_CONTROL=y
|
||||
CONFIG_MODULES_NAVIGATOR=y
|
||||
CONFIG_MODE_NAVIGATOR_VTOL_TAKEOFF=y
|
||||
CONFIG_NUM_MISSION_ITMES_SUPPORTED=1000
|
||||
CONFIG_MODULES_RC_UPDATE=y
|
||||
CONFIG_MODULES_SENSORS=y
|
||||
CONFIG_MODULES_TEMPERATURE_COMPENSATION=y
|
||||
|
||||
@@ -77,6 +77,7 @@ CONFIG_MODULES_MC_POS_CONTROL=y
|
||||
CONFIG_MODULES_MC_RATE_CONTROL=y
|
||||
CONFIG_MODULES_NAVIGATOR=y
|
||||
CONFIG_MODE_NAVIGATOR_VTOL_TAKEOFF=y
|
||||
CONFIG_NUM_MISSION_ITMES_SUPPORTED=1000
|
||||
CONFIG_MODULES_RC_UPDATE=y
|
||||
CONFIG_MODULES_ROVER_POS_CONTROL=y
|
||||
CONFIG_MODULES_SENSORS=y
|
||||
|
||||
@@ -41,6 +41,7 @@ CONFIG_MODULES_MC_POS_CONTROL=y
|
||||
CONFIG_MODULES_MC_RATE_CONTROL=y
|
||||
CONFIG_MODULES_NAVIGATOR=y
|
||||
CONFIG_MODE_NAVIGATOR_VTOL_TAKEOFF=y
|
||||
CONFIG_NUM_MISSION_ITMES_SUPPORTED=10000
|
||||
CONFIG_MODULES_PAYLOAD_DELIVERER=y
|
||||
CONFIG_MODULES_RC_UPDATE=y
|
||||
CONFIG_MODULES_REPLAY=y
|
||||
|
||||
+11
-20
@@ -18,7 +18,7 @@ export default defineConfig({
|
||||
"ja/**/*.md",
|
||||
"ru/**/*.md",
|
||||
"tr/**/*.md",
|
||||
//"kr/**/*.md",
|
||||
//"ko/**/*.md",
|
||||
//"zh/**/*.md",
|
||||
//"uk/**/*.md",
|
||||
"**/_*.md", //Remove source docs that start with "_" (included/not rendered)
|
||||
@@ -81,15 +81,19 @@ export default defineConfig({
|
||||
? ({ filePath, frontmatter }) => {
|
||||
if (frontmatter.newEditLink) {
|
||||
//newEditLink defines a frontmatter key you can use to append a path to main
|
||||
return `https://github.com/PX4/PX4-Autopilot/edit/main/${frontmatter.newEditLink}`;
|
||||
return `https://github.com/PX4/PX4-Autopilot/edit/main/docs/${frontmatter.newEditLink}`;
|
||||
} else {
|
||||
return `https://github.com/PX4/PX4-Autopilot/edit/main/${filePath}`;
|
||||
return `https://github.com/PX4/PX4-Autopilot/edit/main/docs/${filePath}`;
|
||||
}
|
||||
}
|
||||
: (c) =>
|
||||
`${
|
||||
window.location.origin
|
||||
}/__open-in-editor?file=${encodeURIComponent(c.filePath)}`,
|
||||
}/__open-in-editor?file=${encodeURIComponent(
|
||||
c.frontmatter.newEditLink
|
||||
? c.frontmatter.newEditLink
|
||||
: c.filePath
|
||||
)}`,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -156,26 +160,13 @@ export default defineConfig({
|
||||
|
||||
nav: [
|
||||
{
|
||||
text: "PX4",
|
||||
text: "Dronecode",
|
||||
items: [
|
||||
{
|
||||
text: "Website",
|
||||
text: "PX4",
|
||||
link: "https://px4.io/",
|
||||
ariaLabel: "PX4 website link",
|
||||
},
|
||||
{
|
||||
text: "Autopilot Source Code",
|
||||
link: "https://github.com/PX4/PX4-Autopilot",
|
||||
},
|
||||
{
|
||||
text: "Docs Source Code",
|
||||
link: "https://github.com/PX4/PX4-Autopilot/docs/",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "Dronecode",
|
||||
items: [
|
||||
{
|
||||
text: "QGroundControl",
|
||||
link: "http://qgroundcontrol.com/",
|
||||
@@ -206,7 +197,7 @@ export default defineConfig({
|
||||
text: "Version",
|
||||
items: [
|
||||
{ text: "main", link: "https://docs.px4.io/main/en/" },
|
||||
{ text: "v1.15", link: "https://docs.px4.io/v1.15/en/" },
|
||||
{ text: "v1.15 (stable)", link: "https://docs.px4.io/v1.15/en/" },
|
||||
{ text: "v1.14", link: "https://docs.px4.io/v1.14/en/" },
|
||||
{ text: "v1.13", link: "https://docs.px4.io/v1.13/en/" },
|
||||
{ text: "v1.12", link: "https://docs.px4.io/v1.12/en/" },
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 151 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 463 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 52 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.2 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 239 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 450 KiB |
@@ -7,6 +7,7 @@
|
||||
"files": [
|
||||
{
|
||||
"source": "docs/en/**/*.md",
|
||||
"ignore": ["/docs/en/_sidebar.md"],
|
||||
"translation": "docs/%two_letters_code%/**/%original_file_name%"
|
||||
}
|
||||
]
|
||||
|
||||
+5
-3
@@ -165,7 +165,7 @@
|
||||
- [AirMind MindPX](flight_controller/mindpx.md)
|
||||
- [AirMind MindRacer](flight_controller/mindracer.md)
|
||||
- [ARK Electronics ARKV6X](flight_controller/ark_v6x.md)
|
||||
- [ARK FPV Flight Controller](flight_controller/ark_fpv.md)
|
||||
- [ARK FPV Flight Controller](flight_controller/ark_fpv.md)
|
||||
- [ARK Pi6X Flow Flight Controller](flight_controller/ark_pi6x.md)
|
||||
- [CUAV X7](flight_controller/cuav_x7.md)
|
||||
- [CUAV Nora](flight_controller/cuav_nora.md)
|
||||
@@ -253,7 +253,7 @@
|
||||
- [GNSS (GPS)](gps_compass/index.md)
|
||||
- [ARK GPS (CAN)](dronecan/ark_gps.md)
|
||||
- [ARK SAM GPS](gps_compass/ark_sam_gps.md)
|
||||
- [ARK TESEO GPS](dronecan/ark_teseo_gps.md)
|
||||
- [ARK TESEO GPS](dronecan/ark_teseo_gps.md)
|
||||
- [CUAV NEO 3 GPS](gps_compass/gps_cuav_neo_3.md)
|
||||
- [CUAV NEO 3 Pro GPS (CAN)](gps_compass/gps_cuav_neo_3pro.md)
|
||||
- [CUAV NEO 3X GPS (CAN)](gps_compass/gps_cuav_neo_3x.md)
|
||||
@@ -326,7 +326,9 @@
|
||||
- [ARK Electron Microhard Serial Telemetry Radio](telemetry/ark_microhard_serial.md)
|
||||
- [Holybro Microhard P900 Telemetry Radio](telemetry/holybro_microhard_p900_radio.md)
|
||||
- [CUAV P8 Telemetry Radio](telemetry/cuav_p8_radio.md)
|
||||
- [J.Fi Wireless Telemetry Module](telemetry/jfi_telemetry.md)
|
||||
- [HolyBro XBP9X - Discontinued](telemetry/holybro_xbp9x_radio.md)
|
||||
|
||||
- [FrSky Telemetry](peripherals/frsky_telemetry.md)
|
||||
- [TBS Crossfire (CRSF) Telemetry](telemetry/crsf_telemetry.md)
|
||||
- [Satellite Comms (Iridium/RockBlock)](advanced_features/satcom_roadblock.md)
|
||||
@@ -838,4 +840,4 @@
|
||||
- [1.15 (stable)](releases/1.15.md)
|
||||
- [1.14](releases/1.14.md)
|
||||
- [1.13](releases/1.13.md)
|
||||
- [1.12](releases/1.12.md)
|
||||
- [1.12](releases/1.12.md)
|
||||
|
||||
@@ -43,7 +43,9 @@ The gimbal can be connected to _any free serial port_ using the instructions in
|
||||
For example, if the `TELEM2` port on the flight controller is unused you can connect it to the gimbal and set the following PX4 parameters:
|
||||
|
||||
- [MAV_1_CONFIG](../advanced_config/parameter_reference.md#MAV_1_CONFIG) to **TELEM2** (if `MAV_1_CONFIG` is already used for a companion computer (say), use `MAV_2_CONFIG`).
|
||||
- [MAV_1_MODE](../advanced_config/parameter_reference.md#MAV_1_MODE) to **NORMAL**
|
||||
- [MAV_1_MODE](../advanced_config/parameter_reference.md#MAV_1_MODE) to **Gimbal**
|
||||
- [MAV_1_FLOW_CTRL](../advanced_config/parameter_reference.md#MAV_1_FLOW_CTRL) to **Off (0)** (very few gimbals will have RST/CST wires connected).
|
||||
- [MAV_1_FORWARD](../advanced_config/parameter_reference.md#MAV_1_FORWARD) to **Enabled** (Note strictly necessary as forwarding is enabled when `MAV_1_MODE` is set to Gimbal).
|
||||
- [SER_TEL2_BAUD](../advanced_config/parameter_reference.md#SER_TEL2_BAUD) to manufacturer recommended baud rate.
|
||||
|
||||
### Multiple Gimbal Support
|
||||
|
||||
@@ -15215,7 +15215,7 @@ Reboot | minValue | maxValue | increment | default | unit
|
||||
|
||||
### COM_QC_ACT (`INT32`) {#COM_QC_ACT}
|
||||
|
||||
Set command after a quadchute.
|
||||
Set action after a quadchute.
|
||||
|
||||
**Values:**
|
||||
|
||||
@@ -37406,7 +37406,7 @@ Reboot | minValue | maxValue | increment | default | unit
|
||||
|
||||
Airspeed-less front transition time (open loop).
|
||||
|
||||
The duration of the front transition when there is no airspeed feedback available.
|
||||
The duration of the front transition when there is no airspeed feedback available. When airspeed is used, transition timeout is declared if airspeed does not reach VT_ARSP_BLEND after this time.
|
||||
|
||||
Reboot | minValue | maxValue | increment | default | unit
|
||||
--- | --- | --- | --- | --- | ---
|
||||
@@ -37518,7 +37518,7 @@ Reboot | minValue | maxValue | increment | default | unit
|
||||
|
||||
Front transition timeout.
|
||||
|
||||
Time in seconds after which transition will be cancelled. Disabled if set to 0.
|
||||
Time in seconds after which transition will be cancelled.
|
||||
|
||||
Reboot | minValue | maxValue | increment | default | unit
|
||||
--- | --- | --- | --- | --- | ---
|
||||
|
||||
+38
-16
@@ -40,13 +40,13 @@ To make sure the vehicle is stable enough for auto-tuning:
|
||||
|
||||
1. Perform a normal preflight safety checklist to ensure the flight zone is clear and has enough space.
|
||||
|
||||
1. Take off and <div style="display: inline;" v-if="$frontmatter.frame === 'Multicopter'">hover at 1m above ground in [Altitude mode](../flight_modes_mc/altitude.md) or [Stabilized mode](../flight_modes_mc/manual_stabilized.md)</div><div style="display: inline;" v-else-if="$frontmatter.frame === 'Plane'">fly at cruise speed in [Position mode](../flight_modes_fw/position.md) or [Altitude mode](../flight_modes_fw/altitude.md)</div>.
|
||||
2. Take off and <div style="display: inline;" v-if="$frontmatter.frame === 'Multicopter'">hover at 1m above ground in [Altitude mode](../flight_modes_mc/altitude.md) or [Stabilized mode](../flight_modes_mc/manual_stabilized.md)</div><div style="display: inline;" v-else-if="$frontmatter.frame === 'Plane'">fly at cruise speed in [Position mode](../flight_modes_fw/position.md) or [Altitude mode](../flight_modes_fw/altitude.md)</div>.
|
||||
|
||||
1. Use the RC transmitter roll stick to perform the following maneuver, tilting the vehicle just a few degrees: _roll left > roll right > center_ (The whole maneuver should take about 3 seconds).
|
||||
3. Use the RC transmitter roll stick to perform the following maneuver, tilting the vehicle just a few degrees: _roll left > roll right > center_ (The whole maneuver should take about 3 seconds).
|
||||
The vehicle should stabilise itself within 2 oscillations.
|
||||
1. Repeat the maneuver, tilting with larger amplitudes at each attempt.
|
||||
4. Repeat the maneuver, tilting with larger amplitudes at each attempt.
|
||||
If the vehicle can stabilise itself within 2 oscillations at ~20 degrees move to the next step.
|
||||
1. Repeat the same maneuvers but on the pitch axis.
|
||||
5. Repeat the same maneuvers but on the pitch axis.
|
||||
As above, start with small angles and confirm that the vehicle can stabilise itself within 2 oscillations before increasing the tilt.
|
||||
|
||||
If the drone can stabilize itself within 2 oscillations it is ready for the [auto-tuning procedure](#auto-tuning-procedure).
|
||||
@@ -69,12 +69,12 @@ The test steps are:
|
||||
|
||||
1. Perform the [pre-tuning test](#pre-tuning-test).
|
||||
|
||||
1. Takeoff using RC control <div style="display: inline;" v-if="$frontmatter.frame === 'Multicopter'">in [Altitude mode](../flight_modes_mc/altitude.md).
|
||||
2. Takeoff using RC control <div style="display: inline;" v-if="$frontmatter.frame === 'Multicopter'">in [Altitude mode](../flight_modes_mc/altitude.md).
|
||||
Hover the vehicle at a safe distance and at a few meters above ground (between 4 and 20m).</div><div v-else-if="$frontmatter.frame === 'Plane'">
|
||||
Once flying at cruise speed, activate [Hold mode](../flight_modes_fw/hold.md).
|
||||
This will guide the plane to fly in circle at constant altitude and speed.</div>
|
||||
|
||||
1. Enable autotune.
|
||||
3. Enable autotune.
|
||||
|
||||
<div v-if="$frontmatter.frame === 'Plane'">
|
||||
<div class="tip custom-block"><p class="custom-block-title">TIP</p>
|
||||
@@ -87,15 +87,24 @@ The test steps are:
|
||||
|
||||

|
||||
|
||||
1. Select either the _Rate Controller_ or _Attitude Controller_ tabs.
|
||||
1. Ensure that the **Autotune enabled** button is enabled (this will display the **Autotune** button and remove the manual tuning selectors).
|
||||
1. Read the warning popup and click on **OK** to start tuning.
|
||||
2. Select either the _Rate Controller_ or _Attitude Controller_ tabs.
|
||||
3. Ensure that the **Autotune enabled** button is enabled (this will display the **Autotune** button and remove the manual tuning selectors).
|
||||
4. Read the warning popup and click on **OK** to start tuning.
|
||||
|
||||
1. The drone will first start to perform quick roll motions followed by pitch and yaw motions.
|
||||
4. The drone will first start to perform quick roll motions followed by pitch and yaw motions.
|
||||
The progress is shown in the progress bar, next to the _Autotune_ button.
|
||||
1. <div style="display: inline;" v-if="$frontmatter.frame === 'Multicopter'">Manually land and disarm to apply the new tuning parameters.
|
||||
Takeoff carefully and manually test that the vehicle is stable.</div><div v-else-if="$frontmatter.frame === 'Plane'">The tuning will be immediately/automatically be applied and tested in flight (by default).
|
||||
PX4 will then run a 4 second test and revert the new tuning if a problem is detected.</div>
|
||||
|
||||
<div style="display: inline;" v-if="$frontmatter.frame === 'Multicopter'">
|
||||
|
||||
5. Manually land and disarm to apply the new tuning parameters.
|
||||
Takeoff carefully and manually test that the vehicle is stable.
|
||||
|
||||
</div><div v-else-if="$frontmatter.frame === 'Plane'">
|
||||
|
||||
5. The tuning will be immediately/automatically be applied and tested in flight (by default).
|
||||
PX4 will then run a 4 second test and revert the new tuning if a problem is detected.
|
||||
|
||||
</div>
|
||||
|
||||
::: warning
|
||||
If any strong oscillations occur, land immediately and follow the instructions in the [Troubleshooting](#troubleshooting) section below.
|
||||
@@ -118,6 +127,20 @@ Additional notes:
|
||||
|
||||
- Whether tuning is applied while flying or after landing can be [configured using parameters](#apply-tuning-when-in-air-landed).
|
||||
|
||||
<div v-if="$frontmatter.frame === 'Multicopter'">
|
||||
|
||||
## Autotuning Large Vehicles
|
||||
|
||||
For big multicopter vehicles you may need to increase the desired raise time of the step response [MC_AT_RISE_TIME](../advanced_config/parameter_reference.md#MC_AT_RISE_TIME).
|
||||
This requires some trial and error as an appropriate rise time depends on both vehicle size and the rotor response.
|
||||
|
||||
Note that if there are slow oscillations in pretuning it may mean that the attitude loop is too fast compared to the rate loop.
|
||||
In this case you should troubleshoot as described in [Drone oscillates when performing the pre-tuning test](#drone-oscillates-when-performing-the-pre-tuning-test).
|
||||
|
||||
<!-- Fixed wing rise time is hardcoded (it's lower than on multirotors and is probably enough for most platforms). -->
|
||||
|
||||
</div>
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Drone oscillates when performing the pre-tuning test
|
||||
@@ -164,7 +187,6 @@ Attempt manual tuning using the guides listed in [See also](#see-also) below.
|
||||
|
||||
### Apply Tuning when In-Air/Landed
|
||||
|
||||
|
||||
<div v-if="$frontmatter.frame === 'Multicopter'">
|
||||
|
||||
By multicopters land before parameters are applied.
|
||||
@@ -196,8 +218,8 @@ A remote control switch can be configured to enable/disable autotune (in any mod
|
||||
To map a switch:
|
||||
|
||||
1. Select an RC channel on your controller to use for the autotune enable/disable switch.
|
||||
1. Set [RC_MAP_AUX1](../advanced_config/parameter_reference.md#RC_MAP_AUX1) to match the RC channel for your switch (you can use any of `RC_MAP_AUX1` to `RC_MAP_AUX6`).
|
||||
1. Set [FW_AT_MAN_AUX](../advanced_config/parameter_reference.md#FW_AT_MAN_AUX) to the selected channel (i.e. `1: Aux 1` if you mapped `RC_MAP_AUX1`).
|
||||
2. Set [RC_MAP_AUX1](../advanced_config/parameter_reference.md#RC_MAP_AUX1) to match the RC channel for your switch (you can use any of `RC_MAP_AUX1` to `RC_MAP_AUX6`).
|
||||
3. Set [FW_AT_MAN_AUX](../advanced_config/parameter_reference.md#FW_AT_MAN_AUX) to the selected channel (i.e. `1: Aux 1` if you mapped `RC_MAP_AUX1`).
|
||||
|
||||
The auto tuner will be disabled when the switch is below `0.5` (on the manual control setpoint range of of `[-1, 1]`) and enabled when the switch channel is above `0.5`.
|
||||
|
||||
|
||||
@@ -146,6 +146,12 @@ The settings and underlying parameters are shown below.
|
||||
| Data Link Loss Timeout | [COM_DL_LOSS_T](../advanced_config/parameter_reference.md#COM_DL_LOSS_T) | Amount of time after losing the data connection before the failsafe will trigger. |
|
||||
| Failsafe Action | [NAV_DLL_ACT](../advanced_config/parameter_reference.md#NAV_DLL_ACT) | Disabled, Hold mode, Return mode, Land mode, Disarm, Terminate. |
|
||||
|
||||
The following settings also apply, but are not displayed in the QGC UI.
|
||||
|
||||
| Setting | Parameter | Description |
|
||||
| ----------------------------------------------------------- | -------------------------------------------------------------------------- | ---------------------------------------------------- |
|
||||
| <a id="COM_DLL_EXCEPT"></a>Mode exceptions for DLL failsafe | [COM_DLL_EXCEPT](../advanced_config/parameter_reference.md#COM_DLL_EXCEPT) | Set modes where DL loss will not trigger a failsafe. |
|
||||
|
||||
## Geofence Failsafe
|
||||
|
||||
The _Geofence Failsafe_ is triggered when the drone breaches a "virtual" perimeter.
|
||||
|
||||
@@ -83,6 +83,20 @@ This is the airspeed which, when reached, will trigger the transition out of mul
|
||||
It is critical that you have properly calibrated your airspeed sensor.
|
||||
It is also important that you pick an airspeed that is comfortably above your airframes stall speed (check `FW_AIRSPD_MIN`) as this is currently not checked.
|
||||
|
||||
#### Openloop Transition Time
|
||||
Parameter: [VT_F_TR_OL_TM](../advanced_config/parameter_reference.md#VT_F_TR_OL_TM)
|
||||
|
||||
This specifies the duration of the front transition in seconds when no airspeed feedback is available (e.g. no airspeed sensor present).
|
||||
It should be set to a value which ensures that the vehicle reaches a high enough airspeed to complete the transition, e.g. airspeed should exceed [VT_ARSP_TRANS](../advanced_config/parameter_reference.md#VT_ARSP_TRANS).
|
||||
|
||||
#### Transition Timeout
|
||||
[VT_TRANS_TIMEOUT](../advanced_config/parameter_reference.md#VT_TRANS_TIMEOUT)
|
||||
|
||||
This specifies the upper limit for the duration of the front transition. If the vehicle has not reached the transition airspeed after this time, then the transition will be aborted and a [Quadchute](../config/safety.md#quad-chute-failsafe) event will be triggered.
|
||||
:::note
|
||||
Additionally, if an airspeed sensor is present, the transition will also be aborted if the airspeed has not reached [VT_ARSP_BLEND](../advanced_config/parameter_reference.md#VT_ARSP_BLEND) after the openloop transition time [VT_F_TR_OL_TM](../advanced_config/parameter_reference.md#VT_F_TR_OL_TM) has elapsed. This checks is used to avoid a scenario where the vehicle gains excessive speed when the airspeed sensor is faulty.
|
||||
:::
|
||||
|
||||
### Transitioning Tips
|
||||
|
||||
As already mentioned make sure you have a well tuned multirotor mode.
|
||||
|
||||
+51
-22
@@ -15,7 +15,7 @@ Simple changes to _existing content_ can be made by clicking the **Edit on GitHu
|
||||
|
||||

|
||||
|
||||
To edit an existing page:
|
||||
To edit an existing English page:
|
||||
|
||||
1. Open the page.
|
||||
1. Click the **Edit on GitHub** link below the page content.
|
||||
@@ -24,49 +24,62 @@ To edit an existing page:
|
||||
|
||||
The documentation team will review the request and either merge it or work with you to update it.
|
||||
|
||||
## Changes using Git (New Pages and Images)
|
||||
Note that you can only make changes to the English version directly in the source.
|
||||
[Translations are handled in Crowdin](../contribute/translation.md).
|
||||
|
||||
## Changes using Git
|
||||
|
||||
More substantial changes, including adding new pages or adding/modifying images, aren't as easy to make (or properly test) on Github.
|
||||
|
||||
For these kinds of changes we suggest using the same approach as for _code_:
|
||||
|
||||
1. Use the _git_ toolchain to get the documentation source code onto your local computer.
|
||||
1. Use the _git_ toolchain to get the PX4 source code onto your local computer.
|
||||
1. Modify the documentation as needed (add, change, delete).
|
||||
1. _Test_ that it builds properly using Vitepress.
|
||||
1. Create a branch for your changes and create a pull request (PR) to pull it back into the documentation.
|
||||
1. Create a branch for your changes and create a pull request (PR) to pull it back into the [PX4-Autopilot](https://github.com/PX4/PX4-Autopilot.git) repo.
|
||||
|
||||
The following explain how to get the source code, build locally (to test), and modify the code.
|
||||
|
||||
### Get/Push Documentation Source Code
|
||||
### Get Documentation Source Code
|
||||
|
||||
Documentation sources are in the [PX4-Autopilot](https://github.com/PX4/PX4-Autopilot/) repo, alongside all the other PX4 source code.
|
||||
The sources are markdown files located the [/docs](https://github.com/PX4/PX4-Autopilot/tree/main/docs) subdirectory.
|
||||
The English source files are in the [/docs/en/](https://github.com/PX4/PX4-Autopilot/tree/main/docs/en) subdirectory and can be edited directly.
|
||||
[Translation](../contribute/translation.md) sources are in language specific subdirectories, such as `ko` for korean and `zh` for Chinese: these are edited via the Crowdin tool, and should not be edited directly.
|
||||
|
||||
::: tip
|
||||
If you already have a clone of the [PX4-Autopilot](https://github.com/PX4/PX4-Autopilot/) you can ignore this section.
|
||||
:::
|
||||
|
||||
To get the library(s) sources onto your local computer you will need to use the git toolchain.
|
||||
The instructions below explain how to get git and use it on your local computer.
|
||||
|
||||
1. Download git for your computer from [https://git-scm.com/downloads](https://git-scm.com/downloads)
|
||||
1. [Sign up](https://github.com/join) for Github if you haven't already
|
||||
1. Create a copy (Fork) of the [PX4 User Guide repo](https://github.com/PX4/PX4-user_guide) on Github ([instructions here](https://docs.github.com/en/get-started/quickstart/fork-a-repo)).
|
||||
1. Create a copy (Fork) of the [PX4-Autopilot repo](https://github.com/PX4/PX4-Autopilot) on Github ([instructions here](https://docs.github.com/en/get-started/quickstart/fork-a-repo)).
|
||||
1. Clone (copy) your forked repository to your local computer:
|
||||
|
||||
```sh
|
||||
cd ~/wherever/
|
||||
git clone https://github.com/<your git name>/PX4-user_guide.git
|
||||
git clone https://github.com/<your git name>/PX4-Autopilot.git
|
||||
```
|
||||
|
||||
For example, to clone the PX4 userguide fork for a user with Github account "john_citizen":
|
||||
For example, to clone PX4 source fork for a user with Github account "john_citizen":
|
||||
|
||||
```sh
|
||||
git clone https://github.com/john_citizen/PX4-user_guide.git
|
||||
git clone https://github.com/john_citizen/PX4-Autopilot.git
|
||||
```
|
||||
|
||||
1. Navigate to your local repository:
|
||||
|
||||
```sh
|
||||
cd ~/wherever/PX4-user_guide
|
||||
cd ~/wherever/PX4-Autopilot
|
||||
```
|
||||
|
||||
1. Add a _remote_ called "upstream" to point to the PX4 version of the library:
|
||||
1. Add a _remote_ called "upstream" to point to the "official" PX4 version of the library:
|
||||
|
||||
```sh
|
||||
git remote add upstream https://github.com/PX4/PX4-user_guide.git
|
||||
git remote add upstream https://github.com/PX4/PX4-Autopilot.git
|
||||
```
|
||||
|
||||
:::tip
|
||||
@@ -75,7 +88,19 @@ The instructions below explain how to get git and use it on your local computer.
|
||||
Above you create a new remote _upstream_ that points to the PX4 project version of the documents.
|
||||
:::
|
||||
|
||||
1. Create a branch for your changes:
|
||||
### Make/Push Documentation Changes
|
||||
|
||||
Within the repository you created above:
|
||||
|
||||
1. Bring your copy of the repository `main` branch up to date:
|
||||
|
||||
```sh
|
||||
git checkout main
|
||||
git fetch upstream main
|
||||
git pull upstream main
|
||||
```
|
||||
|
||||
2. Create a new branch for your changes:
|
||||
|
||||
```sh
|
||||
git checkout -b <your_feature_branch_name>
|
||||
@@ -83,8 +108,8 @@ The instructions below explain how to get git and use it on your local computer.
|
||||
|
||||
This creates a local branch on your computer named `your_feature_branch_name`.
|
||||
|
||||
1. Make changes to the documentation as needed (general guidance on this in following sections)
|
||||
1. Once you are satisfied with your changes, you can add them to your local branch using a "commit":
|
||||
3. Make changes to the documentation as needed (general guidance on this in following sections)
|
||||
4. Once you are satisfied with your changes, you can add them to your local branch using a "commit":
|
||||
|
||||
```sh
|
||||
git add <file name>
|
||||
@@ -93,21 +118,25 @@ The instructions below explain how to get git and use it on your local computer.
|
||||
|
||||
For a good commit message, please refer to the [Source Code Management](../contribute/code.md#commits-and-commit-messages) section.
|
||||
|
||||
1. Push your local branch (including commits added to it) to your forked repository on Github.
|
||||
5. Push your local branch (including commits added to it) to your forked repository on Github.
|
||||
|
||||
```sh
|
||||
git push origin your_feature_branch_name
|
||||
```
|
||||
|
||||
1. Go to your forked repository on Github in a web browser, e.g.: `https://github.com/<your git name>/PX4-user_guide.git`.
|
||||
6. Go to your forked repository on Github in a web browser, e.g.: `https://github.com/<your git name>/PX4-Autopilot.git`.
|
||||
There you should see the message that a new branch has been pushed to your forked repository.
|
||||
1. Create a pull request (PR):
|
||||
7. Create a pull request (PR):
|
||||
|
||||
- On the right hand side of the "new branch message" (see one step before), you should see a green button saying "Compare & Create Pull Request".
|
||||
Press it.
|
||||
- A pull request template will be created.
|
||||
It will list your commits and you can (must) add a meaningful title (in case of a one commit PR, it's usually the commit message) and message (<span style="color:orange">explain what you did for what reason</span>.
|
||||
Check [other pull requests](https://github.com/PX4/PX4-user_guide/pulls) for comparison)
|
||||
1. You're done!
|
||||
Check [other pull requests](https://github.com/PX4/PX4-Autopilot/pulls) for comparison).
|
||||
- Add the "Documentation" label.
|
||||
|
||||
8. You're done!
|
||||
|
||||
Maintainers for the PX4 User Guide will now have a look at your contribution and decide if they want to integrate it.
|
||||
Check if they have questions on your changes every once in a while.
|
||||
|
||||
@@ -120,10 +149,10 @@ Build the library locally to test that any changes you have made have rendered p
|
||||
- [Nodejs 18+](https://nodejs.org/en)
|
||||
- [Yarn classic](https://classic.yarnpkg.com/en/docs/install)
|
||||
|
||||
1. Navigate to your local repository:
|
||||
1. Navigate to your local repository and the `/docs` subdirectory:
|
||||
|
||||
```sh
|
||||
cd ~/wherever/PX4-user_guide
|
||||
cd ~/wherever/PX4-Autopilot/docs
|
||||
```
|
||||
|
||||
1. Install dependencies (including Vitepress):
|
||||
|
||||
@@ -11,3 +11,7 @@ This section provides information about various radio systems that you can use,
|
||||
- [FrSky Telemetry](../peripherals/frsky_telemetry.md) — Telemetry on your (FRSky) RC Receiver
|
||||
- [TBS Crossfire (CRSF) Telemetry](../telemetry/crsf_telemetry.md) — Telemetry on your (TBS Crossfire) RC Receiver
|
||||
- [Satellite Comms (Iridium/RockBlock)](../advanced_features/satcom_roadblock.md) — High-latency comms via satellite
|
||||
|
||||
## See Also
|
||||
|
||||
- [Safety Configuration > Data Link Loss Failsafe](../config/safety.md#data-link-loss-failsafe)
|
||||
|
||||
@@ -189,67 +189,186 @@ You can now build and test.
|
||||
|
||||
## Download & Decrypt Log Files
|
||||
|
||||
Encrypted log files are downloaded using the QGroundControl [Log Download](https://docs.qgroundcontrol.com/master/en/qgc-user-guide/analyze_view/log_download.html) view (**Analyze Tools > Log Download**) just like ordinary log files.
|
||||
Before you can analyse your logs they must first be downloaded and decrypted.
|
||||
PX4 includes Python scripts in [Tools/log_encryption](https://github.com/PX4/PX4-Autopilot/blob/main/Tools/) that make this process easier:
|
||||
|
||||
Note that the encrypted files will be downloaded with the `.ulg` suffix, instead of `.ulge`.
|
||||
- [download_logs.py](https://github.com/PX4/PX4-Autopilot/blob/main/Tools/log_encryption/download_logs.py): Downloads the logs to `/logs/encrypted`.
|
||||
- [decrypt_logs.py](https://github.com/PX4/PX4-Autopilot/blob/main/Tools/log_encryption/decrypt_logs.py): Decrypts encrypted logs in `/logs/encrypted` to `/logs/decrypted` using a specified (or default) key.
|
||||
|
||||
The following sections show how these are used.
|
||||
|
||||
### Download Log Files
|
||||
|
||||
The easiest way to download the files is to use [download_logs.py](https://github.com/PX4/PX4-Autopilot/blob/main/Tools/log_encryption/download_logs.py).
|
||||
This takes a single argument that sets the serial or UDP MAVLink connection to the device as shown below (adjust parameters as needed):
|
||||
|
||||
- UDP connection
|
||||
|
||||
```sh
|
||||
cd PX4-Autopilot/Tools/log_encryption
|
||||
python3 download_logs.py udp:0.0.0.0:14550
|
||||
```
|
||||
|
||||
- USB serial port on Linux
|
||||
|
||||
```sh
|
||||
cd PX4-Autopilot/Tools/log_encryption
|
||||
python3 download_logs.py /dev/ttyACM0 --baudrate 57600
|
||||
```
|
||||
|
||||
The files are downloaded to `/logs/encrypted`, which is the location expected by the decryption script.
|
||||
|
||||
::: info
|
||||
Encrypted log files can also be downloaded manually using the QGroundControl [Log Download](https://docs.qgroundcontrol.com/master/en/qgc-user-guide/analyze_view/log_download.html) view (**Analyze Tools > Log Download**) just like ordinary log files.
|
||||
|
||||
Note that in this case you will need to copy the files to `/logs/encrypted` and rename them to the `.ulge` suffix (they are downloaded with the `.ulg` suffix)
|
||||
:::
|
||||
|
||||
### Decrypt ULogs
|
||||
|
||||
Before you can analyze your encrypted logs, you will need to decrypt them.
|
||||
There is a Python script that can be used to decrypt logs in `Tools/decrypt_ulog.py`.
|
||||
By default, the [decrypt_logs.py](https://github.com/PX4/PX4-Autopilot/blob/main/Tools/log_encryption/decrypt_logs.py) script decrypts encrypted logs in `/logs/encrypted` using the private key in `keys/private/private_key.pem`, and generates the unencrypted logs in `/logs/decrypted`.
|
||||
|
||||
When decrypting a `.ulge` file the script takes 3 arguments:
|
||||
|
||||
1. The encrypted log file.
|
||||
2. An empty string `''`.
|
||||
3. The decryption key (the RSA2048 `.pem` private key which is used to unwrap the symmetric key).
|
||||
|
||||
For example:
|
||||
Navigate into the `Tools/log_encryption` folder and run the tool as shown below:
|
||||
|
||||
```sh
|
||||
python3 decrypt_ulog.py \
|
||||
/home/john/Downloads/log_24_2024-10-6-23-39-50.ulg '' \
|
||||
new_keys/private_key.pem
|
||||
cd PX4-Autopilot/Tools/log_encryption
|
||||
python3 decrypt_logs.py
|
||||
```
|
||||
|
||||
On success the decrypted log file is created with the `.ulog` suffix.
|
||||
|
||||
::: info
|
||||
The script can be used with both `.ulge` logs and the `.ulgc`/`.ulgk` files used in [PX4 v1.15 Log Encryption](https://docs.px4.io/v1.15/en/dev_log/log_encryption.html).
|
||||
The full command line syntax is given below:
|
||||
On success the decrypted logs can be found in the decrypted folder.
|
||||
|
||||
```sh
|
||||
usage: decrypt_ulog.py [-h] [ulog_file] [ulog_key] [rsa_key]
|
||||
PX4-Autopilot/logs/decrypted
|
||||
```
|
||||
|
||||
CLI tool to decrypt an ulog file
|
||||
The expected folder structure showing the location of encrypted logs, decrypted logs and the default private key is shown below:
|
||||
|
||||
positional arguments:
|
||||
ulog_file .ulge/.ulgc, encrypted log file
|
||||
ulog_key .ulgk, legacy encrypted key (give empty string '' to ignore for .ulge)
|
||||
rsa_key .pem format key for decrypting the ulog key
|
||||
```sh
|
||||
PX4-Autopilot/
|
||||
│
|
||||
├── logs/ # Main directory for logs
|
||||
│ ├── encrypted/ # Stores encrypted logs (.ulge)
|
||||
│ │ ├── log-YYYY-MM-DD_HH-MM-SS_ID.ulge # Encrypted logs
|
||||
│ │
|
||||
│ ├── decrypted/
|
||||
│ │ ├── log-YYYY-MM-DD_HH-MM-SS_ID.ulg # Regular PX4 logs
|
||||
|
|
||||
├── keys/ # Main directory for keys
|
||||
├── private/ # Stores private keys
|
||||
├── private_key.pem # RSA private key (2048-bit)
|
||||
```
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
::: tip
|
||||
The script also allows you to specify a particular key and/or to specify a particular file or folder to be decrypted using optional positional arguments:
|
||||
|
||||
```sh
|
||||
python3 decrypt_logs.py ["" | custom_key] [log_file.ulge | log_folder]
|
||||
```
|
||||
|
||||
The full set of command options are shown below:
|
||||
|
||||
```sh
|
||||
# Default key + default folder
|
||||
python3 decrypt_logs.py
|
||||
|
||||
# Specific key + default folder
|
||||
python3 decrypt_logs.py path/to/private_key.pem
|
||||
|
||||
# Specific key + specific file
|
||||
python3 decrypt_logs.py path/to/private_key.pem path/to/log_file.ulge
|
||||
|
||||
# Specific key + specific folder
|
||||
python3 decrypt_logs.py path/to/private_key.pem path/to/log_folder
|
||||
|
||||
# Default key + specific file
|
||||
python3 decrypt_logs.py "" path/to/log_file.ulge
|
||||
|
||||
# Default key + specific folder
|
||||
python3 decrypt_logs.py "" path/to/log_folder
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## Generate RSA Public & Private Keys
|
||||
|
||||
To generate a RSA2048 private and public key, you can use OpenSSL:
|
||||
The [Tools/log_encryption/generate_keys.py](https://github.com/PX4/PX4-Autopilot/blob/main/Tools/log_encryption/generate_keys.py) script can be used to generate the public key that is used on the device for encryption, and the private key that is used on the computer as part of log decryption.
|
||||
|
||||
::: details The script depends on OpenSSL.
|
||||
|
||||
Run the following command to check if OpenSSL is present:
|
||||
|
||||
```sh
|
||||
openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:2048
|
||||
openssl version
|
||||
```
|
||||
|
||||
Then you can create a public key from this private key:
|
||||
If there is no output you can install OpenSSL as shown below:
|
||||
|
||||
- Ubuntu/Debian
|
||||
|
||||
```sh
|
||||
sudo apt update
|
||||
sudo apt install openssl
|
||||
```
|
||||
|
||||
- macOS
|
||||
|
||||
```sh
|
||||
brew install openssl
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
The script is used as shown:
|
||||
|
||||
```sh
|
||||
# Convert private_key.pem to a DER file
|
||||
openssl rsa -pubout -in private_key.pem -outform DER -out public_key.der
|
||||
# From the DER file, generate a public key in hex format, separated by commas
|
||||
xxd -p public_key.der | tr -d '\n' | sed 's/\(..\)/0x\1, /g' > public_key.pub
|
||||
cd PX4-Autopilot/Tools/log_encryption
|
||||
python3 generate_keys.py
|
||||
```
|
||||
|
||||
To use this key you would modify your `.px4board` file to point `CONFIG_PUBLIC_KEY1` to the file location of `public_key.pub`.
|
||||
The private key generated should be stored safely and used when you need to decrypt log files.
|
||||
The private and public key will be generated into the folder structure below.
|
||||
The private key should be stored safely and used when you need to [decrypt log files](#decrypt-ulogs).
|
||||
|
||||
```sh
|
||||
PX4-Autopilot/
|
||||
│
|
||||
├── keys/ # Main directory for keys
|
||||
│ ├── private/ # Stores private keys
|
||||
│ │ ├── private_key.pem # RSA private key (2048-bit)
|
||||
│ │
|
||||
│ ├── public/ # Stores public keys
|
||||
│ │ ├── public_key.der # Public key in DER format
|
||||
│ │ ├── public_key.pub # Public key in hex format
|
||||
```
|
||||
|
||||
Notes:
|
||||
|
||||
- The script will not overwrite any existing keys in the folders.
|
||||
It will generate a new public key if the folder only includes a private key.
|
||||
- The public key is created with the default name and location expected by the toolchain when building PX4 (i.e. in `CONFIG_PUBLIC_KEY1`), and the private key is created in the default location expected by the script we use for [decrypting ulogs](#decrypt-ulogs).
|
||||
|
||||
### Manual Key Generation
|
||||
|
||||
This section explains how you might manually run the same steps as the script (should you so wish):
|
||||
|
||||
1. First install OpenSSL, as described in the previous section.
|
||||
2. Use OpenSSL to generate a RSA2048 private and public key:
|
||||
|
||||
```sh
|
||||
openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:2048
|
||||
```
|
||||
|
||||
3. Create a public key from this private key:
|
||||
|
||||
```sh
|
||||
# Convert private_key.pem to a DER file
|
||||
openssl rsa -pubout -in private_key.pem -outform DER -out public_key.der
|
||||
# From the DER file, generate a public key in hex format, separated by commas
|
||||
xxd -p public_key.der | tr -d '\n' | sed 's/\(..\)/0x\1, /g' > public_key.pub
|
||||
```
|
||||
|
||||
4. Copy the keys into the appropriate locations expected by the rest of the toolchain (as shown in previous section).
|
||||
5. To use this key, modify your `.px4board` file to point `CONFIG_PUBLIC_KEY1` to the file location of `public_key.pub`.
|
||||
|
||||
```sh
|
||||
CONFIG_PUBLIC_KEY1="../../../keys/public/public_key.pub"
|
||||
```
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# ARK Pi6X Flow
|
||||
|
||||
The [ARK Pi6X Flow](<(https://arkelectron.gitbook.io/ark-documentation/flight-controllers/ark-pi6x-flow)>) integrates a Raspberry Pi Compute Module 4 (CM4) Carrier, [ARKV6X Flight Controller](../flight_controller/ark_v6x.md), [ARK Flow sensors](../dronecan/ark_flow.md) , [ARK PAB Power Module](../power_module/ark_pab_power_module.md), and a 4-in-1 ESC, all mounted onto one compact board.
|
||||
The [ARK Pi6X Flow](https://arkelectron.gitbook.io/ark-documentation/flight-controllers/ark-pi6x-flow) integrates a Raspberry Pi Compute Module 4 (CM4) Carrier, [ARKV6X Flight Controller](../flight_controller/ark_v6x.md), [ARK Flow sensors](../dronecan/ark_flow.md) , [ARK PAB Power Module](../power_module/ark_pab_power_module.md), and a 4-in-1 ESC, all mounted onto one compact board.
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
# Flight Log Analysis
|
||||
|
||||
This topic provide an overview of the tools and methods that can be used to analyze PX4 flight logs (more detailed topics are linked below in some cases).
|
||||
|
||||
::: info INFO
|
||||
[Flight Reporting](../getting_started/flight_reporting.md) explains how to download a log and report/discuss issues about a flight with the development team.
|
||||
:::
|
||||
|
||||
## Structured Analysis
|
||||
|
||||
Before analyzing a flight log it is important to establish its context:
|
||||
|
||||
- If the analysis is done after a malfunction, did the log capture the crash or did it stop mid-air?
|
||||
- Did all controllers track their references?
|
||||
The easiest way to establish this is to compare attitude roll and pitch rates to their set points.
|
||||
- Does the sensor data look valid? Was there very strong vibration (a reasonable threshold for strong vibration is anything with a peak-to-peak of more than 2-3 m/s/s).
|
||||
- If the root cause is not specific to the vehicle make sure to report it with a link to the log file (and video if one exists) on the [PX4 issue tracker](https://github.com/PX4/PX4-Autopilot/issues/new).
|
||||
|
||||
## Ruling Out Power Failures
|
||||
|
||||
If a log file ends mid-air, two main causes are possible: a power failure _or_ a hard fault of the operating system.
|
||||
|
||||
On autopilots based on the [STM32 series](http://www.st.com/en/microcontrollers/stm32-32-bit-arm-cortex-mcus.html), hard faults are logged to the SD card.
|
||||
These are located on the top level of the SD card and named _fault_date.log_, e.g. **fault_2017_04_03_00_26_05.log**.
|
||||
You should check for the presence of this file if a flight log ends abruptly.
|
||||
|
||||
## Analysis Tools
|
||||
|
||||
### Flight Review (Online Tool)
|
||||
|
||||
[Flight Review](http://logs.px4.io) is the successor of _Log Muncher_.
|
||||
It is used in combination with the new [ULog](../dev_log/ulog_file_format.md) logging format.
|
||||
|
||||
Key features:
|
||||
|
||||
- Web based, great for end-users.
|
||||
- Users can upload logs through the web interface, and then share report with others (bulk upload is supported using the [upload_log.py](https://github.com/PX4/PX4-Autopilot/blob/main/Tools/upload_log.py) script)
|
||||
- Interactive plots.
|
||||
|
||||

|
||||
|
||||
See [Log Analysis using Flight Review](../log/flight_review.md) for an introduction.
|
||||
|
||||
### PlotJuggler
|
||||
|
||||
[PlotJuggler](https://github.com/facontidavide/PlotJuggler) is a desktop application that allows users to easily visualize and analyze data expressed in the form of time series.
|
||||
This is one of the best ULog analysis tools as it exposes all information in the log ([Flight Review](#flight-review-online-tool), by comparison, only shows a small subset of the data).
|
||||
|
||||
It supports ULog files (.ulg) since version 2.1.4.
|
||||
|
||||
Key features:
|
||||
|
||||
- Intuitive drag & drop interface.
|
||||
- Arrange your data in multiple plots, tabs or windows.
|
||||
- All uORB topics are shown and can be graphed.
|
||||
- Once you arranged your data, save it into a "Layout" file and reload it multiple times.
|
||||
- Process your data inside _PlotJuggler_ itself, using custom "data transformations".
|
||||
|
||||
Source code and downloads are available on [Github](https://github.com/facontidavide/PlotJuggler).
|
||||
|
||||

|
||||
|
||||
See [Log Analysis using Plot Juggler](../log/plotjuggler_log_analysis.md) for an introduction.
|
||||
|
||||
### pyulog
|
||||
|
||||
[pyulog](https://github.com/PX4/pyulog) is a python package to parse ULog files, along with a set of command-line scripts to extract/display ULog information and convert them to other file formats.
|
||||
|
||||
Key features:
|
||||
|
||||
- Python library for parsing ULog files. Base library used by a number of other ULog analysis and visualisation tools.
|
||||
- Scripts to extract/display ULog information:
|
||||
- _ulog_info_: display information from an ULog file.
|
||||
- _ulog_messages_: display logged messages from an ULog file.
|
||||
- _ulog_params_: extract parameters from an ULog file.
|
||||
- Scripts to convert ULog files to other formats:
|
||||
- _ulog2csv_: convert ULog to (several) CSV files.
|
||||
- _ulog2kml_: convert ULog to (several) KML files.
|
||||
|
||||
All scripts are installed as system-wide applications (i.e. they be called on the command line - provided Python is installed), and support the `-h` flag for getting usage instructions. For example:
|
||||
|
||||
```sh
|
||||
$ ulog_info -h
|
||||
usage: ulog_info [-h] [-v] file.ulg
|
||||
|
||||
Display information from an ULog file
|
||||
|
||||
positional arguments:
|
||||
file.ulg ULog input file
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
-v, --verbose Verbose output
|
||||
```
|
||||
|
||||
Below we see the kind of information exported from a sample file using _ulog_info_.
|
||||
|
||||
```sh
|
||||
$ ulog_info sample.ulg
|
||||
Logging start time: 0:01:52, duration: 0:01:08
|
||||
Dropouts: count: 4, total duration: 0.1 s, max: 62 ms, mean: 29 ms
|
||||
Info Messages:
|
||||
sys_name: PX4
|
||||
time_ref_utc: 0
|
||||
ver_hw: AUAV_X21
|
||||
ver_sw: fd483321a5cf50ead91164356d15aa474643aa73
|
||||
|
||||
Name (multi id, message size in bytes) number of data points, total bytes
|
||||
actuator_controls_0 (0, 48) 3269 156912
|
||||
actuator_outputs (0, 76) 1311 99636
|
||||
commander_state (0, 9) 678 6102
|
||||
control_state (0, 122) 3268 398696
|
||||
cpuload (0, 16) 69 1104
|
||||
ekf2_innovations (0, 140) 3271 457940
|
||||
estimator_status (0, 309) 1311 405099
|
||||
sensor_combined (0, 72) 17070 1229040
|
||||
sensor_preflight (0, 16) 17072 273152
|
||||
telemetry_status (0, 36) 70 2520
|
||||
vehicle_attitude (0, 36) 6461 232596
|
||||
vehicle_attitude_setpoint (0, 55) 3272 179960
|
||||
vehicle_local_position (0, 123) 678 83394
|
||||
vehicle_rates_setpoint (0, 24) 6448 154752
|
||||
vehicle_status (0, 45) 294 13230
|
||||
```
|
||||
|
||||
### FlightPlot
|
||||
|
||||
[FlightPlot](https://github.com/PX4/FlightPlot) is a desktop based tool for log analysis. It can be downloaded from [FlightPlot Downloads](https://github.com/PX4/FlightPlot/releases) (Linux, MacOS, Windows).
|
||||
|
||||
Key features:
|
||||
|
||||
- Java based, cross-platform.
|
||||
- Intuitive GUI, no programming knowledge required.
|
||||
- Supports both new and old PX4 log formats (.ulg, .px4log, .bin)
|
||||
- Allows saving plots as images.
|
||||
|
||||

|
||||
|
||||
### PX4Tools
|
||||
|
||||
[PX4Tools](https://github.com/dronecrew/px4tools) is a log analysis toolbox for the PX4 autopilot written in Python.
|
||||
The recommended installation procedure is to use [anaconda3](https://conda.io/docs/index.html). See [px4tools github page](https://github.com/dronecrew/px4tools) for details.
|
||||
|
||||
Key features:
|
||||
|
||||
- Easy to share, users can view notebooks on Github (e.g. [15-09-30 Kabir Log.ipynb](https://github.com/jgoppert/lpe-analysis/blob/master/15-09-30%20Kabir%20Log.ipynb))
|
||||
- Python based, cross platform, works with anaconda 2 and anaconda3
|
||||
- iPython/ jupyter notebooks can be used to share analysis easily
|
||||
- Advanced plotting capabilities to allow detailed analysis
|
||||
|
||||

|
||||
|
||||
### MAVGCL
|
||||
|
||||
[MAVGCL](https://github.com/ecmnet/MAVGCL) is an in-flight log analyzer for PX4.
|
||||
It can also be used in offline mode with downloaded uLog files.
|
||||
|
||||
Key features:
|
||||
|
||||
- Realtime data acquisition (50ms sampling, 100ms rolling display) based on MAVLink messages or ULOG data over MAVLink
|
||||
- Timechart annotated by messages (MAVLink and ULog) and parameter changes (MAVLink only)
|
||||
- XY Analysis for selected key-figures
|
||||
- 3D View (vehicle and observer perspective)
|
||||
- MAVLink inspector (reporting raw MAVLink messages)
|
||||
- Offline-mode: Import of key-figures from PX4Log/ULog (file or last log from device via WiFi)
|
||||
- Java based. Known to work on macOS and Ubuntu.
|
||||
- And many more ...
|
||||
|
||||

|
||||
|
||||
### Data Comets
|
||||
|
||||
[Data Comets](https://github.com/dsaffo/DataComets) is a interactive PX4 flight log analysis tool that allows you to encode flight data onto the flight path, filter and brush the data by time - and much more!
|
||||
|
||||
You can use the online version of the tool for small log files (< 32Mb), or run it locally in order to analyze longer flights.
|
||||
|
||||

|
||||
@@ -0,0 +1,441 @@
|
||||
# Log Analysis using Flight Review
|
||||
|
||||
The [Flight Review](http://logs.px4.io) plots for a flight can be used to analyze general vehicle condition.
|
||||
|
||||
The plots are meant to be self-explanatory, but it takes some experience to know what ranges are acceptable and what a plot should look like.
|
||||
This page explains how to interpret the plots and identify common problems.
|
||||
|
||||
## General Usage
|
||||
|
||||
Features that are common to many plots:
|
||||
|
||||
- Plot background color is used to indicate flight mode during recording (where graphs depend on mode):
|
||||

|
||||
- **Flight mode:** Background colour on the body of the plot indicates flight mode.
|
||||
Hovering with the mouse over a plot shows the flight mode labels.
|
||||
- **VTOL flight mode:** VTOL vehicles additionally show the VTOL mode as background colour in the bottom part of the plot (blue for multicopter, yellow for fixed-wing, and red for transition).
|
||||
- Mouse scrolling on a particular plot axis zooms that axis (horizontally or vertically).
|
||||
- Mouse scrolling inside the plot zooms both axes.
|
||||
|
||||
<a id="tracking"></a>
|
||||
|
||||
## PID Tracking Performance
|
||||
|
||||
Depending on the flight mode, the vehicle controllers may attempt to track position, velocity, altitude or rate setpoints (the tracked setpoints depend on the mode, e.g.: in Stabilized mode there is no velocity setpoint).
|
||||
|
||||
The **Estimated** line (red) should closely match with the **Setpoint** (green).
|
||||
If they do not, in most cases the PID gains of that controller need to be tuned.
|
||||
|
||||
The [Multicopter PID Tuning Guide](../config_mc/pid_tuning_guide_multicopter.md) contains example plots and information about analysing tracking performance.
|
||||
|
||||
:::tip
|
||||
For the rate controller in particular, it is useful to enable the high-rate logging profile ([SDLOG_PROFILE](../advanced_config/parameter_reference.md#SDLOG_PROFILE)) to get more details when zooming in.
|
||||
:::
|
||||
|
||||
## Vibration
|
||||
|
||||
Vibration is one of the most common problems for multirotor vehicles.
|
||||
High vibration levels can lead to:
|
||||
- less efficient flight and reduced flight time
|
||||
- the motors can heat up
|
||||
- increased material wearout
|
||||
- inability to tune the vehicle tightly, resulting in degraded flight performance.
|
||||
- sensor clipping
|
||||
- position estimation failures, potentially resulting in fly-aways.
|
||||
|
||||
It is therefore important to keep an eye on the vibration levels and improve the setup if needed.
|
||||
|
||||
There is a point where vibration levels are clearly too high, and generally lower vibration levels are better.
|
||||
However there is a broad range between 'everything is ok' and 'the levels are too high'.
|
||||
This range depends on a number of factors, including vehicle size - as larger vehicles have higher inertia, allowing for more software filtering (at the same time the vibrations on larger vehicles are of lower frequency).
|
||||
|
||||
The following paragraphs and sections provide information about what plots to use for checking vibration levels, and how to analyse them.
|
||||
|
||||
:::tip
|
||||
It is worth looking at multiple charts when analyzing vibration (different charts can better highlight some issues).
|
||||
:::
|
||||
|
||||
### Actuator Controls FFT
|
||||
|
||||
::: info
|
||||
You need to enable the high-rate logging profile ([SDLOG_PROFILE](../advanced_config/parameter_reference.md#SDLOG_PROFILE)) to see this plot.
|
||||
:::
|
||||
|
||||
This graph shows a frequency plot for the roll, pitch and yaw axis based on the actuator controls signal (the PID output from the rate controller).
|
||||
It helps to identify frequency peaks and configuring the software filters.
|
||||
There should only be a single peak at the lowest end (below around 20 Hz), the rest should be low and flat.
|
||||
|
||||
Note that the y-axis scaling is different for different vehicles, but logs from the same vehicle can be directly compared to each other.
|
||||
|
||||
#### Examples: Good Vibration
|
||||
|
||||
[QAV-R 5" Racer](../frames_multicopter/qav_r_5_kiss_esc_racer.md) frame (excellent vibration).
|
||||
|
||||

|
||||
|
||||
::: info
|
||||
The excellent vibration characteristics of the above frame mean that we can considerably increase the cutoff frequency of the [software filters](../config_mc/filter_tuning.md) (reducing control latency).
|
||||
:::
|
||||
|
||||
DJI F450 frame (good vibration).
|
||||
|
||||

|
||||
|
||||
S500 frame:
|
||||
|
||||

|
||||
|
||||
::: info
|
||||
While the plot above looks good, the [Raw Acceleration graph for the same flight](#raw_acc_s500) shows that the vibration levels are a bit high for x and y.
|
||||
This is a good example of why it is worth checking several graphs!
|
||||
:::
|
||||
|
||||
#### Examples: Bad Vibration
|
||||
|
||||
This example shows a peak in frequency close to 50 Hz (in this case due to "loose" landing gear).
|
||||
|
||||

|
||||
|
||||
|
||||
### Acceleration Power Spectral Density
|
||||
|
||||
This is a 2D frequency plot showing the frequency response of the raw accelerometer data over time (it displays the sum for the x, y and z axis).
|
||||
The more yellow an area is, the higher the frequency response at that time and frequency.
|
||||
|
||||
Ideally only the lowest part up to a few Hz is yellow, and the rest is mostly green or blue.
|
||||
|
||||
|
||||
#### Examples: Good Vibration
|
||||
|
||||
[QAV-R 5" Racer](../frames_multicopter/qav_r_5_kiss_esc_racer.md) frame (excellent vibration).
|
||||
|
||||

|
||||
<!-- https://logs.px4.io/plot_app?log=cd88b091-ec89-457c-85f6-e63e4fa0f51d -->
|
||||
|
||||
DJI F450 frame (good vibration).
|
||||

|
||||
|
||||
::: info
|
||||
Above you can see the blade passing frequency of the propellers at around 100 Hz.
|
||||
:::
|
||||
|
||||
S500 frame:
|
||||

|
||||
|
||||
|
||||
#### Examples: Bad Vibration
|
||||
|
||||
The strong yellow lines at around 100Hz indicate a potential issue that requires further investigation (starting with a review of the other charts).
|
||||
|
||||

|
||||
|
||||
This plot below shows a peak in frequency close to 50 Hz (in this case due to "loose" landing gear).
|
||||
|
||||
:::tip
|
||||
This indicates a possible problem because it is a strong single low frequency that is close to the vehicle dynamics.
|
||||
With the default filter settings of 80 Hz vibrations at 50 Hz will not be filtered.
|
||||
:::
|
||||
|
||||

|
||||
|
||||
|
||||
Extremely high (unsafe) vibration! Note that the graph is almost completely yellow.
|
||||
|
||||
:::warning
|
||||
You should not fly with such high vibration levels.
|
||||
:::
|
||||
|
||||

|
||||
|
||||
|
||||
### Raw Acceleration
|
||||
|
||||
This graph shows the raw accelerometer measurements for the x, y and z axis.
|
||||
Ideally each line is thin and clearly shows the vehicle's accelerations.
|
||||
|
||||
As a rule of thumb if the z-axis graph is touching the x/y-axis graph during hover or slow flight, the vibration levels are too high.
|
||||
|
||||
:::tip
|
||||
The best way to use this graph is to zoom in a bit to a part where the vehicle is hovering.
|
||||
:::
|
||||
|
||||
#### Examples: Good Vibration
|
||||
|
||||
[QAV-R 5" Racer](../frames_multicopter/qav_r_5_kiss_esc_racer.md) frame (excellent vibration).
|
||||
|
||||

|
||||
|
||||
DJI F450 frame (good vibration).
|
||||

|
||||
|
||||
<!-- https://logs.px4.io/plot_app?log=cd88b091-ec89-457c-85f6-e63e4fa0f51d -->
|
||||
|
||||
|
||||
#### Examples: Bad Vibration
|
||||
|
||||
<a id="raw_acc_s500"></a>
|
||||
S500 frame. Borderline vibration levels - a bit high for x and y (which is typical for an S500 airframe).
|
||||
This is at the limit where it starts to negatively affect flight performance.
|
||||
|
||||

|
||||
|
||||
|
||||
Vibration too high. Note how the graph of the z-axis overlaps with the x/y-axis graph:
|
||||
|
||||

|
||||
|
||||
|
||||
Vibration levels are too high. Note how the graph of the z-axis overlaps with the x/y-axis graph:
|
||||
|
||||

|
||||
|
||||
|
||||
Very high (unsafe) vibration levels.
|
||||
|
||||
:::warning
|
||||
You should not fly with such high vibration levels.
|
||||
:::
|
||||
|
||||

|
||||
|
||||
|
||||
<a id="fifo_logging"></a>
|
||||
|
||||
### Raw High-rate IMU Data Plots
|
||||
|
||||
For an in-depth analysis there is an option to log the raw IMU data at full rate (several kHz, depending on the IMU).
|
||||
This allows inspection of much higher frequencies than with normal logging, which can help when selecting vibration mounts or configuring low-pass and notch filters appropriately.
|
||||
|
||||
To use it, some parameters need to be changed:
|
||||
- Set [IMU_GYRO_RATEMAX](../advanced_config/parameter_reference.md#IMU_GYRO_RATEMAX) to 400.
|
||||
This ensures that the raw sensor data is more efficiently packed when sent from the sensor to the rest of the system, and reduces the log size (without reducing useful data).
|
||||
<!-- Explanation in https://github.com/PX4/PX4-user_guide/pull/751/files#r440509688
|
||||
Data is sent in a fixed size array that will largely empty if sent at higher rate. The "empty data" is also logged.-->
|
||||
- Use a good SD card, as the IMU data requires a high logging bandwidth (Flight Review will show dropouts if the logging rate gets too high).
|
||||
|
||||
:::tip
|
||||
See [Logging > SD Cards](../dev_log/logging.md#sd-cards) for a comparison of popular SD card.
|
||||
:::
|
||||
|
||||
- Enable either the gyro or accel high-rate FIFO profile in [SDLOG_PROFILE](../advanced_config/parameter_reference.md#SDLOG_PROFILE) and disable the rest of the entries.
|
||||
If you are using a really good SD card (seeing few/no dropouts), you can:
|
||||
- either enable both accel and gyro profiles
|
||||
- or enable accel/gyro plus the default logging profile
|
||||
|
||||
Example plot:
|
||||
|
||||

|
||||
|
||||
::: info
|
||||
Data of the first IMU is logged, which is not necessarily the same as the one used for flying.
|
||||
This is mostly only important in cases where IMU's are mounted differently (e.g. hard-mounted vs. soft-mounted).
|
||||
:::
|
||||
|
||||
::: info
|
||||
Do not forget to restore the parameters after testing.
|
||||
:::
|
||||
|
||||
<a id="solutions"></a>
|
||||
|
||||
### Fixing Vibration Problems
|
||||
|
||||
Often a source of vibration (or combination of multiple sources) cannot be identified from logs alone.
|
||||
|
||||
In this case the vehicle should be inspected.
|
||||
[Vibration Isolation](../assembly/vibration_isolation.md) explains some basic things you can check (and do) to reduce vibration levels.
|
||||
|
||||
|
||||
|
||||
## Actuator Outputs
|
||||
|
||||
The *Actuator Outputs* graph shows the signals that are sent to the individual actuators (motors/servos).
|
||||
Generally it is in the range between the minimum and maximum configured PWM values (e.g. from 1000 to 2000).
|
||||
|
||||
This is an example for a quadrotor where everything is OK (all of the signals are within the range, approximately overlap each other, and are not too noisy):
|
||||

|
||||
|
||||
The plot can help to identify different problems:
|
||||
- If one or more of the signals is at the maximum over a longer time, it means the controller runs into **saturation**.
|
||||
It is not necessarily a problem, for example when flying at full throttle this is expected.
|
||||
But if it happens for example during a mission, it's an indication that the vehicle is overweight for the amount of thrust that it can provide.
|
||||
- For a multicopter the plot can be a good indication if the vehicle is **imbalanced**.
|
||||
It shows in the plot that one or more neighboring motors (two in case of a quadrotor) need to run at higher thrust on average.
|
||||
Note that this can also be the case if some motors provide more thrust than others or the ESCs are not calibrated.
|
||||
An imbalanced vehicle is generally not a big problem as the autopilot will automatically account for it.
|
||||
However it reduces the maximum achievable thrust and puts more strain on some motors, so it is better to balance the vehicle.
|
||||
- An imbalance can also come from the yaw axis.
|
||||
The plot will look similar as in the previous case, but opposite motors will run higher or lower respectively.
|
||||
The cause is likely that one or more motors are tilted.
|
||||
|
||||
This is an example from a hexarotor: motors 1, 3 and 6 run at higher thrust:
|
||||

|
||||
<!-- https://logs.px4.io/plot_app?log=9eca6934-b657-4976-a32f-b2e56535f05f -->
|
||||
- If the signals look very **noisy** (with high amplitudes), it can have two causes: sensor noise or vibrations passing through the controller (this shows up in other plots as well, see previous section) or too high PID gains.
|
||||
This is an extreme example:
|
||||

|
||||
|
||||
|
||||
## GPS Uncertainty
|
||||
|
||||
The *GPS Uncertainty* plot shows information from the GPS device:
|
||||
- Number of used satellites (should be around 12 or higher)
|
||||
- Horizontal position accuracy (should be below 1 meter)
|
||||
- Vertical position accuracy (should be below 2 meters)
|
||||
- GPS fix: this is 3 for a 3D GPS fix, 4 for GPS + Dead Reckoning, 5 for RTK float and 6 for RTK fixed type
|
||||
|
||||
|
||||
## GPS Noise & Jamming
|
||||
|
||||
The GPS Noise & Jamming plot is useful to check for GPS signal interferences and jamming.
|
||||
The GPS signal is very weak and thus it can easily be disturbed/jammed by components transmitting (via cable) or radiating in a frequency used by the GPS.
|
||||
|
||||
:::tip
|
||||
USB 3 is [known to be](https://www.usb.org/sites/default/files/327216.pdf) an effective GPS jamming source.
|
||||
:::
|
||||
|
||||
The **jamming indicator** should be around or below 40.
|
||||
Values around 80 or higher are too high and the setup must be inspected.
|
||||
Signal interference is also noticeable as reduced accuracy and lower number of satellites up to the point where no GPS fix is possible.
|
||||
|
||||
This is an example without any interference:
|
||||
|
||||

|
||||
|
||||
|
||||
## Thrust and Magnetic Field
|
||||
|
||||
The *Thrust and Magnetic Field* plot shows the thrust and the norm of the magnetic sensor measurement vector.
|
||||
|
||||
The norm should be constant over the whole flight and uncorrelated with the thrust.
|
||||
This is a good example where the norm is very close to constant:
|
||||

|
||||
|
||||
*If it is correlated*, it means that the current drawn by the motors (or other consumers) is influencing the magnetic field.
|
||||
This must be avoided as it leads to incorrect yaw estimation.
|
||||
The following plot shows a strong correlation between the thrust and the norm of the magnetometer:
|
||||

|
||||
|
||||
Solutions to this are:
|
||||
- Use an external magnetometer (avoid using the internal magnetometer)
|
||||
- If using an external magnetometer, move it further away from strong currents (i.e. by using a (longer) GPS mast).
|
||||
|
||||
If the norm is uncorrelated but not constant, most likely it is not properly calibrated.
|
||||
However it could also be due to external disturbances (for example when flying close to metal constructs).
|
||||
|
||||
This example shows that the norm is non-constant, but it does not correlate with the thrust:
|
||||

|
||||
|
||||
|
||||
## Estimator Watchdog
|
||||
|
||||
The *Estimator Watchdog* plot shows the health report of the estimator.
|
||||
It should be constant zero.
|
||||
|
||||
This is what it should look like if there are no problems:
|
||||

|
||||
|
||||
If one of the flags is non-zero, the estimator detected a problem that needs to be further investigated.
|
||||
Most of the time it is an issue with a sensor, for example magnetometer interferences.
|
||||
It usually helps to look at the plots of the corresponding sensor.
|
||||
<!-- TODO: separate page for estimator issues? -->
|
||||
|
||||
Here is an example with magnetometer problems:
|
||||

|
||||
|
||||
|
||||
## Sampling Regularity of Sensor Data
|
||||
|
||||
The sampling regularity plot provides insights into problems with the logging system and scheduling.
|
||||
|
||||
The amount of **logging dropouts** start to increase if the log buffer is too small, the logging rate is too high or a low-quality SD card is used.
|
||||
|
||||
::: info
|
||||
Occasional dropouts can be expected on medium quality cards.
|
||||
:::
|
||||
|
||||
The **delta t** shows the time difference between two logged IMU samples.
|
||||
It should be close to 4 ms because the data publishing rate is 250Hz.
|
||||
If there are spikes that are a multiple of that (and the estimator time slip does not increase), it means the logger skipped some samples.
|
||||
Occasionally this can happen because the logger runs at lower priority.
|
||||
If there are spikes that are not a multiple, it indicates an irregular sensor driver scheduling, which needs to be investigated.
|
||||
|
||||
The **estimator timeslip** shows the difference between the current time and the time of the integrated sensor intervals up to that time.
|
||||
If it changes it means either the estimator missed sensor data or the driver publishes incorrect integration intervals.
|
||||
It should stay at zero, but it can increase slightly for in-flight parameter changes, which is generally not an issue.
|
||||
|
||||
This is a good example:
|
||||

|
||||
|
||||
The following example contains too many dropouts, the quality of the used SD card was too low in that case
|
||||
(see [here](../dev_log/logging.md#sd-cards) for good SD cards):
|
||||
|
||||

|
||||
|
||||
## Logged Messages
|
||||
|
||||
This is a table with system error and warning messages.
|
||||
For example they show when a task becomes low on stack size.
|
||||
|
||||
The messages need to be examined individually, and not all of them indicate a problem.
|
||||
For example the following shows a kill-switch test:
|
||||

|
||||
|
||||
|
||||
## Flight/Frame Log Review Examples
|
||||
|
||||
It is often worth looking at multiple charts for a particular flight when analyzing vehicle condition (different charts can better highlight some issues).
|
||||
This is particularly important when reviewing for possible vibration problems.
|
||||
|
||||
The section below groups a few (previously presented) charts by flight/vehicle.
|
||||
|
||||
### QAV-R 5" Racer
|
||||
|
||||
These charts are all from the same flight of a [QAV-R 5" Racer](../frames_multicopter/qav_r_5_kiss_esc_racer.md).
|
||||
<!-- https://logs.px4.io/plot_app?log=cd88b091-ec89-457c-85f6-e63e4fa0f51d -->
|
||||
|
||||
They show a vehicle that has very low vibration:
|
||||
- Actuator Controls FFT shows only a single peak at the lowest end, with the rest low and flat.
|
||||
- Spectral density is mostly green, with only a little yellow at the low frequencies.
|
||||
- Raw Acceleration has z-axis trace well separated from the x/y-axis traces.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
|
||||
### DJI F450
|
||||
|
||||
These charts are all from the same flight of a *DJI F450*.
|
||||
<!-- https://logs.px4.io/plot_app?log=cd88b091-ec89-457c-85f6-e63e4fa0f51d -->
|
||||
|
||||
They show a vehicle that has low vibration (but not as low as the QAV-R above!):
|
||||
- Actuator Controls FFT shows a peak at the lowest end.
|
||||
Most of the rest is flat, except for a bump at around 100Hz (this is the blade passing frequency of the propellers).
|
||||
- Spectral density is mostly green. The blade passing frequency is again visible.
|
||||
- Raw Acceleration has z-axis trace well separated from the x/y-axis traces.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
|
||||
### S500
|
||||
|
||||
These charts are all from the same flight of an S500.
|
||||
|
||||
They show a vehicle that has borderline-acceptable vibration:
|
||||
- Actuator Controls FFT shows a peak at the lowest end.
|
||||
Most of the rest is flat, except for a bump at around 100Hz.
|
||||
- Spectral density is mostly green, but more yellow than for the DJI F450 at 100Hz.
|
||||
- Raw Acceleration has z-axis trace fairly close to the x/y-axis traces.
|
||||
This is at the limit where it starts to negatively affect flight performance.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
@@ -0,0 +1,120 @@
|
||||
# Log Analysis using PlotJuggler
|
||||
|
||||
[PlotJuggler](https://github.com/facontidavide/PlotJuggler) can be used to analyze ULogs for in-depth, development purposes.
|
||||
It is incredibly useful as every uORB topic is exposed / can be graphed, as well as having custom functions to modify the data (e.g. from Quaternion values to Roll / Pitch / Yaw).
|
||||
|
||||
## Installation
|
||||
|
||||
You can find the latest releases of the Plot Juggler [here](https://github.com/facontidavide/PlotJuggler/releases).
|
||||
|
||||
#### Notes on Windows distribution
|
||||
|
||||
The latest version of PlotJuggler for Windows may not work.
|
||||
In this case fallback to [v2.8.4 here](https://github.com/facontidavide/PlotJuggler/releases/tag/2.8.4) (this is known to work with Windows).
|
||||
|
||||
#### Notes on AppImage for Linux distributions
|
||||
|
||||
If the downloaded AppImage does not open, you may need to change its access settings.
|
||||
This is done in the terminal using the following command:
|
||||
|
||||
```sh
|
||||
chmod 777 <Path-To-PlotJuggler-AppImage>
|
||||
```
|
||||
|
||||
## General Usage
|
||||
|
||||
Two most common tasks are "Searching" for the logged uORB topic, and "Drag and Dropping" a field in a specific topic onto the graph view.
|
||||
These are demonstrated in the diagram below.
|
||||
|
||||

|
||||
|
||||
### Splitting Horizontally / Vertically : Multi Panel
|
||||
|
||||
One of the most powerful feature is splitting the screen in either horizontal/vertical orientation and displaying different graphs at the same time ( with a synchronized time-bar on top, as you move the time cursor in the bottom).
|
||||
|
||||
This is demonstrated in an animation below:
|
||||
|
||||

|
||||
|
||||
In this example, `vehicle_local_position` topic's `ax`, `ay` and `az` (Acceleration estimate) components were graphed first by splitting the screen in 3 sections.
|
||||
Then, the `vz` (Velocity estimate) component was added under right pane, and finally `battery_status` topic's `current_a` (Battery current) was graphed in the lower-mid pane.
|
||||
|
||||
Although not obvious in the beginning you can observe that whenever the vehicle starts moving (battery current value goes high), the acceleration and velocity values start to move around as well.
|
||||
This is because all the data is displayed as a time-series, which shows each value at on a specific timestamp.
|
||||
|
||||
This is useful for providing a broad view of what happened and why.
|
||||
It is often hard to troubleshoot a problem just by looking at one graph, but by having multiple graphs displayed, it is much easier to figure out what was going on in the system.
|
||||
|
||||
### Displaying Data in 2D
|
||||
|
||||
Another powerful feature is the ability to display 2D data on a XY plane (each data on X, Y axis) in a scatter-plot manner.
|
||||
This is done by selecting two data points by holding `Ctrl` key while selecting each of them (e.g. `vehicle_local_position` topic's `x` and `y` components), and drag & dropping it with the `Right mouse cursor` pressed.
|
||||
|
||||

|
||||
|
||||
In this example, the estimated vehicle's position in local coordinate frame is graphed onto a XY-plane which shows a 2D view of the estimated position, and the `vx` and `vy` components (Velocity estimate) are graphed on the right, with the `vz` (Vertical velocity estimate) graphed underneath it in a split view.
|
||||
|
||||
This in turn shows the relationship between position and the velocity of the vehicle intuitively.
|
||||
For example, note how when the vehicle moves in the X-axis direction, the `vx` value goes high, and as the vehicle turns to the Y-axis direction, the `vy` value starts to change as well.
|
||||
|
||||
#### Using the 'Play' button
|
||||
|
||||
Here the **Play** button is used to play the recorded data in real time (speed factor can be adjusted in the lower-right corner).
|
||||
This shows the position / velocity relationship described above in detail.
|
||||
|
||||

|
||||
|
||||
::: info
|
||||
Try out the boat testing log analysis yourself by downloading the ULog and Layout file used above!
|
||||
- [Boat testing ULog](https://github.com/PX4/PX4-user_guide/raw/main/assets/flight_log_analysis/plot_juggler/sample_log_boat_testing_2022-7-28-13-31-16.ulg)
|
||||
- [Boat testing Analysis Layout](https://raw.githubusercontent.com/PX4/PX4-user_guide/main/assets/flight_log_analysis/plot_juggler/sample_log_boat_testing_layout.xml)
|
||||
:::
|
||||
|
||||
### Layout Templates
|
||||
|
||||
There are a number of PlotJuggler layout files shared by PX4 Developers.
|
||||
Each can be used for a specific purpose (Multicopter tuning, VTOL tuning, Boat debugging, etc.):
|
||||
|
||||
* [Sample View layout](https://github.com/PX4/PX4-user_guide/blob/main/assets/flight_log_analysis/plot_juggler/plotjuggler_sample_view.xml) : Template used in the [Multi-panel example](#splitting-horizontally-vertically-multi-panel) above.
|
||||
|
||||
|
||||
## Advanced Usage
|
||||
|
||||
### Creating custom time series using LUA script
|
||||
|
||||
Plot Juggler supports having LUA scripts to process and display data.
|
||||
This is a powerful feature that can do things like integrating the curve, averaging two curves, removing offsets, etc.
|
||||
|
||||
#### Calculating Roll/Pitch/Yaw from Quaternion
|
||||
|
||||

|
||||
|
||||
To know vehicle's attitude, PX4 logs the estimated attitude's quaternion in the `vehicle_attitude` topic in an array of floating point values (q[4]).
|
||||
Since these values don't give contextual information (e.g. `roll`), it needs a transformation involving trigonometric functions.
|
||||
|
||||
1. Search for `vehicle_attitude` topic in Timeseries List panel on the left
|
||||
2. Select 4 quaternion members (`q.00, q.01, q.02, q.03`) by clicking `q.00` first, then holding Shift + clicking `q.03`. They should all be selected
|
||||
3. Click the '+' symbol in the lower-left 'Custom Series' section to create new series
|
||||
4. Select 4 quaternion members again, and drag them to 'Input timeseries + Additional source timeseries' tab on upper-left corner
|
||||
5. Double click on the `quat_to_roll` from the Function Library. Now you should have the plot on upper section
|
||||
6. Assign the name for the plot (e.g. `roll`) in the text box in upper-right corner
|
||||
7. Click 'Create New Timeseries'. You should now have the plot in 'Custom Series'
|
||||
|
||||
Here the custom series `Roll` is displayed along with other timeseries, including it's original form in Quaternion on the right, which is not human-readable (using PlotJuggler 3.5.0):
|
||||
|
||||

|
||||
|
||||
The `quat_to_roll` function looks like this:
|
||||
```lua
|
||||
w = value
|
||||
x = v1
|
||||
y = v2
|
||||
z = v3
|
||||
|
||||
dcm21 = 2 * (w * x + y * z)
|
||||
dcm22 = w*w - x*x - y*y + z*z
|
||||
|
||||
roll = math.atan(dcm21, dcm22)
|
||||
|
||||
return roll
|
||||
```
|
||||
@@ -1,6 +1,6 @@
|
||||
# MAVLink Peripherals (GCS/OSD/Companion)
|
||||
# MAVLink Peripherals (GCS/OSD/Gimbal/Camera/Companion)
|
||||
|
||||
Ground Control Stations (GCS), On-Screen Displays (OSD), Companion Computers, ADS-B receivers, and other MAVLink peripherals interact with PX4 using separate MAVLink streams, sent via different serial ports.
|
||||
Ground Control Stations (GCS), On-Screen Displays (OSD), MAVLink Cameras & Gimbals, Remote IDs, Companion Computers, ADS-B receivers, and other MAVLink peripherals interact with PX4 using separate MAVLink streams, sent via different serial ports.
|
||||
|
||||
In order to configure that a particular serial port is used for MAVLink traffic with a particular peripheral, we use [Serial Port Configuration](../peripherals/serial_configuration.md), assigning one of the abstract "MAVLink instance" configuration parameters to the desired port.
|
||||
We then set other properties of the MAVLink channel using the parameters associated with our selected MAVLink instance, so that they match the requirements of our particular peripheral.
|
||||
@@ -36,8 +36,10 @@ The parameters for each instance are:
|
||||
- _OSD_: Standard set of messages for an OSD system.
|
||||
- _Config_: Standard set of messages and rate configuration for a fast link (e.g. USB).
|
||||
- _Minimal_: Minimal set of messages for use with a GCS connected on a high latency link.
|
||||
- _ExtVision_ or _ExtVisionMin_: Messages for offboard vision systems (ExtVision needed for VIO).
|
||||
- _Iridium_: Messages for an [Iridium satellite communication system](../advanced_features/satcom_roadblock.md).
|
||||
- _External Vision_: Messages for offboard vision systems.
|
||||
- _Gimbal_: Messages for a gimbal. Note this also enables [message forwarding](#MAV_X_FORWARD)
|
||||
- _Onboard Low Bandwidth_: Standard set of messages for a companion computer connected on a lower speed link.
|
||||
- _uAvionix_: Messages for a uAvionix ADS-B beacon.
|
||||
|
||||
::: info
|
||||
If you need to find the specific set of message for each mode search for `MAVLINK_MODE_` in [/src/modules/mavlink/mavlink_main.cpp](https://github.com/PX4/PX4-Autopilot/blob/main/src/modules/mavlink/mavlink_main.cpp).
|
||||
@@ -64,9 +66,7 @@ You will need to reboot PX4 to make the parameter available (i.e. in QGroundCont
|
||||
The parameter used will depend on the [assigned serial port](../advanced_config/parameter_reference.md#serial) - for example: `SER_GPS1_BAUD`, `SER_TEL2_BAUD`, etc.
|
||||
The value you use will depend on the type of connection and the capabilities of the connected MAVLink peripheral.
|
||||
|
||||
<a id="default_ports"></a>
|
||||
|
||||
## Default MAVLink Ports
|
||||
## Default MAVLink Ports {#default_ports}
|
||||
|
||||
### TELEM1
|
||||
|
||||
@@ -108,8 +108,16 @@ On this hardware, there is a [default serial port mapping](../peripherals/serial
|
||||
|
||||
For more information see: [PX4 Ethernet Setup](../advanced_config/ethernet_setup.md)
|
||||
|
||||
## Device Specific Setup
|
||||
|
||||
Links to setup instructions for specific MAVLink components:
|
||||
|
||||
- [MAVLink Cameras (Camera Protocol v2) > PX4 Configuration](../camera/mavlink_v2_camera.md#px4-configuration)
|
||||
- [Gimbal Configuration > MAVLink Gimbal (MNT_MODE_OUT=MAVLINK)](../advanced/gimbal_control.md#mavlink-gimbal-mnt-mode-out-mavlink)
|
||||
|
||||
## See Also
|
||||
|
||||
- [Serial Port Configuration](../peripherals/serial_configuration.md)
|
||||
- [PX4 Ethernet Setup > PX4 MAVLink Serial Port Configuration](../advanced_config/ethernet_setup.md#px4-mavlink-serial-port-configuration)
|
||||
- [Serial Port Mapping](../hardware/serial_port_mapping.md)
|
||||
|
||||
|
||||
@@ -10,13 +10,14 @@ PX4 supports a number of types of telemetry radios:
|
||||
- <del>_HKPilot Telemetry Radio_</del> (Discontinued)
|
||||
- <del>_3DR Telemetry Radio_</del> (Discontinued)
|
||||
- [Telemetry Wifi](../telemetry/telemetry_wifi.md)
|
||||
- [J.Fi Wireless Telemetry Module](../telemetry/jfi_telemetry.md)
|
||||
- [Microhard Serial Telemetry Radio](../telemetry/microhard_serial.md)
|
||||
- [ARK Electron Microhard Serial Telemetry Radio](../telemetry/ark_microhard_serial.md)
|
||||
- [Holybro Microhard P900 Telemetry Radio](../telemetry/holybro_microhard_p900_radio.md)
|
||||
- CUAV Serial Telemetry Radio
|
||||
- [CUAV P8 Telemetry Radio](../telemetry/cuav_p8_radio.md)
|
||||
- XBee Serial Telemetry Radio
|
||||
- [HolyBro XBP9X Telemetry Radio](../telemetry/holybro_xbp9x_radio.md) (Discontinued)
|
||||
- <del>[HolyBro XBP9X Telemetry Radio](../telemetry/holybro_xbp9x_radio.md)</del> (Discontinued)
|
||||
|
||||
PX4 is protocol compatible with [SiK Radio](../telemetry/sik_radio.md) and will generally work out of the box (though you may need to change/use an appropriate connector).
|
||||
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
# J.Fi Wireless Telemetry Module
|
||||
|
||||
The J.MARPLE [J.Fi telemetry module](https://jmarple.ai/j-fi/) is a compact and lightweight wireless communication device featuring a PCB-integrated antenna or external antenna, enabling seamless telemetry connections between various drone flight controllers (FC) and ground control stations.
|
||||
|
||||
This module includes a Pixhawk-standard JST 6-pin `TELEM` connector, ensuring compatibility with all PX4-based flight controllers.
|
||||
It supports quick plug-and-play operation to `TELEM1` with default settings, requiring no additional configuration.
|
||||
|
||||
The J.Fi telemetry module provides reliable communication up to approximately 500 meters when using a PCB-integrated antenna.
|
||||
Operating in the 2.4GHz frequency band, it allows unrestricted global use without regulatory limitations.
|
||||
|
||||

|
||||
|
||||
## Where to Buy
|
||||
|
||||
- [https://jmarple.ai/j-fi/](https://jmarple.ai/j-fi/)
|
||||
|
||||
## Technical Specifications
|
||||
|
||||
### Wireless Performance
|
||||
|
||||
- **Frequency Band:** 2.4GHz
|
||||
- **Speed:** Up to 11 Mbps (adjustable)
|
||||
- **Range:** Up to 500 meters (varies upon environments)
|
||||
- **Payload Capacity:** Up to 1400 bytes
|
||||
|
||||
### Network Schemes
|
||||
|
||||
- **Supported Topologies:** 1:1, 1:N, N:N
|
||||
- **Collision Management:** Time Slot-Based Response Delay
|
||||
|
||||
### User-Friendly Features
|
||||
|
||||
- **Buttons:** Pairing and Mode Switching
|
||||
- **LED Indicators:** Real-time status updates
|
||||
- **Configuration:** Web browser-based setup
|
||||
- **Micro USB Port for connecting to PC or GCS**
|
||||
|
||||
## Broadcast Communication
|
||||
|
||||
With default settings enabled, the device automatically broadcasts data to all nearby J.Fi devices.
|
||||
Connect your external device or system to the **Broadcast port**.
|
||||
No additional setup is required.
|
||||
|
||||

|
||||
|
||||
## Paired Communication
|
||||
|
||||
- Modules must first undergo an initial pairing procedure.
|
||||
- Once paired, communication is _restricted to paired J.Fi devices_. Connect your external device or system to the **Pair port.**
|
||||
|
||||

|
||||
|
||||
### 1:1 Pairing
|
||||
|
||||

|
||||
|
||||
- On **each device,** press and hold _button A_, then click the _RST button_.
|
||||
Release _button A_ when _LED 1_ blinks.
|
||||
- Both devices will enter pairing mode
|
||||
- Choose one module and double-click _button A_
|
||||
- On the other module, click _button A_ once
|
||||
- On the first module, click _button A_ once again to finish pairing
|
||||
- Pairing complete
|
||||
|
||||
### 1:N Pairing
|
||||
|
||||
- On **each device,** press and hold _button A_, then click the _RST button_.
|
||||
Release _button A_ when _LED 1_ blinks.
|
||||
- All devices will enter pairing mode
|
||||
- **Host module (1):** Double-click _button A_
|
||||
- **Client modules (N):** Click _button A_ once on each module to pair
|
||||
- **Host module (1):** Click _button A_ again to finish pairing
|
||||
- Pairing complete.
|
||||
|
||||
<lite-youtube videoid="CnjhTfvARmw" title="J.Fi Wireless Telemetry Module Pairing Guide"/>
|
||||
|
||||
## PX4 Setup
|
||||
|
||||
PX4 is plug-and-play with J.Fi if connected to the `TELEM1` port, and should connect without further connection.
|
||||
|
||||
If you want to use another port you will need to assign a MAVLink instance to the serial port (see [MAVLink Peripherals (GCS/OSD/Companion)](../peripherals/mavlink_peripherals.md)) (and possibly unassign whatever is currently using the port).
|
||||
|
||||
### One-to-one (1:1) Setups
|
||||
|
||||
The `TELEM1` port is set to use `57600` as the baud rate by default (and J.Fi is set to match).
|
||||
This default baud rate is calibrated for inexpensive low-power telemetry radios.
|
||||
While this should be sufficient for 1:1 setups, J.Fi will work with much higher rates (i.e., `115200`).
|
||||
|
||||
If you want to change the baud rate:
|
||||
|
||||
1. Change [SER_TEL1_BAUD](../advanced_config/parameter_reference.md#SER_TEL1_BAUD) if you're using the `TELEM1` port (see [Serial Port Configuration](../peripherals/serial_configuration.md) for other ports).
|
||||
2. Update the baud rate in the [J.Fi Configuration](#j-fi-configuration) to match.
|
||||
|
||||
### One-to-many (1:N) Setups
|
||||
|
||||
For one-to-many (1:N) setups a higher baud rate is _highly recommended_ to ensure stable data reception.
|
||||
All J.Fi devices should be set to the same baud rate (although communication may work even when when devices use different baud rates).
|
||||
This should be changed in both PX4 and the J.Fi modules as explained in the previous section.
|
||||
|
||||
You will also need to make sure that all vehicles on the MAVLink network are assigned a unique **System ID** ([MAV_SYS_ID](../advanced_config/parameter_reference.md#MAV_SYS_ID)).
|
||||
|
||||

|
||||
|
||||
<lite-youtube videoid="tPeJA2gn7Zw" title="Simultaneous Control using J.Fi Wireless Telemetry Module"/>
|
||||
|
||||
## QGroundControl Configuration
|
||||
|
||||
The J.Fi will connect plug-and-play to **QGroundControl** and automatically connect just like a SiK Radio.
|
||||
|
||||
However if you change the baud rate from 57600 you will need to create and use a new link configuration:
|
||||
|
||||
1. Disable SiK Radio in QGC (**Application Settings → General → AutoConnect**).
|
||||
2. Create a new link configuration:
|
||||
- Go to **Application Settings → Comms Links**.
|
||||
- Click **Add**.
|
||||
- Set **Type** to **Serial**, configure the **Serial Port** and **Baud Rate** to match the J.Fi device.
|
||||
3. Select **Connect** to connect with the new configuration.
|
||||
|
||||
## J.Fi Configuration
|
||||
|
||||
- **Device:** Press and hold _button B_, then click the _RST button_.
|
||||
Release _button B_ when _LED 2_ blinks.
|
||||
- Device enters configuration mode
|
||||
- **Smart device:** Connect to Wi-Fi network named `J.Fi-xxxxxx` (x: alphanumeric characters)
|
||||
- **Browser:** Go to `192.168.4.1` to open the **configuration page**.
|
||||
- **Configuration page:** Adjust settings as needed, then click **Save**
|
||||
- _LED 1_ blinks once upon saving
|
||||
|
||||

|
||||
|
||||
## Further info
|
||||
|
||||
- [User Manual](https://docs.google.com/document/d/1NaVwOLuMCuNpd0uxgilXZ_qfHAnsFgBmaPxX9WGY2h4/edit?usp=sharing)
|
||||
- [ROS Github](https://github.com/SUV-Lab/J-Fi)
|
||||
@@ -10,4 +10,4 @@ This section contains topics about the core actuators used for flight control (E
|
||||
|
||||
## See Also
|
||||
|
||||
- [Peripherals](../peripherals/index.md) - includes non-core actuators such as grippers, parachutes, etc.
|
||||
- [Peripherals](../peripherals/index.md) - includes non-core actuators such as grippers, parachutes, etc.
|
||||
@@ -129,7 +129,7 @@ The on-screen gimbal control can be used to move/test a connected MAVLink camera
|
||||
|
||||
2. Open QGroundControl and enable the on-screen camera control (Application settings).
|
||||
|
||||

|
||||

|
||||
|
||||
3. Make sure the vehicle is armed and flying, e.g. by entering with `commander takeoff`.
|
||||
|
||||
|
||||
@@ -128,21 +128,21 @@ You add some "boilerplate" code to regularly listen for changes in the [uORB Top
|
||||
|
||||
- **px4_platform_common/module_params.h** to get the `DEFINE_PARAMETERS` macro:
|
||||
|
||||
```cpp
|
||||
#include <px4_platform_common/module_params.h>
|
||||
```
|
||||
```cpp
|
||||
#include <px4_platform_common/module_params.h>
|
||||
```
|
||||
|
||||
- **parameter_update.h** to access the uORB `parameter_update` message:
|
||||
|
||||
```cpp
|
||||
#include <uORB/topics/parameter_update.h>
|
||||
```
|
||||
```cpp
|
||||
#include <uORB/topics/parameter_update.h>
|
||||
```
|
||||
|
||||
- **Subscription.hpp** for the uORB C++ subscription API:
|
||||
|
||||
```cpp
|
||||
#include <uORB/Subscription.hpp>
|
||||
```
|
||||
```cpp
|
||||
#include <uORB/Subscription.hpp>
|
||||
```
|
||||
|
||||
Derive your class from `ModuleParams`, and use `DEFINE_PARAMETERS` to specify a list of parameters and their associated parameter attributes.
|
||||
매개변수의 이름은 매개변수 메타데이터 정의와 동일하여야 합니다.
|
||||
@@ -194,7 +194,7 @@ void Module::parameters_update()
|
||||
- `_parameter_update_sub.updated()` tells us if there is _any_ update to the `param_update` uORB message (but not what parameter is affected).
|
||||
- If there has been "some" parameter updated, we copy the update into a `parameter_update_s` (`param_update`), to clear the pending update.
|
||||
- Then we call `ModuleParams::updateParams()`.
|
||||
This "under the hood" updates all parameter attributes listed in our `DEFINE_PARAMETERS` list.
|
||||
This "under the hood" updates all parameter attributes listed in our `DEFINE_PARAMETERS` list.
|
||||
|
||||
The parameter attributes (`_sys_autostart` and `_att_bias_max` in this case) can then be used to represent the parameters, and will be updated whenever the parameter value changes.
|
||||
|
||||
@@ -267,12 +267,12 @@ YAML meta data is intended as a full replacement for the **.c** definitions.
|
||||
- An example of YAML definitions being used can be found in the MAVLink parameter definitions: [/src/modules/mavlink/module.yaml](https://github.com/PX4/PX4-Autopilot/blob/main/src/modules/mavlink/module.yaml).
|
||||
- YAML 파일은 다음을 추가하여 cmake 빌드 시스템에 등록됩니다.
|
||||
|
||||
```cmake
|
||||
MODULE_CONFIG
|
||||
module.yaml
|
||||
```
|
||||
```cmake
|
||||
MODULE_CONFIG
|
||||
module.yaml
|
||||
```
|
||||
|
||||
to the `px4_add_module` section of the `CMakeLists.txt` file of that module.
|
||||
to the `px4_add_module` section of the `CMakeLists.txt` file of that module.
|
||||
|
||||
#### 다중 인스턴스(템플릿) YAML 메타 데이터
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ On Windows, one option is to use _Melody Master_ within _Dosbox_.
|
||||
7. 음악을 저장할 준비가 끝나면:
|
||||
- Press **F2** to give the tune a name and save it in the _/Music_ sub folder of your Melody Master installation.
|
||||
- Press **F7**, the scroll down the list of output formats on the right to get to ANSI.
|
||||
The file will be exported to the _root_ of the Melody Master directory (with the same name and a file-type specific extension).
|
||||
The file will be exported to the _root_ of the Melody Master directory (with the same name and a file-type specific extension).
|
||||
|
||||
8. 파일을 여십시오.
|
||||
출력 내용은 다음과 같습니다:
|
||||
|
||||
@@ -23,7 +23,7 @@ You can locate the parameters in QGroundControl as shown below:
|
||||
1. Open QGroundControl menu: **Settings > Parameters > Sensor Calibration**.
|
||||
2. The parameters as located in the section as shown below (or you can search for them):
|
||||
|
||||

|
||||

|
||||
|
||||
## Parameter Summary
|
||||
|
||||
|
||||
@@ -52,81 +52,81 @@ The following steps explain how you can "manually" update the bootloader using a
|
||||
1. Get a binary containing the bootloader (either from dev team or [build it yourself](#building-the-px4-bootloader)).
|
||||
|
||||
2. Get a [Debug Probe](../debug/swd_debug.md#debug-probes-for-px4-hardware).
|
||||
Connect the probe your PC via USB and setup the `gdbserver`.
|
||||
Connect the probe your PC via USB and setup the `gdbserver`.
|
||||
|
||||
3. Go into the directory containing the binary and run the command for your target bootloader in the terminal:
|
||||
|
||||
- FMUv6X
|
||||
- FMUv6X
|
||||
|
||||
```sh
|
||||
arm-none-eabi-gdb px4_fmu-v6x_bootloader.elf
|
||||
```
|
||||
```sh
|
||||
arm-none-eabi-gdb px4_fmu-v6x_bootloader.elf
|
||||
```
|
||||
|
||||
- FMUv6X-RT
|
||||
- FMUv6X-RT
|
||||
|
||||
```sh
|
||||
arm-none-eabi-gdb px4_fmu-v6xrt_bootloader.elf
|
||||
```
|
||||
```sh
|
||||
arm-none-eabi-gdb px4_fmu-v6xrt_bootloader.elf
|
||||
```
|
||||
|
||||
- FMUv5
|
||||
- FMUv5
|
||||
|
||||
```sh
|
||||
arm-none-eabi-gdb px4fmuv5_bl.elf
|
||||
```
|
||||
```sh
|
||||
arm-none-eabi-gdb px4fmuv5_bl.elf
|
||||
```
|
||||
|
||||
::: info
|
||||
H7 Bootloaders from [PX4/PX4-Autopilot](https://github.com/PX4/PX4-Autopilot) are named with pattern `*._bootloader.elf`.
|
||||
Bootloaders from [PX4/PX4-Bootloader](https://github.com/PX4/PX4-Bootloader) are named with the pattern `*_bl.elf`.
|
||||
::: info
|
||||
H7 Bootloaders from [PX4/PX4-Autopilot](https://github.com/PX4/PX4-Autopilot) are named with pattern `*._bootloader.elf`.
|
||||
Bootloaders from [PX4/PX4-Bootloader](https://github.com/PX4/PX4-Bootloader) are named with the pattern `*_bl.elf`.
|
||||
|
||||
:::
|
||||
|
||||
4. The _gdb terminal_ appears and it should display the following output:
|
||||
|
||||
```sh
|
||||
GNU gdb (GNU Tools for Arm Embedded Processors 7-2017-q4-major) 8.0.50.20171128-git
|
||||
Copyright (C) 2017 Free Software Foundation, Inc.
|
||||
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
|
||||
This is free software: you are free to change and redistribute it.
|
||||
There is NO WARRANTY, to the extent permitted by law.
|
||||
Type "show copying" and "show warranty" for details.
|
||||
This GDB was configured as "--host=x86_64-linux-gnu --target=arm-none-eabi".
|
||||
Type "show configuration" for configuration details.
|
||||
For bug reporting instructions, please see:
|
||||
<http://www.gnu.org/software/gdb/bugs/>.
|
||||
Find the GDB manual and other documentation resources online at:
|
||||
<http://www.gnu.org/software/gdb/documentation/>.
|
||||
For help, type "help".
|
||||
Type "apropos word" to search for commands related to "word"...
|
||||
Reading symbols from px4fmuv5_bl.elf...done.
|
||||
```
|
||||
```sh
|
||||
GNU gdb (GNU Tools for Arm Embedded Processors 7-2017-q4-major) 8.0.50.20171128-git
|
||||
Copyright (C) 2017 Free Software Foundation, Inc.
|
||||
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
|
||||
This is free software: you are free to change and redistribute it.
|
||||
There is NO WARRANTY, to the extent permitted by law.
|
||||
Type "show copying" and "show warranty" for details.
|
||||
This GDB was configured as "--host=x86_64-linux-gnu --target=arm-none-eabi".
|
||||
Type "show configuration" for configuration details.
|
||||
For bug reporting instructions, please see:
|
||||
<http://www.gnu.org/software/gdb/bugs/>.
|
||||
Find the GDB manual and other documentation resources online at:
|
||||
<http://www.gnu.org/software/gdb/documentation/>.
|
||||
For help, type "help".
|
||||
Type "apropos word" to search for commands related to "word"...
|
||||
Reading symbols from px4fmuv5_bl.elf...done.
|
||||
```
|
||||
|
||||
5. Find your `<dronecode-probe-id>` by running an `ls` command in the **/dev/serial/by-id** directory.
|
||||
|
||||
6. Now connect to the debug probe with the following command:
|
||||
|
||||
```sh
|
||||
tar ext /dev/serial/by-id/<dronecode-probe-id>
|
||||
```
|
||||
```sh
|
||||
tar ext /dev/serial/by-id/<dronecode-probe-id>
|
||||
```
|
||||
|
||||
7. Power on the Pixhawk with another USB cable and connect the probe to the `FMU-DEBUG` port.
|
||||
|
||||
::: info
|
||||
If using a Dronecode probe you may need to remove the case in order to connect to the `FMU-DEBUG` port (e.g. on Pixhawk 4 you would do this using a T6 Torx screwdriver).
|
||||
::: info
|
||||
If using a Dronecode probe you may need to remove the case in order to connect to the `FMU-DEBUG` port (e.g. on Pixhawk 4 you would do this using a T6 Torx screwdriver).
|
||||
|
||||
:::
|
||||
|
||||
8. Use the following command to scan for the Pixhawk\`s SWD and connect to it:
|
||||
|
||||
```sh
|
||||
(gdb) mon swdp_scan
|
||||
(gdb) attach 1
|
||||
```
|
||||
```sh
|
||||
(gdb) mon swdp_scan
|
||||
(gdb) attach 1
|
||||
```
|
||||
|
||||
9. 이제 바이너리를 픽스호크에 로드하십시오:
|
||||
|
||||
```sh
|
||||
(gdb) load
|
||||
```
|
||||
```sh
|
||||
(gdb) load
|
||||
```
|
||||
|
||||
After the bootloader has updated you can [Load PX4 Firmware](../config/firmware.md) using _QGroundControl_.
|
||||
|
||||
@@ -147,8 +147,8 @@ Currently only FMUv2 and some custom firmware includes the desired bootloader.
|
||||
|
||||
2. [Update the Firmware](../config/firmware.md#custom) with an image containing the new/desired bootloader.
|
||||
|
||||
::: info
|
||||
The updated bootloader might be supplied in custom firmware (i.e. from the dev team), or it or may be included in the latest main branch.
|
||||
::: info
|
||||
The updated bootloader might be supplied in custom firmware (i.e. from the dev team), or it or may be included in the latest main branch.
|
||||
|
||||
:::
|
||||
|
||||
@@ -157,7 +157,7 @@ Currently only FMUv2 and some custom firmware includes the desired bootloader.
|
||||
4. [Find and enable](../advanced_config/parameters.md) the parameter [SYS_BL_UPDATE](../advanced_config/parameter_reference.md#SYS_BL_UPDATE).
|
||||
|
||||
5. 재부팅하십시오 (보드의 연결을 끊고 다시 연결하십시오.).
|
||||
부트로더 업데이트는 수초내에 완료됩니다.
|
||||
부트로더 업데이트는 수초내에 완료됩니다.
|
||||
|
||||
Generally at this point you may then want to [update the firmware](../config/firmware.md) again using the correct/newly installed bootloader.
|
||||
|
||||
@@ -177,25 +177,25 @@ To update the bootloader:
|
||||
1. SD카드를 삽입합니다 (발생 가능한 문제들의 디버깅을 위한 부트 로그 기록을 가능하게 합니다.)
|
||||
|
||||
2. [Update the Firmware](../config/firmware.md) to PX4 _master_ version (when updating the firmware, check **Advanced settings** and then select **Developer Build (master)** from the dropdown list).
|
||||
_QGroundControl_ will automatically detect that the hardware supports FMUv2 and install the appropriate Firmware.
|
||||
_QGroundControl_ will automatically detect that the hardware supports FMUv2 and install the appropriate Firmware.
|
||||
|
||||

|
||||

|
||||
|
||||
기체가 재부팅될 때까지 기다리십시오.
|
||||
기체가 재부팅될 때까지 기다리십시오.
|
||||
|
||||
3. [Find and enable](../advanced_config/parameters.md) the parameter [SYS_BL_UPDATE](../advanced_config/parameter_reference.md#SYS_BL_UPDATE).
|
||||
|
||||
4. 재부팅하십시오 (보드의 연결을 끊고 다시 연결하십시오.).
|
||||
부트로더 업데이트는 수초내에 완료됩니다.
|
||||
부트로더 업데이트는 수초내에 완료됩니다.
|
||||
|
||||
5. Then [Update the Firmware](../config/firmware.md) again.
|
||||
This time _QGroundControl_ should autodetect the hardware as FMUv3 and update the Firmware appropriately.
|
||||
This time _QGroundControl_ should autodetect the hardware as FMUv3 and update the Firmware appropriately.
|
||||
|
||||

|
||||

|
||||
|
||||
::: info
|
||||
If the hardware has the [Silicon Errata](../flight_controller/silicon_errata.md#fmuv2-pixhawk-silicon-errata) it will still be detected as FMUv2 and you will see that FMUv2 was re-installed (in console).
|
||||
In this case you will not be able to install FMUv3 hardware.
|
||||
::: info
|
||||
If the hardware has the [Silicon Errata](../flight_controller/silicon_errata.md#fmuv2-pixhawk-silicon-errata) it will still be detected as FMUv2 and you will see that FMUv2 was re-installed (in console).
|
||||
In this case you will not be able to install FMUv3 hardware.
|
||||
|
||||
:::
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ The process is demonstrated for a multicopter, but is equally valid for other ve
|
||||
- 기체에 시동을 걸고 스로틀을 천천히 최대로 올립니다.
|
||||
- 스로틀을 천천히 0까지 낮춥니다.
|
||||
- 기체 시동을 끄십시오.
|
||||
> <strong x-id="1">참고</strong> 진동을 면밀히 관찰하고, 신중하게 테스트를 진행하십시오.
|
||||
> <strong x-id="1">참고</strong> 진동을 면밀히 관찰하고, 신중하게 테스트를 진행하십시오.
|
||||
|
||||
::: info
|
||||
Perform the test carefully and closely monitor the vibrations.
|
||||
|
||||
@@ -94,29 +94,29 @@ ESC를 보정하려면 :
|
||||
|
||||
- The minimum value for a motor (default: `1100us`) should make the motor spin slowly but reliably, and also spin up reliably after it was stopped.
|
||||
|
||||
You can confirm that a motor spins at minimum (still without propellers) in [Actuator Testing](../config/actuators.md#actuator-testing), by enabling the sliders, and then moving the test output slider for the motor to the first snap position from the bottom.
|
||||
The correct value should make the motor spin immediately and reliably as you move the slider from disarmed to minimum.
|
||||
You can confirm that a motor spins at minimum (still without propellers) in [Actuator Testing](../config/actuators.md#actuator-testing), by enabling the sliders, and then moving the test output slider for the motor to the first snap position from the bottom.
|
||||
The correct value should make the motor spin immediately and reliably as you move the slider from disarmed to minimum.
|
||||
|
||||
To find the "optimal" minimum value, move the slider to the bottom (disarmed).
|
||||
Then increase the PWM output's `disarmed` setting in small increments (e.g. 1025us, 1050us, etc), until the motor starts to spin reliably (it is better to be a little too high than a little too low).
|
||||
Enter this value into the `minimum` setting for all the motor PWM outputs, and restore the `disarmed` output to `1100us`.
|
||||
To find the "optimal" minimum value, move the slider to the bottom (disarmed).
|
||||
Then increase the PWM output's `disarmed` setting in small increments (e.g. 1025us, 1050us, etc), until the motor starts to spin reliably (it is better to be a little too high than a little too low).
|
||||
Enter this value into the `minimum` setting for all the motor PWM outputs, and restore the `disarmed` output to `1100us`.
|
||||
|
||||
- The maximum value for a motor (default: `1900us`) should be chosen such that increasing the value doesn't make the motor spin any faster.
|
||||
|
||||
You can confirm that the motor spins quickly at the maximum setting in [Actuator Testing](../config/actuators.md#actuator-testing), by moving the associated test output slider to the top position.
|
||||
You can confirm that the motor spins quickly at the maximum setting in [Actuator Testing](../config/actuators.md#actuator-testing), by moving the associated test output slider to the top position.
|
||||
|
||||
To find the "optimal" maximum value, first move the slider to the bottom (disarmed).
|
||||
Then increase the PWM output's `disarmed` setting to near the default maximum (`1900`) - the motors should spin up.
|
||||
Listen to the tone of the motor as you increase the PWM maximum value for the output in increments (e.g. 1925us, 1950us, etc).
|
||||
The optimal value is found at the point when the sound of the motors does not change as you increase the value of the output.
|
||||
Enter this value into the `maximum` setting for all the motor PWM outputs, and restore the `disarmed` output to `1100us`.
|
||||
To find the "optimal" maximum value, first move the slider to the bottom (disarmed).
|
||||
Then increase the PWM output's `disarmed` setting to near the default maximum (`1900`) - the motors should spin up.
|
||||
Listen to the tone of the motor as you increase the PWM maximum value for the output in increments (e.g. 1925us, 1950us, etc).
|
||||
The optimal value is found at the point when the sound of the motors does not change as you increase the value of the output.
|
||||
Enter this value into the `maximum` setting for all the motor PWM outputs, and restore the `disarmed` output to `1100us`.
|
||||
|
||||
- The disarmed value for a motor (default: `1000us`) should make the motor stop and stay stopped.
|
||||
|
||||
You can confirm this in [Actuator Testing](../config/actuators.md#actuator-testing) by moving the test output slider to the snap position at the bottom of the slider and observing that the motor does not spin.
|
||||
You can confirm this in [Actuator Testing](../config/actuators.md#actuator-testing) by moving the test output slider to the snap position at the bottom of the slider and observing that the motor does not spin.
|
||||
|
||||
If the ESC spins with the default value of 1000us then the ESC is not properly calibrated.
|
||||
If using an ESC that can't be calibrated, you should reduce the PWM output value for the output to below where the motor does not spin anymore (such as 950us or 900us).
|
||||
If the ESC spins with the default value of 1000us then the ESC is not properly calibrated.
|
||||
If using an ESC that can't be calibrated, you should reduce the PWM output value for the output to below where the motor does not spin anymore (such as 950us or 900us).
|
||||
|
||||
::: info
|
||||
VTOL and fixed-wing motors do not need any special PWM configuration.
|
||||
|
||||
@@ -87,14 +87,14 @@ To set the above "example" configuration using the _QGroundControl_:
|
||||
|
||||
3. Enter commands "like" the ones below into the _MAVLink Console_ (to write the values to the configuration file):
|
||||
|
||||
```sh
|
||||
echo DEVICE=eth0 > /fs/microsd/net.cfg
|
||||
echo BOOTPROTO=fallback >> /fs/microsd/net.cfg
|
||||
echo IPADDR=10.41.10.2 >> /fs/microsd/net.cfg
|
||||
echo NETMASK=255.255.255.0 >>/fs/microsd/net.cfg
|
||||
echo ROUTER=10.41.10.254 >>/fs/microsd/net.cfg
|
||||
echo DNS=10.41.10.254 >>/fs/microsd/net.cfg
|
||||
```
|
||||
```sh
|
||||
echo DEVICE=eth0 > /fs/microsd/net.cfg
|
||||
echo BOOTPROTO=fallback >> /fs/microsd/net.cfg
|
||||
echo IPADDR=10.41.10.2 >> /fs/microsd/net.cfg
|
||||
echo NETMASK=255.255.255.0 >>/fs/microsd/net.cfg
|
||||
echo ROUTER=10.41.10.254 >>/fs/microsd/net.cfg
|
||||
echo DNS=10.41.10.254 >>/fs/microsd/net.cfg
|
||||
```
|
||||
|
||||
4. Once the network configuration has been set you can disconnect the USB cable.
|
||||
|
||||
@@ -113,36 +113,36 @@ Note that there are many more [examples](https://netplan.io/examples/) and instr
|
||||
To setup the Ubuntu Computer:
|
||||
|
||||
1. In a terminal, create and open a `netplan` configuration file: `/etc/netplan/01-network-manager-all.yaml`
|
||||
Below we do this using the _nano_ text editor.
|
||||
Below we do this using the _nano_ text editor.
|
||||
|
||||
```
|
||||
sudo nano /etc/netplan/01-network-manager-all.yaml
|
||||
```
|
||||
```
|
||||
sudo nano /etc/netplan/01-network-manager-all.yaml
|
||||
```
|
||||
|
||||
2. Copy and paste the following configuration information into the file (note: the indentations are important!):
|
||||
|
||||
```
|
||||
network:
|
||||
version: 2
|
||||
renderer: NetworkManager
|
||||
ethernets:
|
||||
enp2s0:
|
||||
addresses:
|
||||
- 10.41.10.1/24
|
||||
nameservers:
|
||||
addresses: [10.41.10.1]
|
||||
routes:
|
||||
- to: 10.41.10.1
|
||||
via: 10.41.10.1
|
||||
```
|
||||
```
|
||||
network:
|
||||
version: 2
|
||||
renderer: NetworkManager
|
||||
ethernets:
|
||||
enp2s0:
|
||||
addresses:
|
||||
- 10.41.10.1/24
|
||||
nameservers:
|
||||
addresses: [10.41.10.1]
|
||||
routes:
|
||||
- to: 10.41.10.1
|
||||
via: 10.41.10.1
|
||||
```
|
||||
|
||||
Save and exit the editor.
|
||||
Save and exit the editor.
|
||||
|
||||
3. Apply the _netplan_ configuration by entering the following command into the Ubuntu terminal.
|
||||
|
||||
```
|
||||
sudo netplan apply
|
||||
```
|
||||
```
|
||||
sudo netplan apply
|
||||
```
|
||||
|
||||
### Companion Computer Ethernet Network Setup
|
||||
|
||||
@@ -189,9 +189,9 @@ To connect QGroundControl to PX4 over Ethernet:
|
||||
|
||||
3. Start QGroundControl and [define a comm link](https://docs.qgroundcontrol.com/master/en/qgc-user-guide/settings_view/settings_view.html) (**Application Settings > Comm Links**) specifying the _server address_ and port as the IP address and port assigned in PX4, respectively.
|
||||
|
||||
Assuming that the values are set as described in the rest of this topic the setup will look like this:
|
||||
Assuming that the values are set as described in the rest of this topic the setup will look like this:
|
||||
|
||||

|
||||

|
||||
|
||||
4. QGroundControl should then connect if you select this link.
|
||||
|
||||
@@ -205,14 +205,14 @@ To setup MAVSDK-Python running on a companion computer:
|
||||
|
||||
1. [Set up the Ethernet Network](#setting-up-the-ethernet-network) so your companion computer and PX4 run on the same network.
|
||||
2. Modify the [PX4 Ethernet Port Configuration](#px4-ethernet-network-setup) to connect to a companion computer.
|
||||
You might change the parameters [MAV_2_REMOTE_PRT](../advanced_config/parameter_reference.md#MAV_2_REMOTE_PRT) and [MAV_2_UDP_PRT](../advanced_config/parameter_reference.md#MAV_2_UDP_PRT) to `14540`, and [MAV_2_MODE](../advanced_config/parameter_reference.md#MAV_2_MODE) to `2` (Onboard).
|
||||
You might change the parameters [MAV_2_REMOTE_PRT](../advanced_config/parameter_reference.md#MAV_2_REMOTE_PRT) and [MAV_2_UDP_PRT](../advanced_config/parameter_reference.md#MAV_2_UDP_PRT) to `14540`, and [MAV_2_MODE](../advanced_config/parameter_reference.md#MAV_2_MODE) to `2` (Onboard).
|
||||
3. Follow the instructions in [MAVSDK-python](https://github.com/mavlink/MAVSDK-Python) to install and use MAVSDK.
|
||||
|
||||
For example, your code will connect to the PX4 using:
|
||||
For example, your code will connect to the PX4 using:
|
||||
|
||||
```python
|
||||
await drone.connect(system_address="udp://10.41.10.2:14540")
|
||||
```
|
||||
```python
|
||||
await drone.connect(system_address="udp://10.41.10.2:14540")
|
||||
```
|
||||
|
||||
:::info
|
||||
MAVSDK can connect to the PX4 on port `14550` if you don't modify the PX4 Ethernet port configuration.
|
||||
@@ -235,38 +235,38 @@ To set up ROS 2:
|
||||
1. Connect your flight controller and companion computer via Ethernet.
|
||||
|
||||
2. [Start the uXRCE-DDS client on PX4](../middleware/uxrce_dds.md#starting-the-client), either manually or by customizing the system startup script.
|
||||
Note that you must use the IP address of the companion computer and the UDP port on which the agent is listening (the example configuration above sets the companion IP address to `10.41.10.1`, and the agent UDP port is set to `8888` in the next step).
|
||||
Note that you must use the IP address of the companion computer and the UDP port on which the agent is listening (the example configuration above sets the companion IP address to `10.41.10.1`, and the agent UDP port is set to `8888` in the next step).
|
||||
|
||||
3. [Start the micro XRCE-DDS agent on the companion computer](../middleware/uxrce_dds.md#starting-the-agent).
|
||||
For example, enter the following command in a terminal to start the agent listening on UDP port `8888`.
|
||||
For example, enter the following command in a terminal to start the agent listening on UDP port `8888`.
|
||||
|
||||
```sh
|
||||
MicroXRCEAgent udp4 -p 8888
|
||||
```
|
||||
```sh
|
||||
MicroXRCEAgent udp4 -p 8888
|
||||
```
|
||||
|
||||
4. Run a [listener node](../ros2/user_guide.md#running-the-example) in a new terminal to confirm the connection is established:
|
||||
|
||||
```sh
|
||||
source ~/ws_sensor_combined/install/setup.bash
|
||||
ros2 launch px4_ros_com sensor_combined_listener.launch.py
|
||||
```
|
||||
```sh
|
||||
source ~/ws_sensor_combined/install/setup.bash
|
||||
ros2 launch px4_ros_com sensor_combined_listener.launch.py
|
||||
```
|
||||
|
||||
If everything is setup correctly, the following output should be displayed in the terminal:
|
||||
If everything is setup correctly, the following output should be displayed in the terminal:
|
||||
|
||||
```sh
|
||||
RECEIVED SENSOR COMBINED DATA
|
||||
=============================
|
||||
ts: 855801598
|
||||
gyro_rad[0]: -0.00339938
|
||||
gyro_rad[1]: 0.00440091
|
||||
gyro_rad[2]: 0.00513893
|
||||
gyro_integral_dt: 4997
|
||||
accelerometer_timestamp_relative: 0
|
||||
accelerometer_m_s2[0]: -0.0324082
|
||||
accelerometer_m_s2[1]: 0.0392213
|
||||
accelerometer_m_s2[2]: -9.77914
|
||||
accelerometer_integral_dt: 4997
|
||||
```
|
||||
```sh
|
||||
RECEIVED SENSOR COMBINED DATA
|
||||
=============================
|
||||
ts: 855801598
|
||||
gyro_rad[0]: -0.00339938
|
||||
gyro_rad[1]: 0.00440091
|
||||
gyro_rad[2]: 0.00513893
|
||||
gyro_integral_dt: 4997
|
||||
accelerometer_timestamp_relative: 0
|
||||
accelerometer_m_s2[0]: -0.0324082
|
||||
accelerometer_m_s2[1]: 0.0392213
|
||||
accelerometer_m_s2[2]: -9.77914
|
||||
accelerometer_integral_dt: 4997
|
||||
```
|
||||
|
||||
## See Also
|
||||
|
||||
|
||||
@@ -153,15 +153,15 @@ It corresponds to: [COM_PREARM_MODE=1](#COM_PREARM_MODE) (safety switch) and [CB
|
||||
시작 절차는 다음과 같습니다:
|
||||
|
||||
1. 전원 인가
|
||||
- 모든 액츄에이터를 시동 해제 상태로 잠금
|
||||
- 시동 걸기 불가능
|
||||
- 모든 액츄에이터를 시동 해제 상태로 잠금
|
||||
- 시동 걸기 불가능
|
||||
2. 안전 스위치 누름
|
||||
- 시스템이 시동전 상태로 전환: 추진 모터를 제외한 모든 액츄에이터 동작 가능(예: 보조익)
|
||||
- 시스템 안전 장치 꺼짐: 시동 가능
|
||||
- 시스템이 시동전 상태로 전환: 추진 모터를 제외한 모든 액츄에이터 동작 가능(예: 보조익)
|
||||
- 시스템 안전 장치 꺼짐: 시동 가능
|
||||
3. 시동 명령 인가
|
||||
|
||||
- 시스템에 시동이 걸림
|
||||
- 모든 모터와 액츄에이터를 움직일 수 있음
|
||||
- 시스템에 시동이 걸림
|
||||
- 모든 모터와 액츄에이터를 움직일 수 있음
|
||||
|
||||
### COM_PREARM_MODE = Disabled and Safety Switch
|
||||
|
||||
@@ -171,15 +171,15 @@ This corresponds to [COM_PREARM_MODE=0](#COM_PREARM_MODE) (Disabled) and [CBRK_I
|
||||
시작 절차는 다음과 같습니다:
|
||||
|
||||
1. 전원 인가
|
||||
- 모든 액츄에이터를 시동 해제 상태로 잠금
|
||||
- 시동 걸기 불가능
|
||||
- 모든 액츄에이터를 시동 해제 상태로 잠금
|
||||
- 시동 걸기 불가능
|
||||
2. 안전 스위치 누름
|
||||
- _All actuators stay locked into disarmed position (same as disarmed)._
|
||||
- 시스템 안전 장치 꺼짐: 시동 가능
|
||||
- _All actuators stay locked into disarmed position (same as disarmed)._
|
||||
- 시스템 안전 장치 꺼짐: 시동 가능
|
||||
3. 시동 명령 인가
|
||||
|
||||
- 시스템에 시동이 걸림
|
||||
- 모든 모터와 액츄에이터를 움직일 수 있음
|
||||
- 시스템에 시동이 걸림
|
||||
- 모든 모터와 액츄에이터를 움직일 수 있음
|
||||
|
||||
### COM_PREARM_MODE = Always and Safety Switch
|
||||
|
||||
@@ -190,13 +190,13 @@ This corresponds to [COM_PREARM_MODE=2](#COM_PREARM_MODE) (Always) and [CBRK_IO_
|
||||
시작 절차는 다음과 같습니다:
|
||||
|
||||
1. 전원 인가
|
||||
- 시스템이 시동전 상태로 전환: 추진 모터를 제외한 모든 액츄에이터 동작 가능(예: 보조익)
|
||||
- 시동 걸기 불가능
|
||||
- 시스템이 시동전 상태로 전환: 추진 모터를 제외한 모든 액츄에이터 동작 가능(예: 보조익)
|
||||
- 시동 걸기 불가능
|
||||
2. 안전 스위치 누름
|
||||
- 시스템 안전 장치 꺼짐: 시동 가능
|
||||
- 시스템 안전 장치 꺼짐: 시동 가능
|
||||
3. 시동 명령 인가
|
||||
- 시스템에 시동이 걸림
|
||||
- 모든 모터와 액츄에이터를 움직일 수 있음
|
||||
- 시스템에 시동이 걸림
|
||||
- 모든 모터와 액츄에이터를 움직일 수 있음
|
||||
|
||||
### COM_PREARM_MODE = Safety or Disabled and No Safety Switch
|
||||
|
||||
@@ -206,11 +206,11 @@ This corresponds to [COM_PREARM_MODE=0 or 1](#COM_PREARM_MODE) (Disabled/Safety
|
||||
시작 절차는 다음과 같습니다:
|
||||
|
||||
1. 전원 인가
|
||||
- 모든 액츄에이터를 시동 해제 상태로 잠금
|
||||
- 시스템 안전 장치 꺼짐: 시동 가능
|
||||
- 모든 액츄에이터를 시동 해제 상태로 잠금
|
||||
- 시스템 안전 장치 꺼짐: 시동 가능
|
||||
2. 시동 명령 인가
|
||||
- 시스템에 시동이 걸림
|
||||
- 모든 모터와 액츄에이터를 움직일 수 있음
|
||||
- 시스템에 시동이 걸림
|
||||
- 모든 모터와 액츄에이터를 움직일 수 있음
|
||||
|
||||
### COM_PREARM_MODE = Always and No Safety Switch
|
||||
|
||||
@@ -220,11 +220,11 @@ This corresponds to [COM_PREARM_MODE=2](#COM_PREARM_MODE) (Always) and [CBRK_IO_
|
||||
시작 절차는 다음과 같습니다:
|
||||
|
||||
1. 전원 인가
|
||||
- 시스템이 시동전 상태로 전환: 추진 모터를 제외한 모든 액츄에이터 동작 가능(예: 보조익)
|
||||
- 시스템 안전 장치 꺼짐: 시동 가능
|
||||
- 시스템이 시동전 상태로 전환: 추진 모터를 제외한 모든 액츄에이터 동작 가능(예: 보조익)
|
||||
- 시스템 안전 장치 꺼짐: 시동 가능
|
||||
2. 시동 명령 인가
|
||||
- 시스템에 시동이 걸림
|
||||
- 모든 모터와 액츄에이터를 움직일 수 있음
|
||||
- 시스템에 시동이 걸림
|
||||
- 모든 모터와 액츄에이터를 움직일 수 있음
|
||||
|
||||
### 매개변수
|
||||
|
||||
|
||||
@@ -102,11 +102,11 @@ PX4는 두 가지 보정 절차를 지원합니다.
|
||||
|
||||
9. Open a terminal window in the **Firmware/Tools** directory and run the python calibration script:
|
||||
|
||||
```sh
|
||||
python process_sensor_caldata.py <full path name to .ulog file>
|
||||
```
|
||||
```sh
|
||||
python process_sensor_caldata.py <full path name to .ulog file>
|
||||
```
|
||||
|
||||
This will generate a **.pdf** file showing the measured data and curve fits for each sensor, and a **.params** file containing the calibration parameters.
|
||||
This will generate a **.pdf** file showing the measured data and curve fits for each sensor, and a **.params** file containing the calibration parameters.
|
||||
|
||||
10. Power the board, connect _QGroundControl_ and load the parameter from the generated **.params** file onto the board using _QGroundControl_. 매개변수의 갯수가 많이지므로, 로드 시간이 길어질 수 있습니다.
|
||||
|
||||
|
||||
@@ -158,29 +158,29 @@ Three axis body fixed magnetometer data at a minimum rate of 5Hz is required to
|
||||
Magnetometer data fusion can be configured using [EKF2_MAG_TYPE](../advanced_config/parameter_reference.md#EKF2_MAG_TYPE):
|
||||
|
||||
0. Automatic:
|
||||
- The magnetometer readings only affect the heading estimate before arming, and the whole attitude after arming.
|
||||
- Heading and tilt errors are compensated when using this method.
|
||||
- Incorrect magnetic field measurements can degrade the tilt estimate.
|
||||
- The magnetometer biases are estimated whenever observable.
|
||||
- The magnetometer readings only affect the heading estimate before arming, and the whole attitude after arming.
|
||||
- Heading and tilt errors are compensated when using this method.
|
||||
- Incorrect magnetic field measurements can degrade the tilt estimate.
|
||||
- The magnetometer biases are estimated whenever observable.
|
||||
1. Magnetic heading:
|
||||
- Only the heading is corrected.
|
||||
The tilt estimate is never affected by incorrect magnetic field measurements.
|
||||
- Tilt errors that could arise when flying without velocity/position aiding are not corrected when using this method.
|
||||
- The magnetometer biases are estimated whenever observable.
|
||||
- Only the heading is corrected.
|
||||
The tilt estimate is never affected by incorrect magnetic field measurements.
|
||||
- Tilt errors that could arise when flying without velocity/position aiding are not corrected when using this method.
|
||||
- The magnetometer biases are estimated whenever observable.
|
||||
2. Deprecated
|
||||
3. Deprecated
|
||||
4. Deprecated
|
||||
5. None:
|
||||
- Magnetometer data is never used.
|
||||
This is useful when the data can never be trusted (e.g.: high current close to the sensor, external anomalies).
|
||||
- The estimator will use other sources of heading: [GPS heading](#yaw-measurements) or external vision.
|
||||
- When using GPS measurements without another source of heading, the heading can only be initialized after sufficient horizontal acceleration.
|
||||
See [Estimate yaw from vehicle movement](#yaw-from-gps-velocity) below.
|
||||
- Magnetometer data is never used.
|
||||
This is useful when the data can never be trusted (e.g.: high current close to the sensor, external anomalies).
|
||||
- The estimator will use other sources of heading: [GPS heading](#yaw-measurements) or external vision.
|
||||
- When using GPS measurements without another source of heading, the heading can only be initialized after sufficient horizontal acceleration.
|
||||
See [Estimate yaw from vehicle movement](#yaw-from-gps-velocity) below.
|
||||
6. Init only:
|
||||
- Magnetometer data is only used to initialize the heading estimate.
|
||||
This is useful when the data can be used before arming but not afterwards (e.g.: high current after the vehicle is armed).
|
||||
- After initialization, the heading is constrained using other observations.
|
||||
- Unlike mag type `None`, when combined with GPS measurements, this method allows position controlled modes to run directly during takeoff.
|
||||
- Magnetometer data is only used to initialize the heading estimate.
|
||||
This is useful when the data can be used before arming but not afterwards (e.g.: high current after the vehicle is armed).
|
||||
- After initialization, the heading is constrained using other observations.
|
||||
- Unlike mag type `None`, when combined with GPS measurements, this method allows position controlled modes to run directly during takeoff.
|
||||
|
||||
The following selection tree can be used to select the right option:
|
||||
|
||||
@@ -242,8 +242,8 @@ A good tuning is obtained as follows:
|
||||
|
||||
2. Extract the `.ulg` log file using, for example, [QGroundControl: Analyze > Log Download](https://docs.qgroundcontrol.com/master/en/qgc-user-guide/analyze_view/log_download.html)
|
||||
|
||||
::: info
|
||||
The same log file can be used to tune the [multirotor wind estimator](#mc_wind_estimation_using_drag).
|
||||
::: info
|
||||
The same log file can be used to tune the [multirotor wind estimator](#mc_wind_estimation_using_drag).
|
||||
|
||||
:::
|
||||
|
||||
@@ -461,8 +461,8 @@ A good tuning is obtained as follows:
|
||||
|
||||
1. Fly once in [Position mode](../flight_modes_mc/position.md) repeatedly forwards/backwards/left/right/up/down between rest and maximum speed (best results are obtained when this testing is conducted in still conditions).
|
||||
2. Extract the **.ulg** log file using, for example, [QGroundControl: Analyze > Log Download](https://docs.qgroundcontrol.com/master/en/qgc-user-guide/analyze_view/log_download.html)
|
||||
::: info
|
||||
The same **.ulg** log file can also be used to tune the [static pressure position error coefficients](#correction-for-static-pressure-position-error).
|
||||
::: info
|
||||
The same **.ulg** log file can also be used to tune the [static pressure position error coefficients](#correction-for-static-pressure-position-error).
|
||||
|
||||
:::
|
||||
3. Use the log with the [mc_wind_estimator_tuning.py](https://github.com/PX4/PX4-Autopilot/tree/main/src/modules/ekf2/EKF/python/tuning_tools/mc_wind_estimator) Python script to obtain the optimal set of parameters.
|
||||
|
||||
@@ -38,14 +38,14 @@ If it is not visible the vehicle immediately performs a _normal_ landing at the
|
||||
정밀 착륙에는 세 단계가 있습니다.
|
||||
|
||||
1. **Horizontal approach:** The vehicle approaches the target horizontally while keeping its current altitude.
|
||||
Once the position of the target relative to the vehicle is below a threshold ([PLD_HACC_RAD](../advanced_config/parameter_reference.md#PLD_HACC_RAD)), the next phase is entered.
|
||||
If the target is lost during this phase (not visible for longer than [PLD_BTOUT](../advanced_config/parameter_reference.md#PLD_BTOUT)), a search procedure is initiated (during a required precision landing) or the vehicle does a normal landing (during an opportunistic precision landing).
|
||||
Once the position of the target relative to the vehicle is below a threshold ([PLD_HACC_RAD](../advanced_config/parameter_reference.md#PLD_HACC_RAD)), the next phase is entered.
|
||||
If the target is lost during this phase (not visible for longer than [PLD_BTOUT](../advanced_config/parameter_reference.md#PLD_BTOUT)), a search procedure is initiated (during a required precision landing) or the vehicle does a normal landing (during an opportunistic precision landing).
|
||||
|
||||
2. **Descent over target:** The vehicle descends, while remaining centered over the target.
|
||||
If the target is lost during this phase (not visible for longer than `PLD_BTOUT`), a search procedure is initiated (during a required precision landing) or the vehicle does a normal landing (during an opportunistic precision landing).
|
||||
If the target is lost during this phase (not visible for longer than `PLD_BTOUT`), a search procedure is initiated (during a required precision landing) or the vehicle does a normal landing (during an opportunistic precision landing).
|
||||
|
||||
3. **Final approach:** When the vehicle is close to the ground (closer than [PLD_FAPPR_ALT](../advanced_config/parameter_reference.md#PLD_FAPPR_ALT)), it descends while remaining centered over the target.
|
||||
만약 목표물이 이 단계에서 잡히지 않는다면, 기체는 정밀 착륙의 모드와 무관하게 계속 하강합니다.
|
||||
만약 목표물이 이 단계에서 잡히지 않는다면, 기체는 정밀 착륙의 모드와 무관하게 계속 하강합니다.
|
||||
|
||||
Search procedures are initiated in the first and second steps, and will run at most [PLD_MAX_SRCH](../advanced_config/parameter_reference.md#PLD_MAX_SRCH) times.
|
||||
착륙 단계 흐름도
|
||||
|
||||
@@ -54,19 +54,19 @@ To [switch between the two antennas modes](https://docs.rockblock.rock7.com/docs
|
||||
모듈의 기본 보드 속도는 19200입니다. However, the PX4 _iridiumsbd_ driver requires a baud rate of 115200 so it needs to be changed using the [AT commands](https://www.groundcontrol.com/en/wp-content/uploads/2022/02/IRDM_ISU_ATCommandReferenceMAN0009_Rev2.0_ATCOMM_Oct2012.pdf).
|
||||
|
||||
1. Connect to the module with using a 19200/8-N-1 setting and check if the communication is working using the command: `AT`.
|
||||
The response should be: `OK`.
|
||||
The response should be: `OK`.
|
||||
|
||||
2. baudrate 속도를 변경합니다.
|
||||
|
||||
```
|
||||
AT+IPR=9
|
||||
```
|
||||
```
|
||||
AT+IPR=9
|
||||
```
|
||||
|
||||
3. 이제 115200/8-N-1 설정을 사용하여 모델에 다시 연결하고 다음을 사용하여 설정을 저장합니다.
|
||||
|
||||
```
|
||||
AT&W0
|
||||
```
|
||||
```
|
||||
AT&W0
|
||||
```
|
||||
|
||||
이제 이 모듈을 PX4에서 사용할 수 있습니다.
|
||||
|
||||
@@ -102,55 +102,55 @@ Log in to the [account](https://rockblock.rock7.com/Operations) and register the
|
||||
|
||||
1. 메시지 릴레이로 작동하는 서버에는 고정 IP 주소와 열린 TCP 포트 2개가 있어야 합니다.
|
||||
|
||||
- `5672` for the _RabbitMQ_ message broker (can be changed in the _rabbitmq_ settings)
|
||||
- `45679` for the HTTP POST interface (can be changed in the **relay.cfg** file)
|
||||
- `5672` for the _RabbitMQ_ message broker (can be changed in the _rabbitmq_ settings)
|
||||
- `45679` for the HTTP POST interface (can be changed in the **relay.cfg** file)
|
||||
|
||||
2. 필요한 Python 모듈을 설치합니다.
|
||||
|
||||
```sh
|
||||
sudo pip install pika tornado future
|
||||
```
|
||||
```sh
|
||||
sudo pip install pika tornado future
|
||||
```
|
||||
|
||||
3. Install the `rabbitmq` message broker:
|
||||
|
||||
```sh
|
||||
sudo apt install rabbitmq-server
|
||||
```
|
||||
```sh
|
||||
sudo apt install rabbitmq-server
|
||||
```
|
||||
|
||||
4. 브로커 자격 증명을 구성합니다(암호를 PWD로 변경).
|
||||
|
||||
```sh
|
||||
sudo rabbitmqctl add_user iridiumsbd PWD
|
||||
sudo rabbitmqctl set_permissions iridiumsbd ".*" ".*" ".*"
|
||||
```
|
||||
```sh
|
||||
sudo rabbitmqctl add_user iridiumsbd PWD
|
||||
sudo rabbitmqctl set_permissions iridiumsbd ".*" ".*" ".*"
|
||||
```
|
||||
|
||||
5. Clone the [SatComInfrastructure](https://github.com/acfloria/SatComInfrastructure.git) repository:
|
||||
|
||||
```sh
|
||||
git clone https://github.com/acfloria/SatComInfrastructure.git
|
||||
```
|
||||
```sh
|
||||
git clone https://github.com/acfloria/SatComInfrastructure.git
|
||||
```
|
||||
|
||||
6. Go to the location of the _SatComInfrastructure_ repo and configure the broker's queues:
|
||||
|
||||
```sh
|
||||
./setup_rabbit.py localhost iridiumsbd PWD
|
||||
```
|
||||
```sh
|
||||
./setup_rabbit.py localhost iridiumsbd PWD
|
||||
```
|
||||
|
||||
7. 설정을 확인합니다.
|
||||
|
||||
```sh
|
||||
sudo rabbitmqctl list_queues
|
||||
```
|
||||
```sh
|
||||
sudo rabbitmqctl list_queues
|
||||
```
|
||||
|
||||
This should give you a list of 4 queues: `MO`, `MO_LOG`, `MT`, `MT_LOG`
|
||||
This should give you a list of 4 queues: `MO`, `MO_LOG`, `MT`, `MT_LOG`
|
||||
|
||||
8. Edit the `relay.cfg` configuration file to reflect your settings.
|
||||
|
||||
9. 분리 모드에서 릴레이 스크립트를 실행합니다.
|
||||
|
||||
```sh
|
||||
screen -dm bash -c 'cd SatcomInfrastructure/; ./relay.py
|
||||
```
|
||||
```sh
|
||||
screen -dm bash -c 'cd SatcomInfrastructure/; ./relay.py
|
||||
```
|
||||
|
||||
기타 지침은 다음과 같습니다.
|
||||
|
||||
@@ -178,15 +178,15 @@ Log in to the [account](https://rockblock.rock7.com/Operations) and register the
|
||||
|
||||
1. 필요한 Python 모듈을 설치합니다.
|
||||
|
||||
```sh
|
||||
sudo pip install pika tornado future
|
||||
```
|
||||
```sh
|
||||
sudo pip install pika tornado future
|
||||
```
|
||||
|
||||
2. SatComInfrarastructure 저장소 복제:
|
||||
|
||||
```sh
|
||||
git clone https://github.com/acfloria/SatComInfrastructure.git
|
||||
```
|
||||
```sh
|
||||
git clone https://github.com/acfloria/SatComInfrastructure.git
|
||||
```
|
||||
|
||||
3. Edit the **udp2rabbit.cfg** configuration file to reflect your settings.
|
||||
|
||||
@@ -194,20 +194,20 @@ Log in to the [account](https://rockblock.rock7.com/Operations) and register the
|
||||
|
||||
5. 다음 매개 변수를 사용하여 QGC에서 UDP 연결을 추가합니다.
|
||||
|
||||
- 접속 포트: 10000
|
||||
- 대상 호스트: 127.0.0.1:10001
|
||||
- 높은 지연 시간: 확인됨
|
||||
- 접속 포트: 10000
|
||||
- 대상 호스트: 127.0.0.1:10001
|
||||
- 높은 지연 시간: 확인됨
|
||||
|
||||

|
||||

|
||||
|
||||
### 검증
|
||||
|
||||
1. Open a terminal on the ground station computer and change to the location of the _SatComInfrastructure_ repository.
|
||||
Then start the **udp2rabbit.py** script:
|
||||
Then start the **udp2rabbit.py** script:
|
||||
|
||||
```sh
|
||||
./udp2rabbit.py
|
||||
```
|
||||
```sh
|
||||
./udp2rabbit.py
|
||||
```
|
||||
|
||||
2. Send a test message from [RockBlock Account](https://rockblock.rock7.com/Operations) to the created delivery group in the `Test Delivery Groups` tab.
|
||||
|
||||
@@ -218,36 +218,36 @@ If in the terminal where the `udp2rabbit.py` script is running within a couple o
|
||||
## 시스템 실행
|
||||
|
||||
1. Start _QGroundControl_.
|
||||
먼저 높은 지연 시간 링크를 수동으로 연결한 다음, 일반 텔레메트리 링크를 연결합니다.
|
||||
먼저 높은 지연 시간 링크를 수동으로 연결한 다음, 일반 텔레메트리 링크를 연결합니다.
|
||||
|
||||

|
||||

|
||||
|
||||
2. Open a terminal on the ground station computer and change to the location of the _SatComInfrastructure_ repository.
|
||||
Then start the **udp2rabbit.py** script:
|
||||
Then start the **udp2rabbit.py** script:
|
||||
|
||||
```sh
|
||||
./udp2rabbit.py
|
||||
```
|
||||
```sh
|
||||
./udp2rabbit.py
|
||||
```
|
||||
|
||||
3. 기체의 전원을 켭니다.
|
||||
|
||||
4. Wait until the first `HIGH_LATENCY2` message is received on QGC.
|
||||
This can be checked either using the _MAVLink Inspector_ widget or on the toolbar with the _LinkIndicator_.
|
||||
If more than one link is connected to the active vehicle the _LinkIndicator_ shows all of them by clicking on the name of the shown link:
|
||||
This can be checked either using the _MAVLink Inspector_ widget or on the toolbar with the _LinkIndicator_.
|
||||
If more than one link is connected to the active vehicle the _LinkIndicator_ shows all of them by clicking on the name of the shown link:
|
||||
|
||||

|
||||

|
||||
|
||||
링크 표시기는 항상 우선 순위 링크의 이름을 표시합니다.
|
||||
링크 표시기는 항상 우선 순위 링크의 이름을 표시합니다.
|
||||
|
||||
5. 이제 위성 통신 시스템을 사용할 준비가 되었습니다.우선 순위 링크(명령 전송 링크)는 다음 방법으로 결정됩니다.
|
||||
|
||||
- 사용자가 링크를 명령하지 않으면, 지연 시간이 큰 링크보다 일반적인 텔레메트리 링크가 선호됩니다.
|
||||
- 기체가 시동을 켜고 텔레메트리 링크가 끊어지면(특정 시간 동안 MAVLink 메시지가 수신되지 않을 경우), 오토파일럿과 QGC는 일반 텔레메트리에서 긴 대기 시간 링크로 되돌아갑니다.
|
||||
텔레메트리 링크가 복구되는 즉시 QGC와 자동 조종기가 다시 이 링크로 전환됩니다.
|
||||
- The user can select a priority link over the `LinkIndicator` on the toolbar.
|
||||
이 링크가 활성화되어 있거나 사용자가 다른 우선 순위 링크를 선택하면 이 링크는 우선 순위 링크로 유지됩니다.
|
||||
- 사용자가 링크를 명령하지 않으면, 지연 시간이 큰 링크보다 일반적인 텔레메트리 링크가 선호됩니다.
|
||||
- 기체가 시동을 켜고 텔레메트리 링크가 끊어지면(특정 시간 동안 MAVLink 메시지가 수신되지 않을 경우), 오토파일럿과 QGC는 일반 텔레메트리에서 긴 대기 시간 링크로 되돌아갑니다.
|
||||
텔레메트리 링크가 복구되는 즉시 QGC와 자동 조종기가 다시 이 링크로 전환됩니다.
|
||||
- The user can select a priority link over the `LinkIndicator` on the toolbar.
|
||||
이 링크가 활성화되어 있거나 사용자가 다른 우선 순위 링크를 선택하면 이 링크는 우선 순위 링크로 유지됩니다.
|
||||
|
||||

|
||||

|
||||
|
||||
## 문제 해결
|
||||
|
||||
|
||||
@@ -514,7 +514,7 @@ div.frame_variant td, div.frame_variant th {
|
||||
</table>
|
||||
</div>
|
||||
|
||||
## 고정익
|
||||
## Plane
|
||||
|
||||
### 플라잉 윙
|
||||
|
||||
@@ -801,3 +801,4 @@ div.frame_variant td, div.frame_variant th {
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
frame: 고정익
|
||||
frame: Plane
|
||||
title: Assembling a Fixed-Wing
|
||||
newEditLink: en/assembly/_assembly.md
|
||||
---
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user