Commit Graph

50514 Commits

Author SHA1 Message Date
Kirill
56ede3a888 fix(fw_att_control): use adapted tailsitter attitude for FW error
- In tailsitter case, construct current quaternion from _R, which is
   aready rotated correctly a bit above
 - Downside: bloaty solution of converting to rotation matrix, adjusting
   that, and converting back to quaternion
2026-07-06 13:21:15 +02:00
Julian Oes
a201b24287 fix(boards/airbrainh743): mark I2C1 external for external compass scan (#27814)
The AirBrainH743 breaks out a single I2C bus (I2C1) that also carries the
onboard DPS310 baro and IIS2MDC mag. Because the bus was marked internal,
the external-compass autostart (which scans external buses with -X) never
probed it, so an external GPS/compass on that bus was never bound.

Mark I2C1 external so the external-mag autostart scans it, and add a
px4_i2c_device_external() override (guarded by BOARD_OVERRIDE_I2C_DEVICE_EXTERNAL)
that keeps the onboard baro and mag classified as internal. This mirrors the
approach used on fmu-v6c. The onboard baro/mag are now started explicitly by
bus and address (-X -b 1) since -I no longer matches the external bus.

Also enable the i2cdetect command, which is handy for probing the shared
external bus on this board.

Signed-off-by: Julian Oes <julian@oes.ch>
2026-07-06 13:59:39 +12:00
Hamish Willee
4af6fbeabf fix(mavlink): DO_SET_GLOBAL_ORIGIN - enable in release (#27789)
* feat(mavlink): Add DO_SET_GLOBAL_ORIGIN to invalid param use checking

* feat(mavlink): DO_SET_GLOBAL_ORIGIN - remove development gating
2026-07-06 10:30:35 +12:00
Alexis Guijarro
fc8aaedfbe fix(mavlink): init mutexes before argument parsing (#27809) 2026-07-06 09:26:37 +12:00
Wang Jiayue
bfb48ad17e FlightTasks: initialize smoothing with current acceleration 2026-07-03 14:44:35 -07:00
Wang Jiayue
04e656edb9 vtol_takeoff: use takeoff position for default transition yaw 2026-07-03 14:34:12 -07:00
Eurus
c51aabcfec fix(commander): require GNSS altitude fusion for raw home position (#27604)
* HomePosition: require GPS altitude fusion for raw GNSS home

* Commander: name GNSS position fusion mask
2026-07-03 14:29:14 -07:00
gguidone
671f60e6da fix(flight_mode_manager): keep auto-takeoff vertical on a moving deck
On a moving deck the lift-off XY lock alone still leaned the vehicle: the
position smoother carried the inherited deck velocity into the takeoff and
braked it with a backward tilt during the thrust-limited ramp, which sprang
back at FLIGHT.

Give altitude priority for the first metre after lift-off: hold the live
horizontal position through the ramp (zero tracking error, no lean or spring
at FLIGHT) and the live horizontal velocity through the ramp and the first
metre of climb. Self-nulling on a static takeoff (no inherited velocity), so
the path is identical for static and moving takeoffs - no new param, no branch.

Signed-off-by: gguidone <gennaroguido2002@gmail.com>
2026-07-03 13:55:40 -07:00
gguidone
76fdc0f134 fix(flight_mode_manager): hold lift-off XY through the takeoff climb
Track the live horizontal position during the takeoff ramp and freeze it at
TAKEOFF_STATE_FLIGHT, overriding the position target (not just the smoother) so the
climb stays vertical over the lift-off point instead of running to the commanded
lat/lon once tilt authority opens at FLIGHT. Reset the lock on (re)activation.
2026-07-03 13:55:40 -07:00
gguidone
ef1be8be41 docs(flight_modes_mc): document multicopter takeoff from a moving platform
Signed-off-by: gguidone <gennaroguido2002@gmail.com>
2026-07-03 13:55:40 -07:00
gguidone
8ce9389afa fix(flight_mode_manager): hold lift-off point during moving-platform takeoff
Pin the smoother's horizontal position to the live position during the takeoff ramp so a moving platform doesn't stall the climb; released at TAKEOFF_STATE_FLIGHT.

Signed-off-by: gguidone <gennaroguido2002@gmail.com>
2026-07-03 13:55:40 -07:00
Wang Jiayue
733be29297 fix(navigator): clear course on loiter reposition 2026-07-03 13:28:41 -07:00
Julian Oes
b6b2028a80 fix(lockstep_scheduler): wait for threads before advancing time in test (#27798)
test_multiple_semaphores_waiting() spawns a worker thread per TestCase, then
advances virtual time in a loop and completes each case in check(). Since
check() early-returns while !_thread_ready, a slow-to-start worker thread can
miss the whole loop: the loop advances past the case's timeout before the thread
registers, so the case is never completed. ~TestCase() then fails
EXPECT_TRUE(_is_done) and destroys a still-joinable std::thread, which calls
std::terminate() and aborts the test. This was flaky (~50% locally, worse under
CI load).

Wait for every worker thread to be ready before advancing virtual time. Also
re-comment the per-iteration std::cout that was left enabled.

Signed-off-by: Julian Oes <julian@oes.ch>
2026-07-03 13:09:03 -07:00
PX4BuildBot
cc833b894d docs: auto-sync metadata [skip ci]
Co-Authored-By: PX4 BuildBot <bot@px4.io>
2026-07-03 19:53:30 +00:00
saad1551
cf0f76101b fix(navigator): enforce NAV_MIN_LTR_ALT in MC braking loiter
When a multicopter enters Hold (AUTO.LOITER) below NAV_MIN_LTR_ALT the
documented behavior is to first climb to that minimum altitude. The
clamp was added in 2022 to setLoiterItemFromCurrentPosition (the
fixed-wing branch) but never applied to the sibling
setLoiterItemFromCurrentPositionWithBraking, which is the rotary-wing
Hold path selected at loiter.cpp:131. As a result, multicopters
silently held at the entry altitude.

Apply the same min-altitude clamp in the braking variant so the
rotary-wing path matches the fixed-wing one.

Verified in SITL (jMAVSim x500): with NAV_MIN_LTR_ALT=20 and Hold
engaged from a 5m hover, the vehicle now climbs to 20m as documented.

Fixes #27578

Signed-off-by: saad1551 <saad.ashraf.9094@gmail.com>
2026-07-03 12:41:48 -07:00
Beat Küng
5d2cec97f1 chore(commander): remove unused flag_control_termination_enabled flag 2026-07-03 12:33:03 -07:00
Beat Küng
f33b5769fc chore: use setpoint_config in mc_raptor and mc_nn_control 2026-07-03 12:33:03 -07:00
Beat Küng
9fb0f1e43a chore(VehicleControlMode): remove unused flag_control_acceleration_enabled 2026-07-03 12:33:03 -07:00
Beat Küng
343eab2f05 feat(commander): add setpoint types
Switches from using VehicleControlMode to a specific setpoint type message
with reply.
Reasons:
- in case a VehicleControlMode was dropped (e.g. when the mode switched
  setpoint type), no confirmation was returned, and resulting in wrong
  controller flags.
- cleaner interface separation: external modes do not need to configure
  (or know) which controller to run for a certain setpoint
- allows for external modes to check for compatibility: e.g. a mode using
  fixed-wing setpoint types can now be rejected on a multicopter.
- allows for further extensions, like a setpoint timeout

This makes it a bit more effort to add a new setpoint type. Specifically,
setpoint_types.cpp needs to be extended when adding a new setpoint message.

PX4 internal modes also make use of the setpoint types. The information
flow is:
nav_state -> setpoint type -> vehicle control mode flags

It also adds a timeout to the setpoint config, but is not implemented
yet.

This changes the interface for external modes and thus the compatibility
version is increased.
2026-07-03 12:33:03 -07:00
Beat Küng
0280f41867 fix(navigator): resend mode_completed when mode is completed
Important for external modes in case a topic sample gets dropped.
2026-07-03 12:33:03 -07:00
Beat Küng
604fe59ed7 fix(commander): add config_overrides_confirm topic
Allows an external mode to check if the request got processed
2026-07-03 12:33:03 -07:00
Beat Küng
f0fa73bf8d chore(msg): remove unused VehicleAngularAccelerationSetpoint.msg 2026-07-03 12:33:03 -07:00
yannickpoffet
d0f7b7d8fc feat(uxrce_dds_client): drain / unlimited rate options for topic bridging (#27688)
* feat(uxrce_dds_client): add "drain" and "unlimited" rate options for dds_topics bridging

Drain option allows to specify that a queued uORB topic being bridged should
have its queue drained completely at every rate interval, instead of sending
only the latest message. This is useful to prevent jitter and delay being
added on topics subject to burst and irregular publishing patterns.

The "unlimited" rate option allows to specify that a uORB topic being bridged
should be sent as fast as possible, without any rate limiting. This is useful
for reducing latency on topics where no message loss is acceptable and where
the uORB topic is being published at a high rate.

* fix(dds_topics): remove "drain" option and safe guard against inf loop

Drain option is removed to be coupled with rate_limit = unlimited.

The loop is gated to the size of the uorb queue to avoid infinite loops
if publisher is faster that this loop.

* fix(dds_topics): simplification recommended in review
2026-07-03 12:14:40 -07:00
Ramon Roche
f19c9f98c5 fix(tecs): prevent NaN propagation in pitch controller (#27749)
* tecs: Prevent. NaN in pitch integrator

Prevents NaN propagation into _pitch_integ_state when seb_rate.setpoint is non-finite (as seen when exiting FW velocity Offboard). Mirrors the existing throttle integrator finite check. Fixes #25906.

* tecs: Harden the TECS pitch integrator against NaN contamination

* fix(tecs): guard pitch output against non-finite SEB rate

The integrator guard alone does not prevent the reported NaN lockup when
the non-finite value originates on the energy/speed side: the feedforward
and damping terms in _calcPitchControlOutput feed seb_rate straight into
the pitch demand, bypassing the integrator. constrain() does not reject
NaN, so the pitch setpoint latches NaN permanently and the aircraft
becomes uncontrollable.

Fall back to the (now guaranteed finite) integrator state when the
uncorrected pitch setpoint is non-finite, and drop the stray trailing
whitespace introduced by the previous commit.

Signed-off-by: Ramon Roche <mrpollo@gmail.com>

* test(tecs): regression test for NaN pitch integrator and output

Drives TECSControl::update with a non-finite true airspeed setpoint, the
same way seb_rate goes non-finite on the energy/speed side when exiting
offboard velocity mode, and asserts the pitch integrator state and the
pitch setpoint both stay finite, across a single bad frame and sustained
non-finite input. Both assertions fail against unguarded TECS.

Signed-off-by: Ramon Roche <mrpollo@gmail.com>

* test(tecs): cover the corrupted-integrator-state safety reset

Addresses review feedback on #27749: the existing tests inject a
non-finite airspeed setpoint, which the integrator-input guard rejects
before it can reach _pitch_integ_state, so the state-corruption reset
branch in _calcPitchControlUpdate was never actually exercised.

Add a FRIEND_TEST seam so the regression test can pre-corrupt
_pitch_integ_state directly, then confirm a single update() call detects
the non-finite state, resets it, and keeps the pitch setpoint finite.
Verified the test fails against the code with the reset guard removed and
passes with it in place.

---------

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
Co-authored-by: Ryan Johnston <31726584+ryanjAA@users.noreply.github.com>
Co-authored-by: Ryan Johnston <rjohnston@appliedaeronautics.com>
2026-07-03 11:58:33 -07:00
PX4BuildBot
36d0825b6e docs: auto-sync metadata [skip ci]
Co-Authored-By: PX4 BuildBot <bot@px4.io>
2026-07-03 17:06:24 +00:00
Alexis Guijarro
f903391f44 feat(drivers): add DPS368 variant support via -8 flag (#27724)
* feat(drivers/dps310): add DPS368 variant support via -8 flag

Register DRV_BARO_DEVTYPE_DPS368 (0x77) and extend the dps310 driver
entry point with a -8 flag to select the DPS368 devtype at startup.

* fix(drivers/dps310): set device type from devid_driver_index after init
2026-07-03 10:00:03 -07:00
cuav-chen2
40671b2a58 refactor(boards/cuav_x25-evo): Remove INS to save flash 2026-07-03 09:53:30 -07:00
Balduin
580e9750fd refactor(sih): use basic Publication + class member
needs less flash
2026-07-03 09:48:22 -07:00
Balduin
d8847067a8 refactor(sih): remove local variable to save stack
A recent SIH log (V6X) was full of:

WARNING: [px4] [load_mon] sih low on stack! (144 bytes left)

Using PublicationData (which holds the esc_status_s in heap rather than
stack) fixes them and adheres to the philosophy from the module
description: "Most of the variables are declared global in the .hpp file
to avoid stack overflow"
2026-07-03 09:48:22 -07:00
Julian Oes
94c12f468c fix(mc_pos_control): allow disabling trajectory time-stretch and fix docs
The trajectory time-stretch is skipped when the max-error param is at or below
FLT_EPSILON, so zero is a valid 'disabled' setting. Lower the minimum of
MPC_XY_ERR_MAX and MPC_Z_ERR_MAX from 0.1 to 0 so users can actually select it,
and document it in both params.

Also fix the setMaxAllowedVerticalError() doc comment, which incorrectly
claimed zero was the default: the MPC_Z_ERR_MAX param default is 1 m.

Signed-off-by: Julian Oes <julian@oes.ch>
2026-07-03 09:46:48 -07:00
Julian Oes
49535090a8 refactor(motion_planning): remove unused clampToXYNorm/clampToZNorm
These helpers are no longer called from production code after the smoother
was reworked to clamp XY and Z velocity components independently. Their only
remaining references were in TrajectoryConstraintsTest.cpp, which is not
registered in CMake and therefore never compiled. Drop both the functions and
the orphaned tests.

Signed-off-by: Julian Oes <julian@oes.ch>
2026-07-03 09:46:48 -07:00
Julian Oes
495803a1db feat(mc_pos_control): per-axis time-stretch with new MPC_Z_ERR_MAX
PositionSmoothing already has a horizontal-error gate (MPC_XY_ERR_MAX)
that slows trajectory integration when the smoother's virtual position
runs ahead of the drone in XY. The same time-stretch was applied to
all three axes, but it was only ever computed from XY error. So:

- Z lag never slowed Z down: a noisy altitude reference (e.g. mission
  setpoint jittering as home altitude is refined in flight) could
  walk the commanded z 5+ m above the mission target while horizontal
  tracking stayed fine. The jerk-limited smoother integrates each
  small step into a velocity ramp, and successive ramps superpose
  into multi-meter altitude excursions.

- Z lag dragging XY: when a Z stretch eventually was added, applying
  the same scalar to all axes meant a ±1 m altitude jitter could
  cap forward flight speed during a straight mission leg. That's
  almost never what we want.

Fix: compute time_stretch_xy and time_stretch_z independently using
their own _max_allowed_*_error thresholds and apply per-axis. Default
the new MPC_Z_ERR_MAX to 1 m (tighter than XY's 2 m because altitude
holds are usually crisper). Other PositionSmoothing users (Orbit,
GotoControl) keep zero as the vertical error cap, which is the
explicit "disable Z stretch" sentinel — so behaviour there is
unchanged.
2026-07-03 09:46:48 -07:00
Julian Oes
4211f3d427 fix(payload_deliverer): configure gripper before arming callbacks
ScheduleOnInterval and registerCallback can both invoke Run() on
another thread (the work queue / publisher thread). configure_gripper
sets state Run() reads, so it must complete before the callbacks are
armed — otherwise a fast first iteration can race with the gripper
initialization.
2026-07-03 09:46:48 -07:00
Julian Oes
ab5d7aefa9 fix(flight_mode_manager): init state before registering callback
set_interval_us() and the initial _time_stamp_last_loop write must
happen before the uORB subscription callback is armed — otherwise a
publisher on another thread can invoke Run() concurrently with init().
Run() reads _time_stamp_last_loop and depends on the interval being
set; observing zero-init values briefly leads to either a giant first
dt or an over-rate first iteration.
2026-07-03 09:46:48 -07:00
Julian Oes
1ae8f2383f refactor(motion_planning): split XY/Z velocity components in smoother
PositionSmoothing::_generateVelocitySetpoint computed a single
constrained 3D velocity vector and then ran clampToXYNorm /
clampToZNorm in series. The XY clamp could shorten the Z component
(and vice versa), so a Z speed limit ended up capping forward speed
and a tight altitude error capped horizontal motion. Compute XY and
Z velocity components independently using their own speed limits so
they don't mutually clamp.

Companion to the per-axis time-stretch fix (commit added later in
the chain). Together they decouple the horizontal and vertical
trajectory dynamics in the smoother.
2026-07-03 09:46:48 -07:00
Julian Oes
43131d474c fix(mavlink): don't miss mission current updates
When a mission is finished we need to make sure to send the mission
current message and not drop it. Otherwise, MAVSDK tests might not get
the update that the mission has been finished.
2026-07-03 09:46:48 -07:00
PX4BuildBot
c772b23067 docs: auto-sync metadata [skip ci]
Co-Authored-By: PX4 BuildBot <bot@px4.io>
2026-07-03 15:39:03 +00:00
Balduin
deb21ae2be fix(fw_latlon_control): add back FW_PSP_OFF after TECS
Before calling _tecs.update in tecs_update_pitch_throttle, all pitch
values are corrected by subtracting trim pitch, so TECS internal pitch
is always relative to trim.

To stay correct we have to add it back when passing the TECS internal
pitch setpoint to the rest of the system.
2026-07-03 17:33:48 +02:00
Balduin
3e9841cbb6 feat(docs): sort dds topics, fix formatting (#27794) 2026-07-03 08:44:15 +10:00
PX4BuildBot
60ed1a27d4 docs: auto-sync metadata [skip ci]
Co-Authored-By: PX4 BuildBot <bot@px4.io>
2026-07-02 19:21:36 +00:00
Ramon Roche
2f459921f6 docs: add official PX4 developer kits and manufacturer program
Document the Official PX4 Developer Kit program: a new top-level
Developer Kits section listing the certified kits (ModalAI Starling 2
Max, DroneBlocks DEXI 5, Holybro X500 v2), a new DEXI 5 page, and a
manufacturer-facing page describing the program requirements, benefits,
and eligibility.

Restructure the hardware navigation so all certified kits live in one
place instead of being split across Complete Vehicles and Kits, drop
discontinued build guides from the sidebar (still linked from the kit
build guides page), and group the manufacturer guides under a new
Manufacturers section in Development > Hardware.

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-07-02 12:15:03 -07:00
PX4BuildBot
47896d8aa1 docs: auto-sync metadata [skip ci]
Co-Authored-By: PX4 BuildBot <bot@px4.io>
2026-07-02 15:51:29 +00:00
Julian Oes
bca6e3df75 fix(mavlink): give mavlink_channel_send_mutexes internal linkage
The per-channel send mutex array was defined without static, giving it external
linkage in the single-binary firmware even though it is only used within
mavlink_main.cpp (its status/buffer siblings are already static). Make it static
to match and avoid a latent cross-TU name clash.

Signed-off-by: Julian Oes <julian@oes.ch>
2026-07-02 08:42:49 -07:00
Julian Oes
abc5780776 refactor(mavlink): apply protocol version on channel assignment, drop early buffers
get_status()/get_buffer() returned per-instance _mavlink_status_early/
_mavlink_buffer_early fallbacks because the constructor touches the channel
status (via mavlink_update_parameters() -> setProtocolVersion()) before
set_instance_id() has assigned a channel, and set_instance_id() then copied
those into the static per-channel arrays.

Instead, don't touch channel state before we own a channel: setProtocolVersion()
now only caches _protocol_version until _instance_id is valid, and set_instance_id()
applies the cached version to the freshly-claimed channel's status flags. This lets
get_status()/get_buffer() index the per-channel arrays directly and removes the two
early buffers. The end state is identical (the buffer copy always copied a
zero-initialized buffer, since nothing writes it before assignment).

Signed-off-by: Julian Oes <julian@oes.ch>
2026-07-02 08:42:49 -07:00
Julian Oes
f92996f16b test: document why 'sensors status' is disabled in test_imu_filtering
Replace the terse "triggers TSAN" note with a TODO explaining that 'sensors
status' reads sensor module state from the shell thread without synchronization,
so it should be re-enabled once that race is fixed.

Signed-off-by: Julian Oes <julian@oes.ch>
2026-07-02 08:42:49 -07:00
Julian Oes
f15c796b56 docs(nuttx): document px4_task_join limitations
NuttX tasks are task_create() children, not pthreads, so px4_task_join has no
portable join and instead polls whether the task still exists. Document that it
returns no exit status, can wait on the wrong task if the PID is reused, and is
only safe because its sole on-target caller is WorkQueueManager shutdown (and
NuttX shutdown is a full reboot).

Signed-off-by: Julian Oes <julian@oes.ch>
2026-07-02 08:42:49 -07:00
Julian Oes
48a08e1633 fix(posix): guard px4_task_join/delete against negative task ids
px4_task_t is a plain int and callers hold -1 for "no task" (e.g. dataman's
g_task_id after stop). The bounds checks only tested id < PX4_MAX_TASKS, which is
true for negative ids, so px4_task_join(-1) and px4_task_delete(-1) would index
taskmap[-1] out of bounds. Check id >= 0 as well.

Signed-off-by: Julian Oes <julian@oes.ch>
2026-07-02 08:42:49 -07:00
Julian Oes
d828e1b12d fix(uORB): snapshot _data under the node lock before sending to a remote subscriber
process_add_subscription() (CONFIG_ORB_COMMUNICATOR only) read _data_valid and
the topic buffer contents while passing a pointer into _data straight to
send_message(), with no synchronization against a concurrent publisher. A
publisher's write() memcpy's into _data and sets _data_valid under ATOMIC_ENTER,
so the remote-init send can read a torn/partially-updated sample - most clearly
for o_queue == 1, where the read slot ((gen - 1) % 1) is exactly the slot being
written.

This is a pre-existing latent race (the previous px4::atomic<uint8_t*> _data only
guarded the pointer, never the bytes) that neither ASan nor TSan can catch because
CONFIG_ORB_COMMUNICATOR is not built in those configs. On VOXL2 it runs on the
muorb RX thread concurrently with publishers.

Snapshot the most recent sample into a temporary buffer under ATOMIC_ENTER, then
send it outside the critical section - mirroring copy(). The buffer is allocated
before the critical section (it cannot be allocated under ATOMIC_ENTER on NuttX)
and send_message() must run outside it anyway, since it can be slow and may call
back into DeviceNode. This only affects the rare subscription-add path, not the
publish hot path.

Signed-off-by: Julian Oes <julian@oes.ch>
2026-07-02 08:42:49 -07:00
Julian Oes
358b090c4e fix(posix): initialize PX4 before starting the daemon server
The daemon server's client-handler thread spawns module tasks (e.g. dataman).
Start px4::init_once()/init() before creating px4_daemon::Server so platform init
- uORB, work queues, logging - completes with a happens-before edge to those
tasks. Otherwise a module task racing the still-running init reads globals like
uORB::Manager's instance pointer or the log message advertisement without
synchronization (ThreadSanitizer flags it) - and an atomic would not make it
correct, since the publication could simply be skipped.
2026-07-02 08:42:49 -07:00
Julian Oes
99c1eb8123 fix(mavlink): bump per-message tstatus counters lock-free instead of under the mutex
tx_message_count (every send) and tx_buffer_overruns took _tstatus_mutex on the
hot path just to increment a counter. Make them px4::atomic, like the existing
_bytes_* counters, bumped lock-free from either thread's send path and folded
into _tstatus (cumulative) under the mutex at the ~1 Hz publish. The mutex is
kept for the genuinely shared low-frequency fields. (Suggested in review.)
2026-07-02 08:42:49 -07:00