mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-06-19 12:30:34 +08:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6f484b652f | |||
| 990b067b25 | |||
| 68cbbaab92 | |||
| 22c1f07f0c | |||
| f2bbb6f407 | |||
| 85bc8ef885 | |||
| 8a9bac29a2 | |||
| 7236ef2d17 | |||
| 1dad25b763 |
@@ -25,8 +25,14 @@ jobs:
|
||||
submodules: false
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set PX4 Tag
|
||||
id: px4-tag
|
||||
run: |
|
||||
echo "tag=$(git describe --tags --match 'v[0-9]*')" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
if: github.event_name != 'pull_request'
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
@@ -44,16 +50,15 @@ jobs:
|
||||
with:
|
||||
images: |
|
||||
ghcr.io/PX4/px4-dev
|
||||
px4io/px4-dev
|
||||
${{ (github.event_name != 'pull_request') && 'px4io/px4-dev' || '' }}
|
||||
tags: |
|
||||
type=schedule
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=semver,pattern={{major}}
|
||||
type=ref,event=branch,suffix=-{{date 'YYYYMMDD'}},priority=600
|
||||
type=ref,event=branch,value=${{ steps.px4-tag.outputs.tag }},priority=700
|
||||
type=ref,event=branch,suffix=-{{date 'YYYY-MM-DD'}},priority=600
|
||||
type=ref,event=branch,suffix=,priority=500
|
||||
type=ref,event=pr
|
||||
type=sha
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
@@ -45,7 +45,7 @@ param set-default CA_SV_CS1_TRQ_P 1
|
||||
param set-default CA_SV_CS1_TYPE 3
|
||||
param set-default CA_SV_CS2_TRQ_Y 1
|
||||
param set-default CA_SV_CS2_TYPE 4
|
||||
param set-default PWM_MAIN_FUNC3 201
|
||||
param set-default PWM_MAIN_FUNC4 202
|
||||
param set-default PWM_MAIN_FUNC5 203
|
||||
param set-default PWM_MAIN_FUNC6 101
|
||||
param set-default PWM_MAIN_FUNC1 201
|
||||
param set-default PWM_MAIN_FUNC2 202
|
||||
param set-default PWM_MAIN_FUNC3 203
|
||||
param set-default PWM_MAIN_FUNC4 101
|
||||
|
||||
@@ -43,7 +43,7 @@ fi
|
||||
|
||||
# install git pre-commit hook
|
||||
HOOK_FILE="$DIR/../../.git/hooks/pre-commit"
|
||||
if [ ! -f $HOOK_FILE ] && [ "$CI" != "true" ]; then
|
||||
if [ ! -f $HOOK_FILE ] && [ "$CI" != "true" ] && [ $- == *i* ]; then
|
||||
echo ""
|
||||
echo -e "\033[31mNinja tip: add a git pre-commit hook to automatically check code style\033[0m"
|
||||
echo -e "Would you like to install one now? (\033[94mcp ./Tools/astyle/pre-commit .git/hooks/pre-commit\033[0m): [y/\033[1mN\033[0m]"
|
||||
|
||||
@@ -43,35 +43,13 @@
|
||||
|
||||
#include <mathlib/mathlib.h>
|
||||
|
||||
bool Ekf::init(uint64_t timestamp)
|
||||
{
|
||||
if (!_initialised) {
|
||||
_initialised = initialise_interface(timestamp);
|
||||
reset();
|
||||
}
|
||||
|
||||
return _initialised;
|
||||
}
|
||||
|
||||
void Ekf::reset()
|
||||
{
|
||||
ECL_INFO("reset");
|
||||
|
||||
_state = {};
|
||||
_state.quat_nominal.setIdentity();
|
||||
_state.vel.setZero();
|
||||
_state.pos.setZero();
|
||||
_state.gyro_bias.setZero();
|
||||
_state.accel_bias.setZero();
|
||||
|
||||
#if defined(CONFIG_EKF2_MAGNETOMETER)
|
||||
_state.mag_I.setZero();
|
||||
_state.mag_B.setZero();
|
||||
#endif // CONFIG_EKF2_MAGNETOMETER
|
||||
|
||||
#if defined(CONFIG_EKF2_WIND)
|
||||
_state.wind_vel.setZero();
|
||||
#endif // CONFIG_EKF2_WIND
|
||||
//
|
||||
#if defined(CONFIG_EKF2_TERRAIN)
|
||||
// assume a ground clearance
|
||||
_state.terrain = -_gpos.altitude() + _params.rng_gnd_clearance;
|
||||
@@ -101,6 +79,13 @@ void Ekf::reset()
|
||||
|
||||
_output_predictor.reset();
|
||||
|
||||
_time_latest_us = 0;
|
||||
_time_delayed_us = 0;
|
||||
|
||||
_imu_updated = false;
|
||||
|
||||
_filter_initialised = false;
|
||||
|
||||
// Ekf private fields
|
||||
_time_last_horizontal_aiding = 0;
|
||||
_time_last_v_pos_aiding = 0;
|
||||
@@ -133,18 +118,12 @@ void Ekf::reset()
|
||||
_zero_velocity_update.reset();
|
||||
|
||||
updateParameters();
|
||||
|
||||
initialiseCovariance();
|
||||
}
|
||||
|
||||
bool Ekf::update()
|
||||
{
|
||||
if (!_filter_initialised) {
|
||||
_filter_initialised = initialiseFilter();
|
||||
|
||||
if (!_filter_initialised) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Only run the filter if IMU data in the buffer has been updated
|
||||
if (_imu_updated) {
|
||||
_imu_updated = false;
|
||||
@@ -159,14 +138,52 @@ bool Ekf::update()
|
||||
float filter_update_s = 1e-6f * _params.filter_update_interval_us;
|
||||
_dt_ekf_avg = 0.99f * _dt_ekf_avg + 0.01f * math::constrain(input, 0.5f * filter_update_s, 2.f * filter_update_s);
|
||||
|
||||
// Filter accel for tilt initialization
|
||||
if (_is_first_imu_sample) {
|
||||
_accel_lpf.reset(imu_sample_delayed.delta_vel / imu_sample_delayed.delta_vel_dt);
|
||||
_gyro_lpf.reset(imu_sample_delayed.delta_ang / imu_sample_delayed.delta_ang_dt);
|
||||
_is_first_imu_sample = false;
|
||||
|
||||
_state = {};
|
||||
initialiseTilt(_accel_lpf.getState());
|
||||
initialiseCovariance();
|
||||
|
||||
} else {
|
||||
_accel_lpf.update(imu_sample_delayed.delta_vel / imu_sample_delayed.delta_vel_dt);
|
||||
_gyro_lpf.update(imu_sample_delayed.delta_ang / imu_sample_delayed.delta_ang_dt);
|
||||
}
|
||||
|
||||
if (!_filter_initialised) {
|
||||
|
||||
const float accel_norm = _accel_lpf.getState().norm();
|
||||
const float gyro_norm = _gyro_lpf.getState().norm();
|
||||
|
||||
if ((accel_norm > 0.8f * CONSTANTS_ONE_G)
|
||||
&& (accel_norm < 1.2f * CONSTANTS_ONE_G)
|
||||
&& (gyro_norm < math::radians(15.f))
|
||||
) {
|
||||
// once ready reset and init tilt from filtered accel
|
||||
_state = {};
|
||||
initialiseTilt(_accel_lpf.getState());
|
||||
initialiseCovariance();
|
||||
|
||||
// reset the output predictor state history to match the EKF initial values
|
||||
_output_predictor.alignOutputFilter(_state.quat_nominal, _state.vel, _gpos);
|
||||
|
||||
_filter_initialised = true;
|
||||
}
|
||||
}
|
||||
|
||||
updateIMUBiasInhibit(imu_sample_delayed);
|
||||
|
||||
// perform state and covariance prediction for the main filter
|
||||
predictCovariance(imu_sample_delayed);
|
||||
predictState(imu_sample_delayed);
|
||||
|
||||
// control fusion of observation data
|
||||
controlFusionModes(imu_sample_delayed);
|
||||
if (_filter_initialised) {
|
||||
// control fusion of observation data
|
||||
controlFusionModes(imu_sample_delayed);
|
||||
}
|
||||
|
||||
_output_predictor.correctOutputStates(imu_sample_delayed.time_us, _state.quat_nominal, _state.vel, _gpos,
|
||||
_state.gyro_bias, _state.accel_bias);
|
||||
@@ -177,52 +194,10 @@ bool Ekf::update()
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Ekf::initialiseFilter()
|
||||
bool Ekf::initialiseTilt(const Vector3f &accel)
|
||||
{
|
||||
// Filter accel for tilt initialization
|
||||
const imuSample &imu_init = _imu_buffer.get_newest();
|
||||
|
||||
// protect against zero data
|
||||
if (imu_init.delta_vel_dt < 1e-4f || imu_init.delta_ang_dt < 1e-4f) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_is_first_imu_sample) {
|
||||
_accel_lpf.reset(imu_init.delta_vel / imu_init.delta_vel_dt);
|
||||
_gyro_lpf.reset(imu_init.delta_ang / imu_init.delta_ang_dt);
|
||||
_is_first_imu_sample = false;
|
||||
|
||||
} else {
|
||||
_accel_lpf.update(imu_init.delta_vel / imu_init.delta_vel_dt);
|
||||
_gyro_lpf.update(imu_init.delta_ang / imu_init.delta_ang_dt);
|
||||
}
|
||||
|
||||
if (!initialiseTilt()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// initialise the state covariance matrix now we have starting values for all the states
|
||||
initialiseCovariance();
|
||||
|
||||
// reset the output predictor state history to match the EKF initial values
|
||||
_output_predictor.alignOutputFilter(_state.quat_nominal, _state.vel, _gpos);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Ekf::initialiseTilt()
|
||||
{
|
||||
const float accel_norm = _accel_lpf.getState().norm();
|
||||
const float gyro_norm = _gyro_lpf.getState().norm();
|
||||
|
||||
if (accel_norm < 0.8f * CONSTANTS_ONE_G ||
|
||||
accel_norm > 1.2f * CONSTANTS_ONE_G ||
|
||||
gyro_norm > math::radians(15.0f)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// get initial tilt estimate from delta velocity vector, assuming vehicle is static
|
||||
_state.quat_nominal = Quatf(_accel_lpf.getState(), Vector3f(0.f, 0.f, -1.f));
|
||||
_state.quat_nominal = Quatf(accel, Vector3f(0.f, 0.f, -1.f));
|
||||
_R_to_earth = Dcmf(_state.quat_nominal);
|
||||
|
||||
return true;
|
||||
|
||||
@@ -80,15 +80,15 @@ public:
|
||||
Ekf()
|
||||
{
|
||||
reset();
|
||||
initialise_interface();
|
||||
};
|
||||
|
||||
virtual ~Ekf() = default;
|
||||
|
||||
// initialise variables to sane values (also interface class)
|
||||
bool init(uint64_t timestamp) override;
|
||||
~Ekf() = default;
|
||||
|
||||
void print_status();
|
||||
|
||||
void reset();
|
||||
|
||||
// should be called every time new data is pushed into the filter
|
||||
bool update();
|
||||
|
||||
@@ -427,10 +427,7 @@ private:
|
||||
friend class EvVelLocalFrameNed;
|
||||
friend class EvVelLocalFrameFrd;
|
||||
|
||||
// set the internal states and status to their default value
|
||||
void reset();
|
||||
|
||||
bool initialiseTilt();
|
||||
bool initialiseTilt(const Vector3f &accel);
|
||||
|
||||
// check if the EKF is dead reckoning horizontal velocity using inertial data only
|
||||
void updateDeadReckoningStatus();
|
||||
@@ -583,11 +580,6 @@ private:
|
||||
estimator_aid_source2d_s _aid_src_aux_vel {};
|
||||
#endif // CONFIG_EKF2_AUXVEL
|
||||
|
||||
// Variables used by the initial filter alignment
|
||||
bool _is_first_imu_sample{true};
|
||||
AlphaFilter<Vector3f> _accel_lpf{0.1f}; ///< filtered accelerometer measurement used to align tilt (m/s/s)
|
||||
AlphaFilter<Vector3f> _gyro_lpf{0.1f}; ///< filtered gyro measurement used for alignment excessive movement check (rad/sec)
|
||||
|
||||
#if defined(CONFIG_EKF2_BAROMETER)
|
||||
estimator_aid_source1d_s _aid_src_baro_hgt {};
|
||||
|
||||
@@ -626,9 +618,6 @@ private:
|
||||
uint64_t _time_good_vert_accel{0}; ///< last time a good vertical accel was detected (uSec)
|
||||
uint16_t _clip_counter[3]; ///< counter per axis that increments when clipping ad decrements when not
|
||||
|
||||
// initialise filter states of both the delayed ekf and the real time complementary filter
|
||||
bool initialiseFilter(void);
|
||||
|
||||
// initialise ekf covariance matrix
|
||||
void initialiseCovariance();
|
||||
|
||||
|
||||
@@ -78,11 +78,6 @@ EstimatorInterface::~EstimatorInterface()
|
||||
// Accumulate imu data and store to buffer at desired rate
|
||||
void EstimatorInterface::setIMUData(const imuSample &imu_sample)
|
||||
{
|
||||
// TODO: resolve misplaced responsibility
|
||||
if (!_initialised) {
|
||||
_initialised = init(imu_sample.time_us);
|
||||
}
|
||||
|
||||
_time_latest_us = imu_sample.time_us;
|
||||
|
||||
// the output observer always runs
|
||||
@@ -122,18 +117,19 @@ void EstimatorInterface::setIMUData(const imuSample &imu_sample)
|
||||
#if defined(CONFIG_EKF2_MAGNETOMETER)
|
||||
void EstimatorInterface::setMagData(const magSample &mag_sample)
|
||||
{
|
||||
if (!_initialised) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Allocate the required buffer size if not previously done
|
||||
if (_mag_buffer == nullptr) {
|
||||
_mag_buffer = new RingBuffer<magSample>(_obs_buffer_length);
|
||||
if (_obs_buffer_length > 0) {
|
||||
_mag_buffer = new RingBuffer<magSample>(_obs_buffer_length);
|
||||
|
||||
if (_mag_buffer == nullptr || !_mag_buffer->valid()) {
|
||||
delete _mag_buffer;
|
||||
_mag_buffer = nullptr;
|
||||
printBufferAllocationFailed("mag");
|
||||
if (_mag_buffer == nullptr || !_mag_buffer->valid()) {
|
||||
delete _mag_buffer;
|
||||
_mag_buffer = nullptr;
|
||||
printBufferAllocationFailed("mag");
|
||||
return;
|
||||
}
|
||||
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -161,18 +157,19 @@ void EstimatorInterface::setMagData(const magSample &mag_sample)
|
||||
#if defined(CONFIG_EKF2_GNSS)
|
||||
void EstimatorInterface::setGpsData(const gnssSample &gnss_sample)
|
||||
{
|
||||
if (!_initialised) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Allocate the required buffer size if not previously done
|
||||
if (_gps_buffer == nullptr) {
|
||||
_gps_buffer = new RingBuffer<gnssSample>(_obs_buffer_length);
|
||||
if (_obs_buffer_length > 0) {
|
||||
_gps_buffer = new RingBuffer<gnssSample>(_obs_buffer_length);
|
||||
|
||||
if (_gps_buffer == nullptr || !_gps_buffer->valid()) {
|
||||
delete _gps_buffer;
|
||||
_gps_buffer = nullptr;
|
||||
printBufferAllocationFailed("GPS");
|
||||
if (_gps_buffer == nullptr || !_gps_buffer->valid()) {
|
||||
delete _gps_buffer;
|
||||
_gps_buffer = nullptr;
|
||||
printBufferAllocationFailed("GPS");
|
||||
return;
|
||||
}
|
||||
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -208,18 +205,19 @@ void EstimatorInterface::setGpsData(const gnssSample &gnss_sample)
|
||||
#if defined(CONFIG_EKF2_BAROMETER)
|
||||
void EstimatorInterface::setBaroData(const baroSample &baro_sample)
|
||||
{
|
||||
if (!_initialised) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Allocate the required buffer size if not previously done
|
||||
if (_baro_buffer == nullptr) {
|
||||
_baro_buffer = new RingBuffer<baroSample>(_obs_buffer_length);
|
||||
if (_obs_buffer_length > 0) {
|
||||
_baro_buffer = new RingBuffer<baroSample>(_obs_buffer_length);
|
||||
|
||||
if (_baro_buffer == nullptr || !_baro_buffer->valid()) {
|
||||
delete _baro_buffer;
|
||||
_baro_buffer = nullptr;
|
||||
printBufferAllocationFailed("baro");
|
||||
if (_baro_buffer == nullptr || !_baro_buffer->valid()) {
|
||||
delete _baro_buffer;
|
||||
_baro_buffer = nullptr;
|
||||
printBufferAllocationFailed("baro");
|
||||
return;
|
||||
}
|
||||
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -247,18 +245,19 @@ void EstimatorInterface::setBaroData(const baroSample &baro_sample)
|
||||
#if defined(CONFIG_EKF2_AIRSPEED)
|
||||
void EstimatorInterface::setAirspeedData(const airspeedSample &airspeed_sample)
|
||||
{
|
||||
if (!_initialised) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Allocate the required buffer size if not previously done
|
||||
if (_airspeed_buffer == nullptr) {
|
||||
_airspeed_buffer = new RingBuffer<airspeedSample>(_obs_buffer_length);
|
||||
if (_obs_buffer_length > 0) {
|
||||
_airspeed_buffer = new RingBuffer<airspeedSample>(_obs_buffer_length);
|
||||
|
||||
if (_airspeed_buffer == nullptr || !_airspeed_buffer->valid()) {
|
||||
delete _airspeed_buffer;
|
||||
_airspeed_buffer = nullptr;
|
||||
printBufferAllocationFailed("airspeed");
|
||||
if (_airspeed_buffer == nullptr || !_airspeed_buffer->valid()) {
|
||||
delete _airspeed_buffer;
|
||||
_airspeed_buffer = nullptr;
|
||||
printBufferAllocationFailed("airspeed");
|
||||
return;
|
||||
}
|
||||
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -285,18 +284,19 @@ void EstimatorInterface::setAirspeedData(const airspeedSample &airspeed_sample)
|
||||
#if defined(CONFIG_EKF2_RANGE_FINDER)
|
||||
void EstimatorInterface::setRangeData(const sensor::rangeSample &range_sample)
|
||||
{
|
||||
if (!_initialised) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Allocate the required buffer size if not previously done
|
||||
if (_range_buffer == nullptr) {
|
||||
_range_buffer = new RingBuffer<sensor::rangeSample>(_obs_buffer_length);
|
||||
if (_obs_buffer_length > 0) {
|
||||
_range_buffer = new RingBuffer<sensor::rangeSample>(_obs_buffer_length);
|
||||
|
||||
if (_range_buffer == nullptr || !_range_buffer->valid()) {
|
||||
delete _range_buffer;
|
||||
_range_buffer = nullptr;
|
||||
printBufferAllocationFailed("range");
|
||||
if (_range_buffer == nullptr || !_range_buffer->valid()) {
|
||||
delete _range_buffer;
|
||||
_range_buffer = nullptr;
|
||||
printBufferAllocationFailed("range");
|
||||
return;
|
||||
}
|
||||
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -324,18 +324,19 @@ void EstimatorInterface::setRangeData(const sensor::rangeSample &range_sample)
|
||||
#if defined(CONFIG_EKF2_OPTICAL_FLOW)
|
||||
void EstimatorInterface::setOpticalFlowData(const flowSample &flow)
|
||||
{
|
||||
if (!_initialised) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Allocate the required buffer size if not previously done
|
||||
if (_flow_buffer == nullptr) {
|
||||
_flow_buffer = new RingBuffer<flowSample>(_imu_buffer_length);
|
||||
if (_imu_buffer_length > 0) {
|
||||
_flow_buffer = new RingBuffer<flowSample>(_imu_buffer_length);
|
||||
|
||||
if (_flow_buffer == nullptr || !_flow_buffer->valid()) {
|
||||
delete _flow_buffer;
|
||||
_flow_buffer = nullptr;
|
||||
printBufferAllocationFailed("flow");
|
||||
if (_flow_buffer == nullptr || !_flow_buffer->valid()) {
|
||||
delete _flow_buffer;
|
||||
_flow_buffer = nullptr;
|
||||
printBufferAllocationFailed("flow");
|
||||
return;
|
||||
}
|
||||
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -362,18 +363,19 @@ void EstimatorInterface::setOpticalFlowData(const flowSample &flow)
|
||||
#if defined(CONFIG_EKF2_EXTERNAL_VISION)
|
||||
void EstimatorInterface::setExtVisionData(const extVisionSample &evdata)
|
||||
{
|
||||
if (!_initialised) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Allocate the required buffer size if not previously done
|
||||
if (_ext_vision_buffer == nullptr) {
|
||||
_ext_vision_buffer = new RingBuffer<extVisionSample>(_obs_buffer_length);
|
||||
if (_obs_buffer_length > 0) {
|
||||
_ext_vision_buffer = new RingBuffer<extVisionSample>(_obs_buffer_length);
|
||||
|
||||
if (_ext_vision_buffer == nullptr || !_ext_vision_buffer->valid()) {
|
||||
delete _ext_vision_buffer;
|
||||
_ext_vision_buffer = nullptr;
|
||||
printBufferAllocationFailed("vision");
|
||||
if (_ext_vision_buffer == nullptr || !_ext_vision_buffer->valid()) {
|
||||
delete _ext_vision_buffer;
|
||||
_ext_vision_buffer = nullptr;
|
||||
printBufferAllocationFailed("vision");
|
||||
return;
|
||||
}
|
||||
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -402,18 +404,19 @@ void EstimatorInterface::setExtVisionData(const extVisionSample &evdata)
|
||||
#if defined(CONFIG_EKF2_AUXVEL)
|
||||
void EstimatorInterface::setAuxVelData(const auxVelSample &auxvel_sample)
|
||||
{
|
||||
if (!_initialised) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Allocate the required buffer size if not previously done
|
||||
if (_auxvel_buffer == nullptr) {
|
||||
_auxvel_buffer = new RingBuffer<auxVelSample>(_obs_buffer_length);
|
||||
if (_obs_buffer_length > 0) {
|
||||
_auxvel_buffer = new RingBuffer<auxVelSample>(_obs_buffer_length);
|
||||
|
||||
if (_auxvel_buffer == nullptr || !_auxvel_buffer->valid()) {
|
||||
delete _auxvel_buffer;
|
||||
_auxvel_buffer = nullptr;
|
||||
printBufferAllocationFailed("aux vel");
|
||||
if (_auxvel_buffer == nullptr || !_auxvel_buffer->valid()) {
|
||||
delete _auxvel_buffer;
|
||||
_auxvel_buffer = nullptr;
|
||||
printBufferAllocationFailed("aux vel");
|
||||
return;
|
||||
}
|
||||
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -439,18 +442,19 @@ void EstimatorInterface::setAuxVelData(const auxVelSample &auxvel_sample)
|
||||
|
||||
void EstimatorInterface::setSystemFlagData(const systemFlagUpdate &system_flags)
|
||||
{
|
||||
if (!_initialised) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Allocate the required buffer size if not previously done
|
||||
if (_system_flag_buffer == nullptr) {
|
||||
_system_flag_buffer = new RingBuffer<systemFlagUpdate>(_obs_buffer_length);
|
||||
if (_obs_buffer_length > 0) {
|
||||
_system_flag_buffer = new RingBuffer<systemFlagUpdate>(_obs_buffer_length);
|
||||
|
||||
if (_system_flag_buffer == nullptr || !_system_flag_buffer->valid()) {
|
||||
delete _system_flag_buffer;
|
||||
_system_flag_buffer = nullptr;
|
||||
printBufferAllocationFailed("system flag");
|
||||
if (_system_flag_buffer == nullptr || !_system_flag_buffer->valid()) {
|
||||
delete _system_flag_buffer;
|
||||
_system_flag_buffer = nullptr;
|
||||
printBufferAllocationFailed("system flag");
|
||||
return;
|
||||
}
|
||||
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -477,16 +481,21 @@ void EstimatorInterface::setDragData(const imuSample &imu)
|
||||
{
|
||||
// down-sample the drag specific force data by accumulating and calculating the mean when
|
||||
// sufficient samples have been collected
|
||||
if (_params.drag_ctrl > 0) {
|
||||
if (_params.drag_ctrl) {
|
||||
|
||||
// Allocate the required buffer size if not previously done
|
||||
if (_drag_buffer == nullptr) {
|
||||
_drag_buffer = new RingBuffer<dragSample>(_obs_buffer_length);
|
||||
if (_obs_buffer_length > 0) {
|
||||
_drag_buffer = new RingBuffer<dragSample>(_obs_buffer_length);
|
||||
|
||||
if (_drag_buffer == nullptr || !_drag_buffer->valid()) {
|
||||
delete _drag_buffer;
|
||||
_drag_buffer = nullptr;
|
||||
printBufferAllocationFailed("drag");
|
||||
if (_drag_buffer == nullptr || !_drag_buffer->valid()) {
|
||||
delete _drag_buffer;
|
||||
_drag_buffer = nullptr;
|
||||
printBufferAllocationFailed("drag");
|
||||
return;
|
||||
}
|
||||
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -536,7 +545,7 @@ void EstimatorInterface::setDragData(const imuSample &imu)
|
||||
}
|
||||
#endif // CONFIG_EKF2_DRAG_FUSION
|
||||
|
||||
bool EstimatorInterface::initialise_interface(uint64_t timestamp)
|
||||
bool EstimatorInterface::initialise_interface()
|
||||
{
|
||||
const float filter_update_period_ms = _params.filter_update_interval_us / 1000.f;
|
||||
|
||||
@@ -560,11 +569,6 @@ bool EstimatorInterface::initialise_interface(uint64_t timestamp)
|
||||
return false;
|
||||
}
|
||||
|
||||
_time_delayed_us = timestamp;
|
||||
_time_latest_us = timestamp;
|
||||
|
||||
_fault_status.value = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -318,9 +318,7 @@ public:
|
||||
protected:
|
||||
|
||||
EstimatorInterface() = default;
|
||||
virtual ~EstimatorInterface();
|
||||
|
||||
virtual bool init(uint64_t timestamp) = 0;
|
||||
~EstimatorInterface();
|
||||
|
||||
parameters _params{}; // filter parameters
|
||||
|
||||
@@ -346,6 +344,11 @@ protected:
|
||||
uint64_t _time_delayed_us{0}; // captures the imu sample on the delayed time horizon
|
||||
uint64_t _time_latest_us{0}; // imu sample capturing the newest imu data
|
||||
|
||||
// Variables used by the initial filter alignment
|
||||
bool _is_first_imu_sample{true};
|
||||
AlphaFilter<Vector3f> _accel_lpf{0.1f}; ///< filtered accelerometer measurement used to align tilt (m/s/s)
|
||||
AlphaFilter<Vector3f> _gyro_lpf{0.1f}; ///< filtered gyro measurement used for alignment excessive movement check (rad/sec)
|
||||
|
||||
OutputPredictor _output_predictor{};
|
||||
|
||||
#if defined(CONFIG_EKF2_AIRSPEED)
|
||||
@@ -378,7 +381,6 @@ protected:
|
||||
float _air_density{atmosphere::kAirDensitySeaLevelStandardAtmos}; // air density (kg/m**3)
|
||||
|
||||
bool _imu_updated{false}; // true if the ekf should update (completed downsampling process)
|
||||
bool _initialised{false}; // true if the ekf interface instance (data buffering) is initialized
|
||||
|
||||
// Variables used to publish the WGS-84 location of the EKF local NED origin
|
||||
MapProjection _local_origin_lat_lon{};
|
||||
@@ -449,7 +451,7 @@ protected:
|
||||
fault_status_u _fault_status{};
|
||||
|
||||
// allocate data buffers and initialize interface variables
|
||||
bool initialise_interface(uint64_t timestamp);
|
||||
bool initialise_interface();
|
||||
|
||||
#if defined(CONFIG_EKF2_MAGNETOMETER)
|
||||
uint64_t _wmm_mag_time_last_checked {0}; // time WMM update last checked by mag control
|
||||
|
||||
@@ -833,6 +833,14 @@ void EKF2::Run()
|
||||
#if defined(CONFIG_EKF2_MAGNETOMETER)
|
||||
UpdateMagCalibration(now);
|
||||
#endif // CONFIG_EKF2_MAGNETOMETER
|
||||
|
||||
} else {
|
||||
// if filter not initialized
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
// publish ekf2_timestamps
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Timestamp,state[0],state[1],state[2],state[3],state[4],state[5],state[6],state[7],state[8],state[9],state[10],state[11],state[12],state[13],state[14],state[15],state[16],state[17],state[18],state[19],state[20],state[21],state[22],state[23],variance[0],variance[1],variance[2],variance[3],variance[4],variance[5],variance[6],variance[7],variance[8],variance[9],variance[10],variance[11],variance[12],variance[13],variance[14],variance[15],variance[16],variance[17],variance[18],variance[19],variance[20],variance[21],variance[22],variance[23]
|
||||
10000,1,-0.0094,-0.01,-3.2e-06,0.00023,7.3e-05,-0.011,0,0,-0.00045,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.1,0.01,0.01,8.1e-05,25,25,10,1e+02,1e+02,1e+02,0.01,0.01,0.01,0.04,0.04,0.04,0.0025,0.0025,0.0025,0.0025,0.0025,0.0025,1,1,0.032
|
||||
90000,1,-0.0094,-0.011,6.9e-05,-0.00047,0.0026,-0.026,0,0,-0.0023,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.1,0.01,0.01,0.00036,25,25,10,1e+02,1e+02,1e+02,0.01,0.01,0.01,0.04,0.04,0.04,0.0025,0.0025,0.0025,0.0025,0.0025,0.0025,1,1,0.058
|
||||
10000,1,-0.0094,-0.01,-3.2e-06,0.00023,7.3e-05,-0.011,0,0,-0.00045,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.01,0.01,8.1e-05,25,25,10,1e+02,1e+02,1e+02,0.01,0.01,0.01,0.04,0.04,0.04,0.0025,0.0025,0.0025,0.0025,0.0025,0.0025,1,1,0.032
|
||||
90000,1,-0.0094,-0.011,6.9e-05,-0.00047,0.0026,-0.026,0,0,-0.0023,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.01,0.01,0.00036,25,25,10,1e+02,1e+02,1e+02,0.01,0.01,0.01,0.04,0.04,0.04,0.0025,0.0025,0.0025,0.0025,0.0025,0.0025,1,1,0.058
|
||||
190000,1,-0.0094,-0.011,2.8e-05,6.9e-05,0.004,-0.041,0,0,-1.2e+02,-3e-11,-2.6e-12,5.6e-13,0,0,-5e-08,0,0,0,0,0,0,0,0,-1.2e+02,0.011,0.011,0.00084,25,25,10,1e+02,1e+02,1,0.01,0.01,0.01,0.04,0.04,0.04,0.0025,0.0025,0.0025,0.0025,0.0025,0.0025,1,1,0.082
|
||||
290000,1,-0.0094,-0.011,6.3e-05,0.001,0.0064,-0.053,0,0,-1.2e+02,9.1e-10,1e-10,-1.7e-11,0,0,-2.5e-06,0,0,0,0,0,0,0,0,-1.2e+02,0.012,0.012,0.00075,25,25,9.6,0.37,0.37,0.41,0.01,0.01,0.0049,0.04,0.04,0.04,0.0025,0.0025,0.0025,0.0025,0.0025,0.0025,1,1,0.11
|
||||
390000,1,-0.0094,-0.011,7e-05,0.0024,0.0083,-0.059,0,0,-1.2e+02,-1.1e-08,2.8e-09,2.9e-10,0,0,-1.5e-05,0,0,0,0,0,0,0,0,-1.2e+02,0.012,0.012,0.0012,25,25,8.1,0.97,0.97,0.32,0.01,0.01,0.0049,0.04,0.04,0.04,0.0025,0.0025,0.0025,0.0025,0.0025,0.0025,1,1,0.13
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
Timestamp,state[0],state[1],state[2],state[3],state[4],state[5],state[6],state[7],state[8],state[9],state[10],state[11],state[12],state[13],state[14],state[15],state[16],state[17],state[18],state[19],state[20],state[21],state[22],state[23],variance[0],variance[1],variance[2],variance[3],variance[4],variance[5],variance[6],variance[7],variance[8],variance[9],variance[10],variance[11],variance[12],variance[13],variance[14],variance[15],variance[16],variance[17],variance[18],variance[19],variance[20],variance[21],variance[22],variance[23]
|
||||
10000,1,-0.011,-0.01,0.00023,0.00033,-0.00013,-0.01,0,0,-0.00042,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.1,0.01,0.01,8.1e-05,25,25,10,1e+02,1e+02,1e+02,0.01,0.01,0.01,0.04,0.04,0.04,0.0025,0.0025,0.0025,0.0025,0.0025,0.0025,1,1,0.032
|
||||
90000,1,-0.011,-0.01,0.00033,-0.001,-0.0031,-0.024,0,0,-0.0021,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.1,0.01,0.01,0.00036,25,25,10,1e+02,1e+02,1e+02,0.01,0.01,0.01,0.04,0.04,0.04,0.0025,0.0025,0.0025,0.0025,0.0025,0.0025,1,1,0.058
|
||||
10000,1,-0.011,-0.01,0.00023,0.00033,-0.00013,-0.01,0,0,-0.00042,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.01,0.01,8.1e-05,25,25,10,1e+02,1e+02,1e+02,0.01,0.01,0.01,0.04,0.04,0.04,0.0025,0.0025,0.0025,0.0025,0.0025,0.0025,1,1,0.032
|
||||
90000,1,-0.011,-0.01,0.00033,-0.001,-0.0031,-0.024,0,0,-0.0021,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.01,0.01,0.00036,25,25,10,1e+02,1e+02,1e+02,0.01,0.01,0.01,0.04,0.04,0.04,0.0025,0.0025,0.0025,0.0025,0.0025,0.0025,1,1,0.058
|
||||
190000,1,-0.012,-0.011,0.00044,-0.0023,-0.003,-0.035,0,0,-4.9e+02,1.6e-09,-1.4e-09,-6.4e-11,0,0,-3.2e-06,0,0,0,0,0,0,0,0,-4.9e+02,0.011,0.011,0.00084,25,25,10,1e+02,1e+02,1,0.01,0.01,0.01,0.04,0.04,0.04,0.0025,0.0025,0.0025,0.0025,0.0025,0.0025,1,1,0.082
|
||||
290000,1,-0.012,-0.011,0.00044,-0.0033,-0.0044,-0.038,0,0,-4.9e+02,7.3e-09,-1.1e-08,-3.9e-10,0,0,-2e-05,0,0,0,0,0,0,0,0,-4.9e+02,0.012,0.012,0.00075,25,25,9.6,0.37,0.37,0.41,0.01,0.01,0.0049,0.04,0.04,0.04,0.0025,0.0025,0.0025,0.0025,0.0025,0.0025,1,1,0.11
|
||||
390000,1,-0.012,-0.011,0.00049,-0.0025,-0.0059,-0.05,0,0,-4.9e+02,-2.1e-10,-1.4e-08,-3.2e-10,0,0,-1.4e-05,0,0,0,0,0,0,0,0,-4.9e+02,0.012,0.012,0.0012,25,25,8.1,0.97,0.97,0.32,0.01,0.01,0.0049,0.04,0.04,0.04,0.0025,0.0025,0.0025,0.0025,0.0025,0.0025,1,1,0.13
|
||||
|
||||
|
@@ -59,7 +59,7 @@ public:
|
||||
void SetUp() override
|
||||
{
|
||||
// run briefly to init, then manually set in air and at rest (default for a real vehicle)
|
||||
_ekf->init(0);
|
||||
_ekf->reset();
|
||||
_sensor_simulator.runSeconds(0.1);
|
||||
_ekf->set_in_air_status(false);
|
||||
_ekf->set_vehicle_at_rest(true);
|
||||
|
||||
@@ -62,7 +62,7 @@ public:
|
||||
void SetUp() override
|
||||
{
|
||||
// run briefly to init, then manually set in air and at rest (default for a real vehicle)
|
||||
_ekf->init(0);
|
||||
_ekf->reset();
|
||||
_sensor_simulator.runSeconds(0.1);
|
||||
_ekf->set_in_air_status(false);
|
||||
_ekf->set_vehicle_at_rest(true);
|
||||
|
||||
@@ -54,7 +54,7 @@ public:
|
||||
void SetUp() override
|
||||
{
|
||||
// run briefly to init, then manually set in air and at rest (default for a real vehicle)
|
||||
_ekf->init(0);
|
||||
_ekf->reset();
|
||||
_sensor_simulator.runSeconds(0.1);
|
||||
_ekf->set_in_air_status(false);
|
||||
_ekf->set_vehicle_at_rest(true);
|
||||
|
||||
@@ -59,7 +59,7 @@ public:
|
||||
void SetUp() override
|
||||
{
|
||||
// run briefly to init, then manually set in air and at rest (default for a real vehicle)
|
||||
_ekf->init(0);
|
||||
_ekf->reset();
|
||||
_ekf->set_is_fixed_wing(false);
|
||||
_ekf->set_in_air_status(false);
|
||||
_ekf->set_vehicle_at_rest(true);
|
||||
|
||||
@@ -62,7 +62,7 @@ public:
|
||||
void SetUp() override
|
||||
{
|
||||
// Init, then manually set in air and at rest (default for a real vehicle)
|
||||
_ekf->init(0);
|
||||
_ekf->reset();
|
||||
_ekf->set_in_air_status(false);
|
||||
_ekf->set_vehicle_at_rest(true);
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ public:
|
||||
void SetUp() override
|
||||
{
|
||||
// run briefly to init, then manually set in air and at rest (default for a real vehicle)
|
||||
_ekf->init(0);
|
||||
_ekf->reset();
|
||||
_sensor_simulator.runSeconds(0.1);
|
||||
_ekf->set_in_air_status(false);
|
||||
_ekf->set_vehicle_at_rest(true);
|
||||
|
||||
@@ -65,7 +65,7 @@ public:
|
||||
_ekf->set_optical_flow_limits(max_flow_rate, min_ground_distance, max_ground_distance);
|
||||
|
||||
// run briefly to init, then manually set in air and at rest (default for a real vehicle)
|
||||
_ekf->init(0);
|
||||
_ekf->reset();
|
||||
_sensor_simulator.runSeconds(0.1);
|
||||
_ekf->set_in_air_status(false);
|
||||
_ekf->set_vehicle_at_rest(true);
|
||||
|
||||
@@ -60,7 +60,7 @@ public:
|
||||
void SetUp() override
|
||||
{
|
||||
// run briefly to init, then manually set in air and at rest (default for a real vehicle)
|
||||
_ekf->init(0);
|
||||
_ekf->reset();
|
||||
_sensor_simulator.runSeconds(0.1);
|
||||
_ekf->set_in_air_status(false);
|
||||
_ekf->set_vehicle_at_rest(true);
|
||||
|
||||
@@ -62,7 +62,7 @@ public:
|
||||
void SetUp() override
|
||||
{
|
||||
// Init, then manually set in air and at rest (default for a real vehicle)
|
||||
_ekf->init(0);
|
||||
_ekf->reset();
|
||||
_ekf->set_in_air_status(false);
|
||||
_ekf->set_vehicle_at_rest(true);
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ public:
|
||||
void SetUp() override
|
||||
{
|
||||
// run briefly to init, then manually set in air and at rest (default for a real vehicle)
|
||||
_ekf->init(0);
|
||||
_ekf->reset();
|
||||
_sensor_simulator.runSeconds(0.1);
|
||||
_ekf->set_in_air_status(false);
|
||||
_ekf->set_vehicle_at_rest(true);
|
||||
|
||||
@@ -59,7 +59,7 @@ public:
|
||||
void SetUp() override
|
||||
{
|
||||
// Init, then manually set in air and at rest (default for a real vehicle)
|
||||
_ekf->init(0);
|
||||
_ekf->reset();
|
||||
_ekf->set_in_air_status(false);
|
||||
_ekf->set_vehicle_at_rest(true);
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ public:
|
||||
// Setup the Ekf with synthetic measurements
|
||||
void SetUp() override
|
||||
{
|
||||
_ekf->init(0);
|
||||
_ekf->reset();
|
||||
_ekf_wrapper.disableBaroHeightFusion();
|
||||
_ekf_wrapper.disableRangeHeightFusion();
|
||||
_sensor_simulator.runSeconds(0.1);
|
||||
|
||||
@@ -47,8 +47,7 @@ public:
|
||||
// Setup the Ekf with synthetic measurements
|
||||
void SetUp() override
|
||||
{
|
||||
_ekf.init(0);
|
||||
|
||||
_ekf.reset();
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
|
||||
@@ -56,7 +56,7 @@ public:
|
||||
void SetUp() override
|
||||
{
|
||||
// first init, then manually set in air and at rest (default for a real vehicle)
|
||||
_ekf->init(0);
|
||||
_ekf->reset();
|
||||
_ekf->set_in_air_status(false);
|
||||
_ekf->set_vehicle_at_rest(true);
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ public:
|
||||
void SetUp() override
|
||||
{
|
||||
// Init, then manually set in air and at rest (default for a real vehicle)
|
||||
_ekf->init(0);
|
||||
_ekf->reset();
|
||||
_ekf->set_in_air_status(false);
|
||||
_ekf->set_vehicle_at_rest(true);
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ public:
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
_ekf->init(0);
|
||||
_ekf->reset();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ public:
|
||||
void SetUp() override
|
||||
{
|
||||
// run briefly to init, then manually set in air and at rest (default for a real vehicle)
|
||||
_ekf->init(0);
|
||||
_ekf->reset();
|
||||
_sensor_simulator.runSeconds(0.1);
|
||||
_ekf->set_in_air_status(false);
|
||||
_ekf->set_vehicle_at_rest(true);
|
||||
|
||||
@@ -58,7 +58,7 @@ public:
|
||||
void SetUp() override
|
||||
{
|
||||
// run briefly to init, then manually set in air and at rest (default for a real vehicle)
|
||||
_ekf->init(0);
|
||||
_ekf->reset();
|
||||
_sensor_simulator.runSeconds(0.1);
|
||||
_ekf->set_in_air_status(false);
|
||||
_ekf->set_vehicle_at_rest(true);
|
||||
|
||||
@@ -327,9 +327,9 @@ void Sih::generate_fw_aerodynamics()
|
||||
{
|
||||
_v_B = _C_IB.transpose() * _v_I; // velocity in body frame [m/s]
|
||||
float altitude = _H0 - _p_I(2);
|
||||
_wing_l.update_aero(_v_B, _w_B, altitude, _u[0]*FLAP_MAX);
|
||||
_wing_r.update_aero(_v_B, _w_B, altitude, -_u[0]*FLAP_MAX);
|
||||
_tailplane.update_aero(_v_B, _w_B, altitude, _u[1]*FLAP_MAX, _T_MAX * _u[3]);
|
||||
_wing_l.update_aero(_v_B, _w_B, altitude, -_u[0]*FLAP_MAX);
|
||||
_wing_r.update_aero(_v_B, _w_B, altitude, _u[0]*FLAP_MAX);
|
||||
_tailplane.update_aero(_v_B, _w_B, altitude, -_u[1]*FLAP_MAX, _T_MAX * _u[3]);
|
||||
_fin.update_aero(_v_B, _w_B, altitude, _u[2]*FLAP_MAX, _T_MAX * _u[3]);
|
||||
_fuselage.update_aero(_v_B, _w_B, altitude);
|
||||
|
||||
@@ -409,11 +409,9 @@ void Sih::equations_of_motion(const float dt)
|
||||
// integration: Euler forward
|
||||
_p_I = _p_I + _p_I_dot * dt;
|
||||
_v_I = _v_I + _v_I_dot * dt;
|
||||
Eulerf RPY = Eulerf(_q);
|
||||
RPY(0) = 0.0f; // no roll
|
||||
RPY(1) = radians(0.0f); // pitch slightly up if needed to get some lift
|
||||
_q = Quatf(RPY);
|
||||
_w_B.setZero();
|
||||
_q = _q * _dq;
|
||||
_q.normalize();
|
||||
_w_B = constrain(_w_B + _w_B_dot * dt, -6.0f * M_PI_F, 6.0f * M_PI_F);
|
||||
_grounded = true;
|
||||
}
|
||||
|
||||
@@ -450,8 +448,7 @@ void Sih::send_airspeed(const hrt_abstime &time_now_us)
|
||||
// TODO: send differential pressure instead?
|
||||
airspeed_s airspeed{};
|
||||
airspeed.timestamp_sample = time_now_us;
|
||||
// airspeed sensor is mounted along the negative Z axis since the vehicle is a tailsitter
|
||||
airspeed.true_airspeed_m_s = fmaxf(0.1f, -_v_B(2) + generate_wgn() * 0.2f);
|
||||
airspeed.true_airspeed_m_s = fmaxf(0.1f, _v_B.norm() + generate_wgn() * 0.2f);
|
||||
airspeed.indicated_airspeed_m_s = airspeed.true_airspeed_m_s * sqrtf(_wing_l.get_rho() / RHO);
|
||||
airspeed.air_temperature_celsius = NAN;
|
||||
airspeed.confidence = 0.7f;
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#
|
||||
############################################################################
|
||||
|
||||
if(${CMAKE_VERSION} VERSION_LESS "3.11")
|
||||
if(${CMAKE_VERSION} VERSION_LESS_EQUAL "3.15")
|
||||
message(WARNING "skipping uxrce_dds_client, Micro-XRCE-DDS-Client needs to be fixed to work with CMAKE_VERSION ${CMAKE_VERSION}")
|
||||
|
||||
else()
|
||||
|
||||
Reference in New Issue
Block a user