AP_L1_Control: added integrator to help xtrack error converge to zero

new param: NAVL1_XTRACK_I
    // @Description: Crosstrack error integrator gain. This gain is applied to the crosstrack error to ensure it converges to zero. Set to zero to disable. Smaller values converge slower, higher values will cause crosstrack error oscillation.
fixes https://github.com/diydrones/ardupilot/issues/2650

when param is changed the integrator is set to zero. This makes for easier tuning by seeing it converge to zero on each change.
This commit is contained in:
Tom Pittenger 2015-09-21 21:02:54 -07:00 committed by Andrew Tridgell
parent f7c73fbb13
commit 695efb8df3
2 changed files with 35 additions and 3 deletions

View File

@ -22,6 +22,13 @@ const AP_Param::GroupInfo AP_L1_Control::var_info[] PROGMEM = {
// @Increment: 0.05
AP_GROUPINFO("DAMPING", 1, AP_L1_Control, _L1_damping, 0.75f),
// @Param: XTRACK_I
// @DisplayName: L1 control crosstrack integrator gain
// @Description: Crosstrack error integrator gain. This gain is applied to the crosstrack error to ensure it converges to zero. Set to zero to disable. Smaller values converge slower, higher values will cause crosstrack error oscillation.
// @Range: 0 to 0.1
// @Increment: 0.01
AP_GROUPINFO("XTRACK_I", 2, AP_L1_Control, _L1_xtrack_i_gain, 0.02),
AP_GROUPEND
};
@ -179,7 +186,7 @@ void AP_L1_Control::update_waypoint(const struct Location &prev_WP, const struct
Vector2f A_air = location_diff(prev_WP, _current_loc);
// calculate distance to target track, for reporting
_crosstrack_error = AB % A_air;
_crosstrack_error = A_air % AB;
//Determine if the aircraft is behind a +-135 degree degree arc centred on WP A
//and further than L1 distance from WP A. Then use WP A as the L1 reference point
@ -202,11 +209,29 @@ void AP_L1_Control::update_waypoint(const struct Location &prev_WP, const struct
ltrackVel = _groundspeed_vector * AB; // Velocity along track
float Nu2 = atan2f(xtrackVel,ltrackVel);
//Calculate Nu1 angle (Angle to L1 reference point)
float xtrackErr = A_air % AB;
float sine_Nu1 = xtrackErr/max(_L1_dist, 0.1f);
float sine_Nu1 = _crosstrack_error/max(_L1_dist, 0.1f);
//Limit sine of Nu1 to provide a controlled track capture angle of 45 deg
sine_Nu1 = constrain_float(sine_Nu1, -0.7071f, 0.7071f);
float Nu1 = asinf(sine_Nu1);
// compute integral error component to converge to a crosstrack of zero when traveling
// straight but reset it when disabled or if it changes. That allows for much easier
// tuning by having it re-converge each time it changes.
if (_L1_xtrack_i_gain <= 0 || !is_equal(_L1_xtrack_i_gain, _L1_xtrack_i_gain_prev)) {
_L1_xtrack_i = 0;
_L1_xtrack_i_gain_prev = _L1_xtrack_i_gain;
} else if (fabsf(Nu1) < radians(5)) {
const float dt = 0.1f; // 10Hz
_L1_xtrack_i += Nu1 * _L1_xtrack_i_gain * dt;
// an AHRS_TRIM_X=0.1 will drift to about 0.08 so 0.1 is a good worst-case to clip at
_L1_xtrack_i = constrain_float(_L1_xtrack_i, -0.1f, 0.1f);
}
// to converge to zero we must push Nu1 harder
Nu1 += _L1_xtrack_i;
Nu = Nu1 + Nu2;
_nav_bearing = atan2f(AB.y, AB.x) + Nu1; // bearing (radians) from AC to L1 point
}

View File

@ -100,6 +100,13 @@ private:
// prevent indecision in waypoint tracking
void _prevent_indecision(float &Nu);
// integral feedback to correct crosstrack error. Used to ensure xtrack converges to zero.
// For tuning purposes it's helpful to clear the integrator when it changes so a _prev is used
float _L1_xtrack_i = 0;
AP_Float _L1_xtrack_i_gain;
float _L1_xtrack_i_gain_prev = 0;
};