Skip to content

Commit 1e09812

Browse files
lthallpeterbarker
authored andcommitted
AP_Math: Control: Add limit_accel_corner_xy
1 parent aba26e9 commit 1e09812

File tree

2 files changed

+49
-24
lines changed

2 files changed

+49
-24
lines changed

libraries/AP_Math/control.cpp

Lines changed: 41 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -236,30 +236,7 @@ void shape_vel_accel_xy(const Vector2f& vel_desired, const Vector2f& accel_desir
236236
// acceleration to correct velocity
237237
Vector2f accel_target = sqrt_controller(vel_error, KPa, jerk_max, dt);
238238

239-
// limit correction acceleration to accel_max
240-
if (vel_desired.is_zero()) {
241-
accel_target.limit_length(accel_max);
242-
} else {
243-
// calculate acceleration in the direction of and perpendicular to the velocity input
244-
const Vector2f vel_desired_unit = vel_desired.normalized();
245-
float accel_dir = vel_desired_unit * accel_target;
246-
Vector2f accel_cross = accel_target - (vel_desired_unit * accel_dir);
247-
248-
// Ensure sufficient acceleration is reserved for cross-track correction.
249-
// If forward component dominates, limit lateral component to stay within total magnitude.
250-
if (sq(accel_dir) <= accel_cross.length_squared()) {
251-
// accel_target can be simply limited in magnitude
252-
accel_target.limit_length(accel_max);
253-
} else {
254-
// limiting the length of the vector will reduce the lateral acceleration below 1/sqrt(2)
255-
// limit the lateral acceleration to 1/sqrt(2) and retain as much of the remaining
256-
// acceleration as possible.
257-
accel_cross.limit_length(CORNER_ACCELERATION_RATIO * accel_max);
258-
float accel_max_dir = safe_sqrt(sq(accel_max) - accel_cross.length_squared());
259-
accel_dir = constrain_float(accel_dir, -accel_max_dir, accel_max_dir);
260-
accel_target = accel_cross + vel_desired_unit * accel_dir;
261-
}
262-
}
239+
limit_accel_corner_xy(vel_desired, accel_target, accel_max);
263240

264241
accel_target += accel_desired;
265242

@@ -460,6 +437,46 @@ bool limit_accel_xy(const Vector2f& vel, Vector2f& accel, float accel_max)
460437
return false;
461438
}
462439

440+
// Limits acceleration magnitude while preserving cross-track authority during turns.
441+
// - Splits acceleration into components parallel and perpendicular to velocity.
442+
// - Ensures sufficient lateral acceleration is reserved for path curvature.
443+
// - If forward acceleration dominates, lateral acceleration is limited to
444+
// CORNER_ACCELERATION_RATIO * accel_max.
445+
// Returns true if limiting was applied. (including simple magnitude limiting when vel is zero).
446+
bool limit_accel_corner_xy(const Vector2f& vel, Vector2f& accel, float accel_max)
447+
{
448+
// check accel_max is defined
449+
if (!is_positive(accel_max)) {
450+
return false;
451+
}
452+
if (vel.is_zero()) {
453+
// No along/cross decomposition possible; apply a simple magnitude limit.
454+
return accel.limit_length(accel_max);
455+
}
456+
457+
// Unit velocity direction defines the along-track axis.
458+
const Vector2f vel_unit = vel.normalized();
459+
460+
// Decompose accel into along-track and cross-track components.
461+
float accel_dir = vel_unit * accel;
462+
Vector2f accel_cross = accel - (vel_unit * accel_dir);
463+
464+
// If cross-track magnitude is at least as large as along-track, a simple vector limit
465+
// preserves at least 1/sqrt(2) of accel_max for cross-track correction.
466+
if (sq(accel_dir) <= accel_cross.length_squared()) {
467+
// accel can be simply limited in magnitude
468+
return accel.limit_length(accel_max);
469+
}
470+
471+
// Along-track dominates: preserve cross-track authority by limiting cross-track first,
472+
// then allocate remaining magnitude to along-track.
473+
accel_cross.limit_length(CORNER_ACCELERATION_RATIO * accel_max);
474+
float accel_max_dir = safe_sqrt(sq(accel_max) - accel_cross.length_squared());
475+
accel_dir = constrain_float(accel_dir, -accel_max_dir, accel_max_dir);
476+
accel = accel_cross + vel_unit * accel_dir;
477+
return true;
478+
}
479+
463480
// Piecewise square-root + linear controller that limits second-order response (acceleration).
464481
// - Behaves like a P controller near the setpoint.
465482
// - Switches to sqrt(2·a·Δx) shaping beyond a threshold to limit acceleration.

libraries/AP_Math/control.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,14 @@ void shape_angle_vel_accel(float angle_desired, float angle_vel_desired, float a
133133
// Returns true if the acceleration vector was modified.
134134
bool limit_accel_xy(const Vector2f& vel, Vector2f& accel, float accel_max);
135135

136+
// Limits acceleration magnitude while preserving cross-track authority during turns.
137+
// - Splits acceleration into components parallel and perpendicular to velocity.
138+
// - Ensures sufficient lateral acceleration is reserved for path curvature.
139+
// - If forward acceleration dominates, lateral acceleration is limited to
140+
// CORNER_ACCELERATION_RATIO * accel_max.
141+
// Returns true if limiting was applied.
142+
bool limit_accel_corner_xy(const Vector2f& vel, Vector2f& accel, float accel_max);
143+
136144
// Piecewise square-root + linear controller that limits second-order response (acceleration).
137145
// - Behaves like a P controller near the setpoint.
138146
// - Switches to sqrt(2·a·Δx) shaping beyond a threshold to limit acceleration.

0 commit comments

Comments
 (0)