Compare commits

..

36 Commits

Author SHA1 Message Date
copilot-swe-agent[bot] fe7bf8472b Add static_assert to verify LOG_FILEPATH_SCANF_WIDTH is synchronized
- Add compile-time check that LOG_FILEPATH_SIZE == 256
- Ensures LOG_FILEPATH_SCANF_WIDTH stays synchronized if buffer size changes
- Provides clear error message if someone modifies LOG_FILEPATH_SIZE

Co-authored-by: dakejahl <37091262+dakejahl@users.noreply.github.com>
2025-12-15 21:50:04 +00:00
copilot-swe-agent[bot] ca336fb299 Use LOG_FILEPATH_SCANF_WIDTH macro for format specifier
- Define LOG_FILEPATH_SCANF_WIDTH macro for the sscanf width specifier
- Replace hardcoded '255' with the named macro in both sscanf calls
- Improves maintainability and makes the relationship between buffer size and width explicit
- Addresses final code review feedback about magic numbers

Co-authored-by: dakejahl <37091262+dakejahl@users.noreply.github.com>
2025-12-15 21:49:01 +00:00
copilot-swe-agent[bot] 5cdc783b05 Remove duplicate constant and use header LOG_FILEPATH_SIZE
- Remove duplicate LOG_FILEPATH_SIZE macro from cpp file
- Use MavlinkLogHandler::LOG_FILEPATH_SIZE consistently throughout
- Update local filepath buffer to use the same size as LogEntry.filepath
- Addresses code review feedback about duplication and consistency

Co-authored-by: dakejahl <37091262+dakejahl@users.noreply.github.com>
2025-12-15 21:47:25 +00:00
copilot-swe-agent[bot] 5037a96376 Define LOG_FILEPATH_SIZE constant for maintainability
- Add LOG_FILEPATH_SIZE constant (256) in both header and cpp
- Update LogEntry.filepath to use the constant
- Improve comments explaining width specifier relationship
- Addresses code review feedback about magic numbers

Co-authored-by: dakejahl <37091262+dakejahl@users.noreply.github.com>
2025-12-15 21:45:09 +00:00
copilot-swe-agent[bot] 8e0cabaeb7 Add static_assert and use consistent %255s width specifier
- Add static_assert to ensure PX4_MAX_FILEPATH >= 256 at compile time
- Use %255s consistently for both sscanf calls to prevent overflow
- Add explanatory comments for the width specifier choice
- Addresses code review feedback about potential overflow on NuttX

Co-authored-by: dakejahl <37091262+dakejahl@users.noreply.github.com>
2025-12-15 21:43:00 +00:00
copilot-swe-agent[bot] 338595edd1 Fix stack buffer overflow in mavlink_log_handler sscanf calls
- Increase LogEntry.filepath buffer from 60 to 256 bytes
- Add width specifiers to sscanf calls (%255s and %1023s) to prevent buffer overflow
- Prevents remote DoS vulnerability when parsing logdata.txt with excessively long filenames

Co-authored-by: dakejahl <37091262+dakejahl@users.noreply.github.com>
2025-12-15 21:37:29 +00:00
copilot-swe-agent[bot] f219c9f3b9 Initial plan 2025-12-15 21:33:02 +00:00
Brandon W. Banks 1345b3500a Vehicle command for Prearm Safety button (#26079)
* added vehicle command and support to remotely activate/deactivate the safety system (#26078)

* added print_status support for prearm safety status

* updated safety button to map to MAV_CMD_DO_SET_SAFETY_SWITCH_STATE = '5300'

* safety switch cmd: fixed incorrect catch-all and added commanded_state variable for easier reading
2025-12-15 11:25:32 -09:00
Balduin 8604604a5b logged_topics: clean up old commented-out topics (#26120) 2025-12-15 09:53:24 -09:00
bresch d62f112017 ekf2: prevent false mag fault detection
A false positive could be triggered if velocity fusion started,
then stopped after takeoff and only position fusion started again
(because velocity fusion timed out and had a timestamp > time_last_on_ground).
We now also check if the fusion timeout is due to the innovation being
rejected (and not just a temporary check failure or data interruption).
2025-12-15 14:06:04 +01:00
Farhang 14186cf74f [Tests] [CI] fix flaky altitude SITL test (#26106)
* test: increase altitude tolerance to fix flaky test

Altitude tolerance increased from 0.1f to 0.15f to handle simulation
timing variations. Test was failing at 0.201m with 0.2m tolerance.

* test: increase altitude tolerance further to 0.3m

* ci: re-add branch trigger for SITL tests

* Revert "ci: re-add branch trigger for SITL tests"

This reverts commit e5e4c9637b.
2025-12-13 09:13:23 -09:00
Julian Oes 5fe82aa485 [Sponsored by CubePilot] Try to fix potential mavlink segfaults on USB disconnect (#26083)
* mavlink: fix potential use-after-free

If a mavlink instance is force stopped, the main thread might be out of
scope and the receiver thread would be doing a use-after-free.

Instead the receiver thread needs to check its own _should_exit flag.

* mavlink: protect shared data by mutex in dtor

I'm not sure if this potentially fixes any of the segfaults we have seen
on stopping mavlink instances but it potentially could matter if the
mavlink_receiver thread is killed after a timeout and tries to send any
messages as a zombie.
2025-12-12 12:24:02 -09:00
Jacob Dahl b92d21bd31 serial: add txSpaceAvailable function (#26069)
* serial: add txSpaceAvailable function

* serial: txSpaceAvailable and bytesAvailable fixups
2025-12-12 09:31:33 -09:00
Alex Klimaj 12745baf6c Adds configurable I2C address for PCA9685 PWM driver (#26051)
* Adds configurable I2C address for PCA9685 PWM driver

Introduces a parameter to set the I2C address for the PCA9685 PWM output driver, enhancing flexibility for hardware variations. Updates documentation and board initialization scripts to support the new configuration and streamline device startup.

* Update src/drivers/pca9685_pwm_out/module.yaml

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update src/drivers/pca9685_pwm_out/module.yaml

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Jacob Dahl <37091262+dakejahl@users.noreply.github.com>
2025-12-12 09:31:19 -09:00
Jacob Dahl c25fcabcc6 esc_battery: fix current reporting 2025-12-12 11:17:24 -07:00
Jacob Dahl 67d62cb371 Revert "gps: fix RTCM injection to use inject-before-read pattern as before. Add RTCM parser to frame-align injection. Drain GpsInjectData uORB queue into RTCM parser buffer and then inject. Add GPS_UBX_PPK parameter to enable MSM7 output from the GPS module (rather than the default of MSM4) which is required for PPK workflows."
This reverts commit 0704580a30.
2025-12-11 21:32:26 -09:00
Jacob Dahl 0704580a30 gps: fix RTCM injection to use inject-before-read pattern as before. Add RTCM parser to frame-align injection. Drain GpsInjectData uORB queue into RTCM parser buffer and then inject. Add GPS_UBX_PPK parameter to enable MSM7 output from the GPS module (rather than the default of MSM4) which is required for PPK workflows. 2025-12-11 20:10:22 -09:00
Farhang 38eaa8b1d3 Add UAVCAN interfaces numbers board default (#26066) 2025-12-11 08:43:07 -05:00
Hamish Willee 16eac303de docs: Add a magnetometer recalibration section (#26081) 2025-12-11 12:19:57 +11:00
Ryan Johnston aadb83a220 Enhance quick magnetometer calibration feature (#26073)
Added support for specifying an arbitrary initial heading in quick magnetometer calibration.
2025-12-11 11:42:13 +11:00
Hamish Willee 3a2ce0925d Metadata update 20251210 (#26070) 2025-12-10 15:49:47 +11:00
Sindre Meyer Hegre 29ba83109c Update neural_networks.md with Ubuntu version warning (#26029)
* Update neural_networks.md with Ubuntu version warning

Added warning about Ubuntu version requirement for PX4 firmware.

* Update docs/en/advanced/neural_networks.md

* Update docs/en/advanced/neural_networks.md

---------

Co-authored-by: Hamish Willee <hamishwillee@gmail.com>
2025-12-10 10:31:01 +11:00
Antonio Sanjurjo C 7919959f5a Update standard_modes.md. Fix broken Mavlink link (#26059) 2025-12-10 10:22:39 +11:00
Beat Küng 703d66e605 ci: move px4_msgs sync from jenkins to github actions (#26061)
* ci: move px4_msgs sync from jenkins to github actions

I noticed it has not synced in a while, the last time was here:
https://github.com/PX4/px4_msgs/commit/49a0f6c52cf86948e46e5df8a7b61e33319c9ed2

The difference to before is that now also the release branches will be
synced instead of only 'main'.

---------

Co-authored-by: Beniamino Pozzan <beniamino.pozzan@gmail.com>
2025-12-09 18:16:18 +00:00
Alexander Lerach 73a8fc8fb0 boards: v6s, save flash by disabling serial_test 2025-12-09 17:15:39 +01:00
ff-lukas 9b106f71a0 fix: correct baro units in tempcal script 2025-12-09 11:01:06 +01:00
PX4 Build Bot b06094c737 New Crowdin translations - zh-CN (#26057)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2025-12-09 08:41:34 +11:00
PX4 Build Bot 96e5862d88 New Crowdin translations - uk (#26056)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2025-12-09 08:41:26 +11:00
PX4 Build Bot 98d8090458 New Crowdin translations - ko (#26055)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2025-12-09 08:40:51 +11:00
Kyle Fitzpatrick 3ebb47d53f TemperatureCompensationModule: fix order of temp cal args 2025-12-05 08:49:23 -09:00
Matthias Grob b0008e99ff generate_board_target_json: allow to specify individual targets or entire boards in filter 2025-12-05 08:47:11 -09:00
mahima-yoga c962c6a2c1 docs: update airspeed scale docs to include accelerated learning when ASPD_SCALE_n=1 2025-12-05 16:26:11 +01:00
mahima-yoga 18477554e0 wind-estimator: learn airspeed scale faster at beginning of flight
Multiply TAS scale process noise by 100 during the first 5 minutes
when ASPD_SCALE_n = 1.0 (default), enabling faster convergence on first flights.
2025-12-05 16:26:11 +01:00
Mahima Yoga bcd67b7bad ekf: enable constant position fusion during engine warm-up (#26041)
In cold weather, fuel engines need to be warmed up. Currently, this is done by switching to stabilized mode and throttle up. The issue is that when not using GNSS data, the vehicle is not detected as "at rest" due to vibrations and cannot switch into auto/takeoff modes.

If EKF2_ENGINE_WRM is enabled, and if the vehicle is armed and landed, constant position fusion is enabled.
2025-12-05 15:08:37 +01:00
mahima-yoga fcddea4410 v6s: remove rover to free up flash 2025-12-05 14:03:10 +01:00
mahima-yoga ca83b8330d autotune: enable autotune in mission mode
When operating fully autonomously (i.e., without manual control or a guaranteed link to the ground station), tuning a vehicle can be difficult since the current autotune process requires either RC input or a GCS command. For these scenarios, it it useful to be able to start autotune inside a mission.
2025-12-05 14:03:10 +01:00
80 changed files with 604 additions and 261 deletions
+38 -46
View File
@@ -18,58 +18,50 @@ concurrency:
jobs:
build:
runs-on: ${{ matrix.os }}
runs-on: macos-latest
strategy:
matrix:
os: [macos-latest, macos-26]
config: [
"px4_sitl gz_x500"
px4_fmu-v5_default,
px4_sitl
]
steps:
- name: install Python 3.10
uses: actions/setup-python@v5
with:
python-version: "3.10"
- name: install Python 3.10
uses: actions/setup-python@v5
with:
python-version: "3.10"
- uses: actions/checkout@v4
- uses: actions/checkout@v4
- name: Initialize and update git submodules
run: |
git submodule sync --recursive
git submodule update --init --recursive --jobs 4
- name: setup
run: |
./Tools/setup/macos.sh
- name: setup
run: |
./Tools/setup/macos.sh --sim-tools --reinstall
- 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: macos_${{matrix.config}}-ccache-${{steps.ccache_cache_timestamp.outputs.timestamp}}
restore-keys: macos_${{matrix.config}}-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 = 40M" >> ~/.ccache/ccache.conf
echo "hash_dir = false" >> ~/.ccache/ccache.conf
ccache -s
ccache -z
- 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: macos_${{matrix.config}}-ccache-${{steps.ccache_cache_timestamp.outputs.timestamp}}
restore-keys: macos_${{matrix.config}}-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 = 40M" >> ~/.ccache/ccache.conf
echo "hash_dir = false" >> ~/.ccache/ccache.conf
ccache -s
ccache -z
- name: make ${{matrix.config}}
run: |
ccache -z
export CMAKE_PREFIX_PATH="/opt/homebrew/opt/qt@5:$CMAKE_PREFIX_PATH"
make ${{matrix.config}}
ccache -s
- name: make ${{matrix.config}}
run: |
ccache -z
make ${{matrix.config}}
ccache -s
+62
View File
@@ -0,0 +1,62 @@
name: Sync ROS 2 messages to px4_msgs
on:
push:
branches:
- 'main'
- 'stable'
- 'beta'
- 'release/**'
paths:
- 'msg/**'
- 'srv/**'
workflow_dispatch:
permissions:
contents: read
jobs:
sync_to_px4_msgs:
if: github.repository == 'PX4/PX4-Autopilot'
runs-on: [runs-on,runner=4cpu-linux-x64,image=ubuntu22-full-x64,"run-id=${{ github.run_id }}",spot=false]
steps:
- name: Checkout PX4 repo
uses: actions/checkout@v4
- name: Setup git credentials
run: |
git config --global user.name "${{ secrets.PX4BUILDBOT_USER }}"
git config --global user.email "${{ secrets.PX4BUILDBOT_EMAIL }}"
- name: Clone PX4_msgs repo
run: |
git clone https://${{ secrets.PX4BUILTBOT_PERSONAL_ACCESS_TOKEN }}@github.com/PX4/px4_msgs.git
- name: Check out the same branch as the PX4 repo
run: |
cd px4_msgs
if git checkout ${{ github.ref_name }}; then
echo "Checked out existing branch"
else
git checkout -b ${{ github.ref_name }}
fi
- name: Copy ROS 2 messages
run: |
rm -f px4_msgs/msg/*.msg
rm -f px4_msgs/msg/versioned/*.msg
rm -f px4_msgs/srv/*.srv
rm -f px4_msgs/srv/versioned/*.srv
cp msg/*.msg px4_msgs/msg/
cp msg/versioned/*.msg px4_msgs/msg/ || true
cp srv/*.srv px4_msgs/srv/
cp srv/versioned/*.srv px4_msgs/srv/ || true
- name: Commit and push changes
run: |
cd px4_msgs
git status
git add .
git commit -a -m "Update to PX4 ${{ github.sha }}" || true
git push origin ${{ github.ref_name }} || true
cd ..
rm -rf px4_msgs
Vendored
-30
View File
@@ -220,36 +220,6 @@ pipeline {
}
}
stage('PX4 ROS msgs') {
agent {
docker { image 'px4io/px4-dev-base-focal:2021-08-18' }
}
steps {
sh('export')
sh('make distclean; git clean -ff -x -d .')
withCredentials([usernamePassword(credentialsId: 'px4buildbot_github_personal_token', passwordVariable: 'GIT_PASS', usernameVariable: 'GIT_USER')]) {
sh("git clone https://${GIT_USER}:${GIT_PASS}@github.com/PX4/px4_msgs.git")
// 'main' branch
sh('rm -f px4_msgs/msg/*.msg')
sh('rm -f px4_msgs/msg/versioned/*.msg')
sh('rm -f px4_msgs/srv/*.srv')
sh('rm -f px4_msgs/srv/versioned/*.srv')
sh('cp msg/*.msg px4_msgs/msg/')
sh('cp msg/versioned/*.msg px4_msgs/msg/ || true')
sh('cp srv/*.srv px4_msgs/srv/')
sh('cp srv/versioned/*.srv px4_msgs/srv/ || true')
sh('cd px4_msgs; git status; git add .; git commit -a -m "Update message definitions `date`" || true')
sh('cd px4_msgs; git push origin main || true')
sh('rm -rf px4_msgs')
}
}
when {
anyOf {
branch 'main'
}
}
}
stage('S3') {
agent {
docker { image 'px4io/px4-dev-base-focal:2021-08-18' }
+5 -5
View File
@@ -25,15 +25,15 @@ parser.add_argument('-p', '--pretty', dest='pretty', action='store_true',
help='Pretty output instead of a single line')
parser.add_argument('-g', '--groups', dest='group', action='store_true',
help='Groups targets')
parser.add_argument('-f', '--filter', dest='filter', help='comma separated list of board names to use instead of all')
parser.add_argument('-f', '--filter', dest='filter', help='comma separated list of build target name prefixes to include instead of all e.g. "px4_fmu-v5_"')
args = parser.parse_args()
verbose = args.verbose
board_filter = []
target_filter = []
if args.filter:
for board in args.filter.split(','):
board_filter.append(board)
for target in args.filter.split(','):
target_filter.append(target)
default_container = 'ghcr.io/px4/px4-dev:v1.16.0-rc1-258-g0369abd556'
build_configs = []
@@ -144,7 +144,7 @@ for manufacturer in os.scandir(os.path.join(source_dir, '../boards')):
label = files.name[:-9]
target_name = manufacturer.name + '_' + board.name + '_' + label
if board_filter and not board_name in board_filter:
if target_filter and not any(target_name.startswith(f) for f in target_filter):
if verbose: print(f'excluding board {board_name} ({target_name})')
continue
+4 -4
View File
@@ -1675,7 +1675,7 @@ baro_0_x_resample = fit_coef_baro_0_x(temp_rel_resample)
plt.figure(13,figsize=(20,13))
# draw plots
plt.plot(sensor_baro_0['temperature'],100*sensor_baro_0['pressure']-100*median_pressure,'b')
plt.plot(sensor_baro_0['temperature'],sensor_baro_0['pressure']-median_pressure,'b')
plt.plot(temp_resample,baro_0_x_resample,'r')
plt.title('Baro 0 ({}) Bias vs Temperature'.format(baro_0_params['TC_B0_ID']))
plt.ylabel('Z bias (Pa)')
@@ -1736,7 +1736,7 @@ if num_baros >= 2:
plt.figure(14,figsize=(20,13))
# draw plots
plt.plot(sensor_baro_1['temperature'],100*sensor_baro_1['pressure']-100*median_pressure,'b')
plt.plot(sensor_baro_1['temperature'],sensor_baro_1['pressure']-median_pressure,'b')
plt.plot(temp_resample,baro_1_x_resample,'r')
plt.title('Baro 1 ({}) Bias vs Temperature'.format(baro_1_params['TC_B1_ID']))
plt.ylabel('Z bias (Pa)')
@@ -1797,7 +1797,7 @@ if num_baros >= 3:
plt.figure(15,figsize=(20,13))
# draw plots
plt.plot(sensor_baro_2['temperature'],100*sensor_baro_2['pressure']-100*median_pressure,'b')
plt.plot(sensor_baro_2['temperature'],sensor_baro_2['pressure']-median_pressure,'b')
plt.plot(temp_resample,baro_2_x_resample,'r')
plt.title('Baro 2 ({}) Bias vs Temperature'.format(baro_2_params['TC_B2_ID']))
plt.ylabel('Z bias (Pa)')
@@ -1853,7 +1853,7 @@ if num_baros >= 4:
plt.figure(16,figsize=(20,13))
# draw plots
plt.plot(sensor_baro_3['temperature'],100*sensor_baro_3['pressure']-100*median_pressure,'b')
plt.plot(sensor_baro_3['temperature'],sensor_baro_3['pressure']-median_pressure,'b')
plt.plot(temp_resample,baro_3_x_resample,'r')
plt.title('Baro 3 ({}) Bias vs Temperature'.format(baro_3_params['TC_B3_ID']))
plt.ylabel('Z bias (Pa)')
+1
View File
@@ -40,6 +40,7 @@ CONFIG_DRIVERS_MAGNETOMETER_ST_IIS2MDC=y
CONFIG_DRIVERS_POWER_MONITOR_INA226=y
CONFIG_DRIVERS_POWER_MONITOR_INA228=y
CONFIG_DRIVERS_POWER_MONITOR_INA238=y
CONFIG_DRIVERS_PCA9685_PWM_OUT=y
CONFIG_DRIVERS_PWM_OUT=y
CONFIG_DRIVERS_PX4IO=y
CONFIG_COMMON_RC=y
+6
View File
@@ -97,5 +97,11 @@ bmm150 -I start
# Internal Baro on I2C
bmp388 -I start
# Start an external PWM generator
if param greater PCA9685_EN_BUS 0
then
pca9685_pwm_out start
fi
unset HAVE_PM2
unset HAVE_PM3
+1
View File
@@ -21,6 +21,7 @@ CONFIG_DRIVERS_IMU_MURATA_SCH16T=y
CONFIG_COMMON_LIGHT=y
CONFIG_COMMON_MAGNETOMETER=y
CONFIG_DRIVERS_OSD_MSP_OSD=y
CONFIG_DRIVERS_PCA9685_PWM_OUT=y
CONFIG_DRIVERS_PWM_OUT=y
CONFIG_COMMON_RC=y
CONFIG_DRIVERS_UAVCAN=y
+6
View File
@@ -16,3 +16,9 @@ iis2mdc -R 0 -I -b 4 start
# Internal Baro on I2C
bmp388 -I -b 2 start
# Start an external PWM generator
if param greater PCA9685_EN_BUS 0
then
pca9685_pwm_out start
fi
+1
View File
@@ -19,6 +19,7 @@ CONFIG_COMMON_LIGHT=y
CONFIG_DRIVERS_MAGNETOMETER_MEMSIC_MMC5983MA=y
CONFIG_DRIVERS_MAGNETOMETER_ST_IIS2MDC=y
CONFIG_DRIVERS_OPTICAL_FLOW_PAW3902=y
CONFIG_DRIVERS_PCA9685_PWM_OUT=y
CONFIG_DRIVERS_POWER_MONITOR_INA226=y
CONFIG_DRIVERS_PWM_OUT=y
CONFIG_COMMON_RC=y
+6
View File
@@ -34,3 +34,9 @@ paw3902 -s -b 3 start -Y 90
# Internal distance sensor
afbrs50 start
# Start an external PWM generator
if param greater PCA9685_EN_BUS 0
then
pca9685_pwm_out start
fi
-5
View File
@@ -26,7 +26,6 @@ CONFIG_DRIVERS_PCA9685_PWM_OUT=y
CONFIG_DRIVERS_POWER_MONITOR_INA226=y
CONFIG_DRIVERS_POWER_MONITOR_INA228=y
CONFIG_DRIVERS_POWER_MONITOR_INA238=y
CONFIG_DRIVERS_ROBOCLAW=y
CONFIG_DRIVERS_UAVCAN=y
CONFIG_BOARD_UAVCAN_INTERFACES=1
CONFIG_BOARD_UAVCAN_TIMER_OVERRIDE=2
@@ -66,9 +65,6 @@ CONFIG_MODULES_MC_RATE_CONTROL=y
CONFIG_MODULES_NAVIGATOR=y
CONFIG_MODE_NAVIGATOR_VTOL_TAKEOFF=y
CONFIG_MODULES_RC_UPDATE=y
CONFIG_MODULES_ROVER_ACKERMANN=y
CONFIG_MODULES_ROVER_DIFFERENTIAL=y
CONFIG_MODULES_ROVER_MECANUM=y
CONFIG_MODULES_SENSORS=y
CONFIG_MODULES_SIMULATION_SIMULATOR_SIH=y
CONFIG_MODULES_TIME_PERSISTOR=y
@@ -89,7 +85,6 @@ CONFIG_SYSTEMCMDS_PARAM=y
CONFIG_SYSTEMCMDS_PERF=y
CONFIG_SYSTEMCMDS_REBOOT=y
CONFIG_SYSTEMCMDS_SD_BENCH=y
CONFIG_SYSTEMCMDS_SERIAL_TEST=y
CONFIG_SYSTEMCMDS_SYSTEM_TIME=y
CONFIG_SYSTEMCMDS_TOP=y
CONFIG_SYSTEMCMDS_TOPIC_LISTENER=y
@@ -74,5 +74,5 @@ ist8310 -X -b 1 -R 10 start
# Start an external PWM generator
if param greater PCA9685_EN_BUS 0
then
pca9685_pwm_out start -b 1
pca9685_pwm_out start
fi
@@ -11,3 +11,7 @@ param set BAT1_V_DIV 5.7
# Always keep current config
param set SYS_AUTOCONFIG 0
# PCA9685 PWM Out defaults
param set-default PCA9685_EN_BUS 4
param set-default PCA9685_I2C_ADDR 64
@@ -28,7 +28,7 @@ then
echo "ads1115 not found."
fi
if ! pca9685_pwm_out start -a 0x40 -b 4
if ! pca9685_pwm_out start
then
echo "pca9685_pwm_out not found."
fi
+1
View File
@@ -47,6 +47,7 @@ CONFIG_DRIVERS_SAFETY_BUTTON=y
CONFIG_COMMON_TELEMETRY=y
CONFIG_DRIVERS_TONE_ALARM=y
CONFIG_DRIVERS_UAVCAN=y
CONFIG_BOARD_UAVCAN_INTERFACES=3
CONFIG_COMMON_UWB=y
CONFIG_MODULES_AIRSPEED_SELECTOR=y
CONFIG_MODULES_BATTERY_STATUS=y
Binary file not shown.

Before

Width:  |  Height:  |  Size: 387 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 368 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

+4
View File
@@ -26,6 +26,10 @@ If you are looking for more resources to learn about the module, a website has b
## Neural Network PX4 Firmware
::: warning
This module requires Ubuntu 24.04 or newer (it is not supported in Ubuntu 22.04).
:::
The module has been tested on a number of configurations, which can be build locally using the commands:
```sh
+20 -34
View File
@@ -486,6 +486,16 @@ The integer refers to the I2C bus number where PCA9685 is connected.
| ------ | -------- | -------- | --------- | ------- | ---- |
| &nbsp; | 0 | 10 | | 0 |
### PCA9685_I2C_ADDR (`INT32`) {#PCA9685_I2C_ADDR}
I2C address of PCA9685.
The default address is 0x40 (64).
| Reboot | minValue | maxValue | increment | default | unit |
| ------ | -------- | -------- | --------- | ------- | ---- |
| &nbsp; | 0 | 127 | | 64 |
### PCA9685_FAIL1 (`INT32`) {#PCA9685_FAIL1}
PCA9685 Output Channel 1 Failsafe Value.
@@ -14357,22 +14367,6 @@ Defines which RC_MAP_AUXn parameter maps the manual control channel used to enab
| ------ | -------- | -------- | --------- | ------- | ---- |
| &nbsp; | 0 | 6 | | 0 |
### FW_AT_START (`INT32`) {#FW_AT_START}
Start the autotuning sequence.
WARNING: this will inject steps to the rate controller
and can be dangerous. Only activate if you know what you
are doing, and in a safe environment.
Any motion of the remote stick will abort the signal
injection and reset this parameter
Best is to perform the identification in position or
hold mode.
| Reboot | minValue | maxValue | increment | default | unit |
| ------ | -------- | -------- | --------- | ------------ | ---- |
| &nbsp; | | | | Disabled (0) |
### FW_AT_SYSID_F0 (`FLOAT`) {#FW_AT_SYSID_F0}
Start frequency of the injected signal.
@@ -14456,24 +14450,6 @@ Desired angular rate closed-loop rise time.
| ------ | -------- | -------- | --------- | ------- | ---- |
| &nbsp; | 0.01 | 0.5 | | 0.14 | s |
### MC_AT_START (`INT32`) {#MC_AT_START}
Start the autotuning sequence.
WARNING: this will inject steps to the rate controller
and can be dangerous. Only activate if you know what you
are doing, and in a safe environment.
Any motion of the remote stick will abort the signal
injection and reset this parameter
Best is to perform the identification in position or
hold mode.
Increase the amplitude of the injected signal using
MC_AT_SYSID_AMP for more signal/noise ratio
| Reboot | minValue | maxValue | increment | default | unit |
| ------ | -------- | -------- | --------- | ------------ | ---- |
| &nbsp; | | | | Disabled (0) |
### MC_AT_SYSID_AMP (`FLOAT`) {#MC_AT_SYSID_AMP}
Amplitude of the injected signal.
@@ -17097,6 +17073,16 @@ EKF2 enable.
| ------ | -------- | -------- | --------- | ----------- | ---- |
| &nbsp; | | | | Enabled (1) |
### EKF2_ENGINE_WRM (`INT32`) {#EKF2_ENGINE_WRM}
Enable constant position fusion during engine warmup.
When enabled, constant position fusion is enabled when the vehicle is landed and armed. This is intended for IC engine warmup (e.g., fuel engines on catapult) to allow mode transitions to auto/takeoff despite vibrations from running engines.
| Reboot | minValue | maxValue | increment | default | unit |
| ------ | -------- | -------- | --------- | ------------ | ---- |
| &nbsp; | | | | Disabled (0) |
### EKF2_EVA_NOISE (`FLOAT`) {#EKF2_EVA_NOISE}
Measurement noise for vision angle measurements.
+42 -10
View File
@@ -10,7 +10,7 @@ If you have [mounted the compass](../assembly/mount_gps_compass.md#compass-orien
## Overview
You will need to calibrate your compass(es) when you first setup your vehicle, and you may need to recalibrate it if the vehicles is ever exposed to a very strong magnetic field, or if it is used in an area with abnormal magnetic characteristics.
You will need to calibrate your compass(es) when you first setup your vehicle, and you may need to [recalibrate](#recalibration) it if the vehicles is ever exposed to a very strong magnetic field, or if it is used in an area with abnormal magnetic characteristics.
:::tip
Indications of a poor compass calibration include multicopter circling during hover, toilet bowling (circling at increasing radius/spiraling-out, usually constant altitude, leading to fly-way), or veering off-path when attempting to fly straight.
@@ -20,13 +20,16 @@ _QGroundControl_ should also notify the error `mag sensors inconsistent`.
The process calibrates all compasses and autodetects the orientation of any external compasses.
If any external magnetometers are available, it then disables the internal magnetometers (these are primarily needed for automatic rotation detection of external magnetometers).
### Types of Calibration
Several types of compass calibration are available:
1. [Complete](#complete-calibration): This calibration is required after installing the autopilot on an airframe for the first time or when the configuration of the vehicle has changed significantly.
It compensates for hard and soft iron effects by estimating an offset and a scale factor for each axis.
1. [Partial](#partial-quick-calibration): This calibration can be performed as a routine when preparing the vehicle for a flight, after changing the payload, or simply when the compass rose seems inaccurate.
This type of calibration only estimates the offsets to compensate for a hard iron effect.
1. [Large vehicle](#large-vehicle-calibration): This calibration can be performed when the vehicle is too large or heavy to perform a complete calibration. This type of calibration only estimates the offsets to compensate for a hard iron effect.
1. [Large vehicle](#large-vehicle-calibration): This calibration can be performed when the vehicle is too large or heavy to perform a complete calibration.
This type of calibration only estimates the offsets to compensate for a hard iron effect.
## Performing the Calibration
@@ -48,23 +51,27 @@ Before starting the calibration:
The calibration steps are:
1. Start _QGroundControl_ and connect the vehicle.
1. Select **"Q" icon > Vehicle Setup > Sensors** (sidebar) to open _Sensor Setup_.
1. Click the **Compass** sensor button.
2. Select **"Q" icon > Vehicle Setup > Sensors** (sidebar) to open _Sensor Setup_.
3. Click the **Compass** sensor button.
![Select Compass calibration PX4](../../assets/qgc/setup/sensor/sensor_compass_select_px4.png)
::: info
You should already have set the [Autopilot Orientation](../config/flight_controller_orientation.md). If not, you can also set it here.
You should already have set the [Autopilot Orientation](../config/flight_controller_orientation.md).
If not, you can also set it here.
:::
1. Click **OK** to start the calibration.
1. Place the vehicle in any of the orientations shown in red (incomplete) and hold it still. Once prompted (the orientation-image turns yellow) rotate the vehicle around the specified axis in either/both directions. Once the calibration is complete for the current orientation the associated image on the screen will turn green.
4. Click **OK** to start the calibration.
5. Place the vehicle in any of the orientations shown in red (incomplete) and hold it still.
Once prompted (the orientation-image turns yellow) rotate the vehicle around the specified axis in either/both directions.
Once the calibration is complete for the current orientation the associated image on the screen will turn green.
![Compass calibration steps on PX4](../../assets/qgc/setup/sensor/sensor_compass_calibrate_px4.png)
1. Repeat the calibration process for all vehicle orientations.
6. Repeat the calibration process for all vehicle orientations.
Once you've calibrated the vehicle in all the positions _QGroundControl_ will display _Calibration complete_ (all orientation images will be displayed in green and the progress bar will fill completely). You can then proceed to the next sensor.
Once you've calibrated the vehicle in all the positions _QGroundControl_ will display _Calibration complete_ (all orientation images will be displayed in green and the progress bar will fill completely).
You can then proceed to the next sensor.
### Partial "Quick" Calibration
@@ -87,7 +94,8 @@ Notes:
This calibration process leverages external knowledge of vehicle's orientation and location, and a World Magnetic Model (WMM) to calibrate the hard iron biases.
1. Ensure GNSS Fix. This is required to find the expected Earth magnetic field in WMM tables.
1. Ensure GNSS Fix.
This is required to find the expected Earth magnetic field in WMM tables.
2. Align the vehicle to face True North.
Be as accurate as possible for best results.
3. Open the [QGroundControl MAVLink Console](https://docs.qgroundcontrol.com/master/en/qgc-user-guide/analyze_view/mavlink_console.html) and send the following command:
@@ -107,6 +115,30 @@ Notes:
After the calibration is complete, check that the heading indicator and the heading of the arrow on the map are stable and match the orientation of the vehicle when turning it e.g. to the cardinal directions.
## Recalibration
Recalibration is recommended whenever the magnetic environment of the vehicle has changed or when heading behavior appears unreliable.
You can use either complete calibration or mag quick calibration depending on the size of the vehicle and your ability to rotate it through the required orientations.
Complete calibration provides the most accurate soft-iron compensation.
Recalibrate the compass when:
- _The compass module or its mounting orientation has changed._
This includes replacing the GPS or mag unit, rotating the mast, or altering how the module is fixed to the airframe.
- _The vehicle has been exposed to a strong magnetic disturbance._
Examples include transport or storage near large steel structures, welding operations near the airframe, or operation close to high-current equipment.
- _Structural, wiring, or payload changes may have altered the magnetic field around the sensors._
New payloads, rerouted wires, additional batteries, or metal fasteners can introduce soft-iron effects that affect heading accuracy.
- _The vehicle is operated in a region with significantly different magnetic characteristics._
Large changes in latitude, longitude, or magnetic inclination can require re-estimation of offsets.
- _QGroundControl reports magnetometer inconsistencies_.
For example, if you see the error `mag sensors inconsistent`.
- _Heading behavior does not match the vehicles observed orientation._
Symptoms include drifting yaw, sudden heading jumps when attempting to fly straight, and toilet bowling
- _QGroundControl_ sends the error `mag sensors inconsistent`.
This indicates that multiple magnetometers are reporting different headings.
## Additional Calibration/Configuration
The process above will autodetect, [set default rotations](../advanced_config/parameter_reference.md#SENS_MAG_AUTOROT), calibrate, and prioritise, all available magnetometers.
+7 -2
View File
@@ -77,13 +77,18 @@ Follow these steps:
1. **Set an Initial Scale**
Use a conservative starting point: set the CAS scale (`ASPD_SCALE_n`) slightly under 1.0 (for example 0.95).
This biases the system toward over-speed rather than under-speed, reducing stall risk.
Set the CAS scale (`ASPD_SCALE_n`) to 1.0 (the default value).
When the scale is at exactly 1.0, PX4 automatically accelerates the learning process during the first 5 minutes of flight, allowing faster convergence to the correct scale value.
2. **Perform a Flight**
After takeoff, place the vehicle in loiter for about 15 minutes to allow the scale estimation to converge.
::: tip
Flying in circles (loiter/hold mode) is important as the scale-validation algorithm requires the aircraft to pass through multiple heading segments (12 segments covering all compass directions).
If these heading segments arent completed, PX4 cannot validate the estimated scale.
:::
3. **Check Scale Convergence**
After the flight, review the estimated scale in logs.
+4
View File
@@ -162,6 +162,10 @@ Mission Items:
- [MAV_CMD_OBLIQUE_SURVEY](https://mavlink.io/en/messages/common.html#MAV_CMD_OBLIQUE_SURVEY)
- [MAV_CMD_DO_SET_CAMERA_ZOOM](https://mavlink.io/en/messages/common.html#MAV_CMD_DO_SET_CAMERA_ZOOM)
- [MAV_CMD_DO_SET_CAMERA_FOCUS](https://mavlink.io/en/messages/common.html#MAV_CMD_DO_SET_CAMERA_FOCUS)
- [MAV_CMD_DO_AUTOTUNE_ENABLE](https://mavlink.io/en/messages/common.html#MAV_CMD_DO_AUTOTUNE_ENABLE)
- Disabling autotune by setting `param1` to zero is currently not supported. To abort autotune during a mission, switch to another flight mode.
- Axis selection specified in the MAVLink message is ignored (`param2` must be set to 0).
Instead, the axis bitmask defined by [`FW_AT_AXES`](../advanced_config/parameter_reference.md#FW_AT_AXES) is used.
GeoFence Definitions
+3
View File
@@ -166,6 +166,9 @@ Mission Items:
- [MAV_CMD_NAV_VTOL_TAKEOFF](https://mavlink.io/en/messages/common.html#MAV_CMD_NAV_VTOL_TAKEOFF)
- `MAV_CMD_NAV_VTOL_TAKEOFF.param2` (transition heading) is ignored.
Instead the heading to the next waypoint is used for the transition heading. <!-- at LEAST until PX4 v1.13: https://github.com/PX4/PX4-Autopilot/issues/12660 -->
- [MAV_CMD_DO_AUTOTUNE_ENABLE](https://mavlink.io/en/messages/common.html#MAV_CMD_DO_AUTOTUNE_ENABLE)
- Disabling autotune by setting `param1` to zero is currently not supported. To abort autotune during a mission, switch to another flight mode.
- Axis selection specified in the MAVLink message is ignored (`param2` must be set to 0) .
GeoFence Definitions
+1 -1
View File
@@ -2,7 +2,7 @@
<Badge type="tip" text="PX4 v1.15" />
PX4 implements the MAVLink [Standard Modes Protocol](https://mavlink.io/en/services/standard_modes.md) from PX4 v1.15, with a corresponding implementation in QGroundControl Daily builds (and future release builds).
PX4 implements the MAVLink [Standard Modes Protocol](https://mavlink.io/en/services/standard_modes.html) from PX4 v1.15, with a corresponding implementation in QGroundControl Daily builds (and future release builds).
The protocol allows you to discover all flight modes available to the vehicle, including PX4 External modes created using the [PX4 ROS 2 Control Interface](../ros2/px4_ros2_control_interface.md), and get or set the current mode.
+2
View File
@@ -899,6 +899,8 @@ fetching the latest mixing result and write them to PCA9685 at its scheduling ti
It can do full 12bits output as duty-cycle mode, while also able to output precious pulse width
that can be accepted by most ESCs and servos.
The I2C bus and address can be configured via parameters `PCA9685_EN_BUS` and `PCA9685_I2C_ADDR`, or via command line arguments.
### Examples
It is typically started with:
+1
View File
@@ -69,6 +69,7 @@ uint16 VEHICLE_CMD_DO_PARACHUTE=208 # Mission command to trigger a parachute. |a
uint16 VEHICLE_CMD_DO_MOTOR_TEST=209 # Motor test command. |Instance (@range 1, )|throttle type|throttle|timeout [s]|Motor count|Test order|Unused|
uint16 VEHICLE_CMD_DO_INVERTED_FLIGHT=210 # Change to/from inverted flight. |inverted (0=normal, 1=inverted)|Unused|Unused|Unused|Unused|Unused|Unused|
uint16 VEHICLE_CMD_DO_GRIPPER = 211 # Command to operate a gripper.
uint16 VEHICLE_CMD_DO_AUTOTUNE_ENABLE = 212 # Enable autotune module. |1 to enable|Unused|Unused|Unused|Unused|Unused|Unused|
uint16 VEHICLE_CMD_DO_SET_CAM_TRIGG_INTERVAL=214 # Mission command to set TRIG_INTERVAL for this flight. |[m] Camera trigger distance|Shutter integration time (ms)|Unused|Unused|Unused|Unused|Unused|
uint16 VEHICLE_CMD_DO_MOUNT_CONTROL_QUAT=220 # Mission command to control a camera or antenna mount, using a quaternion as reference. |q1 - quaternion param #1, w (1 in null-rotation)|q2 - quaternion param #2, x (0 in null-rotation)|q3 - quaternion param #3, y (0 in null-rotation)|q4 - quaternion param #4, z (0 in null-rotation)|Unused|Unused|Unused|
uint16 VEHICLE_CMD_DO_GUIDED_MASTER=221 # Set id of master controller. |System ID|Component ID|Unused|Unused|Unused|Unused|Unused|
+1
View File
@@ -55,6 +55,7 @@ Please continue reading for [upgrade instructions](#upgrade-guide).
### Sensors
- Add [sbgECom INS driver](../sensor/sbgecom.md) ([PX4-Autopilot#24137](https://github.com/PX4/PX4-Autopilot/pull/24137))
- Quick magnetometer calibration now supports specifying an arbitrary initial heading ([PX4-Autopilot#24637](https://github.com/PX4/PX4-Autopilot/pull/24637))
### Simulation
+8 -2
View File
@@ -78,13 +78,19 @@ Follow these steps:
1. **Set an Initial Scale**
Use a conservative starting point: set the CAS scale (`ASPD_SCALE_n`) slightly under 1.0 (for example 0.95).
This biases the system toward over-speed rather than under-speed, reducing stall risk.
Set the CAS scale (`ASPD_SCALE_n`) to 1.0 (the default value).
When the scale is at exactly 1.0, PX4 automatically accelerates the learning process during the first 5 minutes of flight, allowing faster convergence to the correct scale value.
2. **Perform a Flight**
After takeoff, place the vehicle in loiter for about 15 minutes to allow the scale estimation to converge.
::: tip
Flying in circles (loiter/hold mode) is important as the scale-validation algorithm requires the aircraft to pass through multiple heading segments (12 segments covering all compass directions).
If these heading segments arent completed, PX4 cannot validate the estimated scale.
:::
3. **Check Scale Convergence**
After the flight, review the estimated scale in logs.
+4
View File
@@ -167,6 +167,10 @@ Mission Items:
- [MAV_CMD_OBLIQUE_SURVEY](https://mavlink.io/en/messages/common.html#MAV_CMD_OBLIQUE_SURVEY)
- [MAV_CMD_DO_SET_CAMERA_ZOOM](https://mavlink.io/en/messages/common.html#MAV_CMD_DO_SET_CAMERA_ZOOM)
- [MAV_CMD_DO_SET_CAMERA_FOCUS](https://mavlink.io/en/messages/common.html#MAV_CMD_DO_SET_CAMERA_FOCUS)
- [MAV_CMD_DO_AUTOTUNE_ENABLE](https://mavlink.io/en/messages/common.html#MAV_CMD_DO_AUTOTUNE_ENABLE)
- Disabling autotune by setting `param1` to zero is currently not supported. To abort autotune during a mission, switch to another flight mode.
- Axis selection specified in the MAVLink message is ignored (`param2` must be set to 0).
Instead, the axis bitmask defined by [`FW_AT_AXES`](../advanced_config/parameter_reference.md#FW_AT_AXES) is used.
GeoFence Definitions
+3
View File
@@ -171,6 +171,9 @@ Mission Items:
- [MAV_CMD_NAV_VTOL_TAKEOFF](https://mavlink.io/en/messages/common.html#MAV_CMD_NAV_VTOL_TAKEOFF)
- `MAV_CMD_NAV_VTOL_TAKEOFF.param2` (transition heading) is ignored.
Instead the heading to the next waypoint is used for the transition heading. <!-- at LEAST until PX4 v1.13: https://github.com/PX4/PX4-Autopilot/issues/12660 -->
- [MAV_CMD_DO_AUTOTUNE_ENABLE](https://mavlink.io/en/messages/common.html#MAV_CMD_DO_AUTOTUNE_ENABLE)
- Disabling autotune by setting `param1` to zero is currently not supported. To abort autotune during a mission, switch to another flight mode.
- Axis selection specified in the MAVLink message is ignored (`param2` must be set to 0) .
GeoFence Definitions
+8 -2
View File
@@ -78,13 +78,19 @@ Follow these steps:
1. **Set an Initial Scale**
Use a conservative starting point: set the CAS scale (`ASPD_SCALE_n`) slightly under 1.0 (for example 0.95).
This biases the system toward over-speed rather than under-speed, reducing stall risk.
Set the CAS scale (`ASPD_SCALE_n`) to 1.0 (the default value).
When the scale is at exactly 1.0, PX4 automatically accelerates the learning process during the first 5 minutes of flight, allowing faster convergence to the correct scale value.
2. **Perform a Flight**
After takeoff, place the vehicle in loiter for about 15 minutes to allow the scale estimation to converge.
::: tip
Flying in circles (loiter/hold mode) is important as the scale-validation algorithm requires the aircraft to pass through multiple heading segments (12 segments covering all compass directions).
If these heading segments arent completed, PX4 cannot validate the estimated scale.
:::
3. **Check Scale Convergence**
After the flight, review the estimated scale in logs.
+4
View File
@@ -167,6 +167,10 @@ PX4 "приймає" наступні команди місії MAVLink у ре
- [MAV_CMD_OBLIQUE_SURVEY](https://mavlink.io/en/messages/common.html#MAV_CMD_OBLIQUE_SURVEY)
- [MAV_CMD_DO_SET_CAMERA_ZOOM](https://mavlink.io/en/messages/common.html#MAV_CMD_DO_SET_CAMERA_ZOOM)
- [MAV_CMD_DO_SET_CAMERA_FOCUS](https://mavlink.io/en/messages/common.html#MAV_CMD_DO_SET_CAMERA_FOCUS)
- [MAV_CMD_DO_AUTOTUNE_ENABLE](https://mavlink.io/en/messages/common.html#MAV_CMD_DO_AUTOTUNE_ENABLE)
- Disabling autotune by setting `param1` to zero is currently not supported. To abort autotune during a mission, switch to another flight mode.
- Axis selection specified in the MAVLink message is ignored (`param2` must be set to 0).
Instead, the axis bitmask defined by [`FW_AT_AXES`](../advanced_config/parameter_reference.md#FW_AT_AXES) is used.
Визначення GeoFence
+3
View File
@@ -171,6 +171,9 @@ PX4 "приймає" наступні команди місії MAVLink у ре
- [MAV_CMD_NAV_VTOL_TAKEOFF](https://mavlink.io/en/messages/common.html#MAV_CMD_NAV_VTOL_TAKEOFF)
- `MAV_CMD_NAV_VTOL_TAKEOFF.param2` (заголовок переходу) ігнорується.
Замість цього напрямок до наступної маршрутної точки використовується для переходу. <!-- at LEAST until PX4 v1.13: https://github.com/PX4/PX4-Autopilot/issues/12660 -->
- [MAV_CMD_DO_AUTOTUNE_ENABLE](https://mavlink.io/en/messages/common.html#MAV_CMD_DO_AUTOTUNE_ENABLE)
- Disabling autotune by setting `param1` to zero is currently not supported. To abort autotune during a mission, switch to another flight mode.
- Axis selection specified in the MAVLink message is ignored (`param2` must be set to 0) .
Визначення GeoFence
+8 -2
View File
@@ -78,13 +78,19 @@ Follow these steps:
1. **Set an Initial Scale**
Use a conservative starting point: set the CAS scale (`ASPD_SCALE_n`) slightly under 1.0 (for example 0.95).
This biases the system toward over-speed rather than under-speed, reducing stall risk.
Set the CAS scale (`ASPD_SCALE_n`) to 1.0 (the default value).
When the scale is at exactly 1.0, PX4 automatically accelerates the learning process during the first 5 minutes of flight, allowing faster convergence to the correct scale value.
2. **Perform a Flight**
After takeoff, place the vehicle in loiter for about 15 minutes to allow the scale estimation to converge.
::: tip
Flying in circles (loiter/hold mode) is important as the scale-validation algorithm requires the aircraft to pass through multiple heading segments (12 segments covering all compass directions).
If these heading segments arent completed, PX4 cannot validate the estimated scale.
:::
3. **Check Scale Convergence**
After the flight, review the estimated scale in logs.
+4
View File
@@ -167,6 +167,10 @@ Mission Items:
- [MAV_CMD_OBLIQUE_SURVEY](https://mavlink.io/en/messages/common.html#MAV_CMD_OBLIQUE_SURVEY)
- [MAV_CMD_DO_SET_CAMERA_ZOOM](https://mavlink.io/en/messages/common.html#MAV_CMD_DO_SET_CAMERA_ZOOM)
- [MAV_CMD_DO_SET_CAMERA_FOCUS](https://mavlink.io/en/messages/common.html#MAV_CMD_DO_SET_CAMERA_FOCUS)
- [MAV_CMD_DO_AUTOTUNE_ENABLE](https://mavlink.io/en/messages/common.html#MAV_CMD_DO_AUTOTUNE_ENABLE)
- Disabling autotune by setting `param1` to zero is currently not supported. To abort autotune during a mission, switch to another flight mode.
- Axis selection specified in the MAVLink message is ignored (`param2` must be set to 0).
Instead, the axis bitmask defined by [`FW_AT_AXES`](../advanced_config/parameter_reference.md#FW_AT_AXES) is used.
GeoFence Definitions
+3
View File
@@ -171,6 +171,9 @@ Mission Items:
- [MAV_CMD_NAV_VTOL_TAKEOFF](https://mavlink.io/en/messages/common.html#MAV_CMD_NAV_VTOL_TAKEOFF)
- `MAV_CMD_NAV_VTOL_TAKEOFF.param2` (transition heading) is ignored.
Instead the heading to the next waypoint is used for the transition heading. <!-- at LEAST until PX4 v1.13: https://github.com/PX4/PX4-Autopilot/issues/12660 -->
- [MAV_CMD_DO_AUTOTUNE_ENABLE](https://mavlink.io/en/messages/common.html#MAV_CMD_DO_AUTOTUNE_ENABLE)
- Disabling autotune by setting `param1` to zero is currently not supported. To abort autotune during a mission, switch to another flight mode.
- Axis selection specified in the MAVLink message is ignored (`param2` must be set to 0) .
GeoFence Definitions
+6
View File
@@ -61,6 +61,7 @@ uint16 VEHICLE_CMD_DO_PARACHUTE=208 # Mission command to trigger a parachute. |a
uint16 VEHICLE_CMD_DO_MOTOR_TEST=209 # Motor test command. |Instance (@range 1, )|throttle type|throttle|timeout [s]|Motor count|Test order|Unused|
uint16 VEHICLE_CMD_DO_INVERTED_FLIGHT=210 # Change to/from inverted flight. |inverted (0=normal, 1=inverted)|Unused|Unused|Unused|Unused|Unused|Unused|
uint16 VEHICLE_CMD_DO_GRIPPER = 211 # Command to operate a gripper.
uint16 VEHICLE_CMD_DO_AUTOTUNE_ENABLE = 212 # Enable autotune module. |1 to enable|Unused|Unused|Unused|Unused|Unused|Unused|
uint16 VEHICLE_CMD_DO_SET_CAM_TRIGG_INTERVAL=214 # Mission command to set TRIG_INTERVAL for this flight. |[m] Camera trigger distance|Shutter integration time (ms)|Unused|Unused|Unused|Unused|Unused|
uint16 VEHICLE_CMD_DO_MOUNT_CONTROL_QUAT=220 # Mission command to control a camera or antenna mount, using a quaternion as reference. |q1 - quaternion param #1, w (1 in null-rotation)|q2 - quaternion param #2, x (0 in null-rotation)|q3 - quaternion param #3, y (0 in null-rotation)|q4 - quaternion param #4, z (0 in null-rotation)|Unused|Unused|Unused|
uint16 VEHICLE_CMD_DO_GUIDED_MASTER=221 # Set id of master controller. |System ID|Component ID|Unused|Unused|Unused|Unused|Unused|
@@ -99,6 +100,7 @@ uint16 VEHICLE_CMD_LOGGING_START = 2510 # Start streaming ULog data.
uint16 VEHICLE_CMD_LOGGING_STOP = 2511 # Stop streaming ULog data.
uint16 VEHICLE_CMD_CONTROL_HIGH_LATENCY = 2600 # Control starting/stopping transmitting data over the high latency link.
uint16 VEHICLE_CMD_DO_VTOL_TRANSITION = 3000 # Command VTOL transition.
uint16 VEHICLE_CMD_DO_SET_SAFETY_SWITCH_STATE = 5300 # Command safety on/off. |1 to activate safety, 0 to deactivate safety and allow control surface movements|Unused|Unused|Unused|Unused|Unused|Unused|
uint16 VEHICLE_CMD_ARM_AUTHORIZATION_REQUEST = 3001 # Request arm authorization.
uint16 VEHICLE_CMD_PAYLOAD_PREPARE_DEPLOY = 30001 # Prepare a payload deployment in the flight plan.
uint16 VEHICLE_CMD_PAYLOAD_CONTROL_DEPLOY = 30002 # Control a pre-programmed payload deployment.
@@ -178,6 +180,10 @@ int8 ARMING_ACTION_ARM = 1
uint8 GRIPPER_ACTION_RELEASE = 0
uint8 GRIPPER_ACTION_GRAB = 1
# Used as param1 in DO_SET_SAFETY_SWITCH_STATE command.
uint8 SAFETY_OFF = 0
uint8 SAFETY_ON = 1
uint8 ORB_QUEUE_LENGTH = 8
float32 param1 # Parameter 1, as defined by MAVLink uint16 VEHICLE_CMD enum.
+5
View File
@@ -74,6 +74,11 @@ ssize_t Serial::bytesAvailable()
return _impl.bytesAvailable();
}
ssize_t Serial::txSpaceAvailable()
{
return _impl.txSpaceAvailable();
}
ssize_t Serial::read(uint8_t *buffer, size_t buffer_size)
{
return _impl.read(buffer, buffer_size);
@@ -62,6 +62,7 @@ public:
bool close();
ssize_t bytesAvailable();
ssize_t txSpaceAvailable();
ssize_t read(uint8_t *buffer, size_t buffer_size);
ssize_t readAtLeast(uint8_t *buffer, size_t buffer_size, size_t character_count = 1, uint32_t timeout_ms = 0);
+25 -1
View File
@@ -293,12 +293,36 @@ ssize_t SerialImpl::bytesAvailable()
{
if (!_open) {
PX4_ERR("Device not open!");
errno = EBADF;
return -1;
}
ssize_t bytes_available = 0;
int ret = ioctl(_serial_fd, FIONREAD, &bytes_available);
return ret >= 0 ? bytes_available : 0;
if (ret < 0) {
return -1;
}
return bytes_available;
}
ssize_t SerialImpl::txSpaceAvailable()
{
if (!_open) {
PX4_ERR("Device not open!");
errno = EBADF;
return -1;
}
ssize_t space_available = 0;
int ret = ioctl(_serial_fd, FIONSPACE, &space_available);
if (ret < 0) {
return -1;
}
return space_available;
}
ssize_t SerialImpl::read(uint8_t *buffer, size_t buffer_size)
@@ -60,6 +60,7 @@ public:
bool close();
ssize_t bytesAvailable();
ssize_t txSpaceAvailable();
ssize_t read(uint8_t *buffer, size_t buffer_size);
ssize_t readAtLeast(uint8_t *buffer, size_t buffer_size, size_t character_count = 1, uint32_t timeout_us = 0);
+1
View File
@@ -60,6 +60,7 @@ public:
bool close();
ssize_t bytesAvailable();
ssize_t txSpaceAvailable();
ssize_t read(uint8_t *buffer, size_t buffer_size);
ssize_t readAtLeast(uint8_t *buffer, size_t buffer_size, size_t character_count = 1, uint32_t timeout_us = 0);
+20 -1
View File
@@ -281,12 +281,31 @@ ssize_t SerialImpl::bytesAvailable()
{
if (!_open) {
PX4_ERR("Device not open!");
errno = EBADF;
return -1;
}
ssize_t bytes_available = 0;
int ret = ioctl(_serial_fd, FIONREAD, &bytes_available);
return ret >= 0 ? bytes_available : 0;
if (ret < 0) {
return -1;
}
return bytes_available;
}
ssize_t SerialImpl::txSpaceAvailable()
{
if (!_open) {
PX4_ERR("Device not open!");
errno = EBADF;
return -1;
}
// POSIX/Linux doesn't have a direct equivalent to NuttX's FIONSPACE
errno = ENOSYS;
return -1;
}
ssize_t SerialImpl::read(uint8_t *buffer, size_t buffer_size)
+1
View File
@@ -59,6 +59,7 @@ public:
bool close();
ssize_t bytesAvailable();
ssize_t txSpaceAvailable();
ssize_t read(uint8_t *buffer, size_t buffer_size);
ssize_t readAtLeast(uint8_t *buffer, size_t buffer_size, size_t character_count = 1, uint32_t timeout_us = 0);
+20 -1
View File
@@ -156,14 +156,33 @@ ssize_t SerialImpl::bytesAvailable()
{
if (!_open) {
PX4_ERR("Device not open!");
errno = EBADF;
return -1;
}
uint32_t rx_bytes = 0;
(void) fc_uart_rx_available(_serial_fd, &rx_bytes);
int ret = fc_uart_rx_available(_serial_fd, &rx_bytes);
if (ret < 0) {
return -1;
}
return (ssize_t) rx_bytes;
}
ssize_t SerialImpl::txSpaceAvailable()
{
if (!_open) {
PX4_ERR("Device not open!");
errno = EBADF;
return -1;
}
// QURT doesn't have a direct equivalent to NuttX's FIONSPACE
errno = ENOSYS;
return -1;
}
ssize_t SerialImpl::read(uint8_t *buffer, size_t buffer_size)
{
if (!_open) {
+25 -2
View File
@@ -47,6 +47,7 @@
#include <drivers/drv_hrt.h>
#include <px4_platform_common/getopt.h>
#include <px4_platform_common/sem.hpp>
#include <lib/parameters/param.h>
#include "PCA9685.h"
@@ -356,8 +357,30 @@ int PCA9685Wrapper::custom_command(int argc, char **argv) {
int PCA9685Wrapper::task_spawn(int argc, char **argv) {
int ch;
int address=PCA9685_DEFAULT_ADDRESS;
int iicbus=PCA9685_DEFAULT_IICBUS;
int address = PCA9685_DEFAULT_ADDRESS;
int iicbus = PCA9685_DEFAULT_IICBUS;
int32_t en_bus = 0;
param_t param_handle = param_find("PCA9685_EN_BUS");
if (param_handle != PARAM_INVALID) {
param_get(param_handle, &en_bus);
if (en_bus > 0) {
iicbus = en_bus;
}
}
int32_t i2c_addr = 0;
param_handle = param_find("PCA9685_I2C_ADDR");
if (param_handle != PARAM_INVALID) {
param_get(param_handle, &i2c_addr);
if (i2c_addr > 0) {
address = i2c_addr;
}
}
int myoptind = 1;
const char *myoptarg = nullptr;
+10
View File
@@ -29,6 +29,16 @@ parameters:
min: 0
max: 10
default: 0
PCA9685_I2C_ADDR:
description:
short: I2C address of PCA9685
long: |
I2C address of PCA9685.
The default address is 0x40 (64).
type: int32
min: 1
max: 127
default: 64
PCA9685_SCHD_HZ:
description:
short: PWM update rate
+6 -1
View File
@@ -68,6 +68,7 @@ WindEstimator::initialise(const matrix::Vector3f &velI, const float hor_vel_vari
}
_wind_estimator_reset = true;
_time_initialised = hrt_absolute_time();
return true;
}
@@ -94,10 +95,14 @@ WindEstimator::update(uint64_t time_now)
const float dt = (float)(time_now - _time_last_update) * 1e-6f;
_time_last_update = time_now;
// if airspeed scale is at default (1.0) and we are in the first 5 minutes of flight time, multiply _tas_scale_psd by 100 for faster learning
const float tas_psd_multiplier = (fabsf(_scale_init - 1.0f) < FLT_EPSILON && (time_now - _time_initialised < kTASScaleFastLearnTime)) ?
kTASScalePSDMultiplier : 1.f;
matrix::Matrix3f Qk;
Qk(INDEX_W_N, INDEX_W_N) = _wind_psd * dt;
Qk(INDEX_W_E, INDEX_W_E) = Qk(INDEX_W_N, INDEX_W_N);
Qk(INDEX_TAS_SCALE, INDEX_TAS_SCALE) = _tas_scale_psd * dt;
Qk(INDEX_TAS_SCALE, INDEX_TAS_SCALE) = _tas_scale_psd * tas_psd_multiplier * dt;
_P += Qk;
}
+4
View File
@@ -139,6 +139,10 @@ private:
uint64_t _time_last_airspeed_fuse = 0; ///< timestamp of last airspeed fusion
uint64_t _time_last_beta_fuse = 0; ///< timestamp of last sideslip fusion
uint64_t _time_last_update = 0; ///< timestamp of last covariance prediction
uint64_t _time_initialised = 0; ///< timestamp when estimator is initialised
static constexpr float kTASScalePSDMultiplier = 100;
static constexpr hrt_abstime kTASScaleFastLearnTime = 300_s;
bool _wind_estimator_reset = false; ///< wind estimator was reset in this cycle
+47
View File
@@ -302,6 +302,26 @@ int Commander::custom_command(int argc, char *argv[])
return 0;
}
if (!strcmp(argv[0], "safety")) {
if (argc < 2) {
PX4_ERR("missing argument");
return 1;
}
if (!strcmp(argv[1], "on")) {
send_vehicle_command(vehicle_command_s::VEHICLE_CMD_DO_SET_SAFETY_SWITCH_STATE, vehicle_command_s::SAFETY_ON);
} else if (!strcmp(argv[1], "off")) {
send_vehicle_command(vehicle_command_s::VEHICLE_CMD_DO_SET_SAFETY_SWITCH_STATE, vehicle_command_s::SAFETY_OFF);
} else {
PX4_ERR("invlaid argument, use [on|off]");
return 1;
}
return 0;
}
if (!strcmp(argv[0], "arm")) {
float param2 = 0.f;
@@ -495,6 +515,7 @@ int Commander::custom_command(int argc, char *argv[])
int Commander::print_status()
{
PX4_INFO("%s", isArmed() ? "Armed" : "Disarmed");
PX4_INFO("prearm safety: %s", _safety.isSafetyOff() ? "Off" : "On");
PX4_INFO("navigation mode: %s", mode_util::nav_state_names[_vehicle_status.nav_state]);
PX4_INFO("user intended navigation mode: %s", mode_util::nav_state_names[_vehicle_status.nav_state_user_intention]);
PX4_INFO("in failsafe: %s", _failsafe.inFailsafe() ? "yes" : "no");
@@ -1508,6 +1529,29 @@ Commander::handle_command(const vehicle_command_s &cmd)
answer_command(cmd, vehicle_command_ack_s::VEHICLE_CMD_RESULT_ACCEPTED);
break;
case vehicle_command_s::VEHICLE_CMD_DO_SET_SAFETY_SWITCH_STATE: {
// reject if armed, only allow pre or post flight for safety
if (isArmed()) {
answer_command(cmd, vehicle_command_ack_s::VEHICLE_CMD_RESULT_TEMPORARILY_REJECTED);
} else {
int commanded_state = (int)cmd.param1;
if (commanded_state == vehicle_command_s::SAFETY_OFF) {
_safety.deactivateSafety();
answer_command(cmd, vehicle_command_ack_s::VEHICLE_CMD_RESULT_ACCEPTED);
} else if (commanded_state == vehicle_command_s::SAFETY_ON) {
_safety.activateSafety();
answer_command(cmd, vehicle_command_ack_s::VEHICLE_CMD_RESULT_ACCEPTED);
} else {
answer_command(cmd, vehicle_command_ack_s::VEHICLE_CMD_RESULT_FAILED);
}
}
}
break;
case vehicle_command_s::VEHICLE_CMD_START_RX_PAIR:
case vehicle_command_s::VEHICLE_CMD_CUSTOM_0:
case vehicle_command_s::VEHICLE_CMD_CUSTOM_1:
@@ -1550,6 +1594,7 @@ Commander::handle_command(const vehicle_command_s &cmd)
case vehicle_command_s::VEHICLE_CMD_EXTERNAL_POSITION_ESTIMATE:
case vehicle_command_s::VEHICLE_CMD_REQUEST_CAMERA_INFORMATION:
case vehicle_command_s::VEHICLE_CMD_EXTERNAL_ATTITUDE_ESTIMATE:
case vehicle_command_s::VEHICLE_CMD_DO_AUTOTUNE_ENABLE:
/* ignore commands that are handled by other parts of the system */
break;
@@ -3025,6 +3070,8 @@ The commander module contains the state machine for mode switching and failsafe
PRINT_MODULE_USAGE_ARG("mag|baro|accel|gyro|level|esc|airspeed", "Calibration type", false);
PRINT_MODULE_USAGE_ARG("quick", "Quick calibration [mag, accel (not recommended)]", false);
PRINT_MODULE_USAGE_COMMAND_DESCR("check", "Run preflight checks");
PRINT_MODULE_USAGE_COMMAND_DESCR("safety", "Change prearm safety state");
PRINT_MODULE_USAGE_ARG("on|off", "[on] to activate safety, [off] to deactivate safety and allow control surface movements", false);
PRINT_MODULE_USAGE_COMMAND("arm");
PRINT_MODULE_USAGE_PARAM_FLAG('f', "Force arming (do not run preflight checks)", true);
PRINT_MODULE_USAGE_COMMAND("disarm");
+7
View File
@@ -76,3 +76,10 @@ void Safety::activateSafety()
_safety_off = false;
}
}
void Safety::deactivateSafety()
{
if (!_safety_disabled) {
_safety_off = true;
}
}
+1
View File
@@ -49,6 +49,7 @@ public:
bool safetyButtonHandler();
void activateSafety();
void deactivateSafety();
bool isButtonAvailable() const { return _button_available; }
bool isSafetyOff() const { return _safety_off; }
bool isSafetyDisabled() const { return _safety_disabled; }
@@ -104,12 +104,17 @@ void Ekf::controlGpsFusion(const imuSample &imu_delayed)
bool do_vel_pos_reset = false;
if (!_control_status.flags.gnss_fault && (_control_status.flags.gnss_vel || _control_status.flags.gnss_pos)) {
if (!_control_status.flags.gnss_fault && _control_status.flags.in_air && isYawFailure()) {
const bool velocity_fusion_failure = _aid_src_gnss_vel.innovation_rejected
&& isTimedOut(_time_last_hor_vel_fuse, _params.EKFGSF_reset_delay)
&& (_time_last_hor_vel_fuse > _time_last_on_ground_us);
if (_control_status.flags.in_air
&& isYawFailure()
&& isTimedOut(_time_last_hor_vel_fuse, _params.EKFGSF_reset_delay)
&& (_time_last_hor_vel_fuse > _time_last_on_ground_us)) {
const bool position_fusion_failure = _aid_src_gnss_pos.innovation_rejected
&& isTimedOut(_time_last_hor_pos_fuse, _params.EKFGSF_reset_delay)
&& (_time_last_hor_pos_fuse > _time_last_on_ground_us);
if ((_control_status.flags.gnss_vel && velocity_fusion_failure)
|| (_control_status.flags.gnss_pos && position_fusion_failure)) {
do_vel_pos_reset = tryYawEmergencyReset();
}
}
+7 -1
View File
@@ -2614,11 +2614,14 @@ void EKF2::UpdateSystemFlagsSample(ekf2_timestamps_s &ekf2_timestamps)
// vehicle_status
vehicle_status_s vehicle_status;
bool armed = false;
if (_status_sub.copy(&vehicle_status)
&& (ekf2_timestamps.timestamp < vehicle_status.timestamp + 3_s)) {
// initially set in_air from arming_state (will be overridden if land detector is available)
flags.in_air = (vehicle_status.arming_state == vehicle_status_s::ARMING_STATE_ARMED);
armed = (vehicle_status.arming_state == vehicle_status_s::ARMING_STATE_ARMED);
flags.in_air = armed;
// let the EKF know if the vehicle motion is that of a fixed wing (forward flight only relative to wind)
flags.is_fixed_wing = (vehicle_status.vehicle_type == vehicle_status_s::VEHICLE_TYPE_FIXED_WING);
@@ -2644,6 +2647,9 @@ void EKF2::UpdateSystemFlagsSample(ekf2_timestamps_s &ekf2_timestamps)
flags.at_rest = vehicle_land_detected.at_rest;
flags.in_air = !vehicle_land_detected.landed;
flags.gnd_effect = vehicle_land_detected.in_ground_effect;
// Enable constant position fusion for engine warmup when landed and armed
flags.constant_pos = _param_ekf2_engine_wrm.get() && !flags.in_air && armed;
}
launch_detection_status_s launch_detection_status;
+1
View File
@@ -489,6 +489,7 @@ private:
(ParamExtFloat<px4::params::EKF2_DELAY_MAX>) _param_ekf2_delay_max,
(ParamExtInt<px4::params::EKF2_IMU_CTRL>) _param_ekf2_imu_ctrl,
(ParamExtFloat<px4::params::EKF2_VEL_LIM>) _param_ekf2_vel_lim,
(ParamBool<px4::params::EKF2_ENGINE_WRM>) _param_ekf2_engine_wrm,
#if defined(CONFIG_EKF2_AUXVEL)
(ParamExtFloat<px4::params::EKF2_AVEL_DELAY>)
+8
View File
@@ -183,3 +183,11 @@ parameters:
max: 299792458
unit: m/s
decimal: 1
EKF2_ENGINE_WRM:
description:
short: Enable constant position fusion during engine warmup
long: When enabled, constant position fusion is enabled when the vehicle is landed and armed.
This is intended for IC engine warmup (e.g., fuel engines on catapult) to allow mode transitions to auto/takeoff despite vibrations from running engines.
type: boolean
default: 0
-1
View File
@@ -105,7 +105,6 @@ EscBattery::Run()
}
average_voltage_v /= online_esc_count;
total_current_a /= online_esc_count;
average_temperature_c /= online_esc_count;
_battery.setConnected(true);
@@ -48,7 +48,6 @@ FwAutotuneAttitudeControl::FwAutotuneAttitudeControl(bool is_vtol) :
_actuator_controls_status_sub(is_vtol ? ORB_ID(actuator_controls_status_1) : ORB_ID(actuator_controls_status_0))
{
_autotune_attitude_control_status_pub.advertise();
reset();
}
FwAutotuneAttitudeControl::~FwAutotuneAttitudeControl()
@@ -73,11 +72,6 @@ bool FwAutotuneAttitudeControl::init()
return true;
}
void FwAutotuneAttitudeControl::reset()
{
_param_fw_at_start.reset();
}
void FwAutotuneAttitudeControl::Run()
{
if (should_exit()) {
@@ -107,10 +101,23 @@ void FwAutotuneAttitudeControl::Run()
}
}
if (_vehicle_command_sub.updated()) {
vehicle_command_s vehicle_command;
if (_vehicle_command_sub.copy(&vehicle_command)) {
if (vehicle_command.command == vehicle_command_s::VEHICLE_CMD_DO_AUTOTUNE_ENABLE) {
if (fabsf(vehicle_command.param1 - 1.0f) < FLT_EPSILON && fabsf(vehicle_command.param2) < FLT_EPSILON) {
_vehicle_cmd_start_autotune = true;
}
}
}
}
_aux_switch_en = isAuxEnableSwitchEnabled();
_want_start_autotune = _vehicle_cmd_start_autotune || _aux_switch_en;
// new control data needed every iteration
if ((_state == state::idle && !_aux_switch_en)
if ((_state == state::idle && !_want_start_autotune)
|| !_vehicle_torque_setpoint_sub.updated()) {
return;
@@ -310,7 +317,8 @@ void FwAutotuneAttitudeControl::updateStateMachine(hrt_abstime now)
switch (_state) {
case state::idle:
if (_param_fw_at_start.get() || _aux_switch_en) {
if (_want_start_autotune) {
mavlink_log_info(&_mavlink_log_pub, "Autotune started");
_state = state::init;
@@ -540,8 +548,7 @@ void FwAutotuneAttitudeControl::updateStateMachine(hrt_abstime now)
orb_advert_t mavlink_log_pub = nullptr;
mavlink_log_info(&mavlink_log_pub, "Autotune returned to idle");
_state = state::idle;
_param_fw_at_start.set(false);
_param_fw_at_start.commit();
_vehicle_cmd_start_autotune = false;
}
break;
@@ -561,7 +568,7 @@ void FwAutotuneAttitudeControl::updateStateMachine(hrt_abstime now)
// Abort
mavlink_log_critical(&mavlink_log_pub, "Autotune aborted before finishing");
_state = state::fail;
_start_flight_mode = _nav_state;
_state_start_time = now;
} else if (timeout) {
@@ -589,10 +596,9 @@ void FwAutotuneAttitudeControl::updateStateMachine(hrt_abstime now)
break;
}
_start_flight_mode = _nav_state;
_state_start_time = now;
}
}
}
@@ -58,6 +58,7 @@
#include <uORB/topics/parameter_update.h>
#include <uORB/topics/autotune_attitude_control_status.h>
#include <uORB/topics/vehicle_angular_velocity.h>
#include <uORB/topics/vehicle_command.h>
#include <uORB/topics/vehicle_status.h>
#include <uORB/topics/vehicle_torque_setpoint.h>
#include <mathlib/mathlib.h>
@@ -101,8 +102,6 @@ private:
void Run() override;
void reset();
void checkFilters();
void updateStateMachine(hrt_abstime now);
@@ -126,6 +125,7 @@ private:
uORB::Subscription _manual_control_setpoint_sub{ORB_ID(manual_control_setpoint)};
uORB::Subscription _vehicle_angular_velocity_sub{ORB_ID(vehicle_angular_velocity)};
uORB::Subscription _vehicle_status_sub{ORB_ID(vehicle_status)};
uORB::Subscription _vehicle_command_sub{ORB_ID(vehicle_command)};
uORB::PublicationData<autotune_attitude_control_status_s> _autotune_attitude_control_status_pub{ORB_ID(autotune_attitude_control_status)};
@@ -178,6 +178,8 @@ private:
uint8_t _nav_state{0};
uint8_t _start_flight_mode{0};
bool _aux_switch_en{false};
bool _vehicle_cmd_start_autotune{false};
bool _want_start_autotune{false};
orb_advert_t _mavlink_log_pub{nullptr};
@@ -215,7 +217,6 @@ private:
DEFINE_PARAMETERS(
(ParamInt<px4::params::FW_AT_AXES>) _param_fw_at_axes,
(ParamBool<px4::params::FW_AT_START>) _param_fw_at_start,
(ParamInt<px4::params::FW_AT_MAN_AUX>) _param_fw_at_man_aux,
(ParamInt<px4::params::FW_AT_APPLY>) _param_fw_at_apply,
@@ -39,22 +39,7 @@
* @author Mathieu Bresciani <mathieu@auterion.com>
*/
/**
* Start the autotuning sequence
*
* WARNING: this will inject steps to the rate controller
* and can be dangerous. Only activate if you know what you
* are doing, and in a safe environment.
*
* Any motion of the remote stick will abort the signal
* injection and reset this parameter
* Best is to perform the identification in position or
* hold mode.
*
* @boolean
* @group Autotune
*/
PARAM_DEFINE_INT32(FW_AT_START, 0);
/**
* Controls when to apply the new gains
-2
View File
@@ -63,7 +63,6 @@ void LoggedTopics::add_default_topics()
add_optional_topic("external_ins_attitude");
add_optional_topic("external_ins_global_position");
add_optional_topic("external_ins_local_position");
// add_optional_topic("esc_status", 250);
add_topic("esc_status");
add_topic("failure_detector_status", 100);
add_topic("failsafe_flags");
@@ -209,7 +208,6 @@ void LoggedTopics::add_default_topics()
add_optional_topic_multi("vehicle_magnetometer", 500, 4);
add_topic("vehicle_optical_flow", 500);
add_topic("aux_global_position", 500);
//add_optional_topic("vehicle_optical_flow_vel", 100);
add_optional_topic("pps_capture");
// additional control allocation logging
+18 -3
View File
@@ -54,6 +54,17 @@ static const char *kLogDir = PX4_STORAGEDIR "/log";
#define PX4_MAX_FILEPATH PATH_MAX
#endif
// Ensure PX4_MAX_FILEPATH is large enough for our buffer sizes
// LogEntry.filepath uses MavlinkLogHandler::LOG_FILEPATH_SIZE
static_assert(PX4_MAX_FILEPATH >= MavlinkLogHandler::LOG_FILEPATH_SIZE,
"PX4_MAX_FILEPATH must be at least LOG_FILEPATH_SIZE bytes for log file paths");
// Width specifier for sscanf - must be LOG_FILEPATH_SIZE - 1
// This is hardcoded as 255 because preprocessor can't evaluate (256-1) in format strings
// The static_assert below ensures this stays synchronized with LOG_FILEPATH_SIZE
#define LOG_FILEPATH_SCANF_WIDTH "255"
static_assert(MavlinkLogHandler::LOG_FILEPATH_SIZE == 256, "Update LOG_FILEPATH_SCANF_WIDTH if LOG_FILEPATH_SIZE changes");
MavlinkLogHandler::MavlinkLogHandler(Mavlink &mavlink)
: _mavlink(mavlink)
{}
@@ -171,10 +182,12 @@ void MavlinkLogHandler::state_listing()
// We can send!
uint32_t size_bytes = 0;
uint32_t time_utc = 0;
char filepath[PX4_MAX_FILEPATH];
char filepath[MavlinkLogHandler::LOG_FILEPATH_SIZE];
// If parsed lined successfully, send the entry
if (sscanf(line, "%" PRIu32 " %" PRIu32 " %s", &time_utc, &size_bytes, filepath) != 3) {
// Note: Using width specifier to prevent buffer overflow
// Width is LOG_FILEPATH_SIZE-1 to leave room for null terminator
if (sscanf(line, "%" PRIu32 " %" PRIu32 " %" LOG_FILEPATH_SCANF_WIDTH "s", &time_utc, &size_bytes, filepath) != 3) {
PX4_DEBUG("sscanf failed");
continue;
}
@@ -506,7 +519,9 @@ bool MavlinkLogHandler::log_entry_from_id(uint16_t log_id, LogEntry *entry)
continue;
}
if (sscanf(line, "%" PRIu32 " %" PRIu32 " %s", &(entry->time_utc), &(entry->size_bytes), entry->filepath) != 3) {
// Parse log entry with width specifier to prevent buffer overflow
// Width is LOG_FILEPATH_SIZE-1 to leave room for null terminator
if (sscanf(line, "%" PRIu32 " %" PRIu32 " %" LOG_FILEPATH_SCANF_WIDTH "s", &(entry->time_utc), &(entry->size_bytes), entry->filepath) != 3) {
PX4_DEBUG("sscanf failed");
continue;
}
+3 -1
View File
@@ -48,12 +48,14 @@ public:
void handle_message(const mavlink_message_t *msg);
private:
static constexpr size_t LOG_FILEPATH_SIZE = 256; // Buffer size for log file paths
struct LogEntry {
uint16_t id{0xffff};
uint32_t time_utc{};
uint32_t size_bytes{};
FILE *fp{nullptr};
char filepath[60];
char filepath[LOG_FILEPATH_SIZE];
uint32_t offset{};
};
+4 -1
View File
@@ -163,7 +163,10 @@ Mavlink::~Mavlink()
}
if (_instance_id >= 0) {
mavlink_module_instances[_instance_id] = nullptr;
{
LockGuard lg{mavlink_module_mutex};
mavlink_module_instances[_instance_id] = nullptr;
}
mavlink_instance_count.fetch_sub(1);
}
+7
View File
@@ -1538,6 +1538,12 @@ MavlinkMissionManager::parse_mavlink_mission_item(const mavlink_mission_item_t *
mission_item->params[0] = (uint16_t)mavlink_mission_item->param1;
break;
case MAV_CMD_DO_AUTOTUNE_ENABLE:
mission_item->nav_cmd = (NAV_CMD)mavlink_mission_item->command;
mission_item->params[0] = (uint16_t)mavlink_mission_item->param1;
mission_item->params[1] = (uint16_t)mavlink_mission_item->param2;
break;
default:
mission_item->nav_cmd = NAV_CMD_INVALID;
PX4_DEBUG("Unsupported command %d", mavlink_mission_item->command);
@@ -1627,6 +1633,7 @@ MavlinkMissionManager::parse_mavlink_mission_item(const mavlink_mission_item_t *
case MAV_CMD_CONDITION_DELAY:
case MAV_CMD_CONDITION_DISTANCE:
case MAV_CMD_DO_SET_ACTUATOR:
case MAV_CMD_DO_AUTOTUNE_ENABLE:
case MAV_CMD_COMPONENT_ARM_DISARM:
mission_item->nav_cmd = (NAV_CMD)mavlink_mission_item->command;
break;
+15 -20
View File
@@ -622,46 +622,37 @@ void MavlinkReceiver::handle_message_command_both(mavlink_message_t *msg, const
autotune_attitude_control_status_s status{};
_autotune_attitude_control_status_sub.copy(&status);
// if not busy enable via the parameter
// do not check the return value of the uORB copy above because the module
// starts publishing only when MC_AT_START is set
// publish vehicle command once if:
// - autotune is not already running
// - we are not in transition
// - autotune module is enabled
if (status.state == autotune_attitude_control_status_s::STATE_IDLE) {
vehicle_status_s vehicle_status{};
_vehicle_status_sub.copy(&vehicle_status);
if (!vehicle_status.in_transition_mode) {
param_t atune_start;
switch (vehicle_status.vehicle_type) {
case vehicle_status_s::VEHICLE_TYPE_FIXED_WING:
atune_start = param_find("FW_AT_START");
has_module = param_find("FW_AT_APPLY");
break;
case vehicle_status_s::VEHICLE_TYPE_ROTARY_WING:
atune_start = param_find("MC_AT_START");
has_module = param_find("MC_AT_APPLY");
break;
default:
atune_start = PARAM_INVALID;
has_module = false;
break;
}
if (atune_start == PARAM_INVALID) {
has_module = false;
} else {
int32_t start = 1;
param_set(atune_start, &start);
if (has_module) {
_cmd_pub.publish(vehicle_command);
}
} else {
has_module = false;
}
}
if (has_module) {
if (has_module && fabsf(vehicle_command.param1 - 1.f) <= FLT_EPSILON && fabsf(vehicle_command.param2) < FLT_EPSILON) {
// most are in progress
result = vehicle_command_ack_s::VEHICLE_CMD_RESULT_IN_PROGRESS;
@@ -715,6 +706,10 @@ void MavlinkReceiver::handle_message_command_both(mavlink_message_t *msg, const
break;
}
} else if (has_module && (fabsf(vehicle_command.param1 - 1.f) > FLT_EPSILON || fabsf(vehicle_command.param2) > FLT_EPSILON)) {
result = vehicle_command_ack_s::VEHICLE_CMD_RESULT_DENIED;
} else {
result = vehicle_command_ack_s::VEHICLE_CMD_RESULT_UNSUPPORTED;
}
@@ -3165,7 +3160,7 @@ MavlinkReceiver::run()
ssize_t nread = 0;
hrt_abstime last_send_update = 0;
while (!_mavlink.should_exit()) {
while (!_should_exit.load()) {
// check for parameter updates
if (_parameter_update_sub.updated()) {
@@ -46,7 +46,6 @@ McAutotuneAttitudeControl::McAutotuneAttitudeControl() :
WorkItem(MODULE_NAME, px4::wq_configurations::hp_default)
{
_autotune_attitude_control_status_pub.advertise();
reset();
}
McAutotuneAttitudeControl::~McAutotuneAttitudeControl()
@@ -56,7 +55,8 @@ McAutotuneAttitudeControl::~McAutotuneAttitudeControl()
bool McAutotuneAttitudeControl::init()
{
if (!_parameter_update_sub.registerCallback()) {
if (!_vehicle_torque_setpoint_sub.registerCallback()) {
PX4_ERR("callback registration failed");
return false;
}
@@ -66,11 +66,6 @@ bool McAutotuneAttitudeControl::init()
return true;
}
void McAutotuneAttitudeControl::reset()
{
_param_mc_at_start.reset();
}
void McAutotuneAttitudeControl::Run()
{
if (should_exit()) {
@@ -91,17 +86,12 @@ void McAutotuneAttitudeControl::Run()
updateStateMachine(hrt_absolute_time());
}
// new control data needed every iteration
if (_state == state::idle
|| !_vehicle_torque_setpoint_sub.updated()) {
return;
}
if (_vehicle_status_sub.updated()) {
vehicle_status_s vehicle_status;
if (_vehicle_status_sub.copy(&vehicle_status)) {
_armed = (vehicle_status.arming_state == vehicle_status_s::ARMING_STATE_ARMED);
_nav_state = vehicle_status.nav_state;
}
}
@@ -113,6 +103,24 @@ void McAutotuneAttitudeControl::Run()
}
}
if (_vehicle_command_sub.updated()) {
vehicle_command_s vehicle_command;
if (_vehicle_command_sub.copy(&vehicle_command)) {
if (vehicle_command.command == vehicle_command_s::VEHICLE_CMD_DO_AUTOTUNE_ENABLE) {
if (fabsf(vehicle_command.param1 - 1.0f) < FLT_EPSILON && fabsf(vehicle_command.param2) < FLT_EPSILON) {
_vehicle_cmd_start_autotune = true;
}
}
}
}
// new control data needed every iteration
if ((_state == state::idle && !_vehicle_cmd_start_autotune)
|| !_vehicle_torque_setpoint_sub.updated()) {
return;
}
vehicle_torque_setpoint_s vehicle_torque_setpoint;
vehicle_angular_velocity_s angular_velocity;
@@ -271,7 +279,7 @@ void McAutotuneAttitudeControl::updateStateMachine(hrt_abstime now)
switch (_state) {
case state::idle:
if (_param_mc_at_start.get()) {
if (_vehicle_cmd_start_autotune) {
if (registerActuatorControlsCallback()) {
_state = state::init;
@@ -280,6 +288,7 @@ void McAutotuneAttitudeControl::updateStateMachine(hrt_abstime now)
}
_state_start_time = now;
_start_flight_mode = _nav_state;
}
break;
@@ -438,17 +447,23 @@ void McAutotuneAttitudeControl::updateStateMachine(hrt_abstime now)
break;
}
// In case of convergence timeout or pilot intervention,
// In case of convergence timeout, pilot intervention or mode change,
// the identification sequence is aborted immediately
manual_control_setpoint_s manual_control_setpoint{};
_manual_control_setpoint_sub.copy(&manual_control_setpoint);
const bool timeout = (now - _state_start_time) > 20_s;
const bool mode_changed = (_start_flight_mode != _nav_state);
const bool pilot_intervention = ((fabsf(manual_control_setpoint.roll) > 0.05f)
|| (fabsf(manual_control_setpoint.pitch) > 0.05f));
const bool should_abort = timeout || mode_changed || pilot_intervention;
if (_state != state::wait_for_disarm
&& _state != state::idle
&& (((now - _state_start_time) > 20_s)
|| (fabsf(manual_control_setpoint.roll) > 0.05f)
|| (fabsf(manual_control_setpoint.pitch) > 0.05f))) {
&& _state != state::idle && should_abort) {
_state = state::fail;
_start_flight_mode = _nav_state;
_state_start_time = now;
}
}
@@ -580,8 +595,7 @@ void McAutotuneAttitudeControl::saveGainsToParams()
void McAutotuneAttitudeControl::stopAutotune()
{
_param_mc_at_start.set(false);
_param_mc_at_start.commit();
_vehicle_cmd_start_autotune = false;
_vehicle_torque_setpoint_sub.unregisterCallback();
}
@@ -56,6 +56,7 @@
#include <uORB/topics/parameter_update.h>
#include <uORB/topics/autotune_attitude_control_status.h>
#include <uORB/topics/vehicle_angular_velocity.h>
#include <uORB/topics/vehicle_command.h>
#include <uORB/topics/vehicle_status.h>
#include <uORB/topics/vehicle_torque_setpoint.h>
#include <mathlib/mathlib.h>
@@ -86,8 +87,6 @@ public:
private:
void Run() override;
void reset();
void checkFilters();
void updateStateMachine(hrt_abstime now);
@@ -109,6 +108,7 @@ private:
uORB::Subscription _manual_control_setpoint_sub{ORB_ID(manual_control_setpoint)};
uORB::Subscription _vehicle_angular_velocity_sub{ORB_ID(vehicle_angular_velocity)};
uORB::Subscription _vehicle_status_sub{ORB_ID(vehicle_status)};
uORB::Subscription _vehicle_command_sub{ORB_ID(vehicle_command)};
uORB::PublicationData<autotune_attitude_control_status_s> _autotune_attitude_control_status_pub{ORB_ID(autotune_attitude_control_status)};
@@ -137,6 +137,9 @@ private:
int8_t _signal_sign{0};
bool _armed{false};
uint8_t _nav_state{0};
uint8_t _start_flight_mode{0};
bool _vehicle_cmd_start_autotune{false};
matrix::Vector3f _kid{};
matrix::Vector3f _rate_k{};
@@ -177,7 +180,6 @@ private:
perf_counter_t _cycle_perf{perf_alloc(PC_ELAPSED, MODULE_NAME": cycle time")};
DEFINE_PARAMETERS(
(ParamBool<px4::params::MC_AT_START>) _param_mc_at_start,
(ParamFloat<px4::params::MC_AT_SYSID_AMP>) _param_mc_at_sysid_amp,
(ParamInt<px4::params::MC_AT_APPLY>) _param_mc_at_apply,
(ParamFloat<px4::params::MC_AT_RISE_TIME>) _param_mc_at_rise_time,
@@ -47,24 +47,6 @@
*/
PARAM_DEFINE_INT32(MC_AT_EN, 0);
/**
* Start the autotuning sequence
*
* WARNING: this will inject steps to the rate controller
* and can be dangerous. Only activate if you know what you
* are doing, and in a safe environment.
*
* Any motion of the remote stick will abort the signal
* injection and reset this parameter
* Best is to perform the identification in position or
* hold mode.
* Increase the amplitude of the injected signal using
* MC_AT_SYSID_AMP for more signal/noise ratio
*
* @boolean
* @group Autotune
*/
PARAM_DEFINE_INT32(MC_AT_START, 0);
/**
* Amplitude of the injected signal
@@ -257,6 +257,7 @@ bool FeasibilityChecker::checkMissionItemValidity(mission_item_s &mission_item,
mission_item.nav_cmd != NAV_CMD_CONDITION_GATE &&
mission_item.nav_cmd != NAV_CMD_DO_WINCH &&
mission_item.nav_cmd != NAV_CMD_DO_GRIPPER &&
mission_item.nav_cmd != NAV_CMD_DO_AUTOTUNE_ENABLE &&
mission_item.nav_cmd != NAV_CMD_DO_JUMP &&
mission_item.nav_cmd != NAV_CMD_DO_CHANGE_SPEED &&
mission_item.nav_cmd != NAV_CMD_DO_SET_HOME &&
+1
View File
@@ -83,6 +83,7 @@ MissionBlock::is_mission_item_reached_or_completed()
case NAV_CMD_DO_MOUNT_CONTROL:
case NAV_CMD_DO_GIMBAL_MANAGER_CONFIGURE:
case NAV_CMD_COMPONENT_ARM_DISARM:
case NAV_CMD_DO_AUTOTUNE_ENABLE:
case NAV_CMD_DO_SET_ROI:
case NAV_CMD_DO_SET_ROI_LOCATION:
case NAV_CMD_DO_SET_ROI_WPNEXT_OFFSET:
+1
View File
@@ -73,6 +73,7 @@ enum NAV_CMD {
NAV_CMD_DO_MOUNT_CONFIGURE = 204,
NAV_CMD_DO_MOUNT_CONTROL = 205,
NAV_CMD_DO_GRIPPER = 211,
NAV_CMD_DO_AUTOTUNE_ENABLE = 212,
NAV_CMD_DO_SET_CAM_TRIGG_INTERVAL = 214,
NAV_CMD_DO_SET_CAM_TRIGG_DIST = 206,
NAV_CMD_OBLIQUE_SURVEY = 260,
+15
View File
@@ -759,6 +759,21 @@ void Navigator::run()
reset_cruising_speed();
set_cruising_throttle();
}
else if (cmd.command == vehicle_command_s::VEHICLE_CMD_DO_AUTOTUNE_ENABLE) {
if (fabsf(cmd.param1 - 1.f) > FLT_EPSILON) {
// only support enabling autotune (consistent with autotune module)
events::send(events::ID("navigator_autotune_unsupported_input"), {events::Log::Warning, events::LogInternal::Warning},
"Provided autotune command is not supported. To enable autotune in mission, set param1 to 1");
} else if (fabsf(cmd.param2) > FLT_EPSILON) {
// warn user about axis selection
events::send(events::ID("navigator_autotune_unsupported_ax"), {events::Log::Warning, events::LogInternal::Info},
"Autotune axis selection not supported through Mission. Use FW_AT_AXES to set axes for fixed-wing vehicles");
}
}
}
#if CONFIG_NAVIGATOR_ADSB
@@ -306,7 +306,7 @@ void TemperatureCompensationModule::Run()
}
if (got_temperature_calibration_command) {
int ret = run_temperature_calibration(accel, baro, gyro, mag);
int ret = run_temperature_calibration(accel, gyro, mag, baro);
// publish ACK
vehicle_command_ack_s command_ack{};
@@ -40,7 +40,7 @@
TEST_CASE("Takeoff and hold position", "[multicopter][vtol]")
{
const float takeoff_altitude = 10.f;
const float altitude_tolerance = 0.1f;
const float altitude_tolerance = 0.2f;
const int delay_seconds = 60.f;
AutopilotTester tester;