Compare commits

...

68 Commits

Author SHA1 Message Date
Hamish Willee b64ba9efe5 Fix wording in MAVLink messages documentation 2026-02-18 15:26:08 +11:00
PX4BuildBot 7ef57f6262 docs: auto-sync metadata [skip ci]
Co-Authored-By: PX4 BuildBot <bot@px4.io>
2026-02-18 00:23:31 +00:00
Victor Nan Fernandez-Ayala 2a0b795760 fix: set UXRCE_DDS_AG_IP in UUV airframe, remove from defaults (#26485) 2026-02-17 16:15:45 -08:00
PX4BuildBot 911fc81c59 docs: auto-sync metadata [skip ci]
Co-Authored-By: PX4 BuildBot <bot@px4.io>
2026-02-17 23:17:55 +00:00
Jacob Dahl b2fc5993cc range_finder_consistency_check: fix consistency check timeout units (#26497)
* range_finder_consistency_check: fix consistency check timeout units

* explicit float

* format
2026-02-17 14:10:04 -09:00
Jacob Dahl d5ddc9135d clang-tidy: fix issues (#26498) 2026-02-17 14:09:43 -09:00
PX4BuildBot 6b67ccb0ad docs: auto-sync metadata [skip ci]
Co-Authored-By: PX4 BuildBot <bot@px4.io>
2026-02-17 20:02:19 +00:00
Alex Klimaj 0e6b904e80 LightwareLaser: add SF1XX rotation parameter (#26428)
* Add SF1XX rotation parameter and update orientation in LightwareLaser driver

* remove rotation opt arg, update docs about supported lightware

---------

Co-authored-by: Jacob Dahl <dahl.jakejacob@gmail.com>
2026-02-17 10:54:38 -09:00
Ramon Roche 864df9fc7b CI: disable VTOL and tailsitter SITL tests
Persistent flaky failures (timeouts, erratic transitions) make these
tests unreliable in CI. Commented out from the workflow matrix so they
can be re-enabled once the test infrastructure is stabilized. The test
definitions in sitl.json are preserved for local use.

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-02-17 09:30:18 -08:00
PX4BuildBot d17a5b2c26 docs: auto-sync metadata [skip ci]
Co-Authored-By: PX4 BuildBot <bot@px4.io>
2026-02-17 13:41:39 +00:00
Balduin d46a9266ce Failsafe docs: document COM_POS_LOW_EPH, COM_POS_LOW_ACT (#26508)
* Failsafe docs: document COM_POS_LOW_EPH, COM_POS_LOW_ACT

* Failsafe docs: address review
2026-02-17 14:34:44 +01:00
PX4BuildBot 3a6f566e80 docs: auto-sync metadata [skip ci]
Co-Authored-By: PX4 BuildBot <bot@px4.io>
2026-02-17 09:15:19 +00:00
Jacob Dahl d84903d520 init.d-posix/airframes/4004_gz_standard_vtol: param set-default VT_PITCH_MIN -5 (#26507) 2026-02-17 00:06:29 -09:00
PX4BuildBot 4331f880f5 docs: auto-sync metadata [skip ci]
Co-Authored-By: PX4 BuildBot <bot@px4.io>
2026-02-17 08:37:39 +00:00
Silvan Fuhrer 11007dc893 FW auto launch: Add option to lock selected surfaces before/during launch (#25799)
* FWModeManager: add option to set flag for disabling actuators during launch

Signed-off-by: Silvan <silvan@auterion.com>

* Allocation: add option to each control surface to be locked for launch

Signed-off-by: Silvan <silvan@auterion.com>

* FW rate control: reset integral while control surfaces are locked

Signed-off-by: Silvan <silvan@auterion.com>

---------

Signed-off-by: Silvan <silvan@auterion.com>
Co-authored-by: mahima-yoga <mahima@auterion.com>
2026-02-17 09:26:38 +01:00
Ramon Roche fd4b958790 ci: add geninfo negative error ignore to tests_coverage (#26506) 2026-02-16 20:04:18 -09:00
Ramon Roche a06f062bf7 nuttx: add nuttx_context dependency to jlink-nuttx build (#26505) 2026-02-16 20:04:06 -09:00
PX4BuildBot 79bf7810d4 docs: auto-sync metadata [skip ci]
Co-Authored-By: PX4 BuildBot <bot@px4.io>
2026-02-16 21:41:55 +00:00
Aaron1356 066e8f7fea Adding Light Ware GRF Serial Driver (#26404)
* Creating a base for grf lidar

* Serial Drive is working, need to work out distance publish

* WIP Getting Range Data in cm

* Working Rand Distance Values for GRF 250 and GRF500

* Review Changes

* Compiler fixes

* Update to date

* small update

* Fix typo and remover unused libs

* removing unused enum

* Update to the Documentation

* Fiving scaling issue

* update to the logic

* [Feature] Adding I2C driver for the GRF250 and GRF500 models (#26425)

* Adding the GRF I2C driver

* I2C Driver Working

* Removing a lot of unnecessary code

* fixing names

* Changing the i2c Driver to be in the lightware laser

* remove the old driver

* formatting fix

* Adding Ligthware GRF to documentation

* Update to the Documentation

* Ensuring sample_perf ends

* Updating Docs

* uavcannode: implement hardpoint commands (#26334)

* implement cannode hardpoint commands

Signed-off-by: dirksavage88 <dirksavage88@gmail.com>

* Update src/drivers/uavcannode/Subscribers/HardpointCommand.hpp

Co-authored-by: Jacob Dahl <37091262+dakejahl@users.noreply.github.com>

* Update src/drivers/uavcannode/Subscribers/HardpointCommand.hpp

Co-authored-by: Jacob Dahl <37091262+dakejahl@users.noreply.github.com>

* add hardpoint sub to ark cannode, simplify handling of hardpoint broadcast

Signed-off-by: dirksavage88 <dirksavage88@gmail.com>

---------

Signed-off-by: dirksavage88 <dirksavage88@gmail.com>
Co-authored-by: Jacob Dahl <37091262+dakejahl@users.noreply.github.com>

* voxl_esc: Limit frequency of UART passthru writes to 20Hz

* voxl2_io: Added UART passthru

* docs: update link for px4 ros2 interface lib python api docs

* estimator_interface: remove unused getter

* gnss_checks: always run strict checks on ground

With the goal to never take off if the GNSS solution is not fullfilling the configured requirements still not stopping to use it in case it degrades mid air.

* ekf2 unit-tests: adapt to strict GNSS checks on ground

* escCheck: rework online check to properly report offline ESCs

previous to this
09d79b221f
set `esc_online_flags` e.g. for UAVCAN ESCs which specific one is online and that then got compared to a mask where the first `esc_count` bits were set.

So if only ESC 5 is mapped and online you get the message "ESC 156 offline" because `esc_online_flags = 0b1000` gets compared to `online_bitmask = 0b1` based on `esc_count = 1` and the motor index is `esc[0].actuator_function = 0` wrapped using `0 - actuator_motors_s::ACTUATOR_FUNCTION_MOTOR1 + 1 = 156`.

* FailureDetector: consistent timestamp naming

* FailureDetector: rework motor status check

* FailureDetector: implement upper and lower current limit with offset

* Update src/modules/commander/failure_detector/FailureDetector.cpp

Prevent Buffer overflow

* Update Format

* Subedit

* Shrink and rename image

* Apply suggestion from @hamishwillee

Sounds good

Co-authored-by: Hamish Willee <hamishwillee@gmail.com>

* Apply suggestion from @hamishwillee

More universal approach

Co-authored-by: Hamish Willee <hamishwillee@gmail.com>

* Update to the Documentation

* FailureDetector: rework motor status check

* FailureDetector: implement upper and lower current limit with offset

* Subedit

* docs: update parameter reference metadata

* Remove pregenerated files - that should all be tidied up next time this runs

* remover GRF parameters

* Documentation updates

* Fixing Merge Conflicts

* remove @

* Undo Changes to parameter_reference

* remove the code that will be autogen-ed

* Update the Camake File

---------

Signed-off-by: dirksavage88 <dirksavage88@gmail.com>
Co-authored-by: Andrew Brahim <35986980+dirksavage88@users.noreply.github.com>
Co-authored-by: Jacob Dahl <37091262+dakejahl@users.noreply.github.com>
Co-authored-by: Eric Katzfey <eric.katzfey@modalai.com>
Co-authored-by: Beat Küng <beat-kueng@gmx.net>
Co-authored-by: Matthias Grob <maetugr@gmail.com>
Co-authored-by: Marco Hauswirth <marco.hauswirth@auterion.com>
Co-authored-by: Nick <145654544+ttechnick@users.noreply.github.com>
Co-authored-by: Hamish Willee <hamishwillee@gmail.com>
Co-authored-by: Ramon Roche <mrpollo@gmail.com>
2026-02-16 16:34:48 -05:00
PX4BuildBot 08dc2a776e docs: auto-sync metadata [skip ci]
Co-Authored-By: PX4 BuildBot <bot@px4.io>
2026-02-16 20:33:01 +00:00
ljarvela 061fe4806e uavcan: add warning about CAN error counter reading issue (#26492)
Add warning message in print_info() to alert users that CAN error counter
values may increase during the function call due to internal counter reading
implementation. Users should not fully trust these counters until the
underlying issue is fixed.

Co-authored-by: ljarvela <lasse.jarvela@iceye.com>
2026-02-16 11:25:30 -09:00
PX4BuildBot 4bebbbae93 docs: auto-sync metadata [skip ci]
Co-Authored-By: PX4 BuildBot <bot@px4.io>
2026-02-16 17:47:30 +00:00
Claudio Chies e52ce5c43b UAVCAN: Configurable LED Light Control with Flexible Addressing (#26253)
* feat: implement UAVCAN LED control for individual light control and assignment

* uavcan led: nit-picks from review

* uavcan led: reduce maximum number of lights

to avoid unused parameters

* uavcan led: simplify anticolision on check

* uavcan led: correctly map 8-bit RGB to rgb565

* Trim param name character arrays to 17

16 characters + \0 termination

* uavcan led: final nit-picks

---------

Co-authored-by: Matthias Grob <maetugr@gmail.com>
2026-02-16 18:39:48 +01:00
Ramon Roche 32c94bd3b1 ci: fix S3 upload so tags don't overwrite stable firmware
Remove the step that uploaded every version tag to the stable/ S3
directory, which caused QGC users selecting "stable" to receive
pre-release firmware (#26340). The stable/ and beta/ directories
are now controlled exclusively by their respective branch pushes,
while version tags only upload to their versioned archive directory
(e.g., v1.16.1/). Pre-release tags are also correctly marked on
GitHub Releases.

Co-authored-by: Julian Oes <julian@oes.ch>

Fixes #26340

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-02-13 06:29:13 -08:00
PX4BuildBot b08fefa903 docs: auto-sync metadata [skip ci]
Co-Authored-By: PX4 BuildBot <bot@px4.io>
2026-02-13 13:14:35 +00:00
nlsxp 302d0601bf Smoothen external flight mode GotoControl to Mission transitions (#26254) 2026-02-13 14:06:47 +01:00
PX4BuildBot c90811a277 docs: auto-sync metadata [skip ci]
Co-Authored-By: PX4 BuildBot <bot@px4.io>
2026-02-13 12:49:48 +00:00
Balduin 79a7ef2869 RtlTimeEstimator: Consider minimum ground speed (#26405)
* RtlTimeEstimator: Consider minimum ground speed

This fixes an issue seen when the wind is faster than the trim airspeed,
but not faster than the max airspeed.

In that case the RTL time estimator currently assumes that we always fly
at trim airspeed and are thus unable to cover ground in the upwind
direction. The result is a very large RTL time estimate, resulting in
RTL if configured by COM_FLTT_LOW_ACT.

By considering the FW_GND_SPD_MIN parameter, we correct this wrong
assumption. The RTL remaining time estimate now becomes realistic in
this situation.

* RtlTimeEstimator: assume min ground speed of 5 if param unavailable
2026-02-13 13:42:17 +01:00
Jaeyoung Lim b9f4de0b51 Fix TECS throttle integrator runaway (#26472) 2026-02-13 04:41:27 -08:00
Matthias Grob 14cbcee49f CI: replace all usage of addnab/docker-run-action
It's unmaintained and the docker version it uses is not supported anymore.
2026-02-13 13:39:50 +01:00
cuav-chen2 f38aba3c5b cuav_fmu-v6x: Adjust the startup sequence of the sensors 2026-02-12 22:16:32 -08:00
PX4BuildBot 84933cfbdf docs: auto-sync metadata [skip ci]
Co-Authored-By: PX4 BuildBot <bot@px4.io>
2026-02-13 05:28:01 +00:00
Ramon Roche be3e1fb2ef fix(build): restore smbus/smbus_sbs for Linux board targets
The previous commit (6b8fd11) gated smbus and smbus_sbs behind
PX4_PLATFORM=="nuttx" to prevent clang-tidy errors on SITL, but these
libraries depend on device::I2C which has a POSIX implementation
(posix/I2C.cpp). Linux boards like bluerobotics_navigator (armhf) and
emlid_navio2 (aarch64) enable CONFIG_DRIVERS_BATT_SMBUS, which depends
on drivers__smbus — causing CMake to fail with "non-existent target".

Move smbus and smbus_sbs back to unconditional add_subdirectory() so
they are available on all platforms. Keep mcp_common gated behind NuttX
since it includes px4_platform/gpio/mcp.hpp (NuttX-only GPIO headers).

Re-add src/lib/drivers/smbus to the Makefile clang-tidy exclude list
since the SITL compilation database lacks the I2C platform headers
needed for analysis.

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-02-12 21:20:27 -08:00
Ramon Roche 82850cb149 clang-tidy: exclude emscripten Unity build path from analysis
The failsafe_test target uses CMake Unity Builds (UNITY_BUILD ON),
which merges emscripten.cpp, failsafe.cpp, and framework.cpp into a
single generated file at:
  build/.../failsafe_test.dir/Unity/unity_0_cxx.cxx

The run-clang-tidy.py exclude regex operates on compile_commands.json
paths, which reference this generated unity file — not the original
source path. The previous exclude (src/modules/commander/failsafe/
emscripten) only matched the source path and missed the unity file,
causing clang-diagnostic-error: 'emscripten/emscripten.h' not found.

Add failsafe_test\.dir to the exclude regex to catch the unity build
path in addition to the source path.

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-02-12 21:20:27 -08:00
Ramon Roche 3d457528d2 clang-tidy: gate NuttX-only driver libs by platform instead of exclude list
The clang-tidy CI target builds against the SITL (px4_sitl_default-clang)
compilation database. Three libraries in src/lib/drivers/ were
unconditionally added via add_subdirectory(), causing them to appear in
compile_commands.json despite requiring NuttX-only headers:

- mcp_common: includes px4_platform/gpio/mcp.hpp (NuttX platform GPIO)
- smbus: extends device::I2C which resolves to the NuttX I2C driver
- smbus_sbs: includes smbus/SMBus.hpp, same I2C dependency chain

When clang-tidy analyzed these files it failed on clang-diagnostic-error
(fatal: header not found) since the platform headers don't exist in SITL.

The previous commit worked around this by adding the paths to
CLANG_TIDY_EXCLUDE_EXTRA in the Makefile, but the proper fix is to prevent
these libraries from entering the compilation database at all.

Gate mcp_common, smbus, and smbus_sbs behind
if(PX4_PLATFORM STREQUAL "nuttx") in src/lib/drivers/CMakeLists.txt.
This follows the established pattern already used by the device/ library
in the same directory, which conditionally includes NuttX-specific sources
(CDev.cpp, I2C.cpp, SPI.cpp) while compiling posix stubs for SITL.

The other libraries in the directory (accelerometer, gyroscope, led,
magnetometer, rangefinder) are pure abstractions over uORB topics and
internal utilities with no platform-specific hardware dependencies, so
they compile fine on all platforms without any gating.

Remove the now-unnecessary mcp_common and smbus paths from
CLANG_TIDY_EXCLUDE_EXTRA, keeping only the emscripten failsafe exclusion
(requires the emscripten SDK, not a platform build issue).

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-02-12 21:20:27 -08:00
Ramon Roche d74007dc87 clang-tidy: exclude NuttX-only drivers and emscripten from SITL analysis
These files depend on platform headers (px4_platform/gpio/mcp.hpp,
device::I2C, emscripten/emscripten.h) that are unavailable in the
SITL/clang build, causing clang-tidy to report compiler errors:

- src/lib/drivers/mcp_common (NuttX GPIO)
- src/drivers/gpio (MCP23009, MCP23017)
- src/lib/drivers/smbus (I2C bus driver)
- src/modules/commander/failsafe/emscripten (emscripten SDK)

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-02-12 21:20:27 -08:00
Ramon Roche 47b3f5f6f9 docker-entrypoint.sh: consolidate startup output into single useful line
Replace the two separate echo lines ("Starting" and "(arch)") with a
single line showing architecture and UTC timestamp:

  [docker-entrypoint.sh] aarch64 | 2026-02-09T15:23:45Z

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-02-12 21:20:27 -08:00
Ramon Roche 6d8441dc89 docker_run.sh: modernize image and clean up stale CI references
Update the local Docker convenience script to use the unified
px4io/px4-dev image instead of the retired per-toolchain images
(px4-dev-clang, px4-dev-simulation-bionic).

Usage:
  ./Tools/docker_run.sh make px4_sitl_default
  ./Tools/docker_run.sh make tests TESTFILTER=ULogMessages
  PX4_DOCKER_REPO="px4io/px4-dev:custom" ./Tools/docker_run.sh make px4_fmu-v6x_default

Changes:
- Default to px4io/px4-dev:v1.17.0-beta1, remove conditional image
  guessing for clang/tests targets
- Remove stale env passthrough (Travis CI, AWS, Codecov, Coveralls)
- Keep CCACHE_DIR and sanitizer flags (PX4_ASAN/MSAN/TSAN/UBSAN)
- Fix $PWD shadowing by renaming to SCRIPT_DIR
- Use "$@" instead of "$1 $2 $3" for proper argument forwarding

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-02-12 21:20:27 -08:00
Ramon Roche f29afe1342 logger: expand ULog unit tests to cover all message types
Rename ULogMessageInfoTest to ULogMessagesTest and add struct-level
coverage for every message type in the ULog spec:

- File header: magic bytes, size, field offsets
- Flag Bits ('B'): size, field offsets, flag masks
- Format ('F'): size, serialization
- Info ('I'): string, int32_t, and float value layouts
- Info Multiple ('M'): string layout, continuation flag, field offsets
- Parameter ('P'): int32_t and float value layouts
- Default Parameter ('Q'): size, type bits, field offsets
- Subscription ('A'): size, field offsets, serialization
- Unsubscription ('R'): size, serialization
- Data ('D'): size, field offset
- Logging ('L'): size, field offsets, serialization
- Logging Tagged ('C'): size, field offsets
- Sync ('S'): size, magic bytes
- Dropout ('O'): size, default msg_size, serialization
- Message header: size, field offsets, ULOG_MSG_HEADER_LEN
- Enum values: all 13 ULogMessageType codes

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-02-12 21:20:27 -08:00
Ramon Roche 9849d90877 gps: add null check for path in GPS constructor
Guard the strncpy call with a null check to prevent undefined behavior
if the constructor is ever called with a null path pointer.

Fixes clang-analyzer-core.NonNullParamChecker diagnostic.

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-02-12 21:20:27 -08:00
Ramon Roche 497704f3b9 fw_mode_manager: pass FigureEightPatternPoints by const reference
The 48-byte struct (6 Vector2f) is only read inside initializePattern,
so passing by value creates an unnecessary copy.

Fixes performance-unnecessary-value-param clang-tidy diagnostic.

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-02-12 21:20:27 -08:00
Ramon Roche b60aa5dd2b ekf2, fw_mode_manager, fw_rate_control: remove unused using declarations
Remove using-declarations for math::constrain, math::max, and
math::min that are never used — all call sites use the fully-qualified
form (e.g. math::constrain()).

Fixes misc-unused-using-decls clang-tidy diagnostic.

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-02-12 21:20:27 -08:00
Ramon Roche 5d151c54a4 flight_mode_manager: call direct parent instead of grandparent
FlightTaskManualAcceleration and FlightTaskOrbit both inherit from
FlightTaskManualAltitudeSmoothVel but were calling FlightTask and
FlightTaskManualAltitude respectively, skipping the intermediate
parent's overrides (smoothing velocity init, parameter chain).

Fix the DEFINE_PARAMETERS_CUSTOM_PARENT macro argument and the
activate() call to use FlightTaskManualAltitudeSmoothVel.

Fixes bugprone-parent-virtual-call clang-tidy diagnostic.

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-02-12 21:20:27 -08:00
Ramon Roche 83a4d648e3 logger: copy null terminator in write_info memcpy
clang-tidy flags the memcpy of vlen bytes as
bugprone-not-null-terminated-result because the destination buffer
region is left unterminated in memory.

Copy vlen + 1 bytes (including the source null terminator) so the
buffer is null-terminated in memory. The ULog msg_size is not
incremented for the extra byte — the null sits in the struct's
key_value_str padding and is never written to the log file, preserving
the ULog wire format which does not include a null terminator for
string values.

The bounds check (vlen < sizeof(msg) - msg_size) guarantees at least
one byte of headroom beyond vlen, so vlen + 1 is always within the
struct.

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-02-12 21:20:27 -08:00
Ramon Roche 0646fa6c9d logger: add unit test for ULog INFO message serialization
Add a gtest that validates the exact binary layout of INFO and
INFO_MULTIPLE messages against the ULog spec. This exercises the same
packing logic as write_info/write_info_multiple and will catch any
accidental changes to the wire format (e.g. including a null terminator
in msg_size).

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-02-12 21:20:27 -08:00
Ramon Roche d9b3e48ec5 CI: improve clang-tidy workflow naming and use standard cache actions
Rename workflow to "Static Analysis" with job name "Clang-Tidy" for
clearer GitHub Checks UI. Use Title Case action-verb step names.
Switch from runs-on/cache to actions/cache since the runs-on Magic
Cache sidecar transparently handles S3 backing.

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-02-12 21:20:27 -08:00
Ramon Roche 29fefeeada CI: fix ccache key to use branch name instead of merge ref
github.ref_name resolves to '26367/merge' for pull_request events,
causing cache misses. Use github.head_ref (PR source branch) with
fallback to github.ref_name for push events.

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-02-12 21:20:27 -08:00
Ramon Roche 618a6aa98f CI: add explicit permissions block to clang-tidy workflow
Set minimal permissions (contents: read) as flagged by CodeQL.

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-02-12 21:20:27 -08:00
Ramon Roche 8a007d38e7 CI: split ccache into restore/save so cache persists on failure
Use separate cache/restore and cache/save steps with if: always()
on the save step, matching the build_all_targets pattern.

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-02-12 21:20:27 -08:00
Ramon Roche e831c66ae1 CI: add ccache and S3 caching to clang-tidy workflow
- Switch from addnab/docker-run-action to native container directive
- Use runs-on 16-core runner with S3 cache (extras=s3-cache)
- Add ccache setup matching build_all_targets pattern
- Run clang-tidy with -j16 to leverage all cores

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-02-12 21:20:27 -08:00
Ramon Roche 021eee0c5c CI: use 16-core runs-on runner for clang-tidy workflow
The free GitHub runner (4 vCPUs) takes ~22 minutes. Switch to a
16-core runs-on runner and bump parallelism to -j16 to reduce
clang-tidy analysis time.

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-02-12 21:20:27 -08:00
Ramon Roche 385450ca37 CI: pin clang-tidy workflow to px4-dev:v1.17.0-beta1 container
Pin the container image to v1.17.0-beta1 which includes clang-tidy 18
and all required clang dependencies pre-installed. This removes the
need to install clang-tidy via apt on each workflow run.

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-02-12 21:20:27 -08:00
Ramon Roche 23c9af20da clang-tidy: disable new checks for v18 compatibility
Update .clang-tidy configuration to maintain compatibility with
clang-tidy 18 in the new px4io/px4-dev:v1.17.0-alpha1 container.

The previous CI container used clang-tidy 6.0 (2018) with ~213 checks.
The new container has clang-tidy 18 (2024) with ~537 checks - adding
~324 new checks that would fail without configuration changes.

This commit disables the new checks to preserve the existing code
quality baseline. The disabled checks can be evaluated and enabled
incrementally in future PRs as the codebase is updated to comply.

New checks disabled (partial list):
- bugprone-assignment-in-if-condition
- bugprone-casting-through-void
- bugprone-multi-level-implicit-pointer-conversion
- cppcoreguidelines-avoid-do-while
- cppcoreguidelines-avoid-goto
- cppcoreguidelines-avoid-non-const-global-variables
- misc-definitions-in-headers
- misc-header-include-cycle
- misc-no-recursion
- modernize-macro-to-enum
- modernize-type-traits
- performance-enum-size
- readability-avoid-nested-conditional-operator
- readability-convert-member-functions-to-static
- readability-redundant-string-init
- readability-simplify-boolean-expr
- (and ~35 more)

See full list in .clang-tidy. Each check is prefixed with '-' to
disable it while keeping WarningsAsErrors: '*' active for enabled
checks.

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-02-12 21:20:27 -08:00
Ramon Roche d196d37ef2 clang-tidy: auto-exclude submodules and third-party code
Automatically generate the clang-tidy exclusion list from .gitmodules
so new submodules are excluded without manual intervention.

Changes:
- Makefile: Generate CLANG_TIDY_SUBMODULES from .gitmodules paths
- Makefile: Add CLANG_TIDY_EXCLUDE_EXTRA for manual exclusions:
  - src/systemcmds/tests (test code, looser style allowed)
  - src/examples (educational code, not production)
  - src/modules/gyro_fft/CMSIS_5 (vendored ARM DSP library)
- Delete src/systemcmds/tests/.clang-tidy (stale since 2019)
- Delete src/modules/gyro_fft/CMSIS_5/.clang-tidy (redundant)

Rationale: Submodules and vendored code should be linted in their
upstream repositories, not here. This reduces noise and focuses
clang-tidy on code that PX4 maintainers actually edit.

Contributors adding vendored (non-submodule) third-party code should
add their path to CLANG_TIDY_EXCLUDE_EXTRA in the Makefile.

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-02-12 21:20:27 -08:00
Ramon Roche dc4aa749d3 Tools/run-clang-tidy: add -exclude argument for file filtering
Add regex-based file exclusion to the clang-tidy runner script.
This allows excluding paths (submodules, vendored code, tests) from
static analysis without modifying .clang-tidy files in each directory.

The -exclude argument accepts a regex pattern that is matched against
file paths from the compilation database. Matching files are skipped.

Example: -exclude="src/lib/foo|src/modules/bar"

This prepares for the clang-tidy v6 to v18 migration where we need
to exclude external code that we consume but don't maintain.

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-02-12 21:20:27 -08:00
Ramon Roche 767eb75662 gyro_fft: fix clang build error on Linux arm64
Extend the -Wno-asm-operand-widths workaround to include Linux aarch64
in addition to Apple Silicon. CMSIS DSP contains ARM Cortex-M specific
assembly that clang (but not gcc) warns about on 64-bit ARM platforms.

The assembly code is unused on POSIX builds - only the C fallback
implementations are executed in SITL.

This fixes clang-tidy CI failing on arm64 runners.

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-02-12 21:20:27 -08:00
Marco Hauswirth c29630f6ae adjust clang-tidy checks and workflow 2026-02-12 21:20:27 -08:00
cuav-chen2 c511e72d4f cuav_nora: 5V power overcurrent detection pin default to pull-up 2026-02-12 19:57:37 -08:00
PX4BuildBot a235b5c87f docs: auto-sync metadata [skip ci]
Co-Authored-By: PX4 BuildBot <bot@px4.io>
2026-02-13 03:30:17 +00:00
Matthias Grob 87163c1578 uavcan esc: initializers cosmetics (#26470) 2026-02-12 18:22:19 -09:00
PX4BuildBot 841fccf6b9 docs: auto-sync metadata [skip ci]
Co-Authored-By: PX4 BuildBot <bot@px4.io>
2026-02-13 02:35:53 +00:00
Ramon Roche 8a3e227dc0 docs: address review feedback on build docs
- Update "Failed to import Python packages" section to reference
  gz_x500 instead of jmavsim, and point to Tools/setup/requirements.txt
  instead of listing individual packages
- Fix :::info admonition spacing in Ubuntu dev env docs

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-02-12 18:28:49 -08:00
Hamish Willee ad0b6bdc6b Subedit 2026-02-12 18:28:49 -08:00
Ramon Roche aecd1461d7 docs: document px4-dev as the recommended container
The new px4-dev container replaces the old per-distro container
hierarchy from PX4/PX4-containers. It is:

- Multi-architecture (linux/amd64 + linux/arm64)
- Based on Ubuntu 24.04
- Built from the in-tree Dockerfile via GitHub Actions
- Published to both ghcr.io and Docker Hub
- Tagged with PX4 versions (e.g. px4-dev:v1.16.0)

Mark the legacy per-distro containers (px4-dev-nuttx-jammy,
px4-dev-ros2-humble, etc.) as deprecated, note that px4-sim
is planned for simulation workflows.

Update all examples to use px4-dev instead of legacy containers.

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-02-12 18:28:49 -08:00
Ramon Roche 8017baa6e6 docs: remove outdated Ubuntu/Gazebo Classic references
docker.md:
- Update container hierarchy from focal to jammy
- Replace ROS Noetic/Foxy references with ROS 2 Humble
- Update docker run example to use humble container
- Update SITL example from gazebo-classic to gz_x500
- Update VM tested version from Ubuntu 14.04 to 22.04

vscode.md:
- Remove "Ubuntu 18.04" from inotify troubleshooting header
  (this issue is not Ubuntu-version-specific)

dev_env_linux_centos.md:
- Update GCC warning to reference current Ubuntu LTS toolchain
  instead of old Focal Docker file

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-02-12 18:28:49 -08:00
Ramon Roche 103a61450e docs: update Ubuntu dev env to reflect supported LTS versions
- Replace "older version" collapsible with info block stating
  supported versions: Ubuntu 24.04 (primary) and 22.04
- Remove Gazebo Classic references (Ubuntu 22.04 section, install step)
- Note that GCC version comes from Ubuntu package manager
- Clarify that GCC version depends on Ubuntu release

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-02-12 18:28:49 -08:00
Ramon Roche df242827d2 docs: remove outdated Ubuntu/GCC references from build instructions
- Remove Ubuntu 18.04 troubleshooting sections (compile errors,
  VSCode inotify) — Ubuntu 18.04 is no longer supported
- Remove Gazebo Classic SITL dropdown from first build section
- Update FMUv2 flash warning to reference gcc-arm-none-eabi from
  current Ubuntu LTS instead of vague "CI/docker" reference
- Update flash overflow guidance to point at Ubuntu LTS toolchain
- Simplify "too many open files" error example (remove old GCC 7.2.1
  path from 2017)

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-02-12 18:28:49 -08:00
Ramon Roche d9996742be setup: drop Ubuntu 18.04/20.04 support from ubuntu.sh
Remove Gazebo Classic installation branches for Ubuntu 18.04 and 20.04.
The script now only supports Ubuntu 22.04 and 24.04 with Gazebo Harmonic.

Supported Ubuntu LTS versions going forward:
- Ubuntu 24.04 (primary, used in CI and release builds)
- Ubuntu 22.04 (secondary, still supported)

When Ubuntu 26.04 LTS releases we will bump to 26.04/24.04.

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-02-12 18:28:49 -08:00
105 changed files with 3185 additions and 1068 deletions
+83
View File
@@ -105,6 +105,89 @@ Checks: '*,
-readability-redundant-declaration,
-readability-static-accessed-through-instance,
-readability-static-definition-in-anonymous-namespace,
-altera-struct-pack-align,
-bugprone-easily-swappable-parameters,
-concurrency-mt-unsafe,
-cppcoreguidelines-avoid-const-or-ref-data-members,
-cppcoreguidelines-macro-usage,
-cppcoreguidelines-non-private-member-variables-in-classes,
-hicpp-uppercase-literal-suffix,
-llvm-qualified-auto,
-misc-non-private-member-variables-in-classes,
-misc-use-anonymous-namespace,
-modernize-concat-nested-namespaces,
-readability-const-return-type,
-readability-identifier-length,
-readability-isolate-declaration,
-readability-qualified-auto,
-readability-redundant-access-specifiers,
-cppcoreguidelines-avoid-do-while,
-misc-include-cleaner,
-misc-const-correctness,
-llvm-else-after-return,
-readability-function-cognitive-complexity,
-cppcoreguidelines-init-variables,
-bugprone-reserved-identifier,
-cert-dcl37-c,
-cert-dcl51-cpp,
-modernize-use-nodiscard,
-misc-confusable-identifiers,
-cert-err33-c,
-readability-redundant-inline-specifier,
-readability-uppercase-literal-suffix,
-bugprone-narrowing-conversions,
-cppcoreguidelines-narrowing-conversions,
-bugprone-switch-missing-default-case,
-cppcoreguidelines-avoid-goto,
-hicpp-avoid-goto,
-bugprone-branch-clone,
-bugprone-unhandled-self-assignment,
-cert-oop54-cpp,
-performance-enum-size,
-readability-avoid-nested-conditional-operator,
-cppcoreguidelines-prefer-member-initializer,
-cppcoreguidelines-explicit-virtual-functions,
-cppcoreguidelines-virtual-class-destructor,
-readability-convert-member-functions-to-static,
-readability-make-member-function-const,
-bugprone-assignment-in-if-condition,
-bugprone-implicit-widening-of-multiplication-result,
-bugprone-incorrect-roundings,
-bugprone-macro-parentheses,
-bugprone-multi-level-implicit-pointer-conversion,
-bugprone-signed-char-misuse,
-bugprone-too-small-loop-variable,
-cppcoreguidelines-avoid-non-const-global-variables,
-cppcoreguidelines-use-default-member-init,
-hicpp-multiway-paths-covered,
-hicpp-named-parameter,
-misc-header-include-cycle,
-misc-no-recursion,
-performance-no-int-to-ptr,
-readability-avoid-return-with-void-value,
-readability-avoid-unconditional-preprocessor-if,
-readability-delete-null-pointer,
-readability-duplicate-include,
-readability-redundant-casting,
-readability-redundant-member-init,
-readability-reference-to-constructed-temporary,
-readability-simplify-boolean-expr,
-bugprone-unsafe-functions,
-cert-msc24-c,
-cert-msc32-c,
-cert-msc33-c,
-cert-msc51-cpp,
-cert-str34-c,
-cppcoreguidelines-macro-to-enum,
-modernize-macro-to-enum,
-abseil-string-find-str-contains,
-bugprone-suspicious-include,
-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,
-clang-analyzer-optin.core.EnumCastOutOfRange,
-modernize-type-traits,
-misc-definitions-in-headers,
-bugprone-casting-through-void,
-readability-redundant-string-init,
'
WarningsAsErrors: '*'
CheckOptions:
+50 -27
View File
@@ -2,6 +2,37 @@
# - If you want to keep the tests running in GitHub Actions you need to uncomment the "runs-on: ubuntu-latest" lines
# and comment the "runs-on: [runs-on,runner=..." lines.
# - If you would like to duplicate this setup try setting up "RunsOn" on your own AWS account try https://runs-on.com
#
# ===================================================================================
# RELEASE UPLOAD LOGIC
# ===================================================================================
# This workflow handles building firmware and uploading to S3 + GitHub Releases.
#
# S3 Bucket Structure (s3://px4-travis/Firmware/):
# - master/ <- Latest main branch build (for QGC compatibility)
# - stable/ <- Latest stable release, controlled by 'stable' branch
# - beta/ <- Latest pre-release, controlled by 'beta' branch
# - vX.Y.Z/ <- Archived stable release
# - vX.Y.Z-beta1/ <- Archived pre-release
#
# Trigger Behavior:
# - Tag v1.16.1 -> Upload to: v1.16.1/ only (versioned archive)
# - Tag v1.17.0-beta1 -> Upload to: v1.17.0-beta1/ only (versioned archive)
# - Branch main -> Upload to: master/ (for QGC compatibility)
# - Branch stable -> Upload to: stable/ (QGC stable firmware)
# - Branch beta -> Upload to: beta/ (QGC beta firmware)
# - Branch release/** -> Build only, no S3 upload (CI validation)
# - Pull requests -> Build only, no S3 upload (CI validation)
#
# GitHub Releases:
# - All version tags create a draft GitHub Release
# - Pre-releases (alpha/beta/rc suffixes) are automatically marked as such
#
# IMPORTANT: Version tags do NOT upload to stable/ or beta/. Only the
# corresponding branch pushes control those directories. This prevents
# pre-release tags from accidentally overwriting stable firmware (#26340)
# and avoids race conditions between tag and branch builds.
# ===================================================================================
name: Build all targets
@@ -163,6 +194,13 @@ jobs:
path: ~/.ccache
key: ${{ steps.cc_restore.outputs.cache-primary-key }}
# ===========================================================================
# ARTIFACT UPLOAD JOB
# ===========================================================================
# Uploads build artifacts to S3 and creates GitHub Releases.
# Runs for version tags (v*), main, stable, and beta branch pushes.
# See header comments for full upload logic documentation.
# ===========================================================================
artifacts:
name: Upload Artifacts
# runs-on: ubuntu-latest
@@ -181,31 +219,31 @@ jobs:
- name: Choose Upload Location
id: upload-location
run: |
# Determine upload location based on branch or tag with the following considerations:
# Destination: AWS S3 bucket px4-travis in folder Firmware/
# - If branch is main -> upload to master/
# - Older versions of QGC are hardocded to look for master/
# - If branch is stable or beta -> upload to stable/ or beta/
# - If a tag vX.Y.Z -> upload to vX.Y.Z/
# - Also update stable/ to point to the same version
#. - Older versions of QGC are hardocded to look for stable/
# - If a pull request -> do not upload
set -euo pipefail
ref="${GITHUB_REF}"
branch=${{ needs.group_targets.outputs.branchname }}
location="$branch"
is_prerelease="false"
# Main branch uploads to "master" for QGC backward compatibility
if [[ "$branch" == "main" ]]; then
location="master"
fi
# Version tags: upload to versioned directory (e.g., v1.16.1/)
if [[ "$ref" == refs/tags/v[0-9]* ]]; then
tag="${ref#refs/tags/}"
location="$tag"
# Pre-release tags contain -alpha, -beta, or -rc suffix
if [[ "$tag" =~ -(alpha|beta|rc) ]]; then
is_prerelease="true"
fi
fi
echo "uploadlocation=$location" >> $GITHUB_OUTPUT
echo "is_prerelease=$is_prerelease" >> $GITHUB_OUTPUT
- name: Uploading Artifacts to S3 [${{ steps.upload-location.outputs.uploadlocation }}]
uses: jakejarvis/s3-sync-action@master
@@ -219,28 +257,13 @@ jobs:
SOURCE_DIR: artifacts/
DEST_DIR: Firmware/${{ steps.upload-location.outputs.uploadlocation }}/
# if we are uploading artifacts to a versioned folder
# we should also update the stable folder in the s3 bucket
- name: Uploading Artifacts to S3 [stable]
uses: jakejarvis/s3-sync-action@master
if: startsWith(github.ref, 'refs/tags/v')
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: artifacts/
DEST_DIR: Firmware/stable/
# if build is a release triggered by a versioned tag then create a github release
# and upload the build artifacts. A draft release is created so that the release
# can be reviewed before publishing
# Create a draft GitHub Release for all version tags
# Pre-releases are automatically marked as such
- name: Upload Artifacts to GitHub Release
uses: softprops/action-gh-release@v2
if: startsWith(github.ref, 'refs/tags/v')
with:
draft: true
prerelease: ${{ steps.upload-location.outputs.is_prerelease == 'true' }}
files: artifacts/*.px4
name: ${{ steps.upload-location.outputs.uploadlocation }}
+9 -8
View File
@@ -19,6 +19,10 @@ concurrency:
jobs:
build:
runs-on: ubuntu-latest
container:
image: px4io/px4-dev:v1.16.0-rc1-258-g0369abd556
strategy:
fail-fast: false
matrix:
@@ -35,20 +39,17 @@ jobs:
"px4_sitl_allyes",
"module_documentation",
]
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Building [${{ matrix.check }}]
uses: addnab/docker-run-action@v3
with:
image: px4io/px4-dev:v1.16.0-rc1-258-g0369abd556
options: -v ${{ github.workspace }}:/workspace
run: |
cd /workspace
git config --global --add safe.directory /workspace
make ${{ matrix.check }}
run: |
cd "$GITHUB_WORKSPACE"
git config --global --add safe.directory "$GITHUB_WORKSPACE"
make ${{ matrix.check }}
- name: Uploading Coverage to Codecov.io
if: contains(matrix.check, 'coverage')
+50 -11
View File
@@ -1,4 +1,4 @@
name: Clang Tidy
name: Static Analysis
on:
push:
@@ -11,20 +11,59 @@ on:
- '**'
paths-ignore:
- 'docs/**'
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
clang_tidy:
name: Clang-Tidy
runs-on: [runs-on, runner=16cpu-linux-x64, "run-id=${{ github.run_id }}", "extras=s3-cache"]
container:
image: px4io/px4-dev:v1.17.0-beta1
steps:
- uses: runs-on/action@v2
- uses: actions/checkout@v4
with:
fetch-depth: 0
fetch-tags: true
- name: Testing (clang-tidy)
uses: addnab/docker-run-action@v3
- name: Configure Git Safe Directory
run: git config --system --add safe.directory '*'
- name: Restore Compiler Cache
id: cc_restore
uses: actions/cache/restore@v4
with:
image: px4io/px4-dev-clang:2021-09-08
options: -v ${{ github.workspace }}:/workspace
run: |
cd /workspace
git config --global --add safe.directory /workspace
make clang-tidy
path: ~/.ccache
key: ccache-clang-tidy-${{ github.head_ref || github.ref_name }}
restore-keys: |
ccache-clang-tidy-${{ github.head_ref || github.ref_name }}-
ccache-clang-tidy-main-
ccache-clang-tidy-
- name: Configure Compiler Cache
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
echo "compiler_check = content" >> ~/.ccache/ccache.conf
ccache -s
ccache -z
- name: Run Clang-Tidy Analysis
run: make -j16 clang-tidy
- name: Compiler Cache Stats
if: always()
run: ccache -s
- name: Save Compiler Cache
if: always()
uses: actions/cache/save@v4
with:
path: ~/.ccache
key: ${{ steps.cc_restore.outputs.cache-primary-key }}
@@ -15,21 +15,21 @@ concurrency:
jobs:
unit_tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: main test
uses: addnab/docker-run-action@v3
with:
image: px4io/px4-dev:v1.16.0-rc1-258-g0369abd556
options: -v ${{ github.workspace }}:/workspace
container:
image: px4io/px4-dev:v1.16.0-rc1-258-g0369abd556
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: main test
run: |
cd /workspace
git config --global --add safe.directory /workspace
cd "$GITHUB_WORKSPACE"
git config --global --add safe.directory "$GITHUB_WORKSPACE"
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
- name: Check if there is a functional change
run: git diff --exit-code
working-directory: src/modules/ekf2/test/change_indication
@@ -8,40 +8,47 @@ on:
jobs:
unit_tests:
runs-on: ubuntu-latest
container:
image: px4io/px4-dev:v1.16.0-rc1-258-g0369abd556
env:
GIT_COMMITTER_EMAIL: bot@px4.io
GIT_COMMITTER_NAME: PX4BuildBot
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: main test
uses: addnab/docker-run-action@v3
with:
image: px4io/px4-dev:v1.16.0-rc1-258-g0369abd556
options: -v ${{ github.workspace }}:/workspace
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: main test
run: |
cd /workspace
git config --global --add safe.directory /workspace
cd "$GITHUB_WORKSPACE"
git config --global --add safe.directory "$GITHUB_WORKSPACE"
make tests TESTFILTER=EKF
- name: Check if there exists diff and save result in variable
id: diff-check
run: echo "CHANGE_INDICATED=$(git diff --exit-code --output=/dev/null || echo $?)" >> $GITHUB_OUTPUT
working-directory: src/modules/ekf2/test/change_indication
- name: Check if there exists diff and save result in variable
id: diff-check
working-directory: src/modules/ekf2/test/change_indication
run: |
if git diff --quiet; then
echo "CHANGE_INDICATED=false" >> $GITHUB_OUTPUT
else
echo "CHANGE_INDICATED=true" >> $GITHUB_OUTPUT
fi
- name: auto-commit any changes to change indication
uses: stefanzweifel/git-auto-commit-action@v4
with:
file_pattern: 'src/modules/ekf2/test/change_indication/*.csv'
commit_user_name: ${GIT_COMMITTER_NAME}
commit_user_email: ${GIT_COMMITTER_EMAIL}
commit_message: |
'[AUTO COMMIT] update change indication'
- name: auto-commit any changes to change indication
if: steps.diff-check.outputs.CHANGE_INDICATED == 'true'
uses: stefanzweifel/git-auto-commit-action@v4
with:
file_pattern: 'src/modules/ekf2/test/change_indication/*.csv'
commit_user_name: ${{ env.GIT_COMMITTER_NAME }}
commit_user_email: ${{ env.GIT_COMMITTER_EMAIL }}
commit_message: |
[AUTO COMMIT] update change indication
See .github/workflopws/ekf_update_change_indicator.yml for more details
See .github/workflows/ekf_update_change_indicator.yml for more details
- name: if there is a functional change, fail check
if: ${{ steps.diff-check.outputs.CHANGE_INDICATED }}
run: exit 1
- name: if there is a functional change, fail check
if: steps.diff-check.outputs.CHANGE_INDICATED == 'true'
run: exit 1
+18 -16
View File
@@ -19,25 +19,27 @@ concurrency:
jobs:
build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
config:
- {vehicle: "iris", mission: "MC_mission_box"}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Build SITL and Run Tests
uses: addnab/docker-run-action@v3
with:
image: px4io/px4-dev-ros-melodic:2021-09-08
options: -v ${{ github.workspace }}:/workspace
- name: Build SITL and Run Tests (inside old ROS container)
run: |
cd /workspace
git config --global --add safe.directory /workspace
make px4_sitl_default
make px4_sitl_default sitl_gazebo-classic
./test/rostest_px4_run.sh mavros_posix_test_mission.test mission:=${{matrix.config.mission}} vehicle:=${{matrix.config.vehicle}}
docker run --rm \
-v "${GITHUB_WORKSPACE}:/workspace" \
-w /workspace \
px4io/px4-dev-ros-melodic:2021-09-08 \
bash -c '
git config --global --add safe.directory /workspace
make px4_sitl_default
make px4_sitl_default sitl_gazebo-classic
./test/rostest_px4_run.sh \
mavros_posix_test_mission.test \
mission:=MC_mission_box \
vehicle:=iris
'
+17 -18
View File
@@ -19,27 +19,26 @@ concurrency:
jobs:
build:
runs-on: ubuntu-latest
env:
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
strategy:
fail-fast: false
matrix:
config:
- {test_file: "mavros_posix_tests_offboard_posctl.test", vehicle: "iris"}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Build PX4 and Run Tests
uses: addnab/docker-run-action@v3
with:
image: px4io/px4-dev-ros-melodic:2021-09-08
options: -v ${{ github.workspace }}:/workspace
- name: Build SITL and Run Tests (inside old ROS container)
run: |
cd /workspace
git config --global --add safe.directory /workspace
make px4_sitl_default
make px4_sitl_default sitl_gazebo-classic
./test/rostest_px4_run.sh ${{matrix.config.test_file}} vehicle:=${{matrix.config.vehicle}}
docker run --rm \
-v "${GITHUB_WORKSPACE}:/workspace" \
-w /workspace \
px4io/px4-dev-ros-melodic:2021-09-08 \
bash -c '
git config --global --add safe.directory /workspace
make px4_sitl_default
make px4_sitl_default sitl_gazebo-classic
./test/rostest_px4_run.sh \
mavros_posix_tests_offboard_posctl.test \
vehicle:=iris
'
+15 -14
View File
@@ -19,27 +19,28 @@ concurrency:
jobs:
build:
runs-on: ubuntu-latest
container:
image: px4io/px4-dev:v1.16.0-rc1-258-g0369abd556
strategy:
matrix:
config: [
px4_fmu-v5_default,
]
config:
- px4_fmu-v5_default
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Build PX4 and Run Test [${{ matrix.config }}]
uses: addnab/docker-run-action@v3
with:
image: px4io/px4-dev:v1.16.0-rc1-258-g0369abd556
options: -v ${{ github.workspace }}:/workspace
- name: Build PX4 and Run Test [${{ matrix.config }}]
run: |
cd /workspace
git config --global --add safe.directory /workspace
export PX4_EXTRA_NUTTX_CONFIG="CONFIG_NSH_LOGIN_PASSWORD=\"test\";CONFIG_NSH_CONSOLE_LOGIN=y"
cd "$GITHUB_WORKSPACE"
git config --global --add safe.directory "$GITHUB_WORKSPACE"
export PX4_EXTRA_NUTTX_CONFIG='CONFIG_NSH_LOGIN_PASSWORD="test";CONFIG_NSH_CONSOLE_LOGIN=y'
echo "PX4_EXTRA_NUTTX_CONFIG: $PX4_EXTRA_NUTTX_CONFIG"
make ${{ matrix.config }} nuttx_context
echo "Check that the config option is set"
grep CONFIG_NSH_LOGIN_PASSWORD build/${{ matrix.config }}/NuttX/nuttx/.config
+4 -2
View File
@@ -33,8 +33,10 @@ jobs:
matrix:
config:
- {model: "iris", latitude: "59.617693", longitude: "-151.145316", altitude: "48", build_type: "RelWithDebInfo" } # Alaska
- {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
# VTOL/tailsitter disabled: persistent flaky CI failures (timeouts, erratic
# transitions). Re-enable once the test infrastructure is stabilized.
# - {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
steps:
- uses: actions/checkout@v4
+19 -3
View File
@@ -412,7 +412,7 @@ tests:
$(call cmake-build,px4_sitl_test)
# work around lcov bug #316; remove once lcov is fixed (see https://github.com/linux-test-project/lcov/issues/316)
LCOBUG = --ignore-errors mismatch
LCOBUG = --ignore-errors mismatch,negative
tests_coverage:
@$(MAKE) clean
@$(MAKE) --no-print-directory tests PX4_CMAKE_BUILD_TYPE=Coverage
@@ -492,13 +492,29 @@ px4_sitl_default-clang:
@cd "$(SRC_DIR)"/build/px4_sitl_default-clang && cmake "$(SRC_DIR)" $(CMAKE_ARGS) -G"$(PX4_CMAKE_GENERATOR)" -DCONFIG=px4_sitl_default -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++
@$(PX4_MAKE) -C "$(SRC_DIR)"/build/px4_sitl_default-clang
# Paths to exclude from clang-tidy (auto-generated from .gitmodules + manual additions):
# - All submodules (external code we consume, not edit)
# - Test code (allowed looser style)
# - Example code (educational, not production)
# - Vendored third-party code (e.g., CMSIS_5)
# - NuttX-only drivers excluded at CMake level (mcp_common); I2C-dependent libs excluded here (smbus)
# - GPIO excluded here (NuttX platform headers)
# - Emscripten failsafe web build: source path + Unity build path (failsafe_test.dir)
# because CMake Unity Builds merge sources into a generated .cxx under build/
#
# To add manual exclusions, append to CLANG_TIDY_EXCLUDE_EXTRA below.
# Submodules are automatically excluded - no action needed when adding new ones.
CLANG_TIDY_SUBMODULES := $(shell git config --file .gitmodules --get-regexp path | awk '{print $$2}' | tr '\n' '|' | sed 's/|$$//')
CLANG_TIDY_EXCLUDE_EXTRA := src/systemcmds/tests|src/examples|src/modules/gyro_fft/CMSIS_5|src/lib/drivers/smbus|src/drivers/gpio|src/modules/commander/failsafe/emscripten|failsafe_test\.dir|\.pb\.cc
CLANG_TIDY_EXCLUDE := $(CLANG_TIDY_SUBMODULES)|$(CLANG_TIDY_EXCLUDE_EXTRA)
clang-tidy: px4_sitl_default-clang
@cd "$(SRC_DIR)"/build/px4_sitl_default-clang && "$(SRC_DIR)"/Tools/run-clang-tidy.py -header-filter=".*\.hpp" -j$(j_clang_tidy) -p .
@cd "$(SRC_DIR)"/build/px4_sitl_default-clang && "$(SRC_DIR)"/Tools/run-clang-tidy.py -header-filter=".*\.hpp" -j$(j_clang_tidy) -exclude="$(CLANG_TIDY_EXCLUDE)" -p .
# to automatically fix a single check at a time, eg modernize-redundant-void-arg
# % run-clang-tidy-4.0.py -fix -j4 -checks=-\*,modernize-redundant-void-arg -p .
clang-tidy-fix: px4_sitl_default-clang
@cd "$(SRC_DIR)"/build/px4_sitl_default-clang && "$(SRC_DIR)"/Tools/run-clang-tidy.py -header-filter=".*\.hpp" -j$(j_clang_tidy) -fix -p .
@cd "$(SRC_DIR)"/build/px4_sitl_default-clang && "$(SRC_DIR)"/Tools/run-clang-tidy.py -header-filter=".*\.hpp" -j$(j_clang_tidy) -exclude="$(CLANG_TIDY_EXCLUDE)" -fix -p .
# TODO: Fix cppcheck errors then try --enable=warning,performance,portability,style,unusedFunction or --enable=all
cppcheck: px4_sitl_default
@@ -101,6 +101,7 @@ param set-default NAV_ACC_RAD 5
param set-default NAV_DLL_ACT 2
param set-default VT_FWD_THRUST_EN 4
param set-default VT_PITCH_MIN -5
param set-default VT_F_TRANS_THR 1
param set-default VT_TYPE 2
param set-default FD_ESCS_EN 0
@@ -22,6 +22,9 @@
. ${R}etc/init.d/rc.uuv_defaults
# Overwrite DDS AG IP to `192.168.0.1`
param set-default UXRCE_DDS_AG_IP -1062731775
# param set-default MAV_1_CONFIG 102
param set-default BAT1_A_PER_V 37.8798
@@ -10,9 +10,6 @@ set VEHICLE_TYPE uuv
# MAV_TYPE_SUBMARINE 12
param set-default MAV_TYPE 12
# Set micro-dds-client to use ethernet and IP-address 192.168.0.1
param set-default UXRCE_DDS_AG_IP -1062731775
# Disable preflight disarm to not interfere with external launching
param set-default COM_DISARM_PRFLT -1
param set-default CBRK_SUPPLY_CHK 894281
+4 -24
View File
@@ -1,47 +1,27 @@
#! /bin/bash
if [ -z ${PX4_DOCKER_REPO+x} ]; then
echo "guessing PX4_DOCKER_REPO based on input";
if [[ $@ =~ .*clang.* ]] || [[ $@ =~ .*scan-build.* ]]; then
# clang tools
PX4_DOCKER_REPO="px4io/px4-dev-clang:2021-02-04"
elif [[ $@ =~ .*tests* ]]; then
# run all tests with simulation
PX4_DOCKER_REPO="px4io/px4-dev-simulation-bionic:2021-12-11"
fi
PX4_DOCKER_REPO="px4io/px4-dev:v1.17.0-beta1"
else
echo "PX4_DOCKER_REPO is set to '$PX4_DOCKER_REPO'";
fi
# otherwise default to nuttx
if [ -z ${PX4_DOCKER_REPO+x} ]; then
PX4_DOCKER_REPO="px4io/px4-dev:v1.16.0-rc1-258-g0369abd556"
fi
echo "PX4_DOCKER_REPO: $PX4_DOCKER_REPO";
PWD=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
SRC_DIR=$PWD/../
SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
SRC_DIR=${SCRIPT_DIR}/../
CCACHE_DIR=${HOME}/.ccache
mkdir -p "${CCACHE_DIR}"
docker run -it --rm -w "${SRC_DIR}" \
--user="$(id -u):$(id -g)" \
--env=AWS_ACCESS_KEY_ID \
--env=AWS_SECRET_ACCESS_KEY \
--env=BRANCH_NAME \
--env=CCACHE_DIR="${CCACHE_DIR}" \
--env=CI \
--env=CODECOV_TOKEN \
--env=COVERALLS_REPO_TOKEN \
--env=PX4_ASAN \
--env=PX4_MSAN \
--env=PX4_TSAN \
--env=PX4_UBSAN \
--env=TRAVIS_BRANCH \
--env=TRAVIS_BUILD_ID \
--publish 14556:14556/udp \
--volume=${CCACHE_DIR}:${CCACHE_DIR}:rw \
--volume=${SRC_DIR}:${SRC_DIR}:rw \
${PX4_DOCKER_REPO} /bin/bash -c "$1 $2 $3"
${PX4_DOCKER_REPO} /bin/bash -c "$@"
+5
View File
@@ -144,6 +144,8 @@ def main():
help='number of tidy instances to be run in parallel.')
parser.add_argument('files', nargs='*', default=['.*'],
help='files to be processed (regex on path)')
parser.add_argument('-exclude', dest='exclude', default=None,
help='regular expression matching files to exclude')
parser.add_argument('-fix', action='store_true', help='apply fix-its')
parser.add_argument('-format', action='store_true', help='Reformat code '
'after applying fixes')
@@ -192,6 +194,7 @@ def main():
# Build up a big regexy filter from all command line arguments.
file_name_re = re.compile('(' + ')|('.join(args.files) + ')')
exclude_re = re.compile(args.exclude) if args.exclude else None
try:
# Spin up a bunch of tidy-launching threads.
@@ -205,6 +208,8 @@ def main():
# Fill the queue with files.
for name in files:
if file_name_re.search(name):
if exclude_re and exclude_re.search(name):
continue
queue.put(name)
# Wait for all threads to be done.
+1 -3
View File
@@ -4,7 +4,7 @@ GREEN='\033[0;32m'
NO_COLOR='\033[0m' # No Color
SCRIPTID="${GREEN}[docker-entrypoint.sh]${NO_COLOR}"
echo -e "$SCRIPTID Starting"
echo -e "$SCRIPTID $( uname -m ) | $(date -u +%FT%TZ)"
# Start virtual X server in the background
# - DISPLAY default is :99, set in dockerfile
@@ -22,6 +22,4 @@ if [ -n "${ROS_DISTRO}" ]; then
source "/opt/ros/$ROS_DISTRO/setup.bash"
fi
echo -e "$SCRIPTID ($( uname -m ))"
exec "$@"
+12 -31
View File
@@ -6,9 +6,9 @@ set -e
## Can also be used in docker.
##
## Installs:
## - Common dependencies and tools for nuttx, jMAVSim, Gazebo
## - Common dependencies and tools for nuttx, Gazebo
## - NuttX toolchain (omit with arg: --no-nuttx)
## - jMAVSim and Gazebo9 simulator (omit with arg: --no-sim-tools)
## - Gazebo Harmonic simulator (omit with arg: --no-sim-tools)
##
INSTALL_NUTTX="true"
@@ -207,37 +207,18 @@ if [[ $INSTALL_SIM == "true" ]]; then
bc \
;
# Gazebo / Gazebo classic installation
if [[ "${UBUNTU_RELEASE}" == "18.04" || "${UBUNTU_RELEASE}" == "20.04" ]]; then
sudo sh -c 'echo "deb http://packages.osrfoundation.org/gazebo/ubuntu-stable `lsb_release -cs` main" > /etc/apt/sources.list.d/gazebo-stable.list'
wget http://packages.osrfoundation.org/gazebo.key -O - | sudo apt-key add -
# Update list, since new gazebo-stable.list has been added
sudo apt-get update -y --quiet
# Gazebo Harmonic installation (Ubuntu 22.04+)
echo "[ubuntu.sh] Gazebo (Harmonic) will be installed"
# Add Gazebo binary repository
sudo wget https://packages.osrfoundation.org/gazebo.gpg -O /usr/share/keyrings/pkgs-osrf-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/pkgs-osrf-archive-keyring.gpg] http://packages.osrfoundation.org/gazebo/ubuntu-stable $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/gazebo-stable.list > /dev/null
sudo apt-get update -y --quiet
# Install Gazebo classic
if [[ "${UBUNTU_RELEASE}" == "18.04" ]]; then
gazebo_classic_version=9
gazebo_packages="gazebo$gazebo_classic_version libgazebo$gazebo_classic_version-dev"
else
# default and Ubuntu 20.04
gazebo_classic_version=11
gazebo_packages="gazebo$gazebo_classic_version libgazebo$gazebo_classic_version-dev"
fi
else
# Expects Ubuntu 22.04 > by default
echo "[ubuntu.sh] Gazebo (Harmonic) will be installed"
echo "[ubuntu.sh] Earlier versions will be removed"
# Add Gazebo binary repository
sudo wget https://packages.osrfoundation.org/gazebo.gpg -O /usr/share/keyrings/pkgs-osrf-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/pkgs-osrf-archive-keyring.gpg] http://packages.osrfoundation.org/gazebo/ubuntu-stable $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/gazebo-stable.list > /dev/null
sudo apt-get update -y --quiet
# Install Gazebo
gazebo_packages="gz-harmonic libunwind-dev"
# Install Gazebo
gazebo_packages="gz-harmonic libunwind-dev"
if [[ "${UBUNTU_RELEASE}" == "24.04" ]]; then
gazebo_packages="$gazebo_packages cppzmq-dev"
fi
if [[ "${UBUNTU_RELEASE}" == "24.04" ]]; then
gazebo_packages="$gazebo_packages cppzmq-dev"
fi
sudo DEBIAN_FRONTEND=noninteractive apt-get -y --quiet --no-install-recommends install \
+2 -2
View File
@@ -66,15 +66,15 @@ then
fi
fi
iim42652 -R 6 -s -C 32768 start
bmi088 -A -R 4 -s start
bmi088 -G -R 4 -s start
iim42652 -R 6 -s -C 32768 start
icm45686 -R 2 -s start
rm3100 -I -b 4 start
icp201xx -I -a 0x64 start
bmp581 -b 2 -X -a 0x47 start
icp201xx -I -a 0x64 start
# External compass on GPS1/I2C1 (the 3rd external bus): standard Holybro Pixhawk 4 or CUAV V5 GPS/compass puck (with lights, safety button, and buzzer)
ist8310 -X -b 1 -R 10 start
+2 -2
View File
@@ -127,8 +127,8 @@
#define GPIO_VDD_5V_RC_EN /* PG5 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTG|GPIO_PIN5)
#define GPIO_VDD_3V3_SD_CARD_EN /* PG7 */ (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTG|GPIO_PIN7)
#define GPIO_VDD_5V_HIPOWER_OC /* PJ3 */ (GPIO_INPUT|GPIO_FLOAT|GPIO_PORTJ|GPIO_PIN3)
#define GPIO_nVDD_5V_PERIPH_OC /* PJ4 */ (GPIO_INPUT|GPIO_FLOAT|GPIO_PORTJ|GPIO_PIN4)
#define GPIO_VDD_5V_HIPOWER_OC /* PJ3 */ (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTJ|GPIO_PIN3)
#define GPIO_nVDD_5V_PERIPH_OC /* PJ4 */ (GPIO_INPUT|GPIO_PULLUP|GPIO_PORTJ|GPIO_PIN4)
/* Power switch controls ******************************************************/
#define VDD_5V_PERIPH_EN(on_true) px4_arch_gpiowrite(GPIO_nVDD_5V_PERIPH_EN, (on_true))
+1
View File
@@ -19,6 +19,7 @@ CONFIG_COMMON_DIFFERENTIAL_PRESSURE=y
CONFIG_DRIVERS_DIFFERENTIAL_PRESSURE_AUAV=y
CONFIG_COMMON_DISTANCE_SENSOR=y
CONFIG_DRIVERS_DISTANCE_SENSOR_LIGHTWARE_SF45_SERIAL=y
CONFIG_DRIVERS_DISTANCE_SENSOR_LIGHTWARE_GRF_SERIAL=y
CONFIG_DRIVERS_DSHOT=y
CONFIG_DRIVERS_GNSS_SEPTENTRIO=y
CONFIG_DRIVERS_GPS=y
@@ -1056,9 +1056,6 @@
1 1 UAVCAN_EC_REV 0 6
1 1 UAVCAN_ENABLE 2 6
1 1 UAVCAN_LGT_ANTCL 2 6
1 1 UAVCAN_LGT_LAND 0 6
1 1 UAVCAN_LGT_NAV 3 6
1 1 UAVCAN_LGT_STROB 1 6
1 1 UAVCAN_NODE_ID 1 6
1 1 UAVCAN_PUB_ARM 0 6
1 1 UAVCAN_PUB_MBD 0 6
Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

+1
View File
@@ -255,6 +255,7 @@
- [Lidar-Lite](sensor/lidar_lite.md)
- [Lightware Lidars (SF/LW/GRF)](sensor/sfxx_lidar.md)
- [Lightware SF45 Rotary Lidar](sensor/sf45_rotating_lidar.md)
- [Lightware GRF250/GRF500 Gimbal Lidar](sensor/grf_lidar.md)
- [TeraRanger](sensor/teraranger.md)
- [✘ Lanbao PSK-CM8JL65-CC5](sensor/cm8jl65_ir_distance_sensor.md)
- [Avionics Anonymous Laser Altimeter UAVCAN Interface (CAN)](dronecan/avanon_laser_interface.md)
+191 -45
View File
@@ -19596,6 +19596,18 @@ Launch is detected when acceleration in body forward direction is above FW_LAUN_
| ------ | -------- | -------- | --------- | ------- | ----- |
| &nbsp; | 0 | | 0.5 | 30.0 | m/s^2 |
### FW_LAUN_CS_LK_DY (`FLOAT`) {#FW_LAUN_CS_LK_DY}
Control surface launch delay.
Locks control surfaces during pre-launch (armed) and until this time since launch has passed.
Only affects control surfaces that have corresponding flag set, and not active for runway takeoff.
Set to 0 to disable any surface locking after arming.
| Reboot | minValue | maxValue | increment | default | unit |
| ------ | -------- | -------- | --------- | ------- | ---- |
| &nbsp; | 0.0 | | 0.1 | 0. | s |
### FW_LAUN_DETCN_ON (`INT32`) {#FW_LAUN_DETCN_ON}
Fixed-wing launch detection.
@@ -21325,6 +21337,27 @@ Some are generic, while others are specifically fit to a certain vehicle with a
| ------ | -------- | -------- | --------- | ------- | ---- |
| &nbsp; | | | | 0 |
### CA_CS_LAUN_LK (`INT32`) {#CA_CS_LAUN_LK}
Control surface launch lock enabled.
If actuator launch lock is enabled, this surface is kept at the disarmed value.
**Bitmask:**
- `0`: Control Surface 1
- `1`: Control Surface 2
- `2`: Control Surface 3
- `3`: Control Surface 4
- `4`: Control Surface 5
- `5`: Control Surface 6
- `6`: Control Surface 7
- `7`: Control Surface 8
| Reboot | minValue | maxValue | increment | default | unit |
| ------ | -------- | -------- | --------- | ------- | ---- |
| &nbsp; | 0 | 255 | | 0 |
### CA_FAILURE_MODE (`INT32`) {#CA_FAILURE_MODE}
Motor failure handling mode.
@@ -33078,6 +33111,44 @@ Use SENS_MAG_SIDES instead
| ------ | -------- | -------- | --------- | ------- | ---- |
| &nbsp; | | | | 63 |
### GRF_RATE_CFG (`INT32`) {#GRF_RATE_CFG}
Lightware GRF lidar update rate.
The Lightware GRF distance sensor can increase the update rate to enable greater resolution.
**Values:**
- `1`: 1 Hz
- `2`: 2 Hz
- `3`: 4 Hz
- `4`: 5 Hz
- `5`: 10 Hz
- `6`: 20 Hz
- `7`: 30 Hz
- `8`: 40 Hz
- `9`: 50 Hz
| Reboot | minValue | maxValue | increment | default | unit |
| ------- | -------- | -------- | --------- | ------- | ---- |
| &check; | | | | 4 |
### GRF_SENS_MODEL (`INT32`) {#GRF_SENS_MODEL}
GRF Sensor model.
GRF Sensor Model used to distinush between the GRF250 and GRF500 since both have different max distance range.
**Values:**
- `0`: disable
- `1`: GRF250
- `2`: GRF500
| Reboot | minValue | maxValue | increment | default | unit |
| ------- | -------- | -------- | --------- | ------- | ---- |
| &check; | | | | 0 |
### ILABS_MODE (`INT32`) {#ILABS_MODE}
InertialLabs INS sensor mode configuration.
@@ -34286,6 +34357,31 @@ Enable simulated GPS sinstance.
| ------- | -------- | -------- | --------- | ------- | ---- |
| &check; | 0 | 1 | | 0 |
### SENS_EN_GRF_CFG (`INT32`) {#SENS_EN_GRF_CFG}
Serial Configuration for Lightware GRF Rangefinder (serial).
Configure on which serial port to run Lightware GRF Rangefinder (serial).
**Values:**
- `0`: Disabled
- `6`: UART 6
- `101`: TELEM 1
- `102`: TELEM 2
- `103`: TELEM 3
- `104`: TELEM/SERIAL 4
- `201`: GPS 1
- `202`: GPS 2
- `203`: GPS 3
- `300`: Radio Controller
- `301`: Wifi Port
- `401`: EXT2
| Reboot | minValue | maxValue | increment | default | unit |
| ------- | -------- | -------- | --------- | ------- | ---- |
| &check; | | | | 0 |
### SENS_EN_INA220 (`INT32`) {#SENS_EN_INA220}
Enable INA220 Power Monitor.
@@ -34511,7 +34607,7 @@ Lightware Laser Rangefinder hardware model (serial).
### SENS_EN_SF1XX (`INT32`) {#SENS_EN_SF1XX}
Lightware SF1xx/SF20/LW20 laser rangefinder (i2c).
Lightware laser rangefinder (i2c).
**Values:**
@@ -35686,6 +35782,26 @@ Configure on which serial port to run VectorNav (VN-100, VN-200, VN-300).
| ------- | -------- | -------- | --------- | ------- | ---- |
| &check; | | | | 0 |
### SF1XX_ROT (`INT32`) {#SF1XX_ROT}
Lightware laser rangefinder Rotation.
Distance sensor orientation as MAV_SENSOR_ORIENTATION enum.
Applies to all models supported by SENS_EN_SF1XX.
**Values:**
- `0`: Forward
- `2`: Right
- `4`: Backward
- `6`: Left
- `24`: Upward
- `25`: Downward
| Reboot | minValue | maxValue | increment | default | unit |
| ------- | -------- | -------- | --------- | ------- | ---- |
| &check; | 0 | 25 | | 25 |
### SF45_ORIENT_CFG (`INT32`) {#SF45_ORIENT_CFG}
Orientation upright or facing downward.
@@ -40288,7 +40404,7 @@ starve other nodes on the bus.
UAVCAN ANTI_COLLISION light operating mode.
This parameter defines the minimum condition under which the system will command
the ANTI_COLLISION lights on
lights with anti-collision function to turn on (white).
0 - Always off
1 - When autopilot is armed
2 - When autopilot is prearmed
@@ -40305,67 +40421,97 @@ the ANTI_COLLISION lights on
| ------- | -------- | -------- | --------- | ------- | ---- |
| &check; | 0 | 3 | | 2 |
### UAVCAN_LGT_LAND (`INT32`) {#UAVCAN_LGT_LAND}
### UAVCAN_LGT_FN0 (`INT32`) {#UAVCAN_LGT_FN0}
UAVCAN LIGHT_ID_LANDING light operating mode.
Light 0 function.
This parameter defines the minimum condition under which the system will command
the LIGHT_ID_LANDING lights on
0 - Always off
1 - When autopilot is armed
2 - When autopilot is prearmed
3 - Always on
Function assigned to light 0.
0: Status - displays system status colors
1: Anti-collision - white beacon controlled by LGT_ANTCL parameter
**Values:**
- `0`: Always off
- `1`: When autopilot is armed
- `2`: When autopilot is prearmed
- `3`: Always on
- `0`: Status Light
- `1`: Anti-collision Light
| Reboot | minValue | maxValue | increment | default | unit |
| ------- | -------- | -------- | --------- | ------- | ---- |
| &check; | 0 | 3 | | 0 |
| Reboot | minValue | maxValue | increment | default | unit |
| ------ | -------- | -------- | --------- | ------- | ---- |
| &nbsp; | 0 | 1 | | 0 |
### UAVCAN_LGT_NAV (`INT32`) {#UAVCAN_LGT_NAV}
### UAVCAN_LGT_FN1 (`INT32`) {#UAVCAN_LGT_FN1}
UAVCAN RIGHT_OF_WAY light operating mode.
Light 1 function.
This parameter defines the minimum condition under which the system will command
the RIGHT_OF_WAY lights on
0 - Always off
1 - When autopilot is armed
2 - When autopilot is prearmed
3 - Always on
Function assigned to light 1.
0: Status - displays system status colors
1: Anti-collision - white beacon controlled by LGT_ANTCL parameter
**Values:**
- `0`: Always off
- `1`: When autopilot is armed
- `2`: When autopilot is prearmed
- `3`: Always on
- `0`: Status Light
- `1`: Anti-collision Light
| Reboot | minValue | maxValue | increment | default | unit |
| ------- | -------- | -------- | --------- | ------- | ---- |
| &check; | 0 | 3 | | 3 |
| Reboot | minValue | maxValue | increment | default | unit |
| ------ | -------- | -------- | --------- | ------- | ---- |
| &nbsp; | 0 | 1 | | 0 |
### UAVCAN_LGT_STROB (`INT32`) {#UAVCAN_LGT_STROB}
### UAVCAN_LGT_FN2 (`INT32`) {#UAVCAN_LGT_FN2}
UAVCAN STROBE light operating mode.
Light 2 function.
This parameter defines the minimum condition under which the system will command
the STROBE lights on
0 - Always off
1 - When autopilot is armed
2 - When autopilot is prearmed
3 - Always on
Function assigned to light 2.
0: Status - displays system status colors
1: Anti-collision - white beacon controlled by LGT_ANTCL parameter
**Values:**
- `0`: Always off
- `1`: When autopilot is armed
- `2`: When autopilot is prearmed
- `3`: Always on
- `0`: Status Light
- `1`: Anti-collision Light
| Reboot | minValue | maxValue | increment | default | unit |
| ------ | -------- | -------- | --------- | ------- | ---- |
| &nbsp; | 0 | 1 | | 0 |
### UAVCAN_LGT_ID0 (`INT32`) {#UAVCAN_LGT_ID0}
Light 0 ID.
specifies the light_id value for light 0 in UAVCAN LightsCommand messages.
This determines which physical LED responds to commands for this light slot.
| Reboot | minValue | maxValue | increment | default | unit |
| ------ | -------- | -------- | --------- | ------- | ---- |
| &nbsp; | 0 | 255 | | 0 |
### UAVCAN_LGT_ID1 (`INT32`) {#UAVCAN_LGT_ID1}
Light 1 ID.
specifies the light_id value for light 1 in UAVCAN LightsCommand messages.
This determines which physical LED responds to commands for this light slot.
| Reboot | minValue | maxValue | increment | default | unit |
| ------ | -------- | -------- | --------- | ------- | ---- |
| &nbsp; | 0 | 255 | | 0 |
### UAVCAN_LGT_ID2 (`INT32`) {#UAVCAN_LGT_ID2}
Light 2 ID.
specifies the light_id value for light 2 in UAVCAN LightsCommand messages.
This determines which physical LED responds to commands for this light slot.
| Reboot | minValue | maxValue | increment | default | unit |
| ------ | -------- | -------- | --------- | ------- | ---- |
| &nbsp; | 0 | 255 | | 0 |
### UAVCAN_LGT_NUM (`INT32`) {#UAVCAN_LGT_NUM}
Number of UAVCAN lights to configure.
Number of lights to control via UAVCAN LightsCommand messages.
Set to 0 to disable UAVCAN light control.
Each light uses two parameters: LGT_IDx for the light_id and LGT_FNx for the function.
| Reboot | minValue | maxValue | increment | default | unit |
| ------- | -------- | -------- | --------- | ------- | ---- |
@@ -42484,7 +42630,7 @@ Gyro filter settings.
### SF1XX_MODE (`INT32`) {#SF1XX_MODE}
Lightware SF1xx/SF20/LW20 Operation Mode.
Lightware laser rangefinder Operation Mode.
**Values:**
+26 -11
View File
@@ -181,17 +181,22 @@ The following settings also apply, but are not displayed in the QGC UI.
| <a id="GF_PREDICT"></a>Preemptive geofence triggering | [GF_PREDICT](../advanced_config/parameter_reference.md#GF_PREDICT) | (Experimental) Trigger geofence if current motion of the vehicle is predicted to trigger the breach (rather than late triggering after the breach). |
| <a id="CBRK_FLIGHTTERM"></a>Circuit breaker for flight termination | [CBRK_FLIGHTTERM](../advanced_config/parameter_reference.md#CBRK_FLIGHTTERM) | Enables/Disables flight termination action (disabled by default). |
## Position (GNSS) Loss Failsafe
## Position Estimation Failsafes
This section describes failsafes related to the quality of the vehicle's position estimate.
### Position Loss Failsafe
The _Position Loss Failsafe_ is triggered if the quality of the PX4 position estimate falls below acceptable levels (this might be caused by GPS loss) while in a mode that requires an acceptable position estimate.
The sections below cover first the trigger and then the failsafe action taken by the controller.
### Position Loss Failsafe Trigger
There are basically two mechanisms in PX4 to trigger position failsafes:
The position loss failsafe triggers if the position estimate becomes _invalid_. There are two mechanisms in PX4 to invalidate the position estimate:
- A timeout since the last sensor data was fused that provides direct speed or horizontal position measurements. Sensors that fall into that category are: GNSS, optical flow, airspeed, VIO, auxiliary global position.
- The estimated horizontal position accuracy exceeds a certain threshold. This check is only done on hovering systems (rotary wing vehicles or VTOLs in hover phase).
- A timeout since the last sensor data was fused that provides direct speed or horizontal position measurements.
- Sensors that fall into that category are: GNSS, optical flow, airspeed, VIO, auxiliary global position.
- The estimated horizontal position inaccuracy exceeds the threshold [COM_POS_LOW_EPH](../advanced_config/parameter_reference.md#COM_POS_LOW_EPH)
- This check is only done on hovering systems (rotary-wing vehicles or VTOLs in hover phase). For fixed-wing vehicles, refer to the [Position Accuracy Low](#position-accuracy-low-failsafe) section.
The relevant parameters shown below.
@@ -207,14 +212,24 @@ Multicopters will switch to [Altitude mode](../flight_modes_mc/altitude.md) if a
Fixed-wing planes, and VTOLs not configured to land in hover ([NAV_FORCE_VT](../advanced_config/parameter_reference.md#NAV_FORCE_VT)), have a parameter ([FW_GPSF_LT](../advanced_config/parameter_reference.md#FW_GPSF_LT)) that defines how long they will loiter (circle with a constant roll angle ([FW_GPSF_R](../advanced_config/parameter_reference.md#FW_GPSF_R)) at the current altitude) after losing position before attempting to land.
If VTOLs have are configured to switch to hover for landing ([NAV_FORCE_VT](../advanced_config/parameter_reference.md#NAV_FORCE_VT)) then they will first transition and then descend.
The relevant parameters for all vehicles shown below.
The relevant parameters are:
Parameters that only affect Fixed-wing vehicles:
| Parameter | Description |
| ----------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| <a id="FW_GPSF_LT"></a>[FW_GPSF_LT](../advanced_config/parameter_reference.md#FW_GPSF_LT) | Fixed-wing only: Loiter time (waiting at current altitude for position estimation recovery before starting to descend). Set to 0 to disable. |
| <a id="FW_GPSF_R"></a>[FW_GPSF_R](../advanced_config/parameter_reference.md#FW_GPSF_R) | Fixed roll/bank angle while circling. |
| <a id="NAV_FORCE_VT"></a>[NAV_FORCE_VT](../advanced_config/parameter_reference.md#NAV_FORCE_VT) | If true, force VTOL takeoff and landing, even in `Descend` failsafe. |
| Parameter | Description |
| ----------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| <a id="FW_GPSF_LT"></a>[FW_GPSF_LT](../advanced_config/parameter_reference.md#FW_GPSF_LT) | Loiter time (waiting for GPS recovery before it goes into land or flight termination). Set to 0 to disable. |
| <a id="FW_GPSF_R"></a>[FW_GPSF_R](../advanced_config/parameter_reference.md#FW_GPSF_R) | Fixed roll/bank angle while circling. |
### Position Accuracy Low Failsafe
In Fixed-wing, the position estimate is never strictly invalidated as long as we have a horizontal aiding source, such as an airspeed sensor. In that case, a separate failsafe can be configured that triggers if the position estimate inacuraccy exceeds the threshold [COM_POS_LOW_EPH](../advanced_config/parameter_reference.md#COM_POS_LOW_EPH). The failsafe action is taken if the vehicle is in mission or hold mode, otherwise it is only a warning. The relevant parameters are:
| Parameter | Description |
| -------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
| <a id="COM_POS_LOW_EPH"></a>[COM_POS_LOW_EPH](../advanced_config/parameter_reference.md#COM_POS_LOW_EPH) | Position inaccuracy threshold above which COM_POS_LOW_ACT is taken. |
| <a id="COM_POS_LOW_ACT"></a>[COM_POS_LOW_ACT](../advanced_config/parameter_reference.md#COM_POS_LOW_ACT) | Failsafe action taken when position inaccuracy is above configured threshold. |
Note that if there is no horizontal aiding source anymore, the position estimate is invalidated after `EKF2_NOAID_TOUT`, and the standard position loss failsafe applies.
## Offboard Loss Failsafe
+18 -41
View File
@@ -39,15 +39,6 @@ Navigate into the **PX4-Autopilot** directory and start [Gazebo SITL](../sim_gaz
make px4_sitl gz_x500
```
::: details If you installed Gazebo Classic
Start [Gazebo Classic SITL](../sim_gazebo_classic/index.md) using the following command:
```sh
make px4_sitl gazebo-classic
```
:::
This will bring up the PX4 console:
![PX4 Console](../../assets/toolchain/console_gazebo.png)
@@ -88,6 +79,16 @@ cd PX4-Autopilot
make px4_fmu-v5_default
```
:::tip
You can also build using the [px4-dev Docker container](../test_and_ci/docker.md) without installing the toolchain locally.
From the PX4-Autopilot directory:
```sh
./Tools/docker_run.sh 'make px4_fmu-v5_default'
```
:::
A successful run will end with similar output to:
```sh
@@ -126,7 +127,8 @@ The following list shows the build commands for the [Pixhawk standard](../flight
- [Pixhawk 1 (FMUv2)](../flight_controller/pixhawk.md): `make px4_fmu-v2_default`
:::warning
You **must** use a supported version of GCC to build this board (e.g. the same as used by [CI/docker](../test_and_ci/docker.md)) or remove modules from the build. Building with an unsupported GCC may fail, as PX4 is close to the board's 1MB flash limit.
You **must** use a supported version of GCC to build this board (e.g. the `gcc-arm-none-eabi` package from the current Ubuntu LTS, which is the same toolchain used by CI) or remove modules from the build.
Building with an unsupported GCC may fail, as PX4 is close to the board's 1MB flash limit.
:::
- Pixhawk 1 with 2 MB flash: `make px4_fmu-v3_default`
@@ -191,7 +193,7 @@ The `region 'flash' overflowed by XXXX bytes` error indicates that the firmware
This is common for `make px4_fmu-v2_default` builds, where the flash size is limited to 1MB.
If you're building the _vanilla_ master branch, the most likely cause is using an unsupported version of GCC.
In this case, install the version specified in the [Developer Toolchain](../dev_setup/dev_env.md) instructions.
In this case, install the `gcc-arm-none-eabi` package from the current Ubuntu LTS as described in the [Developer Toolchain](../dev_setup/dev_env.md) instructions.
If building your own branch, it is possible that you have increased the firmware size over the 1MB limit.
In this case you will need to remove any drivers/modules that you don't need from the build.
@@ -204,7 +206,7 @@ The PX4 build system opens a large number of files, so you may exceed this numbe
The build toolchain will then report `Too many open files` for many files, as shown below:
```sh
/usr/local/Cellar/gcc-arm-none-eabi/20171218/bin/../lib/gcc/arm-none-eabi/7.2.1/../../../../arm-none-eabi/bin/ld: cannot find NuttX/nuttx/fs/libfs.a: Too many open files
arm-none-eabi-ld: cannot find NuttX/nuttx/fs/libfs.a: Too many open files
```
The solution is to increase the maximum allowed number of open files (e.g. to 300).
@@ -227,34 +229,9 @@ xcode-select --install
sudo ln -s /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/* /usr/local/include/
```
### Ubuntu 18.04: Compile errors involving arm_none_eabi_gcc
Build issues related to `arm_none_eabi_gcc`may be due to a broken g++ toolchain installation.
You can verify that this is the case by checking for missing dependencies using:
```sh
arm-none-eabi-gcc --version
arm-none-eabi-g++ --version
arm-none-eabi-gdb --version
arm-none-eabi-size --version
```
Example of bash output with missing dependencies:
```sh
arm-none-eabi-gdb --version
arm-none-eabi-gdb: command not found
```
This can be resolved by removing and [reinstalling the compiler](https://askubuntu.com/questions/1243252/how-to-install-arm-none-eabi-gdb-on-ubuntu-20-04-lts-focal-fossa).
### Ubuntu 18.04: Visual Studio Code is unable to watch for file changes in this large workspace
See [Visual Studio Code IDE (VSCode) > Troubleshooting](../dev_setup/vscode.md#troubleshooting).
### Failed to import Python packages
"Failed to import" errors when running the `make px4_sitl jmavsim` command indicates that some Python packages are not installed (where expected).
"Failed to import" errors when running the `make px4_sitl gz_x500` command indicates that some Python packages are not installed (where expected).
```sh
Failed to import jinja2: No module named 'jinja2'
@@ -262,12 +239,12 @@ You may need to install it using:
pip3 install --user jinja2
```
If you have already installed these dependencies this may be because there is more than one Python version on the computer (e.g. Python 2.7.16 Python 3.8.3), and the module is not present in the version used by the build toolchain.
If you have already installed these dependencies this may be because there is more than one Python version on the computer (e.g. Python 2.7.16 and Python 3.8.3), and the module is not present in the version used by the build toolchain.
You should be able to fix this by explicitly installing the dependencies as shown:
You should be able to fix this by installing the dependencies from the repository's requirements file:
```sh
pip3 install --user pyserial empty toml numpy pandas jinja2 pyyaml pyros-genmsg packaging
pip3 install --user -r Tools/setup/requirements.txt
```
## PX4 Make Build Targets
+4 -4
View File
@@ -20,7 +20,7 @@ The equipment below is highly recommended:
:::
- Lenovo Thinkpad with i5-core running Windows 11
- MacBook Pro (early 2015 and later) with macOS 10.15 or later
- Lenovo Thinkpad i5 with Ubuntu Linux 20.04 or later
- Lenovo Thinkpad i5 with Ubuntu Linux 22.04 or later
- **Ground control station** (computer or tablet):
- iPad (may require Wifi telemetry adapter)
@@ -39,9 +39,9 @@ Install the [QGroundControl Daily Build](../dev_setup/qgc_daily_build.md) for a
To configure the vehicle:
1. [Install PX4 firmware](../config/firmware.md#installing-px4-main-beta-or-custom-firmware) (including "custom" firmware with your own changes).
1. [Start with the airframe](../config/airframe.md) that best-matches your vehicle from the [airframe reference](../airframes/airframe_reference.md).
1. [Basic Configuration](../config/index.md) explains how to perform basic configuration.
1. [Parameter Configuration](../advanced_config/parameters.md) explains how you can find and modify individual parameters.
2. [Start with the airframe](../config/airframe.md) that best-matches your vehicle from the [airframe reference](../airframes/airframe_reference.md).
3. [Basic Configuration](../config/index.md) explains how to perform basic configuration.
4. [Parameter Configuration](../advanced_config/parameters.md) explains how you can find and modify individual parameters.
::: info
+3 -3
View File
@@ -2,7 +2,7 @@
The _supported platforms_ for PX4 development are:
- [Ubuntu Linux (24.04/22.04)](../dev_setup/dev_env_linux_ubuntu.md) — Recommended
- [Ubuntu Linux (24.04/22.04)](../dev_setup/dev_env_linux_ubuntu.md)
- [Windows (10/11)](../dev_setup/dev_env_windows_wsl.md) — via WSL2
- [macOS](../dev_setup/dev_env_mac.md)
@@ -15,9 +15,9 @@ The table below shows what PX4 targets you can build on each OS.
| **NuttX based hardware:** [Pixhawk Series](../flight_controller/pixhawk_series.md), [Crazyflie](../complete_vehicles_mc/crazyflie2.md) | ✓ | ✓ | ✓ |
| **Linux-based hardware:** [Raspberry Pi 2/3](../flight_controller/raspberry_pi_navio2.md) | ✓ | | |
| **Simulation:** [Gazebo SITL](../sim_gazebo_gz/index.md) | ✓ | ✓ | ✓ |
| **Simulation:** [Gazebo Classic SITL](../sim_gazebo_classic/index.md) | ✓ | ✓ | ✓ |
| **Simulation:** [ROS with Gazebo Classic](../simulation/ros_interface.md) | ✓ | | ✓ |
| **Simulation:** ROS 2 with Gazebo | ✓ | | ✓ |
| **Simulation:** [Gazebo Classic SITL](../sim_gazebo_classic/index.md) | | ✓ | ✓ |
| **Simulation:** [ROS with Gazebo Classic](../simulation/ros_interface.md) | | | ✓ |
Experienced Docker users can also build with the containers used by our continuous integration system: [Docker Containers](../test_and_ci/docker.md)
+3 -2
View File
@@ -39,8 +39,9 @@ You may want to also install `python-pip` and `screen`.
Execute the script below to install GCC 7-2017-q4:
:::warning
This version of GCC is out of date.
At time of writing the current version on Ubuntu is `9-2020-q2-update` (see [focal nuttx docker file](https://github.com/PX4/PX4-containers/blob/master/docker/Dockerfile_nuttx-focal#L28))
This version of GCC is very outdated.
PX4 now uses the `gcc-arm-none-eabi` package from the current Ubuntu LTS (GCC 13.2.1 on Ubuntu 24.04).
This CentOS guide is community-maintained and may not produce working builds.
:::
```sh
+9 -16
View File
@@ -4,20 +4,14 @@ The following instructions use a bash script to set up the PX4 development envir
The environment includes:
- [Gazebo Simulator](../sim_gazebo_gz/index.md) ("Harmonic")
- [Build toolchain for Pixhawk (and other NuttX-based hardware)](../dev_setup/building_px4.md#nuttx-pixhawk-based-boards).
On Ubuntu 22.04:
- [Gazebo Classic Simulator](../sim_gazebo_classic/index.md) can be used instead of Gazebo.
Gazebo is nearing feature-parity with Gazebo-Classic on PX4, and will soon replace it for all use cases.
- [Gazebo Simulator](../sim_gazebo_gz/index.md) (Gazebo Harmonic)
- [Build toolchain for Pixhawk (and other NuttX-based hardware)](../dev_setup/building_px4.md#nuttx-pixhawk-based-boards) using the `gcc-arm-none-eabi` compiler from the Ubuntu package manager.
The build toolchain for other flight controllers, simulators, and working with ROS are discussed in the [Other Targets](#other-targets) section below.
::: details Can I use an older version of Ubuntu?
PX4 supports the current and last Ubuntu LTS release where possible.
Older releases are not supported (so you can't raise defects against them), but may still work.
For example, Gazebo Classic setup is included in our standard build instructions for macOS, Ubuntu 18.04 and 20.04, and Windows on WSL2 for the same hosts.
::: info
PX4 targets the **current Ubuntu LTS** (24.04) for CI and release builds, with the **previous LTS** (22.04) also supported.
Older Ubuntu versions are not supported and may not work.
:::
## Simulation and NuttX (Pixhawk) Targets
@@ -50,19 +44,18 @@ To install the toolchain:
- Acknowledge any prompts as the script progress.
- You can use the `--no-nuttx` and `--no-sim-tools` options to omit the NuttX and/or simulation tools.
3. If you need Gazebo Classic (Ubuntu 22.04 only) then you can manually remove Gazebo and install it by following the instructions in [Gazebo Classic > Installation](../sim_gazebo_classic/index.md#installation).
4. Restart the computer on completion.
3. Restart the computer on completion.
:::details Additional notes
These notes are provided "for information only":
- This setup is supported by the PX4 Dev Team.
The instructions may also work on other Debian Linux based systems.
- You can verify the NuttX installation by confirming the `gcc` version as shown:
- You can verify the NuttX installation by confirming `gcc` is available.
The version depends on your Ubuntu release (e.g. GCC 13.2.1 on Ubuntu 24.04):
```sh
$arm-none-eabi-gcc --version
$ arm-none-eabi-gcc --version
arm-none-eabi-gcc (15:13.2.rel1-2) 13.2.1 20231009
Copyright (C) 2023 Free Software Foundation, Inc.
+8 -8
View File
@@ -58,20 +58,20 @@ To install WSL2 with Ubuntu on a new installation of Windows 10 or 11:
wsl --install
```
- Ubuntu 20.04 ([Gazebo-Classic Simulation](../sim_gazebo_classic/index.md))
```sh
wsl --install -d Ubuntu-20.04
```
- Ubuntu 22.04 ([Gazebo Simulation](../sim_gazebo_gz/index.md))
```sh
wsl --install -d Ubuntu-22.04
```
- Ubuntu 24.04 ([Gazebo Simulation](../sim_gazebo_gz/index.md))
```sh
wsl --install -d Ubuntu-24.04
```
::: info
You can also install[Ubuntu 20.04](https://www.microsoft.com/store/productId/9MTTCL66CPXJ) and [Ubuntu 22.04](https://www.microsoft.com/store/productId/9PN20MSR04DW) from the store, which allows you to delete the application using the normal Windows Add/Remove settings:
You can also [Ubuntu 24.04](https://www.microsoft.com/store/productId/9nz3klhxdjp5) or [Ubuntu 22.04](https://www.microsoft.com/store/productId/9PN20MSR04DW) from Microsoft Store, which allows you to delete the application using the normal Windows Add/Remove settings.
:::
1. WSL will prompt you for a user name and password for the Ubuntu installation.
@@ -106,7 +106,7 @@ To open a WSL shell using a command prompt:
```
```sh
wsl -d Ubuntu-20.04
wsl -d Ubuntu-24.04
```
If you only have one version of Ubuntu, you can just use `wsl`.
+2 -2
View File
@@ -124,10 +124,10 @@ Once that is done you don't need to do anything else; the toolchain will automat
This section includes guidance on setup and build errors.
### Ubuntu 18.04: "Visual Studio Code is unable to watch for file changes in this large workspace"
### "Visual Studio Code is unable to watch for file changes in this large workspace"
This error surfaces on startup.
On some systems, there is an upper-limit of 8192 file handles imposed on applications, which means that VSCode might not be able to detect file modifications in `/PX4-Autopilot`.
On some systems, there is an upper-limit on file handles imposed on applications, which means that VSCode might not be able to detect file modifications in `/PX4-Autopilot`.
You can increase this limit to avoid the error, at the expense of memory consumption.
Follow the [instructions here](https://code.visualstudio.com/docs/setup/linux#_visual-studio-code-is-unable-to-watch-for-file-changes-in-this-large-workspace-error-enospc).
+13
View File
@@ -281,6 +281,19 @@ PX4 DroneCAN parameters:
Select the specific CAN interface(s) used for ESC data output using the [UAVCAN_ESC_IFACE](../advanced_config/parameter_reference.md#UAVCAN_ESC_IFACE) parameter (all that all interfaces are selected by default).
Note that DroneCAN ESCs should be on their own dedicated CAN interface(s) because ESC messages can saturate the bus and starve other nodes of bandwidth.
### Lights
PX4 can control LEDs via DroneCAN [LightsCommand](https://dronecan.github.io/Specification/7._List_of_standard_data_types/#lightscommand) messages.
Configuration:
1. Set [UAVCAN_LGT_NUM](../advanced_config/parameter_reference.md#UAVCAN_LGT_NUM) to the number of lights (0 disables). You might need to reopen the ground station to have parameters for new instances available.
2. For each light slot (0 to NUM-1), set:
- `UAVCAN_LGT_IDx`: The `light_id` matching your peripheral.
- `UAVCAN_LGT_FNx`: `Status` for system status colours, or `Anti-collision` for white beacon.
3. For anti-collision lights, [UAVCAN_LGT_ANTCL](../advanced_config/parameter_reference.md#UAVCAN_LGT_ANTCL) controls when they illuminate (off, armed, prearmed, always on).
4. Reboot for any changes to take effect.
## QGC CANNODE Parameter Configuration
QGroundControl can inspect and modify parameters belonging to CAN devices attached to the flight controller, provided the device are connected to the flight controller before QGC is started.
+3
View File
@@ -85,6 +85,7 @@ The vehicle always respects normal FW max/min throttle settings during takeoff (
In _catapult/hand-launch mode_ the vehicle waits to detect launch (based on acceleration trigger).
On launch it enables the motor(s) and climbs with the maximum climb rate [FW_T_CLMB_MAX](#FW_T_CLMB_MAX) while keeping the pitch setpoint above [FW_TKO_PITCH_MIN](#FW_TKO_PITCH_MIN).
Once it reaches [MIS_TAKEOFF_ALT](#MIS_TAKEOFF_ALT) it will automatically switch to [Hold mode](../flight_modes_fw/hold.md) and loiter.
It is possible to delay the activation of the motors and control surfaces separately, see parameters [FW_LAUN_MOT_DEL](#FW_LAUN_MOT_DEL), [FW_LAUN_CS_LK_DY](#FW_LAUN_CS_LK_DY) and [CA_CS_LAUN_LK](#CA_CS_LAUN_LK). The later is also exposed in the actuator configuration page under the advanced view.
All RC stick movement is ignored during the full takeoff sequence.
@@ -105,6 +106,8 @@ The _launch detector_ is affected by the following parameters:
| <a id="FW_LAUN_AC_THLD"></a>[FW_LAUN_AC_THLD](../advanced_config/parameter_reference.md#FW_LAUN_AC_THLD) | Acceleration threshold (acceleration in body-forward direction must be above this value) |
| <a id="FW_LAUN_AC_T"></a>[FW_LAUN_AC_T](../advanced_config/parameter_reference.md#FW_LAUN_AC_T) | Trigger time (acceleration must be above threshold for this amount of seconds) |
| <a id="FW_LAUN_MOT_DEL"></a>[FW_LAUN_MOT_DEL](../advanced_config/parameter_reference.md#FW_LAUN_MOT_DEL) | Delay from launch detection to motor spin up |
| <a id="FW_LAUN_CS_LK_DY"></a>[FW_LAUN_CS_LK_DY](../advanced_config/parameter_reference.md#FW_LAUN_CS_LK_DY) | Delay from launch detection to unlocking the control surfaces |
| <a id="CA_CS_LAUN_LK"></a>[CA_CS_LAUN_LK](../advanced_config/parameter_reference.md#CA_CS_LAUN_LK) | Bitmask to select which control surfaces are to be locked during launch |
## Runway Takeoff {#runway_launch}
+1 -1
View File
@@ -5,7 +5,7 @@ This topic explains how to add new MAVLink messages and commands that are expect
## Standard MAVLink Messages
The PX4/PX4-Autopilot source code uses only messages that have been standardized by MAVLink.
That is to say, the standard definitions in [common.xml](https://mavlink.io/en/messages/common.html) in releases, and [development.xml](https://mavlink.io/en/messages/development.html) during development.
That is to say, the definitions in [common.xml](https://mavlink.io/en/messages/common.html) or [development.xml](https://mavlink.io/en/messages/development.html) in releases, and [development.xml](https://mavlink.io/en/messages/development.html) during development.
These messages are present in at least one significant flight stack, and members of other flight stacks have accepted them as a reasonable design that would likely be adopted if the same functionality was required.
::: tip
+186 -186
View File
@@ -94,199 +94,199 @@ They are not build into the module, and hence are neither published or subscribe
::: details See messages
- [GpioIn](../msg_docs/GpioIn.md)
- [SystemPower](../msg_docs/SystemPower.md)
- [LandingTargetInnovations](../msg_docs/LandingTargetInnovations.md)
- [VehicleOpticalFlow](../msg_docs/VehicleOpticalFlow.md)
- [LandingTargetPose](../msg_docs/LandingTargetPose.md)
- [EstimatorGpsStatus](../msg_docs/EstimatorGpsStatus.md)
- [EstimatorBias](../msg_docs/EstimatorBias.md)
- [ParameterSetValueResponse](../msg_docs/ParameterSetValueResponse.md)
- [LogMessage](../msg_docs/LogMessage.md)
- [PowerMonitor](../msg_docs/PowerMonitor.md)
- [VehicleConstraints](../msg_docs/VehicleConstraints.md)
- [SensorAirflow](../msg_docs/SensorAirflow.md)
- [ArmingCheckRequestV0](../msg_docs/ArmingCheckRequestV0.md)
- [ActuatorArmed](../msg_docs/ActuatorArmed.md)
- [HoverThrustEstimate](../msg_docs/HoverThrustEstimate.md)
- [LaunchDetectionStatus](../msg_docs/LaunchDetectionStatus.md)
- [DifferentialPressure](../msg_docs/DifferentialPressure.md)
- [Ekf2Timestamps](../msg_docs/Ekf2Timestamps.md)
- [EstimatorAidSource2d](../msg_docs/EstimatorAidSource2d.md)
- [OpenDroneIdOperatorId](../msg_docs/OpenDroneIdOperatorId.md)
- [AutotuneAttitudeControlStatus](../msg_docs/AutotuneAttitudeControlStatus.md)
- [EventV0](../msg_docs/EventV0.md)
- [EscStatus](../msg_docs/EscStatus.md)
- [VehicleAirData](../msg_docs/VehicleAirData.md)
- [GpsDump](../msg_docs/GpsDump.md)
- [IridiumsbdStatus](../msg_docs/IridiumsbdStatus.md)
- [DebugValue](../msg_docs/DebugValue.md)
- [SensorGyroFft](../msg_docs/SensorGyroFft.md)
- [CameraStatus](../msg_docs/CameraStatus.md)
- [GimbalManagerStatus](../msg_docs/GimbalManagerStatus.md)
- [CameraCapture](../msg_docs/CameraCapture.md)
- [GimbalControls](../msg_docs/GimbalControls.md)
- [MagnetometerBiasEstimate](../msg_docs/MagnetometerBiasEstimate.md)
- [PwmInput](../msg_docs/PwmInput.md)
- [OrbTestMedium](../msg_docs/OrbTestMedium.md)
- [QshellReq](../msg_docs/QshellReq.md)
- [GeofenceStatus](../msg_docs/GeofenceStatus.md)
- [RcChannels](../msg_docs/RcChannels.md)
- [Cpuload](../msg_docs/Cpuload.md)
- [DebugArray](../msg_docs/DebugArray.md)
- [FlightPhaseEstimation](../msg_docs/FlightPhaseEstimation.md)
- [Mission](../msg_docs/Mission.md)
- [AirspeedValidatedV0](../msg_docs/AirspeedValidatedV0.md)
- [BatteryStatusV0](../msg_docs/BatteryStatusV0.md)
- [FollowTarget](../msg_docs/FollowTarget.md)
- [LandingGearWheel](../msg_docs/LandingGearWheel.md)
- [SensorGyroFifo](../msg_docs/SensorGyroFifo.md)
- [ParameterSetUsedRequest](../msg_docs/ParameterSetUsedRequest.md)
- [TrajectorySetpoint6dof](../msg_docs/TrajectorySetpoint6dof.md)
- [CameraTrigger](../msg_docs/CameraTrigger.md)
- [MavlinkTunnel](../msg_docs/MavlinkTunnel.md)
- [RegisterExtComponentRequestV0](../msg_docs/RegisterExtComponentRequestV0.md)
- [GimbalDeviceInformation](../msg_docs/GimbalDeviceInformation.md)
- [ActuatorArmed](../msg_docs/ActuatorArmed.md)
- [SensorUwb](../msg_docs/SensorUwb.md)
- [MountOrientation](../msg_docs/MountOrientation.md)
- [ArmingCheckRequestV0](../msg_docs/ArmingCheckRequestV0.md)
- [UavcanParameterRequest](../msg_docs/UavcanParameterRequest.md)
- [GpioOut](../msg_docs/GpioOut.md)
- [FailureDetectorStatus](../msg_docs/FailureDetectorStatus.md)
- [Airspeed](../msg_docs/Airspeed.md)
- [LedControl](../msg_docs/LedControl.md)
- [RoverSpeedStatus](../msg_docs/RoverSpeedStatus.md)
- [RaptorStatus](../msg_docs/RaptorStatus.md)
- [ActuatorOutputs](../msg_docs/ActuatorOutputs.md)
- [GeneratorStatus](../msg_docs/GeneratorStatus.md)
- [TaskStackInfo](../msg_docs/TaskStackInfo.md)
- [EstimatorAidSource1d](../msg_docs/EstimatorAidSource1d.md)
- [EstimatorSensorBias](../msg_docs/EstimatorSensorBias.md)
- [FixedWingLateralStatus](../msg_docs/FixedWingLateralStatus.md)
- [OrbTest](../msg_docs/OrbTest.md)
- [ParameterSetValueRequest](../msg_docs/ParameterSetValueRequest.md)
- [ParameterResetRequest](../msg_docs/ParameterResetRequest.md)
- [RateCtrlStatus](../msg_docs/RateCtrlStatus.md)
- [MissionResult](../msg_docs/MissionResult.md)
- [QshellRetval](../msg_docs/QshellRetval.md)
- [FlightPhaseEstimation](../msg_docs/FlightPhaseEstimation.md)
- [BatteryInfo](../msg_docs/BatteryInfo.md)
- [OpenDroneIdSelfId](../msg_docs/OpenDroneIdSelfId.md)
- [UlogStreamAck](../msg_docs/UlogStreamAck.md)
- [PwmInput](../msg_docs/PwmInput.md)
- [YawEstimatorStatus](../msg_docs/YawEstimatorStatus.md)
- [DatamanRequest](../msg_docs/DatamanRequest.md)
- [InputRc](../msg_docs/InputRc.md)
- [DatamanResponse](../msg_docs/DatamanResponse.md)
- [DronecanNodeStatus](../msg_docs/DronecanNodeStatus.md)
- [OpenDroneIdArmStatus](../msg_docs/OpenDroneIdArmStatus.md)
- [SensorGyro](../msg_docs/SensorGyro.md)
- [VehicleLocalPositionV0](../msg_docs/VehicleLocalPositionV0.md)
- [DebugKeyValue](../msg_docs/DebugKeyValue.md)
- [LandingTargetPose](../msg_docs/LandingTargetPose.md)
- [EstimatorBias3d](../msg_docs/EstimatorBias3d.md)
- [SensorBaro](../msg_docs/SensorBaro.md)
- [CellularStatus](../msg_docs/CellularStatus.md)
- [NavigatorMissionItem](../msg_docs/NavigatorMissionItem.md)
- [NormalizedUnsignedSetpoint](../msg_docs/NormalizedUnsignedSetpoint.md)
- [UlogStream](../msg_docs/UlogStream.md)
- [VehicleStatusV0](../msg_docs/VehicleStatusV0.md)
- [SensorGnssRelative](../msg_docs/SensorGnssRelative.md)
- [RadioStatus](../msg_docs/RadioStatus.md)
- [RoverAttitudeStatus](../msg_docs/RoverAttitudeStatus.md)
- [SensorsStatusImu](../msg_docs/SensorsStatusImu.md)
- [AdcReport](../msg_docs/AdcReport.md)
- [RoverRateStatus](../msg_docs/RoverRateStatus.md)
- [TuneControl](../msg_docs/TuneControl.md)
- [PpsCapture](../msg_docs/PpsCapture.md)
- [Cpuload](../msg_docs/Cpuload.md)
- [GeofenceResult](../msg_docs/GeofenceResult.md)
- [SensorHygrometer](../msg_docs/SensorHygrometer.md)
- [NeuralControl](../msg_docs/NeuralControl.md)
- [EstimatorStates](../msg_docs/EstimatorStates.md)
- [Px4ioStatus](../msg_docs/Px4ioStatus.md)
- [MagWorkerData](../msg_docs/MagWorkerData.md)
- [VehicleMagnetometer](../msg_docs/VehicleMagnetometer.md)
- [EstimatorBias](../msg_docs/EstimatorBias.md)
- [DebugArray](../msg_docs/DebugArray.md)
- [InternalCombustionEngineControl](../msg_docs/InternalCombustionEngineControl.md)
- [HoverThrustEstimate](../msg_docs/HoverThrustEstimate.md)
- [RtlStatus](../msg_docs/RtlStatus.md)
- [SensorMag](../msg_docs/SensorMag.md)
- [EstimatorSelectorStatus](../msg_docs/EstimatorSelectorStatus.md)
- [HomePositionV0](../msg_docs/HomePositionV0.md)
- [EstimatorStatus](../msg_docs/EstimatorStatus.md)
- [ActuatorServosTrim](../msg_docs/ActuatorServosTrim.md)
- [Rpm](../msg_docs/Rpm.md)
- [GpioRequest](../msg_docs/GpioRequest.md)
- [VehicleOpticalFlow](../msg_docs/VehicleOpticalFlow.md)
- [InternalCombustionEngineStatus](../msg_docs/InternalCombustionEngineStatus.md)
- [OrbTestLarge](../msg_docs/OrbTestLarge.md)
- [IrlockReport](../msg_docs/IrlockReport.md)
- [FixedWingRunwayControl](../msg_docs/FixedWingRunwayControl.md)
- [QshellReq](../msg_docs/QshellReq.md)
- [EstimatorAidSource3d](../msg_docs/EstimatorAidSource3d.md)
- [TiltrotorExtraControls](../msg_docs/TiltrotorExtraControls.md)
- [ControlAllocatorStatus](../msg_docs/ControlAllocatorStatus.md)
- [VehicleOpticalFlowVel](../msg_docs/VehicleOpticalFlowVel.md)
- [EstimatorGpsStatus](../msg_docs/EstimatorGpsStatus.md)
- [PowerButtonState](../msg_docs/PowerButtonState.md)
- [Mission](../msg_docs/Mission.md)
- [RegisterExtComponentReplyV0](../msg_docs/RegisterExtComponentReplyV0.md)
- [Ping](../msg_docs/Ping.md)
- [LogMessage](../msg_docs/LogMessage.md)
- [HealthReport](../msg_docs/HealthReport.md)
- [RtlTimeEstimate](../msg_docs/RtlTimeEstimate.md)
- [FollowTargetStatus](../msg_docs/FollowTargetStatus.md)
- [ActuatorTest](../msg_docs/ActuatorTest.md)
- [GimbalManagerSetManualControl](../msg_docs/GimbalManagerSetManualControl.md)
- [Event](../msg_docs/Event.md)
- [LedControl](../msg_docs/LedControl.md)
- [NavigatorStatus](../msg_docs/NavigatorStatus.md)
- [GpioIn](../msg_docs/GpioIn.md)
- [OrbTestMedium](../msg_docs/OrbTestMedium.md)
- [VehicleImuStatus](../msg_docs/VehicleImuStatus.md)
- [SensorGnssStatus](../msg_docs/SensorGnssStatus.md)
- [PurePursuitStatus](../msg_docs/PurePursuitStatus.md)
- [PowerMonitor](../msg_docs/PowerMonitor.md)
- [CanInterfaceStatus](../msg_docs/CanInterfaceStatus.md)
- [TecsStatus](../msg_docs/TecsStatus.md)
- [GeofenceStatus](../msg_docs/GeofenceStatus.md)
- [LoggerStatus](../msg_docs/LoggerStatus.md)
- [WheelEncoders](../msg_docs/WheelEncoders.md)
- [RaptorInput](../msg_docs/RaptorInput.md)
- [DifferentialPressure](../msg_docs/DifferentialPressure.md)
- [UavcanParameterValue](../msg_docs/UavcanParameterValue.md)
- [SatelliteInfo](../msg_docs/SatelliteInfo.md)
- [FixedWingLateralGuidanceStatus](../msg_docs/FixedWingLateralGuidanceStatus.md)
- [FigureEightStatus](../msg_docs/FigureEightStatus.md)
- [EstimatorInnovations](../msg_docs/EstimatorInnovations.md)
- [VehicleImuStatus](../msg_docs/VehicleImuStatus.md)
- [VehicleLocalPositionSetpoint](../msg_docs/VehicleLocalPositionSetpoint.md)
- [InputRc](../msg_docs/InputRc.md)
- [UavcanParameterRequest](../msg_docs/UavcanParameterRequest.md)
- [FixedWingRunwayControl](../msg_docs/FixedWingRunwayControl.md)
- [SensorCorrection](../msg_docs/SensorCorrection.md)
- [ControlAllocatorStatus](../msg_docs/ControlAllocatorStatus.md)
- [AirspeedValidatedV0](../msg_docs/AirspeedValidatedV0.md)
- [CanInterfaceStatus](../msg_docs/CanInterfaceStatus.md)
- [SensorSelection](../msg_docs/SensorSelection.md)
- [DeviceInformation](../msg_docs/DeviceInformation.md)
- [CameraTrigger](../msg_docs/CameraTrigger.md)
- [SensorAccel](../msg_docs/SensorAccel.md)
- [ActuatorServosTrim](../msg_docs/ActuatorServosTrim.md)
- [SensorsStatusImu](../msg_docs/SensorsStatusImu.md)
- [EstimatorBias3d](../msg_docs/EstimatorBias3d.md)
- [GimbalManagerStatus](../msg_docs/GimbalManagerStatus.md)
- [BatteryStatusV0](../msg_docs/BatteryStatusV0.md)
- [OpenDroneIdSelfId](../msg_docs/OpenDroneIdSelfId.md)
- [VehicleImu](../msg_docs/VehicleImu.md)
- [MissionResult](../msg_docs/MissionResult.md)
- [SensorAccelFifo](../msg_docs/SensorAccelFifo.md)
- [DistanceSensorModeChangeRequest](../msg_docs/DistanceSensorModeChangeRequest.md)
- [SensorPreflightMag](../msg_docs/SensorPreflightMag.md)
- [OrbTest](../msg_docs/OrbTest.md)
- [PositionControllerLandingStatus](../msg_docs/PositionControllerLandingStatus.md)
- [FuelTankStatus](../msg_docs/FuelTankStatus.md)
- [OpenDroneIdSystem](../msg_docs/OpenDroneIdSystem.md)
- [OrbitStatus](../msg_docs/OrbitStatus.md)
- [Px4ioStatus](../msg_docs/Px4ioStatus.md)
- [RtlStatus](../msg_docs/RtlStatus.md)
- [ButtonEvent](../msg_docs/ButtonEvent.md)
- [VehicleLocalPositionV0](../msg_docs/VehicleLocalPositionV0.md)
- [DebugValue](../msg_docs/DebugValue.md)
- [ParameterSetUsedRequest](../msg_docs/ParameterSetUsedRequest.md)
- [RoverSpeedStatus](../msg_docs/RoverSpeedStatus.md)
- [SensorHygrometer](../msg_docs/SensorHygrometer.md)
- [OpenDroneIdOperatorId](../msg_docs/OpenDroneIdOperatorId.md)
- [InternalCombustionEngineStatus](../msg_docs/InternalCombustionEngineStatus.md)
- [GpioOut](../msg_docs/GpioOut.md)
- [ActuatorTest](../msg_docs/ActuatorTest.md)
- [SensorBaro](../msg_docs/SensorBaro.md)
- [PositionControllerStatus](../msg_docs/PositionControllerStatus.md)
- [PurePursuitStatus](../msg_docs/PurePursuitStatus.md)
- [RoverRateStatus](../msg_docs/RoverRateStatus.md)
- [TecsStatus](../msg_docs/TecsStatus.md)
- [PpsCapture](../msg_docs/PpsCapture.md)
- [RaptorStatus](../msg_docs/RaptorStatus.md)
- [EventV0](../msg_docs/EventV0.md)
- [GpioRequest](../msg_docs/GpioRequest.md)
- [FollowTargetEstimator](../msg_docs/FollowTargetEstimator.md)
- [MagWorkerData](../msg_docs/MagWorkerData.md)
- [FollowTarget](../msg_docs/FollowTarget.md)
- [EstimatorAidSource1d](../msg_docs/EstimatorAidSource1d.md)
- [GimbalDeviceSetAttitude](../msg_docs/GimbalDeviceSetAttitude.md)
- [SensorGnssRelative](../msg_docs/SensorGnssRelative.md)
- [ActionRequest](../msg_docs/ActionRequest.md)
- [NavigatorMissionItem](../msg_docs/NavigatorMissionItem.md)
- [GpsInjectData](../msg_docs/GpsInjectData.md)
- [VehicleStatusV0](../msg_docs/VehicleStatusV0.md)
- [DronecanNodeStatus](../msg_docs/DronecanNodeStatus.md)
- [UlogStream](../msg_docs/UlogStream.md)
- [DebugKeyValue](../msg_docs/DebugKeyValue.md)
- [NavigatorStatus](../msg_docs/NavigatorStatus.md)
- [MountOrientation](../msg_docs/MountOrientation.md)
- [RcParameterMap](../msg_docs/RcParameterMap.md)
- [AdcReport](../msg_docs/AdcReport.md)
- [EstimatorSensorBias](../msg_docs/EstimatorSensorBias.md)
- [InternalCombustionEngineControl](../msg_docs/InternalCombustionEngineControl.md)
- [MavlinkLog](../msg_docs/MavlinkLog.md)
- [VehicleMagnetometer](../msg_docs/VehicleMagnetometer.md)
- [GpioConfig](../msg_docs/GpioConfig.md)
- [GainCompression](../msg_docs/GainCompression.md)
- [DebugVect](../msg_docs/DebugVect.md)
- [ArmingCheckReplyV0](../msg_docs/ArmingCheckReplyV0.md)
- [VehicleAttitudeSetpointV0](../msg_docs/VehicleAttitudeSetpointV0.md)
- [FollowTargetStatus](../msg_docs/FollowTargetStatus.md)
- [RtlTimeEstimate](../msg_docs/RtlTimeEstimate.md)
- [RoverAttitudeStatus](../msg_docs/RoverAttitudeStatus.md)
- [SensorUwb](../msg_docs/SensorUwb.md)
- [YawEstimatorStatus](../msg_docs/YawEstimatorStatus.md)
- [VelocityLimits](../msg_docs/VelocityLimits.md)
- [TrajectorySetpoint6dof](../msg_docs/TrajectorySetpoint6dof.md)
- [OpenDroneIdArmStatus](../msg_docs/OpenDroneIdArmStatus.md)
- [EscStatus](../msg_docs/EscStatus.md)
- [GimbalManagerInformation](../msg_docs/GimbalManagerInformation.md)
- [HeaterStatus](../msg_docs/HeaterStatus.md)
- [EstimatorSelectorStatus](../msg_docs/EstimatorSelectorStatus.md)
- [GeofenceResult](../msg_docs/GeofenceResult.md)
- [PowerButtonState](../msg_docs/PowerButtonState.md)
- [Rpm](../msg_docs/Rpm.md)
- [WheelEncoders](../msg_docs/WheelEncoders.md)
- [LoggerStatus](../msg_docs/LoggerStatus.md)
- [CellularStatus](../msg_docs/CellularStatus.md)
- [TuneControl](../msg_docs/TuneControl.md)
- [ConfigOverridesV0](../msg_docs/ConfigOverridesV0.md)
- [GimbalManagerSetAttitude](../msg_docs/GimbalManagerSetAttitude.md)
- [OrbTestLarge](../msg_docs/OrbTestLarge.md)
- [BatteryInfo](../msg_docs/BatteryInfo.md)
- [CameraStatus](../msg_docs/CameraStatus.md)
- [QshellRetval](../msg_docs/QshellRetval.md)
- [SensorMag](../msg_docs/SensorMag.md)
- [RateCtrlStatus](../msg_docs/RateCtrlStatus.md)
- [TaskStackInfo](../msg_docs/TaskStackInfo.md)
- [EstimatorAidSource2d](../msg_docs/EstimatorAidSource2d.md)
- [AirspeedWind](../msg_docs/AirspeedWind.md)
- [AutotuneAttitudeControlStatus](../msg_docs/AutotuneAttitudeControlStatus.md)
- [GimbalDeviceInformation](../msg_docs/GimbalDeviceInformation.md)
- [GpsDump](../msg_docs/GpsDump.md)
- [SensorTemp](../msg_docs/SensorTemp.md)
- [ParameterResetRequest](../msg_docs/ParameterResetRequest.md)
- [TiltrotorExtraControls](../msg_docs/TiltrotorExtraControls.md)
- [SensorsStatus](../msg_docs/SensorsStatus.md)
- [EstimatorStatus](../msg_docs/EstimatorStatus.md)
- [FailureDetectorStatus](../msg_docs/FailureDetectorStatus.md)
- [VehicleAirData](../msg_docs/VehicleAirData.md)
- [ActuatorControlsStatus](../msg_docs/ActuatorControlsStatus.md)
- [TakeoffStatus](../msg_docs/TakeoffStatus.md)
- [GeneratorStatus](../msg_docs/GeneratorStatus.md)
- [SensorGyroFifo](../msg_docs/SensorGyroFifo.md)
- [VehicleAngularVelocity](../msg_docs/VehicleAngularVelocity.md)
- [LandingGearWheel](../msg_docs/LandingGearWheel.md)
- [ParameterSetValueRequest](../msg_docs/ParameterSetValueRequest.md)
- [RegisterExtComponentReplyV0](../msg_docs/RegisterExtComponentReplyV0.md)
- [RaptorInput](../msg_docs/RaptorInput.md)
- [SensorGyro](../msg_docs/SensorGyro.md)
- [DebugVect](../msg_docs/DebugVect.md)
- [PositionControllerLandingStatus](../msg_docs/PositionControllerLandingStatus.md)
- [GimbalManagerSetAttitude](../msg_docs/GimbalManagerSetAttitude.md)
- [ParameterUpdate](../msg_docs/ParameterUpdate.md)
- [NormalizedUnsignedSetpoint](../msg_docs/NormalizedUnsignedSetpoint.md)
- [PositionSetpoint](../msg_docs/PositionSetpoint.md)
- [EstimatorStates](../msg_docs/EstimatorStates.md)
- [ActuatorOutputs](../msg_docs/ActuatorOutputs.md)
- [ManualControlSwitches](../msg_docs/ManualControlSwitches.md)
- [UavcanParameterValue](../msg_docs/UavcanParameterValue.md)
- [VehicleAngularAccelerationSetpoint](../msg_docs/VehicleAngularAccelerationSetpoint.md)
- [EstimatorEventFlags](../msg_docs/EstimatorEventFlags.md)
- [SensorGnssStatus](../msg_docs/SensorGnssStatus.md)
- [GimbalManagerSetManualControl](../msg_docs/GimbalManagerSetManualControl.md)
- [HomePositionV0](../msg_docs/HomePositionV0.md)
- [FixedWingLateralStatus](../msg_docs/FixedWingLateralStatus.md)
- [SatelliteInfo](../msg_docs/SatelliteInfo.md)
- [IrlockReport](../msg_docs/IrlockReport.md)
- [Ping](../msg_docs/Ping.md)
- [CameraCapture](../msg_docs/CameraCapture.md)
- [Vtx](../msg_docs/Vtx.md)
- [Ekf2Timestamps](../msg_docs/Ekf2Timestamps.md)
- [RegisterExtComponentRequestV0](../msg_docs/RegisterExtComponentRequestV0.md)
- [EscReport](../msg_docs/EscReport.md)
- [Gripper](../msg_docs/Gripper.md)
- [UlogStreamAck](../msg_docs/UlogStreamAck.md)
- [SensorGyroFft](../msg_docs/SensorGyroFft.md)
- [PositionControllerStatus](../msg_docs/PositionControllerStatus.md)
- [VehicleRoi](../msg_docs/VehicleRoi.md)
- [ActuatorControlsStatus](../msg_docs/ActuatorControlsStatus.md)
- [ActionRequest](../msg_docs/ActionRequest.md)
- [VehicleLocalPositionSetpoint](../msg_docs/VehicleLocalPositionSetpoint.md)
- [OpenDroneIdSystem](../msg_docs/OpenDroneIdSystem.md)
- [EscReport](../msg_docs/EscReport.md)
- [FollowTargetEstimator](../msg_docs/FollowTargetEstimator.md)
- [GpioConfig](../msg_docs/GpioConfig.md)
- [RcParameterMap](../msg_docs/RcParameterMap.md)
- [ConfigOverridesV0](../msg_docs/ConfigOverridesV0.md)
- [GimbalDeviceSetAttitude](../msg_docs/GimbalDeviceSetAttitude.md)
- [LaunchDetectionStatus](../msg_docs/LaunchDetectionStatus.md)
- [SensorAccel](../msg_docs/SensorAccel.md)
- [VehicleAngularVelocity](../msg_docs/VehicleAngularVelocity.md)
- [GainCompression](../msg_docs/GainCompression.md)
- [GpsInjectData](../msg_docs/GpsInjectData.md)
- [SensorPreflightMag](../msg_docs/SensorPreflightMag.md)
- [Gripper](../msg_docs/Gripper.md)
- [Vtx](../msg_docs/Vtx.md)
- [PositionSetpoint](../msg_docs/PositionSetpoint.md)
- [ParameterSetValueResponse](../msg_docs/ParameterSetValueResponse.md)
- [DistanceSensorModeChangeRequest](../msg_docs/DistanceSensorModeChangeRequest.md)
- [VehicleImu](../msg_docs/VehicleImu.md)
- [SensorAirflow](../msg_docs/SensorAirflow.md)
- [VehicleAngularAccelerationSetpoint](../msg_docs/VehicleAngularAccelerationSetpoint.md)
- [VehicleConstraints](../msg_docs/VehicleConstraints.md)
- [OrbitStatus](../msg_docs/OrbitStatus.md)
- [LandingTargetInnovations](../msg_docs/LandingTargetInnovations.md)
- [ButtonEvent](../msg_docs/ButtonEvent.md)
- [SensorAccelFifo](../msg_docs/SensorAccelFifo.md)
- [EstimatorEventFlags](../msg_docs/EstimatorEventFlags.md)
- [ManualControlSwitches](../msg_docs/ManualControlSwitches.md)
- [MavlinkLog](../msg_docs/MavlinkLog.md)
- [SensorTemp](../msg_docs/SensorTemp.md)
- [FuelTankStatus](../msg_docs/FuelTankStatus.md)
- [DeviceInformation](../msg_docs/DeviceInformation.md)
- [VehicleAcceleration](../msg_docs/VehicleAcceleration.md)
- [NeuralControl](../msg_docs/NeuralControl.md)
- [DatamanResponse](../msg_docs/DatamanResponse.md)
- [GimbalControls](../msg_docs/GimbalControls.md)
- [MavlinkTunnel](../msg_docs/MavlinkTunnel.md)
- [EstimatorAidSource3d](../msg_docs/EstimatorAidSource3d.md)
- [DatamanRequest](../msg_docs/DatamanRequest.md)
- [Event](../msg_docs/Event.md)
- [RadioStatus](../msg_docs/RadioStatus.md)
- [VehicleOpticalFlowVel](../msg_docs/VehicleOpticalFlowVel.md)
- [IridiumsbdStatus](../msg_docs/IridiumsbdStatus.md)
- [SensorCorrection](../msg_docs/SensorCorrection.md)
- [SystemPower](../msg_docs/SystemPower.md)
- [GimbalManagerInformation](../msg_docs/GimbalManagerInformation.md)
- [VehicleAttitudeSetpointV0](../msg_docs/VehicleAttitudeSetpointV0.md)
- [ArmingCheckReplyV0](../msg_docs/ArmingCheckReplyV0.md)
- [RcChannels](../msg_docs/RcChannels.md)
- [EstimatorInnovations](../msg_docs/EstimatorInnovations.md)
- [VelocityLimits](../msg_docs/VelocityLimits.md)
- [TakeoffStatus](../msg_docs/TakeoffStatus.md)
- [SensorSelection](../msg_docs/SensorSelection.md)
- [AirspeedWind](../msg_docs/AirspeedWind.md)
- [HeaterStatus](../msg_docs/HeaterStatus.md)
:::
@@ -98,13 +98,56 @@ leddar_one <command> [arguments...]
stop Stop driver
```
## lightware_grf_serial
Source: [drivers/distance_sensor/lightware_grf_serial](https://github.com/PX4/PX4-Autopilot/tree/main/src/drivers/distance_sensor/lightware_grf_serial)
### Description
Serial bus driver for the Lightware GRF Laser rangefinder.
### Configuration
https://docs.px4.io/main/en/sensor/grf_lidar
### Parameters
https://docs.px4.io/main/en/advanced_config/parameter_reference#GRF_SENS_MODEL
https://docs.px4.io/main/en/advanced_config/parameter_reference#GRF_RATE_CFG
https://docs.px4.io/main/en/advanced_config/parameter_reference#SENS_EN_GRF_CFG
### Examples
Attempt to start driver on a specified serial device.
```
lightware_grf_serial start -d /dev/ttyS1
```
Stop driver
```
lightware_grf_serial stop
```
### Usage {#lightware_grf_serial_usage}
```
lightware_grf_serial <command> [arguments...]
Commands:
start Start driver
-d <val> Serial device
stop Stop driver
```
## lightware_laser_i2c
Source: [drivers/distance_sensor/lightware_laser_i2c](https://github.com/PX4/PX4-Autopilot/tree/main/src/drivers/distance_sensor/lightware_laser_i2c)
### Description
I2C bus driver for Lightware SFxx series LIDAR rangefinders: SF10/a, SF10/b, SF10/c, SF11/c, SF/LW20, SF30/d.
I2C bus driver for Lightware LIDAR rangefinders: SF10/a, SF10/b, SF10/c, SF11/c, SF/LW20, SF/LW30/d, GRF250, GRF500.
Setup/usage information: https://docs.px4.io/main/en/sensor/sfxx_lidar.html
@@ -122,8 +165,6 @@ lightware_laser_i2c <command> [arguments...]
[-q] quiet startup (no message if no device found)
[-a <val>] I2C address
default: 102
[-R <val>] Sensor rotation - downward facing by default
default: 25
stop
+7 -4
View File
@@ -10,10 +10,11 @@ Status of the launch detection state machine (fixed-wing only).
## Fields
| Name | Type | Unit [Frame] | Range/Enum | Description |
| ---------------------- | -------- | ------------ | ---------- | -------------------------------------- |
| timestamp | `uint64` | | | time since system start (microseconds) |
| launch_detection_state | `uint8` | | |
| Name | Type | Unit [Frame] | Range/Enum | Description |
| --------------------------------- | -------- | ------------ | ---------- | ------------------------------------------------------------------------------------------------------------- |
| timestamp | `uint64` | | | time since system start (microseconds) |
| launch_detection_state | `uint8` | | |
| selected_control_surface_disarmed | `bool` | | | flag indicating whether selected actuators should kept disarmed (have to be configured in control allocation) |
## Constants
@@ -39,6 +40,8 @@ uint8 STATE_LAUNCH_DETECTED_DISABLED_MOTOR = 1 # launch detected, but keep moto
uint8 STATE_FLYING = 2 # launch detected, use normal takeoff/flying configuration
uint8 launch_detection_state
bool selected_control_surface_disarmed # [-] flag indicating whether selected actuators should kept disarmed (have to be configured in control allocation)
```
:::
+12
View File
@@ -38,6 +38,18 @@ Instructions for integrating the motor/ESC using with DroneCAN can be found in [
These instructions walk you through setting the correct parameters for enabling the flight controller's DroneCAN drivers, setting the correct configuration parameters for communication with Vertiq modules on the DroneCAN bus, ESC configuration, and testing that your flight controller can properly control your modules over DroneCAN.
#### LED Configuration for Vertiq Modules
::: info
This configuration is only required if you have the optional [Vertiq LED module add-on](https://www.vertiq.co/add-ons).
Standard Vertiq ESC modules do not include LEDs.
:::
Vertiq LED Add-on modules have two LEDs per ESC (RGB for status, White for anti-collision).
See [DroneCAN Lights](../dronecan/index.md#lights) for configuration instructions.
The `light_id` for each LED is calculated as: `esc_index × 3 + BASE_ID`, where `BASE_ID` is 1 for RGB and 2 for White.
### DShot/PWM Configuration
Instructions for integrating the motor/ESC using PWM and DShot can be found in [PWM and DShot Control with a Flight Controller](https://iqmotion.readthedocs.io/en/latest/tutorials/pwm_control_flight_controller.html).
+2 -2
View File
@@ -26,7 +26,7 @@ They cover the _ROS Melodic and Noetic_ releases.
::: tab ROS Noetic (Ubuntu 20.04)
If you're working with [ROS Noetic](https://wiki.ros.org/noetic) on Ubuntu 20.04:
If you're working with [ROS "Noetic"](https://wiki.ros.org/noetic) on Ubuntu 20.04:
1. Install PX4 without the simulator toolchain:
1. [Download PX4 Source Code](../dev_setup/building_px4.md):
@@ -57,7 +57,7 @@ If you're working with [ROS Noetic](https://wiki.ros.org/noetic) on Ubuntu 20.04
::: tab ROS Melodic (Ubuntu 18.04)
If you're working with ROS "Melodic on Ubuntu 18.04:
If you're working with ROS "Melodic" on Ubuntu 18.04:
1. Download the [ubuntu_sim_ros_melodic.sh](https://raw.githubusercontent.com/PX4/Devguide/master/build_scripts/ubuntu_sim_ros_melodic.sh) script in a bash shell:
+69
View File
@@ -0,0 +1,69 @@
# Lightware GRF250/GRF500 Gimbal Lidar
LightWare [GRF250](https://lightwarelidar.com/shop/grf-250/) and [GRF500](https://lightwarelidar.com/shop/grf-500/) are small and light Lidar modules with a range of 250m and 500m, respectively.
![LightWare GRF250 Gimbal Lidar](../../assets/hardware/sensors/lidar_lightware/grf_500.png)
::: info
The Lidar driver is not included in the default build of PX4.
You will need to [create and use a custom build](#add-the-driver-to-the-px4-build).
:::
## Where to Buy
Order these modules from:
- [GRF250](https://lightwarelidar.com/shop/grf-250/)
- [GRF500](https://lightwarelidar.com/shop/grf-500/)
## Hardware Setup
The rangefinder can be connected to any unused serial port, such as `TELEM2`.
[Parameter Configuration](#parameter-configuration) explains how to configure the port to use and the other properties of the rangefinder.
## PX4 Setup
### Add the Driver to the PX4 Build
The [lightware_grf_serial](../modules/modules_driver_distance_sensor.md#lightware-grf-serial) driver for this Lidar is not included in PX4 firmware by default.
In order to use these modules you will first need to update the firmware configuration to add the driver, and then build the firmware.
1. Update the firmware configuration. You can use either of the following options:
- Menuconfig:
1. Install and open [menuconfig](../hardware/porting_guide_config.md#px4-menuconfig-setup)
2. In [menuconfig](../hardware/porting_guide_config.md#px4-menuconfig-setup), navigate to **Drivers > Distance sensors**
3. Select/Enable `lightware_grf_serial`
4. Save the configuration
- Manually update `default.px4` to include the configuration key:
1. Open the `default.px4board` config file that corresponds to the board you want to build for.
For example, to add the driver to `fmu-v6x` boards you would update [/boards/px4/fmu-v6x/default.px4board ](https://github.com/PX4/PX4-Autopilot/blob/main/boards/px4/fmu-v6x/default.px4board)
2. Add the following line and save the file:
```txt
CONFIG_DRIVERS_DISTANCE_SENSOR_LIGHTWARE_GRF_SERIAL=y
```
2. [Build PX4](../dev_setup/building_px4.md) for your flight controller target and upload the new firmware.
### Parameter Configuration
You will need to configure PX4 to indicate the serial port to which the sensor is connected (as per [Serial Port Configuration](../peripherals/serial_configuration.md)) and also the orientation and other properties of the sensor.
The [parameters to change](../advanced_config/parameters.md) are listed in the table.
| Parameter | Description |
| -------------------------------------------------------------------------------------------------------- | -------------------------------------------------- |
| <a id="SENS_EN_GRF_CFG"></a>[SENS_EN_GRF_CFG](../advanced_config/parameter_reference.md#SENS_EN_GRF_CFG) | Set to the serial port the sensor is connected to. |
| <a id="GRF_UPDATE_CFG"></a>[GRF_UPDATE_CFG](../advanced_config/parameter_reference.md#GRF_UPDATE_CFG) | Set the update rate. |
| <a id="GRF_SENS_MODEL"></a>[GRF_SENS_MODEL](../advanced_config/parameter_reference.md#GRF_SENS_MODEL) | Set the update rate. |
## Testing
You can confirm that the sensor is correctly configured by connecting QGroundControl, and observing that [DISTANCE_SENSOR](https://mavlink.io/en/messages/common.html#DISTANCE_SENSOR) is present in the [MAVLink Inspector](https://docs.qgroundcontrol.com/master/en/qgc-user-guide/analyze_view/mavlink_inspector.html).
Moving the sensor around at various distances from a surface will have the `current_distance` value change.
## Troubleshooting
If you are having problems with connecting to the sensor you may need to unassign a the default serial port. [Unassign Default Serial Port](../peripherals/serial_configuration.md)
+5 -2
View File
@@ -15,8 +15,8 @@ The following models are supported by PX4, and can be connected to either the I2
| [LW20/C](https://lightware.co.za/products/lw20-c-100-m) | 100 | I2C bus | Waterproofed (IP67) with servo for sense-and-avoid applications |
| [SF30/D](https://lightwarelidar.com/shop/sf30-d-200-m/) | 200 | I2C bus | Waterproofed (IP67) |
| [SF45/B](../sensor/sf45_rotating_lidar.md) | 50 | Serial | Rotary Lidar (Used for [Collision Prevention](../computer_vision/collision_prevention.md)) |
| [GRF250](https://lightwarelidar.com/shop/grf-250/) | 250 | I2C | Gimbal Range Finder |
| [GRF500](https://lightwarelidar.com/shop/grf-500/) | 500 | I2C | Gimbal Range Finder |
| [GRF250](../sensor/grf_lidar.md) | 250 | Serial or I2C | Gimbal Range Finder |
| [GRF500](../sensor/grf_lidar.md) | 500 | Serial or I2C | Gimbal Range Finder |
::: details Discontinued
@@ -69,6 +69,9 @@ VTOL vehicles may choose to also set [SF1XX_MODE](../advanced_config/parameter_r
::: tip
[SF45/B](../sensor/sf45_rotating_lidar.md) setup is covered in the linked document.
:::
::: tip
[GRF250/GRF500](../sensor/grf_lidar.md) setup is covered in the linked document.
:::
### Hardware
+29 -27
View File
@@ -1,12 +1,11 @@
# PX4 Docker Containers
Docker containers are provided for the complete [PX4 development toolchain](../dev_setup/dev_env.md#supported-targets) including NuttX and Linux based hardware, [Gazebo Classic](../sim_gazebo_classic/index.md) simulation, and [ROS](../simulation/ros_interface.md).
Docker containers are provided for the complete [PX4 development toolchain](../dev_setup/dev_env.md#supported-targets) including NuttX and Linux based hardware, [Gazebo](../sim_gazebo_gz/index.md) simulation, and [ROS 2](../ros2/user_guide.md).
This topic shows how to use the [available docker containers](#px4_containers) to access the build environment in a local Linux computer.
::: info
Dockerfiles and README can be found on [Github here](https://github.com/PX4/PX4-containers/tree/master?tab=readme-ov-file#container-hierarchy).
They are built automatically on [Docker Hub](https://hub.docker.com/u/px4io/).
The recommended `px4-dev` container is built from the [Dockerfile in the PX4-Autopilot source tree](https://github.com/PX4/PX4-Autopilot/blob/main/Tools/setup/Dockerfile) by the [Container build workflow](https://github.com/PX4/PX4-Autopilot/actions/workflows/dev_container.yml).
:::
## Prerequisites
@@ -35,33 +34,36 @@ sudo usermod -aG docker $USER
# Log in/out again before using docker!
```
## Container Hierarchy {#px4_containers}
## px4-dev Container (Recommended) {#px4_containers}
The available containers are on [GitHub here](https://github.com/PX4/PX4-containers/tree/master?tab=readme-ov-file#container-hierarchy).
The **`px4-dev`** container is the recommended container for building PX4 firmware.
It is a single, multi-architecture container (linux/amd64 and linux/arm64) based on Ubuntu 24.04 that includes everything needed to build PX4 for NuttX hardware targets.
These allow testing of various build targets and configurations (the included tools can be inferred from their names).
The containers are hierarchical, such that containers have the functionality of their parents.
For example, the partial hierarchy below shows that the docker container with NuttX build tools (`px4-dev-nuttx-focal`) does not include ROS 2, while the simulation containers do:
It is published to both registries simultaneously:
```plain
- px4io/px4-dev-base-focal
- px4io/px4-dev-nuttx-focal
- px4io/px4-dev-simulation-focal
- px4io/px4-dev-ros-noetic
- px4io/px4-dev-ros2-foxy
- px4io/px4-dev-ros2-rolling
- px4io/px4-dev-base-jammy
- px4io/px4-dev-nuttx-jammy
```
- **GitHub Container Registry:** [ghcr.io/px4/px4-dev](https://github.com/PX4/PX4-Autopilot/pkgs/container/px4-dev)
- **Docker Hub:** [px4io/px4-dev](https://hub.docker.com/r/px4io/px4-dev)
The most recent version can be accessed using the `latest` tag: `px4io/px4-dev-nuttx-focal:latest`
(available tags are listed for each container on _hub.docker.com_.
For example, the `px4io/px4-dev-nuttx-focal` tags can be found on [hub.docker.com here](https://hub.docker.com/r/px4io/px4-dev-nuttx-focal/tags?page=1&ordering=last_updated)).
The container includes:
- Ubuntu 24.04 base
- ARM cross-compiler (`gcc-arm-none-eabi`) and Xtensa compiler (for ESP32 targets)
- Build tools: `cmake`, `ninja`, `ccache`, `make`
- Python 3 with PX4 build dependencies
- NuttX toolchain libraries (`libnewlib-arm-none-eabi`, etc.)
The container is built from the [Dockerfile](https://github.com/PX4/PX4-Autopilot/blob/main/Tools/setup/Dockerfile) in the PX4 source tree using the [Container build workflow](https://github.com/PX4/PX4-Autopilot/actions/workflows/dev_container.yml).
Images are tagged with the PX4 version (e.g. `px4io/px4-dev:v1.16.0`).
:::tip
Typically you should use a recent container, but not necessarily the `latest` (as this changes too often).
A `px4-sim` container with simulation tools (Gazebo Harmonic) is planned to complement `px4-dev` for simulation workflows.
:::
### Legacy Containers
The older per-distro containers from [PX4/PX4-containers](https://github.com/PX4/PX4-containers) (e.g. `px4-dev-nuttx-jammy`, `px4-dev-ros2-humble`, etc.) are no longer recommended.
They will be replaced by `px4-dev` (for builds) and the upcoming `px4-sim` (for simulation).
## Use the Docker Container
The following instructions show how to build PX4 source code on the host computer using a toolchain running in a docker container.
@@ -121,7 +123,7 @@ Where,
- `<host_src>`: The host computer directory to be mapped to `<container_src>` in the container. This should normally be the **PX4-Autopilot** directory.
- `<container_src>`: The location of the shared (source) directory when inside the container.
- `<local_container_name>`: A name for the docker container being created. This can later be used if we need to reference the container again.
- `<container>:<tag>`: The container with version tag to start - e.g.: `px4io/px4-dev-ros:2017-10-23`.
- `<container>:<tag>`: The container with version tag to start - e.g.: `px4io/px4-dev:v1.16.0`.
- `<build_command>`: The command to invoke on the new container. E.g. `bash` is used to open a bash shell in the container.
The concrete example below shows how to open a bash shell and share the directory **~/src/PX4-Autopilot** on the host computer.
@@ -137,7 +139,7 @@ docker run -it --privileged \
-v /tmp/.X11-unix:/tmp/.X11-unix:ro \
-e DISPLAY=:0 \
--network host \
--name=px4-ros px4io/px4-dev-ros2-foxy:2022-07-31 bash
--name=px4-dev px4io/px4-dev:v1.16.0 bash
```
::: info
@@ -155,7 +157,7 @@ Verify if everything works by running, for example, SITL:
```sh
cd src/PX4-Autopilot #This is <container_src>
make px4_sitl_default gazebo-classic
make px4_sitl gz_x500
```
### Re-enter the Container
@@ -219,7 +221,7 @@ This ensures that all files created within the container will be accessible on t
#### Graphics Driver Issues
It's possible that running Gazebo Classic will result in a similar error message like the following:
It's possible that running Gazebo will result in a similar error message like the following:
```sh
libGL error: failed to load driver: swrast
@@ -239,7 +241,7 @@ Any recent Linux distribution should work.
The following configuration is tested:
- OS X with VMWare Fusion and Ubuntu 14.04 (Docker container with GUI support on Parallels make the X-Server crash).
- OS X with VMWare Fusion and Ubuntu 22.04 (Docker container with GUI support on Parallels make the X-Server crash).
**Memory**
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
+2
View File
@@ -7,3 +7,5 @@ uint8 STATE_LAUNCH_DETECTED_DISABLED_MOTOR = 1 # launch detected, but keep moto
uint8 STATE_FLYING = 2 # launch detected, use normal takeoff/flying configuration
uint8 launch_detection_state
bool selected_control_surface_disarmed # [-] flag indicating whether selected actuators should kept disarmed (have to be configured in control allocation)
+1
View File
@@ -598,6 +598,7 @@ if(NOT NUTTX_DIR MATCHES "external")
add_custom_target(jlink-nuttx ALL
DEPENDS ${NUTTX_DIR}/tools/jlink-nuttx.so
)
add_dependencies(jlink-nuttx nuttx_context)
# JLINK_RTOS_PATH used by launch.json.in
set(JLINK_RTOS_PATH ${NUTTX_DIR}/tools/jlink-nuttx.so)
@@ -0,0 +1,46 @@
############################################################################
#
# Copyright (c) 2026 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__distance_sensor__lightware_grf_serial
MAIN lightware_grf_serial
COMPILE_FLAGS
SRCS
lightware_grf_serial.cpp
lightware_grf_serial.hpp
lightware_grf_serial_main.cpp
DEPENDS
drivers_rangefinder
px4_work_queue
MODULE_CONFIG
module.yaml
)
+5
View File
@@ -0,0 +1,5 @@
menuconfig DRIVERS_DISTANCE_SENSOR_LIGHTWARE_GRF_SERIAL
bool "lightware_grf_serial"
default n
---help---
Enable support for lightware_grf_serial
@@ -0,0 +1,91 @@
/****************************************************************************
*
* Copyright (c) 2026 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 grf_commands.h
* @author Aaron Porter
*
* Declarations of grf serial commands for the Lightware grf series
*/
#pragma once
#define GRF_MAX_PAYLOAD 256
#define GRF_CRC_FIELDS 2
enum GRF_SERIAL_CMD {
GRF_PRODUCT_NAME = 0,
GRF_HARDWARE_VERSION = 1,
GRF_FIRMWARE_VERSION = 2,
GRF_SERIAL_NUMBER = 3,
GRF_TEXT_MESSAGE = 7,
GRF_USER_DATA = 9,
GRF_TOKEN = 10,
GRF_SAVE_PARAMETERS = 12,
GRF_RESET = 14,
GRF_STAGE_FIRMWARE = 16,
GRF_COMMIT_FIRMWARE = 17,
GRF_DISTANCE_OUTPUT = 27,
GRF_STREAM = 30,
GRF_DISTANCE_DATA_CM = 44,
GRF_DISTANCE_DATA_MM = 45,
GRF_LASER_FIRING = 50,
GRF_TEMPERATURE = 55,
GRF_AUTO_EXPOSURE = 70,
GRF_UPDATE_RATE = 74,
GRF_LOST_SIGNAL_COUNT = 78,
GRF_GPIO_MODE = 83,
GRF_GPIO_ALARM = 84,
GRF_MEDIAN_FILTER_EN = 86,
GRF_MEDIAN_FILETER_S = 87,
GRF_SMOOTH_FILTER_EN = 88,
GRF_SMOOTH_FACTOR = 89,
GRF_BAUD_RATE = 91,
GRF_I2C_ADDRESS = 92,
GRF_ROLL_AVG_EN = 93,
GRF_ROLL_AVG_SIZE = 94,
GRF_SLEEP_COMMAND = 98,
GRF_ZERO_OFFSET = 114
};
// Store contents of rx'd frame
struct {
const uint8_t data_fields = 2; // useful for breaking crc's into byte separated fields
uint16_t data_len{0}; // last message payload length (1+ bytes in payload)
uint8_t data[GRF_MAX_PAYLOAD]; // payload size limited by posix serial
uint8_t msg_id{0}; // latest message's message id
uint8_t flags_lo{0}; // flags low byte
uint8_t flags_hi{0}; // flags high byte
uint16_t crc[GRF_CRC_FIELDS] = {0, 0};
uint8_t crc_lo{0}; // crc low byte
uint8_t crc_hi{0}; // crc high byte
} rx_field;
@@ -0,0 +1,633 @@
/**************************************************************************
*
* Copyright (c) 2026 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 "lightware_grf_serial.hpp"
#include <fcntl.h>
#include <float.h>
#include <inttypes.h>
#include <termios.h>
#include <lib/crc/crc.h>
using namespace time_literals;
GRFLaserSerial::GRFLaserSerial(const char *port, uint8_t rotation) :
ScheduledWorkItem(MODULE_NAME, px4::serial_port_to_wq(port)),
_px4_rangefinder(0, rotation),
_sample_perf(perf_alloc(PC_ELAPSED, MODULE_NAME": read")),
_comms_errors(perf_alloc(PC_COUNT, MODULE_NAME": com_err"))
{
/* store port name */
strncpy(_port, port, sizeof(_port) - 1);
/* enforce null termination */
_port[sizeof(_port) - 1] = '\0';
device::Device::DeviceId device_id;
device_id.devid_s.bus_type = device::Device::DeviceBusType_SERIAL;
uint8_t bus_num = atoi(&_port[strlen(_port) - 1]); // Assuming '/dev/ttySx'
if (bus_num < 10) {
device_id.devid_s.bus = bus_num;
}
_px4_rangefinder.set_device_id(device_id.devid);
_px4_rangefinder.set_device_type(DRV_DIST_DEVTYPE_LIGHTWARE_LASER);
}
GRFLaserSerial::~GRFLaserSerial()
{
stop();
perf_free(_sample_perf);
perf_free(_comms_errors);
}
int GRFLaserSerial::init()
{
param_get(param_find("GRF_RATE_CFG"), &_update_rate);
param_get(param_find("GRF_SENS_MODEL"), &_model_type);
start();
return PX4_OK;
}
int GRFLaserSerial::measure()
{
int32_t rate = (int32_t)_update_rate;
_data_output = 0x01; // raw distance (last return)
_stream_data = 5; // enable constant streaming
// send packets to the sensor depending on the state
switch (_sensor_state) {
case STATE_UNINIT:
// Used to probe if the sensor is alive
grf_send(GRF_PRODUCT_NAME, false, &_product_name[0], 0);
break;
case STATE_ACK_PRODUCT_NAME:
// Update rate default to 5 readings/s
grf_send(GRF_UPDATE_RATE, true, &rate, sizeof(uint8_t));
ScheduleDelayed(100_ms);
break;
case STATE_ACK_UPDATE_RATE:
// Configure the data that the sensor shall output
grf_send(GRF_DISTANCE_OUTPUT, true, &_data_output, sizeof(_data_output));
break;
case STATE_ACK_DISTANCE_OUTPUT:
// Configure the sensor to automatically output data at the configured update rate
grf_send(GRF_STREAM, true, &_stream_data, sizeof(_stream_data));
_sensor_state = STATE_SEND_STREAM;
break;
default:
break;
}
return PX4_OK;
}
int GRFLaserSerial::collect()
{
if (_sensor_state == STATE_UNINIT) {
perf_begin(_sample_perf);
const int payload_length = 22;
_crc_valid = false;
grf_get_and_handle_request(payload_length, GRF_PRODUCT_NAME);
if (_crc_valid) {
_sensor_state = STATE_ACK_PRODUCT_NAME;
perf_end(_sample_perf);
return PX4_OK;
}
perf_end(_sample_perf);
return -EAGAIN;
} else if (_sensor_state == STATE_ACK_PRODUCT_NAME) {
perf_begin(_sample_perf);
const int payload_length = 7;
_crc_valid = false;
grf_get_and_handle_request(payload_length, GRF_UPDATE_RATE);
if (_crc_valid) {
_sensor_state = STATE_ACK_UPDATE_RATE;
perf_end(_sample_perf);
return PX4_OK;
}
perf_end(_sample_perf);
return -EAGAIN;
} else if (_sensor_state == STATE_ACK_UPDATE_RATE) {
perf_begin(_sample_perf);
const int payload_length = 10;
_crc_valid = false;
grf_get_and_handle_request(payload_length, GRF_DISTANCE_OUTPUT);
if (_crc_valid) {
_sensor_state = STATE_ACK_DISTANCE_OUTPUT;
perf_end(_sample_perf);
return PX4_OK;
}
perf_end(_sample_perf);
return -EAGAIN;
} else {
// Stream data from sensor
perf_begin(_sample_perf);
const int payload_length = 10;
_crc_valid = false;
grf_get_and_handle_request(payload_length, GRF_DISTANCE_DATA_CM);
if (_crc_valid) {
grf_process_replies();
perf_end(_sample_perf);
return PX4_OK;
}
perf_end(_sample_perf);
return -EAGAIN;
}
}
void GRFLaserSerial::start()
{
/* reset the sensor state */
_sensor_state = STATE_UNINIT;
/* reset the report ring */
_collect_phase = false;
/* reset the UART receive buffer size */
_linebuf_size = 0;
/* reset the fail counter */
_last_received_time = hrt_absolute_time();
/*Set Lidar Min/Max based on model*/
switch (_model_type) {
case GRF250: {
_px4_rangefinder.set_min_distance(0.1f);
_px4_rangefinder.set_max_distance(250.0f);
break;
}
case GRF500: {
_px4_rangefinder.set_min_distance(0.1f);
_px4_rangefinder.set_max_distance(500.0f);
break;
}
}
/* schedule a cycle to start things */
ScheduleNow();
}
void GRFLaserSerial::stop()
{
ScheduleClear();
}
void GRFLaserSerial::Run()
{
/* fds initialized? */
if (_fd < 0) {
/* open fd: non-blocking read mode*/
_fd = ::open(_port, O_RDWR | O_NOCTTY | O_NONBLOCK);
if (_fd < 0) {
PX4_ERR("serial open failed (%i)", errno);
return;
}
struct termios uart_config;
int termios_state;
/* fill the struct for the new configuration */
tcgetattr(_fd, &uart_config);
/* clear ONLCR flag (which appends a CR for every LF) */
uart_config.c_oflag &= ~ONLCR;
/* no parity, one stop bit */
uart_config.c_cflag &= ~(CSTOPB | PARENB);
unsigned speed = B115200;
/* 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(_fd, TCSANOW, &uart_config)) < 0) {
PX4_ERR("baud %d ATTR", termios_state);
}
}
if (_collect_phase) {
if (hrt_absolute_time() - _last_received_time >= 1_s) {
start();
return;
}
/* perform collection */
if (collect() != PX4_OK && errno != EAGAIN) {
PX4_DEBUG("collect error");
}
if (_sensor_state != STATE_SEND_STREAM) {
/* next phase is measurement */
_collect_phase = false;
}
} else {
/* measurement phase */
if (measure() != PX4_OK) {
PX4_DEBUG("measure error");
}
/* next phase is collection */
_collect_phase = true;
}
/* schedule a fresh cycle call when the measurement is done */
ScheduleDelayed(_interval);
}
void GRFLaserSerial::print_info()
{
perf_print_counter(_sample_perf);
perf_print_counter(_comms_errors);
}
void GRFLaserSerial::grf_get_and_handle_request(const int payload_length, const GRF_SERIAL_CMD msg_id)
{
// GRF protocol
// Start byte is 0xAA and is the start of packet
// Payload length sanity check (0-1023) bytes
// and represented by 16-bit integer (payload +
// read/write status)
// ID byte precedes the data in the payload
// CRC comprised of 16-bit checksum (not included in checksum calc.)
int ret;
size_t max_read = sizeof(_linebuf) - _linebuf_size;
ret = ::read(_fd, &_linebuf[_linebuf_size], max_read);
if (ret < 0 && errno != EAGAIN) {
PX4_ERR("ERROR (ack from streaming distance data): %d", ret);
_linebuf_size = 0;
perf_count(_comms_errors);
perf_end(_sample_perf);
return;
}
if (ret > 0) {
_last_received_time = hrt_absolute_time();
_linebuf_size += ret;
}
// Not enough data to parse a complete packet. Gather more data in the next cycle.
if (_linebuf_size < payload_length) {
return;
}
int index = 0;
while (index <= _linebuf_size - payload_length && _crc_valid == false) {
bool restart_flag = false;
while (restart_flag != true) {
switch (_parsed_state) {
case GRF_PARSED_STATE::START: {
if (_linebuf[index] == 0xAA) {
// start of frame is valid, continue
_calc_crc = grf_format_crc(_calc_crc, _start_of_frame);
_parsed_state = GRF_PARSED_STATE::FLG_LOW;
break;
} else {
_crc_valid = false;
_parsed_state = GRF_PARSED_STATE::START;
restart_flag = true;
_calc_crc = 0;
PX4_DEBUG("Start of packet not valid: %d", _sensor_state);
break;
}
}
case GRF_PARSED_STATE::FLG_LOW: {
rx_field.flags_lo = _linebuf[index + 1];
_calc_crc = grf_format_crc(_calc_crc, rx_field.flags_lo);
_parsed_state = GRF_PARSED_STATE::FLG_HIGH;
break;
}
case GRF_PARSED_STATE::FLG_HIGH: {
rx_field.flags_hi = _linebuf[index + 2];
rx_field.data_len = (rx_field.flags_hi << 2) | (rx_field.flags_lo >> 6);
_calc_crc = grf_format_crc(_calc_crc, rx_field.flags_hi);
// Check payload length against known max value
if (rx_field.data_len > 17) {
_parsed_state = GRF_PARSED_STATE::START;
restart_flag = true;
_calc_crc = 0;
PX4_DEBUG("Payload length error: %d", _sensor_state);
break;
} else {
_parsed_state = GRF_PARSED_STATE::ID;
break;
}
}
case GRF_PARSED_STATE::ID: {
rx_field.msg_id = _linebuf[index + 3];
if (rx_field.msg_id == msg_id) {
_calc_crc = grf_format_crc(_calc_crc, rx_field.msg_id);
_parsed_state = GRF_PARSED_STATE::DATA;
break;
}
// Ignore message ID's that aren't searched
else {
_parsed_state = GRF_PARSED_STATE::START;
_calc_crc = 0;
restart_flag = true;
PX4_DEBUG("Non needed message ID: %d", _sensor_state);
break;
}
}
case GRF_PARSED_STATE::DATA: {
// Process commands with & w/out data bytes
if (rx_field.data_len > 1) {
for (uint8_t i = 4; i < 3 + rx_field.data_len; ++i) {
rx_field.data[_data_bytes_recv] = _linebuf[index + i];
_calc_crc = grf_format_crc(_calc_crc, rx_field.data[_data_bytes_recv]);
_data_bytes_recv = _data_bytes_recv + 1;
}
}
else {
_parsed_state = GRF_PARSED_STATE::CRC_LOW;
_data_bytes_recv = 0;
_calc_crc = grf_format_crc(_calc_crc, _data_bytes_recv);
}
_parsed_state = GRF_PARSED_STATE::CRC_LOW;
_data_bytes_recv = 0;
break;
}
case GRF_PARSED_STATE::CRC_LOW: {
rx_field.crc[0] = _linebuf[index + 3 + rx_field.data_len];
_parsed_state = GRF_PARSED_STATE::CRC_HIGH;
break;
}
case GRF_PARSED_STATE::CRC_HIGH: {
rx_field.crc[1] = _linebuf[index + 4 + rx_field.data_len];
uint16_t recv_crc = (rx_field.crc[1] << 8) | rx_field.crc[0];
// Check the received crc bytes from the grf against our own CRC calcuation
// If it matches, we can check if sensor ready
// Only if crc match is valid and sensor ready (transmitting distance data) do we flag _init_complete
if (recv_crc == _calc_crc) {
_crc_valid = true;
_parsed_state = GRF_PARSED_STATE::START;
_calc_crc = 0;
restart_flag = true;
break;
} else {
_crc_valid = false;
_parsed_state = GRF_PARSED_STATE::START;
_calc_crc = 0;
restart_flag = true;
perf_count(_comms_errors);
PX4_DEBUG("CRC mismatch: %d", _sensor_state);
break;
}
}
}
}
index++;
}
// If we parsed successfully, remove the parsed part from the buffer if it is still large enough
if (_crc_valid && index + payload_length < _linebuf_size) {
unsigned next_after_index = index + payload_length;
memmove(&_linebuf[0], &_linebuf[next_after_index], _linebuf_size - next_after_index);
_linebuf_size -= next_after_index;
}
// The buffer is filled. Either we can't keep up with the stream and/or it contains only invalid data. Reset to try again.
if ((unsigned)_linebuf_size >= sizeof(_linebuf)) {
_linebuf_size = 0;
perf_count(_comms_errors);
}
}
void GRFLaserSerial::grf_send(uint8_t msg_id, bool write, int32_t *data, uint8_t data_len)
{
uint16_t crc_val = 0;
uint8_t packet_buff[GRF_MAX_PAYLOAD];
uint8_t data_inc = 4;
int ret = 0;
uint8_t packet_len = 0;
// Include payload ID byte in payload len
uint16_t flags = (data_len + 1) << 6;
// If writing to the device, lsb is 1
if (write) {
flags |= 0x01;
}
else {
flags |= 0x0;
}
uint8_t flags_lo = flags & 0xFF;
uint8_t flags_hi = (flags >> 8) & 0xFF;
// Add packet bytes to format into crc based on CRC-16-CCITT 0x1021/XMODEM
crc_val = grf_format_crc(crc_val, _start_of_frame);
crc_val = grf_format_crc(crc_val, flags_lo);
crc_val = grf_format_crc(crc_val, flags_hi);
crc_val = grf_format_crc(crc_val, msg_id);
// Write the packet header contents + payload msg ID to the output buffer
packet_buff[0] = _start_of_frame;
packet_buff[1] = flags_lo;
packet_buff[2] = flags_hi;
packet_buff[3] = msg_id;
if (msg_id == GRF_DISTANCE_OUTPUT) {
uint8_t data_convert = data[0] & 0x00FF;
// write data bytes to the output buffer
packet_buff[data_inc] = data_convert;
// Add data bytes to crc add function
crc_val = grf_format_crc(crc_val, data_convert);
data_inc = data_inc + 1;
data_convert = data[0] >> 8;
packet_buff[data_inc] = data_convert;
crc_val = grf_format_crc(crc_val, data_convert);
data_inc = data_inc + 1;
packet_buff[data_inc] = 0;
crc_val = grf_format_crc(crc_val, packet_buff[data_inc]);
data_inc = data_inc + 1;
packet_buff[data_inc] = 0;
crc_val = grf_format_crc(crc_val, packet_buff[data_inc]);
data_inc = data_inc + 1;
}
else if (msg_id == GRF_STREAM) {
packet_buff[data_inc] = data[0];
//pad zeroes
crc_val = grf_format_crc(crc_val, data[0]);
data_inc = data_inc + 1;
packet_buff[data_inc] = 0;
crc_val = grf_format_crc(crc_val, packet_buff[data_inc]);
data_inc = data_inc + 1;
packet_buff[data_inc] = 0;
crc_val = grf_format_crc(crc_val, packet_buff[data_inc]);
data_inc = data_inc + 1;
packet_buff[data_inc] = 0;
crc_val = grf_format_crc(crc_val, packet_buff[data_inc]);
data_inc = data_inc + 1;
}
else if (msg_id == GRF_UPDATE_RATE) {
// Update Rate
packet_buff[data_inc] = (uint8_t)data[0];
// Add data bytes to crc add function
crc_val = grf_format_crc(crc_val, data[0]);
data_inc = data_inc + 1;
}
else {
// Product Name
PX4_DEBUG("DEBUG: Product name");
}
uint8_t crc_lo = crc_val & 0xFF;
uint8_t crc_hi = (crc_val >> 8) & 0xFF;
packet_buff[data_inc] = crc_lo;
data_inc = data_inc + 1;
packet_buff[data_inc] = crc_hi;
size_t len = sizeof(packet_buff[0]) * (data_inc + 1);
packet_len = (uint8_t)len;
// DEBUG
for (uint8_t i = 0; i < packet_len; ++i) {
PX4_DEBUG("DEBUG: Send byte: %d", packet_buff[i]);
}
ret = ::write(_fd, packet_buff, packet_len);
if (ret != packet_len) {
perf_count(_comms_errors);
PX4_ERR("serial write fail %d", ret);
// Flush data written, not transmitted
tcflush(_fd, TCOFLUSH);
}
}
void GRFLaserSerial::grf_process_replies()
{
float distance_m = -1.0f;
hrt_abstime now = hrt_absolute_time();
switch (rx_field.msg_id) {
case GRF_DISTANCE_DATA_CM: {
const float raw_distance = (rx_field.data[0] << 0) | (rx_field.data[1] << 8) | (rx_field.data[2] << 16);
distance_m = raw_distance * GRF_SCALE_FACTOR;
_px4_rangefinder.update(now, distance_m);
break;
}
default:
// add case for future use
break;
}
}
uint16_t GRFLaserSerial::grf_format_crc(uint16_t crc, uint8_t data_val)
{
uint32_t i;
const uint16_t poly = 0x1021u;
crc ^= (uint16_t)((uint16_t) data_val << 8u);
for (i = 0; i < 8; i++) {
if (crc & (1u << 15u)) {
crc = (uint16_t)((crc << 1u) ^ poly);
} else {
crc = (uint16_t)(crc << 1u);
}
}
return crc;
}
@@ -0,0 +1,134 @@
/****************************************************************************
*
* Copyright (c) 2026 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 lightware_grf_serial.hpp
* @author Aaron Porter <aaron.porter@ascendengineer.com>
*
* Serial Protocol driver for the Lightware GRF rangefinder series
*/
#pragma once
#include <px4_platform_common/px4_config.h>
#include <px4_platform_common/px4_work_queue/ScheduledWorkItem.hpp>
#include <lib/drivers/rangefinder/PX4Rangefinder.hpp>
#include <drivers/drv_hrt.h>
#include <drivers/device/device.h>
#include <lib/parameters/param.h>
#include <lib/perf/perf_counter.h>
#include <uORB/Publication.hpp>
#include <uORB/topics/distance_sensor.h>
#include "grf_commands.h"
enum GRF_SERIAL_STATE {
STATE_UNINIT = 0,
STATE_ACK_PRODUCT_NAME = 1,
STATE_ACK_UPDATE_RATE = 2,
STATE_ACK_DISTANCE_OUTPUT = 3,
STATE_SEND_STREAM = 4,
};
enum GRF_PARSED_STATE {
START = 0,
FLG_LOW,
FLG_HIGH,
ID,
DATA,
CRC_LOW,
CRC_HIGH
};
enum MODEL {
Disable = 0,
GRF250 = 1,
GRF500 = 2
};
using namespace time_literals;
class GRFLaserSerial : public px4::ScheduledWorkItem
{
public:
GRFLaserSerial(const char *port, uint8_t rotation = distance_sensor_s::ROTATION_DOWNWARD_FACING);
~GRFLaserSerial() override;
int init();
void print_info();
void grf_get_and_handle_request(const int payload_length, const GRF_SERIAL_CMD msg_id);
void grf_send(uint8_t msg_id, bool r_w, int32_t *data, uint8_t data_len);
uint16_t grf_format_crc(uint16_t crc, uint8_t data_value);
void grf_process_replies();
private:
distance_sensor_s _distance{};
static constexpr uint64_t GRF_MEAS_TIMEOUT{100_ms};
static constexpr float GRF_SCALE_FACTOR = 0.1f;
void start();
void stop();
void Run() override;
int measure();
int collect();
bool _crc_valid{false};
PX4Rangefinder _px4_rangefinder;
char _port[20] {};
int _interval{200000};
bool _collect_phase{false};
int _fd{-1};
uint8_t _linebuf[GRF_MAX_PAYLOAD] {};
int _linebuf_size{0};
// GRF uses a binary protocol to include header,flags
// message ID, payload, and checksum
GRF_SERIAL_STATE _sensor_state{STATE_UNINIT};
int _baud_rate{0};
int32_t _product_name[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int32_t _stream_data{0};
int32_t _update_rate{0};
int32_t _model_type{0};
int32_t _data_output{0};
const uint8_t _start_of_frame{0xAA};
uint16_t _data_bytes_recv{0};
uint8_t _parsed_state{0};
uint16_t _calc_crc{0};
// end of GRF data members
hrt_abstime _last_received_time{0};
perf_counter_t _sample_perf;
perf_counter_t _comms_errors;
};
@@ -0,0 +1,167 @@
/****************************************************************************
*
* Copyright (c) 2026 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 "lightware_grf_serial.hpp"
#include <px4_platform_common/getopt.h>
#include <px4_platform_common/module.h>
namespace lightware_grf
{
GRFLaserSerial *g_dev{nullptr};
static int start(const char *port)
{
if (g_dev != nullptr) {
PX4_WARN("already started");
return -1;
}
if (port == nullptr) {
PX4_ERR("no device specified");
return -1;
}
/* create the driver */
g_dev = new GRFLaserSerial(port);
if (g_dev == nullptr) {
return -1;
}
if (g_dev->init() != PX4_OK) {
delete g_dev;
g_dev = nullptr;
return -1;
}
return 0;
}
static int stop()
{
if (g_dev != nullptr) {
delete g_dev;
g_dev = nullptr;
} else {
return -1;
}
return 0;
}
static int status()
{
if (g_dev == nullptr) {
PX4_ERR("driver not running");
return -1;
}
g_dev->print_info();
return 0;
}
static int usage()
{
PRINT_MODULE_DESCRIPTION(
R"DESCR_STR(
### Description
Serial bus driver for the Lightware GRF Laser rangefinder.
### Configuration
https://docs.px4.io/main/en/sensor/grf_lidar
### Parameters
https://docs.px4.io/main/en/advanced_config/parameter_reference#GRF_SENS_MODEL
https://docs.px4.io/main/en/advanced_config/parameter_reference#GRF_RATE_CFG
https://docs.px4.io/main/en/advanced_config/parameter_reference#SENS_EN_GRF_CFG
### Examples
Attempt to start driver on a specified serial device.
$ lightware_grf_serial start -d /dev/ttyS1
Stop driver
$ lightware_grf_serial stop
)DESCR_STR");
PRINT_MODULE_USAGE_NAME("lightware_grf_serial", "driver");
PRINT_MODULE_USAGE_SUBCATEGORY("distance_sensor");
PRINT_MODULE_USAGE_COMMAND_DESCR("start", "Start driver");
PRINT_MODULE_USAGE_PARAM_STRING('d', nullptr, nullptr, "Serial device", false);
PRINT_MODULE_USAGE_COMMAND_DESCR("stop", "Stop driver");
return PX4_OK;
}
} // namespace
extern "C" __EXPORT int lightware_grf_serial_main(int argc, char *argv[])
{
const char *device_path = nullptr;
int ch;
int myoptind = 1;
const char *myoptarg = nullptr;
while ((ch = px4_getopt(argc, argv, "d:", &myoptind, &myoptarg)) != EOF) {
switch (ch) {
case 'd':
device_path = myoptarg;
break;
default:
lightware_grf::usage();
return -1;
}
}
if (myoptind >= argc) {
lightware_grf::usage();
return -1;
}
if (!strcmp(argv[myoptind], "start")) {
return lightware_grf::start(device_path);
} else if (!strcmp(argv[myoptind], "stop")) {
return lightware_grf::stop();
} else if (!strcmp(argv[myoptind], "status")) {
return lightware_grf::status();
}
lightware_grf::usage();
return -1;
}
@@ -0,0 +1,44 @@
module_name: Lightware GRF Rangefinder (serial)
serial_config:
- command: lightware_grf_serial start -d ${SERIAL_DEV}
port_config_param:
name: SENS_EN_GRF_CFG
group: Sensors
num_instances: 1
supports_networking: false
parameters:
- group: Sensors
definitions:
GRF_RATE_CFG:
description:
short: Lightware GRF lidar update rate.
long: |
The Lightware GRF distance sensor can increase the update rate to enable greater resolution.
type: enum
values:
1: 1 Hz
2: 2 Hz
3: 4 Hz
4: 5 Hz
5: 10 Hz
6: 20 Hz
7: 30 Hz
8: 40 Hz
9: 50 Hz
reboot_required: true
num_instances: 1
default: 4
GRF_SENS_MODEL:
description:
short: GRF Sensor model
long: |
GRF Sensor Model used to distinush between the GRF250 and GRF500 since both have different max distance range.
type: enum
values:
0: disable
1: GRF250
2: GRF500
reboot_required: true
num_instances: 1
default: 0
@@ -162,7 +162,8 @@ private:
DEFINE_PARAMETERS(
(ParamInt<px4::params::SENS_EN_SF1XX>) _param_sens_en_sf1xx,
(ParamInt<px4::params::SF1XX_MODE>) _param_sf1xx_mode
(ParamInt<px4::params::SF1XX_MODE>) _param_sf1xx_mode,
(ParamInt<px4::params::SF1XX_ROT>) _param_sf1xx_rot
)
uORB::Subscription _parameter_update_sub{ORB_ID(parameter_update)};
uORB::Subscription _vehicle_status_sub{ORB_ID(vehicle_status)};
@@ -178,7 +179,7 @@ LightwareLaser::LightwareLaser(const I2CSPIDriverConfig &config) :
I2C(config),
I2CSPIDriver(config),
ModuleParams(nullptr),
_px4_rangefinder(get_device_id(), config.rotation)
_px4_rangefinder(get_device_id())
{
_px4_rangefinder.set_device_type(DRV_DIST_DEVTYPE_LIGHTWARE_LASER);
}
@@ -194,6 +195,9 @@ int LightwareLaser::init()
{
int ret = PX4_ERROR;
updateParams();
_px4_rangefinder.set_orientation(_param_sf1xx_rot.get());
const int32_t hw_model = _param_sens_en_sf1xx.get();
switch (hw_model) {
@@ -630,7 +634,7 @@ void LightwareLaser::print_usage()
R"DESCR_STR(
### Description
I2C bus driver for Lightware SFxx series LIDAR rangefinders: SF10/a, SF10/b, SF10/c, SF11/c, SF/LW20, SF30/d.
I2C bus driver for Lightware LIDAR rangefinders: SF10/a, SF10/b, SF10/c, SF11/c, SF/LW20, SF/LW30/d, GRF250, GRF500.
Setup/usage information: https://docs.px4.io/main/en/sensor/sfxx_lidar.html
)DESCR_STR");
@@ -640,28 +644,17 @@ Setup/usage information: https://docs.px4.io/main/en/sensor/sfxx_lidar.html
PRINT_MODULE_USAGE_COMMAND("start");
PRINT_MODULE_USAGE_PARAMS_I2C_SPI_DRIVER(true, false);
PRINT_MODULE_USAGE_PARAMS_I2C_ADDRESS(0x66);
PRINT_MODULE_USAGE_PARAM_INT('R', 25, 0, 25, "Sensor rotation - downward facing by default", true);
PRINT_MODULE_USAGE_DEFAULT_COMMANDS();
}
extern "C" __EXPORT int lightware_laser_i2c_main(int argc, char *argv[])
{
int ch;
using ThisDriver = LightwareLaser;
BusCLIArguments cli{true, false};
cli.rotation = (Rotation)distance_sensor_s::ROTATION_DOWNWARD_FACING;
cli.default_i2c_frequency = 400000;
cli.i2c_address = LIGHTWARE_LASER_BASEADDR;
while ((ch = cli.getOpt(argc, argv, "R:")) != EOF) {
switch (ch) {
case 'R':
cli.rotation = (Rotation)atoi(cli.optArg());
break;
}
}
const char *verb = cli.optArg();
const char *verb = cli.parseDefaultArguments(argc, argv);
if (!verb) {
ThisDriver::print_usage();
@@ -32,7 +32,7 @@
****************************************************************************/
/**
* Lightware SF1xx/SF20/LW20 laser rangefinder (i2c)
* Lightware laser rangefinder (i2c)
*
* @reboot_required true
* @min 0
@@ -52,7 +52,7 @@
PARAM_DEFINE_INT32(SENS_EN_SF1XX, 0);
/**
* Lightware SF1xx/SF20/LW20 Operation Mode
* Lightware laser rangefinder Operation Mode
*
* @value 0 Disabled
* @value 1 Enabled
@@ -62,3 +62,22 @@ PARAM_DEFINE_INT32(SENS_EN_SF1XX, 0);
* @max 2
*/
PARAM_DEFINE_INT32(SF1XX_MODE, 1);
/**
* Lightware laser rangefinder Rotation
*
* Distance sensor orientation as MAV_SENSOR_ORIENTATION enum.
* Applies to all models supported by SENS_EN_SF1XX.
*
* @reboot_required true
* @min 0
* @max 25
* @group Sensors
* @value 0 Forward
* @value 2 Right
* @value 4 Backward
* @value 6 Left
* @value 24 Upward
* @value 25 Downward
*/
PARAM_DEFINE_INT32(SF1XX_ROT, 25);
+7 -3
View File
@@ -318,9 +318,13 @@ GPS::GPS(const char *path, gps_driver_mode_t mode, GPSHelper::Interface interfac
_instance(instance)
{
/* store port name */
strncpy(_port, path, sizeof(_port) - 1);
/* enforce null termination */
_port[sizeof(_port) - 1] = '\0';
if (path != nullptr) {
strncpy(_port, path, sizeof(_port) - 1);
_port[sizeof(_port) - 1] = '\0';
} else {
_port[0] = '\0';
}
_sensor_gps.heading = NAN;
_sensor_gps.heading_offset = NAN;
+1 -1
View File
@@ -89,7 +89,7 @@ UavcanEscController::update_outputs(uint16_t outputs[MAX_ACTUATORS], uint8_t out
_prev_cmd_pub = timestamp;
uavcan::equipment::esc::RawCommand msg = {};
uavcan::equipment::esc::RawCommand msg{};
for (unsigned i = 0; i < output_array_size; i++) {
msg.cmd.push_back(static_cast<int>(outputs[i]));
+1 -1
View File
@@ -97,7 +97,7 @@ private:
typedef uavcan::MethodBinder<UavcanEscController *,
void (UavcanEscController::*)(const uavcan::TimerEvent &)> TimerCbBinder;
bool _initialized{};
bool _initialized = false;
esc_status_s _esc_status{};
+42
View File
@@ -1,3 +1,5 @@
__max_num_uavcan_lights: &max_num_uavcan_lights 3 # Needs to be equal to MAX_NUM_UAVCAN_LIGHTS constant
module_name: UAVCAN
parameters:
- group: UAVCAN
@@ -24,6 +26,46 @@ parameters:
min: 1
max: 255
reboot_required: true
UAVCAN_LGT_NUM:
description:
short: Number of UAVCAN lights to configure
long: |
Number of lights to control via UAVCAN LightsCommand messages.
Set to 0 to disable UAVCAN light control.
Each light uses two parameters: LGT_IDx for the light_id and LGT_FNx for the function.
type: int32
min: 0
max: *max_num_uavcan_lights
default: 1
reboot_required: true
UAVCAN_LGT_ID${i}:
description:
short: Light ${i} ID
long: |
specifies the light_id value for light ${i} in UAVCAN LightsCommand messages.
This determines which physical LED responds to commands for this light slot.
type: int32
num_instances: *max_num_uavcan_lights
instance_start: 0
min: 0
max: 255
default: 0
UAVCAN_LGT_FN${i}:
description:
short: Light ${i} function
long: |
Function assigned to light ${i}.
0: Status - displays system status colors
1: Anti-collision - white beacon controlled by LGT_ANTCL parameter
type: enum
num_instances: *max_num_uavcan_lights
instance_start: 0
min: 0
max: 1
default: 0
values:
0: Status Light
1: Anti-collision Light
actuator_output:
show_subgroups_if: 'UAVCAN_ENABLE>=3'
config_parameters:
+119 -120
View File
@@ -32,6 +32,7 @@
****************************************************************************/
#include "rgbled.hpp"
#include <lib/mathlib/mathlib.h>
UavcanRGBController::UavcanRGBController(uavcan::INode &node) :
ModuleParams(nullptr),
@@ -44,6 +45,38 @@ UavcanRGBController::UavcanRGBController(uavcan::INode &node) :
int UavcanRGBController::init()
{
// Cache number of lights (0 disables the feature)
_num_lights = math::min(static_cast<uint8_t>(_param_lgt_num.get()), MAX_NUM_UAVCAN_LIGHTS);
if (_num_lights == 0) {
return 0; // Disabled, don't start timer
}
// Cache parameter handles and values for each light
for (uint8_t i = 0; i < _num_lights; i++) {
char param_name[17];
// Light ID parameter
snprintf(param_name, sizeof(param_name), "UAVCAN_LGT_ID%u", i);
_light_id_params[i] = param_find(param_name);
if (_light_id_params[i] != PARAM_INVALID) {
int32_t light_id = 0;
param_get(_light_id_params[i], &light_id);
_light_ids[i] = static_cast<uint8_t>(light_id);
}
// Light function parameter
snprintf(param_name, sizeof(param_name), "UAVCAN_LGT_FN%u", i);
_light_fn_params[i] = param_find(param_name);
if (_light_fn_params[i] != PARAM_INVALID) {
int32_t light_fn = 0;
param_get(_light_fn_params[i], &light_fn);
_light_functions[i] = static_cast<LightFunction>(light_fn);
}
}
// Setup timer and call back function for periodic updates
_timer.setCallback(TimerCbBinder(this, &UavcanRGBController::periodic_update));
_timer.startPeriodic(uavcan::MonotonicDuration::fromMSec(1000 / MAX_RATE_HZ));
@@ -52,142 +85,108 @@ int UavcanRGBController::init()
void UavcanRGBController::periodic_update(const uavcan::TimerEvent &)
{
bool publish_lights = false;
uavcan::equipment::indication::LightsCommand cmds;
// Early return if disabled or no lights configured
if (_num_lights == 0) {
return;
}
// Check for status color updates from led_controller
LedControlData led_control_data;
if (_led_controller.update(led_control_data) == 1) {
publish_lights = true;
if (_led_controller.update(led_control_data) != 1) {
return; // No update, nothing to do
}
// RGB color in the standard 5-6-5 16-bit palette.
// Monocolor lights should interpret this as brightness setpoint: from zero (0, 0, 0) to full brightness (31, 63, 31).
// Compute status color from led_control_data
uavcan::equipment::indication::RGB565 status_color{};
uint8_t brightness = led_control_data.leds[0].brightness;
switch (led_control_data.leds[0].color) {
case led_control_s::COLOR_RED:
status_color = rgb888_to_rgb565(brightness, 0, 0);
break;
case led_control_s::COLOR_GREEN:
status_color = rgb888_to_rgb565(0, brightness, 0);
break;
case led_control_s::COLOR_BLUE:
status_color = rgb888_to_rgb565(0, 0, brightness);
break;
case led_control_s::COLOR_AMBER: // make it the same as yellow
case led_control_s::COLOR_YELLOW:
status_color = rgb888_to_rgb565(brightness, brightness, 0);
break;
case led_control_s::COLOR_PURPLE:
status_color = rgb888_to_rgb565(brightness, 0, brightness);
break;
case led_control_s::COLOR_CYAN:
status_color = rgb888_to_rgb565(0, brightness, brightness);
break;
case led_control_s::COLOR_WHITE:
status_color = rgb888_to_rgb565(brightness, brightness, brightness);
break;
default:
case led_control_s::COLOR_OFF:
break;
}
// Build and send light commands for all configured lights
uavcan::equipment::indication::LightsCommand light_command;
for (uint8_t i = 0; i < _num_lights; i++) {
uavcan::equipment::indication::SingleLightCommand cmd;
cmd.light_id = _light_ids[i];
uint8_t brightness = led_control_data.leds[0].brightness;
switch (led_control_data.leds[0].color) {
case led_control_s::COLOR_RED:
cmd.color.red = brightness >> 3;
cmd.color.green = 0;
cmd.color.blue = 0;
switch (_light_functions[i]) {
case LightFunction::Status:
cmd.color = status_color;
break;
case led_control_s::COLOR_GREEN:
cmd.color.red = 0;
cmd.color.green = brightness >> 2;
cmd.color.blue = 0;
break;
case led_control_s::COLOR_BLUE:
cmd.color.red = 0;
cmd.color.green = 0;
cmd.color.blue = brightness >> 3;
break;
case led_control_s::COLOR_AMBER: // make it the same as yellow
// FALLTHROUGH
case led_control_s::COLOR_YELLOW:
cmd.color.red = (brightness / 2) >> 3;
cmd.color.green = (brightness / 2) >> 2;
cmd.color.blue = 0;
break;
case led_control_s::COLOR_PURPLE:
cmd.color.red = (brightness / 2) >> 3;
cmd.color.green = 0;
cmd.color.blue = (brightness / 2) >> 3;
break;
case led_control_s::COLOR_CYAN:
cmd.color.red = 0;
cmd.color.green = (brightness / 2) >> 2;
cmd.color.blue = (brightness / 2) >> 3;
break;
case led_control_s::COLOR_WHITE:
cmd.color.red = (brightness / 3) >> 3;
cmd.color.green = (brightness / 3) >> 2;
cmd.color.blue = (brightness / 3) >> 3;
break;
default: // led_control_s::COLOR_OFF
cmd.color.red = 0;
cmd.color.green = 0;
cmd.color.blue = 0;
case LightFunction::AntiCollision:
uint8_t brigtness = is_anticolision_on() ? 255 : 0;
cmd.color = rgb888_to_rgb565(brigtness, brigtness, brigtness);
break;
}
cmds.commands.push_back(cmd);
light_command.commands.push_back(cmd);
}
if (_armed_sub.updated()) {
publish_lights = true;
actuator_armed_s armed;
if (_armed_sub.copy(&armed)) {
/* Determine the current control mode
* If a light's control mode config >= current control mode, the light will be enabled
* Logic must match UAVCAN_LGT_* param values.
* @value 0 Always off
* @value 1 When autopilot is armed
* @value 2 When autopilot is prearmed
* @value 3 Always on
*/
uint8_t control_mode = 0;
if (armed.armed) {
control_mode = 1;
} else if (armed.prearmed) {
control_mode = 2;
} else {
control_mode = 3;
}
uavcan::equipment::indication::SingleLightCommand cmd;
// Beacons
cmd.light_id = uavcan::equipment::indication::SingleLightCommand::LIGHT_ID_ANTI_COLLISION;
cmd.color = brightness_to_rgb565(_param_mode_anti_col.get() >= control_mode ? 255 : 0);
cmds.commands.push_back(cmd);
// Strobes
cmd.light_id = uavcan::equipment::indication::SingleLightCommand::LIGHT_ID_STROBE;
cmd.color = brightness_to_rgb565(_param_mode_strobe.get() >= control_mode ? 255 : 0);
cmds.commands.push_back(cmd);
// Nav lights
cmd.light_id = uavcan::equipment::indication::SingleLightCommand::LIGHT_ID_RIGHT_OF_WAY;
cmd.color = brightness_to_rgb565(_param_mode_nav.get() >= control_mode ? 255 : 0);
cmds.commands.push_back(cmd);
// Landing lights
cmd.light_id = uavcan::equipment::indication::SingleLightCommand::LIGHT_ID_LANDING;
cmd.color = brightness_to_rgb565(_param_mode_land.get() >= control_mode ? 255 : 0);
cmds.commands.push_back(cmd);
}
}
if (publish_lights) {
_uavcan_pub_lights_cmd.broadcast(cmds);
}
_uavcan_pub_lights_cmd.broadcast(light_command);
}
uavcan::equipment::indication::RGB565 UavcanRGBController::brightness_to_rgb565(uint8_t brightness)
bool UavcanRGBController::is_anticolision_on()
{
// RGB color in the standard 5-6-5 16-bit palette.
// Monocolor lights should interpret this as brightness setpoint: from zero (0, 0, 0) to full brightness (31, 63, 31).
uavcan::equipment::indication::RGB565 color;
actuator_armed_s actuator_armed{};
_actuator_armed_sub.copy(&actuator_armed);
color.red = (31.0f * (float)brightness / 255.0f);
color.green = (62.0f * (float)brightness / 255.0f);
color.blue = (31.0f * (float)brightness / 255.0f);
switch (_param_uavcan_lgt_antcl.get()) {
case 3: // Always on
return true;
return color;
case 2: // When autopilot is prearmed
return actuator_armed.armed || actuator_armed.prearmed;
case 1: // When autopilot is armed
return actuator_armed.armed;
case 0: // Always off
default:
return false;
}
}
uavcan::equipment::indication::RGB565 UavcanRGBController::rgb888_to_rgb565(uint8_t red, uint8_t green, uint8_t blue)
{
// RGB565: Full brightness is (31, 63, 31), off is (0, 0, 0)
uavcan::equipment::indication::RGB565 rgb565{};
rgb565.red = (red * 31 + 127) / 255;
rgb565.green = (green * 63 + 127) / 255;
rgb565.blue = (blue * 31 + 127) / 255;
return rgb565;
}
+24 -6
View File
@@ -54,9 +54,20 @@ private:
// Max update rate to avoid excessive bus traffic
static constexpr unsigned MAX_RATE_HZ = 20;
// Maximum number of configurable lights
static constexpr uint8_t MAX_NUM_UAVCAN_LIGHTS = 3;
// Light function types
enum class LightFunction : uint8_t {
Status = 0, // System status colors from led_control
AntiCollision = 1 // White beacon based on arm state
};
void periodic_update(const uavcan::TimerEvent &);
uavcan::equipment::indication::RGB565 brightness_to_rgb565(uint8_t brightness);
bool is_anticolision_on(); ///< Evaluates current on state of collision lights accordingt to UAVCAN_LGT_ANTCL
uavcan::equipment::indication::RGB565 rgb888_to_rgb565(uint8_t red, uint8_t green, uint8_t blue);
typedef uavcan::MethodBinder<UavcanRGBController *, void (UavcanRGBController::*)(const uavcan::TimerEvent &)>
TimerCbBinder;
@@ -65,14 +76,21 @@ private:
uavcan::Publisher<uavcan::equipment::indication::LightsCommand> _uavcan_pub_lights_cmd;
uavcan::TimerEventForwarder<TimerCbBinder> _timer;
uORB::Subscription _armed_sub{ORB_ID(actuator_armed)};
uORB::Subscription _actuator_armed_sub{ORB_ID(actuator_armed)};
LedController _led_controller;
// Cached configuration (set during init, requires reboot to change)
uint8_t _num_lights{0};
uint8_t _light_ids[MAX_NUM_UAVCAN_LIGHTS] {};
LightFunction _light_functions[MAX_NUM_UAVCAN_LIGHTS] {};
// Cached parameter handles
param_t _light_id_params[MAX_NUM_UAVCAN_LIGHTS] {};
param_t _light_fn_params[MAX_NUM_UAVCAN_LIGHTS] {};
DEFINE_PARAMETERS(
(ParamInt<px4::params::UAVCAN_LGT_ANTCL>) _param_mode_anti_col,
(ParamInt<px4::params::UAVCAN_LGT_STROB>) _param_mode_strobe,
(ParamInt<px4::params::UAVCAN_LGT_NAV>) _param_mode_nav,
(ParamInt<px4::params::UAVCAN_LGT_LAND>) _param_mode_land
(ParamInt<px4::params::UAVCAN_LGT_NUM>) _param_lgt_num,
(ParamInt<px4::params::UAVCAN_LGT_ANTCL>) _param_uavcan_lgt_antcl
)
};
+5
View File
@@ -1163,6 +1163,11 @@ UavcanNode::print_info()
printf("\n");
// See https://github.com/PX4/PX4-Autopilot/issues/22871
printf("WARNING: CAN error counter values below may increase during this function call due to internal counter reading implementation.\n");
printf("Do not fully trust these counters until this issue is fixed.\n");
printf("\n");
// UAVCAN node perfcounters
printf("UAVCAN node status:\n");
printf("\tInternal failures: %" PRIu64 "\n", _node.getInternalFailureCount());
+1 -67
View File
@@ -135,7 +135,7 @@ PARAM_DEFINE_INT32(UAVCAN_ECU_FUELT, 1);
* UAVCAN ANTI_COLLISION light operating mode
*
* This parameter defines the minimum condition under which the system will command
* the ANTI_COLLISION lights on
* lights with anti-collision function to turn on (white).
*
* 0 - Always off
* 1 - When autopilot is armed
@@ -153,72 +153,6 @@ PARAM_DEFINE_INT32(UAVCAN_ECU_FUELT, 1);
*/
PARAM_DEFINE_INT32(UAVCAN_LGT_ANTCL, 2);
/**
* UAVCAN STROBE light operating mode
*
* This parameter defines the minimum condition under which the system will command
* the STROBE lights on
*
* 0 - Always off
* 1 - When autopilot is armed
* 2 - When autopilot is prearmed
* 3 - Always on
*
* @min 0
* @max 3
* @value 0 Always off
* @value 1 When autopilot is armed
* @value 2 When autopilot is prearmed
* @value 3 Always on
* @reboot_required true
* @group UAVCAN
*/
PARAM_DEFINE_INT32(UAVCAN_LGT_STROB, 1);
/**
* UAVCAN RIGHT_OF_WAY light operating mode
*
* This parameter defines the minimum condition under which the system will command
* the RIGHT_OF_WAY lights on
*
* 0 - Always off
* 1 - When autopilot is armed
* 2 - When autopilot is prearmed
* 3 - Always on
*
* @min 0
* @max 3
* @value 0 Always off
* @value 1 When autopilot is armed
* @value 2 When autopilot is prearmed
* @value 3 Always on
* @reboot_required true
* @group UAVCAN
*/
PARAM_DEFINE_INT32(UAVCAN_LGT_NAV, 3);
/**
* UAVCAN LIGHT_ID_LANDING light operating mode
*
* This parameter defines the minimum condition under which the system will command
* the LIGHT_ID_LANDING lights on
*
* 0 - Always off
* 1 - When autopilot is armed
* 2 - When autopilot is prearmed
* 3 - Always on
*
* @min 0
* @max 3
* @value 0 Always off
* @value 1 When autopilot is armed
* @value 2 When autopilot is prearmed
* @value 3 Always on
* @reboot_required true
* @group UAVCAN
*/
PARAM_DEFINE_INT32(UAVCAN_LGT_LAND, 0);
/**
* publish Arming Status stream
*
+5 -1
View File
@@ -36,7 +36,11 @@ add_subdirectory(device)
add_subdirectory(gyroscope)
add_subdirectory(led)
add_subdirectory(magnetometer)
add_subdirectory(mcp_common)
add_subdirectory(rangefinder)
add_subdirectory(smbus)
add_subdirectory(smbus_sbs)
if (${PX4_PLATFORM} STREQUAL "nuttx")
add_subdirectory(mcp_common)
endif()
@@ -100,7 +100,7 @@ public:
// Direct Form II implementation
T delay_element_0{sample - _delay_element_1 *_a1 - _delay_element_2 * _a2};
const T output{delay_element_0 *_b0 + _delay_element_1 *_b1 + _delay_element_2 * _b2};
T output{delay_element_0 *_b0 + _delay_element_1 *_b1 + _delay_element_2 * _b2};
_delay_element_2 = _delay_element_1;
_delay_element_1 = delay_element_0;
+1 -1
View File
@@ -75,7 +75,7 @@ Vector3f RateControl::update(const Vector3f &rate, const Vector3f &rate_sp, cons
Vector3f rate_error = rate_sp - rate;
// PID control with feed forward
const Vector3f torque = _gain_p.emult(rate_error) + _rate_int - _gain_d.emult(angular_accel) + _gain_ff.emult(rate_sp);
Vector3f torque = _gain_p.emult(rate_error) + _rate_int - _gain_d.emult(angular_accel) + _gain_ff.emult(rate_sp);
// update integral only if we are not landed
if (!landed) {
+13 -1
View File
@@ -54,6 +54,7 @@ RtlTimeEstimator::RtlTimeEstimator() : ModuleParams(nullptr)
_param_fw_climb_rate = param_find("FW_T_CLMB_R_SP");
_param_fw_sink_rate = param_find("FW_T_SINK_R_SP");
_param_fw_airspeed_trim = param_find("FW_AIRSPD_TRIM");
_param_fw_gnd_spd_min = param_find("FW_GND_SPD_MIN");
_param_mpc_xy_cruise = param_find("MPC_XY_CRUISE");
_param_rover_cruise_speed = param_find("RO_SPEED_LIM");
};
@@ -142,7 +143,18 @@ float RtlTimeEstimator::getCruiseGroundSpeed(const matrix::Vector2f &direction_n
const float ground_speed = sqrtf(cruise_speed * cruise_speed - wind_across_dir * wind_across_dir) + fminf(
0.f, wind_along_dir);
cruise_speed = ground_speed;
// Assume that minimum ground speed is always satisfied. If
// windspeed < cas2tas(FW_AIRSPD_MAX) - FW_GND_SPD_MIN
// the assumption always holds. Otherwise it breaks down when
// flying upwind, and the RTL time estimate is optimistic.
float fw_gnd_spd_min = 5.0f;
if (_param_fw_gnd_spd_min != PARAM_INVALID) {
param_get(_param_fw_gnd_spd_min, &fw_gnd_spd_min);
}
cruise_speed = fmaxf(ground_speed, fw_gnd_spd_min);
}
return cruise_speed;
+1
View File
@@ -129,6 +129,7 @@ private:
param_t _param_fw_sink_rate{PARAM_INVALID}; /**< FW descend speed parameter */
param_t _param_fw_airspeed_trim{PARAM_INVALID}; /**< FW cruise airspeed parameter */
param_t _param_fw_gnd_spd_min{PARAM_INVALID}; /**< FW min groundspeed parameter */
param_t _param_mpc_xy_cruise{PARAM_INVALID}; /**< MC horizontal cruise speed parameter */
param_t _param_rover_cruise_speed{PARAM_INVALID}; /**< Rover cruise speed parameter */
+3 -1
View File
@@ -590,7 +590,9 @@ void TECSControl::_calcThrottleControlUpdate(float dt, const STERateLimit &limit
if (_throttle_setpoint >= param.throttle_max) {
throttle_integ_input = math::min(0.f, throttle_integ_input);
} else if (_throttle_setpoint <= param.throttle_min) {
}
if (_throttle_setpoint <= param.throttle_min) {
throttle_integ_input = math::max(0.f, throttle_integ_input);
}
+2 -2
View File
@@ -107,7 +107,7 @@ uint8_t Modes::addExternalMode(const Modes::Mode &mode)
int matching_idx = -1;
for (int i = 0; i < MAX_NUM; ++i) {
char hash_param_name[20];
char hash_param_name[17];
snprintf(hash_param_name, sizeof(hash_param_name), "COM_MODE%d_HASH", i);
const param_t handle = param_find(hash_param_name);
int32_t current_hash{};
@@ -164,7 +164,7 @@ uint8_t Modes::addExternalMode(const Modes::Mode &mode)
if (new_mode_idx != -1 && !_modes[new_mode_idx].valid) {
if (need_to_update_param) {
char hash_param_name[20];
char hash_param_name[17];
snprintf(hash_param_name, sizeof(hash_param_name), "COM_MODE%d_HASH", new_mode_idx);
const param_t handle = param_find(hash_param_name);
@@ -63,6 +63,7 @@ ActuatorEffectivenessControlSurfaces::ActuatorEffectivenessControlSurfaces(Modul
_spoilers_setpoint_with_slewrate.setSlewRate(kSpoilersSlewRate);
_count_handle = param_find("CA_SV_CS_COUNT");
_param_handle_ca_cs_laun_lk = param_find("CA_CS_LAUN_LK");
updateParams();
}
@@ -80,7 +81,7 @@ void ActuatorEffectivenessControlSurfaces::updateParams()
// Helper to check if a PWM center parameter is enabled, and clamp it to valid range
auto check_pwm_center = [](const char *prefix, int channel) -> bool {
char param_name[20];
char param_name[17];
snprintf(param_name, sizeof(param_name), "%s_CENT%d", prefix, channel);
param_t param = param_find(param_name);
@@ -112,6 +113,8 @@ void ActuatorEffectivenessControlSurfaces::updateParams()
}
}
param_get(_param_handle_ca_cs_laun_lk, &_param_ca_cs_laun_lk);
for (int i = 0; i < _count; i++) {
param_get(_param_handles[i].type, (int32_t *)&_params[i].type);
@@ -234,3 +237,14 @@ void ActuatorEffectivenessControlSurfaces::applySpoilers(float spoilers_control,
actuator_sp(i + first_actuator_idx) += _spoilers_setpoint_with_slewrate.getState() * _params[i].scale_spoiler;
}
}
void ActuatorEffectivenessControlSurfaces::applyLaunchLock(int first_actuator_idx,
ActuatorVector &actuator_sp)
{
for (int i = 0; i < _count; ++i) {
if (_param_ca_cs_laun_lk & (1u << i)) {
actuator_sp(i + first_actuator_idx) = NAN;
}
}
}
@@ -90,6 +90,7 @@ public:
void applyFlaps(float flaps_control, int first_actuator_idx, float dt, ActuatorVector &actuator_sp);
void applySpoilers(float spoilers_control, int first_actuator_idx, float dt, ActuatorVector &actuator_sp);
void applyLaunchLock(int first_actuator_idx, ActuatorVector &actuator_sp);
private:
void updateParams() override;
@@ -104,9 +105,11 @@ private:
};
ParamHandles _param_handles[MAX_COUNT];
param_t _count_handle;
param_t _param_handle_ca_cs_laun_lk;
Params _params[MAX_COUNT] {};
int32_t _count{0};
int32_t _param_ca_cs_laun_lk{0};
SlewRate<float> _flaps_setpoint_with_slewrate;
SlewRate<float> _spoilers_setpoint_with_slewrate;
@@ -65,6 +65,18 @@ void ActuatorEffectivenessFixedWing::updateSetpoint(const matrix::Vector<float,
ActuatorVector &actuator_sp, const ActuatorVector &actuator_min, const ActuatorVector &actuator_max)
{
stopMaskedMotorsWithZeroThrust(_forwards_motors_mask, actuator_sp);
// disable selected control surfaces during launch
launch_detection_status_s launch_detection_status;
if (_launch_detection_status_sub.copy(&launch_detection_status)) {
if (launch_detection_status.selected_control_surface_disarmed
&& hrt_elapsed_time(&launch_detection_status.timestamp) < 100_ms) {
_control_surfaces.applyLaunchLock(_first_control_surface_idx, actuator_sp);
}
}
}
void ActuatorEffectivenessFixedWing::allocateAuxilaryControls(const float dt, int matrix_index,
@@ -38,6 +38,7 @@
#include "ActuatorEffectivenessControlSurfaces.hpp"
#include <uORB/topics/normalized_unsigned_setpoint.h>
#include <uORB/topics/launch_detection_status.h>
class ActuatorEffectivenessFixedWing : public ModuleParams, public ActuatorEffectiveness
{
@@ -60,6 +61,7 @@ private:
uORB::Subscription _flaps_setpoint_sub{ORB_ID(flaps_setpoint)};
uORB::Subscription _spoilers_setpoint_sub{ORB_ID(spoilers_setpoint)};
uORB::Subscription _launch_detection_status_sub{ORB_ID(launch_detection_status)};
int _first_control_surface_idx{0}; ///< applies to matrix 1
+23 -1
View File
@@ -356,6 +356,22 @@ parameters:
instance_start: 0
default: 0
CA_CS_LAUN_LK:
description:
short: Control surface launch lock enabled
long: If actuator launch lock is enabled, this surface is kept at the disarmed value.
type: bitmask
bit:
0: Control Surface 1
1: Control Surface 2
2: Control Surface 3
3: Control Surface 4
4: Control Surface 5
5: Control Surface 6
6: Control Surface 7
7: Control Surface 8
default: 0
# Tilts
CA_SV_TL_COUNT:
description:
@@ -659,7 +675,7 @@ mixer:
rules:
- select_identifier: 'servo-type' # restrict torque based on servo type
apply_identifiers: ['servo-torque-roll', 'servo-torque-pitch', 'servo-torque-yaw', 'servo-scale-flap', 'servo-scale-spoiler']
apply_identifiers: ['servo-torque-roll', 'servo-torque-pitch', 'servo-torque-yaw', 'servo-scale-flap', 'servo-scale-spoiler', 'servo-launch-lock']
items:
# Convention: horizontal surfaces: up=positive, vertical: right=positive, mixed: up=positive.
# By default the scale is set to 1/N, where N is the amount of actuators with an effect on
@@ -858,6 +874,12 @@ mixer:
label: 'Spoiler Scale'
advanced: true
identifier: 'servo-scale-spoiler'
- name: 'CA_CS_LAUN_LK'
label: 'Launch Lock'
advanced: true
identifier: 'servo-launch-lock'
index_offset: 0
show_as: 'bitset'
2: # Standard VTOL
title: 'Standard VTOL'
@@ -75,7 +75,9 @@ void RangeFinderConsistencyCheck::update(float dist_bottom, float dist_bottom_va
void RangeFinderConsistencyCheck::updateConsistency(float vz, uint64_t time_us)
{
if (fabsf(_signed_test_ratio_lpf.getState()) >= 1.f) {
if ((time_us - _time_last_horizontal_motion) > _signed_test_ratio_tau) {
uint64_t timeout_us = _signed_test_ratio_tau * 1e6f;
if ((time_us - _time_last_horizontal_motion) > timeout_us) {
_is_kinematically_consistent = false;
_time_last_inconsistent_us = time_us;
}
-1
View File
@@ -35,7 +35,6 @@
#include "EKF2.hpp"
using namespace time_literals;
using math::constrain;
using matrix::Eulerf;
using matrix::Quatf;
using matrix::Vector3f;
@@ -61,8 +61,8 @@ bool FlightTaskAuto::activate(const trajectory_setpoint_s &last_setpoint)
// If the velocity setpoint is unknown, set to the current velocity
if (!PX4_ISFINITE(vel_prev(i))) { vel_prev(i) = _velocity(i); }
// No acceleration estimate available, set to zero if the setpoint is NAN
if (!PX4_ISFINITE(accel_prev(i))) { accel_prev(i) = 0.f; }
// If accel setpoint unknown, set to the current accel
if (!PX4_ISFINITE(accel_prev(i))) { accel_prev(i) = _acceleration(i); }
}
_position_smoothing.reset(accel_prev, vel_prev, pos_prev);
@@ -153,6 +153,17 @@ void FlightTask::_evaluateVehicleLocalPosition()
_velocity(2) = _sub_vehicle_local_position.get().vz;
}
// acceleration is calculated as the velocity derivative in EKF2,
// if velocity is available acceleration values are available
if (_sub_vehicle_local_position.get().v_xy_valid) {
_acceleration(0) = _sub_vehicle_local_position.get().ax;
_acceleration(1) = _sub_vehicle_local_position.get().ay;
}
if (_sub_vehicle_local_position.get().v_z_valid) {
_acceleration(2) = _sub_vehicle_local_position.get().az;
}
// distance to bottom
if (_sub_vehicle_local_position.get().dist_bottom_valid
&& PX4_ISFINITE(_sub_vehicle_local_position.get().dist_bottom)) {
@@ -201,6 +201,7 @@ protected:
/* Current vehicle state */
matrix::Vector3f _position; /**< current vehicle position */
matrix::Vector3f _velocity; /**< current vehicle velocity */
matrix::Vector3f _acceleration; /**< current vehicle acceleration (derivative of velocity) */
float _yaw{}; /**< current vehicle yaw heading */
float _unaided_yaw{};
@@ -52,7 +52,7 @@ protected:
StickAccelerationXY _stick_acceleration_xy{this};
WeatherVane _weathervane{this}; /**< weathervane library, used to implement a yaw control law that turns the vehicle nose into the wind */
DEFINE_PARAMETERS_CUSTOM_PARENT(FlightTask,
DEFINE_PARAMETERS_CUSTOM_PARENT(FlightTaskManualAltitudeSmoothVel,
(ParamFloat<px4::params::MPC_VEL_MANUAL>) _param_mpc_vel_manual,
(ParamFloat<px4::params::MPC_ACC_HOR>) _param_mpc_acc_hor
)
@@ -173,7 +173,7 @@ void FlightTaskOrbit::_sanitizeParams(float &radius, float &velocity) const
bool FlightTaskOrbit::activate(const trajectory_setpoint_s &last_setpoint)
{
bool ret = FlightTaskManualAltitude::activate(last_setpoint);
bool ret = FlightTaskManualAltitudeSmoothVel::activate(last_setpoint);
_currently_orbiting = false;
_orbit_radius = _radius_min;
_orbit_velocity = 1.f;
@@ -36,9 +36,6 @@
#include <px4_platform_common/events.h>
#include <uORB/topics/longitudinal_control_configuration.h>
using math::constrain;
using math::max;
using math::min;
using math::radians;
using matrix::Dcmf;
@@ -1210,6 +1207,7 @@ FixedWingModeManager::control_auto_takeoff(const hrt_abstime &now, const float c
_takeoff_init_position = global_position;
_takeoff_ground_alt = _current_altitude;
_launch_current_yaw = _yaw;
_time_launch_detected = now;
}
const Vector2f launch_local_position = _global_local_proj_ref.project(_takeoff_init_position(0),
@@ -1285,6 +1283,9 @@ FixedWingModeManager::control_auto_takeoff(const hrt_abstime &now, const float c
launch_detection_status_s launch_detection_status;
launch_detection_status.timestamp = now;
launch_detection_status.launch_detection_state = _launchDetector.getLaunchDetected();
launch_detection_status.selected_control_surface_disarmed =
hrt_elapsed_time(&_time_launch_detected) < _param_fw_laun_cs_lk_dy.get() * 1_s
|| _time_launch_detected == 0;
_launch_detection_status_pub.publish(launch_detection_status);
}
@@ -1380,6 +1381,7 @@ FixedWingModeManager::control_auto_takeoff_no_nav(const hrt_abstime &now, const
if (!_launch_detected && _launchDetector.getLaunchDetected() > launch_detection_status_s::STATE_WAITING_FOR_LAUNCH) {
_launch_detected = true;
_takeoff_ground_alt = _current_altitude;
_time_launch_detected = now;
}
/* Launch has been detected, hence we have to control the plane. */
@@ -1411,6 +1413,9 @@ FixedWingModeManager::control_auto_takeoff_no_nav(const hrt_abstime &now, const
launch_detection_status_s launch_detection_status;
launch_detection_status.timestamp = now;
launch_detection_status.launch_detection_state = _launchDetector.getLaunchDetected();
launch_detection_status.selected_control_surface_disarmed =
hrt_elapsed_time(&_time_launch_detected) < _param_fw_laun_cs_lk_dy.get() * 1_s
|| _time_launch_detected == 0;
_launch_detection_status_pub.publish(launch_detection_status);
}
@@ -2315,6 +2320,8 @@ FixedWingModeManager::reset_takeoff_state()
_launch_detected = false;
_time_launch_detected = 0;
_takeoff_ground_alt = _current_altitude;
}
@@ -298,6 +298,9 @@ private:
// true if a launch, specifically using the launch detector, has been detected
bool _launch_detected{false};
// [us] time stamp of (runway/catapult) launch detection
hrt_abstime _time_launch_detected{0};
// [deg] global position of the vehicle at the time launch is detected (using launch detector) or takeoff is started (runway)
Vector2d _takeoff_init_position{0, 0};
@@ -865,6 +868,10 @@ private:
(ParamFloat<px4::params::FW_GPSF_R>) _param_nav_gpsf_r,
(ParamFloat<px4::params::FW_T_SPDWEIGHT>) _param_t_spdweight,
// Launch detection parameters
(ParamBool<px4::params::FW_LAUN_DETCN_ON>) _param_fw_laun_detcn_on,
(ParamFloat<px4::params::FW_LAUN_CS_LK_DY>) _param_fw_laun_cs_lk_dy,
// external parameters
(ParamBool<px4::params::FW_USE_AIRSPD>) _param_fw_use_airspd,
(ParamFloat<px4::params::NAV_LOITER_RAD>) _param_nav_loiter_rad,
@@ -881,7 +888,6 @@ private:
(ParamInt<px4::params::FW_LND_ABORT>) _param_fw_lnd_abort,
(ParamFloat<px4::params::FW_TKO_AIRSPD>) _param_fw_tko_airspd,
(ParamFloat<px4::params::RWTO_PSP>) _param_rwto_psp,
(ParamBool<px4::params::FW_LAUN_DETCN_ON>) _param_fw_laun_detcn_on,
(ParamFloat<px4::params::FW_AIRSPD_MAX>) _param_fw_airspd_max,
(ParamFloat<px4::params::FW_AIRSPD_MIN>) _param_fw_airspd_min,
(ParamFloat<px4::params::FW_AIRSPD_TRIM>) _param_fw_airspd_trim,
@@ -105,7 +105,7 @@ FigureEight::FigureEightPatternParameters FigureEight::sanitizeParameters(const
}
void FigureEight::initializePattern(const matrix::Vector2f &curr_pos_local, const matrix::Vector2f &ground_speed,
const FigureEightPatternParameters &parameters, FigureEightPatternPoints pattern_points)
const FigureEightPatternParameters &parameters, const FigureEightPatternPoints &pattern_points)
{
// Initialize the currently active segment, if it hasn't been active yet, or the pattern has been changed.
if ((_current_segment == FigureEightSegment::SEGMENT_UNDEFINED) || (_active_parameters != parameters)) {
@@ -140,7 +140,7 @@ private:
* @param[in] pattern_points are the figure of eight pattern points.
*/
void initializePattern(const matrix::Vector2f &curr_pos_local, const matrix::Vector2f &ground_speed,
const FigureEightPatternParameters &parameters, FigureEightPatternPoints pattern_points);
const FigureEightPatternParameters &parameters, const FigureEightPatternPoints &pattern_points);
/**
* @brief Calculate figure eight pattern points
@@ -580,6 +580,21 @@ PARAM_DEFINE_INT32(FW_LND_ABORT, 3);
*/
PARAM_DEFINE_INT32(FW_LAUN_DETCN_ON, 0);
/**
* Control surface launch delay
*
* Locks control surfaces during pre-launch (armed) and until this time since launch has passed.
* Only affects control surfaces that have corresponding flag set, and not active for runway takeoff.
* Set to 0 to disable any surface locking after arming.
*
* @unit s
* @min 0.0
* @decimal 1
* @increment 0.1
* @group FW Auto Takeoff
*/
PARAM_DEFINE_FLOAT(FW_LAUN_CS_LK_DY, 0.f);
/**
* Flaps setting during take-off
*
@@ -36,7 +36,6 @@
using namespace time_literals;
using namespace matrix;
using math::constrain;
using math::interpolate;
using math::radians;
@@ -288,8 +287,18 @@ void FixedwingRateControl::Run()
_rate_control.resetIntegral();
}
launch_detection_status_s launch_detection_status{};
_launch_detection_status_sub.copy(&launch_detection_status);
bool control_surfaces_locked = false;
if (hrt_elapsed_time(&launch_detection_status.timestamp) < 100_ms
&& launch_detection_status.selected_control_surface_disarmed) {
control_surfaces_locked = true;
}
// Reset integrators if the aircraft is on ground or not in a state where the fw attitude controller is run
if (_landed || !_in_fw_or_transition_wo_tailsitter_transition) {
if (_landed || !_in_fw_or_transition_wo_tailsitter_transition || control_surfaces_locked) {
_gain_compression.reset();
_rate_control.resetIntegral();
@@ -70,6 +70,7 @@
#include <uORB/topics/vehicle_status.h>
#include <uORB/topics/vehicle_thrust_setpoint.h>
#include <uORB/topics/vehicle_torque_setpoint.h>
#include <uORB/topics/launch_detection_status.h>
using matrix::Eulerf;
using matrix::Quatf;
@@ -110,6 +111,7 @@ private:
uORB::Subscription _vehicle_land_detected_sub{ORB_ID(vehicle_land_detected)};
uORB::Subscription _vehicle_status_sub{ORB_ID(vehicle_status)};
uORB::Subscription _vehicle_rates_sub{ORB_ID(vehicle_angular_velocity)};
uORB::Subscription _launch_detection_status_sub{ORB_ID(launch_detection_status)};
uORB::SubscriptionMultiArray<control_allocator_status_s, 2> _control_allocator_status_subs{ORB_ID::control_allocator_status};
-120
View File
@@ -1,120 +0,0 @@
---
Checks: '*,
-android*,
-bugprone-integer-division,
-cert-dcl50-cpp,
-cert-env33-c,
-cert-err34-c,
-cert-err58-cpp,
-cert-msc30-c,
-cert-msc50-cpp,
-cert-flp30-c,
-clang-analyzer-core.CallAndMessage,
-clang-analyzer-core.NullDereference,
-clang-analyzer-core.UndefinedBinaryOperatorResult,
-clang-analyzer-core.uninitialized.Assign,
-clang-analyzer-core.VLASize,
-clang-analyzer-cplusplus.NewDelete,
-clang-analyzer-cplusplus.NewDeleteLeaks,
-clang-analyzer-deadcode.DeadStores,
-clang-analyzer-optin.cplusplus.VirtualCall,
-clang-analyzer-optin.performance.Padding,
-clang-analyzer-security.FloatLoopCounter,
-clang-analyzer-security.insecureAPI.strcpy,
-clang-analyzer-unix.API,
-clang-analyzer-unix.cstring.BadSizeArg,
-clang-analyzer-unix.Malloc,
-clang-analyzer-unix.MallocSizeof,
-cppcoreguidelines-c-copy-assignment-signature,
-cppcoreguidelines-interfaces-global-init,
-cppcoreguidelines-no-malloc,
-cppcoreguidelines-owning-memory,
-cppcoreguidelines-pro-bounds-array-to-pointer-decay,
-cppcoreguidelines-pro-bounds-constant-array-index,
-cppcoreguidelines-pro-bounds-pointer-arithmetic,
-cppcoreguidelines-pro-type-const-cast,
-cppcoreguidelines-pro-type-cstyle-cast,
-cppcoreguidelines-pro-type-member-init,
-cppcoreguidelines-pro-type-reinterpret-cast,
-cppcoreguidelines-pro-type-union-access,
-cppcoreguidelines-pro-type-vararg,
-cppcoreguidelines-special-member-functions,
-fuchsia-default-arguments,
-fuchsia-overloaded-operator,
-google-build-using-namespace,
-google-explicit-constructor,
-google-global-names-in-headers,
-google-readability-braces-around-statements,
-google-readability-casting,
-google-readability-function-size,
-google-readability-namespace-comments,
-google-readability-todo,
-google-runtime-int,
-google-runtime-references,
-hicpp-braces-around-statements,
-hicpp-deprecated-headers,
-hicpp-explicit-conversions,
-hicpp-function-size,
-hicpp-member-init,
-hicpp-no-array-decay,
-hicpp-no-assembler,
-hicpp-no-malloc,
-hicpp-signed-bitwise,
-hicpp-special-member-functions,
-hicpp-use-auto,
-hicpp-use-equals-default,
-hicpp-use-equals-delete,
-hicpp-use-override,
-hicpp-vararg,
-llvm-header-guard,
-llvm-include-order,
-llvm-namespace-comment,
-misc-incorrect-roundings,
-misc-macro-parentheses,
-misc-misplaced-widening-cast,
-misc-redundant-expression,
-misc-unconventional-assign-operator,
-misc-unused-parameters,
-modernize-deprecated-headers,
-modernize-loop-convert,
-modernize-pass-by-value,
-modernize-return-braced-init-list,
-modernize-use-auto,
-modernize-use-bool-literals,
-modernize-use-default-member-init,
-modernize-use-emplace,
-modernize-use-equals-default,
-modernize-use-equals-delete,
-modernize-use-override,
-modernize-use-using,
-performance-inefficient-string-concatenation,
-performance-unnecessary-value-param,
-readability-avoid-const-params-in-decls,
-readability-braces-around-statements,
-readability-container-size-empty,
-readability-delete-null-pointer,
-readability-else-after-return,
-readability-function-size,
-readability-implicit-bool-cast,
-readability-implicit-bool-conversion,
-readability-inconsistent-declaration-parameter-name,
-readability-named-parameter,
-readability-non-const-parameter,
-readability-redundant-control-flow,
-readability-redundant-declaration,
-readability-redundant-member-init,
-readability-simplify-boolean-expr,
-readability-static-accessed-through-instance,
-readability-static-definition-in-anonymous-namespace,
'
WarningsAsErrors: '*'
CheckOptions:
- key: google-readability-braces-around-statements.ShortStatementLines
value: '1'
- key: google-readability-function-size.BranchThreshold
value: '600'
- key: google-readability-function-size.LineThreshold
value: '4000'
- key: google-readability-function-size.StatementThreshold
value: '4000'
...
+4 -2
View File
@@ -38,8 +38,10 @@ if(${PX4_PLATFORM} MATCHES "NuttX")
add_compile_options(-DARM_MATH_DSP)
endif()
# Disable 32-bit assembly warnings on apple silicon. Triggered by unused code only.
if(${PX4_PLATFORM} MATCHES "posix" AND APPLE AND ${CMAKE_HOST_SYSTEM_PROCESSOR} MATCHES "arm64")
# Disable 32-bit assembly warnings on arm64 platforms (Apple Silicon, Linux aarch64).
# CMSIS DSP contains ARM Cortex-M assembly that triggers clang warnings on 64-bit ARM.
# This code is unused on POSIX platforms - only the C fallback implementations run.
if(${PX4_PLATFORM} MATCHES "posix" AND ${CMAKE_HOST_SYSTEM_PROCESSOR} MATCHES "arm64|aarch64")
add_compile_options(-Wno-asm-operand-widths)
endif()
+2
View File
@@ -60,3 +60,5 @@ px4_add_module(
version
component_general_json # for checksums.h
)
px4_add_unit_gtest(SRC ULogMessagesTest.cpp)
+666
View File
@@ -0,0 +1,666 @@
/****************************************************************************
*
* Copyright (C) 2025 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#include <gtest/gtest.h>
#include <cstdio>
#include <cstring>
#include "messages.h"
// ----------------------------------------------------------------------------
// Header & constants
// ----------------------------------------------------------------------------
TEST(ULogMessages, HeaderLen)
{
EXPECT_EQ(ULOG_MSG_HEADER_LEN, 3u);
}
TEST(ULogMessages, MessageHeaderSize)
{
EXPECT_EQ(sizeof(ulog_message_header_s), 3u);
}
TEST(ULogMessages, MessageHeaderFieldOffsets)
{
ulog_message_header_s msg = {};
uint8_t *base = reinterpret_cast<uint8_t *>(&msg);
EXPECT_EQ(reinterpret_cast<uint8_t *>(&msg.msg_size) - base, 0);
EXPECT_EQ(reinterpret_cast<uint8_t *>(&msg.msg_type) - base, 2);
}
// ----------------------------------------------------------------------------
// File header (16 bytes: 8 magic + 8 timestamp)
// ----------------------------------------------------------------------------
TEST(ULogMessages, FileHeaderSize)
{
EXPECT_EQ(sizeof(ulog_file_header_s), 16u);
}
TEST(ULogMessages, FileHeaderMagic)
{
ulog_file_header_s hdr = {};
const uint8_t expected_magic[] = {'U', 'L', 'o', 'g', 0x01, 0x12, 0x35, 0x01};
memcpy(hdr.magic, expected_magic, sizeof(expected_magic));
hdr.timestamp = 1000000ULL;
EXPECT_EQ(memcmp(hdr.magic, expected_magic, 7), 0);
EXPECT_EQ(hdr.magic[7], 0x01);
EXPECT_EQ(hdr.timestamp, 1000000ULL);
}
TEST(ULogMessages, FileHeaderFieldOffsets)
{
ulog_file_header_s hdr = {};
uint8_t *base = reinterpret_cast<uint8_t *>(&hdr);
EXPECT_EQ(reinterpret_cast<uint8_t *>(&hdr.magic) - base, 0);
EXPECT_EQ(reinterpret_cast<uint8_t *>(&hdr.timestamp) - base, 8);
}
// ----------------------------------------------------------------------------
// Flag Bits ('B') — must be first message after header
// ----------------------------------------------------------------------------
TEST(ULogMessages, FlagBitsSize)
{
// payload: 8 compat + 8 incompat + 24 appended_offsets = 40
EXPECT_EQ(sizeof(ulog_message_flag_bits_s), ULOG_MSG_HEADER_LEN + 40u);
}
TEST(ULogMessages, FlagBitsTypeCode)
{
ulog_message_flag_bits_s msg = {};
EXPECT_EQ(msg.msg_type, static_cast<uint8_t>('B'));
}
TEST(ULogMessages, FlagBitsFieldOffsets)
{
ulog_message_flag_bits_s msg = {};
uint8_t *base = reinterpret_cast<uint8_t *>(&msg);
EXPECT_EQ(reinterpret_cast<uint8_t *>(&msg.compat_flags) - base, ULOG_MSG_HEADER_LEN);
EXPECT_EQ(reinterpret_cast<uint8_t *>(&msg.incompat_flags) - base, ULOG_MSG_HEADER_LEN + 8);
EXPECT_EQ(reinterpret_cast<uint8_t *>(&msg.appended_offsets) - base, ULOG_MSG_HEADER_LEN + 16);
}
TEST(ULogMessages, FlagBitsDataAppendedMask)
{
EXPECT_EQ(ULOG_INCOMPAT_FLAG0_DATA_APPENDED_MASK, 1 << 0);
EXPECT_EQ(ULOG_COMPAT_FLAG0_DEFAULT_PARAMETERS_MASK, 1 << 0);
}
// ----------------------------------------------------------------------------
// Format Definition ('F')
// ----------------------------------------------------------------------------
TEST(ULogMessages, FormatSize)
{
EXPECT_EQ(sizeof(ulog_message_format_s), ULOG_MSG_HEADER_LEN + 1600u);
}
TEST(ULogMessages, FormatTypeCode)
{
ulog_message_format_s msg = {};
EXPECT_EQ(msg.msg_type, static_cast<uint8_t>('F'));
}
TEST(ULogMessages, FormatSerialization)
{
ulog_message_format_s msg = {};
const char *format_str = "test_topic:uint64_t timestamp;float value;";
size_t len = strlen(format_str);
strncpy(msg.format, format_str, sizeof(msg.format));
msg.msg_size = len;
EXPECT_EQ(msg.msg_size, len);
EXPECT_EQ(memcmp(msg.format, format_str, len), 0);
}
// ----------------------------------------------------------------------------
// Information ('I')
// ----------------------------------------------------------------------------
TEST(ULogMessages, InfoSize)
{
// header(3) + key_len(1) + key_value_str(255) = 259
EXPECT_EQ(sizeof(ulog_message_info_s), ULOG_MSG_HEADER_LEN + 1u + 255u);
}
TEST(ULogMessages, InfoTypeCode)
{
ulog_message_info_s msg = {};
EXPECT_EQ(msg.msg_type, static_cast<uint8_t>('I'));
}
TEST(ULogMessages, InfoStringLayout)
{
const char *name = "hello";
const char *value = "world";
const size_t vlen = strlen(value);
ulog_message_info_s msg = {};
uint8_t *buffer = reinterpret_cast<uint8_t *>(&msg);
msg.msg_type = static_cast<uint8_t>(ULogMessageType::INFO);
msg.key_len = snprintf(msg.key_value_str, sizeof(msg.key_value_str),
"char[%zu] %s", vlen, name);
size_t msg_size = sizeof(msg) - sizeof(msg.key_value_str) + msg.key_len;
ASSERT_LT(vlen, sizeof(msg) - msg_size);
memcpy(&buffer[msg_size], value, vlen);
msg_size += vlen;
msg.msg_size = msg_size - ULOG_MSG_HEADER_LEN;
// msg_size == key_len_field(1) + key_len + vlen
EXPECT_EQ(msg.msg_size, msg.key_len + vlen + 1);
const char expected_key[] = "char[5] hello";
EXPECT_EQ(msg.key_len, strlen(expected_key));
const size_t header_size = sizeof(msg) - sizeof(msg.key_value_str);
const uint8_t *value_start = &buffer[header_size + msg.key_len];
EXPECT_EQ(memcmp(value_start, "world", vlen), 0);
// no null terminator in msg_size
EXPECT_EQ(msg_size, header_size + msg.key_len + vlen);
}
TEST(ULogMessages, InfoInt32Layout)
{
const char *name = "sys_param";
int32_t value = 42;
ulog_message_info_s msg = {};
uint8_t *buffer = reinterpret_cast<uint8_t *>(&msg);
msg.msg_type = static_cast<uint8_t>(ULogMessageType::INFO);
msg.key_len = snprintf(msg.key_value_str, sizeof(msg.key_value_str),
"int32_t %s", name);
size_t msg_size = sizeof(msg) - sizeof(msg.key_value_str) + msg.key_len;
ASSERT_LE(sizeof(value), sizeof(msg) - msg_size);
memcpy(&buffer[msg_size], &value, sizeof(value));
msg_size += sizeof(value);
msg.msg_size = msg_size - ULOG_MSG_HEADER_LEN;
EXPECT_EQ(msg.msg_size, msg.key_len + sizeof(int32_t) + 1);
const char expected_key[] = "int32_t sys_param";
EXPECT_EQ(msg.key_len, strlen(expected_key));
const size_t header_size = sizeof(msg) - sizeof(msg.key_value_str);
int32_t read_back = 0;
memcpy(&read_back, &buffer[header_size + msg.key_len], sizeof(int32_t));
EXPECT_EQ(read_back, 42);
}
TEST(ULogMessages, InfoFloatLayout)
{
const char *name = "cal_offset";
float value = 3.14f;
ulog_message_info_s msg = {};
uint8_t *buffer = reinterpret_cast<uint8_t *>(&msg);
msg.msg_type = static_cast<uint8_t>(ULogMessageType::INFO);
msg.key_len = snprintf(msg.key_value_str, sizeof(msg.key_value_str),
"float %s", name);
size_t msg_size = sizeof(msg) - sizeof(msg.key_value_str) + msg.key_len;
ASSERT_LE(sizeof(value), sizeof(msg) - msg_size);
memcpy(&buffer[msg_size], &value, sizeof(value));
msg_size += sizeof(value);
msg.msg_size = msg_size - ULOG_MSG_HEADER_LEN;
EXPECT_EQ(msg.msg_size, msg.key_len + sizeof(float) + 1);
const size_t header_size = sizeof(msg) - sizeof(msg.key_value_str);
float read_back = 0.f;
memcpy(&read_back, &buffer[header_size + msg.key_len], sizeof(float));
EXPECT_FLOAT_EQ(read_back, 3.14f);
}
// ----------------------------------------------------------------------------
// Information Multiple ('M')
// ----------------------------------------------------------------------------
TEST(ULogMessages, InfoMultipleSize)
{
// header(3) + is_continued(1) + key_len(1) + key_value_str(1200) = 1205
EXPECT_EQ(sizeof(ulog_message_info_multiple_s), ULOG_MSG_HEADER_LEN + 1u + 1u + 1200u);
}
TEST(ULogMessages, InfoMultipleTypeCode)
{
ulog_message_info_multiple_s msg = {};
EXPECT_EQ(msg.msg_type, static_cast<uint8_t>('M'));
}
TEST(ULogMessages, InfoMultipleStringLayout)
{
const char *name = "ver";
const char *value = "1.0";
const size_t vlen = strlen(value);
ulog_message_info_multiple_s msg = {};
uint8_t *buffer = reinterpret_cast<uint8_t *>(&msg);
msg.msg_type = static_cast<uint8_t>(ULogMessageType::INFO_MULTIPLE);
msg.is_continued = false;
msg.key_len = snprintf(msg.key_value_str, sizeof(msg.key_value_str),
"char[%zu] %s", vlen, name);
size_t msg_size = sizeof(msg) - sizeof(msg.key_value_str) + msg.key_len;
ASSERT_LT(vlen, sizeof(msg) - msg_size);
memcpy(&buffer[msg_size], value, vlen);
msg_size += vlen;
msg.msg_size = msg_size - ULOG_MSG_HEADER_LEN;
const size_t header_size = sizeof(msg) - sizeof(msg.key_value_str);
EXPECT_EQ(msg.msg_size, msg_size - ULOG_MSG_HEADER_LEN);
EXPECT_EQ(msg.is_continued, 0);
const char expected_key[] = "char[3] ver";
EXPECT_EQ(msg.key_len, strlen(expected_key));
const uint8_t *value_start = &buffer[header_size + msg.key_len];
EXPECT_EQ(memcmp(value_start, "1.0", vlen), 0);
EXPECT_EQ(msg_size, header_size + msg.key_len + vlen);
}
TEST(ULogMessages, InfoMultipleContinuation)
{
ulog_message_info_multiple_s msg = {};
msg.is_continued = 1;
EXPECT_EQ(msg.is_continued, 1);
EXPECT_EQ(msg.msg_type, static_cast<uint8_t>('M'));
}
TEST(ULogMessages, InfoMultipleFieldOffsets)
{
ulog_message_info_multiple_s msg = {};
uint8_t *base = reinterpret_cast<uint8_t *>(&msg);
EXPECT_EQ(reinterpret_cast<uint8_t *>(&msg.is_continued) - base, ULOG_MSG_HEADER_LEN);
EXPECT_EQ(reinterpret_cast<uint8_t *>(&msg.key_len) - base, ULOG_MSG_HEADER_LEN + 1);
EXPECT_EQ(reinterpret_cast<uint8_t *>(&msg.key_value_str) - base, ULOG_MSG_HEADER_LEN + 2);
}
// ----------------------------------------------------------------------------
// Parameter ('P')
// ----------------------------------------------------------------------------
TEST(ULogMessages, ParameterSize)
{
EXPECT_EQ(sizeof(ulog_message_parameter_s), ULOG_MSG_HEADER_LEN + 1u + 255u);
}
TEST(ULogMessages, ParameterTypeCode)
{
ulog_message_parameter_s msg = {};
EXPECT_EQ(msg.msg_type, static_cast<uint8_t>('P'));
}
TEST(ULogMessages, ParameterInt32Layout)
{
const char *name = "SYS_AUTOSTART";
int32_t value = 4001;
ulog_message_parameter_s msg = {};
uint8_t *buffer = reinterpret_cast<uint8_t *>(&msg);
msg.key_len = snprintf(msg.key_value_str, sizeof(msg.key_value_str),
"int32_t %s", name);
size_t msg_size = sizeof(msg) - sizeof(msg.key_value_str) + msg.key_len;
memcpy(&buffer[msg_size], &value, sizeof(value));
msg_size += sizeof(value);
msg.msg_size = msg_size - ULOG_MSG_HEADER_LEN;
EXPECT_EQ(msg.msg_size, msg.key_len + sizeof(int32_t) + 1);
const size_t header_size = sizeof(msg) - sizeof(msg.key_value_str);
int32_t read_back = 0;
memcpy(&read_back, &buffer[header_size + msg.key_len], sizeof(int32_t));
EXPECT_EQ(read_back, 4001);
}
TEST(ULogMessages, ParameterFloatLayout)
{
const char *name = "MC_PITCHRATE_P";
float value = 0.15f;
ulog_message_parameter_s msg = {};
uint8_t *buffer = reinterpret_cast<uint8_t *>(&msg);
msg.key_len = snprintf(msg.key_value_str, sizeof(msg.key_value_str),
"float %s", name);
size_t msg_size = sizeof(msg) - sizeof(msg.key_value_str) + msg.key_len;
memcpy(&buffer[msg_size], &value, sizeof(value));
msg_size += sizeof(value);
msg.msg_size = msg_size - ULOG_MSG_HEADER_LEN;
const size_t header_size = sizeof(msg) - sizeof(msg.key_value_str);
float read_back = 0.f;
memcpy(&read_back, &buffer[header_size + msg.key_len], sizeof(float));
EXPECT_FLOAT_EQ(read_back, 0.15f);
}
// ----------------------------------------------------------------------------
// Default Parameter ('Q')
// ----------------------------------------------------------------------------
TEST(ULogMessages, ParameterDefaultSize)
{
// header(3) + default_types(1) + key_len(1) + key_value_str(255) = 260
EXPECT_EQ(sizeof(ulog_message_parameter_default_s), ULOG_MSG_HEADER_LEN + 1u + 1u + 255u);
}
TEST(ULogMessages, ParameterDefaultTypeCode)
{
ulog_message_parameter_default_s msg = {};
EXPECT_EQ(msg.msg_type, static_cast<uint8_t>('Q'));
}
TEST(ULogMessages, ParameterDefaultTypeBits)
{
EXPECT_EQ(static_cast<uint8_t>(ulog_parameter_default_type_t::system), 1 << 0);
EXPECT_EQ(static_cast<uint8_t>(ulog_parameter_default_type_t::current_setup), 1 << 1);
auto combined = ulog_parameter_default_type_t::system | ulog_parameter_default_type_t::current_setup;
EXPECT_EQ(static_cast<uint8_t>(combined), 0x03);
}
TEST(ULogMessages, ParameterDefaultFieldOffsets)
{
ulog_message_parameter_default_s msg = {};
uint8_t *base = reinterpret_cast<uint8_t *>(&msg);
EXPECT_EQ(reinterpret_cast<uint8_t *>(&msg.default_types) - base, ULOG_MSG_HEADER_LEN);
EXPECT_EQ(reinterpret_cast<uint8_t *>(&msg.key_len) - base, ULOG_MSG_HEADER_LEN + 1);
EXPECT_EQ(reinterpret_cast<uint8_t *>(&msg.key_value_str) - base, ULOG_MSG_HEADER_LEN + 2);
}
// ----------------------------------------------------------------------------
// Subscription ('A')
// ----------------------------------------------------------------------------
TEST(ULogMessages, AddLoggedSize)
{
// header(3) + multi_id(1) + msg_id(2) + message_name(255) = 261
EXPECT_EQ(sizeof(ulog_message_add_logged_s), ULOG_MSG_HEADER_LEN + 1u + 2u + 255u);
}
TEST(ULogMessages, AddLoggedTypeCode)
{
ulog_message_add_logged_s msg = {};
EXPECT_EQ(msg.msg_type, static_cast<uint8_t>('A'));
}
TEST(ULogMessages, AddLoggedFieldOffsets)
{
ulog_message_add_logged_s msg = {};
uint8_t *base = reinterpret_cast<uint8_t *>(&msg);
EXPECT_EQ(reinterpret_cast<uint8_t *>(&msg.multi_id) - base, ULOG_MSG_HEADER_LEN);
EXPECT_EQ(reinterpret_cast<uint8_t *>(&msg.msg_id) - base, ULOG_MSG_HEADER_LEN + 1);
EXPECT_EQ(reinterpret_cast<uint8_t *>(&msg.message_name) - base, ULOG_MSG_HEADER_LEN + 3);
}
TEST(ULogMessages, AddLoggedSerialization)
{
ulog_message_add_logged_s msg = {};
msg.multi_id = 0;
msg.msg_id = 7;
const char *topic = "sensor_accel";
size_t len = strlen(topic);
strncpy(msg.message_name, topic, sizeof(msg.message_name));
msg.msg_size = sizeof(msg.multi_id) + sizeof(msg.msg_id) + len;
EXPECT_EQ(msg.multi_id, 0);
EXPECT_EQ(msg.msg_id, 7);
EXPECT_EQ(memcmp(msg.message_name, "sensor_accel", len), 0);
}
// ----------------------------------------------------------------------------
// Unsubscription ('R')
// ----------------------------------------------------------------------------
TEST(ULogMessages, RemoveLoggedSize)
{
// header(3) + msg_id(2) = 5
EXPECT_EQ(sizeof(ulog_message_remove_logged_s), ULOG_MSG_HEADER_LEN + 2u);
}
TEST(ULogMessages, RemoveLoggedTypeCode)
{
ulog_message_remove_logged_s msg = {};
EXPECT_EQ(msg.msg_type, static_cast<uint8_t>('R'));
}
TEST(ULogMessages, RemoveLoggedSerialization)
{
ulog_message_remove_logged_s msg = {};
msg.msg_id = 42;
msg.msg_size = sizeof(msg.msg_id);
EXPECT_EQ(msg.msg_id, 42);
EXPECT_EQ(msg.msg_size, 2);
}
// ----------------------------------------------------------------------------
// Logged Data ('D')
// ----------------------------------------------------------------------------
TEST(ULogMessages, DataSize)
{
// header(3) + msg_id(2) = 5 (variable-length payload follows)
EXPECT_EQ(sizeof(ulog_message_data_s), ULOG_MSG_HEADER_LEN + 2u);
}
TEST(ULogMessages, DataTypeCode)
{
ulog_message_data_s msg = {};
EXPECT_EQ(msg.msg_type, static_cast<uint8_t>('D'));
}
TEST(ULogMessages, DataFieldOffset)
{
ulog_message_data_s msg = {};
uint8_t *base = reinterpret_cast<uint8_t *>(&msg);
EXPECT_EQ(reinterpret_cast<uint8_t *>(&msg.msg_id) - base, ULOG_MSG_HEADER_LEN);
}
// ----------------------------------------------------------------------------
// Logging ('L')
// ----------------------------------------------------------------------------
TEST(ULogMessages, LoggingSize)
{
// header(3) + log_level(1) + timestamp(8) + message(128) = 140
EXPECT_EQ(sizeof(ulog_message_logging_s), ULOG_MSG_HEADER_LEN + 1u + 8u + 128u);
}
TEST(ULogMessages, LoggingTypeCode)
{
ulog_message_logging_s msg = {};
EXPECT_EQ(msg.msg_type, static_cast<uint8_t>('L'));
}
TEST(ULogMessages, LoggingFieldOffsets)
{
ulog_message_logging_s msg = {};
uint8_t *base = reinterpret_cast<uint8_t *>(&msg);
EXPECT_EQ(reinterpret_cast<uint8_t *>(&msg.log_level) - base, ULOG_MSG_HEADER_LEN);
EXPECT_EQ(reinterpret_cast<uint8_t *>(&msg.timestamp) - base, ULOG_MSG_HEADER_LEN + 1);
EXPECT_EQ(reinterpret_cast<uint8_t *>(&msg.message) - base, ULOG_MSG_HEADER_LEN + 9);
}
TEST(ULogMessages, LoggingSerialization)
{
ulog_message_logging_s msg = {};
msg.log_level = 6;
msg.timestamp = 5000000ULL;
const char *text = "test message";
size_t len = strlen(text);
strncpy(msg.message, text, sizeof(msg.message));
msg.msg_size = sizeof(msg.log_level) + sizeof(msg.timestamp) + len;
EXPECT_EQ(msg.log_level, 6);
EXPECT_EQ(msg.timestamp, 5000000ULL);
EXPECT_EQ(memcmp(msg.message, "test message", len), 0);
}
// ----------------------------------------------------------------------------
// Logging Tagged ('C')
// ----------------------------------------------------------------------------
TEST(ULogMessages, LoggingTaggedSize)
{
// header(3) + log_level(1) + tag(2) + timestamp(8) + message(128) = 142
EXPECT_EQ(sizeof(ulog_message_logging_tagged_s), ULOG_MSG_HEADER_LEN + 1u + 2u + 8u + 128u);
}
TEST(ULogMessages, LoggingTaggedTypeCode)
{
ulog_message_logging_tagged_s msg = {};
EXPECT_EQ(msg.msg_type, static_cast<uint8_t>('C'));
}
TEST(ULogMessages, LoggingTaggedFieldOffsets)
{
ulog_message_logging_tagged_s msg = {};
uint8_t *base = reinterpret_cast<uint8_t *>(&msg);
EXPECT_EQ(reinterpret_cast<uint8_t *>(&msg.log_level) - base, ULOG_MSG_HEADER_LEN);
EXPECT_EQ(reinterpret_cast<uint8_t *>(&msg.tag) - base, ULOG_MSG_HEADER_LEN + 1);
EXPECT_EQ(reinterpret_cast<uint8_t *>(&msg.timestamp) - base, ULOG_MSG_HEADER_LEN + 3);
EXPECT_EQ(reinterpret_cast<uint8_t *>(&msg.message) - base, ULOG_MSG_HEADER_LEN + 11);
}
// ----------------------------------------------------------------------------
// Sync ('S')
// ----------------------------------------------------------------------------
TEST(ULogMessages, SyncSize)
{
// header(3) + sync_magic(8) = 11
EXPECT_EQ(sizeof(ulog_message_sync_s), ULOG_MSG_HEADER_LEN + 8u);
}
TEST(ULogMessages, SyncTypeCode)
{
ulog_message_sync_s msg = {};
EXPECT_EQ(msg.msg_type, static_cast<uint8_t>('S'));
}
TEST(ULogMessages, SyncMagicBytes)
{
ulog_message_sync_s msg = {};
const uint8_t expected_magic[] = {0x2F, 0x73, 0x13, 0x20, 0x25, 0x0C, 0xBB, 0x12};
memcpy(msg.sync_magic, expected_magic, sizeof(expected_magic));
msg.msg_size = sizeof(msg.sync_magic);
EXPECT_EQ(memcmp(msg.sync_magic, expected_magic, 8), 0);
EXPECT_EQ(msg.msg_size, 8);
}
// ----------------------------------------------------------------------------
// Dropout ('O')
// ----------------------------------------------------------------------------
TEST(ULogMessages, DropoutSize)
{
// header(3) + duration(2) = 5
EXPECT_EQ(sizeof(ulog_message_dropout_s), ULOG_MSG_HEADER_LEN + 2u);
}
TEST(ULogMessages, DropoutTypeCode)
{
ulog_message_dropout_s msg = {};
EXPECT_EQ(msg.msg_type, static_cast<uint8_t>('O'));
}
TEST(ULogMessages, DropoutDefaultMsgSize)
{
ulog_message_dropout_s msg = {};
EXPECT_EQ(msg.msg_size, sizeof(uint16_t));
}
TEST(ULogMessages, DropoutSerialization)
{
ulog_message_dropout_s msg = {};
msg.duration = 150;
EXPECT_EQ(msg.duration, 150);
EXPECT_EQ(msg.msg_size, sizeof(uint16_t));
}
// ----------------------------------------------------------------------------
// ULogMessageType enum values
// ----------------------------------------------------------------------------
TEST(ULogMessages, TypeEnumValues)
{
EXPECT_EQ(static_cast<uint8_t>(ULogMessageType::FORMAT), 'F');
EXPECT_EQ(static_cast<uint8_t>(ULogMessageType::DATA), 'D');
EXPECT_EQ(static_cast<uint8_t>(ULogMessageType::INFO), 'I');
EXPECT_EQ(static_cast<uint8_t>(ULogMessageType::INFO_MULTIPLE), 'M');
EXPECT_EQ(static_cast<uint8_t>(ULogMessageType::PARAMETER), 'P');
EXPECT_EQ(static_cast<uint8_t>(ULogMessageType::PARAMETER_DEFAULT), 'Q');
EXPECT_EQ(static_cast<uint8_t>(ULogMessageType::ADD_LOGGED_MSG), 'A');
EXPECT_EQ(static_cast<uint8_t>(ULogMessageType::REMOVE_LOGGED_MSG), 'R');
EXPECT_EQ(static_cast<uint8_t>(ULogMessageType::SYNC), 'S');
EXPECT_EQ(static_cast<uint8_t>(ULogMessageType::DROPOUT), 'O');
EXPECT_EQ(static_cast<uint8_t>(ULogMessageType::LOGGING), 'L');
EXPECT_EQ(static_cast<uint8_t>(ULogMessageType::LOGGING_TAGGED), 'C');
EXPECT_EQ(static_cast<uint8_t>(ULogMessageType::FLAG_BITS), 'B');
}
+2 -2
View File
@@ -1890,7 +1890,7 @@ void Logger::write_info(LogType type, const char *name, const char *value)
/* copy string value directly to buffer */
if (vlen < (sizeof(msg) - msg_size)) {
memcpy(&buffer[msg_size], value, vlen);
memcpy(&buffer[msg_size], value, vlen + 1);
msg_size += vlen;
msg.msg_size = msg_size - ULOG_MSG_HEADER_LEN;
@@ -1916,7 +1916,7 @@ void Logger::write_info_multiple(LogType type, const char *name, const char *val
/* copy string value directly to buffer */
if (vlen < (sizeof(msg) - msg_size)) {
memcpy(&buffer[msg_size], value, vlen);
memcpy(&buffer[msg_size], value, vlen + 1);
msg_size += vlen;
msg.msg_size = msg_size - ULOG_MSG_HEADER_LEN;
@@ -42,6 +42,7 @@
#include <lib/mathlib/mathlib.h>
using namespace time_literals;
using namespace matrix;
bool GotoControl::checkForSetpoint(const hrt_abstime &now, const bool enabled)
{
@@ -64,10 +65,11 @@ bool GotoControl::checkForSetpoint(const hrt_abstime &now, const bool enabled)
return need_to_run;
}
void GotoControl::update(const float dt, const matrix::Vector3f &position, const float heading)
void GotoControl::update(const float dt, const Vector3f &position, const Vector3f &velocity, const Vector3f &acceleration,
const float heading)
{
if (!_is_initialized) {
resetPositionSmoother(position);
resetPositionSmoother(position, velocity, acceleration);
resetHeadingSmoother(heading);
_is_initialized = true;
}
@@ -87,7 +89,7 @@ void GotoControl::update(const float dt, const matrix::Vector3f &position, const
}
if (_need_smoother_reset) {
resetPositionSmoother(position);
resetPositionSmoother(position, velocity, acceleration);
}
setPositionSmootherLimits(_goto_setpoint);
@@ -138,7 +140,7 @@ void GotoControl::update(const float dt, const matrix::Vector3f &position, const
_vehicle_constraints_pub.publish(vehicle_constraints);
}
void GotoControl::resetPositionSmoother(const matrix::Vector3f &position)
void GotoControl::resetPositionSmoother(const Vector3f &position, const Vector3f &velocity, const Vector3f &acceleration)
{
if (!position.isAllFinite()) {
// TODO: error messaging
@@ -146,9 +148,7 @@ void GotoControl::resetPositionSmoother(const matrix::Vector3f &position)
return;
}
const Vector3f initial_acceleration{};
const Vector3f initial_velocity{};
_position_smoothing.reset(initial_acceleration, initial_velocity, position);
_position_smoothing.reset(acceleration, velocity, position);
_need_smoother_reset = false;
}
@@ -64,9 +64,11 @@ public:
/**
* @brief resets the position smoother at the current position with zero velocity and acceleration.
*
* @param position [m] (NED) local vehicle position
* @param position [m] vehicle position state NED local frame
* @param velocity [m/s] vehicle velocity state
* @param acceleration [m/s^2] vehicle acceleration state
*/
void resetPositionSmoother(const matrix::Vector3f &position);
void resetPositionSmoother(const matrix::Vector3f &position, const matrix::Vector3f &velocity, const matrix::Vector3f &acceleration);
/**
* @brief resets the heading smoother at the current heading with zero heading rate and acceleration.
@@ -80,12 +82,15 @@ public:
* loops to track.
*
* @param[in] dt [s] time since last control update
* @param[in] position [m] (NED) local vehicle position
* @param[in] position [m] vehicle position state NED local frame
* @param[in] velocity [m/s] vehicle velocity state
* @param[in] acceleration [m/s^2] vehicle acceleration state
* @param[in] heading [rad] (from North) vehicle heading
* @param[in] goto_setpoint struct containing current go-to setpoints
* @param[out] trajectory_setpoint struct containing trajectory (tracking) setpoints
*/
void update(const float dt, const matrix::Vector3f &position, const float heading);
void update(const float dt, const matrix::Vector3f &position, const matrix::Vector3f &velocity, const matrix::Vector3f &acceleration,
const float heading);
// Setting all parameters from the outside saves 300bytes flash
void setParamMpcAccHor(const float param_mpc_acc_hor) { _param_mpc_acc_hor = param_mpc_acc_hor; }
@@ -433,7 +433,7 @@ void MulticopterPositionControl::Run()
&& !_trajectory_setpoint_sub.updated();
if (_goto_control.checkForSetpoint(vehicle_local_position.timestamp_sample, goto_setpoint_enable)) {
_goto_control.update(dt, states.position, states.yaw);
_goto_control.update(dt, states.position, states.velocity, states.acceleration, states.yaw);
}
_trajectory_setpoint_sub.update(&_setpoint);

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