Skip to content

Commit 4a5aa1e

Browse files
authored
Fix max-hagl restriction to position/altitude control (#23667)
* fix max-hagl restriction to position/altitude control * max hagl vel restriction in ManAcc position mode * use interpolate func, change naming * simplyfied vertical vel limitation * move velocity-constraint adjustment to StickAccelXY
1 parent 0d22905 commit 4a5aa1e

File tree

15 files changed

+90
-46
lines changed

15 files changed

+90
-46
lines changed

msg/versioned/VehicleLocalPosition.msg

+6-4
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,12 @@ float32 evv # Standard deviation of vertical velocity error, (metres/sec)
7777
bool dead_reckoning # True if this position is estimated through dead-reckoning
7878

7979
# estimator specified vehicle limits
80-
float32 vxy_max # maximum horizontal speed - set to 0 when limiting not required (meters/sec)
81-
float32 vz_max # maximum vertical speed - set to 0 when limiting not required (meters/sec)
82-
float32 hagl_min # minimum height above ground level - set to 0 when limiting not required (meters)
83-
float32 hagl_max # maximum height above ground level - set to 0 when limiting not required (meters)
80+
# set to INFINITY when limiting not required
81+
float32 vxy_max # maximum horizontal speed (meters/sec)
82+
float32 vz_max # maximum vertical speed (meters/sec)
83+
float32 hagl_min # minimum height above ground level (meters)
84+
float32 hagl_max_z # maximum height above ground level for z-control (meters)
85+
float32 hagl_max_xy # maximum height above ground level for xy-control (meters)
8486

8587
# TOPICS vehicle_local_position vehicle_local_position_groundtruth external_ins_local_position
8688
# TOPICS estimator_local_position

src/drivers/ins/vectornav/VectorNav.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,8 @@ void VectorNav::sensorCallback(VnUartPacket *packet)
328328
local_position.vxy_max = INFINITY;
329329
local_position.vz_max = INFINITY;
330330
local_position.hagl_min = INFINITY;
331-
local_position.hagl_max = INFINITY;
331+
local_position.hagl_max_z = INFINITY;
332+
local_position.hagl_max_xy = INFINITY;
332333

333334
local_position.unaided_heading = NAN;
334335
local_position.timestamp = hrt_absolute_time();

src/modules/ekf2/EKF/ekf.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -208,8 +208,9 @@ class Ekf final : public EstimatorInterface
208208
// vxy_max : Maximum ground relative horizontal speed (meters/sec). NaN when limiting is not needed.
209209
// vz_max : Maximum ground relative vertical speed (meters/sec). NaN when limiting is not needed.
210210
// hagl_min : Minimum height above ground (meters). NaN when limiting is not needed.
211-
// hagl_max : Maximum height above ground (meters). NaN when limiting is not needed.
212-
void get_ekf_ctrl_limits(float *vxy_max, float *vz_max, float *hagl_min, float *hagl_max) const;
211+
// hagl_max_z : Maximum height above ground for vertical altitude control (meters). NaN when limiting is not needed.
212+
// hagl_max_xy : Maximum height above ground for horizontal position control (meters). NaN when limiting is not needed.
213+
void get_ekf_ctrl_limits(float *vxy_max, float *vz_max, float *hagl_min, float *hagl_max_z, float *hagl_max_xy) const;
213214

214215
void resetGyroBias();
215216
void resetGyroBiasCov();

src/modules/ekf2/EKF/ekf_helper.cpp

+8-5
Original file line numberDiff line numberDiff line change
@@ -327,13 +327,15 @@ void Ekf::get_ekf_vel_accuracy(float *ekf_evh, float *ekf_evv) const
327327
*ekf_evv = sqrtf(P(State::vel.idx + 2, State::vel.idx + 2));
328328
}
329329

330-
void Ekf::get_ekf_ctrl_limits(float *vxy_max, float *vz_max, float *hagl_min, float *hagl_max) const
330+
void Ekf::get_ekf_ctrl_limits(float *vxy_max, float *vz_max, float *hagl_min, float *hagl_max_z,
331+
float *hagl_max_xy) const
331332
{
332333
// Do not require limiting by default
333334
*vxy_max = NAN;
334335
*vz_max = NAN;
335336
*hagl_min = NAN;
336-
*hagl_max = NAN;
337+
*hagl_max_z = NAN;
338+
*hagl_max_xy = NAN;
337339

338340
#if defined(CONFIG_EKF2_RANGE_FINDER)
339341
// Calculate range finder limits
@@ -347,7 +349,7 @@ void Ekf::get_ekf_ctrl_limits(float *vxy_max, float *vz_max, float *hagl_min, fl
347349

348350
if (relying_on_rangefinder) {
349351
*hagl_min = rangefinder_hagl_min;
350-
*hagl_max = rangefinder_hagl_max;
352+
*hagl_max_z = rangefinder_hagl_max;
351353
}
352354

353355
# if defined(CONFIG_EKF2_OPTICAL_FLOW)
@@ -370,11 +372,12 @@ void Ekf::get_ekf_ctrl_limits(float *vxy_max, float *vz_max, float *hagl_min, fl
370372
const float flow_constrained_height = math::constrain(getHagl(), flow_hagl_min, flow_hagl_max);
371373

372374
// Allow ground relative velocity to use 50% of available flow sensor range to allow for angular motion
373-
const float flow_vxy_max = 0.5f * _flow_max_rate * flow_constrained_height;
375+
float flow_vxy_max = 0.5f * _flow_max_rate * flow_constrained_height;
376+
flow_hagl_max = math::max(flow_hagl_max * 0.9f, flow_hagl_max - 1.0f);
374377

375378
*vxy_max = flow_vxy_max;
376379
*hagl_min = flow_hagl_min;
377-
*hagl_max = flow_hagl_max;
380+
*hagl_max_xy = flow_hagl_max;
378381
}
379382

380383
# endif // CONFIG_EKF2_OPTICAL_FLOW

src/modules/ekf2/EKF2.cpp

+7-3
Original file line numberDiff line numberDiff line change
@@ -1628,7 +1628,7 @@ void EKF2::PublishLocalPosition(const hrt_abstime &timestamp)
16281628
|| _ekf.control_status_flags().wind_dead_reckoning;
16291629

16301630
// get control limit information
1631-
_ekf.get_ekf_ctrl_limits(&lpos.vxy_max, &lpos.vz_max, &lpos.hagl_min, &lpos.hagl_max);
1631+
_ekf.get_ekf_ctrl_limits(&lpos.vxy_max, &lpos.vz_max, &lpos.hagl_min, &lpos.hagl_max_z, &lpos.hagl_max_xy);
16321632

16331633
// convert NaN to INFINITY
16341634
if (!PX4_ISFINITE(lpos.vxy_max)) {
@@ -1643,8 +1643,12 @@ void EKF2::PublishLocalPosition(const hrt_abstime &timestamp)
16431643
lpos.hagl_min = INFINITY;
16441644
}
16451645

1646-
if (!PX4_ISFINITE(lpos.hagl_max)) {
1647-
lpos.hagl_max = INFINITY;
1646+
if (!PX4_ISFINITE(lpos.hagl_max_z)) {
1647+
lpos.hagl_max_z = INFINITY;
1648+
}
1649+
1650+
if (!PX4_ISFINITE(lpos.hagl_max_xy)) {
1651+
lpos.hagl_max_xy = INFINITY;
16481652
}
16491653

16501654
// publish vehicle local position data

src/modules/flight_mode_manager/tasks/ManualAcceleration/FlightTaskManualAcceleration.cpp

+21
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,29 @@ bool FlightTaskManualAcceleration::activate(const trajectory_setpoint_s &last_se
5959

6060
bool FlightTaskManualAcceleration::update()
6161
{
62+
const vehicle_local_position_s vehicle_local_pos = _sub_vehicle_local_position.get();
63+
setMaxDistanceToGround(vehicle_local_pos.hagl_max_xy);
6264
bool ret = FlightTaskManualAltitudeSmoothVel::update();
6365

66+
float max_hagl_ratio = 0.0f;
67+
68+
if (PX4_ISFINITE(vehicle_local_pos.hagl_max_xy) && vehicle_local_pos.hagl_max_xy > FLT_EPSILON) {
69+
max_hagl_ratio = (vehicle_local_pos.dist_bottom) / vehicle_local_pos.hagl_max_xy;
70+
}
71+
72+
// limit horizontal velocity near max hagl to decrease chance of larger gound distance jumps
73+
static constexpr float factor_threshold = 0.8f; // threshold ratio of max_hagl
74+
static constexpr float min_vel = 2.f; // minimum max-velocity near max_hagl
75+
76+
if (max_hagl_ratio > factor_threshold) {
77+
max_hagl_ratio = math::min(max_hagl_ratio, 1.f);
78+
const float vxy_max = math::min(vehicle_local_pos.vxy_max, _param_mpc_vel_manual.get());
79+
_stick_acceleration_xy.setVelocityConstraint(interpolate(vxy_max, factor_threshold, min_vel, vxy_max, min_vel));
80+
81+
} else {
82+
_stick_acceleration_xy.setVelocityConstraint(math::min(_param_mpc_vel_manual.get(), vehicle_local_pos.vxy_max));
83+
}
84+
6485
_stick_acceleration_xy.generateSetpoints(_sticks.getPitchRollExpo(), _yaw, _yaw_setpoint, _position,
6586
_velocity_setpoint_feedback.xy(), _deltatime);
6687
_stick_acceleration_xy.getSetpoints(_position_setpoint, _velocity_setpoint, _acceleration_setpoint);

src/modules/flight_mode_manager/tasks/ManualAcceleration/FlightTaskManualAcceleration.hpp

+5
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,9 @@ class FlightTaskManualAcceleration : public FlightTaskManualAltitudeSmoothVel
5252

5353
StickAccelerationXY _stick_acceleration_xy{this};
5454
WeatherVane _weathervane{this}; /**< weathervane library, used to implement a yaw control law that turns the vehicle nose into the wind */
55+
56+
DEFINE_PARAMETERS_CUSTOM_PARENT(FlightTask,
57+
(ParamFloat<px4::params::MPC_VEL_MANUAL>) _param_mpc_vel_manual,
58+
(ParamFloat<px4::params::MPC_ACC_HOR>) _param_mpc_acc_hor
59+
)
5560
};

src/modules/flight_mode_manager/tasks/ManualAltitude/FlightTaskManualAltitude.cpp

+12-24
Original file line numberDiff line numberDiff line change
@@ -81,11 +81,8 @@ void FlightTaskManualAltitude::_updateConstraintsFromEstimator()
8181
_min_distance_to_ground = -INFINITY;
8282
}
8383

84-
if (PX4_ISFINITE(_sub_vehicle_local_position.get().hagl_max)) {
85-
_max_distance_to_ground = _sub_vehicle_local_position.get().hagl_max;
86-
87-
} else {
88-
_max_distance_to_ground = INFINITY;
84+
if (!PX4_ISFINITE(_max_distance_to_ground) && PX4_ISFINITE(_sub_vehicle_local_position.get().hagl_max_z)) {
85+
_max_distance_to_ground = _sub_vehicle_local_position.get().hagl_max_z;
8986
}
9087
}
9188

@@ -154,8 +151,6 @@ void FlightTaskManualAltitude::_updateAltitudeLock()
154151
if ((_param_mpc_alt_mode.get() == 1 || _terrain_hold) && PX4_ISFINITE(_dist_to_bottom)) {
155152
// terrain following
156153
_terrainFollowing(apply_brake, stopped);
157-
// respect maximum altitude
158-
_respectMaxAltitude();
159154

160155
} else {
161156
// normal mode where height is dependent on local frame
@@ -185,9 +180,10 @@ void FlightTaskManualAltitude::_updateAltitudeLock()
185180
// user demands velocity change
186181
_position_setpoint(2) = NAN;
187182
// ensure that maximum altitude is respected
188-
_respectMaxAltitude();
189183
}
190184
}
185+
186+
_respectMaxAltitude();
191187
}
192188

193189
void FlightTaskManualAltitude::_respectMinAltitude()
@@ -229,29 +225,20 @@ void FlightTaskManualAltitude::_respectMaxAltitude()
229225
{
230226
if (PX4_ISFINITE(_dist_to_bottom)) {
231227

232-
// if there is a valid maximum distance to ground, linearly increase speed limit with distance
233-
// below the maximum, preserving control loop vertical position error gain.
234-
// TODO: manipulate the velocity setpoint instead of tweaking the saturation of the controller
228+
float vel_constrained = _param_mpc_z_p.get() * (_max_distance_to_ground - _dist_to_bottom);
229+
235230
if (PX4_ISFINITE(_max_distance_to_ground)) {
236-
_constraints.speed_up = math::constrain(_param_mpc_z_p.get() * (_max_distance_to_ground - _dist_to_bottom),
237-
-_param_mpc_z_vel_max_dn.get(), _param_mpc_z_vel_max_up.get());
231+
_constraints.speed_up = math::constrain(vel_constrained, -_param_mpc_z_vel_max_dn.get(), _param_mpc_z_vel_max_up.get());
238232

239233
} else {
240234
_constraints.speed_up = _param_mpc_z_vel_max_up.get();
241235
}
242236

243-
// if distance to bottom exceeded maximum distance, slowly approach maximum distance
244-
if (_dist_to_bottom > _max_distance_to_ground) {
245-
// difference between current distance to ground and maximum distance to ground
246-
const float delta_distance_to_max = _dist_to_bottom - _max_distance_to_ground;
247-
// set position setpoint to maximum distance to ground
248-
_position_setpoint(2) = _position(2) + delta_distance_to_max;
249-
// limit speed downwards to 0.7m/s
250-
_constraints.speed_down = math::min(_param_mpc_z_vel_max_dn.get(), 0.7f);
251-
252-
} else {
253-
_constraints.speed_down = _param_mpc_z_vel_max_dn.get();
237+
if (_dist_to_bottom > _max_distance_to_ground && !(_sticks.getThrottleZeroCenteredExpo() < FLT_EPSILON)) {
238+
_velocity_setpoint(2) = math::constrain(-vel_constrained, 0.f, _param_mpc_z_vel_max_dn.get());
254239
}
240+
241+
_constraints.speed_down = _param_mpc_z_vel_max_dn.get();
255242
}
256243
}
257244

@@ -306,6 +293,7 @@ bool FlightTaskManualAltitude::update()
306293
_scaleSticks();
307294
_updateSetpoints();
308295
_constraints.want_takeoff = _checkTakeoff();
296+
_max_distance_to_ground = INFINITY;
309297

310298
return ret;
311299
}

src/modules/flight_mode_manager/tasks/ManualAltitude/FlightTaskManualAltitude.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ class FlightTaskManualAltitude : public FlightTask
5353
bool activate(const trajectory_setpoint_s &last_setpoint) override;
5454
bool updateInitialize() override;
5555
bool update() override;
56+
void setMaxDistanceToGround(float max_distance) { _max_distance_to_ground = max_distance; }
5657

5758
protected:
5859
void _ekfResetHandlerHeading(float delta_psi) override; /**< adjust heading setpoint in case of EKF reset event */

src/modules/flight_mode_manager/tasks/Utility/StickAccelerationXY.cpp

+13-1
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,20 @@ void StickAccelerationXY::resetAcceleration(const matrix::Vector2f &acceleration
7373
void StickAccelerationXY::generateSetpoints(Vector2f stick_xy, const float yaw, const float yaw_sp, const Vector3f &pos,
7474
const matrix::Vector2f &vel_sp_feedback, const float dt)
7575
{
76+
// gradually adjust velocity constraint because good tracking is required for the drag estimation
77+
if (fabsf(_targeted_velocity_constraint - _current_velocity_constraint) > 0.1f) {
78+
if (!PX4_ISFINITE(_current_velocity_constraint) || !PX4_ISFINITE(_targeted_velocity_constraint)) {
79+
_current_velocity_constraint = _targeted_velocity_constraint;
80+
81+
} else {
82+
_current_velocity_constraint = math::constrain(_targeted_velocity_constraint,
83+
_current_velocity_constraint - dt * _param_mpc_acc_hor.get(),
84+
_current_velocity_constraint + dt * _param_mpc_acc_hor.get());
85+
}
86+
}
87+
7688
// maximum commanded velocity can be constrained dynamically
77-
const float velocity_sc = fminf(_param_mpc_vel_manual.get(), _velocity_constraint);
89+
const float velocity_sc = fminf(_param_mpc_vel_manual.get(), _current_velocity_constraint);
7890
Vector2f velocity_scale(velocity_sc, velocity_sc);
7991
// maximum commanded acceleration is scaled down with velocity
8092
const float acceleration_sc = _param_mpc_acc_hor.get() * (velocity_sc / _param_mpc_vel_manual.get());

src/modules/flight_mode_manager/tasks/Utility/StickAccelerationXY.hpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ class StickAccelerationXY : public ModuleParams
6363
void getSetpoints(matrix::Vector3f &pos_sp, matrix::Vector3f &vel_sp, matrix::Vector3f &acc_sp);
6464
float getMaxAcceleration() { return _param_mpc_acc_hor.get(); };
6565
float getMaxJerk() { return _param_mpc_jerk_max.get(); };
66-
void setVelocityConstraint(float vel) { _velocity_constraint = fmaxf(vel, FLT_EPSILON); };
66+
void setVelocityConstraint(float vel) { _targeted_velocity_constraint = fmaxf(vel, FLT_EPSILON); };
67+
float getVelocityConstraint() { return _current_velocity_constraint; };
6768

6869
private:
6970
CollisionPrevention _collision_prevention{this};
@@ -85,7 +86,8 @@ class StickAccelerationXY : public ModuleParams
8586
matrix::Vector2f _acceleration_setpoint;
8687
matrix::Vector2f _acceleration_setpoint_prev;
8788

88-
float _velocity_constraint{INFINITY};
89+
float _targeted_velocity_constraint{INFINITY};
90+
float _current_velocity_constraint{INFINITY};
8991

9092
DEFINE_PARAMETERS(
9193
(ParamFloat<px4::params::MPC_VEL_MANUAL>) _param_mpc_vel_manual,

src/modules/local_position_estimator/BlockLocalPositionEstimator.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -643,7 +643,8 @@ void BlockLocalPositionEstimator::publishLocalPos()
643643
_pub_lpos.get().vxy_max = INFINITY;
644644
_pub_lpos.get().vz_max = INFINITY;
645645
_pub_lpos.get().hagl_min = INFINITY;
646-
_pub_lpos.get().hagl_max = INFINITY;
646+
_pub_lpos.get().hagl_max_z = INFINITY;
647+
_pub_lpos.get().hagl_max_xy = INFINITY;
647648
_pub_lpos.get().timestamp = hrt_absolute_time();;
648649
_pub_lpos.update();
649650
}

src/modules/mavlink/mavlink_receiver.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -2738,7 +2738,8 @@ MavlinkReceiver::handle_message_hil_state_quaternion(mavlink_message_t *msg)
27382738
hil_local_pos.vxy_max = INFINITY;
27392739
hil_local_pos.vz_max = INFINITY;
27402740
hil_local_pos.hagl_min = INFINITY;
2741-
hil_local_pos.hagl_max = INFINITY;
2741+
hil_local_pos.hagl_max_z = INFINITY;
2742+
hil_local_pos.hagl_max_xy = INFINITY;
27422743
hil_local_pos.timestamp = hrt_absolute_time();
27432744
_local_pos_pub.publish(hil_local_pos);
27442745
}

src/modules/navigator/mission_block.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -1026,7 +1026,8 @@ void MissionBlock::updateMaxHaglFailsafe()
10261026
const float target_alt = _navigator->get_position_setpoint_triplet()->current.alt;
10271027

10281028
if (_navigator->get_global_position()->terrain_alt_valid
1029-
&& ((target_alt - _navigator->get_global_position()->terrain_alt) > _navigator->get_local_position()->hagl_max)) {
1029+
&& ((target_alt - _navigator->get_global_position()->terrain_alt)
1030+
> math::min(_navigator->get_local_position()->hagl_max_z, _navigator->get_local_position()->hagl_max_xy))) {
10301031
// Handle case where the altitude setpoint is above the maximum HAGL (height above ground level)
10311032
mavlink_log_info(_navigator->get_mavlink_log_pub(), "Target altitude higher than max HAGL\t");
10321033
events::send(events::ID("navigator_fail_max_hagl"), events::Log::Error, "Target altitude higher than max HAGL");

src/modules/simulation/simulator_mavlink/SimulatorMavlink.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -607,7 +607,8 @@ void SimulatorMavlink::handle_message_hil_state_quaternion(const mavlink_message
607607
hil_lpos.vxy_max = std::numeric_limits<float>::infinity();
608608
hil_lpos.vz_max = std::numeric_limits<float>::infinity();
609609
hil_lpos.hagl_min = std::numeric_limits<float>::infinity();
610-
hil_lpos.hagl_max = std::numeric_limits<float>::infinity();
610+
hil_lpos.hagl_max_z = std::numeric_limits<float>::infinity();
611+
hil_lpos.hagl_max_xy = std::numeric_limits<float>::infinity();
611612

612613
// always publish ground truth attitude message
613614
_lpos_ground_truth_pub.publish(hil_lpos);

0 commit comments

Comments
 (0)