mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-08-21 01:50:35 +08:00
Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 556bec3374 | |||
| 06d25b9400 | |||
| bfbc76189e | |||
| 80febaf0f0 | |||
| f0ecd9e757 | |||
| 168d99cd18 | |||
| b8dacf5ae4 | |||
| 54f2652329 | |||
| f9b811b0c5 | |||
| a755dfa07f | |||
| b4bfbbb5e0 | |||
| 35a3f519f2 | |||
| a3f1fb2e01 | |||
| f224d27e4d | |||
| 7d33df4650 | |||
| 3c0a0ed129 | |||
| 7f5119f402 |
@@ -0,0 +1,72 @@
|
||||
#!/bin/sh
|
||||
# @name Rover Ackermann
|
||||
# @type Rover
|
||||
# @class Rover
|
||||
|
||||
. ${R}etc/init.d/rc.rover_ackermann_defaults
|
||||
|
||||
set VEHICLE_TYPE rover_ackermann
|
||||
param set-default CA_AIRFRAME 5 # Rover (Ackermann)
|
||||
param set-default CA_R_REV 1 # Motor is assumed to be reversible
|
||||
param set-default EKF2_MAG_TYPE 1 # Make sure magnetometer is fused even when not driving
|
||||
param set-default NAV_ACC_RAD 0.5 # Waypoint acceptance radius
|
||||
param set-default EKF2_GBIAS_INIT 0.01
|
||||
param set-default EKF2_ANGERR_INIT 0.01
|
||||
|
||||
|
||||
PX4_SIMULATOR=${PX4_SIMULATOR:=sihsim}
|
||||
PX4_SIM_MODEL=${PX4_SIM_MODEL:=rover_ackermann}
|
||||
|
||||
param set-default SIH_VEHICLE_TYPE 5 # sih as rover ackermann
|
||||
|
||||
param set-default PWM_MAIN_FUNC1 201 # Steering
|
||||
param set-default PWM_MAIN_FUNC2 101 # Throttle
|
||||
param set-default SIH_MASS 20
|
||||
param set-default SIH_IXX 0.4333
|
||||
param set-default SIH_IYY 1.6833
|
||||
param set-default SIH_IZZ 2.0833
|
||||
param set-default SIH_IXZ 0
|
||||
param set-default SIH_KDV 50
|
||||
param set-default SIH_KDW 10
|
||||
|
||||
param set-default SENS_EN_GPSSIM 1
|
||||
param set-default SENS_EN_BAROSIM 1
|
||||
param set-default SENS_EN_MAGSIM 1
|
||||
|
||||
# Ackermann Parameters
|
||||
param set-default RA_WHEEL_BASE 0.321
|
||||
param set-default RA_ACC_RAD_GAIN 2
|
||||
param set-default RA_ACC_RAD_MAX 3
|
||||
param set-default RA_MAX_STR_ANG 0.5236
|
||||
param set-default RA_STR_RATE_LIM 360
|
||||
|
||||
# Rate Control Parameters
|
||||
param set-default RO_YAW_RATE_I 0.01
|
||||
param set-default RO_YAW_RATE_P 0.25
|
||||
param set-default RO_YAW_RATE_LIM 180
|
||||
param set-default RO_YAW_ACCEL_LIM 400
|
||||
param set-default RO_YAW_DECEL_LIM 800
|
||||
param set-default RO_YAW_RATE_CORR 1
|
||||
|
||||
# Attitude Control Parameters
|
||||
param set-default RO_YAW_P 5
|
||||
|
||||
# Velocity Control Parameters
|
||||
param set-default RO_ACCEL_LIM 3
|
||||
param set-default RO_DECEL_LIM 3
|
||||
param set-default RO_JERK_LIM 10
|
||||
param set-default RO_MAX_THR_SPEED 3.2
|
||||
param set-default RO_SPEED_LIM 3
|
||||
param set-default RO_SPEED_I 0.001
|
||||
param set-default RO_SPEED_P 0.001
|
||||
param set-default RO_SPEED_RED 1
|
||||
|
||||
# Pure Pursuit parameters
|
||||
param set-default PP_LOOKAHD_GAIN 1
|
||||
param set-default PP_LOOKAHD_MAX 10
|
||||
param set-default PP_LOOKAHD_MIN 1
|
||||
|
||||
# Pure Pursuit parameters
|
||||
param set-default PP_LOOKAHD_GAIN 1
|
||||
param set-default PP_LOOKAHD_MAX 10
|
||||
param set-default PP_LOOKAHD_MIN 1
|
||||
@@ -108,6 +108,7 @@ px4_add_romfs_files(
|
||||
10042_sihsim_xvert
|
||||
10043_sihsim_standard_vtol
|
||||
10044_sihsim_hex
|
||||
10045_sihsim_rover_ackermann
|
||||
|
||||
17001_flightgear_tf-g1
|
||||
17002_flightgear_tf-g2
|
||||
|
||||
@@ -236,6 +236,7 @@ then
|
||||
qmc5883l -X -q start
|
||||
qmc5883p -X -q start
|
||||
rm3100 -X -q start
|
||||
bmm350 -X -q start
|
||||
|
||||
# start last (wait for possible icm20948 passthrough mode)
|
||||
ak09916 -X -q start
|
||||
|
||||
@@ -18,7 +18,6 @@ CONFIG_COMMON_INS=y
|
||||
CONFIG_COMMON_LIGHT=y
|
||||
CONFIG_COMMON_MAGNETOMETER=y
|
||||
CONFIG_DATAMAN_PERSISTENT_STORAGE=n
|
||||
CONFIG_DRIVERS_MAGNETOMETER_BOSCH_BMM350=y
|
||||
CONFIG_DRIVERS_PWM_OUT=y
|
||||
CONFIG_DRIVERS_RC_INPUT=y
|
||||
CONFIG_DRIVERS_ROBOCLAW=y
|
||||
|
||||
@@ -25,7 +25,6 @@ CONFIG_COMMON_INS=y
|
||||
CONFIG_COMMON_LIGHT=y
|
||||
CONFIG_DRIVERS_LIGHTS_RGBLED_PWM=y
|
||||
CONFIG_COMMON_MAGNETOMETER=y
|
||||
CONFIG_DRIVERS_MAGNETOMETER_BOSCH_BMM350=y
|
||||
CONFIG_COMMON_OPTICAL_FLOW=y
|
||||
CONFIG_COMMON_OSD=y
|
||||
CONFIG_DRIVERS_POWER_MONITOR_INA226=y
|
||||
|
||||
+1
-1
@@ -34,7 +34,6 @@
|
||||
- [Static Pressure Buildup](advanced_config/static_pressure_buildup.md)
|
||||
- [Flying (Basics)](flying/basic_flying_mc.md)
|
||||
- [Complete Vehicles](complete_vehicles_mc/index.md)
|
||||
- [ModalAI Starling](complete_vehicles_mc/modalai_starling.md)
|
||||
- [PX4 Vision Kit](complete_vehicles_mc/px4_vision_kit.md)
|
||||
- [MindRacer BNF & RTF](complete_vehicles_mc/mindracer_BNF_RTF.md)
|
||||
- [MindRacer 210](complete_vehicles_mc/mindracer210.md)
|
||||
@@ -42,6 +41,7 @@
|
||||
- [Bitcraze Crazyflie 2.1](complete_vehicles_mc/crazyflie21.md)
|
||||
- [Holybro Kopis 2](complete_vehicles_mc/holybro_kopis2.md)
|
||||
- [Amov F410 Drone](complete_vehicles_mc/amov_F410_drone.md)
|
||||
- [ModalAI Starling (Superseded)](complete_vehicles_mc/modalai_starling.md)
|
||||
- [Kits](frames_multicopter/kits.md)
|
||||
- [X500 v2 (Pixhawk 6C)](frames_multicopter/holybro_x500v2_pixhawk6c.md)
|
||||
- [X500 v2 (Pixhawk 5X)](frames_multicopter/holybro_x500V2_pixhawk5x.md)
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
# VOXL 2 Starling PX4 Development Drone
|
||||
# VOXL 2 Starling PX4 Development Drone (Discontinued/Superseded)
|
||||
|
||||
The [Starling](https://modalai.com/starling) is a SLAM development drone supercharged by [VOXL 2](../flight_controller/modalai_voxl_2.md) and PX4 with SWAP-optimized sensors and payloads optimized for indoor and outdoor autonomous navigation.
|
||||
::: info
|
||||
The Starling as been superseded by new frames (see [Starlings](https://www.modalai.com/pages/starlings) for more information).
|
||||
It is not clear whether these can be used in the same way.
|
||||
:::
|
||||
|
||||
The [Starling](https://www.modalai.com/pages/starlings) is a SLAM development drone supercharged by [VOXL 2](../flight_controller/modalai_voxl_2.md) and PX4 with SWAP-optimized sensors and payloads optimized for indoor and outdoor autonomous navigation.
|
||||
Powered by Blue UAS Framework autopilot, VOXL 2, the Starling weighs only 275g and boasts an impressive 30 minutes of autonomous indoor flight time.
|
||||
|
||||

|
||||
@@ -21,7 +26,7 @@ If you are new to VOXL, be sure to familiarize yourself with the core features o
|
||||
|
||||
## Where to Buy
|
||||
|
||||
[modalai.com/starling](https://modalai.com/starling)
|
||||
[modalai.com/starling](https://www.modalai.com/pages/starlings)
|
||||
|
||||
## Hardware Overview
|
||||
|
||||
|
||||
@@ -104,9 +104,9 @@ The debug port definition includes the following solder pads (on board next to c
|
||||
| 2 | GPIO1 | +3.3V |
|
||||
| 3 | GPIO2 | +3.3V |
|
||||
|
||||
The socket is a _6-pin JST SH_ - Digikey number: [BM06B-SRSS-TBT(LF)(SN)](https://www.digikey.com/products/en?keywords=455-2875-1-ND) (vertical mount), [SM06B-SRSS-TBT(LF)(SN)](https://www.digikey.com/products/en?keywords=455-1806-1-ND)(side mount).
|
||||
The socket is a _6-pin JST SH_ - Digikey number: [BM06B-SRSS-TBT(LF)(SN)](https://www.digikey.com/en/products/detail/jst-sales-america-inc/BM06B-SRSS-TBT/1785724) (vertical mount), [SM06B-SRSS-TBT(LF)(SN)](https://www.digikey.com/en/products/detail/jst-sales-america-inc/SM06B-SRSS-TB/926712) (side mount).
|
||||
|
||||
You can connect to the debug port using a [cable like this one](https://www.digikey.com/products/en?keywords=A06SR06SR30K152A).
|
||||
You can connect to the debug port using a [cable like this one](https://www.digikey.com/en/products/detail/jst-sales-america-inc/A06SR06SR30K152A/6009379).
|
||||
|
||||

|
||||
|
||||
@@ -134,7 +134,7 @@ The pinout is as shown below (pins required for debugging are bold):
|
||||
|
||||
The GPIO1/2 pins are free pins that can be used to generate signals in software for timing analysis with a logic analyzer.
|
||||
|
||||
The socket is a _10-pin JST SH_ - Digikey number: [BM10B-SRSS-TB(LF)(SN)](https://www.digikey.com/products/en?keywords=455-1796-2-ND) (vertical mount) or [SM10B-SRSS-TB(LF)(SN)](https://www.digikey.com/products/en?keywords=455-1810-2-ND) (side mount).
|
||||
The socket is a _10-pin JST SH_ - Digikey number: [BM10B-SRSS-TB(LF)(SN)](https://www.digikey.com/en/products/detail/jst-sales-america-inc/BM10B-SRSS-TB/926702) (vertical mount) or [SM10B-SRSS-TB(LF)(SN)](https://www.digikey.com/en/products/detail/jst-sales-america-inc/BM10B-SRSS-TB/926702) (side mount).
|
||||
|
||||
You can connect to the debug port using a [cable like this one](https://www.digikey.com/products/en?keywords=A10SR10SR30K203A).
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ The recommended process for developing a new frame configuration is:
|
||||
1. Configure the [geometry and actuator outputs](../config/actuators.md).
|
||||
1. Perform other [basic configuration](../config/index.md).
|
||||
1. Tune the vehicle.
|
||||
1. Run the [`param show-for-airframe`](../modules/modules_command.md#param) console command to list the parameter difference compared to the original generic airfame.
|
||||
1. Run the [`param show-for-airframe`](../modules/modules_command.md#param) console command to list the parameter difference compared to the original generic airframe.
|
||||
|
||||
Once you have the parameters you can create a new frame configuration file by copying the configuration file for the generic configuration, and appending the new parameters.
|
||||
|
||||
@@ -39,7 +39,7 @@ To add a frame configuration to firmware:
|
||||
1. Create a new config file in the [init.d/airframes](https://github.com/PX4/PX4-Autopilot/tree/main/ROMFS/px4fmu_common/init.d/airframes) folder.
|
||||
- Give it a short descriptive filename and prepend the filename with an unused autostart ID (for example, `1033092_superfast_vtol`).
|
||||
- Update the file with configuration parameters and apps (see section above).
|
||||
1. Add the name of the new frame config file to the [CMakeLists.txt](https://github.com/PX4/PX4-Autopilot/blob/main/ROMFS/px4fmu_common/init.d/airframes/CMakeLists.txt) in the relevant section for the type of vehicle
|
||||
1. Add the name of the new frame config file to the [CMakeLists.txt](https://github.com/PX4/PX4-Autopilot/blob/main/ROMFS/px4fmu_common/init.d/airframes/CMakeLists.txt) in the relevant section for the type of vehicle.
|
||||
1. [Build and upload](../dev_setup/building_px4.md) the software.
|
||||
|
||||
## How to add a Configuration to an SD Card
|
||||
@@ -65,6 +65,18 @@ These aspects are mostly independent, which means that many configurations share
|
||||
New frame configuration files are only automatically added to the build system after a clean build (run `make clean`).
|
||||
:::
|
||||
|
||||
## Force Reset of Airframe Parameters on Update
|
||||
|
||||
To force a reset to the airframe defaults for all users of a specific airframe during update, increase the `PARAM_DEFAULTS_VER` variable in the airframe configuration.
|
||||
It starts at `1` in [rcS](https://github.com/PX4/PX4-Autopilot/blob/main/ROMFS/px4fmu_common/init.d/rcS#L40).
|
||||
Add `set PARAM_DEFAULTS_VER 2` in your airframe file, increasing the value with each future reset needed.
|
||||
|
||||
This value is compared to [SYS_PARAM_VER](https://github.com/PX4/PX4-Autopilot/pull/advanced_config/parameter_reference.md#SYS_PARAM_VER) during PX4 updates.
|
||||
If different, user-customized parameters are reset to defaults.
|
||||
|
||||
Note that system parameters primarily include those related to the vehicle airframe configuration.
|
||||
Parameters such as accumulating flight hours, RC and sensor calibrations, are preserved.
|
||||
|
||||
### Example - Generic Quadcopter Frame Config
|
||||
|
||||
The configuration file for a generic Quad X copter is shown below ([original file here](https://github.com/PX4/PX4-Autopilot/blob/main/ROMFS/px4fmu_common/init.d/airframes/4001_quad_x)).
|
||||
|
||||
@@ -26,7 +26,6 @@ Omissions:
|
||||
|
||||
- Simulation: Gazebo and ROS are not supported.
|
||||
- Only NuttX and JMAVSim/SITL builds are supported.
|
||||
- [Known problems](https://github.com/orgs/PX4/projects/6) (Also use to report issues).
|
||||
|
||||
### Shell Script Installation
|
||||
|
||||
@@ -86,7 +85,7 @@ The toolchain gets maintained and hence these instructions might not cover every
|
||||
That's what [cygwin64/install-cygwin-px4.bat](https://github.com/PX4/PX4-windows-toolchain/blob/master/toolchain/cygwin64/install-cygwin-px4.bat) does.
|
||||
:::
|
||||
|
||||
1. Write up or copy the **batch scripts** [`run-console.bat`](https://github.com/MaEtUgR/PX4Toolchain/blob/master/run-console.bat) and [`setup-environment.bat`](https://github.com/PX4/PX4-windows-toolchain/blob/master/toolchain/scripts/setup-environment.bat).
|
||||
1. Write up or copy the **batch scripts** [`run-console.bat`](https://github.com/PX4/PX4-windows-toolchain/blob/master/run-console.bat) and [`setup-environment.bat`](https://github.com/PX4/PX4-windows-toolchain/blob/master/toolchain/scripts/setup-environment.bat).
|
||||
|
||||
The reason to start all the development tools through the prepared batch script is they preconfigure the starting program to use the local, portable Cygwin environment inside the toolchain's folder.
|
||||
This is done by always first calling the script [**setup-environment.bat**](https://github.com/PX4/PX4-windows-toolchain/blob/master/toolchain/scripts/setup-environment.bat) and the desired application like the console after that.
|
||||
@@ -102,17 +101,17 @@ The toolchain gets maintained and hence these instructions might not cover every
|
||||
```
|
||||
|
||||
::: info
|
||||
That's what [cygwin64/install-cygwin-python-packages.bat](https://github.com/MaEtUgR/PX4Toolchain/blob/master/toolchain/cygwin64/install-cygwin-python-packages.bat) does.
|
||||
That's what [cygwin64/install-cygwin-python-packages.bat](https://github.com/PX4/PX4-windows-toolchain/blob/master/toolchain/cygwin64/install-cygwin-python-packages.bat) does.
|
||||
:::
|
||||
|
||||
1. Download the [**ARM GCC compiler**](https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads) as zip archive of the binaries for Windows and unpack the content to the folder `C:\PX4\toolchain\gcc-arm`.
|
||||
1. Download the [**ARM GCC compiler**](https://developer.arm.com/Tools%20and%20Software/GNU%20Toolchain) as zip archive of the binaries for Windows and unpack the content to the folder `C:\PX4\toolchain\gcc-arm`.
|
||||
|
||||
::: info
|
||||
This is what the toolchain does in: [gcc-arm/install-gcc-arm.bat](https://github.com/PX4/PX4-windows-toolchain/blob/master/toolchain/gcc-arm/install-gcc-arm.bat).
|
||||
:::
|
||||
|
||||
1. Install the JDK:
|
||||
- Download Java 14 from [Oracle](https://www.oracle.com/java/technologies/downloads/) or [AdoptOpenJDK](https://adoptopenjdk.net/).
|
||||
- Download Java 14 from [Oracle](https://www.oracle.com/java/technologies/downloads/)
|
||||
- Because sadly there is no portable archive containing the binaries directly you have to install it.
|
||||
- Find the binaries and move/copy them to **C:\PX4\toolchain\jdk**.
|
||||
- You can uninstall the Kit from your Windows system again, we only needed the binaries for the toolchain.
|
||||
|
||||
@@ -26,40 +26,61 @@ Vehicles are [hand or catapult launched](#catapult-hand-launch) by default, but
|
||||
Takeoff mode (and [fixed wing mission takeoff](../flight_modes_fw/mission.md#mission-takeoff)) has two modalities: [catapult/hand-launch](#catapult-hand-launch) or [runway takeoff](#runway-takeoff) (hardware-dependent).
|
||||
The mode defaults to catapult/hand launch, but can be set to runway takeoff by setting [RWTO_TKOFF](#RWTO_TKOFF) to 1.
|
||||
|
||||
To use _Takeoff mode_ you first switch to the mode, and then arm the vehicle.
|
||||
To use _Takeoff mode_ you first switch to the mode, and then arm the vehicle (or send the [MAV_CMD_NAV_TAKEOFF](https://mavlink.io/en/messages/common.html#MAV_CMD_NAV_TAKEOFF) command which does both).
|
||||
The acceleration of hand/catapult launch triggers the motors to start.
|
||||
For runway launch, motors ramp up automatically once the vehicle has been armed.
|
||||
|
||||
Irrespective of the modality, a flight path (starting point and takeoff course) and clearance altitude are defined:
|
||||
|
||||
- The starting point is the vehicle position when the takeoff mode is first entered.
|
||||
- The course is set to the vehicle heading on arming
|
||||
- The clearance altitude is set to [MIS_TAKEOFF_ALT](#MIS_TAKEOFF_ALT).
|
||||
- The course is set to the vehicle heading on arming by default.
|
||||
If a valid waypoint latitude/longitude is set the vehicle will instead track towards the waypoint.
|
||||
- The clearance altitude is set to [MIS_TAKEOFF_ALT](#MIS_TAKEOFF_ALT) by default.
|
||||
If a valid waypoint altitude is set is set the vehicle will instead use it as the clearance altitude.
|
||||
|
||||
On takeoff, the aircraft will follow line defined by the starting point and course, climbing at the maximum climb rate ([FW_T_CLMB_MAX](../advanced_config/parameter_reference.md#FW_T_CLMB_MAX)) until reaching the clearance altitude.
|
||||
By default, on takeoff the aircraft will follow the line defined by the starting point and course, climbing at the maximum climb rate ([FW_T_CLMB_MAX](../advanced_config/parameter_reference.md#FW_T_CLMB_MAX)) until reaching the clearance altitude.
|
||||
Reaching the clearance altitude causes the vehicle to enter [Hold mode](../flight_modes_fw/takeoff.md).
|
||||
Special case for invalid local position: In case the local position is invalid or becomes invalid while executing the takeoff, the controller is not able to track a course setpoint and will instead proceed climbing while keeping the wings level until the clearance altitude is reached.
|
||||
|
||||
If a valid waypoint target is set, using `MAV_CMD_NAV_TAKEOFF` or the [VehicleCommand](../msg_docs/VehicleCommand.md) uORB topic, the vehicle will instead track towards the waypoint, and enter [Hold mode](../flight_modes_fw/takeoff.md) after reaching the waypoint altitude (within the acceptance radius).
|
||||
|
||||
::: tip
|
||||
If the local position is invalid or becomes invalid while executing the takeoff, the controller is not able to track a course setpoint and will instead proceed climbing while keeping the wings level until the clearance altitude is reached.
|
||||
:::
|
||||
|
||||
::: info
|
||||
|
||||
- Takeoff towards a target position was added in <Badge type="tip" text="main (planned for: PX4 v1.17)" />.
|
||||
- Holding wings level and ascending to clearance attitude when local position is invalid during takeoff was added in <Badge type="tip" text="main (planned for: PX4 v1.17)" />.
|
||||
- QGroundControl does not support `MAV_CMD_NAV_TAKEOFF` (at time of writing).
|
||||
|
||||
:::
|
||||
|
||||
### Parameters
|
||||
|
||||
Parameters that affect both catapult/hand-launch and runway takeoffs:
|
||||
|
||||
| Parameter | Description |
|
||||
| ----------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| <a id="MIS_TAKEOFF_ALT"></a>[MIS_TAKEOFF_ALT](../advanced_config/parameter_reference.md#MIS_TAKEOFF_ALT) | Minimum altitude setpoint above Home that the vehicle will climb to during takeoff. |
|
||||
| <a id="FW_TKO_AIRSPD"></a>[FW_TKO_AIRSPD](../advanced_config/parameter_reference.md#FW_TKO_AIRSPD) | Takeoff airspeed (is set to [FW_AIRSPD_MIN](../advanced_config/parameter_reference.md#FW_AIRSPD_MIN) if not defined by operator) |
|
||||
| <a id="FW_TKO_PITCH_MIN"></a>[FW_TKO_PITCH_MIN](../advanced_config/parameter_reference.md#FW_TKO_PITCH_MIN) | This is the minimum pitch angle setpoint during the climbout phase |
|
||||
| <a id="FW_T_CLMB_MAX"></a>[FW_T_CLMB_MAX](../advanced_config/parameter_reference.md#FW_T_CLMB_MAX) | Climb rate setpoint during climbout to takeoff altitude. |
|
||||
| <a id="FW_FLAPS_TO_SCL"></a>[FW_FLAPS_TO_SCL](../advanced_config/parameter_reference.md#FW_FLAPS_TO_SCL) | Flaps setpoint during takeoff |
|
||||
| <a id="FW_AIRSPD_FLP_SC"></a>[FW_AIRSPD_FLP_SC](../advanced_config/parameter_reference.md#FW_AIRSPD_FLP_SC) | Factor applied to the minimum airspeed when flaps are fully deployed. Necessary if FW_TKO_AIRSPD is below FW_AIRSPD_MIN. |
|
||||
| Parameter | Description |
|
||||
| ----------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| <a id="MIS_TAKEOFF_ALT"></a>[MIS_TAKEOFF_ALT][MIS_TAKEOFF_ALT] | This is the relative altitude (above launch altitude) the system will take off to if not otherwise specified. takeoff. |
|
||||
| <a id="FW_TKO_AIRSPD"></a>[FW_TKO_AIRSPD][FW_TKO_AIRSPD] | Takeoff airspeed (is set to [FW_AIRSPD_MIN][FW_AIRSPD_MIN] if not defined by operator) |
|
||||
| <a id="FW_TKO_PITCH_MIN"></a>[FW_TKO_PITCH_MIN][FW_TKO_PITCH_MIN] | This is the minimum pitch angle setpoint during the climbout phase |
|
||||
| <a id="FW_T_CLMB_MAX"></a>[FW_T_CLMB_MAX][FW_T_CLMB_MAX] | Climb rate setpoint during climbout to takeoff altitude. |
|
||||
| <a id="FW_FLAPS_TO_SCL"></a>[FW_FLAPS_TO_SCL][FW_FLAPS_TO_SCL] | Flaps setpoint during takeoff |
|
||||
| <a id="FW_AIRSPD_FLP_SC"></a>[FW_AIRSPD_FLP_SC][FW_AIRSPD_FLP_SC] | Factor applied to the minimum airspeed when flaps are fully deployed. Needed if [FW_TKO_AIRSPD](#FW_TKO_AIRSPD) is below [FW_AIRSPD_MIN][FW_AIRSPD_MIN]. |
|
||||
|
||||
[FW_AIRSPD_MIN]: ../advanced_config/parameter_reference.md#FW_AIRSPD_MIN
|
||||
[FW_FLAPS_TO_SCL]: ../advanced_config/parameter_reference.md#FW_FLAPS_TO_SCL
|
||||
[FW_AIRSPD_FLP_SC]: ../advanced_config/parameter_reference.md#FW_AIRSPD_FLP_SC
|
||||
[FW_TKO_AIRSPD]: ../advanced_config/parameter_reference.md#FW_TKO_AIRSPD
|
||||
[MIS_TAKEOFF_ALT]: ../advanced_config/parameter_reference.md#MIS_TAKEOFF_ALT
|
||||
[FW_TKO_PITCH_MIN]: ../advanced_config/parameter_reference.md#FW_TKO_PITCH_MIN
|
||||
[FW_T_CLMB_MAX]: ../advanced_config/parameter_reference.md#FW_T_CLMB_MAX
|
||||
|
||||
::: info
|
||||
The vehicle always respects normal FW max/min throttle settings during takeoff ([FW_THR_MIN](../advanced_config/parameter_reference.md#FW_THR_MIN), [FW_THR_MAX](../advanced_config/parameter_reference.md#FW_THR_MAX)).
|
||||
:::
|
||||
|
||||
<a id="hand_launch"></a>
|
||||
|
||||
## Catapult/Hand Launch
|
||||
## Catapult/Hand Launch {#hand_launch}
|
||||
|
||||
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).
|
||||
@@ -85,9 +106,7 @@ The _launch detector_ is affected by the following parameters:
|
||||
| <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="runway_launch"></a>
|
||||
|
||||
## Runway Takeoff
|
||||
## Runway Takeoff {#runway_launch}
|
||||
|
||||
Runway takeoffs can be used by vehicles with landing gear and and steerable wheel (only).
|
||||
You will first need to enable the wheel controller using the parameter [FW_W_EN](#FW_W_EN).
|
||||
@@ -110,18 +129,18 @@ It consists of a rate controller (P-I-FF-controller with the parameters [FW_WR_P
|
||||
|
||||
Runway takeoff is affected by the following parameters:
|
||||
|
||||
| Parameter | Description |
|
||||
| ----------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
|
||||
| <a id="RWTO_TKOFF"></a>[RWTO_TKOFF](../advanced_config/parameter_reference.md#RWTO_TKOFF) | Enable runway takeoff |
|
||||
| <a id="FW_W_EN"></a>[FW_W_EN](../advanced_config/parameter_reference.md#FW_W_EN) | Enable wheel controller |
|
||||
| <a id="RWTO_MAX_THR"></a>[RWTO_MAX_THR](../advanced_config/parameter_reference.md#RWTO_MAX_THR) | Max throttle during runway takeoff |
|
||||
| <a id="RWTO_RAMP_TIME"></a>[RWTO_RAMP_TIME](../advanced_config/parameter_reference.md#RWTO_RAMP_TIME) | Throttle ramp up time |
|
||||
| <a id="RWTO_ROT_AIRSPD"></a>[RWTO_ROT_AIRSPD](../advanced_config/parameter_reference.md#RWTO_ROT_AIRSPD) | Airspeed threshold to start rotation (pitching up). If not configured by operator is set to 0.9\*FW_TKO_AIRSPD. |
|
||||
| <a id="RWTO_ROT_TIME"></a>[RWTO_ROT_TIME](../advanced_config/parameter_reference.md#RWTO_ROT_TIME) | This is the time desired to linearly ramp in takeoff pitch constraints during the takeoff rotation. |
|
||||
| <a id="FW_TKO_AIRSPD"></a>[FW_TKO_AIRSPD](../advanced_config/parameter_reference.md#FW_TKO_AIRSPD) | Airspeed setpoint during the takeoff climbout phase (after rotation). If not configured by operator is set to FW_AIRSPD_MIN. |
|
||||
| <a id="RWTO_NUDGE"></a>[RWTO_NUDGE](../advanced_config/parameter_reference.md#RWTO_NUDGE) | Enable wheel controller nudging while on the runway |
|
||||
| <a id="FW_WING_SPAN"></a>[FW_WING_SPAN](../advanced_config/parameter_reference.md#FW_WING_SPAN) | The wingspan of the vehicle. Used to prevent wingstrikes. |
|
||||
| <a id="FW_WING_HEIGHT"></a>[FW_WING_HEIGHT](../advanced_config/parameter_reference.md#FW_WING_HEIGHT) | The height of the wings above ground (ground clearance). Used to prevent wingstrikes. |
|
||||
| Parameter | Description |
|
||||
| -------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
|
||||
| <a id="RWTO_TKOFF"></a>[RWTO_TKOFF](../advanced_config/parameter_reference.md#RWTO_TKOFF) | Enable runway takeoff |
|
||||
| <a id="FW_W_EN"></a>[FW_W_EN](../advanced_config/parameter_reference.md#FW_W_EN) | Enable wheel controller |
|
||||
| <a id="RWTO_MAX_THR"></a>[RWTO_MAX_THR](../advanced_config/parameter_reference.md#RWTO_MAX_THR) | Max throttle during runway takeoff |
|
||||
| <a id="RWTO_RAMP_TIME"></a>[RWTO_RAMP_TIME](../advanced_config/parameter_reference.md#RWTO_RAMP_TIME) | Throttle ramp up time |
|
||||
| <a id="RWTO_ROT_AIRSPD"></a>[RWTO_ROT_AIRSPD](../advanced_config/parameter_reference.md#RWTO_ROT_AIRSPD) | Airspeed threshold to start rotation (pitching up). If not configured by operator is set to 0.9\*FW_TKO_AIRSPD. |
|
||||
| <a id="RWTO_ROT_TIME"></a>[RWTO_ROT_TIME](../advanced_config/parameter_reference.md#RWTO_ROT_TIME) | This is the time desired to linearly ramp in takeoff pitch constraints during the takeoff rotation. |
|
||||
| <a id="FW_TKO_AIRSPD"></a>[FW_TKO_AIRSPD](../advanced_config/parameter_reference.md#FW_TKO_AIRSPD) | Airspeed setpoint during the takeoff climbout phase (after rotation). If not configured by operator is set to FW_AIRSPD_MIN. |
|
||||
| <a id="RWTO_NUDGE"></a>[RWTO_NUDGE](../advanced_config/parameter_reference.md#RWTO_NUDGE) | Enable wheel controller nudging while on the runway |
|
||||
| <a id="FW_WING_SPAN"></a>[FW_WING_SPAN](../advanced_config/parameter_reference.md#FW_WING_SPAN) | The wingspan of the vehicle. Used to prevent wingstrikes. |
|
||||
| <a id="FW_WING_HEIGHT"></a>[FW_WING_HEIGHT](../advanced_config/parameter_reference.md#FW_WING_HEIGHT) | The height of the wings above ground (ground clearance). Used to prevent wingstrikes. |
|
||||
|
||||
## See Also
|
||||
|
||||
|
||||
@@ -38,13 +38,16 @@ RC control cannot be used to start the mode (if you switch to the mode via RC it
|
||||
RC control can be used to change the orbit altitude, radius, speed, and orbit direction:
|
||||
|
||||
- **Left stick:**
|
||||
- _up/down:_ controls speed of ascent/descent, as in [Position mode](../flight_modes_mc/position.md). When in center deadzone, altitude is locked.
|
||||
- _up/down:_ controls speed of ascent/descent, as in [Position mode](../flight_modes_mc/position.md).
|
||||
When in center deadzone, altitude is locked.
|
||||
- _left/right:_ no effect.
|
||||
- **Right stick:**
|
||||
- _left/right:_ controls acceleration of orbit in clockwise/counter-clockwise directions. When centered the current speed is locked.
|
||||
- Maximum velocity is 10m/s and further limited to keep the centripetal acceleration below 2m/s^2.
|
||||
- _left/right:_ controls acceleration of orbit in clockwise/counter-clockwise directions.
|
||||
When centered the current speed is locked.
|
||||
- Maximum velocity is [MPC_XY_VEL_MAX](#MPC_XY_VEL_MAX) and further limited to keep the centripetal acceleration below 2m/s^2.
|
||||
- _up/down:_ controls orbit radius (smaller/bigger). When centered the current radius is locked.
|
||||
- Minimum radius is 1m. Maximum radius is 100m.
|
||||
- Minimum radius is 1m.
|
||||
Maximum radius is [MC_ORBIT_RAD_MAX](#MC_ORBIT_RAD_MAX).
|
||||
|
||||
The diagram below shows the mode behaviour visually (for a [mode 2 transmitter](../getting_started/rc_transmitter_receiver.md#transmitter_modes)).
|
||||
|
||||
@@ -56,19 +59,22 @@ The mode can be stopped by switching to any other flight mode (using RC or QGC).
|
||||
|
||||
The mode is affected by the following parameters:
|
||||
|
||||
| Parameter | Description |
|
||||
| ----------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- |
|
||||
| <a id="MC_ORBIT_RAD_MAX"></a>[MC_ORBIT_RAD_MAX](../advanced_config/parameter_reference.md#MC_ORBIT_RAD_MAX) | Maximum radius of orbit. Default: 1000m. |
|
||||
| <a id="MC_ORBIT_YAW_MOD"></a>[MC_ORBIT_YAW_MOD](../advanced_config/parameter_reference.md#MC_ORBIT_YAW_MOD) | Yaw behaviour during orbit flight. Default: Front to Circle Center. |
|
||||
| Parameter | Description |
|
||||
| ----------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
|
||||
| <a id="MC_ORBIT_RAD_MAX"></a>[MC_ORBIT_RAD_MAX](../advanced_config/parameter_reference.md#MC_ORBIT_RAD_MAX) | Maximum radius of orbit. Default: 1000m. |
|
||||
| <a id="MC_ORBIT_YAW_MOD"></a>[MC_ORBIT_YAW_MOD](../advanced_config/parameter_reference.md#MC_ORBIT_YAW_MOD) | Yaw behaviour during orbit flight. Default: Front to Circle Center. |
|
||||
| <a id="MPC_XY_VEL_MAX"></a>[MPC_XY_VEL_MAX](../advanced_config/parameter_reference.md#MPC_XY_VEL_MAX) | Tangential speed limit. Stick input won't accelerate beyond this limit. Higher commands are accepted but capped. |
|
||||
|
||||
The following limits are hard coded:
|
||||
|
||||
- Initial/default rotation is 1 m/s in a clockwise direction.
|
||||
- The maximum acceleration is limited to 2 m/s^2, with priority on keeping the commanded circle trajectory rather than commanded ground speed (i.e. the vehicle will slow down in order to achieve the correct circle if the acceleration exceeds 2m/s^2).
|
||||
- Initial/default rotation is 1m/s in a clockwise direction.
|
||||
- The maximum acceleration is limited to 2m/s^2, with priority on keeping the commanded circle trajectory rather than commanded ground speed (i.e. the vehicle will slow down in order to achieve the correct circle if the acceleration exceeds 2m/s^2).
|
||||
|
||||
## MAVLink Messages (Developers)
|
||||
|
||||
Orbit mode uses the following MAVLink commands:
|
||||
|
||||
- [MAV_CMD_DO_ORBIT](https://mavlink.io/en/messages/common.html#MAV_CMD_DO_ORBIT) - Start an orbit with specified center point, radius, direction, altitude, speed and [yaw direction](https://mavlink.io/en/messages/common.html#ORBIT_YAW_BEHAVIOUR) (vehicle defaults to faceing centre of orbit).
|
||||
- [MAV_CMD_DO_ORBIT](https://mavlink.io/en/messages/common.html#MAV_CMD_DO_ORBIT) - Start an orbit with specified center point, radius, direction, altitude, speed and [yaw direction](https://mavlink.io/en/messages/common.html#ORBIT_YAW_BEHAVIOUR).
|
||||
The same defaults and limits apply.
|
||||
When exceeding limits the command is accepted but velocity and radius capped.
|
||||
- [ORBIT_EXECUTION_STATUS](https://mavlink.io/en/messages/common.html#ORBIT_EXECUTION_STATUS) - Orbit status emitted during orbit to update GCS of current orbit parameters (these may be changed by the RC controller).
|
||||
|
||||
@@ -80,7 +80,8 @@ Please continue reading for [upgrade instructions](#upgrade-guide).
|
||||
|
||||
### Fixed-wing
|
||||
|
||||
- TBD
|
||||
- [Fixed Wing Takeoff mode](../flight_modes_fw/takeoff.md) will now keep climbing with level wings on position loss.
|
||||
A target takeoff waypoint can be set to control takeoff course and loiter altitude. ([PX4-Autopilot#25083](https://github.com/PX4/PX4-Autopilot/pull/25083)).
|
||||
|
||||
### Rover
|
||||
|
||||
|
||||
@@ -12,8 +12,6 @@ float32 x # X coordinate in meters
|
||||
float32 y # Y coordinate in meters
|
||||
float32 z # Z coordinate in meters
|
||||
|
||||
float32 roll # Pitch angle in radians
|
||||
float32 pitch # Roll angle in radians
|
||||
float32 yaw # Yaw angle in radians
|
||||
|
||||
bool valid_alt # true when the altitude has been set
|
||||
|
||||
@@ -5,6 +5,7 @@ menu "Magnetometer"
|
||||
select DRIVERS_MAGNETOMETER_AKM_AK8963
|
||||
select DRIVERS_MAGNETOMETER_AKM_AK09916
|
||||
select DRIVERS_MAGNETOMETER_BOSCH_BMM150
|
||||
select DRIVERS_MAGNETOMETER_BOSCH_BMM350
|
||||
select DRIVERS_MAGNETOMETER_HMC5883
|
||||
select DRIVERS_MAGNETOMETER_QMC5883L
|
||||
select DRIVERS_MAGNETOMETER_QMC5883P
|
||||
|
||||
@@ -999,10 +999,6 @@ Commander::handle_command(const vehicle_command_s &cmd)
|
||||
}
|
||||
|
||||
} else {
|
||||
float roll = matrix::wrap_2pi(math::radians(cmd.param2));
|
||||
roll = PX4_ISFINITE(roll) ? roll : 0.0f;
|
||||
float pitch = matrix::wrap_2pi(math::radians(cmd.param3));
|
||||
pitch = PX4_ISFINITE(pitch) ? pitch : 0.0f;
|
||||
float yaw = matrix::wrap_2pi(math::radians(cmd.param4));
|
||||
yaw = PX4_ISFINITE(yaw) ? yaw : (float)NAN;
|
||||
const double lat = cmd.param5;
|
||||
@@ -1011,7 +1007,7 @@ Commander::handle_command(const vehicle_command_s &cmd)
|
||||
|
||||
if (PX4_ISFINITE(lat) && PX4_ISFINITE(lon) && PX4_ISFINITE(alt)) {
|
||||
|
||||
if (_home_position.setManually(lat, lon, alt, roll, pitch, yaw)) {
|
||||
if (_home_position.setManually(lat, lon, alt, yaw)) {
|
||||
|
||||
cmd_result = vehicle_command_ack_s::VEHICLE_CMD_RESULT_ACCEPTED;
|
||||
|
||||
@@ -2347,6 +2343,7 @@ bool Commander::handleModeIntentionAndFailsafe()
|
||||
}
|
||||
|
||||
// Handle failsafe action
|
||||
_mode_management.setFailsafeState(_failsafe.selectedAction() > FailsafeBase::Action::Warn);
|
||||
_vehicle_status.nav_state_user_intention = _mode_management.getNavStateReplacementIfValid(_user_mode_intention.get(),
|
||||
false);
|
||||
_vehicle_status.nav_state = _mode_management.getNavStateReplacementIfValid(FailsafeBase::modeFromAction(
|
||||
@@ -2414,7 +2411,7 @@ void Commander::modeManagementUpdate()
|
||||
{
|
||||
ModeManagement::UpdateRequest mode_management_update{};
|
||||
_mode_management.update(isArmed(), _vehicle_status.nav_state_user_intention,
|
||||
_failsafe.selectedAction() > FailsafeBase::Action::Warn, mode_management_update);
|
||||
mode_management_update);
|
||||
|
||||
if (!isArmed() && mode_management_update.change_user_intended_nav_state) {
|
||||
_user_mode_intention.change(mode_management_update.user_intended_nav_state);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2022-2025 PX4 Development Team. All rights reserved.
|
||||
* Copyright (c) 2022-2023 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -99,9 +99,7 @@ bool HomePosition::setHomePosition(bool force)
|
||||
const vehicle_local_position_s &lpos = _local_position_sub.get();
|
||||
_heading_reset_counter = lpos.heading_reset_counter; // TODO: should not be here
|
||||
|
||||
const vehicle_attitude_s &attitude = _attitude_sub.get();
|
||||
|
||||
fillLocalHomePos(home, lpos, attitude);
|
||||
fillLocalHomePos(home, lpos);
|
||||
updated = true;
|
||||
}
|
||||
|
||||
@@ -137,25 +135,19 @@ bool HomePosition::setHomePosition(bool force)
|
||||
return updated;
|
||||
}
|
||||
|
||||
void HomePosition::fillLocalHomePos(home_position_s &home, const vehicle_local_position_s &lpos,
|
||||
const vehicle_attitude_s &attitude)
|
||||
void HomePosition::fillLocalHomePos(home_position_s &home, const vehicle_local_position_s &lpos)
|
||||
{
|
||||
matrix::Quatf q(attitude.q);
|
||||
matrix::Eulerf euler(q);
|
||||
fillLocalHomePos(home, lpos.x, lpos.y, lpos.z, euler(0), euler(1), euler(2));
|
||||
fillLocalHomePos(home, lpos.x, lpos.y, lpos.z, lpos.heading);
|
||||
}
|
||||
|
||||
void HomePosition::fillLocalHomePos(home_position_s &home, float x, float y, float z, float roll, float pitch,
|
||||
float yaw)
|
||||
void HomePosition::fillLocalHomePos(home_position_s &home, float x, float y, float z, float heading)
|
||||
{
|
||||
home.x = x;
|
||||
home.y = y;
|
||||
home.z = z;
|
||||
home.valid_lpos = true;
|
||||
|
||||
home.roll = roll;
|
||||
home.pitch = pitch;
|
||||
home.yaw = yaw;
|
||||
home.yaw = heading;
|
||||
}
|
||||
|
||||
void HomePosition::fillGlobalHomePos(home_position_s &home, const vehicle_global_position_s &gpos)
|
||||
@@ -237,7 +229,7 @@ void HomePosition::setInAirHomePosition()
|
||||
ref_pos.project(home.lat, home.lon, home_x, home_y);
|
||||
|
||||
const float home_z = -(home.alt - lpos.ref_alt);
|
||||
fillLocalHomePos(home, home_x, home_y, home_z, NAN, NAN, NAN);
|
||||
fillLocalHomePos(home, home_x, home_y, home_z, NAN);
|
||||
|
||||
home.timestamp = hrt_absolute_time();
|
||||
home.update_count++;
|
||||
@@ -253,7 +245,7 @@ void HomePosition::setInAirHomePosition()
|
||||
}
|
||||
}
|
||||
|
||||
bool HomePosition::setManually(double lat, double lon, float alt, float roll, float pitch, float yaw)
|
||||
bool HomePosition::setManually(double lat, double lon, float alt, float yaw)
|
||||
{
|
||||
const vehicle_local_position_s &vehicle_local_position = _local_position_sub.get();
|
||||
|
||||
@@ -276,8 +268,6 @@ bool HomePosition::setManually(double lat, double lon, float alt, float roll, fl
|
||||
home.z = -(alt - vehicle_local_position.ref_alt);
|
||||
home.valid_lpos = vehicle_local_position.xy_valid && vehicle_local_position.z_valid;
|
||||
|
||||
home.roll = roll;
|
||||
home.pitch = pitch;
|
||||
home.yaw = yaw;
|
||||
|
||||
home.timestamp = hrt_absolute_time();
|
||||
@@ -313,7 +303,6 @@ void HomePosition::update(bool set_automatically, bool check_if_changed)
|
||||
{
|
||||
_local_position_sub.update();
|
||||
_global_position_sub.update();
|
||||
_attitude_sub.update();
|
||||
|
||||
if (_vehicle_air_data_sub.updated()) {
|
||||
vehicle_air_data_s baro_data;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2022-2025 PX4 Development Team. All rights reserved.
|
||||
* Copyright (c) 2022-2023 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -39,7 +39,6 @@
|
||||
#include <uORB/topics/sensor_gps.h>
|
||||
#include <uORB/topics/vehicle_global_position.h>
|
||||
#include <uORB/topics/vehicle_local_position.h>
|
||||
#include <uORB/topics/vehicle_attitude.h>
|
||||
#include <uORB/topics/failsafe_flags.h>
|
||||
#include <uORB/topics/vehicle_air_data.h>
|
||||
#include <lib/mathlib/math/filter/AlphaFilter.hpp>
|
||||
@@ -65,7 +64,7 @@ public:
|
||||
|
||||
bool setHomePosition(bool force = false);
|
||||
void setInAirHomePosition();
|
||||
bool setManually(double lat, double lon, float alt, float roll, float pitch, float yaw);
|
||||
bool setManually(double lat, double lon, float alt, float yaw);
|
||||
void setTakeoffTime(uint64_t takeoff_time) { _takeoff_time = takeoff_time; }
|
||||
|
||||
void update(bool set_automatically, bool check_if_changed);
|
||||
@@ -77,9 +76,8 @@ private:
|
||||
void setHomePosValid();
|
||||
void updateHomePositionYaw(float yaw);
|
||||
|
||||
static void fillLocalHomePos(home_position_s &home, const vehicle_local_position_s &lpos,
|
||||
const vehicle_attitude_s &attitude);
|
||||
static void fillLocalHomePos(home_position_s &home, float x, float y, float z, float roll, float pitch, float yaw);
|
||||
static void fillLocalHomePos(home_position_s &home, const vehicle_local_position_s &lpos);
|
||||
static void fillLocalHomePos(home_position_s &home, float x, float y, float z, float heading);
|
||||
static void fillGlobalHomePos(home_position_s &home, const vehicle_global_position_s &gpos);
|
||||
static void fillGlobalHomePos(home_position_s &home, double lat, double lon, double alt);
|
||||
|
||||
@@ -87,7 +85,6 @@ private:
|
||||
|
||||
uORB::SubscriptionData<vehicle_global_position_s> _global_position_sub{ORB_ID(vehicle_global_position)};
|
||||
uORB::SubscriptionData<vehicle_local_position_s> _local_position_sub{ORB_ID(vehicle_local_position)};
|
||||
uORB::SubscriptionData<vehicle_attitude_s> _attitude_sub{ORB_ID(vehicle_attitude)};
|
||||
uORB::Subscription _vehicle_air_data_sub{ORB_ID(vehicle_air_data)};
|
||||
|
||||
uint64_t _last_gps_timestamp{0};
|
||||
|
||||
@@ -364,10 +364,8 @@ void ModeManagement::checkUnregistrations(uint8_t user_intended_nav_state, Updat
|
||||
}
|
||||
}
|
||||
|
||||
void ModeManagement::update(bool armed, uint8_t user_intended_nav_state, bool failsafe_action_active,
|
||||
UpdateRequest &update_request)
|
||||
void ModeManagement::update(bool armed, uint8_t user_intended_nav_state, UpdateRequest &update_request)
|
||||
{
|
||||
_failsafe_action_active = failsafe_action_active;
|
||||
_external_checks.update();
|
||||
|
||||
bool allow_update_while_armed = _external_checks.allowUpdateWhileArmed();
|
||||
|
||||
@@ -138,7 +138,11 @@ public:
|
||||
bool control_setpoint_update{false};
|
||||
};
|
||||
|
||||
void update(bool armed, uint8_t user_intended_nav_state, bool failsafe_action_active, UpdateRequest &update_request);
|
||||
void update(bool armed, uint8_t user_intended_nav_state, UpdateRequest &update_request);
|
||||
void setFailsafeState(bool failsafe_action_active)
|
||||
{
|
||||
_failsafe_action_active = failsafe_action_active;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mode executor ID for who is currently in charge (and can send commands etc).
|
||||
@@ -198,7 +202,8 @@ public:
|
||||
bool control_setpoint_update{false};
|
||||
};
|
||||
|
||||
void update(bool armed, uint8_t user_intended_nav_state, bool failsafe_action_active, UpdateRequest &update_request) {}
|
||||
void update(bool armed, uint8_t user_intended_nav_state, UpdateRequest &update_request) {}
|
||||
void setFailsafeState(bool failsafe_action_active) {}
|
||||
|
||||
int modeExecutorInCharge() const { return ModeExecutors::AUTOPILOT_EXECUTOR_ID; }
|
||||
|
||||
|
||||
@@ -618,13 +618,15 @@ PARAM_DEFINE_INT32(NAV_RCL_ACT, 2);
|
||||
/**
|
||||
* RC loss exceptions
|
||||
*
|
||||
* Specify modes in which RC loss is ignored and the failsafe action not triggered.
|
||||
* Specify modes where manual control loss is ignored and no failsafe is triggered.
|
||||
* External modes requiring stick input will still failsafe.
|
||||
*
|
||||
* @min 0
|
||||
* @max 7
|
||||
* @max 15
|
||||
* @bit 0 Mission
|
||||
* @bit 1 Hold
|
||||
* @bit 2 Offboard
|
||||
* @bit 3 External Mode
|
||||
* @group Commander
|
||||
*/
|
||||
PARAM_DEFINE_INT32(COM_RCL_EXCEPT, 0);
|
||||
|
||||
@@ -472,8 +472,19 @@ void Failsafe::checkStateAndMode(const hrt_abstime &time_us, const State &state,
|
||||
state.user_intended_mode == vehicle_status_s::NAVIGATION_STATE_AUTO_VTOL_TAKEOFF)
|
||||
&& (_param_com_rcl_except.get() & (int)ManualControlLossExceptionBits::Hold);
|
||||
|
||||
const bool rc_loss_ignored_external_mode =
|
||||
(state.user_intended_mode == vehicle_status_s::NAVIGATION_STATE_EXTERNAL1 ||
|
||||
state.user_intended_mode == vehicle_status_s::NAVIGATION_STATE_EXTERNAL2 ||
|
||||
state.user_intended_mode == vehicle_status_s::NAVIGATION_STATE_EXTERNAL3 ||
|
||||
state.user_intended_mode == vehicle_status_s::NAVIGATION_STATE_EXTERNAL4 ||
|
||||
state.user_intended_mode == vehicle_status_s::NAVIGATION_STATE_EXTERNAL5 ||
|
||||
state.user_intended_mode == vehicle_status_s::NAVIGATION_STATE_EXTERNAL6 ||
|
||||
state.user_intended_mode == vehicle_status_s::NAVIGATION_STATE_EXTERNAL7 ||
|
||||
state.user_intended_mode == vehicle_status_s::NAVIGATION_STATE_EXTERNAL8)
|
||||
&& (_param_com_rcl_except.get() & (int)ManualControlLossExceptionBits::ExternalMode);
|
||||
|
||||
const bool rc_loss_ignored = rc_loss_ignored_mission || rc_loss_ignored_loiter || rc_loss_ignored_offboard ||
|
||||
rc_loss_ignored_takeoff || ignore_any_link_loss_vtol_takeoff_fixedwing
|
||||
rc_loss_ignored_takeoff || rc_loss_ignored_external_mode || ignore_any_link_loss_vtol_takeoff_fixedwing
|
||||
|| _manual_control_lost_at_arming;
|
||||
|
||||
if (_param_com_rc_in_mode.get() != int32_t(RcInMode::StickInputDisabled) && !rc_loss_ignored) {
|
||||
|
||||
@@ -56,7 +56,8 @@ private:
|
||||
enum class ManualControlLossExceptionBits : int32_t {
|
||||
Mission = (1 << 0),
|
||||
Hold = (1 << 1),
|
||||
Offboard = (1 << 2)
|
||||
Offboard = (1 << 2),
|
||||
ExternalMode = (1 << 3)
|
||||
};
|
||||
|
||||
enum class DatalinkLossExceptionBits : int32_t {
|
||||
|
||||
@@ -370,6 +370,46 @@ TEST_F(FailsafeTest, defer)
|
||||
ASSERT_FALSE(failsafe.failsafeDeferred());
|
||||
}
|
||||
|
||||
TEST_F(FailsafeTest, defer_and_clear)
|
||||
{
|
||||
FailsafeTester failsafe(nullptr);
|
||||
|
||||
failsafe_flags_s failsafe_flags{};
|
||||
FailsafeBase::State state{};
|
||||
state.armed = true;
|
||||
state.user_intended_mode = vehicle_status_s::NAVIGATION_STATE_POSCTL;
|
||||
state.vehicle_type = vehicle_status_s::VEHICLE_TYPE_ROTARY_WING;
|
||||
hrt_abstime time = 3847124342;
|
||||
|
||||
uint8_t updated_user_intented_mode = failsafe.update(time, state, false, false, failsafe_flags);
|
||||
|
||||
failsafe.deferFailsafes(true, -1);
|
||||
ASSERT_TRUE(failsafe.getDeferFailsafes());
|
||||
ASSERT_FALSE(failsafe.failsafeDeferred());
|
||||
// Manual control lost -> deferred
|
||||
time += 10_ms;
|
||||
failsafe_flags.manual_control_signal_lost = true;
|
||||
updated_user_intented_mode = failsafe.update(time, state, false, false, failsafe_flags);
|
||||
ASSERT_EQ(failsafe.selectedAction(), FailsafeBase::Action::None);
|
||||
ASSERT_TRUE(failsafe.failsafeDeferred());
|
||||
|
||||
// Clear flag (the failsafe action only clears on mode switch, but we still expect it to clear as it's being deferred)
|
||||
failsafe_flags.manual_control_signal_lost = false;
|
||||
time += 5_s;
|
||||
updated_user_intented_mode = failsafe.update(time, state, false, false, failsafe_flags);
|
||||
ASSERT_EQ(failsafe.selectedAction(), FailsafeBase::Action::None);
|
||||
ASSERT_FALSE(failsafe.failsafeDeferred());
|
||||
|
||||
// Wait a bit, don't defer anymore -> no failsafe triggered
|
||||
time += 1_s;
|
||||
failsafe.deferFailsafes(false, 0);
|
||||
updated_user_intented_mode = failsafe.update(time, state, false, false, failsafe_flags);
|
||||
ASSERT_EQ(updated_user_intented_mode, state.user_intended_mode);
|
||||
ASSERT_EQ(failsafe.selectedAction(), FailsafeBase::Action::None);
|
||||
ASSERT_FALSE(failsafe.getDeferFailsafes());
|
||||
ASSERT_FALSE(failsafe.failsafeDeferred());
|
||||
}
|
||||
|
||||
TEST_F(FailsafeTest, skip_failsafe)
|
||||
{
|
||||
FailsafeTester failsafe(nullptr);
|
||||
|
||||
@@ -396,7 +396,11 @@ bool FailsafeBase::checkFailsafe(int caller_id, bool last_state_failure, bool cu
|
||||
|
||||
void FailsafeBase::removeAction(ActionOptions &action) const
|
||||
{
|
||||
if (action.clear_condition == ClearCondition::WhenConditionClears) {
|
||||
// If failsafes are being deferred and the action can be deferred, remove it immediately independent of the
|
||||
// clear_condition to avoid triggering a failsafe after deferring is disabled.
|
||||
const bool remove_while_deferring = _defer_failsafes && action.can_be_deferred;
|
||||
|
||||
if (action.clear_condition == ClearCondition::WhenConditionClears || remove_while_deferring) {
|
||||
// Remove action
|
||||
PX4_DEBUG("Caller %i: state changed to valid, removing action", action.id);
|
||||
action.setInvalid();
|
||||
@@ -482,8 +486,13 @@ void FailsafeBase::getSelectedAction(const State &state, const failsafe_flags_s
|
||||
}
|
||||
|
||||
// Check if we should enter delayed Hold
|
||||
const bool action_can_be_delayed = selected_action != Action::None &&
|
||||
selected_action != Action::Disarm &&
|
||||
selected_action != Action::Terminate &&
|
||||
selected_action != Action::Hold;
|
||||
|
||||
if (_current_delay > 0 && !_user_takeover_active && allow_user_takeover <= UserTakeoverAllowed::AlwaysModeSwitchOnly
|
||||
&& selected_action != Action::Disarm && selected_action != Action::Terminate && selected_action != Action::Hold) {
|
||||
&& action_can_be_delayed) {
|
||||
returned_state.delayed_action = selected_action;
|
||||
selected_action = Action::Hold;
|
||||
allow_user_takeover = UserTakeoverAllowed::AlwaysModeSwitchOnly;
|
||||
@@ -711,6 +720,10 @@ bool FailsafeBase::deferFailsafes(bool enabled, int timeout_s)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!enabled && _failsafe_defer_started == 0) {
|
||||
_current_delay = 0;
|
||||
}
|
||||
|
||||
if (timeout_s == 0) {
|
||||
_defer_timeout = DEFAULT_DEFER_TIMEOUT;
|
||||
|
||||
|
||||
@@ -137,7 +137,7 @@ void AuxGlobalPosition::update(Ekf &ekf, const estimator::imuSample &imu_delayed
|
||||
if (continuing_conditions) {
|
||||
ekf.fuseHorizontalPosition(aid_src);
|
||||
|
||||
if (isTimedOut(aid_src.time_last_fuse, imu_delayed.time_us, ekf._params.no_aid_timeout_max)
|
||||
if (isTimedOut(aid_src.time_last_fuse, imu_delayed.time_us, ekf._params.reset_timeout_max)
|
||||
|| (_reset_counters.lat_lon != sample.lat_lon_reset_counter)) {
|
||||
if (ekf.isOnlyActiveSourceOfHorizontalPositionAiding(ekf.control_status_flags().aux_gpos)) {
|
||||
|
||||
|
||||
@@ -81,16 +81,26 @@ void Ekf::resetHorizontalVelocityTo(const Vector2f &new_horz_vel, const Vector2f
|
||||
const Vector2f delta_horz_vel = new_horz_vel - Vector2f(_state.vel);
|
||||
_state.vel.xy() = new_horz_vel;
|
||||
|
||||
Vector2f hor_vel_var;
|
||||
|
||||
if (PX4_ISFINITE(new_horz_vel_var(0))) {
|
||||
P.uncorrelateCovarianceSetVariance<1>(State::vel.idx, math::max(sq(0.01f), new_horz_vel_var(0)));
|
||||
hor_vel_var(0) = math::max(sq(0.01f), new_horz_vel_var(0));
|
||||
|
||||
} else {
|
||||
hor_vel_var(0) = P(State::vel.idx, State::vel.idx);
|
||||
}
|
||||
|
||||
if (PX4_ISFINITE(new_horz_vel_var(1))) {
|
||||
P.uncorrelateCovarianceSetVariance<1>(State::vel.idx + 1, math::max(sq(0.01f), new_horz_vel_var(1)));
|
||||
hor_vel_var(1) = math::max(sq(0.01f), new_horz_vel_var(1));
|
||||
|
||||
} else {
|
||||
hor_vel_var(1) = P(State::vel.idx + 1, State::vel.idx + 1);
|
||||
}
|
||||
|
||||
P.uncorrelateCovarianceSetVariance<1>(State::pos.idx, P(State::pos.idx, State::pos.idx));
|
||||
P.uncorrelateCovarianceSetVariance<1>(State::pos.idx + 1, P(State::pos.idx + 1, State::pos.idx + 1));
|
||||
P.uncorrelateCovarianceSetVariance<2>(State::vel.idx, hor_vel_var);
|
||||
|
||||
// Position decorrelation is also required to avoid issues when no position aiding is active
|
||||
P.uncorrelateCovarianceSetVariance<2>(State::pos.idx, getPositionVariance().xy());
|
||||
|
||||
_output_predictor.resetHorizontalVelocityTo(delta_horz_vel);
|
||||
|
||||
|
||||
@@ -2099,6 +2099,9 @@ Mavlink::task_main(int argc, char *argv[])
|
||||
} else if (strcmp(myoptarg, "uavionix") == 0) {
|
||||
_mode = MAVLINK_MODE_UAVIONIX;
|
||||
|
||||
} else if (strcmp(myoptarg, "low_bandwidth") == 0) {
|
||||
_mode = MAVLINK_MODE_LOW_BANDWIDTH;
|
||||
|
||||
} else {
|
||||
PX4_ERR("invalid mode");
|
||||
err_flag = true;
|
||||
|
||||
@@ -75,7 +75,7 @@ private:
|
||||
msg.y = home.y;
|
||||
msg.z = home.z;
|
||||
|
||||
matrix::Quatf q(matrix::Eulerf(home.roll, home.pitch, home.yaw));
|
||||
matrix::Quatf q(matrix::Eulerf(0.f, 0.f, home.yaw));
|
||||
q.copyTo(msg.q);
|
||||
|
||||
msg.approach_x = 0.f;
|
||||
|
||||
@@ -45,9 +45,16 @@ using namespace time_literals;
|
||||
|
||||
bool GotoControl::checkForSetpoint(const hrt_abstime &now, const bool enabled)
|
||||
{
|
||||
_goto_setpoint_sub.update();
|
||||
const bool timestamp_initialized = _goto_setpoint_sub.get().timestamp != 0;
|
||||
const bool no_timeout = now < (_goto_setpoint_sub.get().timestamp + 500_ms);
|
||||
_goto_setpoint_sub.update(&_goto_setpoint);
|
||||
|
||||
if (!enabled) {
|
||||
// Flag the setpoint as invalid if disabled, so if it is enabled in near future,
|
||||
// we don't use an old setpoint
|
||||
_goto_setpoint.timestamp = 0;
|
||||
}
|
||||
|
||||
const bool timestamp_initialized = _goto_setpoint.timestamp != 0;
|
||||
const bool no_timeout = now < (_goto_setpoint.timestamp + 500_ms);
|
||||
const bool need_to_run = timestamp_initialized && no_timeout && enabled;
|
||||
|
||||
if (!need_to_run) {
|
||||
@@ -65,9 +72,7 @@ void GotoControl::update(const float dt, const matrix::Vector3f &position, const
|
||||
_is_initialized = true;
|
||||
}
|
||||
|
||||
const goto_setpoint_s &goto_setpoint = _goto_setpoint_sub.get();
|
||||
|
||||
const Vector3f position_setpoint(_goto_setpoint_sub.get().position);
|
||||
const Vector3f position_setpoint(_goto_setpoint.position);
|
||||
|
||||
if (!position_setpoint.isAllFinite()) {
|
||||
// TODO: error messaging
|
||||
@@ -85,7 +90,7 @@ void GotoControl::update(const float dt, const matrix::Vector3f &position, const
|
||||
resetPositionSmoother(position);
|
||||
}
|
||||
|
||||
setPositionSmootherLimits(goto_setpoint);
|
||||
setPositionSmootherLimits(_goto_setpoint);
|
||||
|
||||
const Vector3f feedforward_velocity{};
|
||||
const bool force_zero_velocity_setpoint = false;
|
||||
@@ -99,13 +104,13 @@ void GotoControl::update(const float dt, const matrix::Vector3f &position, const
|
||||
out_setpoints.acceleration.copyTo(trajectory_setpoint.acceleration);
|
||||
out_setpoints.jerk.copyTo(trajectory_setpoint.jerk);
|
||||
|
||||
if (goto_setpoint.flag_control_heading && PX4_ISFINITE(goto_setpoint.heading) && PX4_ISFINITE(heading)) {
|
||||
if (_goto_setpoint.flag_control_heading && PX4_ISFINITE(_goto_setpoint.heading) && PX4_ISFINITE(heading)) {
|
||||
if (!_controlling_heading || _need_smoother_reset) {
|
||||
resetHeadingSmoother(heading);
|
||||
}
|
||||
|
||||
setHeadingSmootherLimits(goto_setpoint);
|
||||
_heading_smoothing.update(goto_setpoint.heading, dt);
|
||||
setHeadingSmootherLimits(_goto_setpoint);
|
||||
_heading_smoothing.update(_goto_setpoint.heading, dt);
|
||||
|
||||
trajectory_setpoint.yaw = _heading_smoothing.getSmoothedHeading();
|
||||
trajectory_setpoint.yawspeed = _heading_smoothing.getSmoothedHeadingRate();
|
||||
@@ -121,11 +126,11 @@ void GotoControl::update(const float dt, const matrix::Vector3f &position, const
|
||||
|
||||
_need_smoother_reset = false;
|
||||
|
||||
trajectory_setpoint.timestamp = goto_setpoint.timestamp;
|
||||
trajectory_setpoint.timestamp = hrt_absolute_time();
|
||||
_trajectory_setpoint_pub.publish(trajectory_setpoint);
|
||||
|
||||
vehicle_constraints_s vehicle_constraints{
|
||||
.timestamp = goto_setpoint.timestamp,
|
||||
.timestamp = trajectory_setpoint.timestamp,
|
||||
.speed_up = NAN,
|
||||
.speed_down = NAN,
|
||||
.want_takeoff = false
|
||||
|
||||
@@ -115,10 +115,11 @@ private:
|
||||
*/
|
||||
void setHeadingSmootherLimits(const goto_setpoint_s &goto_setpoint);
|
||||
|
||||
uORB::SubscriptionData<goto_setpoint_s> _goto_setpoint_sub{ORB_ID(goto_setpoint)};
|
||||
uORB::Subscription _goto_setpoint_sub{ORB_ID(goto_setpoint)};
|
||||
uORB::Publication<trajectory_setpoint_s> _trajectory_setpoint_pub{ORB_ID(trajectory_setpoint)};
|
||||
uORB::Publication<vehicle_constraints_s> _vehicle_constraints_pub{ORB_ID(vehicle_constraints)};
|
||||
|
||||
goto_setpoint_s _goto_setpoint{};
|
||||
PositionSmoothing _position_smoothing;
|
||||
HeadingSmoothing _heading_smoothing;
|
||||
|
||||
|
||||
@@ -426,9 +426,12 @@ void MulticopterPositionControl::Run()
|
||||
|
||||
PositionControlStates states{set_vehicle_states(vehicle_local_position, dt)};
|
||||
|
||||
// if a goto setpoint available this publishes a trajectory setpoint to go there
|
||||
if (_goto_control.checkForSetpoint(vehicle_local_position.timestamp_sample,
|
||||
_vehicle_control_mode.flag_multicopter_position_control_enabled)) {
|
||||
// If a goto setpoint is available this publishes a trajectory setpoint to go there
|
||||
// If trajectory_setpoint is published elsewhere, do not use the goto setpoint
|
||||
const bool goto_setpoint_enable = _vehicle_control_mode.flag_multicopter_position_control_enabled
|
||||
&& !_trajectory_setpoint_sub.updated();
|
||||
|
||||
if (_goto_control.checkForSetpoint(vehicle_local_position.timestamp_sample, goto_setpoint_enable)) {
|
||||
_goto_control.update(dt, states.position, states.yaw);
|
||||
}
|
||||
|
||||
|
||||
@@ -61,12 +61,14 @@ void AckermannPosControl::updatePosControl()
|
||||
if (target_waypoint_ned.isAllFinite()) {
|
||||
float distance_to_target = (target_waypoint_ned - _curr_pos_ned).norm();
|
||||
|
||||
if (distance_to_target > _acceptance_radius) {
|
||||
float arrival_speed = PX4_ISFINITE(_rover_position_setpoint.arrival_speed) ? _rover_position_setpoint.arrival_speed :
|
||||
0.f;
|
||||
const float distance = arrival_speed > 0.f + FLT_EPSILON ? distance_to_target - _acceptance_radius : distance_to_target;
|
||||
if (_arrival_speed > FLT_EPSILON) {
|
||||
distance_to_target -= _acceptance_radius; // shift target to the edge of the acceptance radius if arrival speed not zero
|
||||
}
|
||||
|
||||
if (distance_to_target > _acceptance_radius || _arrival_speed > FLT_EPSILON) {
|
||||
|
||||
float speed_setpoint = math::trajectory::computeMaxSpeedFromDistance(_param_ro_jerk_limit.get(),
|
||||
_param_ro_decel_limit.get(), distance, fabsf(arrival_speed));
|
||||
_param_ro_decel_limit.get(), distance_to_target, fabsf(_arrival_speed));
|
||||
speed_setpoint = math::min(speed_setpoint, _param_ro_speed_limit.get());
|
||||
|
||||
if (PX4_ISFINITE(_rover_position_setpoint.cruising_speed)) {
|
||||
@@ -130,6 +132,7 @@ void AckermannPosControl::updateSubscriptions()
|
||||
_rover_position_setpoint_sub.copy(&_rover_position_setpoint);
|
||||
_start_ned = Vector2f(_rover_position_setpoint.start_ned[0], _rover_position_setpoint.start_ned[1]);
|
||||
_start_ned = _start_ned.isAllFinite() ? _start_ned : _curr_pos_ned;
|
||||
_arrival_speed = PX4_ISFINITE(_rover_position_setpoint.arrival_speed) ? _rover_position_setpoint.arrival_speed : 0.f;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -106,6 +106,7 @@ private:
|
||||
Quatf _vehicle_attitude_quaternion{};
|
||||
Vector2f _curr_pos_ned{};
|
||||
Vector2f _start_ned{};
|
||||
float _arrival_speed{0.f};
|
||||
float _vehicle_yaw{0.f};
|
||||
float _max_yaw_rate{0.f};
|
||||
float _acceptance_radius{0.f}; // Acceptance radius for the waypoint.
|
||||
|
||||
@@ -54,24 +54,19 @@ void DifferentialPosControl::updatePosControl()
|
||||
|
||||
hrt_abstime timestamp = hrt_absolute_time();
|
||||
|
||||
if (_rover_position_setpoint_sub.updated()) {
|
||||
_rover_position_setpoint_sub.copy(&_rover_position_setpoint);
|
||||
_start_ned = Vector2f(_rover_position_setpoint.start_ned[0], _rover_position_setpoint.start_ned[1]);
|
||||
_start_ned = _start_ned.isAllFinite() ? _start_ned : _curr_pos_ned;
|
||||
}
|
||||
|
||||
const Vector2f target_waypoint_ned(_rover_position_setpoint.position_ned[0], _rover_position_setpoint.position_ned[1]);
|
||||
|
||||
if (target_waypoint_ned.isAllFinite()) {
|
||||
float distance_to_target = (target_waypoint_ned - _curr_pos_ned).norm();
|
||||
|
||||
if (distance_to_target > _param_nav_acc_rad.get()) {
|
||||
float arrival_speed = PX4_ISFINITE(_rover_position_setpoint.arrival_speed) ? _rover_position_setpoint.arrival_speed :
|
||||
0.f;
|
||||
const float distance = arrival_speed > 0.f + FLT_EPSILON ? distance_to_target - _param_nav_acc_rad.get() :
|
||||
distance_to_target;
|
||||
if (_arrival_speed > FLT_EPSILON) {
|
||||
distance_to_target -=
|
||||
_param_nav_acc_rad.get(); // shift target to the edge of the acceptance radius if arrival speed not zero
|
||||
}
|
||||
|
||||
if (distance_to_target > _param_nav_acc_rad.get() || _arrival_speed > FLT_EPSILON) {
|
||||
float speed_setpoint = math::trajectory::computeMaxSpeedFromDistance(_param_ro_jerk_limit.get(),
|
||||
_param_ro_decel_limit.get(), distance, fabsf(arrival_speed));
|
||||
_param_ro_decel_limit.get(), distance_to_target, fabsf(_arrival_speed));
|
||||
speed_setpoint = math::min(speed_setpoint, _param_ro_speed_limit.get());
|
||||
|
||||
if (PX4_ISFINITE(_rover_position_setpoint.cruising_speed)) {
|
||||
@@ -119,6 +114,14 @@ void DifferentialPosControl::updateSubscriptions()
|
||||
_curr_pos_ned = Vector2f(vehicle_local_position.x, vehicle_local_position.y);
|
||||
}
|
||||
|
||||
if (_rover_position_setpoint_sub.updated()) {
|
||||
_rover_position_setpoint_sub.copy(&_rover_position_setpoint);
|
||||
_start_ned = Vector2f(_rover_position_setpoint.start_ned[0], _rover_position_setpoint.start_ned[1]);
|
||||
_start_ned = _start_ned.isAllFinite() ? _start_ned : _curr_pos_ned;
|
||||
_arrival_speed = PX4_ISFINITE(_rover_position_setpoint.arrival_speed) ? _rover_position_setpoint.arrival_speed : 0.f;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
bool DifferentialPosControl::runSanityChecks()
|
||||
|
||||
@@ -103,6 +103,7 @@ private:
|
||||
// Variables
|
||||
Vector2f _curr_pos_ned{};
|
||||
Vector2f _start_ned{};
|
||||
float _arrival_speed{0.f};
|
||||
float _vehicle_yaw{0.f};
|
||||
|
||||
DEFINE_PARAMETERS(
|
||||
|
||||
@@ -56,26 +56,21 @@ void MecanumPosControl::updatePosControl()
|
||||
|
||||
hrt_abstime timestamp = hrt_absolute_time();
|
||||
|
||||
if (_rover_position_setpoint_sub.updated()) {
|
||||
_rover_position_setpoint_sub.copy(&_rover_position_setpoint);
|
||||
_start_ned = Vector2f(_rover_position_setpoint.start_ned[0], _rover_position_setpoint.start_ned[1]);
|
||||
_start_ned = _start_ned.isAllFinite() ? _start_ned : _curr_pos_ned;
|
||||
_yaw_setpoint = PX4_ISFINITE(_rover_position_setpoint.yaw) ? _rover_position_setpoint.yaw : _vehicle_yaw;
|
||||
}
|
||||
|
||||
const Vector2f target_waypoint_ned(_rover_position_setpoint.position_ned[0], _rover_position_setpoint.position_ned[1]);
|
||||
|
||||
if (target_waypoint_ned.isAllFinite()) {
|
||||
|
||||
float distance_to_target = (target_waypoint_ned - _curr_pos_ned).norm();
|
||||
|
||||
if (distance_to_target > _param_nav_acc_rad.get()) {
|
||||
float arrival_speed = PX4_ISFINITE(_rover_position_setpoint.arrival_speed) ? _rover_position_setpoint.arrival_speed :
|
||||
0.f;
|
||||
const float distance = arrival_speed > 0.f + FLT_EPSILON ? distance_to_target - _param_nav_acc_rad.get() :
|
||||
distance_to_target;
|
||||
if (_arrival_speed > FLT_EPSILON) {
|
||||
distance_to_target -=
|
||||
_param_nav_acc_rad.get(); // shift target to the edge of the acceptance radius if arrival speed not zero
|
||||
}
|
||||
|
||||
if (distance_to_target > _param_nav_acc_rad.get() || _arrival_speed > FLT_EPSILON) {
|
||||
|
||||
float speed_setpoint = math::trajectory::computeMaxSpeedFromDistance(_param_ro_jerk_limit.get(),
|
||||
_param_ro_decel_limit.get(), distance, fabsf(arrival_speed));
|
||||
_param_ro_decel_limit.get(), distance_to_target, fabsf(_arrival_speed));
|
||||
speed_setpoint = math::min(speed_setpoint, _param_ro_speed_limit.get());
|
||||
|
||||
if (PX4_ISFINITE(_rover_position_setpoint.cruising_speed)) {
|
||||
@@ -130,6 +125,14 @@ void MecanumPosControl::updateSubscriptions()
|
||||
_curr_pos_ned = Vector2f(vehicle_local_position.x, vehicle_local_position.y);
|
||||
}
|
||||
|
||||
if (_rover_position_setpoint_sub.updated()) {
|
||||
_rover_position_setpoint_sub.copy(&_rover_position_setpoint);
|
||||
_start_ned = Vector2f(_rover_position_setpoint.start_ned[0], _rover_position_setpoint.start_ned[1]);
|
||||
_start_ned = _start_ned.isAllFinite() ? _start_ned : _curr_pos_ned;
|
||||
_yaw_setpoint = PX4_ISFINITE(_rover_position_setpoint.yaw) ? _rover_position_setpoint.yaw : _vehicle_yaw;
|
||||
_arrival_speed = PX4_ISFINITE(_rover_position_setpoint.arrival_speed) ? _rover_position_setpoint.arrival_speed : 0.f;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool MecanumPosControl::runSanityChecks()
|
||||
|
||||
@@ -105,6 +105,7 @@ private:
|
||||
Quatf _vehicle_attitude_quaternion{};
|
||||
Vector2f _curr_pos_ned{};
|
||||
Vector2f _start_ned{};
|
||||
float _arrival_speed{0.f};
|
||||
float _vehicle_yaw{0.f};
|
||||
float _max_yaw_rate{0.f};
|
||||
float _yaw_setpoint{NAN};
|
||||
|
||||
@@ -64,4 +64,4 @@ PARAM_DEFINE_FLOAT(SENS_BARO_RATE, 20.0f);
|
||||
* @category system
|
||||
* @group Sensors
|
||||
*/
|
||||
PARAM_DEFINE_INT32(SENS_BAR_AUTOCAL, 0);
|
||||
PARAM_DEFINE_INT32(SENS_BAR_AUTOCAL, 1);
|
||||
|
||||
@@ -55,6 +55,7 @@ if(PX4_PLATFORM MATCHES "posix")
|
||||
xvert
|
||||
standard_vtol
|
||||
hex
|
||||
rover_ackermann
|
||||
)
|
||||
|
||||
# find corresponding airframes
|
||||
|
||||
@@ -211,7 +211,7 @@ void Sih::sensor_step()
|
||||
|
||||
read_motors(dt);
|
||||
|
||||
generate_force_and_torques();
|
||||
generate_force_and_torques(dt);
|
||||
|
||||
equations_of_motion(dt);
|
||||
|
||||
@@ -290,6 +290,7 @@ void Sih::init_variables()
|
||||
|
||||
_lpos = Vector3f(0.0f, 0.0f, 0.0f);
|
||||
_v_N = Vector3f(0.0f, 0.0f, 0.0f);
|
||||
_v_N_dot = Vector3f(0.0f, 0.0f, 0.0f);
|
||||
_p_E = Vector3d(Wgs84::equatorial_radius, 0.0, 0.0);
|
||||
_v_E = Vector3f(0.0f, 0.0f, 0.0f);
|
||||
_q = Quatf(1.0f, 0.0f, 0.0f, 0.0f);
|
||||
@@ -318,7 +319,7 @@ void Sih::read_motors(const float dt)
|
||||
}
|
||||
}
|
||||
|
||||
void Sih::generate_force_and_torques()
|
||||
void Sih::generate_force_and_torques(const float dt)
|
||||
{
|
||||
if (_vehicle == VehicleType::Quadcopter) {
|
||||
_T_B = Vector3f(0.0f, 0.0f, -_T_MAX * (+_u[0] + _u[1] + _u[2] + _u[3]));
|
||||
@@ -367,6 +368,9 @@ void Sih::generate_force_and_torques()
|
||||
// thrust 0 because it is already contained in _T_B. in
|
||||
// equations_of_motion they are all summed into sum_of_forces_E
|
||||
generate_fw_aerodynamics(_u[4], _u[5], _u[6], 0);
|
||||
|
||||
} else if (_vehicle == VehicleType::RoverAckermann) {
|
||||
generate_rover_ackermann_dynamics(_u[1], _u[0], dt);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -422,6 +426,73 @@ void Sih::generate_ts_aerodynamics()
|
||||
_Ma_B = _R_S2B * Ma_ts - _KDW * _w_B; // aerodynamic moments
|
||||
}
|
||||
|
||||
void Sih::generate_rover_ackermann_dynamics(const float throttle_cmd, const float steering_cmd, const float dt)
|
||||
{
|
||||
// --- Constants ---
|
||||
static constexpr float MAX_THROTTLE_FORCE = 400.0f; // [N]
|
||||
static constexpr float MAX_STEER_ANGLE = radians(30.f); // [rad]
|
||||
static constexpr float WHEEL_BASE = 0.321f; // [m] Distance between front and rear axle
|
||||
static constexpr float C = 500.f; // [N/rad] Cornering stiffness
|
||||
static constexpr float MU_S = 0.5f; // [-] Static Coefficient of friction
|
||||
static constexpr float MU_K = 0.4f; // [-] Kinetic Coefficient of friction
|
||||
static constexpr float MU_R = 0.3f; // [-] Rolling Coefficient of friction
|
||||
static constexpr float ROLLING_THRESHOLD = 0.05f; // [m/s] Threshold for rolling resistance
|
||||
static constexpr float STATIC_THRESHOLD = 0.01f; // [m/s] Threshold for static resistance
|
||||
|
||||
matrix::Vector3f v_B = _q.rotateVectorInverse(_v_N); // Nav -> Body
|
||||
|
||||
// --- Compute inputs ---
|
||||
const float delta = MAX_STEER_ANGLE * steering_cmd; // [rad] Steering angle
|
||||
const float F_x = MAX_THROTTLE_FORCE * throttle_cmd; // [N] Throttle force
|
||||
|
||||
// --- Compute forces and moments ---
|
||||
float F_y = 0.f; // [N] Lateral force
|
||||
float M_z = 0.f; // [Nm] Yaw moment
|
||||
|
||||
if (fabsf(v_B(0)) > ROLLING_THRESHOLD) {
|
||||
// Equations based on the lateral dynamics of the bicycle model from [1]
|
||||
// [1] Sri Anumakonda, Everything you need to know about Self-Driving Cars in <30 minutes
|
||||
// Link: https://srianumakonda.medium.com/everything-you-need-to-know-about-self-driving-in-30-minutes-b38d68bd3427
|
||||
const float a_y = C * delta / _MASS - fabsf(v_B(0)) * _w_B(2)
|
||||
- 2 * C * v_B(1) / (_MASS * fabsf(v_B(0))); // [m/s^2] Lateral acceleration
|
||||
const float psi_dot_dot = WHEEL_BASE * C * delta / _sih_izz.get()
|
||||
- C * WHEEL_BASE * WHEEL_BASE * _w_B(2) / (_sih_izz.get() * fabsf(v_B(0))); // [rad/s^2] Yaw acceleration
|
||||
F_y = _MASS * a_y; // Lateral force [N]
|
||||
M_z = _sih_izz.get() * psi_dot_dot; // [Nm] Yaw moment
|
||||
}
|
||||
|
||||
_T_B = Vector3f(F_x, F_y, 0.f);
|
||||
_Mt_B = Vector3f(0.f, 0.f, M_z);
|
||||
|
||||
// --- Compute drag/friction forces and moments ---
|
||||
Vector3f F_f = Vector3f(0.f, 0.f, 0.f); // [N] Friction force
|
||||
Vector3f F_a = Vector3f(0.f, 0.f, 0.f); // [N] Aerodynamic force (neglect until rover is rolling)
|
||||
|
||||
if (_v_E.norm() < STATIC_THRESHOLD) { // Static friction
|
||||
Vector3f F_f_B = Vector3f(sign(F_x) * math::min(fabsf(F_x), MU_S * _MASS * 9.81f), sign(F_y) * math::min(fabsf(F_y),
|
||||
MU_S * _MASS * 9.81f), 0.f);
|
||||
F_f = _q_E.rotateVector(F_f_B);
|
||||
|
||||
} else if (_v_E.norm() < ROLLING_THRESHOLD) { // Kinetic friction
|
||||
if (_T_B.norm() > FLT_EPSILON) {
|
||||
F_f = _v_E.unit_or_zero() * MU_K * _MASS * 9.81f;
|
||||
|
||||
} else {
|
||||
F_f = _v_E * _MASS / dt; // Stop the vehicle
|
||||
}
|
||||
|
||||
} else { // Rolling friction
|
||||
F_f = _v_E.unit_or_zero() * MU_R * _MASS * 9.81f;
|
||||
Vector3f v_E_squared = Vector3f(sign(_v_E(0)) * _v_E(0) * _v_E(0), sign(_v_E(1)) * _v_E(1) * _v_E(1),
|
||||
sign(_v_E(2)) * _v_E(2) * _v_E(2));
|
||||
F_a = _KDV * v_E_squared; // [N] Second order drag
|
||||
}
|
||||
|
||||
_Fa_E = -F_a - F_f; // [N] Second order drag and friction
|
||||
_Ma_B = -_KDW * _w_B; // [Nm] First order angular damper
|
||||
|
||||
}
|
||||
|
||||
float Sih::computeGravity(const double lat)
|
||||
{
|
||||
// Somigliana formula for gravitational acceleration
|
||||
@@ -459,7 +530,8 @@ void Sih::equations_of_motion(const float dt)
|
||||
|
||||
_grounded = true;
|
||||
|
||||
} else if (_vehicle == VehicleType::FixedWing) {
|
||||
} else if (_vehicle == VehicleType::FixedWing
|
||||
|| _vehicle == VehicleType::RoverAckermann) {
|
||||
Vector3f down_u = _R_N2E.col(2);
|
||||
ground_force_E = -down_u * sum_of_forces_E * down_u;
|
||||
|
||||
@@ -749,6 +821,9 @@ int Sih::print_status()
|
||||
|
||||
} else if (_vehicle == VehicleType::StandardVTOL) {
|
||||
PX4_INFO("Standard VTOL");
|
||||
|
||||
} else if (_vehicle == VehicleType::RoverAckermann) {
|
||||
PX4_INFO("Rover Ackermann");
|
||||
}
|
||||
|
||||
PX4_INFO("vehicle landed: %d", _grounded);
|
||||
|
||||
@@ -151,7 +151,7 @@ private:
|
||||
void read_motors(const float dt);
|
||||
|
||||
// generate the motors thrust and torque in the body frame
|
||||
void generate_force_and_torques();
|
||||
void generate_force_and_torques(const float dt);
|
||||
|
||||
// apply the equations of motion of a rigid body and integrate one step
|
||||
void equations_of_motion(const float dt);
|
||||
@@ -163,6 +163,7 @@ private:
|
||||
void publish_ground_truth(const hrt_abstime &time_now_us);
|
||||
void generate_fw_aerodynamics(const float roll_cmd, const float pitch_cmd, const float yaw_cmd, const float thrust);
|
||||
void generate_ts_aerodynamics();
|
||||
void generate_rover_ackermann_dynamics(const float throttle_cmd, const float steering_cmd, const float dt);
|
||||
void sensor_step();
|
||||
static float computeGravity(double lat);
|
||||
|
||||
@@ -220,7 +221,7 @@ private:
|
||||
|
||||
float _u[NUM_ACTUATORS_MAX] {}; // thruster signals
|
||||
|
||||
enum class VehicleType {Quadcopter, FixedWing, TailsitterVTOL, StandardVTOL, Hexacopter, First = Quadcopter, Last = Hexacopter}; // numbering dependent on parameter SIH_VEHICLE_TYPE
|
||||
enum class VehicleType {Quadcopter, FixedWing, TailsitterVTOL, StandardVTOL, Hexacopter, RoverAckermann, First = Quadcopter, Last = RoverAckermann}; // numbering dependent on parameter SIH_VEHICLE_TYPE
|
||||
VehicleType _vehicle = VehicleType::Quadcopter;
|
||||
|
||||
// aerodynamic segments for the fixedwing
|
||||
|
||||
@@ -334,6 +334,7 @@ PARAM_DEFINE_FLOAT(SIH_T_TAU, 0.05f);
|
||||
* @value 2 Tailsitter
|
||||
* @value 3 Standard VTOL
|
||||
* @value 4 Hexacopter
|
||||
* @value 5 Rover Ackermann
|
||||
* @reboot_required true
|
||||
* @group Simulation In Hardware
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user