Simulate a downward facing optical flow sensor in SIH so that flow aided
navigation can be exercised without a rendered camera image. The flow rate is
the sum of the body rates and of the ground relative velocity scaled by the
distance to the ground, integrated over one publication interval and published
on sensor_optical_flow with configurable rate (SIH_OF_RATE) and noise
(SIH_OF_NOISE).
The sensor reports the integrated flow only: the flow module completes the
sample with the vehicle gyro and the downward facing distance sensor, which
therefore has to be enabled as well. Quality drops to zero above
SIH_OF_H_MAX or when the flow rate exceeds what the sensor can correlate.
The topic is advertised before the simulated clock starts, because the sensors
module brings up its flow pipeline on the first appearance of the topic, and
publishing during startup deadlocks the lockstep clock this thread advances.
Add the quadx_flow and standard_vtol_flow models with matching airframes:
SYS_AUTOSTART 10046 flies the multicopter on flow only with no GNSS, 10047
fuses the flow next to GNSS on a VTOL.
On NuttX these are two things: / is the filesystem root, and /fs/microsd is the
SD card mounted under it. MAVLink FTP serves the root and confines writes to the
SD card, so the read-only ROMFS at /etc is visible but cannot be written.
On POSIX they were the same directory. PX4_ROOTFSDIR and PX4_STORAGEDIR both
resolved to CONFIG_BOARD_ROOT_PATH, which on SITL is ".", so the working
directory was simultaneously the FTP root and the only writable area. The
consequences were that the ROMFS symlink sat inside the FTP root, and that
_validatePathIsWritable() had nothing meaningful to check against and so was
compiled out on POSIX entirely, leaving no write restriction at all.
Give POSIX the same split. CONFIG_BOARD_ROOT_PATH keeps its meaning as the
storage directory, and a new CONFIG_BOARD_FS_ROOT_PATH names the root FTP
serves, defaulting to the storage path so every existing board is unchanged.
SITL sets the root to "." and storage to "./fs", which mirrors NuttX: logs,
parameters, dataman and eeprom move under ./fs, and etc/ stays in the root as
read-only data.
With storage distinct from the root, the write restriction now applies on every
platform rather than NuttX only, and no longer compares against a hardcoded
prefix length that was wrong for any board not using /fs/microsd.
Assisted-by: Claude:claude-opus-5[1m]
Signed-off-by: Julian Oes <julian@oes.ch>
At 9000 RPM the propeller produced 4.6 N at trim airspeed while the model
needs about 5.3 N to hold 15 m/s level, so the plane could not sustain
trim airspeed at all.
Spin the same APC 8x6" propeller at 13000 RPM, which gives 11.3 N at trim
airspeed. The step is this large because prop wash over the tailplane and
the fin increases their local dynamic pressure, which eats roughly three
quarters of any added thrust.
Also raise the maximum climb rate, since a 30 deg climb at trim airspeed
needs 15 m/s * sin(30 deg) = 7.5 m/s and the default is 5 m/s.
Measured in SITL: 19.7 m/s at full throttle in near level flight (3 deg,
1 m/s climb). The thrust sustains a climb of over 30 deg, but reaching it
requires a steeper pitch than the takeoff and pitch limit defaults allow.
Signed-off-by: Silvan <silvan@auterion.com>
Docs - Orchestrator / T2: Link Check (push) Canceled after 0s
Docs - Orchestrator / T3: Build Site (push) Canceled after 0s
Docs - Orchestrator / T4: Deploy (push) Canceled after 0s
Failsafe Simulator Build / build (failsafe_web) (push) Canceled after 0s
ITCM check / Checking nxp_mr-tropic (push) Canceled after 0s
ITCM check / Checking nxp_tropic-community (push) Canceled after 0s
ITCM check / Checking px4_fmu-v5x (push) Canceled after 0s
ITCM check / Checking px4_fmu-v6xrt (push) Canceled after 0s
ROS Integration Tests / build (push) Canceled after 0s
ROS Translation Node Tests / Build and test [humble] (push) Canceled after 0s
ROS Translation Node Tests / Build and test [jazzy] (push) Canceled after 0s
SITL Tests / Testing PX4 quadx (push) Canceled after 0s
SITL Tests / Testing PX4 standard_vtol (push) Canceled after 0s
SITL Tests / Testing PX4 xvert (push) Canceled after 0s
FLASH usage analysis / Analyzing px4_fmu-v5x (push) Canceled after 0s
FLASH usage analysis / Analyzing px4_fmu-v6x (push) Canceled after 0s
Python CI Checks / build (push) Canceled after 0s
FLASH usage analysis / Publish Results (push) Canceled after 0s
Static Analysis / Clang-Tidy (push) Canceled after 0s
The gz_x500 airframe configures asymmetric CA_ROTOR positions while the current Gazebo x500 model places all four rotors on a square at +/-0.174 m.
Because ControlAllocator builds its effectiveness matrix from CA_ROTOR geometry, the mismatch produces a fixed roll/pitch control-effectiveness asymmetry in an otherwise symmetric simulated vehicle.
Align CA_ROTOR0-3 PX/PY with the current x500 model geometry. No allocator logic, thrust model, motor ordering, KM, CT, or controller gains are changed.
SITL validation with stock PX4 position control:
- 4/4 takeoff/hover/step/land flights completed without errors
- before: K_pitch/K_roll = 1.3804 +/- 0.0114 (OLS)
- after: K_pitch/K_roll = 1.0015 +/- 0.0002 (OLS)
Assisted-by: Claude:claude-opus-5
Signed-off-by: Veli Bakırcıoğlu <vbakircioglu@gmail.com>
* feat(reboot): new param to reset also CAL_* params with reboot and SYS_AUTOCONFIG on
* refactor(reboot): SYS_AUTOCFG_CAL description shorter
* refactor(reboot): reset SYS_AUTOCFG_CAL
* refactor(reboot): swap lines to make SYS_AUTOCFG_CAL appear in params list even if not set default to anything
Symmetric with the existing COM_DL_LOSS_T / COM_RC_LOSS_T /
COM_OF_LOSS_T / COM_OBC_LOSS_T scalings just above. At high simulation
speed the default 10s preflight disarm is reached much sooner in
real wall time than tests expect, so scale it the same way.
* feat(failure_injection): integrate failure injection support across sensor drivers
* feat(failure_injection): enhance failure injection with RC switch support and instance bitmasking
feat(failure_injection): add disabled failure injection manager and system command support for v5x and v6x boards
* feat(failure_injection): add battery failure injection
Add a value-mutating apply-site for FAILURE_UNIT_SYSTEM_BATTERY. On an
injected OFF the outgoing battery_status is reported as a depleted pack
(zero remaining, emergency warning) so the low-battery failsafe triggers.
The apply-site lives in the shared Battery library, covering the analog
ADC, INA power monitors, ESC battery and SITL in one place, plus the
UAVCAN battery driver which publishes battery_status directly. The
previous SITL-only hack in BatterySimulator is removed in favour of this
shared path so simulation and hardware behave identically.
* fix(failure_injection): change parameter types from int32 to enum
* refactor(failure_injection): disable failure injection manager and system commands across multiple boards
* feat(failure_injection): enhance failure injection with timestamp handling and message-less support
* refactor(failure_injection): simplify has_timestamp_sample implementation and remove unused includes
* refactor(failure_injection):move conditional compilation into helper libary
* refactor(failure_injection): update CMakeLists to include failure_injection dependency across multiple drivers
---------
Co-authored-by: Claudio Chies <chiesc@chies.com>
* refactor(ROMFS): remove trailing zeros from all airframes
* refactor(ROMFS): remove allignment whitespace from all startup scripts
* feat(romfs_pruner): strip end of line comments in startup scripts
and airframes to not waste any flash.
* feat(romfs_pruner): strip inline multi-whitespace
* fix typo
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: Jacob Dahl <37091262+dakejahl@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
The sihsim_xvert currently tumbles immediately on takeoff. Here is why:
generate_ts_aerodynamics in sih.cpp calculates elevon torques.
everything is rotated into the fixed-wing frame, in which
- positive _u[4] (configured as CA_SV_CS0) generates positive FW roll
torque (left wing pushed up)
- positive _u[5] (configured as CA_SV_CS1) generates positive FW roll
torque (right wing pushed down, note the additional minus)
So in the FW frame, they work like this:
- positive _u[4] + _u[5] -> positive FW roll torque
- positive _u[4] - _u[5] -> positive FW pitch torque
The airframe file however configures all of these in the multicopter
frame. So accounting for the frame conversion, we have:
- MC yaw = -FW roll = -_u[4] - _u[5]
- because FW x points nose-forward while MC z points nose-backward
- MC pitch = FW pitch = _u[4] - _u[5]
or in matrix form:
[ MC yaw ] [ -1 -1 ] [ _u[4] ]
[ MC pitch ] = [ 1 -1 ] [ _u[5] ]
and as this matrix is basically (up to scaling)
[ CS0_TRQ_Y CS1_TRQ_Y ]
[ CS0_TRQ_P CS1_TRQ_P ]
we have to change the CS1_TRQ_* coefficients to be negative.
This setting comes from a time where takeoff was accepted immediately if the acceptance radius was too big and also the mission behavior was completely different:
95a8414895
#27605 gated the dshot/pwm_out start on `param compare -s PASSTHRU_EN 0`.
PASSTHRU_EN is registered only when the serialpassthrough driver is
compiled in, which is not the case on most boards (e.g. fmu-v5x). There
param_find() fails, `param compare` returns "no match", the else branch
runs, and the FMU outputs never start: the PWM_AUX group disappears from
the Actuators screen and motors wired to those pins won't arm. SITL uses a
separate init.d-posix rcS and is unaffected, so CI did not catch it.
Use the start-unless-explicitly-enabled idiom already used elsewhere in
rcS (`param greater -s`): only skip the outputs when PASSTHRU_EN is
explicitly > 0. A missing or zero parameter starts the outputs as before.
* fix(commander): save parameters synchronously after parameter reset
ParamResetAll and ParamResetAllConfig relied on the deferred autosave (300 ms delay, 2 s rate limit) to persist the reset, so a reboot or power cycle right after the command ack could leave the old parameters in storage. Save synchronously like ParamResetSensorFactory already does.
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>
* fix(rcS): only run caldata BSON size repair on boards with caldata
The bsondump docsize block from #23088 repairs a zeroed BSON document size field in /fs/mtd_caldata, but it ran unconditionally with a comment claiming it checks /fs/mtd_params, producing failed-bsondump boot noise on every board without a caldata partition. Move it inside the MTD_CALDATA gate next to the param load it exists to protect.
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>
---------
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>
PR #18421 added the initial mag calibration save and was deliberately merged with SENS_MAG_AUTOCAL=0 until parameter system concerns were addressed. PR #19818 (CAN GPS nodes) flipped the global default to 1 as an undiscussed side change, shipped in v1.14.0. Since then every uncalibrated mag marks itself calibrated (CAL_MAGn_ID set) shortly after the disarmed bias estimator stabilizes, so ground stations stop prompting for compass calibration on new setups, and the first flight happens on a hard-iron-only estimate with an assumed mount rotation.
Restore the disabled default and enable it where it is genuinely needed: CAN nodes, which have no GCS calibration flow and no EKF for in-flight refinement. MBE_ENABLE is untouched, the bias estimator still runs and corrects everywhere.
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>
* feat: implemented serial passthrough
* fix: used make format
* fix: changed function order to match other drivers
* fix: moved passthrough from systemcmds to drivers
* fix: renamed BITBANG_TIMER to UART_BITBANG_TIMER
* fix: used make format
* feat: added PASSTHRU_EN guard to start of dshot&pwm_out
* fix: made changing ESC channels more stable
* fix: adjusted naming of guards
* fix: changed include guard of bitbang
* fix: removed unused variable SER_PASS_BAUD
* fix: adjusted comments
* fix: adjusted print_usage() to match other drivers
* fix: remove bitbang_write_byte from public API and some buffer guard
* fix: added Serialpassthrough&Bitbang to exclude list of allyesconfig.py
* fix: added missing flag to print_usage()
Flashing PX4 over another firmware (e.g. ArduPilot on an ARK FPV) or
first-booting a board with blank parameter storage played the error tune
on every boot: the param layer treated a blank store as corruption, and
the rcS recovery persisted with a file cp that is a no-op on
FLASH_BASED_PARAMS boards, so the store never became valid.
- param_import()/param_load() return 1 ("not yet stored") for a blank
source - empty file, zeroed FRAM, or erased flash - on both the file
and flash backends; a store that holds data but no valid entry (torn
write, bit-rot, foreign data) is still reported as corrupt (-EILSEQ).
The file backend detects a zero-length file via fstat (NuttX FAT
cannot read() a 0-byte file: no cluster chain returns an error, not
EOF) and otherwise inspects the leading BSON document length; the
flash backend scans the whole store
- new 'param load-or-init <backup>' command: loads from the default
storage; a blank store is seeded from the SD backup (or firmware
defaults) and persisted so the next boot loads normally. A corrupt
store, a backup that exists but cannot be opened or imported, or a
result that cannot be persisted returns failure. The three-way
loaded/blank/corrupt logic lives in C because nsh $? is a binary
success flag. A failed backup seed does not reset to defaults, which
preserves parameters loaded earlier in boot (e.g. factory calibration
from /fs/mtd_caldata)
- rcS uses 'param load-or-init' instead of 'param import', and the
corrupt-store recovery persists via 'param save' (works on
flash-backed boards) only when the backup actually imported, so a
corrupt backup keeps alerting the operator on the next boot
- commander ParamLoadDefault treats blank storage (1) as success and
warns the GCS that parameters were reset to defaults, instead of
reporting "Error loading settings"
- parameter_flashfs_init() in flashfs.c no longer reports a successful
erase byte count as a failure (parity with flashfs32.c)
Tested with new blankImport and corruptImport cases in 'tests
parameters' (empty/zeroed/erased sources import as "not yet stored",
garbage fails to import); the CustomDefaults test now restores the
firmware default so the suite is repeatable within one boot.
The STM32H7 flash-erase DCACHE invalidate fix this depends on
(PX4/NuttX#381) is already in main's NuttX submodule.
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>
Build all targets / Scan for Board Targets (push) Has been cancelled
Build all targets / Seed [${{ matrix.chip_family }}] (push) Has been cancelled
Build all targets / Build [${{ matrix.runner }}][${{ matrix.group }}] (push) Has been cancelled
Build all targets / Upload Artifacts (push) Has been cancelled
Checks / Gate Checks [check_format] (push) Has been cancelled
Checks / Gate Checks [check_newlines] (push) Has been cancelled
Checks / Gate Checks [module_documentation] (push) Has been cancelled
Checks / Gate Checks [shellcheck_all] (push) Has been cancelled
Checks / Gate Checks [validate_module_configs] (push) Has been cancelled
Checks / Unit Tests (push) Has been cancelled
MacOS build / build (push) Has been cancelled
Ubuntu environment build / Build and Test (ubuntu:22.04) (push) Has been cancelled
Ubuntu environment build / Build and Test (ubuntu:24.04) (push) Has been cancelled
Container build / Set Tags and Variables (push) Has been cancelled
Container build / Build Container (amd64) (push) Has been cancelled
Container build / Build Container (arm64) (push) Has been cancelled
Container build / Deploy To Registry (push) Has been cancelled
Docs - Orchestrator / T1: Detect Changes (push) Has been cancelled
Docs - Orchestrator / T2: PR Metadata (push) Has been cancelled
Docs - Orchestrator / T2: Metadata Sync (push) Has been cancelled
Docs - Orchestrator / T2: Link Check (push) Has been cancelled
Docs - Orchestrator / T3: Build Site (push) Has been cancelled
Docs - Orchestrator / T4: Deploy (push) Has been cancelled
Failsafe Simulator Build / build (failsafe_web) (push) Has been cancelled
ITCM check / Checking nxp_mr-tropic (push) Has been cancelled
ITCM check / Checking nxp_tropic-community (push) Has been cancelled
ITCM check / Checking px4_fmu-v5x (push) Has been cancelled
ITCM check / Checking px4_fmu-v6xrt (push) Has been cancelled
ROS Integration Tests / build (push) Has been cancelled
ROS Translation Node Tests / Build and test [humble] (push) Has been cancelled
ROS Translation Node Tests / Build and test [jazzy] (push) Has been cancelled
SITL Tests / Testing PX4 iris (push) Has been cancelled
Docs - Crowdin - Upload Guide sources (en) / upload-to-crowdin (push) Has been cancelled
FLASH usage analysis / Analyzing px4_fmu-v5x (push) Has been cancelled
FLASH usage analysis / Analyzing px4_fmu-v6x (push) Has been cancelled
Python CI Checks / build (push) Has been cancelled
Sync ROS 2 messages to px4_msgs / sync_to_px4_msgs (push) Has been cancelled
FLASH usage analysis / Publish Results (push) Has been cancelled
Static Analysis / Clang-Tidy (push) Has been cancelled
* fix(simulation): preserve gravity and step_size in px4-rc.gzsim set_physics
The set_physics service call in px4-rc.gzsim sent only real_time_factor.
Other fields in gz.msgs.Physics (gravity, max_step_size) defaulted to 0
per protobuf semantics, silently zeroing world gravity in the gz physics
engine when PX4_SIM_SPEED_FACTOR was set. Vehicles became weightless
while PX4's accelerometer (sourced from the gz IMU plugin's cached SDF
gravity) continued to report -9.81 m/s², making the bug invisible from
PX4's side.
Resolve the values via the live gz physics topic, fall back to the
world SDF, and finally to Earth gravity / gz-harmonic default step
size, then include the full set in the set_physics request.
Fixes#27480
Signed-off-by: Marko T <marko.tavcar@c-astral.com>
* fix(simulation): resolve world name in standalone and drop dead physics topic
The gz physics topic queried for gravity/max_step_size does not exist in
gz Harmonic (only a write-only set_physics service), so that branch always
timed out and fell through. Read both values directly from the world SDF,
which is the source of truth at load time.
Also resolve PX4_GZ_WORLD from the running gz instance (clock topic) inside
the readiness check, so standalone launches — where the world name is not
known up front — can find the scene and the world SDF.
Signed-off-by: Marko T <marko.tavcar@c-astral.com>
* Update ROMFS/px4fmu_common/init.d-posix/px4-rc.gzsim
Co-authored-by: Jacob Dahl <37091262+dakejahl@users.noreply.github.com>
* Update ROMFS/px4fmu_common/init.d-posix/px4-rc.gzsim
Co-authored-by: Jacob Dahl <37091262+dakejahl@users.noreply.github.com>
* docs(simulation): clarify gravity-default fallback comment in px4-rc.gzsim
Fix typo ("greavity") and reword the comment to clearly state that the
hardcoded gravity/step-size defaults are only used when the world SDF
cannot be located, and are wrong for custom-gravity worlds.
Signed-off-by: Marko T <marko.tavcar@c-astral.com>
---------
Signed-off-by: Marko T <marko.tavcar@c-astral.com>
Co-authored-by: Jacob Dahl <37091262+dakejahl@users.noreply.github.com>
Place firmware .bin files at the SD card root or staging directory
(/fs/microsd/ufw_staging/); on boot the UAVCAN server migrates them
to /fs/microsd/ufw/ and updates FW.db, then flashes any connected
node whose firmware version mismatches.
- Add firmware migration from SD root and staging dir into /fs/microsd/ufw/
- Maintain FW.db flat-file database mapping board IDs to original filenames
- Use cache-aligned DMA-safe read/write buffers (required on STM32H7)
- Add Tools/auterion/remote_update_fmu.sh for SSH-based FMU+canio updates
* SITL: mavlink bind to a specific interface using an environment variable PX4_NET_INTERFACE
Fixes issue #26384
* document the usage of PX4_NET_INTERFACE
* Improved Docs:
- Added new Environment Configuration subsection at the end of SITL Simulation
- Removed the old Bind MAVLink to Specific Network Interface subsection (content consolidated into the new section)
---------
Co-authored-by: Hamish Willee <hamishwillee@gmail.com>
* Quadratic thrust for SIH hexarotor (#67)
* sih: add thrust model hexacopter model
* fix: add missing line break
* sihsim_hey airframe: add THR_MDL_FAC
to accomodate for simulated quadratic motor thrust.
* fix(sih): fix quadratic model in simulation
The square was done in place and the low pass filter also effected the same variable, the result was that for small numbers the low pass filter gain was not enouhg with respect to the decay caused by squaring numbers close to zero. As a result even if you where trying to send 1 xcommands in simulation it would stoip around 0.008. Now the square is done in a different variable, the problem is not there anymore.
Tested in simulation
---------
Signed-off-by: Gennaro Guidone <gennaroguido2002@gmail.com>
Co-authored-by: Matthias Grob <maetugr@gmail.com>
Co-authored-by: Gennaro Guidone <gennaroguido2002@gmail.com>
Integrators can declare read-only parameters in a per-board YAML file:
readonly_params.yaml.
There are two ways to define the read-only params:
- "block": default writable, explicitly list params to be locked
- "allow": default readonly, explicitly list params to be writable
Enforcement is activated by `param lock` in rcS after all startup
scripts have run, so board defaults and airframe scripts can still set
params during init.
The feedback via MAVLink uses the new
MAV_PARAM_ERROR_READ_ONLY as part of the PARAM_ERROR message.
The airframe 10043 (make px4_sitl sihsim_standard_vtol) currently does
not have enough forward thrust to reach VT_ARSP_TRANS (10) or
VT_ARSP_BLEND (8), so we get front transition timeout.
By bisecting, we find that #26720 breaks it. The PR introduces a new
dynamic prop model, which is now used in the airframes 1101, 1102, 1103,
and 1105 (new addition), but not 10043.
The PR also removes a previous magic number that gave the standard VTOL
pusher twice the max thrust of the hover motors (2 * 2N = 4N). It
introduces a separate SIH_F_T_MAX, but by default it is 2N, causing the
weak pusher for 10043.
Fix by using the new dynamic propeller model by default, with the same
params that #26720 introduces for airframe 1103 (It would also suffice
to only set SIH_F_T_MAX=6, but now that we have the nicer model let's
use it).
Note that 10041 (sihsim_airplane) is not broken by #26720 in this way,
as it already has SIH_T_MAX of 6N.
* refactor(battery_simulator): remove SIM_BAT_ENABLE
disable instead with SIM_BAT_DRAIN <= 0
* fix(battery_simulator): disable battery sim only if SIM_BAT_DRAIN strictly < 0
* fix(battery_simulator): disable if 0, adjust limit to 0
* fix(battery_simulator): remove constraining again
now that SIM_BAT_DRAIN=0 means the module is not started we are safe
from division by zero again (param compare has a tolerance of 1e-7)
* fix(battery_simulator): constrain param to min of 1
to avoid division by zero.
This reverts commit 6380c4fdee.
* fix(battery_simulator): remove arbitrary param max
* fix(battery_simulator): reword long param description
Co-authored-by: Jacob Dahl <37091262+dakejahl@users.noreply.github.com>
* fix(battery_simulator): reword short param description
Co-authored-by: Jacob Dahl <37091262+dakejahl@users.noreply.github.com>
---------
Co-authored-by: Jacob Dahl <37091262+dakejahl@users.noreply.github.com>
rc.mc_defaults sets MAV_TYPE=2 (quadrotor) which the hex airframe
never overrides. Set MAV_TYPE=13 (hexarotor) so the heartbeat
correctly identifies the vehicle type.
Signed-off-by: Ramon Roche <mrpollo@gmail.com>
There are many settings falling into the RC_* category
that definitely should be reset when e.g. placing the autopilot
into a new airframe.
And even for RC calibration values: it's not the worst
if those are newly calibrated after a reset. Or if they
are not expected to change one can bake them into the
airframe file.
Signed-off-by: Silvan <silvan@auterion.com>