Compare commits

...

70 Commits

Author SHA1 Message Date
Junwoo Hwang e7896215be Echo git branch and also content of GITHUB_ENV file 2023-11-16 18:48:46 +09:00
Junwoo Hwang 96b559a65f Only build ver_gen subtarget 2023-11-16 18:42:14 +09:00
Junwoo Hwang b426e1e7c8 Echo version tag before cd & echo env total 2023-11-16 18:39:19 +09:00
Junwoo Hwang 691015e461 Fix metadata build command to v5 target 2023-11-16 18:30:26 +09:00
Junwoo Hwang b25115846c Build fmuv5x only & pring out version tag too 2023-11-16 18:24:43 +09:00
Junwoo Hwang 50cd169f79 Fix dependency on enumerate_targets 2023-11-16 18:20:26 +09:00
Junwoo Hwang de5e0cde49 deploy_all.yml: Restore trigger on push to branch 2023-11-16 18:18:01 +09:00
Junwoo Hwang b169dc6c0e [Remove me] Add test.txt to trigger CI 2023-11-16 18:15:38 +09:00
Junwoo Hwang a9239cded0 Little fixes 2023-07-19 21:26:09 +02:00
Junwoo Hwang 49a9cfd575 Fake Release test: Check if version/branch is getting set for metadata
I noticed that all the metadata deployment actions were uploading to
Firmware/master, which is obviously wrong (especially for 1.13, 1.12
branches).

I suspected that env.version is not getting set properly, or somethow
getting overwritten. So this script changes will test exactly that.
Without actually uploading to S3 of course!
2023-07-19 21:16:28 +02:00
Daniel Agar 24603589d2 Jenkinsfile-compile board updates 2023-07-18 13:53:14 -04:00
Beat Küng 4b70105583 airframes/x500_v2: move motors from AUX to MAIN 2023-07-18 11:12:20 -04:00
bresch 61036599db mag_cal: fix mag bias estimate to mag cal
- since last_us is set to 0 every time the bias is not observable, the
  total time was also reset -> needed 30 consecutive seconds in mag 3D
  to be declared "stable"
- after landing, the mag_aligned_in_flight flag is reset. Using this for
  bias validity makes it invalid before we have a chance to save it to
  the calibration.
2023-07-18 07:38:47 -07:00
bresch eb23779c57 ekf2 - preflt checks: scale flow innovation checks
Opt flow raw innovations can be really large on ground due to the small
distance to the ground (vel = flow / dist). To make the pre-flight check
more meaningful, scale it with the current distance.
2023-07-17 11:13:43 -04:00
bresch a07b8c08ab ekf2: report dist bottom also when using flow for terrain
Terrain height can be estimated using a range finder and/or optical flow
2023-07-17 11:13:43 -04:00
alexklimaj 36ec1fa811 Add EKF2_OF_QMIN_GND to handle 0 optical flow quality when on ground 2023-07-17 11:13:43 -04:00
alexklimaj 694501b782 Apply code review changes from @dagar 2023-07-17 11:13:43 -04:00
Eric Katzfey 7dd8e3f614 Removed the huge HAGL fuse timeout increase 2023-07-17 11:13:43 -04:00
Eric Katzfey fe335344e7 Cleaned up some comments and debug code 2023-07-17 11:13:43 -04:00
mjturi-mai 343c7fcd52 actual fixes for velocity estimate errors and bad rng fusion 2023-07-17 11:13:43 -04:00
Loic Fernau 66df5c1bd1 drivers: rework NXP UWB driver (#21124)
* UWB driver rework that uses 2 UWB MKBoards - 1 as Controller (Initiator), one as Controllee (Anchor)

Co-authored-by: NXPBrianna <108274268+NXPBrianna@users.noreply.github.com>
2023-07-12 11:49:40 -04:00
Ramon Roche 090f929659 drivers/barometer/invensense/icp201xx: increase delay after configuration (#21765)
- fixes wrong altitude reporting
2023-07-11 20:20:13 +02:00
alexklimaj 89b238f094 Revert "rover_pos_control: thrust normalization for joystick input (#20885)"
This reverts commit 22f7d913bd.
2023-07-11 08:26:09 -07:00
Matthias Grob ecd1e9f730 rc_update: fix on-off-switch with negative threshold values 2023-07-11 15:59:19 +02:00
Junwoo Hwang cca59843cc
netman: fix line too long (#21829)
Signed-off-by: Julian Oes <julian@oes.ch>
Co-authored-by: Julian Oes <julian@oes.ch>
2023-07-11 00:07:43 +02:00
Matthias Grob 1806a7cec8 drv_pwm_output: remove unused PWM_ defines 2023-07-10 19:00:52 +02:00
Matthias Grob 856b2e6178 UUV: stop motors when commanding zero speed 2023-07-10 19:00:52 +02:00
Matthias Grob e0e5b38c0e Boats: stop motors when commanding zero speed 2023-07-10 19:00:52 +02:00
Matthias Grob d0d113405a Rovers: stop motors when commanding zero speed 2023-07-10 19:00:52 +02:00
Matthias Grob 4ff03e4a06 TiltrotorVTOL: allow stopping front tilted motors in fast forward flight 2023-07-10 19:00:52 +02:00
Matthias Grob 8eb34ce8ce TailsitterVTOL: allow explicitly stop forward motor with zero thrust 2023-07-10 19:00:52 +02:00
Matthias Grob 62077908a3 StandardVTOL: explicitly stop forward motor with zero thrust 2023-07-10 19:00:52 +02:00
Matthias Grob cb2cc65eff FixedWing: explicitly stop forward motor with zero thrust
This allows PWM and all other output methods to configure
stopped, idling and full thrust points and use them consistently.
The fact that a fixed wing motor can be stopped when zero thrust
is demanded is explicit and could in principle even be disabled.
The mechanism is the same as for a standard VTOL stopping the
multicopter motors in the fixed wing flight phase.
2023-07-10 19:00:52 +02:00
Matthias Grob 4fc3f07cb1 ActuatorEffectiveness: add function to delectively stop motors with zero thrust 2023-07-10 19:00:52 +02:00
Matthias Grob 9b092d6d35 Set default minimum and maximum PWM for motors
This allows to consistently define:
Motor stopped - disarmed PWM
Motor idling - minimum PWM
Motor at full thrust - maximum PWM

Any allocation can then distinctly decide if
a motor should be running or not depending
on the context and also explicitly command that.
2023-07-10 19:00:52 +02:00
Vincent Poon 21fb22d581 Add ADC_ADS1115 Parameter to FMUv6x Default Build
Adding ADC_ADS1115 Parameter to FMUv6x Default Build to allow FMUv6X user to use ADS1115 with Analog Power Modules.
2023-07-07 13:42:00 +12:00
Julian Oes 3c1bcbdee6 fmu-v6x: build battery status
This is required to process data from the ADS1115 ADC and enables the
params BATx_I_CHANNEL and BATx_V_CHANNEL.

Testing is required whether this actually works on Pixhawk 6X though.

Signed-off-by: Julian Oes <julian@oes.ch>
2023-07-07 13:42:00 +12:00
Julian Oes d9b1a695b5 ROMFS: auto try RGBLED is31fl3195
This is required to auto-start the is31fl3195 driver if connected.

Signed-off-by: Julian Oes <julian@oes.ch>
2023-07-06 09:19:00 +12:00
Silvan Fuhrer 8838ebd77d Navigator: Loiter: always establish new Loiter with center at current pos
When switching into Hold mode establish a Loiter around current position,
even if we were before already loitering (eg in Mission mode).

Signed-off-by: Silvan Fuhrer <silvan@auterion.com>
2023-07-04 17:03:14 +02:00
Silvan Fuhrer 7e0f0516a5 ROMFS: set default for VT_B_TRANS_DUR for all tailsitter configs to 5s
5s is a more reasobale time for tailsitters, which rely differently on this param
than other VTOL types. Tailsitters will ramp the pitch up withing this time,
while for other VTOLS types its only the max transitiont time.

Signed-off-by: Silvan Fuhrer <silvan@auterion.com>
2023-06-29 15:21:20 +02:00
Silvan Fuhrer 5b3d19944c ROMFS: tailsitter SITL config: improve tuning after model changes
Signed-off-by: Silvan Fuhrer <silvan@auterion.com>
2023-06-29 15:21:20 +02:00
Silvan Fuhrer f2e706d7c4 ROMFS: quadtailsitter SITL config: improve tuning
Signed-off-by: Silvan Fuhrer <silvan@auterion.com>
2023-06-29 15:21:20 +02:00
Julian Oes 5a5849d61a ROMFS: initial quadtailsitter tuning
This is now using the advanced lift drag plugin.

The important step was to enable airmode for yaw, otherwise yaw gets
saturated at low throttle and we can barely roll.

The other trick was to raise airspeed a little bit to avoid operating
too much at the lower end of throttle where control authority is low.

Signed-off-by: Julian Oes <julian@oes.ch>
2023-06-29 15:21:20 +02:00
JaeyoungLim 682190a21f Support quadtailsitter in SITL 2023-06-29 15:21:20 +02:00
Alex Klimaj e0a2e0b223
GPS RTCM selection fixes (#21666)
* uavcan rtcm set max num injections
* Subscribe to all instances of gps_inject_data and mirror uavcan rtcm pub mirror gps driver
* Minor logic refactor in gps and uavcan gps inject data
2023-06-20 11:24:06 -04:00
Silvan Fuhrer d9585bf3d3 FWRateController: use param find for VT_DIFTHR_EN as pure FW build doesn't have VTOL module built
Signed-off-by: Silvan Fuhrer <silvan@auterion.com>
2023-06-19 11:00:23 +02:00
Matthias Grob 2374937388 FixedwingRateControl: rework VTOL differential thrust saturation
Co-authored-by: Silvan Fuhrer <silvan@auterion.com>
2023-06-19 11:00:23 +02:00
Matthias Grob ce8c4094a8 RateControl: allow setting individual saturation flags
This helps for more complicated cases where certain axes are controlled
through and get feedback from a different allocator.
2023-06-19 11:00:23 +02:00
Matthias Grob 11436f4109 esc_calibration: handle timeout wraps better
Co-authored-by: Beat Küng <beat-kueng@gmx.net>
2023-06-16 15:48:20 +02:00
Matthias Grob db89bd5b5e esc_calibration: allow to calibrate ESCs without battery detection
Before this the ESC calibration aborts if battery detection doesn't work.
The problem is if the user still connects the battery as he gets instructed
and the calibration aborts then the ESCs are in calibration mode and
after abortion calibrate to the wrong value.

Also I realized there's no additional safety by aborting the calibration
if the battery cannot be detected during the timeout because a pixhawk
board without power module will report a battery status from the
ADC driverand in it that no battery is connected which is the best
it can do. In this situation the motors will still spin if the
ESCs are powered.
2023-06-16 15:48:20 +02:00
Matthias Grob ae678e8e2f esc_calibration: adjust timing to work with all tested ESCs
Some ESCs e.g. Gaui enter the menu relatively quickly if the
signal is high for too long. To solve that it's kept high shorter.
Also all tested ESCs detect the low signal within a shorter time
so no need to wait longer.
2023-06-16 15:48:20 +02:00
Matthias Grob 53bcb8789f esc_calibration: Improve readability and robustness
- Change timings for a more reliable calibration.
- Make sure there's an error message when battery measurement is not
available also when it gets disabled after system boot in the power
just above the calibration button.
- Safety check if measured electrical current goes up after issuing the
high calibration value for the case the user did not unplug power
and the detection either fails or is not enforced.
2023-06-16 15:48:20 +02:00
Matthias Grob afa56d21c5 mixer_module: consistent PWM/oneshot calibration range 2023-06-16 15:48:20 +02:00
Matthias Grob 8cb7a67819 actuator_test: condition order refactoring 2023-06-16 15:48:20 +02:00
Matthias Grob c89f0776f6 Unify MixingOutput constructor calls
to make them easy to search for and check the arguments.
2023-06-16 15:48:20 +02:00
Julian Oes b21e7e6c87 lights: Add LP5562 RGBLED driver
This adds support for the TI LP5562 RGB LED driver.

Things to note:
- The driver is initialized in simple PWM mode using its internal clock,
  for R,G,B, but not for W(hite).
- The chip doesn't have a WHO_AM_I or DEVICE_ID register to check.
  Instead we read the W_CURRENT register that we're generally not using
  and therefore doesn't get changed.
- The current is left at the default 17.5 mA but could be changed using
  the command line argument.

Datasheet:
https://www.ti.com/lit/ds/symlink/lp5562.pdf

Signed-off-by: Julian Oes <julian@oes.ch>
2023-06-13 13:51:59 +12:00
Matthias Grob ccb46a2152 PULL_REQUEST_TEMPLATE: fix typo 2023-06-06 17:44:32 +02:00
Matthias Grob f34fbdf0d3 rc_update: throttle trim centering fix for reverse channel
The entire logic did not work for the case when the throttle channel is
reversed because then QGC sets trim = max for that channel and
the result is only half the throttle range.
2023-06-06 17:44:32 +02:00
Junwoo Hwang 7cbf720d26
Geofence: Disable pre-emptive geofence predictor by default (#21657)
Co-authored-by: Hamish Willee <hamishwillee@gmail.com>
2023-06-06 11:22:47 -04:00
Ramon Roche 29a3abb817 netman: update module description (#21664)
Co-authored-by: David Sidrane <David.Sidrane@Nscdg.com>
Co-authored-by: Hamish Willee <hamishwillee@gmail.com>
2023-06-02 15:07:31 -04:00
Silvan Fuhrer 4e4ba40289 FW TECS: reduce default for FW_T_I_GAIN_THR to more appropriate 0.05
Signed-off-by: Silvan Fuhrer <silvan@auterion.com>
2023-06-02 13:06:10 +02:00
Silvan Fuhrer d5cbf5df01 VTOL: params: add missing @decimal and @increment
Signed-off-by: Silvan Fuhrer <silvan@auterion.com>
2023-06-02 13:06:10 +02:00
Silvan Fuhrer 0d7933beac Tiltrotor params: set default for VT_TILT_TRANS to 0.4
0.4 tilt is more reasobale to get nice transitions than
the previous 0.3.

Signed-off-by: Silvan Fuhrer <silvan@auterion.com>
2023-06-02 13:06:10 +02:00
Silvan Fuhrer 19029526d0 FWAttitudeController: params: increases parameter ranges
Signed-off-by: Silvan Fuhrer <silvan@auterion.com>
2023-06-02 13:06:10 +02:00
Silvan Fuhrer b0712ef7a0 Commander: open up limits on TRIM_ROLL/PITCH/YAW to +/- 50%
Signed-off-by: Silvan Fuhrer <silvan@auterion.com>
2023-06-02 13:06:10 +02:00
Silvan Fuhrer 71293b4943 FWRateController: fix @group, all should be in FW Rate Control group
Signed-off-by: Silvan Fuhrer <silvan@auterion.com>
2023-06-02 13:06:10 +02:00
Silvan Fuhrer fb1491de33 FW Rate Controller: relax param ranges
Signed-off-by: Silvan Fuhrer <silvan@auterion.com>
2023-06-02 13:06:10 +02:00
Silvan Fuhrer 487b9ca7ef Navigator: make sure to reset mission.item fields touched by set_vtol_transition_item
set_vtol_transition_item sets the params of the mission item directly
to values that make sense for NAV_CMD_DO_VTOL_TRANSITION, but don't
for other NAV_CMDs. So make sure that whenever we use it, we then in
the next step reset the touched mission_item fields.

Signed-off-by: Silvan Fuhrer <silvan@auterion.com>
2023-06-02 10:22:34 +02:00
Roman Bapst 5aa5fc2da5 Refactor uncommanded descend Quad-Chute (#21598)
* refactored uncommanded descend quadchute
- use fixed altitude error threshold
- compute error relative to higest altitude the vehicle has achieved
since it has flown below the altitude reference (setpoint)

* disabled altitude loss quadchute by default

* altitude loss quadchute: added protection against invalid local z


---------

Signed-off-by: RomanBapst <bapstroman@gmail.com>
2023-06-02 10:22:34 +02:00
Silvan Fuhrer 4b7da42a6e
FWPositionControl: navigateWaypoints: fix logic if already past waypoint and need to turn back (#21642)
Signed-off-by: Silvan Fuhrer <silvan@auterion.com>
2023-06-01 09:25:09 +02:00
125 changed files with 1629 additions and 2189 deletions

View File

@ -40,6 +40,8 @@ pipeline {
"ark_can-flow_default",
"ark_can-gps_canbootloader",
"ark_can-gps_default",
"ark_cannode-gps_canbootloader",
"ark_cannode-gps_default",
"ark_can-rtk-gps_canbootloader",
"ark_can-rtk-gps_default",
"ark_fmu-v6x_bootloader",
@ -53,8 +55,10 @@ pipeline {
"cuav_nora_default",
"cuav_x7pro_default",
"cubepilot_cubeorange_default",
"cubepilot_cubeorangeplus_default",
"cubepilot_cubeyellow_default",
"diatone_mamba-f405-mk2_default",
"flywoo_gn-f405_default",
"freefly_can-rtk-gps_canbootloader",
"freefly_can-rtk-gps_default",
"holybro_can-gps-v1_canbootloader",
@ -73,6 +77,7 @@ pipeline {
"modalai_fc-v1_default",
"modalai_fc-v2_default",
"modalai_voxl2-io_default",
"mro_ctrl-zero-classic_default",
"mro_ctrl-zero-f7_default",
"mro_ctrl-zero-f7-oem_default",
"mro_ctrl-zero-h7-oem_default",
@ -85,6 +90,7 @@ pipeline {
"nxp_fmuk66-v3_default",
"nxp_fmuk66-v3_socketcan",
"nxp_fmurt1062-v1_default",
"nxp_mr-canhubk3_default",
"nxp_ucans32k146_canbootloader",
"nxp_ucans32k146_default",
"omnibus_f4sd_default",

View File

@ -23,7 +23,7 @@ For release notes:
```
Feature/Bugfix XYZ
New parameter: XYZ_Z
Documentation: Need to clarfiy page ... / done, read docs.px4.io/...
Documentation: Need to clarify page ... / done, read docs.px4.io/...
```
### Alternatives

View File

@ -1,34 +0,0 @@
name: ClusterFuzzLite batch fuzzing
on:
schedule:
- cron: '0 6 * * *' # UTC 6am every day.
permissions: read-all
jobs:
BatchFuzzing:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
sanitizer:
- address
- undefined
- memory
steps:
- name: Build Fuzzers (${{ matrix.sanitizer }})
id: build
uses: google/clusterfuzzlite/actions/build_fuzzers@v1
with:
sanitizer: ${{ matrix.sanitizer }}
- name: Run Fuzzers (${{ matrix.sanitizer }})
id: run
uses: google/clusterfuzzlite/actions/run_fuzzers@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
fuzz-seconds: 1800 # 30 mins
mode: 'batch'
sanitizer: ${{ matrix.sanitizer }}
# Optional but recommended: For storing certain artifacts from fuzzing.
# See later section on "Git repo for storage".
# storage-repo: https://${{ secrets.PERSONAL_ACCESS_TOKEN }}@github.com/OWNER/STORAGE-REPO-NAME.git
# storage-repo-branch: main # Optional. Defaults to "main"
# storage-repo-branch-coverage: gh-pages # Optional. Defaults to "gh-pages".

View File

@ -1,50 +0,0 @@
name: Checks
on:
push:
branches:
- 'main'
pull_request:
branches:
- '*'
jobs:
build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
check: [
"check_format",
"tests",
"tests_coverage",
"px4_fmu-v2_default stack_check",
"validate_module_configs",
"shellcheck_all",
"NO_NINJA_BUILD=1 px4_fmu-v5_default",
"NO_NINJA_BUILD=1 px4_sitl_default",
"airframe_metadata",
"module_documentation",
"parameters_metadata",
]
container:
image: px4io/px4-dev-nuttx-focal:2021-09-08
options: --privileged --ulimit core=-1 --security-opt seccomp=unconfined
steps:
- uses: actions/checkout@v1
with:
token: ${{ secrets.ACCESS_TOKEN }}
- name: check environment
run: |
export
ulimit -a
- name: ${{matrix.check}}
run: make ${{matrix.check}}
- name: upload coverage
if: contains(matrix.check, 'coverage')
uses: codecov/codecov-action@v1
with:
token: ${{ secrets.CODECOV_TOKEN }}
flags: unittests
file: coverage/lcov.info

View File

@ -1,21 +0,0 @@
name: Clang Tidy
on:
push:
branches:
- 'main'
pull_request:
branches:
- '*'
jobs:
build:
runs-on: ubuntu-latest
container: px4io/px4-dev-clang:2021-09-08
steps:
- uses: actions/checkout@v1
with:
token: ${{secrets.ACCESS_TOKEN}}
- name: make clang-tidy-quiet
run: make clang-tidy-quiet

View File

@ -1,54 +0,0 @@
name: Linux Targets
on:
push:
branches:
- 'main'
pull_request:
branches:
- '*'
jobs:
build:
runs-on: ubuntu-latest
container: px4io/px4-dev-armhf:2021-09-08
strategy:
matrix:
config: [
beaglebone_blue_default,
emlid_navio2_default,
px4_raspberrypi_default,
scumaker_pilotpi_default,
]
steps:
- uses: actions/checkout@v1
with:
token: ${{secrets.ACCESS_TOKEN}}
- 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@v2
with:
path: ~/.ccache
key: ${{matrix.config}}-ccache-${{steps.ccache_cache_timestamp.outputs.timestamp}}
restore-keys: ${{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 = 100M" >> ~/.ccache/ccache.conf
echo "hash_dir = false" >> ~/.ccache/ccache.conf
ccache -s
ccache -z
- name: make ${{matrix.config}}
run: make ${{matrix.config}}
- name: ccache post-run
run: ccache -s

View File

@ -1,51 +0,0 @@
name: Linux ARM64 Targets
on:
push:
branches:
- 'main'
pull_request:
branches:
- '*'
jobs:
build:
runs-on: ubuntu-latest
container: px4io/px4-dev-aarch64:2021-09-08
strategy:
matrix:
config: [
scumaker_pilotpi_arm64,
]
steps:
- uses: actions/checkout@v1
with:
token: ${{secrets.ACCESS_TOKEN}}
- 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@v2
with:
path: ~/.ccache
key: ${{matrix.config}}-ccache-${{steps.ccache_cache_timestamp.outputs.timestamp}}
restore-keys: ${{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 = 100M" >> ~/.ccache/ccache.conf
echo "hash_dir = false" >> ~/.ccache/ccache.conf
ccache -s
ccache -z
- name: make ${{matrix.config}}
run: make ${{matrix.config}}
- name: ccache post-run
run: ccache -s

View File

@ -1,56 +0,0 @@
name: MacOS build
on:
push:
branches:
- 'main'
pull_request:
branches:
- '*'
jobs:
build:
runs-on: macos-10.15
strategy:
matrix:
config: [
px4_fmu-v5_default,
px4_sitl
#tests, # includes px4_sitl
]
steps:
- uses: actions/checkout@v1
with:
token: ${{secrets.ACCESS_TOKEN}}
- name: setup
run: ./Tools/setup/macos.sh; ./Tools/setup/macos.sh
- 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@v2
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
make ${{matrix.config}}
ccache -s

View File

@ -1,129 +0,0 @@
name: Nuttx Targets
on:
push:
branches:
- 'main'
pull_request:
branches:
- '*'
jobs:
build:
runs-on: ubuntu-latest
container: px4io/px4-dev-nuttx-focal:2021-09-08
strategy:
fail-fast: false
matrix:
config: [
airmind_mindpx-v2,
ark_can-flow,
ark_can-gps,
ark_can-rtk-gps,
ark_cannode,
ark_fmu-v6x,
atl_mantis-edu,
av_x-v1,
bitcraze_crazyflie,
bitcraze_crazyflie21,
cuav_can-gps-v1,
cuav_nora,
cuav_x7pro,
cubepilot_cubeorange,
cubepilot_cubeorangeplus,
cubepilot_cubeyellow,
diatone_mamba-f405-mk2,
freefly_can-rtk-gps,
holybro_can-gps-v1,
holybro_durandal-v1,
holybro_kakutef7,
holybro_kakuteh7,
holybro_pix32v5,
matek_gnss-m9n-f4,
matek_h743,
matek_h743-mini,
matek_h743-slim,
modalai_fc-v1,
modalai_fc-v2,
mro_ctrl-zero-f7,
mro_ctrl-zero-f7-oem,
mro_ctrl-zero-h7,
mro_ctrl-zero-h7-oem,
mro_pixracerpro,
mro_x21,
mro_x21-777,
nxp_fmuk66-e,
nxp_fmuk66-v3,
nxp_fmurt1062-v1,
nxp_mr-canhubk3,
nxp_ucans32k146,
omnibus_f4sd,
px4_fmu-v2,
px4_fmu-v3,
px4_fmu-v4,
px4_fmu-v4pro,
px4_fmu-v5,
px4_fmu-v5x,
px4_fmu-v6c,
px4_fmu-v6u,
px4_fmu-v6x,
raspberrypi_pico,
sky-drones_smartap-airlink,
spracing_h7extreme,
uvify_core
]
steps:
- uses: actions/checkout@v1
with:
token: ${{secrets.ACCESS_TOKEN}}
- 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@v2
with:
path: ~/.ccache
key: ${{matrix.config}}-ccache-${{steps.ccache_cache_timestamp.outputs.timestamp}}
restore-keys: ${{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 = 120M" >> ~/.ccache/ccache.conf
echo "hash_dir = false" >> ~/.ccache/ccache.conf
ccache -s
ccache -z
- name: make all_variants_${{matrix.config}}
run: make all_variants_${{matrix.config}}
timeout-minutes: 45
- name: make ${{matrix.config}} bloaty_compileunits
run: make ${{matrix.config}} bloaty_compileunits || true
- name: make ${{matrix.config}} bloaty_inlines
run: make ${{matrix.config}} bloaty_inlines || true
- name: make ${{matrix.config}} bloaty_segments
run: make ${{matrix.config}} bloaty_segments || true
- name: make ${{matrix.config}} bloaty_symbols
run: make ${{matrix.config}} bloaty_symbols || true
- name: make ${{matrix.config}} bloaty_templates
run: make ${{matrix.config}} bloaty_templates || true
- name: make ${{matrix.config}} bloaty_ram
run: make ${{matrix.config}} bloaty_ram || true
- name: make ${{matrix.config}} bloaty_compare_master
run: make ${{matrix.config}} bloaty_compare_master || true
- name: ccache post-run
run: ccache -s
- name: Upload px4 package
uses: actions/upload-artifact@v2
with:
name: px4_package_${{matrix.config}}
path: |
build/**/*.px4
build/**/*.bin

View File

@ -6,49 +6,51 @@ on:
- 'main'
- 'release/*'
- 'pr-metadata-test'
pull_request:
branches:
- '*'
jobs:
enumerate_targets:
runs-on: ubuntu-latest
container: px4io/px4-dev-base-focal:2021-09-08
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- uses: actions/checkout@v1
with:
token: ${{secrets.ACCESS_TOKEN}}
- id: set-matrix
run: echo "::set-output name=matrix::$(./Tools/generate_board_targets_json.py)"
build:
runs-on: ubuntu-latest
needs: enumerate_targets
strategy:
matrix: ${{fromJson(needs.enumerate_targets.outputs.matrix)}}
container: px4io/px4-dev-${{ matrix.container }}:2021-09-08
container: px4io/px4-dev-nuttx-focal:2021-09-08
steps:
- uses: actions/checkout@v1
with:
token: ${{secrets.ACCESS_TOKEN}}
- name: make ${{matrix.target}}
run: make ${{matrix.target}}
- name: make target
run: make px4_fmu-v5_default
- name: parameter & events metadata
run: |
make ${{matrix.target}} ver_gen events_json actuators_json
./src/lib/version/get_git_tag_or_branch_version.sh build/${{ matrix.target }} >> $GITHUB_ENV
cd build/${{ matrix.target }}
mkdir _metadata || true
cp parameters.* events/*.xz actuators.json* _metadata
make px4_fmu-v5_default ver_gen
echo "Git branch:"
echo $(git branch)
echo "Version tag detected: "
echo $(./src/lib/version/get_git_tag_or_branch_version.sh build/px4_fmu-v5_default)
./src/lib/version/get_git_tag_or_branch_version.sh build/px4_fmu-v5_default >> $GITHUB_ENV
echo "Github ENV:"
echo $(cat $GITHUB_ENV)
echo $env.version
- name: Check environment variables
run: |
echo "Version:"
echo $version
echo "Envs:"
echo $(env)
- uses: jakejarvis/s3-sync-action@master
with:
args: --acl public-read
env:
AWS_S3_BUCKET: 'px4-travis'
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_ACCESS_KEY_ID: ASDFJJGS + DFS ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ASDF ASDF + ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_REGION: 'us-west-1'
SOURCE_DIR: 'build/${{ matrix.target }}/_metadata/'
DEST_DIR: 'Firmware/${{ env.version }}/${{ matrix.target }}/'
SOURCE_DIR: 'build/px4_fmu-v5_default/_metadata/'
DEST_DIR: 'Firmware/${{ env.version }}/px4_fmu-v5_default/'

View File

@ -1,21 +0,0 @@
name: EKF Change Indicator
on: pull_request
jobs:
unit_tests:
runs-on: ubuntu-latest
container: px4io/px4-dev-base-focal:2021-09-08
steps:
- uses: actions/checkout@v2.3.1
with:
fetch-depth: 0
- name: checkout newest version of branch
run: |
git fetch origin pull/${{github.event.pull_request.number}}/head:${{github.head_ref}}
git checkout ${GITHUB_HEAD_REF}
- name: main test
run: make tests TESTFILTER=EKF
- name: Check if there is a functional change
run: git diff --exit-code
working-directory: src/modules/ekf2/test/change_indication

View File

@ -1,29 +0,0 @@
name: EKF Update Change Indicator
on: push
jobs:
unit_tests:
runs-on: ubuntu-latest
container: px4io/px4-dev-base-focal:2021-09-08
env:
GIT_COMMITTER_EMAIL: bot@px4.io
GIT_COMMITTER_NAME: PX4BuildBot
steps:
- uses: actions/checkout@v2.3.1
with:
fetch-depth: 0
- name: main test updates change indication files
run: make tests TESTFILTER=EKF
- name: Check if there exists diff and save result in variable
run: echo "CHANGE_INDICATED=$(git diff --exit-code --output=/dev/null || echo $?)" >> $GITHUB_ENV
working-directory: src/modules/ekf2/test/change_indication
- name: auto-commit any changes to change indication
uses: stefanzweifel/git-auto-commit-action@v4
with:
commit_message: '[AUTO COMMIT] update change indication'
commit_user_name: ${GIT_COMMITTER_NAME}
commit_user_email: ${GIT_COMMITTER_EMAIL}
- if: ${{env.CHANGE_INDICATED}}
name: if there is a functional change, fail check
run: exit 1

View File

@ -1,44 +0,0 @@
name: Failsafe Simulator Build
on:
push:
branches:
- 'main'
pull_request:
branches:
- '*'
jobs:
build:
runs-on: ubuntu-latest
defaults:
run:
shell: bash
strategy:
fail-fast: false
matrix:
check: [
"failsafe_web",
]
container:
image: px4io/px4-dev-nuttx-focal:2021-09-08
options: --privileged --ulimit core=-1 --security-opt seccomp=unconfined
steps:
- uses: actions/checkout@v1
with:
token: ${{ secrets.ACCESS_TOKEN }}
- name: check environment
run: |
export
ulimit -a
- name: install emscripten
run: |
git clone https://github.com/emscripten-core/emsdk.git _emscripten_sdk
cd _emscripten_sdk
./emsdk install latest
./emsdk activate latest
- name: ${{matrix.check}}
run: |
. ./_emscripten_sdk/emsdk_env.sh
make ${{matrix.check}}

View File

@ -1,139 +0,0 @@
name: MAVROS Mission Tests
on:
push:
branches:
- 'main'
pull_request:
branches:
- '*'
jobs:
build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
config:
- {vehicle: "iris", mission: "MC_mission_box", build_type: "RelWithDebInfo"}
- {vehicle: "rover", mission: "rover_mission_1", build_type: "RelWithDebInfo"}
#- {vehicle: "plane", mission: "FW_mission_1", build_type: "RelWithDebInfo"}
#- {vehicle: "plane_catapult",mission: "FW_mission_1", build_type: "RelWithDebInfo"}
#- {vehicle: "standard_vtol", mission: "VTOL_mission_1", build_type: "Coverage"}
#- {vehicle: "standard_vtol", mission: "VTOL_mission_1", build_type: "AddressSanitizer"}
#- {vehicle: "tailsitter", mission: "VTOL_mission_1", build_type: "RelWithDebInfo"}
#- {vehicle: "tiltrotor", mission: "VTOL_mission_1", build_type: "RelWithDebInfo"}
container:
image: px4io/px4-dev-ros-melodic:2021-09-08
options: --privileged --ulimit core=-1 --security-opt seccomp=unconfined
steps:
- uses: actions/checkout@v1
with:
token: ${{ secrets.ACCESS_TOKEN }}
- 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@v2
with:
path: ~/.ccache
key: sitl_tests-${{matrix.config.build_type}}-ccache-${{steps.ccache_cache_timestamp.outputs.timestamp}}
restore-keys: sitl_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 = 100M" >> ~/.ccache/ccache.conf
echo "hash_dir = false" >> ~/.ccache/ccache.conf
ccache -s
ccache -z
- name: check environment
run: |
export
ulimit -a
- name: Build PX4 and sitl_gazebo-classic
env:
PX4_CMAKE_BUILD_TYPE: ${{matrix.config.build_type}}
run: |
ccache -z
make px4_sitl_default
make px4_sitl_default sitl_gazebo-classic
ccache -s
- name: Core dump settings
run: |
ulimit -c unlimited
echo "`pwd`/%e.core" > /proc/sys/kernel/core_pattern
- name: Run SITL tests
env:
PX4_CMAKE_BUILD_TYPE: ${{matrix.config.build_type}}
run: |
export
./test/rostest_px4_run.sh mavros_posix_test_mission.test mission:=${{matrix.config.mission}} vehicle:=${{matrix.config.vehicle}}
timeout-minutes: 45
- name: Look at core files
if: failure()
run: gdb build/px4_sitl_default/bin/px4 px4.core -ex "thread apply all bt" -ex "quit"
- name: Upload px4 coredump
if: failure()
uses: actions/upload-artifact@v2-preview
with:
name: coredump
path: px4.core
- name: ecl EKF analysis
if: always()
run: ./Tools/ecl_ekf/process_logdata_ekf.py ~/.ros/log/*/*.ulg || true
- name: Upload logs to flight review
if: always()
run: ./Tools/upload_log.py -q --description "${GITHUB_WORKFLOW} ${GITHUB_RUN_ID}" --feedback "${GITHUB_WORKFLOW} ${GITHUB_RUN_ID} ${GITHUB_REPOSITORY} ${GITHUB_REF}" --source CI ~/.ros/log/*/*.ulg
- name: Upload px4 binary
if: failure()
uses: actions/upload-artifact@v2
with:
name: binary
path: build/px4_sitl_default/bin/px4
- name: Store PX4 log
if: failure()
uses: actions/upload-artifact@v2
with:
name: px4_log
path: ~/.ros/log/*/*.ulg
- name: Store ROS log
if: failure()
uses: actions/upload-artifact@v2
with:
name: ros_log
path: ~/.ros/**/rostest-*.log
# Report test coverage
- name: Upload coverage
if: contains(matrix.config.build_type, 'Coverage')
run: |
git config --global credential.helper "" # disable the keychain credential helper
git config --global --add credential.helper store # enable the local store credential helper
echo "https://x-access-token:${{ secrets.ACCESS_TOKEN }}@github.com" >> ~/.git-credentials # add credential
git config --global url."https://github.com/".insteadof git@github.com: # credentials add credential
mkdir -p coverage
lcov --directory build/px4_sitl_default --base-directory build/px4_sitl_default --gcov-tool gcov --capture -o coverage/lcov.info
- name: Upload coverage information to Codecov
if: contains(matrix.config.build_type, 'Coverage')
uses: codecov/codecov-action@v1
with:
token: ${{ secrets.CODECOV_TOKEN }}
flags: mavros_mission
file: coverage/lcov.info

View File

@ -1,134 +0,0 @@
name: MAVROS Offboard Tests
on:
push:
branches:
- 'main'
pull_request:
branches:
- '*'
jobs:
build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
config:
- {test_file: "mavros_posix_tests_offboard_posctl.test", vehicle: "iris", build_type: "RelWithDebInfo"}
#- {test_file: "mavros_posix_tests_offboard_attctl.test", vehicle: "iris", build_type: "RelWithDebInfo"}
#- {test_file: "mavros_posix_tests_offboard_rpyrt_ctl.test", vehicle: "iris", build_type: "RelWithDebInfo"}
container:
image: px4io/px4-dev-ros-melodic:2021-09-08
options: --privileged --ulimit core=-1 --security-opt seccomp=unconfined
steps:
- uses: actions/checkout@v1
with:
token: ${{ secrets.ACCESS_TOKEN }}
- 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@v2
with:
path: ~/.ccache
key: sitl_tests-${{matrix.config.build_type}}-ccache-${{steps.ccache_cache_timestamp.outputs.timestamp}}
restore-keys: sitl_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 = 100M" >> ~/.ccache/ccache.conf
echo "hash_dir = false" >> ~/.ccache/ccache.conf
ccache -s
ccache -z
- name: check environment
run: |
export
ulimit -a
- name: Build PX4 and sitl_gazebo-classic
env:
PX4_CMAKE_BUILD_TYPE: ${{matrix.config.build_type}}
run: |
ccache -z
make px4_sitl_default
make px4_sitl_default sitl_gazebo-classic
ccache -s
- name: Core dump settings
run: |
ulimit -c unlimited
echo "`pwd`/%e.core" > /proc/sys/kernel/core_pattern
- name: Run SITL tests
env:
PX4_CMAKE_BUILD_TYPE: ${{matrix.config.build_type}}
run: |
export
./test/rostest_px4_run.sh ${{matrix.config.test_file}} vehicle:=${{matrix.config.vehicle}}
timeout-minutes: 45
- name: Look at core files
if: failure()
run: gdb build/px4_sitl_default/bin/px4 px4.core -ex "thread apply all bt" -ex "quit"
- name: Upload px4 coredump
if: failure()
uses: actions/upload-artifact@v2-preview
with:
name: coredump
path: px4.core
- name: ecl EKF analysis
if: always()
run: ./Tools/ecl_ekf/process_logdata_ekf.py ~/.ros/log/*/*.ulg || true
- name: Upload logs to flight review
if: always()
run: ./Tools/upload_log.py -q --description "${GITHUB_WORKFLOW} ${GITHUB_RUN_ID}" --feedback "${GITHUB_WORKFLOW} ${GITHUB_RUN_ID} ${GITHUB_REPOSITORY} ${GITHUB_REF}" --source CI ~/.ros/log/*/*.ulg
- name: Upload px4 binary
if: failure()
uses: actions/upload-artifact@v2
with:
name: binary
path: build/px4_sitl_default/bin/px4
- name: Store PX4 log
if: failure()
uses: actions/upload-artifact@v2
with:
name: px4_log
path: ~/.ros/log/*/*.ulg
- name: Store ROS log
if: failure()
uses: actions/upload-artifact@v2
with:
name: ros_log
path: ~/.ros/**/rostest-*.log
# Report test coverage
- name: Upload coverage
if: contains(matrix.config.build_type, 'Coverage')
run: |
git config --global credential.helper "" # disable the keychain credential helper
git config --global --add credential.helper store # enable the local store credential helper
echo "https://x-access-token:${{ secrets.ACCESS_TOKEN }}@github.com" >> ~/.git-credentials # add credential
git config --global url."https://github.com/".insteadof git@github.com: # credentials add credential
mkdir -p coverage
lcov --directory build/px4_sitl_default --base-directory build/px4_sitl_default --gcov-tool gcov --capture -o coverage/lcov.info
- name: Upload coverage information to Codecov
if: contains(matrix.config.build_type, 'Coverage')
uses: codecov/codecov-action@v1
with:
token: ${{ secrets.CODECOV_TOKEN }}
flags: mavros_offboard
file: coverage/lcov.info

View File

@ -1,131 +0,0 @@
name: Metadata
on:
push:
branches:
- 'main'
- 'release/*'
- 'pr-metadata-test'
jobs:
airframe:
runs-on: ubuntu-latest
container: px4io/px4-dev-base-focal:2021-09-08
steps:
- uses: actions/checkout@v1
with:
token: ${{ secrets.ACCESS_TOKEN }}
- name: airframe metadata
run: |
make airframe_metadata
./src/lib/version/get_git_tag_or_branch_version.sh build/px4_sitl_default >> $GITHUB_ENV
cd build/px4_sitl_default/docs
# TODO: deploy to userguide gitbook
- uses: jakejarvis/s3-sync-action@master
with:
args: --acl public-read
env:
AWS_S3_BUCKET: 'px4-travis'
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_REGION: 'us-west-1'
SOURCE_DIR: 'build/px4_sitl_default/docs/'
DEST_DIR: 'Firmware/${{ env.version }}/_general/'
module:
runs-on: ubuntu-latest
container: px4io/px4-dev-base-focal:2021-09-08
steps:
- uses: actions/checkout@v1
with:
token: ${{ secrets.ACCESS_TOKEN }}
- name: module documentation
run: |
make module_documentation
cd build/px4_sitl_default/docs
ls -ls *
# TODO: deploy to userguide gitbook and s3
parameter:
runs-on: ubuntu-latest
container: px4io/px4-dev-base-focal:2021-09-08
steps:
- uses: actions/checkout@v1
with:
token: ${{ secrets.ACCESS_TOKEN }}
- name: parameter metadata
run: |
make parameters_metadata
./src/lib/version/get_git_tag_or_branch_version.sh build/px4_sitl_default >> $GITHUB_ENV
- uses: jakejarvis/s3-sync-action@master
with:
args: --acl public-read
env:
AWS_S3_BUCKET: 'px4-travis'
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_REGION: 'us-west-1'
SOURCE_DIR: 'build/px4_sitl_default/docs/'
DEST_DIR: 'Firmware/${{ env.version }}/_general/'
events:
runs-on: ubuntu-latest
container: px4io/px4-dev-base-focal:2021-09-08
steps:
- uses: actions/checkout@v1
with:
token: ${{ secrets.ACCESS_TOKEN }}
- name: events metadata
run: |
make extract_events
./src/lib/version/get_git_tag_or_branch_version.sh build/px4_sitl_default >> $GITHUB_ENV
cd build/px4_sitl_default
mkdir _events_full || true
cp events/all_events_full.json.xz _events_full/all_events.json.xz
- uses: jakejarvis/s3-sync-action@master
with:
args: --acl public-read
env:
AWS_S3_BUCKET: 'px4-travis'
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_REGION: 'us-west-1'
SOURCE_DIR: 'build/px4_sitl_default/_events_full/'
DEST_DIR: 'Firmware/${{ env.version }}/_general/'
uorb_graph:
runs-on: ubuntu-latest
container: px4io/px4-dev-nuttx-focal:2021-09-08
steps:
- uses: actions/checkout@v1
with:
token: ${{ secrets.ACCESS_TOKEN }}
- name: uORB graph
run: |
make uorb_graphs
cd Tools/uorb_graph
ls -ls *
# TODO: deploy graph_px4_sitl.json to S3 px4-travis:Firmware/master/
ROS2_msgs:
runs-on: ubuntu-latest
container: px4io/px4-dev-base-focal:2021-09-08
steps:
- uses: actions/checkout@v1
with:
token: ${{ secrets.ACCESS_TOKEN }}
- name: PX4 ROS2 msgs
run: |
git clone https://github.com/PX4/px4_msgs.git
rm px4_msgs/msg/*.msg
cp msg/*.msg px4_msgs/msg/

View File

@ -1,25 +0,0 @@
name: Python CI Checks
on:
push:
branches:
- 'main'
pull_request:
branches:
- '*'
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
with:
token: ${{ secrets.ACCESS_TOKEN }}
- name: Install Python3
run: sudo apt-get install python3 python3-setuptools python3-pip -y
- name: Install tools
run: pip3 install --user mypy types-requests flake8
- name: Check MAVSDK test scripts with mypy
run: $HOME/.local/bin/mypy --strict test/mavsdk_tests/*.py
- name: Check MAVSDK test scripts with flake8
run: $HOME/.local/bin/flake8 test/mavsdk_tests/*.py

View File

@ -1,135 +0,0 @@
name: SITL Tests
on:
push:
branches:
- 'main'
pull_request:
branches:
- '*'
jobs:
build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
config:
- {model: "iris", latitude: "59.617693", longitude: "-151.145316", altitude: "48", build_type: "RelWithDebInfo" } # Alaska
# - {model: "standard_vtol", latitude: "-38.071235", longitude: "145.281220", altitude: "31", build_type: "AddressSanitizer" } # Australia
- {model: "tailsitter" , latitude: "29.660316", longitude: "-82.316658", altitude: "30", build_type: "RelWithDebInfo" } # Florida
- {model: "standard_vtol", latitude: "47.397742", longitude: "8.545594", altitude: "488", build_type: "Coverage" } # Zurich
container:
image: px4io/px4-dev-simulation-focal:2021-09-08
options: --privileged --ulimit core=-1 --security-opt seccomp=unconfined
steps:
- uses: actions/checkout@v1
with:
token: ${{ secrets.ACCESS_TOKEN }}
- name: Download MAVSDK
run: wget "https://github.com/mavlink/MAVSDK/releases/download/v$(cat test/mavsdk_tests/MAVSDK_VERSION)/libmavsdk-dev_$(cat test/mavsdk_tests/MAVSDK_VERSION)_ubuntu20.04_amd64.deb"
- name: Install MAVSDK
run: dpkg -i "libmavsdk-dev_$(cat test/mavsdk_tests/MAVSDK_VERSION)_ubuntu20.04_amd64.deb"
- 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@v2
with:
path: ~/.ccache
key: sitl_tests-${{matrix.config.build_type}}-ccache-${{steps.ccache_cache_timestamp.outputs.timestamp}}
restore-keys: sitl_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 = 100M" >> ~/.ccache/ccache.conf
echo "hash_dir = false" >> ~/.ccache/ccache.conf
ccache -s
ccache -z
- name: check environment
env:
PX4_HOME_LAT: ${{matrix.config.latitude}}
PX4_HOME_LON: ${{matrix.config.longitude}}
PX4_HOME_ALT: ${{matrix.config.altitude}}
PX4_CMAKE_BUILD_TYPE: ${{matrix.config.build_type}}
run: |
export
ulimit -a
- name: Build PX4
env:
PX4_CMAKE_BUILD_TYPE: ${{matrix.config.build_type}}
run: make px4_sitl_default
- name: ccache post-run px4/firmware
run: ccache -s
- name: Build SITL Gazebo
env:
PX4_CMAKE_BUILD_TYPE: ${{matrix.config.build_type}}
run: make px4_sitl_default sitl_gazebo-classic
- name: ccache post-run sitl_gazebo-classic
run: ccache -s
- name: Build MAVSDK tests
env:
PX4_CMAKE_BUILD_TYPE: ${{matrix.config.build_type}}
DONT_RUN: 1
run: make px4_sitl_default sitl_gazebo-classic mavsdk_tests
- name: ccache post-run mavsdk_tests
run: ccache -s
- name: Core dump settings
run: |
ulimit -c unlimited
echo "`pwd`/%e.core" > /proc/sys/kernel/core_pattern
- name: Run SITL tests
env:
PX4_HOME_LAT: ${{matrix.config.latitude}}
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 20 --abort-early --model ${{matrix.config.model}} --upload test/mavsdk_tests/configs/sitl.json --verbose
timeout-minutes: 45
- name: Look at core files
if: failure()
run: gdb build/px4_sitl_default/bin/px4 px4.core -ex "thread apply all bt" -ex "quit"
- name: Upload px4 coredump
if: failure()
uses: actions/upload-artifact@v2-preview
with:
name: coredump
path: px4.core
- name: Upload px4 binary
if: failure()
uses: actions/upload-artifact@v2-preview
with:
name: binary
path: build/px4_sitl_default/bin/px4
# Report test coverage
- name: Upload coverage
if: contains(matrix.config.build_type, 'Coverage')
run: |
git config --global credential.helper "" # disable the keychain credential helper
git config --global --add credential.helper store # enable the local store credential helper
echo "https://x-access-token:${{ secrets.ACCESS_TOKEN }}@github.com" >> ~/.git-credentials # add credential
git config --global url."https://github.com/".insteadof git@github.com: # credentials add credential
mkdir -p coverage
lcov --directory build/px4_sitl_default --base-directory build/px4_sitl_default --gcov-tool gcov --capture -o coverage/lcov.info
- name: Upload coverage information to Codecov
if: contains(matrix.config.build_type, 'Coverage')
uses: codecov/codecov-action@v1
with:
token: ${{ secrets.CODECOV_TOKEN }}
flags: mavsdk
file: coverage/lcov.info

View File

@ -17,6 +17,7 @@ param set-default SENS_EN_GPSSIM 1
param set-default SENS_EN_BAROSIM 1
param set-default SENS_EN_MAGSIM 1
param set-default VT_B_TRANS_DUR 5
param set-default VT_ELEV_MC_LOCK 0
param set-default VT_TYPE 0
param set-default VT_FW_DIFTHR_EN 1

View File

@ -48,35 +48,32 @@ param set-default PWM_MAIN_REV 96 # invert both elevons
param set-default EKF2_MULTI_IMU 0
param set-default SENS_IMU_MODE 1
param set-default NPFG_PERIOD 12
param set-default FW_PR_I 0.2
param set-default FW_PR_P 0.2
param set-default FW_P_TC 0.6
param set-default FW_PR_FF 0.1
param set-default FW_PSP_OFF 2
param set-default FW_P_LIM_MIN -15
param set-default FW_RR_P 0.2
param set-default FW_THR_TRIM 0.33
param set-default FW_THR_MAX 0.6
param set-default FW_RR_FF 0.1
param set-default FW_RR_I 0.2
param set-default FW_RR_P 0.3
param set-default FW_THR_TRIM 0.35
param set-default FW_THR_MAX 0.8
param set-default FW_THR_MIN 0.05
param set-default FW_T_ALT_TC 2
param set-default FW_T_CLMB_MAX 8
param set-default FW_T_SINK_MAX 2.7
param set-default FW_T_SINK_MIN 2.2
param set-default FW_T_TAS_TC 2
param set-default FW_T_CLMB_MAX 6
param set-default FW_T_HRATE_FF 0.5
param set-default FW_T_SINK_MAX 3
param set-default FW_T_SINK_MIN 1.6
param set-default MC_AIRMODE 1
param set-default MC_ROLL_P 3
param set-default MC_PITCH_P 3
param set-default MC_ROLLRATE_P 0.3
param set-default MC_PITCHRATE_P 0.3
param set-default MPC_XY_P 0.8
param set-default MPC_XY_VEL_P_ACC 3
param set-default MPC_XY_VEL_I_ACC 4
param set-default MPC_XY_VEL_D_ACC 0.1
param set-default NAV_ACC_RAD 5
param set-default VT_ARSP_TRANS 10
param set-default VT_B_TRANS_DUR 5
param set-default VT_FW_DIFTHR_EN 1
param set-default VT_FW_DIFTHR_S_Y 0.5
param set-default VT_FW_DIFTHR_S_Y 1
param set-default VT_F_TRANS_DUR 1.5
param set-default VT_F_TRANS_THR 0.7
param set-default VT_TYPE 0
param set-default WV_EN 0

View File

@ -0,0 +1,74 @@
#!/bin/sh
#
# @name Quadrotor + Tailsitter
#
# @type VTOL Quad Tailsitter
#
. ${R}etc/init.d/rc.vtol_defaults
param set-default MAV_TYPE 20
param set-default CA_AIRFRAME 4
param set-default CA_ROTOR_COUNT 4
param set-default CA_ROTOR0_PX 0.15
param set-default CA_ROTOR0_PY 0.23
param set-default CA_ROTOR0_KM 0.05
param set-default CA_ROTOR1_PX -0.15
param set-default CA_ROTOR1_PY -0.23
param set-default CA_ROTOR1_KM 0.05
param set-default CA_ROTOR2_PX 0.15
param set-default CA_ROTOR2_PY -0.23
param set-default CA_ROTOR2_KM -0.05
param set-default CA_ROTOR3_PX -0.15
param set-default CA_ROTOR3_PY 0.23
param set-default CA_ROTOR3_KM -0.05
param set-default CA_SV_CS_COUNT 0
param set-default PWM_MAIN_FUNC1 101
param set-default PWM_MAIN_FUNC2 102
param set-default PWM_MAIN_FUNC3 103
param set-default PWM_MAIN_FUNC4 104
param set-default PWM_MAIN_FUNC5 0
parm set-default FD_FAIL_R 70
param set-default FW_P_TC 0.6
param set-default FW_PR_I 0.3
param set-default FW_PR_P 0.5
param set-default FW_PSP_OFF 2
param set-default FW_RR_FF 0.1
param set-default FW_RR_I 0.1
param set-default FW_RR_P 0.2
param set-default FW_YR_FF 0 # make yaw rate controller very weak, only keep default P
param set-default FW_YR_I 0
param set-default FW_THR_TRIM 0.35
param set-default FW_THR_MAX 0.8
param set-default FW_THR_MIN 0.05
param set-default FW_T_CLMB_MAX 6
param set-default FW_T_HRATE_FF 0.5
param set-default FW_T_SINK_MAX 3
param set-default FW_T_SINK_MIN 1.6
param set-default FW_AIRSPD_STALL 10
param set-default FW_AIRSPD_MIN 14
param set-default FW_AIRSPD_TRIM 18
param set-default FW_AIRSPD_MAX 22
param set-default MC_AIRMODE 2
param set-default MAN_ARM_GESTURE 0 # required for yaw airmode
param set-default MC_ROLL_P 3
param set-default MC_PITCH_P 3
param set-default MC_ROLLRATE_P 0.3
param set-default MC_PITCHRATE_P 0.3
param set-default VT_ARSP_TRANS 15
param set-default VT_B_TRANS_DUR 5
param set-default VT_FW_DIFTHR_EN 7
param set-default VT_FW_DIFTHR_S_Y 1
param set-default VT_F_TRANS_DUR 1.5
param set-default VT_TYPE 0
param set-default WV_EN 0

View File

@ -60,6 +60,7 @@ px4_add_romfs_files(
1042_gazebo-classic_tiltrotor
1043_gazebo-classic_standard_vtol_drop
1044_gazebo-classic_plane_lidar
1045_gazebo-classic_quadtailsitter
1060_gazebo-classic_rover
1061_gazebo-classic_r1_rover
1062_flightgear_tf-r1

View File

@ -20,6 +20,7 @@
param set-default EKF2_FUSE_BETA 0 # side slip fusion is currently not supported for tailsitters
param set UAVCAN_ENABLE 0
param set-default VT_B_TRANS_DUR 5
param set-default VT_ELEV_MC_LOCK 0
param set-default VT_MOT_COUNT 2
param set-default VT_TYPE 0

View File

@ -31,3 +31,4 @@ param set-default CA_SV_CS1_TYPE 6
param set-default MAV_TYPE 19
param set-default VT_TYPE 0
param set-default VT_ELEV_MC_LOCK 0
param set-default VT_B_TRANS_DUR 5

View File

@ -34,9 +34,9 @@ param set-default CA_ROTOR3_PX -0.25
param set-default CA_ROTOR3_PY 0.25
param set-default CA_ROTOR3_KM -0.05
param set-default PWM_AUX_FUNC1 101
param set-default PWM_AUX_FUNC2 102
param set-default PWM_AUX_FUNC3 103
param set-default PWM_AUX_FUNC4 104
param set-default PWM_AUX_TIM0 -4
param set-default PWM_MAIN_FUNC1 101
param set-default PWM_MAIN_FUNC2 102
param set-default PWM_MAIN_FUNC3 103
param set-default PWM_MAIN_FUNC4 104
param set-default PWM_MAIN_TIM0 -4

View File

@ -254,6 +254,8 @@ else
#
rgbled start -X -q
rgbled_ncp5623c start -X -q
rgbled_lp5562 start -X -q
rgbled_is31fl3195 start -X -q
#
# Override parameters from user configuration file.

View File

@ -140,15 +140,7 @@
#define PX4_PWM_ALTERNATE_RANGES
#define PWM_LOWEST_MIN 0
#define PWM_MOTOR_OFF 0
#define PWM_SERVO_STOP 0
#define PWM_DEFAULT_MIN 20
#define PWM_HIGHEST_MIN 0
#define PWM_HIGHEST_MAX 255
#define PWM_DEFAULT_MAX 255
#define PWM_LOWEST_MAX 255
#define PWM_DEFAULT_TRIM 1500
/* High-resolution timer */
#define HRT_TIMER 8 /* use timer8 for the HRT */

View File

@ -141,15 +141,7 @@
#define PX4_PWM_ALTERNATE_RANGES
#define PWM_LOWEST_MIN 0
#define PWM_MOTOR_OFF 0
#define PWM_SERVO_STOP 0
#define PWM_DEFAULT_MIN 20
#define PWM_HIGHEST_MIN 0
#define PWM_HIGHEST_MAX 255
#define PWM_DEFAULT_MAX 255
#define PWM_LOWEST_MAX 255
#define PWM_DEFAULT_TRIM 1500
/* High-resolution timer */
#define HRT_TIMER 8 /* use timer8 for the HRT */

View File

@ -19,6 +19,7 @@ CONFIG_DRIVERS_IMU_BOSCH_BMI088=y
CONFIG_DRIVERS_IMU_INVENSENSE_ICM20948=y
CONFIG_DRIVERS_IMU_INVENSENSE_ICM42688P=y
CONFIG_DRIVERS_IRLOCK=y
CONFIG_DRIVERS_UWB_UWB_SR150=y
CONFIG_COMMON_LIGHT=y
CONFIG_DRIVERS_LIGHTS_RGBLED_PWM=y
CONFIG_COMMON_MAGNETOMETER=y

View File

@ -22,7 +22,7 @@ CONFIG_DRIVERS_PWM_OUT=y
CONFIG_DRIVERS_RC_INPUT=y
CONFIG_DRIVERS_SAFETY_BUTTON=y
CONFIG_DRIVERS_TONE_ALARM=y
CONFIG_COMMON_UWB=y
CONFIG_DRIVERS_UWB_UWB_SR150=y
CONFIG_MODULES_BATTERY_STATUS=y
CONFIG_MODULES_CAMERA_FEEDBACK=y
CONFIG_MODULES_COMMANDER=y

View File

@ -13,6 +13,7 @@ CONFIG_COMMON_MAGNETOMETER=y
CONFIG_DRIVERS_PWM_OUT=y
CONFIG_BOARD_UAVCAN_INTERFACES=1
CONFIG_DRIVERS_UAVCANNODE=y
CONFIG_DRIVERS_UWB_UWB_SR150=y
CONFIG_UAVCANNODE_ARMING_STATUS=y
CONFIG_UAVCANNODE_BEEP_COMMAND=y
CONFIG_UAVCANNODE_ESC_RAW_COMMAND=y

View File

@ -7,6 +7,7 @@ CONFIG_BOARD_SERIAL_TEL1="/dev/ttyS6"
CONFIG_BOARD_SERIAL_TEL2="/dev/ttyS4"
CONFIG_BOARD_SERIAL_TEL3="/dev/ttyS1"
CONFIG_BOARD_SERIAL_EXT2="/dev/ttyS3"
CONFIG_DRIVERS_ADC_ADS1115=y
CONFIG_DRIVERS_ADC_BOARD_ADC=y
CONFIG_DRIVERS_BAROMETER_BMP388=y
CONFIG_DRIVERS_BAROMETER_INVENSENSE_ICP201XX=y
@ -41,6 +42,7 @@ CONFIG_DRIVERS_TONE_ALARM=y
CONFIG_DRIVERS_UAVCAN=y
CONFIG_BOARD_UAVCAN_TIMER_OVERRIDE=2
CONFIG_MODULES_AIRSPEED_SELECTOR=y
CONFIG_MODULES_BATTERY_STATUS=y
CONFIG_MODULES_CAMERA_FEEDBACK=y
CONFIG_MODULES_COMMANDER=y
CONFIG_MODULES_CONTROL_ALLOCATOR=y

View File

@ -174,6 +174,7 @@ set(msg_files
SensorSelection.msg
SensorsStatus.msg
SensorsStatusImu.msg
SensorUwb.msg
SystemPower.msg
TakeoffStatus.msg
TaskStackInfo.msg
@ -190,8 +191,6 @@ set(msg_files
UavcanParameterValue.msg
UlogStream.msg
UlogStreamAck.msg
UwbDistance.msg
UwbGrid.msg
VehicleAcceleration.msg
VehicleAirData.msg
VehicleAngularAccelerationSetpoint.msg

34
msg/SensorUwb.msg Normal file
View File

@ -0,0 +1,34 @@
# UWB distance contains the distance information measured by an ultra-wideband positioning system,
# such as Pozyx or NXP Rddrone.
uint64 timestamp # time since system start (microseconds)
uint32 sessionid # UWB SessionID
uint32 time_offset # Time between Ranging Rounds in ms
uint32 counter # Number of Ranges since last Start of Ranging
uint16 mac # MAC adress of Initiator (controller)
uint16 mac_dest # MAC adress of Responder (Controlee)
uint16 status # status feedback #
uint8 nlos # None line of site condition y/n
float32 distance # distance in m to the UWB receiver
#Angle of arrival, Angle in Degree -60..+60; FOV in both axis is 120 degrees
float32 aoa_azimuth_dev # Angle of arrival of first incomming RX msg
float32 aoa_elevation_dev # Angle of arrival of first incomming RX msg
float32 aoa_azimuth_resp # Angle of arrival of first incomming RX msg at the responder
float32 aoa_elevation_resp # Angle of arrival of first incomming RX msg at the responder
# Figure of merit for the angle measurements
uint8 aoa_azimuth_fom # AOA Azimuth FOM
uint8 aoa_elevation_fom # AOA Elevation FOM
uint8 aoa_dest_azimuth_fom # AOA Azimuth FOM
uint8 aoa_dest_elevation_fom # AOA Elevation FOM
# Initiator physical configuration
uint8 orientation # Direction the sensor faces from MAV_SENSOR_ORIENTATION enum
# Standard configuration is Antennas facing down and azimuth aligened in forward direction
float32 offset_x # UWB initiator offset in X axis (NED drone frame)
float32 offset_y # UWB initiator offset in Y axis (NED drone frame)
float32 offset_z # UWB initiator offset in Z axis (NED drone frame)

View File

@ -1,15 +0,0 @@
# UWB distance contains the distance information measured by an ultra-wideband positioning system,
# such as Pozyx or NXP Rddrone.
uint64 timestamp # time since system start (microseconds)
uint32 time_uwb_ms # Time of UWB device in ms
uint32 counter # Number of Ranges since last Start of Ranging
uint32 sessionid # UWB SessionID
uint32 time_offset # Time between Ranging Rounds in ms
uint16 status # status feedback #
uint16[12] anchor_distance # distance in cm to each UWB Anchor (UWB Device which takes part in Ranging)
bool[12] nlos # Visual line of sight yes/no
float32[12] aoafirst # Angle of arrival of first incoming RX msg
float32[3] position # Position of the Landing point in relation to the Drone (x,y,z in Meters NED)

View File

@ -1,25 +0,0 @@
# UWB report message contains the grid information measured by an ultra-wideband positioning system,
# such as Pozyx or NXP Rddrone.
uint64 timestamp # time since system start (microseconds)
uint16 initator_time # time to synchronize clocks (microseconds)
uint8 num_anchors # Number of anchors
float64[4] target_gps # GPS position of target of the UWB system (Lat / Lon / Alt / Yaw Offset to true North)
# Grid position information
# Position in x,y,z in (x,y,z in centimeters NED)
# staring with POI and Anchor 0 up to Anchor 11
int16[3] target_pos # Point of Interest, mostly landing Target x,y,z
int16[3] anchor_pos_0
int16[3] anchor_pos_1
int16[3] anchor_pos_2
int16[3] anchor_pos_3
int16[3] anchor_pos_4
int16[3] anchor_pos_5
int16[3] anchor_pos_6
int16[3] anchor_pos_7
int16[3] anchor_pos_8
int16[3] anchor_pos_9
int16[3] anchor_pos_10
int16[3] anchor_pos_11

View File

@ -48,7 +48,6 @@ const char *_device;
ModalIo::ModalIo() :
OutputModuleInterface(MODULE_NAME, px4::serial_port_to_wq(MODAL_IO_DEFAULT_PORT)),
_mixing_output{"MODAL_IO", MODAL_IO_OUTPUT_CHANNELS, *this, MixingOutput::SchedulingPolicy::Auto, false, false},
_cycle_perf(perf_alloc(PC_ELAPSED, MODULE_NAME": cycle")),
_output_update_perf(perf_alloc(PC_INTERVAL, MODULE_NAME": output update interval"))
{

View File

@ -174,7 +174,7 @@ private:
} led_rsc_t;
ch_assign_t _output_map[MODAL_IO_OUTPUT_CHANNELS] {{1, 1}, {2, 1}, {3, 1}, {4, 1}};
MixingOutput _mixing_output;
MixingOutput _mixing_output{"MODAL_IO", MODAL_IO_OUTPUT_CHANNELS, *this, MixingOutput::SchedulingPolicy::Auto, false, false};
perf_counter_t _cycle_perf;
perf_counter_t _output_update_perf;

View File

@ -250,7 +250,7 @@ ICP201XX::RunImpl()
case STATE::CONFIG: {
if (configure()) {
_state = STATE::WAIT_READ;
ScheduleDelayed(10_ms);
ScheduleDelayed(30_ms);
} else {
if (hrt_elapsed_time(&_reset_timestamp) > 1000_ms) {

View File

@ -61,41 +61,11 @@ __BEGIN_DECLS
*/
#define PWM_LOWEST_MIN 90
/**
* Default value for a shutdown motor
*/
#define PWM_MOTOR_OFF 900
/**
* Default minimum PWM in us
*/
#define PWM_DEFAULT_MIN 1000
/**
* Highest PWM allowed as the minimum PWM
*/
#define PWM_HIGHEST_MIN 1600
/**
* Highest maximum PWM in us
*/
#define PWM_HIGHEST_MAX 2500
/**
* Default maximum PWM in us
*/
#define PWM_DEFAULT_MAX 2000
/**
* Default trim PWM in us
*/
#define PWM_DEFAULT_TRIM 0
/**
* Lowest PWM allowed as the maximum PWM
*/
#define PWM_LOWEST_MAX 200
#endif // not PX4_PWM_ALTERNATE_RANGES
/**

View File

@ -157,6 +157,8 @@
#define DRV_LED_DEVTYPE_RGBLED 0x7a
#define DRV_LED_DEVTYPE_RGBLED_NCP5623C 0x7b
#define DRV_LED_DEVTYPE_RGBLED_IS31FL3195 0xbf
#define DRV_LED_DEVTYPE_RGBLED_LP5562 0xc0
#define DRV_BAT_DEVTYPE_SMBUS 0x7c
#define DRV_SENS_DEVTYPE_IRLOCK 0x7d
#define DRV_SENS_DEVTYPE_PCF8583 0x7e

View File

@ -60,6 +60,7 @@
#include <uORB/Publication.hpp>
#include <uORB/PublicationMulti.hpp>
#include <uORB/Subscription.hpp>
#include <uORB/SubscriptionMultiArray.hpp>
#include <uORB/topics/gps_dump.h>
#include <uORB/topics/gps_inject_data.h>
#include <uORB/topics/sensor_gps.h>
@ -203,7 +204,7 @@ private:
const Instance _instance;
uORB::Subscription _orb_inject_data_sub{ORB_ID(gps_inject_data)};
uORB::SubscriptionMultiArray<gps_inject_data_s, gps_inject_data_s::MAX_INSTANCES> _orb_inject_data_sub{ORB_ID::gps_inject_data};
uORB::Publication<gps_inject_data_s> _gps_inject_data_pub{ORB_ID(gps_inject_data)};
uORB::Publication<gps_dump_s> _dump_communication_pub{ORB_ID(gps_dump)};
gps_dump_s *_dump_to_device{nullptr};
@ -530,13 +531,15 @@ void GPS::handleInjectDataTopic()
// If there has not been a valid RTCM message for a while, try to switch to a different RTCM link
if ((hrt_absolute_time() - _last_rtcm_injection_time) > 5_s) {
for (uint8_t i = 0; i < gps_inject_data_s::MAX_INSTANCES; i++) {
if (_orb_inject_data_sub.ChangeInstance(i)) {
if (_orb_inject_data_sub.copy(&msg)) {
for (int instance = 0; instance < _orb_inject_data_sub.size(); instance++) {
const bool exists = _orb_inject_data_sub[instance].advertised();
if (exists) {
if (_orb_inject_data_sub[instance].copy(&msg)) {
if ((hrt_absolute_time() - msg.timestamp) < 5_s) {
// Remember that we already did a copy on this instance.
already_copied = true;
_selected_rtcm_instance = i;
_selected_rtcm_instance = instance;
break;
}
}
@ -544,9 +547,6 @@ void GPS::handleInjectDataTopic()
}
}
// Reset instance in case we didn't actually want to switch
_orb_inject_data_sub.ChangeInstance(_selected_rtcm_instance);
bool updated = already_copied;
// Limit maximum number of GPS injections to 8 since usually
@ -574,7 +574,7 @@ void GPS::handleInjectDataTopic()
}
}
updated = _orb_inject_data_sub.update(&msg);
updated = _orb_inject_data_sub[_selected_rtcm_instance].update(&msg);
} while (updated && num_injections < max_num_injections);
}

View File

@ -35,4 +35,5 @@
add_subdirectory(rgbled)
add_subdirectory(rgbled_ncp5623c)
add_subdirectory(rgbled_is31fl3195)
add_subdirectory(rgbled_lp5562)
#add_subdirectory(rgbled_pwm) # requires board support (BOARD_HAS_LED_PWM/BOARD_HAS_UI_LED_PWM)

View File

@ -5,6 +5,7 @@ menu "Lights"
select DRIVERS_LIGHTS_RGBLED
select DRIVERS_LIGHTS_RGBLED_NCP5623C
select DRIVERS_LIGHTS_RGBLED_IS31FL3195
select DRIVERS_LIGHTS_RGBLED_LP5562
---help---
Enable default set of light drivers
rsource "*/Kconfig"

View File

@ -0,0 +1,42 @@
############################################################################
#
# Copyright (c) 2023 PX4 Development Team. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# 3. Neither the name PX4 nor the names of its contributors may be
# used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
############################################################################
px4_add_module(
MODULE drivers__rgbled_lp5562
MAIN rgbled_lp5562
SRCS
rgbled_lp5562.cpp
DEPENDS
drivers__device
led
)

View File

@ -0,0 +1,5 @@
menuconfig DRIVERS_LIGHTS_RGBLED_LP5562
bool "rgbled lp5562"
default n
---help---
Enable support for RGBLED LP5562 driver

View File

@ -0,0 +1,329 @@
/****************************************************************************
*
* Copyright (c) 2023 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file rgbled_lp5562.cpp
*
* Driver for the RGB LED controller Texas Instruments LP5562 connected via I2C.
*
* @author Julian Oes <julian@oes.ch>
*/
#include <stdint.h>
#include <string.h>
#include <drivers/device/i2c.h>
#include <lib/led/led.h>
#include <lib/parameters/param.h>
#include <px4_platform_common/getopt.h>
#include <px4_platform_common/i2c_spi_buses.h>
#include <px4_platform_common/module.h>
using namespace time_literals;
// The addresses are 0x60, 0x62, 0x64, 0x66 according to the datasheet page 27.
// We specify 7bit addresses, hence 0x60 becomes 0x30.
#define I2C_ADDR 0x30
// Unfortunately, there is no WHO_AM_I or device id register, so
// instead we query the W_CURRENT which has a certain pattern
// after reset, and we don't use it or change it, so we don't have
// to reset it and therefore don't mess with a device that we're
// not sure what it is.
static constexpr uint8_t LED_MAP_ADDR = 0x70;
static constexpr uint8_t LED_MAP_ALL_PWM = 0b00000000;
static constexpr uint8_t ENABLE_ADDR = 0x00;
static constexpr uint8_t ENABLE_CHIP_EN = 0b01000000;
static constexpr uint8_t CONFIG_ADDR = 0x08;
static constexpr uint8_t CONFIG_ENABLE_INTERNAL_CLOCK = 0b00000001;
static constexpr uint8_t RESET_ADDR = 0x0D;
static constexpr uint8_t RESET_DO_RESET = 0xFF;
static constexpr uint8_t B_PWM_ADDR = 0x02;
static constexpr uint8_t B_CURRENT_ADDR = 0x05;
static constexpr uint8_t W_CURRENT_ADDR = 0x0F;
static constexpr uint8_t W_CURRENT_DEFAULT = 0b10101111;
class RGBLED_LP5562: public device::I2C, public I2CSPIDriver<RGBLED_LP5562>
{
public:
RGBLED_LP5562(const I2CSPIDriverConfig &config);
virtual ~RGBLED_LP5562() = default;
static void print_usage();
int init() override;
int probe() override;
void RunImpl();
private:
int read(uint8_t address, uint8_t *data, unsigned count);
int write(uint8_t address, uint8_t *data, unsigned count);
int send_led_rgb(uint8_t r, uint8_t g, uint8_t b);
LedController _led_controller;
uint8_t _current = 175; // matching default current of 17.5mA
};
RGBLED_LP5562::RGBLED_LP5562(const I2CSPIDriverConfig &config) :
I2C(config),
I2CSPIDriver(config)
{
_current = config.custom1;
}
int
RGBLED_LP5562::init()
{
int ret = I2C::init();
if (ret != OK) {
return ret;
}
uint8_t command[1] = {ENABLE_CHIP_EN};
ret = write(ENABLE_ADDR, command, sizeof(command));
if (ret != OK) {
return ret;
}
// We have to wait 500us after enable.
px4_usleep(500);
command[0] = CONFIG_ENABLE_INTERNAL_CLOCK;
ret = write(CONFIG_ADDR, command, sizeof(command));
if (ret != OK) {
return ret;
}
command[0] = LED_MAP_ALL_PWM;
ret = write(LED_MAP_ADDR, command, sizeof(command));
if (ret != OK) {
return ret;
}
// Write all 3 colors at once.
uint8_t currents[3] = {_current, _current, _current};
ret = write(B_CURRENT_ADDR, currents, sizeof(currents));
if (ret != OK) {
return ret;
}
ScheduleNow();
return OK;
}
int
RGBLED_LP5562::probe()
{
uint8_t result[1] = {0};
int ret = read(W_CURRENT_ADDR, result, sizeof(result));
if (ret != OK) {
return ret;
}
_retries = 1;
return (result[0] == W_CURRENT_DEFAULT) ? OK : ERROR;
}
int
RGBLED_LP5562::read(uint8_t address, uint8_t *data, unsigned count)
{
uint8_t cmd = address;
return transfer(&cmd, 1, (uint8_t *)data, count);
}
int
RGBLED_LP5562::write(uint8_t address, uint8_t *data, unsigned count)
{
uint8_t buf[4];
if (sizeof(buf) < (count + 1)) {
return -EIO;
}
buf[0] = address;
memcpy(&buf[1], data, count);
return transfer(&buf[0], count + 1, nullptr, 0);
}
void
RGBLED_LP5562::RunImpl()
{
if (should_exit()) {
send_led_rgb(0, 0, 0);
return;
}
LedControlData led_control_data;
if (_led_controller.update(led_control_data) == 1) {
const uint8_t on = led_control_data.leds[0].brightness;
switch (led_control_data.leds[0].color) {
case led_control_s::COLOR_RED:
send_led_rgb(on, 0, 0);
break;
case led_control_s::COLOR_GREEN:
send_led_rgb(0, on, 0);
break;
case led_control_s::COLOR_BLUE:
send_led_rgb(0, 0, on);
break;
case led_control_s::COLOR_AMBER: // same as yellow
case led_control_s::COLOR_YELLOW:
send_led_rgb(on, on, 0);
break;
case led_control_s::COLOR_PURPLE:
send_led_rgb(on, 0, on);
break;
case led_control_s::COLOR_CYAN:
send_led_rgb(0, on, on);
break;
case led_control_s::COLOR_WHITE:
send_led_rgb(on, on, on);
break;
case led_control_s::COLOR_OFF:
default:
send_led_rgb(0, 0, 0);
break;
}
}
ScheduleDelayed(_led_controller.maximum_update_interval());
}
int
RGBLED_LP5562::send_led_rgb(uint8_t r, uint8_t g, uint8_t b)
{
uint8_t leds[3] = {b, g, r};
return write(B_PWM_ADDR, leds, sizeof(leds));
}
void
RGBLED_LP5562::print_usage()
{
PRINT_MODULE_DESCRIPTION(
R"DESCR_STR(
### Description
Driver for [LP5562](https://www.ti.com/product/LP5562) LED driver connected via I2C.
This used in some GPS modules by Holybro for [PX4 status notification](../getting_started/led_meanings.md)
The driver is included by default in firmware (KConfig key DRIVERS_LIGHTS_RGBLED_LP5562) and is always enabled.
)DESCR_STR");
PRINT_MODULE_USAGE_NAME("rgbled_lp5562", "driver");
PRINT_MODULE_USAGE_COMMAND("start");
PRINT_MODULE_USAGE_PARAMS_I2C_SPI_DRIVER(true, false);
PRINT_MODULE_USAGE_PARAMS_I2C_ADDRESS(I2C_ADDR);
PRINT_MODULE_USAGE_PARAM_FLOAT('u', 17.5f, 0.1f, 25.5f, "Current in mA", true);
PRINT_MODULE_USAGE_DEFAULT_COMMANDS();
}
extern "C" __EXPORT int rgbled_lp5562_main(int argc, char *argv[])
{
int ch;
using ThisDriver = RGBLED_LP5562;
BusCLIArguments cli{true, false};
cli.default_i2c_frequency = 100000;
cli.i2c_address = I2C_ADDR;
cli.custom1 = 175;
while ((ch = cli.getOpt(argc, argv, "u:")) != EOF) {
switch (ch) {
case 'u':
float v = atof(cli.optArg());
if (v >= 0.1f && v <= 25.5f) {
cli.custom1 = ((uint8_t)(v * 10.f));
} else {
PX4_ERR("current out of range");
return -1;
}
break;
}
}
const char *verb = cli.optArg();
if (!verb) {
ThisDriver::print_usage();
return -1;
}
BusInstanceIterator iterator(MODULE_NAME, cli, DRV_LED_DEVTYPE_RGBLED_LP5562);
if (!strcmp(verb, "start")) {
return ThisDriver::module_start(cli, iterator);
}
if (!strcmp(verb, "stop")) {
return ThisDriver::module_stop(iterator);
}
if (!strcmp(verb, "status")) {
return ThisDriver::module_status(iterator);
}
ThisDriver::print_usage();
return -1;
}

View File

@ -4,7 +4,7 @@ actuator_output:
- param_prefix: PWM_MAIN
channel_label: 'Channel'
standard_params:
disarmed: { min: 800, max: 2200, default: 900 }
disarmed: { min: 800, max: 2200, default: 1000 }
min: { min: 800, max: 1400, default: 1000 }
max: { min: 1600, max: 2200, default: 2000 }
failsafe: { min: 800, max: 2200 }

View File

@ -4,7 +4,7 @@ actuator_output:
- param_prefix: PCA9685
channel_label: 'Channel'
standard_params:
disarmed: { min: 800, max: 2200, default: 900 }
disarmed: { min: 800, max: 2200, default: 1000 }
min: { min: 800, max: 1400, default: 1000 }
max: { min: 1600, max: 2200, default: 2000 }
failsafe: { min: 800, max: 2200 }

View File

@ -218,17 +218,18 @@ void PWMOut::update_params()
updateParams();
// Automatically set the PWM rate and disarmed value when a channel is first set to a servo
// Automatically set PWM configuration when a channel is first assigned
if (!_first_update_cycle) {
for (size_t i = 0; i < _num_outputs; i++) {
if ((previously_set_functions & (1u << i)) == 0 && _mixing_output.functionParamHandle(i) != PARAM_INVALID) {
int32_t output_function;
if (param_get(_mixing_output.functionParamHandle(i), &output_function) == 0
&& output_function >= (int)OutputFunction::Servo1
if (param_get(_mixing_output.functionParamHandle(i), &output_function) == 0) {
// Servos need PWM rate 50Hz and disramed value 1500us
if (output_function >= (int)OutputFunction::Servo1
&& output_function <= (int)OutputFunction::ServoMax) { // Function got set to a servo
int32_t val = 1500;
PX4_INFO("Setting disarmed to %i for channel %i", (int) val, i);
PX4_INFO("Setting channel %i disarmed to %i", (int) val, i);
param_set(_mixing_output.disarmedParamHandle(i), &val);
// If the whole timer group was not set previously, then set the pwm rate to 50 Hz
@ -255,6 +256,18 @@ void PWMOut::update_params()
}
}
}
// Motors need a minimum value that idles the motor and have a deadzone at the top of the range
if (output_function >= (int)OutputFunction::Motor1
&& output_function <= (int)OutputFunction::MotorMax) { // Function got set to a motor
int32_t val = 1100;
PX4_INFO("Setting channel %i minimum to %i", (int) val, i);
param_set(_mixing_output.minParamHandle(i), &val);
val = 1900;
PX4_INFO("Setting channel %i maximum to %i", (int) val, i);
param_set(_mixing_output.maxParamHandle(i), &val);
}
}
}
}
}

View File

@ -5,7 +5,7 @@ actuator_output:
param_prefix: '${PWM_MAIN_OR_AUX}'
channel_labels: ['${PWM_MAIN_OR_AUX}', '${PWM_MAIN_OR_AUX_CAP}']
standard_params:
disarmed: { min: 800, max: 2200, default: 900 }
disarmed: { min: 800, max: 2200, default: 1000 }
min: { min: 800, max: 1400, default: 1000 }
max: { min: 1600, max: 2200, default: 2000 }
failsafe: { min: 800, max: 2200 }

View File

@ -7,7 +7,7 @@ actuator_output:
channel_label_module_name_prefix: false
timer_config_file: "boards/px4/io-v2/src/timer_config.cpp"
standard_params:
disarmed: { min: 800, max: 2200, default: 900 }
disarmed: { min: 800, max: 2200, default: 1000 }
min: { min: 800, max: 1400, default: 1000 }
max: { min: 1600, max: 2200, default: 2000 }
failsafe: { min: 800, max: 2200 }

View File

@ -702,11 +702,11 @@ void PX4IO::update_params()
if ((previously_set_functions & (1u << i)) == 0 && _mixing_output.functionParamHandle(i) != PARAM_INVALID) {
int32_t output_function;
if (param_get(_mixing_output.functionParamHandle(i), &output_function) == 0
&& output_function >= (int)OutputFunction::Servo1
if (param_get(_mixing_output.functionParamHandle(i), &output_function) == 0) {
if (output_function >= (int)OutputFunction::Servo1
&& output_function <= (int)OutputFunction::ServoMax) { // Function got set to a servo
int32_t val = 1500;
PX4_INFO("Setting disarmed to %i for channel %i", (int) val, i);
PX4_INFO("Setting channel %i disarmed to %i", (int) val, i);
param_set(_mixing_output.disarmedParamHandle(i), &val);
// If the whole timer group was not set previously, then set the pwm rate to 50 Hz
@ -733,6 +733,18 @@ void PX4IO::update_params()
}
}
}
// Motors need a minimum value that idles the motor
if (output_function >= (int)OutputFunction::Motor1
&& output_function <= (int)OutputFunction::MotorMax) { // Function got set to a motor
int32_t val = 1100;
PX4_INFO("Setting channel %i minimum to %i", (int) val, i);
param_set(_mixing_output.minParamHandle(i), &val);
val = 1900;
PX4_INFO("Setting channel %i maximum to %i", (int) val, i);
param_set(_mixing_output.maxParamHandle(i), &val);
}
}
}
}
}

View File

@ -467,29 +467,61 @@ void UavcanGnssBridge::update()
// to work.
void UavcanGnssBridge::handleInjectDataTopic()
{
// Limit maximum number of GPS injections to 6 since usually
// We don't want to call copy again further down if we have already done a
// copy in the selection process.
bool already_copied = false;
gps_inject_data_s msg;
// If there has not been a valid RTCM message for a while, try to switch to a different RTCM link
if ((hrt_absolute_time() - _last_rtcm_injection_time) > 5_s) {
for (int instance = 0; instance < _orb_inject_data_sub.size(); instance++) {
const bool exists = _orb_inject_data_sub[instance].advertised();
if (exists) {
if (_orb_inject_data_sub[instance].copy(&msg)) {
if ((hrt_absolute_time() - msg.timestamp) < 5_s) {
// Remember that we already did a copy on this instance.
already_copied = true;
_selected_rtcm_instance = instance;
break;
}
}
}
}
}
bool updated = already_copied;
// Limit maximum number of GPS injections to 8 since usually
// GPS injections should consist of 1-4 packets (GPS, Glonass, BeiDou, Galileo).
// Looking at 6 packets thus guarantees, that at least a full injection
// Looking at 8 packets thus guarantees, that at least a full injection
// data set is evaluated.
static constexpr size_t MAX_NUM_INJECTIONS = 6;
// Moving Base reuires a higher rate, so we allow up to 8 packets.
const size_t max_num_injections = gps_inject_data_s::ORB_QUEUE_LENGTH;
size_t num_injections = 0;
gps_inject_data_s gps_inject_data;
while ((num_injections <= MAX_NUM_INJECTIONS) && _gps_inject_data_sub.update(&gps_inject_data)) {
do {
if (updated) {
num_injections++;
// Write the message to the gps device. Note that the message could be fragmented.
// But as we don't write anywhere else to the device during operation, we don't
// need to assemble the message first.
if (_publish_rtcm_stream) {
PublishRTCMStream(gps_inject_data.data, gps_inject_data.len);
PublishRTCMStream(msg.data, msg.len);
}
if (_publish_moving_baseline_data) {
PublishMovingBaselineData(gps_inject_data.data, gps_inject_data.len);
PublishMovingBaselineData(msg.data, msg.len);
}
num_injections++;
_last_rtcm_injection_time = hrt_absolute_time();
}
updated = _orb_inject_data_sub[_selected_rtcm_instance].update(&msg);
} while (updated && num_injections < max_num_injections);
}
bool UavcanGnssBridge::PublishRTCMStream(const uint8_t *const data, const size_t data_len)

View File

@ -45,6 +45,7 @@
#pragma once
#include <uORB/Subscription.hpp>
#include <uORB/SubscriptionMultiArray.hpp>
#include <uORB/PublicationMulti.hpp>
#include <uORB/topics/sensor_gps.h>
#include <uORB/topics/gps_inject_data.h>
@ -123,7 +124,9 @@ private:
float _last_gnss_auxiliary_hdop{0.0f};
float _last_gnss_auxiliary_vdop{0.0f};
uORB::Subscription _gps_inject_data_sub{ORB_ID(gps_inject_data)};
uORB::SubscriptionMultiArray<gps_inject_data_s, gps_inject_data_s::MAX_INSTANCES> _orb_inject_data_sub{ORB_ID::gps_inject_data};
hrt_abstime _last_rtcm_injection_time{0}; ///< time of last rtcm injection
uint8_t _selected_rtcm_instance{0}; ///< uorb instance that is being used for RTCM corrections
bool _system_clock_set{false}; ///< Have we set the system clock at least once from GNSS data?

View File

@ -4,12 +4,11 @@ serial_config:
port_config_param:
name: UWB_PORT_CFG
group: UWB
default: ""
default: "TEL2"
parameters:
- group: UWB
definitions:
UWB_INIT_OFF_X:
description:
short: UWB sensor X offset in body frame
@ -32,7 +31,7 @@ parameters:
UWB_INIT_OFF_Z:
description:
short: UWB sensor Y offset in body frame
short: UWB sensor Z offset in body frame
long: UWB sensor positioning in relation to Drone in NED. Z offset.
type: float
unit: m
@ -40,14 +39,52 @@ parameters:
increment: 0.01
default: 0.00
UWB_INIT_OFF_YAW:
UWB_SENS_ROT:
description:
short: UWB sensor YAW offset in body frame
long: UWB sensor positioning in relation to Drone in NED. Yaw rotation in relation to direction of FMU.
type: float
unit: deg
decimal: 1
increment: 0.1
default: 0.00
short: UWB sensor orientation
long: The orientation of the sensor relative to the forward direction of the body frame. Look up table in src/lib/conversion/rotation.h
Default position is the antannaes downward facing, UWB board parallel with body frame.
type: enum
values:
0: ROTATION_NONE
1: ROTATION_YAW_45
2: ROTATION_YAW_90
3: ROTATION_YAW_135
4: ROTATION_YAW_180
5: ROTATION_YAW_225
6: ROTATION_YAW_270
7: ROTATION_YAW_315
8: ROTATION_ROLL_180
9: ROTATION_ROLL_180_YAW_45
10: ROTATION_ROLL_180_YAW_90
11: ROTATION_ROLL_180_YAW_135
12: ROTATION_PITCH_180
13: ROTATION_ROLL_180_YAW_225
14: ROTATION_ROLL_180_YAW_270
15: ROTATION_ROLL_180_YAW_315
16: ROTATION_ROLL_90
17: ROTATION_ROLL_90_YAW_45
18: ROTATION_ROLL_90_YAW_90
19: ROTATION_ROLL_90_YAW_135
20: ROTATION_ROLL_270
21: ROTATION_ROLL_270_YAW_45
22: ROTATION_ROLL_270_YAW_90
23: ROTATION_ROLL_270_YAW_135
24: ROTATION_PITCH_90
25: ROTATION_PITCH_270
26: ROTATION_PITCH_180_YAW_90
27: ROTATION_PITCH_180_YAW_270
28: ROTATION_ROLL_90_PITCH_90
29: ROTATION_ROLL_180_PITCH_90
30: ROTATION_ROLL_270_PITCH_90
31: ROTATION_ROLL_90_PITCH_180
32: ROTATION_ROLL_270_PITCH_180
33: ROTATION_ROLL_90_PITCH_270
34: ROTATION_ROLL_180_PITCH_270
35: ROTATION_ROLL_270_PITCH_270
36: ROTATION_ROLL_90_PITCH_180_YAW_90
37: ROTATION_ROLL_90_YAW_270
38: ROTATION_ROLL_90_PITCH_68_YAW_293
39: ROTATION_PITCH_315
40: ROTATION_ROLL_90_PITCH_315
default: 0

View File

@ -1,6 +1,6 @@
/****************************************************************************
*
* Copyright (c) 2020-2022 PX4 Development Team. All rights reserved.
* Copyright (c) 2020-2023 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@ -63,128 +63,130 @@
// The default baudrate of the uwb_sr150 module before configuration
#define DEFAULT_BAUD B115200
const uint8_t CMD_RANGING_STOP[UWB_CMD_LEN ] = {UWB_CMD, 0x00, 0x02, UWB_DRONE_CTL, UWB_CMD_STOP};
const uint8_t CMD_RANGING_START[UWB_CMD_LEN ] = {UWB_CMD, 0x00, 0x02, UWB_DRONE_CTL, UWB_CMD_START};
const uint8_t CMD_APP_START[UWB_CMD_LEN ] = {0x01, 0x00, 0x02, UWB_APP_START, UWB_PRECNAV_APP};
const uint8_t CMD_APP_STOP[0x04 ] = {0x01, 0x00, 0x01, UWB_APP_STOP};
extern "C" __EXPORT int uwb_sr150_main(int argc, char *argv[]);
UWB_SR150::UWB_SR150(const char *device_name, speed_t baudrate, bool uwb_pos_debug):
UWB_SR150::UWB_SR150(const char *port):
ModuleParams(nullptr),
ScheduledWorkItem(MODULE_NAME, px4::serial_port_to_wq(port)),
_read_count_perf(perf_alloc(PC_COUNT, "uwb_sr150_count")),
_read_err_perf(perf_alloc(PC_COUNT, "uwb_sr150_err"))
{
_uwb_pos_debug = uwb_pos_debug;
// start serial port
_uart = open(device_name, O_RDWR | O_NOCTTY);
if (_uart < 0) { err(1, "could not open %s", device_name); }
int ret = 0;
struct termios uart_config {};
ret = tcgetattr(_uart, &uart_config);
if (ret < 0) { err(1, "failed to get attr"); }
uart_config.c_oflag &= ~ONLCR; // no CR for every LF
ret = cfsetispeed(&uart_config, baudrate);
if (ret < 0) { err(1, "failed to set input speed"); }
ret = cfsetospeed(&uart_config, baudrate);
if (ret < 0) { err(1, "failed to set output speed"); }
ret = tcsetattr(_uart, TCSANOW, &uart_config);
if (ret < 0) { err(1, "failed to set attr"); }
/* store port name */
strncpy(_port, port, sizeof(_port) - 1);
/* enforce null termination */
_port[sizeof(_port) - 1] = '\0';
}
UWB_SR150::~UWB_SR150()
{
printf("UWB: Ranging Stopped\t\n");
int written = write(_uart, &CMD_APP_STOP, sizeof(CMD_APP_STOP));
if (written < (int) sizeof(CMD_APP_STOP)) {
PX4_ERR("Only wrote %d bytes out of %d.", written, (int) sizeof(CMD_APP_STOP));
}
// stop{}; will be implemented when this is changed to a scheduled work task
perf_free(_read_err_perf);
perf_free(_read_count_perf);
close(_uart);
}
void UWB_SR150::run()
bool UWB_SR150::init()
{
// Subscribe to parameter_update message
parameters_update();
//TODO replace with BLE grid configuration
grid_info_read(&_uwb_grid_info.target_pos);
_uwb_grid_info.num_anchors = 4;
_uwb_grid_info.initator_time = hrt_absolute_time();
_uwb_grid_info.mac_mode = 0x00;
/* Grid Info Message*/
_uwb_grid.timestamp = hrt_absolute_time();
_uwb_grid.initator_time = _uwb_grid_info.initator_time;
_uwb_grid.num_anchors = _uwb_grid_info.num_anchors;
memcpy(&_uwb_grid.target_pos, &_uwb_grid_info.target_pos, sizeof(position_t) * 5); //write Grid positions
_uwb_grid_pub.publish(_uwb_grid);
/* Ranging Command */
int written = write(_uart, CMD_RANGING_START, UWB_CMD_LEN);
if (written < UWB_CMD_LEN) {
PX4_ERR("Only wrote %d bytes out of %d.", written, (int) sizeof(uint8_t) * UWB_CMD_LEN);
// execute Run() on every sensor_accel publication
if (!_sensor_uwb_sub.registerCallback()) {
PX4_ERR("callback registration failed");
return false;
}
while (!should_exit()) {
written = UWB_SR150::distance(); //evaluate Ranging Messages until Stop
// alternatively, Run on fixed interval
// ScheduleOnInterval(5000_us); // 2000 us interval, 200 Hz rate
return true;
}
if (!written) { printf("ERROR: Distance Failed"); }
// Automatic Stop. This should not be reachable
written = write(_uart, &CMD_RANGING_STOP, UWB_CMD_LEN);
if (written < (int) sizeof(CMD_RANGING_STOP)) {
PX4_ERR("Only wrote %d bytes out of %d.", written, (int) sizeof(CMD_RANGING_STOP));
}
}
void UWB_SR150::grid_info_read(position_t *grid)
void UWB_SR150::start()
{
//place holder, until UWB initiator can respond with Grid info
/* This Reads the position of each Anchor in the Grid.
Right now the Grid configuration is saved on the SD card.
In the future, we would like, that the Initiator responds with the Grid Information (Including Position). */
PX4_INFO("Reading UWB GRID from SD... \t\n");
FILE *file;
file = fopen(UWB_GRID_CONFIG, "r");
int bread = 0;
for (int i = 0; i < 5; i++) {
bread += fscanf(file, "%hd,%hd,%hd\n", &grid[i].x, &grid[i].y, &grid[i].z);
/* schedule a cycle to start things */
ScheduleNow();
}
if (bread == 5 * 3) {
PX4_INFO("GRID INFO READ! bytes read: %d \t\n", bread);
} else { //use UUID from Grid survey
PX4_INFO("GRID INFO Missing! bytes read: %d \t\n Using standrd Grid \t\n", bread);
position_t grid_setup[5] = {{0x0, 0x0, 0x0}, {(int16_t)0xff68, 0x0, 0x0a}, {0x99, 0x0, 0x0a}, {0x0, 0x96, 0x64}, {0x0, (int16_t)0xff6a, 0x63}};
memcpy(grid, &grid_setup, sizeof(grid_setup));
PX4_INFO("Insert \"uwb_grid_config.csv\" containing gridinfo in cm at \"/fs/microsd/etc/\".\t\n");
PX4_INFO("n + 1 Anchor Positions starting with Landing Target. Int16 Format: \"x,y,z\" \t\n");
void UWB_SR150::stop()
{
ScheduleClear();
}
fclose(file);
void UWB_SR150::Run()
{
if (should_exit()) {
ScheduleClear();
exit_and_cleanup();
return;
}
if (_uart < 0) {
/* open fd */
_uart = ::open(_port, O_RDWR | O_NOCTTY | O_NONBLOCK);
if (_uart < 0) {
PX4_ERR("open failed (%i)", errno);
return;
}
struct termios uart_config;
int termios_state;
/* fill the struct for the new configuration */
tcgetattr(_uart, &uart_config);
/* clear ONLCR flag (which appends a CR for every LF) */
uart_config.c_oflag &= ~ONLCR;
//TODO: should I keep this?
/* no parity, one stop bit */
uart_config.c_cflag &= ~(CSTOPB | PARENB);
unsigned speed = DEFAULT_BAUD;
/* set baud rate */
if ((termios_state = cfsetispeed(&uart_config, speed)) < 0) {
PX4_ERR("CFG: %d ISPD", termios_state);
}
if ((termios_state = cfsetospeed(&uart_config, speed)) < 0) {
PX4_ERR("CFG: %d OSPD", termios_state);
}
if ((termios_state = tcsetattr(_uart, TCSANOW, &uart_config)) < 0) {
PX4_ERR("baud %d ATTR", termios_state);
}
}
/* perform collection */
int collect_ret = collectData();
if (collect_ret == -EAGAIN) {
/* reschedule to grab the missing bits, time to transmit 8 bytes @ 9600 bps */
ScheduleDelayed(1042 * 8);
return;
}
if (OK != collect_ret) {
/* we know the sensor needs about four seconds to initialize */
if (hrt_absolute_time() > 5 * 1000 * 1000LL && _consecutive_fail_count < 5) {
PX4_ERR("collection error #%u", _consecutive_fail_count);
}
_consecutive_fail_count++;
/* restart the measurement state machine */
start();
return;
} else {
/* apparently success */
_consecutive_fail_count = 0;
}
}
int UWB_SR150::custom_command(int argc, char *argv[])
@ -214,43 +216,20 @@ $ uwb start -d /dev/ttyS2
PRINT_MODULE_USAGE_COMMAND("start");
PRINT_MODULE_USAGE_PARAM_STRING('d', nullptr, "<file:dev>", "Name of device for serial communication with UWB", false);
PRINT_MODULE_USAGE_PARAM_STRING('b', nullptr, "<int>", "Baudrate for serial communication", false);
PRINT_MODULE_USAGE_PARAM_STRING('p', nullptr, "<int>", "Position Debug: displays errors in Multilateration", false);
PRINT_MODULE_USAGE_COMMAND("stop");
PRINT_MODULE_USAGE_COMMAND("status");
return 0;
}
int UWB_SR150::task_spawn(int argc, char *argv[])
{
int task_id = px4_task_spawn_cmd(
"uwb_driver",
SCHED_DEFAULT,
SCHED_PRIORITY_DEFAULT,
2048,
&run_trampoline,
argv
);
if (task_id < 0) {
return -errno;
} else {
_task_id = task_id;
return 0;
}
}
UWB_SR150 *UWB_SR150::instantiate(int argc, char *argv[])
{
int ch;
int option_index = 1;
const char *option_arg;
const char *device_name = nullptr;
bool error_flag = false;
const char *device_name = UWB_DEFAULT_PORT;
int baudrate = 0;
bool uwb_pos_debug = false; // Display UWB position calculation debug Messages
while ((ch = px4_getopt(argc, argv, "d:b:p", &option_index, &option_arg)) != EOF) {
while ((ch = px4_getopt(argc, argv, "d:b", &option_index, &option_arg)) != EOF) {
switch (ch) {
case 'd':
device_name = option_arg;
@ -260,47 +239,54 @@ UWB_SR150 *UWB_SR150::instantiate(int argc, char *argv[])
px4_get_parameter_value(option_arg, baudrate);
break;
case 'p':
uwb_pos_debug = true;
break;
default:
PX4_WARN("Unrecognized flag: %c", ch);
error_flag = true;
break;
}
}
if (!error_flag && device_name == nullptr) {
print_usage("Device name not provided. Using default Device: TEL1:/dev/ttyS4 \n");
device_name = "TEL2";
error_flag = true;
}
UWB_SR150 *instance = new UWB_SR150(device_name);
if (!error_flag && baudrate == 0) {
printf("Baudrate not provided. Using default Baud: 115200 \n");
baudrate = B115200;
}
if (instance) {
_object.store(instance);
_task_id = task_id_is_work_queue;
if (!error_flag && uwb_pos_debug == true) {
printf("UWB Position algorithm Debugging \n");
}
instance->ScheduleOnInterval(5000_us);
if (error_flag) {
PX4_WARN("Failed to start UWB driver. \n");
return nullptr;
if (instance->init()) {
return PX4_OK;
}
} else {
PX4_INFO("Constructing UWB_SR150. Device: %s", device_name);
return new UWB_SR150(device_name, baudrate, uwb_pos_debug);
PX4_ERR("alloc failed");
}
delete instance;
_object.store(nullptr);
_task_id = -1;
return PX4_ERROR;
}
int uwb_sr150_main(int argc, char *argv[])
{
return UWB_SR150::main(argc, argv);
}
void UWB_SR150::parameters_update()
{
if (_parameter_update_sub.updated()) {
parameter_update_s param_update;
_parameter_update_sub.copy(&param_update);
// If any parameter updated, call updateParams() to check if
// this class attributes need updating (and do so).
updateParams();
}
}
int UWB_SR150::distance()
int UWB_SR150::collectData()
{
_uwb_init_offset_v3f = matrix::Vector3f(_uwb_init_off_x.get(), _uwb_init_off_y.get(),
_uwb_init_off_z.get()); //set offset at the start
uint8_t *buffer = (uint8_t *) &_distance_result_msg;
FD_ZERO(&_uart_set);
@ -350,366 +336,54 @@ int UWB_SR150::distance()
perf_count(_read_count_perf);
// All of the following criteria must be met for the message to be acceptable:
// - Size of message == sizeof(distance_msg_t) (51 bytes)
// - Size of message == sizeof(distance_msg_t) (36 bytes)
// - status == 0x00
// - Values of all 3 position measurements are reasonable
// (If one or more anchors is missed, then position might be an unreasonably large number.)
bool ok = (buffer_location == sizeof(distance_msg_t) && _distance_result_msg.stop == 0x1b); //||
//(buffer_location == sizeof(grid_msg_t) && _distance_result_msg.stop == 0x1b)
//);
bool ok = (buffer_location == sizeof(distance_msg_t) && _distance_result_msg.stop == 0x1b);
if (ok) {
/* Ranging Message*/
_uwb_distance.timestamp = hrt_absolute_time();
_uwb_distance.time_uwb_ms = _distance_result_msg.time_uwb_ms;
_uwb_distance.counter = _distance_result_msg.seq_ctr;
_uwb_distance.sessionid = _distance_result_msg.sessionId;
_uwb_distance.time_offset = _distance_result_msg.range_interval;
_sensor_uwb.timestamp = hrt_absolute_time();
for (int i = 0; i < 4; i++) {
_uwb_distance.anchor_distance[i] = _distance_result_msg.measurements[i].distance;
_uwb_distance.nlos[i] = _distance_result_msg.measurements[i].nLos;
_uwb_distance.aoafirst[i] = float(_distance_result_msg.measurements[i].aoaFirst) /
128; // Angle of Arrival has Format Q9.7; dividing by 2^7 results in the correct value
}
_sensor_uwb.sessionid = _distance_result_msg.sessionId;
_sensor_uwb.time_offset = _distance_result_msg.range_interval;
_sensor_uwb.counter = _distance_result_msg.seq_ctr;
_sensor_uwb.mac = _distance_result_msg.MAC;
// Algorithm goes here
UWB_POS_ERROR_CODES UWB_POS_ERROR = UWB_SR150::localization();
_sensor_uwb.mac_dest = _distance_result_msg.measurements.MAC;
_sensor_uwb.status = _distance_result_msg.measurements.status;
_sensor_uwb.nlos = _distance_result_msg.measurements.nLos;
_sensor_uwb.distance = double(_distance_result_msg.measurements.distance) / 100;
_uwb_distance.status = UWB_POS_ERROR;
if (UWB_OK == UWB_POS_ERROR) {
/*Angle of Arrival has Format Q9.7; dividing by 2^7 and negating results in the correct value*/
_sensor_uwb.aoa_azimuth_dev = - double(_distance_result_msg.measurements.aoa_azimuth) / 128;
_sensor_uwb.aoa_elevation_dev = - double(_distance_result_msg.measurements.aoa_elevation) / 128;
_sensor_uwb.aoa_azimuth_resp = - double(_distance_result_msg.measurements.aoa_dest_azimuth) / 128;
_sensor_uwb.aoa_elevation_resp = - double(_distance_result_msg.measurements.aoa_dest_elevation) / 128;
_uwb_distance.position[0] = _rel_pos(0);
_uwb_distance.position[1] = _rel_pos(1);
_uwb_distance.position[2] = _rel_pos(2);
/*Angle of Arrival has Format Q9.7; dividing by 2^7 and negating results in the correct value*/
_sensor_uwb.aoa_azimuth_fom = - double(_distance_result_msg.measurements.aoa_azimuth) / 128;
_sensor_uwb.aoa_elevation_fom = - double(_distance_result_msg.measurements.aoa_elevation) / 128;
_sensor_uwb.aoa_dest_azimuth_fom = - double(_distance_result_msg.measurements.aoa_dest_azimuth) / 128;
_sensor_uwb.aoa_dest_elevation_fom = - double(_distance_result_msg.measurements.aoa_dest_elevation) / 128;
/* Sensor physical offset*/ //for now we propagate the physical configuration via Uorb
_sensor_uwb.orientation = _sensor_rot.get();
_sensor_uwb.offset_x = _offset_x.get();
_sensor_uwb.offset_y = _offset_y.get();
_sensor_uwb.offset_z = _offset_z.get();
_sensor_uwb_pub.publish(_sensor_uwb);
} else {
//only print the error if debug is enabled
if (_uwb_pos_debug) {
switch (UWB_POS_ERROR) { //UWB POSITION ALGORItHM Errors
case UWB_ANC_BELOW_THREE:
PX4_INFO("UWB not enough anchors for doing localization");
break;
case UWB_LIN_DEP_FOR_THREE:
PX4_INFO("UWB localization: linear dependent with 3 Anchors");
break;
case UWB_ANC_ON_ONE_LEVEL:
PX4_INFO("UWB localization: Anchors are on a X,Y Plane and there are not enought Anchors");
break;
case UWB_LIN_DEP_FOR_FOUR:
PX4_INFO("UWB localization: linear dependent with four or more Anchors");
break;
case UWB_RANK_ZERO:
PX4_INFO("UWB localization: rank is zero");
break;
default:
PX4_INFO("UWB localization: Unknown failure in Position Algorithm");
break;
}
}
}
_uwb_distance_pub.publish(_uwb_distance);
} else {
//PX4_ERR("Read %d bytes instead of %d.", (int) buffer_location, (int) sizeof(distance_msg_t));
perf_count(_read_err_perf);
if (buffer_location == 0) {
PX4_WARN("UWB module is not responding.");
//TODO add retry Ranging Start Message. Sometimes the UWB devices Crashes. (Check Power)
}
}
return 1;
}
UWB_POS_ERROR_CODES UWB_SR150::localization()
{
// WIP
/******************************************************
****************** 3D Localization *******************
*****************************************************/
/*!@brief: This function calculates the 3D position of the initiator from the anchor distances and positions using least squared errors.
* The function expects more than 4 anchors. The used equation system looks like follows:\n
\verbatim
- -
| M_11 M_12 M_13 | x b[0]
| M_12 M_22 M_23 | * y = b[1]
| M_23 M_13 M_33 | z b[2]
- -
\endverbatim
* @param distances_cm_in_pt: Pointer to array that contains the distances to the anchors in cm (including invalid results)
* @param no_distances: Number of valid distances in distance array (it's not the size of the array)
* @param anchor_pos: Pointer to array that contains anchor positions in cm (including positions related to invalid results)
* @param no_anc_positions: Number of valid anchor positions in the position array (it's not the size of the array)
* @param position_result_pt: Pointer toposition. position_t variable that holds the result of this calculation
* @return: The function returns a status code. */
/* Algorithm used:
* Linear Least Sqaures to solve Multilateration
* with a Special case if there are only 3 Anchors.
* Output is the Coordinates of the Initiator in relation to Anchor 0 in NEU (North-East-Up) Framing
* In cm
*/
/* Resulting Position Vector*/
int64_t x_pos = 0;
int64_t y_pos = 0;
int64_t z_pos = 0;
/* Matrix components (3*3 Matrix resulting from least square error method) [cm^2] */
int64_t M_11 = 0;
int64_t M_12 = 0; // = M_21
int64_t M_13 = 0; // = M_31
int64_t M_22 = 0;
int64_t M_23 = 0; // = M_23
int64_t M_33 = 0;
/* Vector components (3*1 Vector resulting from least square error method) [cm^3] */
int64_t b[3] = {0};
/* Miscellaneous variables */
int64_t temp = 0;
int64_t temp2 = 0;
int64_t nominator = 0;
int64_t denominator = 0;
bool anchors_on_x_y_plane = true; // Is true, if all anchors are on the same height => x-y-plane
bool lin_dep = true; // All vectors are linear dependent, if this variable is true
uint8_t ind_y_indi =
0; //numberr of independet vectors // First anchor index, for which the second row entry of the matrix [(x_1 - x_0) (x_2 - x_0) ... ; (y_1 - x_0) (y_2 - x_0) ...] is non-zero => linear independent
/* Arrays for used distances and anchor positions (without rejected ones) */
uint8_t no_distances = _uwb_grid_info.num_anchors;
uint32_t distances_cm[no_distances];
position_t anchor_pos[no_distances]; //position in CM
uint8_t no_valid_distances = 0;
/* Reject invalid distances (including related anchor position) */
for (int i = 0; i < no_distances; i++) {
if (_distance_result_msg.measurements[i].distance != 0xFFFFu) {
//excludes any distance that is 0xFFFFU (int16 Maximum Value)
distances_cm[no_valid_distances] = _distance_result_msg.measurements[i].distance;
anchor_pos[no_valid_distances] = _uwb_grid_info.anchor_pos[i];
no_valid_distances++;
}
}
/* Check, if there are enough valid results for doing the localization at all */
if (no_valid_distances < 3) {
return UWB_ANC_BELOW_THREE;
}
/* Check, if anchors are on the same x-y plane */
for (int i = 1; i < no_valid_distances; i++) {
if (anchor_pos[i].z != anchor_pos[0].z) {
anchors_on_x_y_plane = false;
break;
}
}
/**** Check, if there are enough linear independent anchor positions ****/
/* Check, if the matrix |(x_1 - x_0) (x_2 - x_0) ... | has rank 2
* |(y_1 - y_0) (y_2 - y_0) ... | */
for (ind_y_indi = 2; ((ind_y_indi < no_valid_distances) && (lin_dep == true)); ind_y_indi++) {
temp = ((int64_t)anchor_pos[ind_y_indi].y - (int64_t)anchor_pos[0].y) * ((int64_t)anchor_pos[1].x -
(int64_t)anchor_pos[0].x);
temp2 = ((int64_t)anchor_pos[1].y - (int64_t)anchor_pos[0].y) * ((int64_t)anchor_pos[ind_y_indi].x -
(int64_t)anchor_pos[0].x);
if ((temp - temp2) != 0) {
lin_dep = false;
break;
}
}
/* Leave function, if rank is below 2 */
if (lin_dep == true) {
return UWB_LIN_DEP_FOR_THREE;
}
/* If the anchors are not on the same plane, three vectors must be independent => check */
if (!anchors_on_x_y_plane) {
/* Check, if there are enough valid results for doing the localization */
if (no_valid_distances < 4) {
return UWB_ANC_ON_ONE_LEVEL;
}
/* Check, if the matrix |(x_1 - x_0) (x_2 - x_0) (x_3 - x_0) ... | has rank 3 (Rank y, y already checked)
* |(y_1 - y_0) (y_2 - y_0) (y_3 - y_0) ... |
* |(z_1 - z_0) (z_2 - z_0) (z_3 - z_0) ... | */
lin_dep = true;
for (int i = 2; ((i < no_valid_distances) && (lin_dep == true)); i++) {
if (i != ind_y_indi) {
/* (x_1 - x_0)*[(y_2 - y_0)(z_n - z_0) - (y_n - y_0)(z_2 - z_0)] */
temp = ((int64_t)anchor_pos[ind_y_indi].y - (int64_t)anchor_pos[0].y) * ((int64_t)anchor_pos[i].z -
(int64_t)anchor_pos[0].z);
temp -= ((int64_t)anchor_pos[i].y - (int64_t)anchor_pos[0].y) * ((int64_t)anchor_pos[ind_y_indi].z -
(int64_t)anchor_pos[0].z);
temp2 = ((int64_t)anchor_pos[1].x - (int64_t)anchor_pos[0].x) * temp;
/* Add (x_2 - x_0)*[(y_n - y_0)(z_1 - z_0) - (y_1 - y_0)(z_n - z_0)] */
temp = ((int64_t)anchor_pos[i].y - (int64_t)anchor_pos[0].y) * ((int64_t)anchor_pos[1].z - (int64_t)anchor_pos[0].z);
temp -= ((int64_t)anchor_pos[1].y - (int64_t)anchor_pos[0].y) * ((int64_t)anchor_pos[i].z - (int64_t)anchor_pos[0].z);
temp2 += ((int64_t)anchor_pos[ind_y_indi].x - (int64_t)anchor_pos[0].x) * temp;
/* Add (x_n - x_0)*[(y_1 - y_0)(z_2 - z_0) - (y_2 - y_0)(z_1 - z_0)] */
temp = ((int64_t)anchor_pos[1].y - (int64_t)anchor_pos[0].y) * ((int64_t)anchor_pos[ind_y_indi].z -
(int64_t)anchor_pos[0].z);
temp -= ((int64_t)anchor_pos[ind_y_indi].y - (int64_t)anchor_pos[0].y) * ((int64_t)anchor_pos[1].z -
(int64_t)anchor_pos[0].z);
temp2 += ((int64_t)anchor_pos[i].x - (int64_t)anchor_pos[0].x) * temp;
if (temp2 != 0) { lin_dep = false; }
}
}
/* Leave function, if rank is below 3 */
if (lin_dep == true) {
return UWB_LIN_DEP_FOR_FOUR;
}
}
/************************************************** Algorithm ***********************************************************************/
/* Writing values resulting from least square error method (A_trans*A*x = A_trans*r; row 0 was used to remove x^2,y^2,z^2 entries => index starts at 1) */
for (int i = 1; i < no_valid_distances; i++) {
/* Matrix (needed to be multiplied with 2, afterwards) */
M_11 += sq((int64_t)(anchor_pos[i].x - anchor_pos[0].x));
M_12 += (int64_t)((int64_t)(anchor_pos[i].x - anchor_pos[0].x) * (int64_t)(anchor_pos[i].y - anchor_pos[0].y));
M_13 += (int64_t)((int64_t)(anchor_pos[i].x - anchor_pos[0].x) * (int64_t)(anchor_pos[i].z - anchor_pos[0].z));
M_22 += sq((int64_t)(anchor_pos[i].y - anchor_pos[0].y));
M_23 += (int64_t)((int64_t)(anchor_pos[i].y - anchor_pos[0].y) * (int64_t)(anchor_pos[i].z - anchor_pos[0].z));
M_33 += sq((int64_t)(anchor_pos[i].z - anchor_pos[0].z));
/* Vector */
temp = sq(distances_cm[0]) - sq(distances_cm[i])
+ sq(anchor_pos[i].x) + sq(anchor_pos[i].y)
+ sq(anchor_pos[i].z) - sq(anchor_pos[0].x)
- sq(anchor_pos[0].y) - sq(anchor_pos[0].z);
b[0] += (int64_t)((int64_t)(anchor_pos[i].x - anchor_pos[0].x) * temp);
b[1] += (int64_t)((int64_t)(anchor_pos[i].y - anchor_pos[0].y) * temp);
b[2] += (int64_t)((int64_t)(anchor_pos[i].z - anchor_pos[0].z) * temp);
}
M_11 = 2 * M_11;
M_12 = 2 * M_12;
M_13 = 2 * M_13;
M_22 = 2 * M_22;
M_23 = 2 * M_23;
M_33 = 2 * M_33;
/* Calculating the z-position, if calculation is possible (at least one anchor at z != 0) */
if (anchors_on_x_y_plane == false) {
nominator = b[0] * (M_12 * M_23 - M_13 * M_22) + b[1] * (M_12 * M_13 - M_11 * M_23) + b[2] *
(M_11 * M_22 - M_12 * M_12); // [cm^7]
denominator = M_11 * (M_33 * M_22 - M_23 * M_23) + 2 * M_12 * M_13 * M_23 - M_33 * M_12 * M_12 - M_22 * M_13 *
M_13; // [cm^6]
/* Check, if denominator is zero (Rank of matrix not high enough) */
if (denominator == 0) {
return UWB_RANK_ZERO;
}
z_pos = ((nominator * 10) / denominator + 5) / 10; // [cm]
}
/* Else prepare for different calculation approach (after x and y were calculated) */
else {
z_pos = 0;
}
/* Calculating the y-position */
nominator = b[1] * M_11 - b[0] * M_12 - (z_pos * (M_11 * M_23 - M_12 * M_13)); // [cm^5]
denominator = M_11 * M_22 - M_12 * M_12;// [cm^4]
/* Check, if denominator is zero (Rank of matrix not high enough) */
if (denominator == 0) {
return UWB_RANK_ZERO;
}
y_pos = ((nominator * 10) / denominator + 5) / 10; // [cm]
/* Calculating the x-position */
nominator = b[0] - z_pos * M_13 - y_pos * M_12; // [cm^3]
denominator = M_11; // [cm^2]
x_pos = ((nominator * 10) / denominator + 5) / 10;// [cm]
/* Calculate z-position form x and y coordinates, if z can't be determined by previous steps (All anchors at z_n = 0) */
if (anchors_on_x_y_plane == true) {
/* Calculate z-positon relative to the anchor grid's height */
for (int i = 0; i < no_distances; i++) {
/* z² = dis_meas_n² - (x - x_anc_n)² - (y - y_anc_n)² */
temp = (int64_t)((int64_t)pow(distances_cm[i], 2)
- (int64_t)pow((x_pos - (int64_t)anchor_pos[i].x), 2)
- (int64_t)pow((y_pos - (int64_t)anchor_pos[i].y), 2));
/* z² must be positive, else x and y must be wrong => calculate positive sqrt and sum up all calculated heights, if positive */
if (temp >= 0) {
z_pos += (int64_t)sqrt(temp);
} else {
z_pos = 0;
}
}
z_pos = z_pos / no_distances; // Divide sum by number of distances to get the average
/* Add height of the anchor grid's height */
z_pos += anchor_pos[0].z;
}
//Output is the Coordinates of the Initiator in relation to 0,0,0 in NEU (North-East-Up) Framing
// The end goal of this math is to get the position relative to the landing point in the NED frame.
_current_position_uwb_init = matrix::Vector3f(x_pos, y_pos, z_pos);
// Construct the rotation from the UWB_R4frame to the NWU frame.
// The UWB_SR150 frame is just NWU, rotated by some amount about the Z (up) axis. (Parameter Yaw offset)
// To get back to NWU, just rotate by negative this amount about Z.
_uwb_init_to_nwu = matrix::Dcmf(matrix::Eulerf(0.0f, 0.0f,
-(_uwb_init_off_yaw.get() * M_PI_F / 180.0f))); //
// The actual conversion:
// - Subtract _landing_point to get the position relative to the landing point, in UWB_R4 frame
// - Rotate by _rddrone_to_nwu to get into the NWU frame
// - Rotate by _nwu_to_ned to get into the NED frame
_current_position_ned = _nwu_to_ned * _uwb_init_to_nwu * _current_position_uwb_init;
// Now the position is the landing point relative to the vehicle.
// so the only thing left is to convert cm to Meters and to add the Initiator offset
_rel_pos = _current_position_ned / 100 + _uwb_init_offset_v3f;
// The UWB report contains the position of the vehicle relative to the landing point.
return UWB_OK;
}
int uwb_sr150_main(int argc, char *argv[])
{
return UWB_SR150::main(argc, argv);
}
void UWB_SR150::parameters_update()
{
if (_parameter_update_sub.updated()) {
parameter_update_s param_update;
_parameter_update_sub.copy(&param_update);
// If any parameter updated, call updateParams() to check if
// this class attributes need updating (and do so).
updateParams();
}
}

View File

@ -1,6 +1,6 @@
/****************************************************************************
*
* Copyright (c) 2020-2022 PX4 Development Team. All rights reserved.
* Copyright (c) 2020-2023 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@ -38,101 +38,63 @@
#include <poll.h>
#include <sys/select.h>
#include <sys/time.h>
#include <perf/perf_counter.h>
#include <lib/conversion/rotation.h>
#include <px4_platform_common/module_params.h>
#include <px4_platform_common/module.h>
#include <perf/perf_counter.h>
#include <px4_platform_common/px4_work_queue/ScheduledWorkItem.hpp>
#include <uORB/Publication.hpp>
#include <uORB/topics/landing_target_pose.h>
#include <uORB/topics/uwb_grid.h>
#include <uORB/topics/uwb_distance.h>
#include <uORB/topics/parameter_update.h>
#include <uORB/Subscription.hpp>
#include <uORB/SubscriptionCallback.hpp>
#include <uORB/SubscriptionInterval.hpp>
#include <uORB/topics/vehicle_attitude.h>
#include <uORB/topics/sensor_uwb.h>
#include <uORB/topics/parameter_update.h>
#include <matrix/math.hpp>
#include <matrix/Matrix.hpp>
#define UWB_DEFAULT_PORT "/dev/ttyS1"
using namespace time_literals;
#define UWB_CMD 0x8e
#define UWB_CMD_START 0x01
#define UWB_CMD_STOP 0x00
#define UWB_CMD_RANGING 0x0A
#define STOP_B 0x0A
#define UWB_PRECNAV_APP 0x04
#define UWB_APP_START 0x10
#define UWB_APP_STOP 0x11
#define UWB_SESSION_START 0x22
#define UWB_SESSION_STOP 0x23
#define UWB_RANGING_START 0x01
#define UWB_RANGING_STOP 0x00
#define UWB_DRONE_CTL 0x0A
#define UWB_CMD_LEN 0x05
#define UWB_CMD_DISTANCE_LEN 0x21
#define UWB_MAC_MODE 2
#define MAX_ANCHORS 12
#define UWB_GRID_CONFIG "/fs/microsd/etc/uwb_grid_config.csv"
typedef struct { //needs higher accuracy?
float lat, lon, alt, yaw; //offset to true North
} gps_pos_t;
typedef struct {
int16_t x, y, z; //axis in cm
} position_t; // Position of a device or target in 3D space
enum UWB_POS_ERROR_CODES {
UWB_OK,
UWB_ANC_BELOW_THREE,
UWB_LIN_DEP_FOR_THREE,
UWB_ANC_ON_ONE_LEVEL,
UWB_LIN_DEP_FOR_FOUR,
UWB_RANK_ZERO
};
typedef struct {
uint8_t MAC[2]; // MAC Adress of UWB device
uint16_t MAC; // MAC address of UWB device
uint8_t status; // Status of Measurement
uint16_t distance; // Distance in cm
uint8_t nLos; // line of sight y/n
uint16_t aoaFirst; // Angle of Arrival of incoming msg
int16_t aoa_azimuth; // AOA of incoming msg for Azimuth antenna pairing
int16_t aoa_elevation; // AOA of incoming msg for Altitude antenna pairing
int16_t aoa_dest_azimuth; // AOA destination Azimuth
int16_t aoa_dest_elevation; // AOA destination elevation
uint8_t aoa_azimuth_FOM; // AOA Azimuth FOM
uint8_t aoa_elevation_FOM; // AOA Elevation FOM
uint8_t aoa_dest_azimuth_FOM; // AOA Azimuth FOM
uint8_t aoa_dest_elevation_FOM; // AOA Elevation FOM
} __attribute__((packed)) UWB_range_meas_t;
typedef struct {
uint32_t initator_time; //timestamp of init
uint32_t sessionId; // Session ID of UWB session
uint8_t num_anchors; //number of anchors
gps_pos_t target_gps; //GPS position of Landing Point
uint8_t mac_mode; // MAC adress mode, either 2 Byte or 8 Byte
uint8_t MAC[UWB_MAC_MODE][MAX_ANCHORS];
position_t target_pos; //target position
position_t anchor_pos[MAX_ANCHORS]; // Position of each anchor
uint8_t stop; // Should be 27
} grid_msg_t;
typedef struct {
uint8_t cmd; // Should be 0x8E for distance result message
uint16_t len; // Should be 0x30 for distance result message
uint32_t time_uwb_ms; // Timestamp of UWB device in ms
uint32_t seq_ctr; // Number of Ranges since last Start of Ranging
uint32_t sessionId; // Session ID of UWB session
uint32_t range_interval; // Time between ranging rounds
uint8_t mac_mode; // MAC adress mode, either 2 Byte or 8 Byte
uint8_t no_measurements; // MAC adress mode, either 2 Byte or 8 Byte
UWB_range_meas_t measurements[4]; //Raw anchor_distance distances in CM 2*9
uint16_t MAC; // MAC address of UWB device
UWB_range_meas_t measurements; //Raw anchor_distance distances in CM 2*9
uint8_t stop; // Should be 0x1B
} __attribute__((packed)) distance_msg_t;
class UWB_SR150 : public ModuleBase<UWB_SR150>, public ModuleParams
class UWB_SR150 : public ModuleBase<UWB_SR150>, public ModuleParams, public px4::ScheduledWorkItem
{
public:
UWB_SR150(const char *device_name, speed_t baudrate, bool uwb_pos_debug);
UWB_SR150(const char *port);
~UWB_SR150();
/**
* @see ModuleBase::task_spawn
*/
static int task_spawn(int argc, char *argv[]);
/**
* @see ModuleBase::custom_command
*/
@ -143,67 +105,51 @@ public:
*/
static int print_usage(const char *reason = nullptr);
/**
* @see ModuleBase::Multilateration
*/
UWB_POS_ERROR_CODES localization();
bool init();
/**
* @see ModuleBase::Distance Result
*/
int distance();
void start();
/**
* @see ModuleBase::task_spawn
*/
static int task_spawn(int argc, char *argv[]);
void stop();
static UWB_SR150 *instantiate(int argc, char *argv[]);
void run() override;
int collectData();
private:
static constexpr int64_t sq(int64_t x) { return x * x; }
void parameters_update();
void grid_info_read(position_t *grid);
void Run() override;
DEFINE_PARAMETERS(
(ParamFloat<px4::params::UWB_INIT_OFF_X>) _uwb_init_off_x,
(ParamFloat<px4::params::UWB_INIT_OFF_Y>) _uwb_init_off_y,
(ParamFloat<px4::params::UWB_INIT_OFF_Z>) _uwb_init_off_z,
(ParamFloat<px4::params::UWB_INIT_OFF_YAW>) _uwb_init_off_yaw
)
// Publications
uORB::Publication<sensor_uwb_s> _sensor_uwb_pub{ORB_ID(sensor_uwb)};
// Subscriptions
uORB::SubscriptionCallbackWorkItem _sensor_uwb_sub{this, ORB_ID(sensor_uwb)};
uORB::SubscriptionInterval _parameter_update_sub{ORB_ID(parameter_update), 1_s};
int _uart;
fd_set _uart_set;
struct timeval _uart_timeout {};
bool _uwb_pos_debug;
uORB::Publication<uwb_grid_s> _uwb_grid_pub{ORB_ID(uwb_grid)};
uwb_grid_s _uwb_grid{};
uORB::Publication<uwb_distance_s> _uwb_distance_pub{ORB_ID(uwb_distance)};
uwb_distance_s _uwb_distance{};
uORB::Publication<landing_target_pose_s> _landing_target_pub{ORB_ID(landing_target_pose)};
landing_target_pose_s _landing_target{};
grid_msg_t _uwb_grid_info{};
distance_msg_t _distance_result_msg{};
matrix::Vector3f _rel_pos;
matrix::Dcmf _uwb_init_to_nwu;
matrix::Dcmf _nwu_to_ned{matrix::Eulerf(M_PI_F, 0.0f, 0.0f)};
matrix::Vector3f _current_position_uwb_init;
matrix::Vector3f _current_position_ned;
matrix::Vector3f _uwb_init_offset_v3f;
// Parameters
DEFINE_PARAMETERS(
(ParamInt<px4::params::UWB_PORT_CFG>) _uwb_port_cfg,
(ParamFloat<px4::params::UWB_INIT_OFF_X>) _offset_x,
(ParamFloat<px4::params::UWB_INIT_OFF_Y>) _offset_y,
(ParamFloat<px4::params::UWB_INIT_OFF_Z>) _offset_z,
(ParamInt<px4::params::UWB_SENS_ROT>) _sensor_rot
)
// Performance (perf) counters
perf_counter_t _read_count_perf;
perf_counter_t _read_err_perf;
};
sensor_uwb_s _sensor_uwb{};
char _port[20] {};
hrt_abstime param_timestamp{0};
int _uart{-1};
fd_set _uart_set;
struct timeval _uart_timeout {};
unsigned _consecutive_fail_count;
int _interval{100000};
distance_msg_t _distance_result_msg{};
};
#endif //PX4_RDDRONE_H

View File

@ -75,7 +75,7 @@ void ActuatorTest::update(int num_outputs, float thrust_curve)
float value = actuator_test.value;
// handle motors
if (actuator_test.function >= (int)OutputFunction::Motor1 && actuator_test.function <= (int)OutputFunction::MotorMax) {
if ((int)OutputFunction::Motor1 <= actuator_test.function && actuator_test.function <= (int)OutputFunction::MotorMax) {
actuator_motors_s motors;
motors.reversible_flags = 0;
_actuator_motors_sub.copy(&motors);
@ -84,7 +84,7 @@ void ActuatorTest::update(int num_outputs, float thrust_curve)
}
// handle servos: add trim
if (actuator_test.function >= (int)OutputFunction::Servo1 && actuator_test.function <= (int)OutputFunction::ServoMax) {
if ((int)OutputFunction::Servo1 <= actuator_test.function && actuator_test.function <= (int)OutputFunction::ServoMax) {
actuator_servos_trim_s trim{};
_actuator_servos_trim_sub.copy(&trim);
int idx = actuator_test.function - (int)OutputFunction::Servo1;

View File

@ -490,6 +490,24 @@ MixingOutput::limitAndUpdateOutputs(float outputs[MAX_ACTUATORS], bool has_updat
output_limit_calc(_throttle_armed || _actuator_test.inTestMode(), _max_num_outputs, outputs);
}
// We must calibrate the PWM and Oneshot ESCs to a consistent range of 1000-2000us (gets mapped to 125-250us for Oneshot)
// Doing so makes calibrations consistent among different configurations and hence PWM minimum and maximum have a consistent effect
// hence the defaults for these parameters also make most setups work out of the box
if (_armed.in_esc_calibration_mode) {
static constexpr uint16_t PWM_CALIBRATION_LOW = 1000;
static constexpr uint16_t PWM_CALIBRATION_HIGH = 2000;
for (int i = 0; i < _max_num_outputs; i++) {
if (_current_output_value[i] == _min_value[i]) {
_current_output_value[i] = PWM_CALIBRATION_LOW;
}
if (_current_output_value[i] == _max_value[i]) {
_current_output_value[i] = PWM_CALIBRATION_HIGH;
}
}
}
/* now return the outputs to the driver */
if (_interface.updateOutputs(stop_motors, _current_output_value, _max_num_outputs, has_updates)) {
actuator_outputs_s actuator_outputs{};

View File

@ -179,6 +179,8 @@ public:
param_t functionParamHandle(int index) const { return _param_handles[index].function; }
param_t disarmedParamHandle(int index) const { return _param_handles[index].disarmed; }
param_t minParamHandle(int index) const { return _param_handles[index].min; }
param_t maxParamHandle(int index) const { return _param_handles[index].max; }
/**
* Returns the actual failsafe value taking into account the assigned function

View File

@ -47,13 +47,27 @@ void RateControl::setGains(const Vector3f &P, const Vector3f &I, const Vector3f
_gain_d = D;
}
void RateControl::setSaturationStatus(const Vector<bool, 3> &saturation_positive,
const Vector<bool, 3> &saturation_negative)
void RateControl::setSaturationStatus(const Vector3<bool> &saturation_positive,
const Vector3<bool> &saturation_negative)
{
_control_allocator_saturation_positive = saturation_positive;
_control_allocator_saturation_negative = saturation_negative;
}
void RateControl::setPositiveSaturationFlag(size_t axis, bool is_saturated)
{
if (axis < 3) {
_control_allocator_saturation_positive(axis) = is_saturated;
}
}
void RateControl::setNegativeSaturationFlag(size_t axis, bool is_saturated)
{
if (axis < 3) {
_control_allocator_saturation_negative(axis) = is_saturated;
}
}
Vector3f RateControl::update(const Vector3f &rate, const Vector3f &rate_sp, const Vector3f &angular_accel,
const float dt, const bool landed)
{

View File

@ -75,8 +75,16 @@ public:
* Set saturation status
* @param control saturation vector from control allocator
*/
void setSaturationStatus(const matrix::Vector<bool, 3> &saturation_positive,
const matrix::Vector<bool, 3> &saturation_negative);
void setSaturationStatus(const matrix::Vector3<bool> &saturation_positive,
const matrix::Vector3<bool> &saturation_negative);
/**
* Set individual saturation flags
* @param axis 0 roll, 1 pitch, 2 yaw
* @param is_saturated value to update the flag with
*/
void setPositiveSaturationFlag(size_t axis, bool is_saturated);
void setNegativeSaturationFlag(size_t axis, bool is_saturated);
/**
* Run one control loop cycle calculation

View File

@ -70,7 +70,7 @@ void Magnetometer::set_device_id(uint32_t device_id)
bool Magnetometer::set_offset(const Vector3f &offset)
{
if (Vector3f(_offset - offset).longerThan(0.01f)) {
if (Vector3f(_offset - offset).longerThan(0.005f)) {
if (offset.isAllFinite()) {
_offset = offset;
_calibration_count++;

View File

@ -50,8 +50,8 @@
* copying them using the GCS.
*
* @group Radio Calibration
* @min -0.25
* @max 0.25
* @min -0.5
* @max 0.5
* @decimal 2
* @increment 0.01
*/
@ -66,8 +66,8 @@ PARAM_DEFINE_FLOAT(TRIM_ROLL, 0.0f);
* copying them using the GCS.
*
* @group Radio Calibration
* @min -0.25
* @max 0.25
* @min -0.5
* @max 0.5
* @decimal 2
* @increment 0.01
*/
@ -82,8 +82,8 @@ PARAM_DEFINE_FLOAT(TRIM_PITCH, 0.0f);
* copying them using the GCS.
*
* @group Radio Calibration
* @min -0.25
* @max 0.25
* @min -0.5
* @max 0.5
* @decimal 2
* @increment 0.01
*/

View File

@ -58,18 +58,19 @@ using namespace time_literals;
bool check_battery_disconnected(orb_advert_t *mavlink_log_pub)
{
uORB::SubscriptionData<battery_status_s> batt_sub{ORB_ID(battery_status)};
const battery_status_s &battery = batt_sub.get();
batt_sub.update();
uORB::SubscriptionData<battery_status_s> battery_status_sub{ORB_ID(battery_status)};
battery_status_sub.update();
if (battery.timestamp == 0) {
calibration_log_critical(mavlink_log_pub, CAL_QGC_FAILED_MSG, "battery unavailable");
const bool recent_battery_measurement = hrt_absolute_time() < (battery_status_sub.get().timestamp + 1_s);
if (!recent_battery_measurement) {
// We have to send this message for now because "battery unavailable" gets ignored by QGC
calibration_log_critical(mavlink_log_pub, CAL_QGC_FAILED_MSG, "Disconnect battery and try again");
return false;
}
// Make sure battery is disconnected
// battery is not connected if the connected flag is not set and we have a recent battery measurement
if (!battery.connected && (hrt_elapsed_time(&battery.timestamp) < 500_ms)) {
// Make sure battery is reported to be disconnected
if (recent_battery_measurement && !battery_status_sub.get().connected) {
return true;
}
@ -93,66 +94,80 @@ static void set_motor_actuators(uORB::Publication<actuator_test_s> &publisher, f
int do_esc_calibration(orb_advert_t *mavlink_log_pub)
{
calibration_log_info(mavlink_log_pub, CAL_QGC_STARTED_MSG, "esc");
// 1 Initialization
bool calibration_failed = false;
int return_code = PX4_OK;
uORB::Publication<actuator_test_s> actuator_test_pub{ORB_ID(actuator_test)};
// since we publish multiple at once, make sure the output driver subscribes before we publish
actuator_test_pub.advertise();
px4_usleep(10000);
// set motors to high
uORB::SubscriptionData<battery_status_s> battery_status_sub{ORB_ID(battery_status)};
battery_status_sub.update();
const bool battery_connected_before_calibration = battery_status_sub.get().connected;
const float current_before_calibration = battery_status_sub.get().current_a;
calibration_log_info(mavlink_log_pub, CAL_QGC_STARTED_MSG, "esc");
px4_usleep(10_ms);
// 2 Set motors to high
set_motor_actuators(actuator_test_pub, 1.f, false);
calibration_log_info(mavlink_log_pub, "[cal] Connect battery now");
uORB::SubscriptionData<battery_status_s> batt_sub{ORB_ID(battery_status)};
const battery_status_s &battery = batt_sub.get();
batt_sub.update();
bool batt_connected = battery.connected;
hrt_abstime timeout_start = hrt_absolute_time();
// 3 Wait for user to connect power
while (true) {
// We are either waiting for the user to connect the battery. Or we are waiting to let the PWM
// sit high.
static constexpr hrt_abstime battery_connect_wait_timeout{20_s};
static constexpr hrt_abstime pwm_high_timeout{3_s};
hrt_abstime timeout_wait = batt_connected ? pwm_high_timeout : battery_connect_wait_timeout;
hrt_abstime now = hrt_absolute_time();
battery_status_sub.update();
if (hrt_elapsed_time(&timeout_start) > timeout_wait) {
if (!batt_connected) {
calibration_log_critical(mavlink_log_pub, CAL_QGC_FAILED_MSG, "Timeout waiting for battery");
return_code = PX4_ERROR;
}
// PWM was high long enough
if (now > (timeout_start + 1_s) && (battery_status_sub.get().current_a > current_before_calibration + 1.f)) {
// Safety termination, current rises immediately, user didn't unplug power before
calibration_failed = true;
break;
}
if (!batt_connected) {
if (batt_sub.update()) {
if (battery.connected) {
// Battery is connected, signal to user and start waiting again
batt_connected = true;
timeout_start = hrt_absolute_time();
if (!battery_connected_before_calibration && battery_status_sub.get().connected) {
// Battery connection detected we can go to the next step immediately
break;
}
if (now > (timeout_start + 6_s)) {
// Timeout, we continue since maybe the battery cannot be detected properly
// If we abort here and the ESCs are infact connected and started calibrating
// they will measure the disarmed value as the lower limit instead of the fixed 1000us
break;
}
px4_usleep(50_ms);
}
// 4 Wait for ESCs to measure high signal
if (!calibration_failed) {
calibration_log_info(mavlink_log_pub, "[cal] Battery connected");
}
}
px4_usleep(3_s);
}
px4_usleep(50000);
}
if (return_code == PX4_OK) {
// set motors to low
// 5 Set motors to low
if (!calibration_failed) {
set_motor_actuators(actuator_test_pub, 0.f, false);
px4_usleep(4000000);
}
// release control
// 6 Wait for ESCs to measure low signal
if (!calibration_failed) {
px4_usleep(5_s);
}
// 7 release control
set_motor_actuators(actuator_test_pub, 0.f, true);
calibration_log_info(mavlink_log_pub, CAL_QGC_DONE_MSG, "esc");
}
// 8 Report
if (calibration_failed) {
calibration_log_critical(mavlink_log_pub, CAL_QGC_FAILED_MSG, "Timeout waiting for battery");
return PX4_ERROR;
return return_code;
} else {
calibration_log_info(mavlink_log_pub, CAL_QGC_DONE_MSG, "esc");
return PX4_OK;
}
}

View File

@ -84,3 +84,19 @@ int ActuatorEffectiveness::Configuration::totalNumActuators() const
return total_count;
}
void ActuatorEffectiveness::stopMaskedMotorsWithZeroThrust(uint32_t stoppable_motors_mask, ActuatorVector &actuator_sp)
{
for (int actuator_idx = 0; actuator_idx < NUM_ACTUATORS; actuator_idx++) {
const uint32_t motor_mask = (1u << actuator_idx);
if (stoppable_motors_mask & motor_mask) {
if (fabsf(actuator_sp(actuator_idx)) < .02f) {
_stopped_motors_mask |= motor_mask;
} else {
_stopped_motors_mask &= ~motor_mask;
}
}
}
}

View File

@ -203,7 +203,7 @@ public:
/**
* Get a bitmask of motors to be stopped
*/
virtual uint32_t getStoppedMotors() const { return 0; }
virtual uint32_t getStoppedMotors() const { return _stopped_motors_mask; }
/**
* Fill in the unallocated torque and thrust, customized by effectiveness type.
@ -211,6 +211,15 @@ public:
*/
virtual void getUnallocatedControl(int matrix_index, control_allocator_status_s &status) {}
/**
* Stops motors which are masked by stoppable_motors_mask and whose demanded thrust is zero
*
* @param stoppable_motors_mask mask of motors that should be stopped if there's no thrust demand
* @param actuator_sp outcome of the allocation to determine if the motor should be stopped
*/
virtual void stopMaskedMotorsWithZeroThrust(uint32_t stoppable_motors_mask, ActuatorVector &actuator_sp);
protected:
FlightPhase _flight_phase{FlightPhase::HOVER_FLIGHT}; ///< Current flight phase
FlightPhase _flight_phase{FlightPhase::HOVER_FLIGHT};
uint32_t _stopped_motors_mask{0};
};

View File

@ -48,9 +48,10 @@ ActuatorEffectivenessCustom::getEffectivenessMatrix(Configuration &configuration
return false;
}
// motors
// Motors
_motors.enablePropellerTorque(false);
const bool motors_added_successfully = _motors.addActuators(configuration);
_motors_mask = _motors.getMotors();
// Torque
const bool torque_added_successfully = _torque.addActuators(configuration);
@ -58,3 +59,9 @@ ActuatorEffectivenessCustom::getEffectivenessMatrix(Configuration &configuration
return (motors_added_successfully && torque_added_successfully);
}
void ActuatorEffectivenessCustom::updateSetpoint(const matrix::Vector<float, NUM_AXES> &control_sp,
int matrix_index, ActuatorVector &actuator_sp, const matrix::Vector<float, NUM_ACTUATORS> &actuator_min,
const matrix::Vector<float, NUM_ACTUATORS> &actuator_max)
{
stopMaskedMotorsWithZeroThrust(_motors_mask, actuator_sp);
}

View File

@ -45,9 +45,15 @@ public:
bool getEffectivenessMatrix(Configuration &configuration, EffectivenessUpdateReason external_update) override;
void updateSetpoint(const matrix::Vector<float, NUM_AXES> &control_sp, int matrix_index,
ActuatorVector &actuator_sp, const matrix::Vector<float, NUM_ACTUATORS> &actuator_min,
const matrix::Vector<float, NUM_ACTUATORS> &actuator_max) override;
const char *name() const override { return "Custom"; }
protected:
ActuatorEffectivenessRotors _motors;
ActuatorEffectivenessControlSurfaces _torque;
uint32_t _motors_mask{};
};

View File

@ -53,6 +53,7 @@ ActuatorEffectivenessFixedWing::getEffectivenessMatrix(Configuration &configurat
// Motors
_rotors.enablePropellerTorque(false);
const bool rotors_added_successfully = _rotors.addActuators(configuration);
_forwards_motors_mask = _rotors.getForwardsMotors();
// Control Surfaces
_first_control_surface_idx = configuration.num_actuators_matrix[0];
@ -61,6 +62,13 @@ ActuatorEffectivenessFixedWing::getEffectivenessMatrix(Configuration &configurat
return (rotors_added_successfully && surfaces_added_successfully);
}
void ActuatorEffectivenessFixedWing::updateSetpoint(const matrix::Vector<float, NUM_AXES> &control_sp,
int matrix_index, ActuatorVector &actuator_sp, const matrix::Vector<float, NUM_ACTUATORS> &actuator_min,
const matrix::Vector<float, NUM_ACTUATORS> &actuator_max)
{
stopMaskedMotorsWithZeroThrust(_forwards_motors_mask, actuator_sp);
}
void ActuatorEffectivenessFixedWing::allocateAuxilaryControls(const float dt, int matrix_index,
ActuatorVector &actuator_sp)
{

View File

@ -51,6 +51,10 @@ public:
void allocateAuxilaryControls(const float dt, int matrix_index, ActuatorVector &actuator_sp) override;
void updateSetpoint(const matrix::Vector<float, NUM_AXES> &control_sp, int matrix_index,
ActuatorVector &actuator_sp, const matrix::Vector<float, NUM_ACTUATORS> &actuator_min,
const matrix::Vector<float, NUM_ACTUATORS> &actuator_max) override;
private:
ActuatorEffectivenessRotors _rotors;
ActuatorEffectivenessControlSurfaces _control_surfaces;
@ -59,4 +63,6 @@ private:
uORB::Subscription _spoilers_setpoint_sub{ORB_ID(spoilers_setpoint)};
int _first_control_surface_idx{0}; ///< applies to matrix 1
uint32_t _forwards_motors_mask{};
};

View File

@ -265,6 +265,17 @@ Vector3f ActuatorEffectivenessRotors::tiltedAxis(float tilt_angle, float tilt_di
return Dcmf{Eulerf{0.f, -tilt_angle, tilt_direction}} * axis;
}
uint32_t ActuatorEffectivenessRotors::getMotors() const
{
uint32_t motors = 0;
for (int i = 0; i < _geometry.num_rotors; ++i) {
motors |= 1u << i;
}
return motors;
}
uint32_t ActuatorEffectivenessRotors::getUpwardsMotors() const
{
uint32_t upwards_motors = 0;
@ -280,6 +291,21 @@ uint32_t ActuatorEffectivenessRotors::getUpwardsMotors() const
return upwards_motors;
}
uint32_t ActuatorEffectivenessRotors::getForwardsMotors() const
{
uint32_t forward_motors = 0;
for (int i = 0; i < _geometry.num_rotors; ++i) {
const Vector3f &axis = _geometry.rotors[i].axis;
if (axis(0) > 0.5f && fabsf(axis(1)) < 0.1f && fabsf(axis(2)) < 0.1f) {
forward_motors |= 1u << i;
}
}
return forward_motors;
}
bool
ActuatorEffectivenessRotors::getEffectivenessMatrix(Configuration &configuration,
EffectivenessUpdateReason external_update)

View File

@ -126,7 +126,9 @@ public:
void enableThreeDimensionalThrust(bool enable) { _geometry.three_dimensional_thrust_disabled = !enable; }
uint32_t getMotors() const;
uint32_t getUpwardsMotors() const;
uint32_t getForwardsMotors() const;
private:
void updateParams() override;

View File

@ -45,7 +45,15 @@ ActuatorEffectivenessRoverAckermann::getEffectivenessMatrix(Configuration &confi
}
configuration.addActuator(ActuatorType::MOTORS, Vector3f{}, Vector3f{1.f, 0.f, 0.f});
_motors_mask = 1u << 0;
configuration.addActuator(ActuatorType::SERVOS, Vector3f{0.f, 0.f, 1.f}, Vector3f{});
return true;
}
void ActuatorEffectivenessRoverAckermann::updateSetpoint(const matrix::Vector<float, NUM_AXES> &control_sp,
int matrix_index, ActuatorVector &actuator_sp, const matrix::Vector<float, NUM_ACTUATORS> &actuator_min,
const matrix::Vector<float, NUM_ACTUATORS> &actuator_max)
{
stopMaskedMotorsWithZeroThrust(_motors_mask, actuator_sp);
}

View File

@ -43,6 +43,11 @@ public:
bool getEffectivenessMatrix(Configuration &configuration, EffectivenessUpdateReason external_update) override;
void updateSetpoint(const matrix::Vector<float, NUM_AXES> &control_sp, int matrix_index,
ActuatorVector &actuator_sp, const matrix::Vector<float, NUM_ACTUATORS> &actuator_min,
const matrix::Vector<float, NUM_ACTUATORS> &actuator_max) override;
const char *name() const override { return "Rover (Ackermann)"; }
private:
uint32_t _motors_mask{};
};

View File

@ -46,6 +46,14 @@ ActuatorEffectivenessRoverDifferential::getEffectivenessMatrix(Configuration &co
configuration.addActuator(ActuatorType::MOTORS, Vector3f{0.f, 0.f, 0.5f}, Vector3f{0.5f, 0.f, 0.f});
configuration.addActuator(ActuatorType::MOTORS, Vector3f{0.f, 0.f, -0.5f}, Vector3f{0.5f, 0.f, 0.f});
_motors_mask = (1u << 0) | (1u << 1);
return true;
}
void ActuatorEffectivenessRoverDifferential::updateSetpoint(const matrix::Vector<float, NUM_AXES> &control_sp,
int matrix_index, ActuatorVector &actuator_sp, const matrix::Vector<float, NUM_ACTUATORS> &actuator_min,
const matrix::Vector<float, NUM_ACTUATORS> &actuator_max)
{
stopMaskedMotorsWithZeroThrust(_motors_mask, actuator_sp);
}

View File

@ -43,6 +43,11 @@ public:
bool getEffectivenessMatrix(Configuration &configuration, EffectivenessUpdateReason external_update) override;
void updateSetpoint(const matrix::Vector<float, NUM_AXES> &control_sp, int matrix_index,
ActuatorVector &actuator_sp, const matrix::Vector<float, NUM_ACTUATORS> &actuator_min,
const matrix::Vector<float, NUM_ACTUATORS> &actuator_max) override;
const char *name() const override { return "Rover (Differential)"; }
private:
uint32_t _motors_mask{};
};

View File

@ -53,7 +53,8 @@ ActuatorEffectivenessStandardVTOL::getEffectivenessMatrix(Configuration &configu
configuration.selected_matrix = 0;
_rotors.enablePropellerTorqueNonUpwards(false);
const bool mc_rotors_added_successfully = _rotors.addActuators(configuration);
_mc_motors_mask = _rotors.getUpwardsMotors();
_upwards_motors_mask = _rotors.getUpwardsMotors();
_forwards_motors_mask = _rotors.getForwardsMotors();
// Control Surfaces
configuration.selected_matrix = 1;
@ -83,6 +84,15 @@ void ActuatorEffectivenessStandardVTOL::allocateAuxilaryControls(const float dt,
}
}
void ActuatorEffectivenessStandardVTOL::updateSetpoint(const matrix::Vector<float, NUM_AXES> &control_sp,
int matrix_index, ActuatorVector &actuator_sp, const matrix::Vector<float, NUM_ACTUATORS> &actuator_min,
const matrix::Vector<float, NUM_ACTUATORS> &actuator_max)
{
if (matrix_index == 0) {
stopMaskedMotorsWithZeroThrust(_forwards_motors_mask, actuator_sp);
}
}
void ActuatorEffectivenessStandardVTOL::setFlightPhase(const FlightPhase &flight_phase)
{
if (_flight_phase == flight_phase) {
@ -94,13 +104,13 @@ void ActuatorEffectivenessStandardVTOL::setFlightPhase(const FlightPhase &flight
// update stopped motors
switch (flight_phase) {
case FlightPhase::FORWARD_FLIGHT:
_stopped_motors = _mc_motors_mask;
_stopped_motors_mask |= _upwards_motors_mask;
break;
case FlightPhase::HOVER_FLIGHT:
case FlightPhase::TRANSITION_FF_TO_HF:
case FlightPhase::TRANSITION_HF_TO_FF:
_stopped_motors = 0;
_stopped_motors_mask &= ~_upwards_motors_mask;
break;
}
}

View File

@ -75,20 +75,21 @@ public:
void allocateAuxilaryControls(const float dt, int matrix_index, ActuatorVector &actuator_sp) override;
void setFlightPhase(const FlightPhase &flight_phase) override;
void updateSetpoint(const matrix::Vector<float, NUM_AXES> &control_sp, int matrix_index,
ActuatorVector &actuator_sp, const matrix::Vector<float, NUM_ACTUATORS> &actuator_min,
const matrix::Vector<float, NUM_ACTUATORS> &actuator_max) override;
uint32_t getStoppedMotors() const override { return _stopped_motors; }
void setFlightPhase(const FlightPhase &flight_phase) override;
private:
ActuatorEffectivenessRotors _rotors;
ActuatorEffectivenessControlSurfaces _control_surfaces;
uint32_t _mc_motors_mask{}; ///< mc motors (stopped during forward flight)
uint32_t _stopped_motors{}; ///< currently stopped motors
uint32_t _upwards_motors_mask{};
uint32_t _forwards_motors_mask{};
int _first_control_surface_idx{0}; ///< applies to matrix 1
uORB::Subscription _flaps_setpoint_sub{ORB_ID(flaps_setpoint)};
uORB::Subscription _spoilers_setpoint_sub{ORB_ID(spoilers_setpoint)};
};

View File

@ -86,7 +86,15 @@ void ActuatorEffectivenessTailsitterVTOL::allocateAuxilaryControls(const float d
_control_surfaces.applySpoilers(spoilers_setpoint.normalized_setpoint, _first_control_surface_idx, dt, actuator_sp);
}
}
}
void ActuatorEffectivenessTailsitterVTOL::updateSetpoint(const matrix::Vector<float, NUM_AXES> &control_sp,
int matrix_index, ActuatorVector &actuator_sp, const matrix::Vector<float, NUM_ACTUATORS> &actuator_min,
const matrix::Vector<float, NUM_ACTUATORS> &actuator_max)
{
if (matrix_index == 0) {
stopMaskedMotorsWithZeroThrust(_forwards_motors_mask, actuator_sp);
}
}
void ActuatorEffectivenessTailsitterVTOL::setFlightPhase(const FlightPhase &flight_phase)
@ -97,16 +105,17 @@ void ActuatorEffectivenessTailsitterVTOL::setFlightPhase(const FlightPhase &flig
ActuatorEffectiveness::setFlightPhase(flight_phase);
// update stopped motors //TODO: add option to switch off certain motors in FW
// update stopped motors
switch (flight_phase) {
case FlightPhase::FORWARD_FLIGHT:
_stopped_motors = 0;
_forwards_motors_mask = _mc_rotors.getUpwardsMotors(); // allocation frame they stay upwards
break;
case FlightPhase::HOVER_FLIGHT:
case FlightPhase::TRANSITION_FF_TO_HF:
case FlightPhase::TRANSITION_HF_TO_FF:
_stopped_motors = 0;
_forwards_motors_mask = 0;
_stopped_motors_mask = 0;
break;
}
}

View File

@ -72,16 +72,20 @@ public:
void allocateAuxilaryControls(const float dt, int matrix_index, ActuatorVector &actuator_sp) override;
void updateSetpoint(const matrix::Vector<float, NUM_AXES> &control_sp, int matrix_index,
ActuatorVector &actuator_sp, const matrix::Vector<float, NUM_ACTUATORS> &actuator_min,
const matrix::Vector<float, NUM_ACTUATORS> &actuator_max) override;
void setFlightPhase(const FlightPhase &flight_phase) override;
const char *name() const override { return "VTOL Tailsitter"; }
uint32_t getStoppedMotors() const override { return _stopped_motors; }
protected:
ActuatorEffectivenessRotors _mc_rotors;
ActuatorEffectivenessControlSurfaces _control_surfaces;
uint32_t _stopped_motors{}; ///< currently stopped motors
uint32_t _forwards_motors_mask{};
int _first_control_surface_idx{0}; ///< applies to matrix 1

View File

@ -68,10 +68,11 @@ ActuatorEffectivenessTiltrotorVTOL::getEffectivenessMatrix(Configuration &config
// scales are tilt-invariant. Note: configuration updates are only possible when disarmed.
const float collective_tilt_control_applied = (external_update == EffectivenessUpdateReason::CONFIGURATION_UPDATE) ?
-1.f : _last_collective_tilt_control;
_nontilted_motors = _mc_rotors.updateAxisFromTilts(_tilts, collective_tilt_control_applied)
_untiltable_motors = _mc_rotors.updateAxisFromTilts(_tilts, collective_tilt_control_applied)
<< configuration.num_actuators[(int)ActuatorType::MOTORS];
const bool mc_rotors_added_successfully = _mc_rotors.addActuators(configuration);
_motors = _mc_rotors.getMotors();
// Control Surfaces
configuration.selected_matrix = 1;
@ -118,7 +119,6 @@ void ActuatorEffectivenessTiltrotorVTOL::updateSetpoint(const matrix::Vector<flo
{
// apply tilt
if (matrix_index == 0) {
tiltrotor_extra_controls_s tiltrotor_extra_controls;
if (_tiltrotor_extra_controls_sub.copy(&tiltrotor_extra_controls)) {
@ -145,12 +145,15 @@ void ActuatorEffectivenessTiltrotorVTOL::updateSetpoint(const matrix::Vector<flo
// in FW directly use throttle sp
if (_flight_phase == FlightPhase::FORWARD_FLIGHT) {
for (int i = 0; i < _first_tilt_idx; ++i) {
actuator_sp(i) = tiltrotor_extra_controls.collective_thrust_normalized_setpoint;
}
}
}
if (_flight_phase == FlightPhase::FORWARD_FLIGHT) {
stopMaskedMotorsWithZeroThrust(_motors & ~_untiltable_motors, actuator_sp);
}
}
// Set yaw saturation flag in case of yaw through tilt. As in this case the yaw actuation is decoupled from
@ -180,13 +183,13 @@ void ActuatorEffectivenessTiltrotorVTOL::setFlightPhase(const FlightPhase &fligh
// update stopped motors
switch (flight_phase) {
case FlightPhase::FORWARD_FLIGHT:
_stopped_motors = _nontilted_motors;
_stopped_motors_mask |= _untiltable_motors;
break;
case FlightPhase::HOVER_FLIGHT:
case FlightPhase::TRANSITION_FF_TO_HF:
case FlightPhase::TRANSITION_HF_TO_FF:
_stopped_motors = 0;
_stopped_motors_mask = 0;
break;
}
}

View File

@ -84,8 +84,6 @@ public:
const char *name() const override { return "VTOL Tiltrotor"; }
uint32_t getStoppedMotors() const override { return _stopped_motors; }
void getUnallocatedControl(int matrix_index, control_allocator_status_s &status) override;
protected:
@ -94,8 +92,8 @@ protected:
ActuatorEffectivenessControlSurfaces _control_surfaces;
ActuatorEffectivenessTilts _tilts;
uint32_t _nontilted_motors{}; ///< motors that are not tiltable
uint32_t _stopped_motors{}; ///< currently stopped motors
uint32_t _motors{};
uint32_t _untiltable_motors{};
int _first_control_surface_idx{0}; ///< applies to matrix 1
int _first_tilt_idx{0}; ///< applies to matrix 0

View File

@ -0,0 +1,63 @@
/****************************************************************************
*
* Copyright (c) 2023 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#include "ActuatorEffectivenessUUV.hpp"
using namespace matrix;
ActuatorEffectivenessUUV::ActuatorEffectivenessUUV(ModuleParams *parent)
: ModuleParams(parent),
_rotors(this)
{
}
bool ActuatorEffectivenessUUV::getEffectivenessMatrix(Configuration &configuration,
EffectivenessUpdateReason external_update)
{
if (external_update == EffectivenessUpdateReason::NO_EXTERNAL_UPDATE) {
return false;
}
// Motors
const bool rotors_added_successfully = _rotors.addActuators(configuration);
_motors_mask = _rotors.getMotors();
return rotors_added_successfully;
}
void ActuatorEffectivenessUUV::updateSetpoint(const matrix::Vector<float, NUM_AXES> &control_sp,
int matrix_index, ActuatorVector &actuator_sp, const matrix::Vector<float, NUM_ACTUATORS> &actuator_min,
const matrix::Vector<float, NUM_ACTUATORS> &actuator_max)
{
stopMaskedMotorsWithZeroThrust(_motors_mask, actuator_sp);
}

View File

@ -0,0 +1,67 @@
/****************************************************************************
*
* Copyright (c) 2023 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#pragma once
#include "ActuatorEffectiveness.hpp"
#include "ActuatorEffectivenessRotors.hpp"
class ActuatorEffectivenessUUV : public ModuleParams, public ActuatorEffectiveness
{
public:
ActuatorEffectivenessUUV(ModuleParams *parent);
virtual ~ActuatorEffectivenessUUV() = default;
bool getEffectivenessMatrix(Configuration &configuration, EffectivenessUpdateReason external_update) override;
void getDesiredAllocationMethod(AllocationMethod allocation_method_out[MAX_NUM_MATRICES]) const override
{
allocation_method_out[0] = AllocationMethod::SEQUENTIAL_DESATURATION;
}
void getNormalizeRPY(bool normalize[MAX_NUM_MATRICES]) const override
{
normalize[0] = true;
}
void updateSetpoint(const matrix::Vector<float, NUM_AXES> &control_sp, int matrix_index,
ActuatorVector &actuator_sp, const matrix::Vector<float, NUM_ACTUATORS> &actuator_min,
const matrix::Vector<float, NUM_ACTUATORS> &actuator_max) override;
const char *name() const override { return "UUV"; }
protected:
ActuatorEffectivenessRotors _rotors;
uint32_t _motors_mask{};
};

View File

@ -34,6 +34,8 @@
px4_add_library(ActuatorEffectiveness
ActuatorEffectiveness.cpp
ActuatorEffectiveness.hpp
ActuatorEffectivenessUUV.cpp
ActuatorEffectivenessUUV.hpp
ActuatorEffectivenessControlSurfaces.cpp
ActuatorEffectivenessControlSurfaces.hpp
ActuatorEffectivenessCustom.cpp

View File

@ -247,7 +247,7 @@ ControlAllocator::update_effectiveness_source()
break;
case EffectivenessSource::MOTORS_6DOF: // just a different UI from MULTIROTOR
tmp = new ActuatorEffectivenessRotors(this);
tmp = new ActuatorEffectivenessUUV(this);
break;
case EffectivenessSource::MULTIROTOR_WITH_TILT:

View File

@ -51,6 +51,7 @@
#include <ActuatorEffectivenessFixedWing.hpp>
#include <ActuatorEffectivenessMCTilt.hpp>
#include <ActuatorEffectivenessCustom.hpp>
#include <ActuatorEffectivenessUUV.hpp>
#include <ActuatorEffectivenessHelicopter.hpp>
#include <ControlAllocation.hpp>

View File

@ -416,6 +416,7 @@ struct parameters {
float flow_noise{0.15f}; ///< observation noise for optical flow LOS rate measurements (rad/sec)
float flow_noise_qual_min{0.5f}; ///< observation noise for optical flow LOS rate measurements when flow sensor quality is at the minimum useable (rad/sec)
int32_t flow_qual_min{1}; ///< minimum acceptable quality integer from the flow sensor
int32_t flow_qual_min_gnd{0}; ///< minimum acceptable quality integer from the flow sensor when on ground
float flow_innov_gate{3.0f}; ///< optical flow fusion innovation consistency gate size (STD)
Vector3f flow_pos_body{}; ///< xyz position of range sensor focal point in body frame (m)

View File

@ -760,9 +760,7 @@ void Ekf::get_ekf_soln_status(uint16_t *status) const
soln_status.flags.pos_horiz_rel = (_control_status.flags.gps || _control_status.flags.ev_pos || _control_status.flags.opt_flow) && (_fault_status.value == 0);
soln_status.flags.pos_horiz_abs = (_control_status.flags.gps || _control_status.flags.ev_pos) && (_fault_status.value == 0);
soln_status.flags.pos_vert_abs = soln_status.flags.velocity_vert;
#if defined(CONFIG_EKF2_RANGE_FINDER)
soln_status.flags.pos_vert_agl = isTerrainEstimateValid();
#endif // CONFIG_EKF2_RANGE_FINDER
soln_status.flags.const_pos_mode = !soln_status.flags.velocity_horiz;
soln_status.flags.pred_pos_horiz_rel = soln_status.flags.pos_horiz_rel;
soln_status.flags.pred_pos_horiz_abs = soln_status.flags.pos_horiz_abs;
@ -1026,15 +1024,12 @@ void Ekf::initialiseQuatCovariances(Vector3f &rot_vec_var)
void Ekf::updateGroundEffect()
{
if (_control_status.flags.in_air && !_control_status.flags.fixed_wing) {
#if defined(CONFIG_EKF2_RANGE_FINDER)
if (isTerrainEstimateValid()) {
// automatically set ground effect if terrain is valid
float height = _terrain_vpos - _state.pos(2);
_control_status.flags.gnd_effect = (height < _params.gnd_effect_max_hgt);
} else
#endif // CONFIG_EKF2_RANGE_FINDER
if (_control_status.flags.gnd_effect) {
} else if (_control_status.flags.gnd_effect) {
// Turn off ground effect compensation if it times out
if (isTimedOut(_time_last_gnd_effect_on, GNDEFFECT_TIMEOUT)) {
_control_status.flags.gnd_effect = false;

View File

@ -77,6 +77,16 @@ void Ekf::updateOptFlow(estimator_aid_source2d_s &aid_src)
const float R_LOS = calcOptFlowMeasVar(_flow_sample_delayed);
aid_src.observation_variance[0] = R_LOS;
aid_src.observation_variance[1] = R_LOS;
const Vector24f state_vector = getStateAtFusionHorizonAsVector();
Vector2f innov_var;
Vector24f H;
sym::ComputeFlowXyInnovVarAndHx(state_vector, P, range, R_LOS, FLT_EPSILON, &innov_var, &H);
innov_var.copyTo(aid_src.innovation_variance);
// run the innovation consistency check and record result
setEstimatorAidStatusTestRatio(aid_src, math::max(_params.flow_innov_gate, 1.f));
}
void Ekf::fuseOptFlow()

View File

@ -59,7 +59,7 @@ void Ekf::controlOpticalFlowFusion(const imuSample &imu_delayed)
// Accumulate autopilot gyro data across the same time interval as the flow sensor
const Vector3f delta_angle(imu_delayed.delta_ang - (getGyroBias() * imu_delayed.delta_ang_dt));
if (_delta_time_of < 0.1f) {
if (_delta_time_of < 0.2f) {
_imu_del_ang_of += delta_angle;
_delta_time_of += imu_delayed.delta_ang_dt;
@ -70,7 +70,12 @@ void Ekf::controlOpticalFlowFusion(const imuSample &imu_delayed)
}
if (_flow_data_ready) {
const bool is_quality_good = (_flow_sample_delayed.quality >= _params.flow_qual_min);
int32_t min_quality = _params.flow_qual_min;
if (!_control_status.flags.in_air) {
min_quality = _params.flow_qual_min_gnd;
}
const bool is_quality_good = (_flow_sample_delayed.quality >= min_quality);
const bool is_magnitude_good = !_flow_sample_delayed.flow_xy_rad.longerThan(_flow_sample_delayed.dt * _flow_max_rate);
const bool is_tilt_good = (_R_to_earth(2, 2) > _params.range_cos_max_tilt);

View File

@ -415,10 +415,12 @@ void Ekf::controlHaglFakeFusion()
bool Ekf::isTerrainEstimateValid() const
{
#if defined(CONFIG_EKF2_RANGE_FINDER)
// we have been fusing range finder measurements in the last 5 seconds
if (_hagl_sensor_status.flags.range_finder && isRecent(_time_last_hagl_fuse, (uint64_t)5e6)) {
return true;
}
#endif // CONFIG_EKF2_RANGE_FINDER
#if defined(CONFIG_EKF2_OPTICAL_FLOW)
// we have been fusing optical flow measurements for terrain estimation within the last 5 seconds

View File

@ -154,6 +154,7 @@ EKF2::EKF2(bool multi_mode, const px4::wq_config_t &config, bool replay_mode):
_param_ekf2_of_n_min(_params->flow_noise),
_param_ekf2_of_n_max(_params->flow_noise_qual_min),
_param_ekf2_of_qmin(_params->flow_qual_min),
_param_ekf2_of_qmin_gnd(_params->flow_qual_min_gnd),
_param_ekf2_of_gate(_params->flow_innov_gate),
_param_ekf2_of_pos_x(_params->flow_pos_body(0)),
_param_ekf2_of_pos_y(_params->flow_pos_body(1)),
@ -1295,6 +1296,10 @@ void EKF2::PublishInnovations(const hrt_abstime &timestamp)
_preflt_checker.setUsingGpsAiding(_ekf.control_status_flags().gps);
#if defined(CONFIG_EKF2_OPTICAL_FLOW)
_preflt_checker.setUsingFlowAiding(_ekf.control_status_flags().opt_flow);
// set dist bottom to scale flow innovation
const float dist_bottom = _ekf.getTerrainVertPos() - _ekf.getPosition()(2);
_preflt_checker.setDistBottom(dist_bottom);
#endif // CONFIG_EKF2_OPTICAL_FLOW
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
@ -1461,13 +1466,10 @@ void EKF2::PublishLocalPosition(const hrt_abstime &timestamp)
lpos.delta_heading = Eulerf(delta_q_reset).psi();
lpos.heading_good_for_control = _ekf.isYawFinalAlignComplete();
#if defined(CONFIG_EKF2_RANGE_FINDER)
// Distance to bottom surface (ground) in meters
// constrain the distance to ground to _rng_gnd_clearance
lpos.dist_bottom = math::max(_ekf.getTerrainVertPos() - lpos.z, _param_ekf2_min_rng.get());
// Distance to bottom surface (ground) in meters, must be positive
lpos.dist_bottom = math::max(_ekf.getTerrainVertPos() - lpos.z, 0.f);
lpos.dist_bottom_valid = _ekf.isTerrainEstimateValid();
lpos.dist_bottom_sensor_bitfield = _ekf.getTerrainEstimateSensorBitfield();
#endif // CONFIG_EKF2_RANGE_FINDER
_ekf.get_ekf_lpos_accuracy(&lpos.eph, &lpos.epv);
_ekf.get_ekf_vel_accuracy(&lpos.evh, &lpos.evv);
@ -2454,8 +2456,10 @@ void EKF2::UpdateCalibration(const hrt_abstime &timestamp, InFlightCalibration &
// consider bias estimates stable when all checks pass consistently and bias hasn't changed more than 10% of the limit
const float bias_change_limit = 0.1f * bias_limit;
if ((cal.last_us != 0) && !(cal.bias - bias).longerThan(bias_change_limit)) {
if (!(cal.bias - bias).longerThan(bias_change_limit)) {
if (cal.last_us != 0) {
cal.total_time_us += timestamp - cal.last_us;
}
if (cal.total_time_us > 30_s) {
cal.cal_available = true;
@ -2515,7 +2519,6 @@ void EKF2::UpdateGyroCalibration(const hrt_abstime &timestamp)
void EKF2::UpdateMagCalibration(const hrt_abstime &timestamp)
{
const bool bias_valid = (_ekf.control_status_flags().mag_hdg || _ekf.control_status_flags().mag_3D)
&& _ekf.control_status_flags().mag_aligned_in_flight
&& !_ekf.control_status_flags().mag_fault
&& !_ekf.control_status_flags().mag_field_disturbed;

View File

@ -662,7 +662,9 @@ private:
(ParamExtFloat<px4::params::EKF2_OF_N_MAX>)
_param_ekf2_of_n_max, ///< worst quality observation noise for optical flow LOS rate measurements (rad/sec)
(ParamExtInt<px4::params::EKF2_OF_QMIN>)
_param_ekf2_of_qmin, ///< minimum acceptable quality integer from the flow sensor
_param_ekf2_of_qmin, ///< minimum acceptable quality integer from the flow sensor when in air
(ParamExtInt<px4::params::EKF2_OF_QMIN_GND>)
_param_ekf2_of_qmin_gnd, ///< minimum acceptable quality integer from the flow sensor when on ground
(ParamExtFloat<px4::params::EKF2_OF_GATE>)
_param_ekf2_of_gate, ///< optical flow fusion innovation consistency gate size (STD)
(ParamExtFloat<px4::params::EKF2_OF_POS_X>)

View File

@ -85,7 +85,7 @@ bool PreFlightChecker::preFlightCheckHorizVelFailed(const estimator_innovations_
#if defined(CONFIG_EKF2_OPTICAL_FLOW)
if (_is_using_flow_aiding) {
const Vector2f flow_innov = Vector2f(innov.flow);
const Vector2f flow_innov = Vector2f(innov.flow) * _flow_dist_bottom;
Vector2f flow_innov_lpf;
flow_innov_lpf(0) = _filter_flow_x_innov.update(flow_innov(0), alpha, _flow_innov_spike_lim);
flow_innov_lpf(1) = _filter_flow_y_innov.update(flow_innov(1), alpha, _flow_innov_spike_lim);

View File

@ -77,6 +77,7 @@ public:
void setUsingGpsAiding(bool val) { _is_using_gps_aiding = val; }
#if defined(CONFIG_EKF2_OPTICAL_FLOW)
void setUsingFlowAiding(bool val) { _is_using_flow_aiding = val; }
void setDistBottom(float dist_bottom) { _flow_dist_bottom = dist_bottom; }
#endif // CONFIG_EKF2_OPTICAL_FLOW
void setUsingEvPosAiding(bool val) { _is_using_ev_pos_aiding = val; }
void setUsingEvVelAiding(bool val) { _is_using_ev_vel_aiding = val; }
@ -179,6 +180,7 @@ private:
#if defined(CONFIG_EKF2_OPTICAL_FLOW)
bool _is_using_flow_aiding {};
float _flow_dist_bottom {};
InnovationLpf _filter_flow_x_innov; ///< Preflight low pass filter optical flow innovation (rad)
InnovationLpf _filter_flow_y_innov; ///< Preflight low pass filter optical flow innovation (rad)

View File

@ -901,7 +901,7 @@ PARAM_DEFINE_FLOAT(EKF2_OF_N_MIN, 0.15f);
PARAM_DEFINE_FLOAT(EKF2_OF_N_MAX, 0.5f);
/**
* Optical Flow data will only be used if the sensor reports a quality metric >= EKF2_OF_QMIN.
* Optical Flow data will only be used in air if the sensor reports a quality metric >= EKF2_OF_QMIN.
*
* @group EKF2
* @min 0
@ -909,6 +909,15 @@ PARAM_DEFINE_FLOAT(EKF2_OF_N_MAX, 0.5f);
*/
PARAM_DEFINE_INT32(EKF2_OF_QMIN, 1);
/**
* Optical Flow data will only be used on the ground if the sensor reports a quality metric >= EKF2_OF_QMIN_GND.
*
* @group EKF2
* @min 0
* @max 255
*/
PARAM_DEFINE_INT32(EKF2_OF_QMIN_GND, 0);
/**
* Gate size for optical flow fusion
*

View File

@ -40,11 +40,6 @@
* @author Thomas Gubler <thomas@px4.io>
*/
/*
* Controller parameters, accessible via MAVLink
*
*/
/**
* Attitude Roll Time Constant
*
@ -86,7 +81,7 @@ PARAM_DEFINE_FLOAT(FW_P_TC, 0.4f);
*
* @unit deg/s
* @min 0.0
* @max 90.0
* @max 180
* @decimal 1
* @increment 0.5
* @group FW Attitude Control
@ -98,7 +93,7 @@ PARAM_DEFINE_FLOAT(FW_P_RMAX_POS, 60.0f);
*
* @unit deg/s
* @min 0.0
* @max 90.0
* @max 180
* @decimal 1
* @increment 0.5
* @group FW Attitude Control
@ -110,7 +105,7 @@ PARAM_DEFINE_FLOAT(FW_P_RMAX_NEG, 60.0f);
*
* @unit deg/s
* @min 0.0
* @max 90.0
* @max 180
* @decimal 1
* @increment 0.5
* @group FW Attitude Control
@ -122,7 +117,7 @@ PARAM_DEFINE_FLOAT(FW_R_RMAX, 70.0f);
*
* @unit deg/s
* @min 0.0
* @max 90.0
* @max 180
* @decimal 1
* @increment 0.5
* @group FW Attitude Control
@ -140,7 +135,6 @@ PARAM_DEFINE_FLOAT(FW_Y_RMAX, 50.0f);
*/
PARAM_DEFINE_INT32(FW_W_EN, 0);
/**
* Wheel steering rate proportional gain
*
@ -149,7 +143,7 @@ PARAM_DEFINE_INT32(FW_W_EN, 0);
*
* @unit %/rad/s
* @min 0.0
* @max 1.0
* @max 10
* @decimal 3
* @increment 0.005
* @group FW Attitude Control
@ -164,7 +158,7 @@ PARAM_DEFINE_FLOAT(FW_WR_P, 0.5f);
*
* @unit %/rad
* @min 0.0
* @max 0.5
* @max 10
* @decimal 3
* @increment 0.005
* @group FW Attitude Control
@ -207,7 +201,7 @@ PARAM_DEFINE_FLOAT(FW_W_RMAX, 30.0f);
*
* @unit %/rad/s
* @min 0.0
* @max 1.0
* @max 10
* @decimal 2
* @increment 0.05
* @group FW Attitude Control

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