Skip to content

Commit 376b35d

Browse files
authored
Merge pull request #10278 from breadoven/abo_wp_tracking_improvements
Waypoint tracking improvements
2 parents 6a27be8 + 570b301 commit 376b35d

File tree

3 files changed

+47
-33
lines changed

3 files changed

+47
-33
lines changed

docs/Settings.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3524,7 +3524,7 @@ Pitch Angle deadband when soaring mode enabled (deg). Angle mode inactive within
35243524

35253525
### nav_fw_wp_tracking_accuracy
35263526

3527-
Waypoint tracking accuracy forces the craft to quickly head toward and track along the waypoint course line as closely as possible. Settings 1 to 10 adjust the course tracking response. Higher values dampen the response reducing possible overshoot. A value of 5 is a good starting point. Set to 0 to disable.
3527+
Waypoint tracking accuracy forces the craft to quickly head toward and track along the waypoint course line as closely as possible. Setting adjusts tracking deadband distance fom waypoint courseline [m]. Tracking isn't actively controlled within the deadband providing smoother flight adjustments but less accurate tracking. A 2m deadband should work OK in most cases. Setting to 0 disables waypoint tracking accuracy.
35283528

35293529
| Default | Min | Max |
35303530
| --- | --- | --- |

src/main/fc/settings.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ tables:
8383
values: ["NONE", "AGL", "FLOW_RAW", "FLOW", "ALWAYS", "SAG_COMP_VOLTAGE",
8484
"VIBE", "CRUISE", "REM_FLIGHT_TIME", "SMARTAUDIO", "ACC",
8585
"NAV_YAW", "PCF8574", "DYN_GYRO_LPF", "AUTOLEVEL", "ALTITUDE",
86-
"AUTOTRIM", "AUTOTUNE", "RATE_DYNAMICS", "LANDING", "POS_EST",
86+
"AUTOTRIM", "AUTOTUNE", "RATE_DYNAMICS", "LANDING", "POS_EST",
8787
"ADAPTIVE_FILTER", "HEADTRACKER", "GPS", "LULU", "SBUS2"]
8888
- name: aux_operator
8989
values: ["OR", "AND"]
@@ -2545,7 +2545,7 @@ groups:
25452545
min: 1
25462546
max: 9
25472547
- name: nav_fw_wp_tracking_accuracy
2548-
description: "Waypoint tracking accuracy forces the craft to quickly head toward and track along the waypoint course line as closely as possible. Settings 1 to 10 adjust the course tracking response. Higher values dampen the response reducing possible overshoot. A value of 5 is a good starting point. Set to 0 to disable."
2548+
description: "Waypoint tracking accuracy forces the craft to quickly head toward and track along the waypoint course line as closely as possible. Setting adjusts tracking deadband distance fom waypoint courseline [m]. Tracking isn't actively controlled within the deadband providing smoother flight adjustments but less accurate tracking. A 2m deadband should work OK in most cases. Setting to 0 disables waypoint tracking accuracy."
25492549
default_value: 0
25502550
field: fw.wp_tracking_accuracy
25512551
min: 0

src/main/navigation/navigation_fixedwing.c

Lines changed: 44 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -399,38 +399,52 @@ static void updatePositionHeadingController_FW(timeUs_t currentTimeUs, timeDelta
399399
virtualTargetBearing = calculateBearingToDestination(&virtualDesiredPosition);
400400
}
401401

402-
/* If waypoint tracking enabled quickly force craft toward waypoint course line and closely track along it */
403-
if (navConfig()->fw.wp_tracking_accuracy && isWaypointNavTrackingActive() && !needToCalculateCircularLoiter) {
404-
// courseVirtualCorrection initially used to determine current position relative to course line for later use
405-
int32_t courseVirtualCorrection = wrap_18000(posControl.activeWaypoint.bearing - virtualTargetBearing);
406-
navCrossTrackError = ABS(posControl.wpDistance * sin_approx(CENTIDEGREES_TO_RADIANS(courseVirtualCorrection)));
407-
408-
// tracking only active when certain distance and heading conditions are met
409-
if ((ABS(wrap_18000(virtualTargetBearing - posControl.actualState.cog)) < 9000 || posControl.wpDistance < 1000.0f) && navCrossTrackError > 200) {
410-
int32_t courseHeadingError = wrap_18000(posControl.activeWaypoint.bearing - posControl.actualState.cog);
411-
412-
// captureFactor adjusts distance/heading sensitivity balance when closing in on course line.
413-
// Closing distance threashold based on speed and an assumed 1 second response time.
414-
float captureFactor = navCrossTrackError < posControl.actualState.velXY ? constrainf(2.0f - ABS(courseHeadingError) / 500.0f, 0.0f, 2.0f) : 1.0f;
415-
416-
// bias between reducing distance to course line and aligning with course heading adjusted by waypoint_tracking_accuracy
417-
// initial courseCorrectionFactor based on distance to course line
418-
float courseCorrectionFactor = constrainf(captureFactor * navCrossTrackError / (1000.0f * navConfig()->fw.wp_tracking_accuracy), 0.0f, 1.0f);
419-
courseCorrectionFactor = courseVirtualCorrection < 0 ? -courseCorrectionFactor : courseCorrectionFactor;
420-
421-
// course heading alignment factor
422-
float courseHeadingFactor = constrainf(courseHeadingError / 18000.0f, 0.0f, 1.0f);
423-
courseHeadingFactor = courseHeadingError < 0 ? -courseHeadingFactor : courseHeadingFactor;
424-
425-
// final courseCorrectionFactor combining distance and heading factors
426-
courseCorrectionFactor = constrainf(courseCorrectionFactor - courseHeadingFactor, -1.0f, 1.0f);
427-
428-
// final courseVirtualCorrection value
429-
courseVirtualCorrection = DEGREES_TO_CENTIDEGREES(navConfig()->fw.wp_tracking_max_angle) * courseCorrectionFactor;
430-
virtualTargetBearing = wrap_36000(posControl.activeWaypoint.bearing - courseVirtualCorrection);
402+
if (isWaypointNavTrackingActive()) {
403+
/* Calculate cross track error */
404+
posControl.wpDistance = calculateDistanceToDestination(&posControl.activeWaypoint.pos);
405+
406+
fpVector3_t virtualCoursePoint;
407+
virtualCoursePoint.x = posControl.activeWaypoint.pos.x -
408+
posControl.wpDistance * cos_approx(CENTIDEGREES_TO_RADIANS(posControl.activeWaypoint.bearing));
409+
virtualCoursePoint.y = posControl.activeWaypoint.pos.y -
410+
posControl.wpDistance * sin_approx(CENTIDEGREES_TO_RADIANS(posControl.activeWaypoint.bearing));
411+
navCrossTrackError = calculateDistanceToDestination(&virtualCoursePoint);
412+
413+
/* If waypoint tracking enabled force craft toward and closely track along waypoint course line */
414+
if (navConfig()->fw.wp_tracking_accuracy && !needToCalculateCircularLoiter) {
415+
static float crossTrackErrorRate;
416+
static timeUs_t previousCrossTrackErrorUpdateTime;
417+
static float previousCrossTrackError = 0.0f;
418+
static pt1Filter_t fwCrossTrackErrorRateFilterState;
419+
420+
if ((currentTimeUs - previousCrossTrackErrorUpdateTime) >= HZ2US(20) && fabsf(previousCrossTrackError - navCrossTrackError) > 10.0f) {
421+
const float crossTrackErrorDtSec = US2S(currentTimeUs - previousCrossTrackErrorUpdateTime);
422+
if (fabsf(previousCrossTrackError - navCrossTrackError) < 500.0f) {
423+
crossTrackErrorRate = (previousCrossTrackError - navCrossTrackError) / crossTrackErrorDtSec;
424+
}
425+
crossTrackErrorRate = pt1FilterApply4(&fwCrossTrackErrorRateFilterState, crossTrackErrorRate, 3.0f, crossTrackErrorDtSec);
426+
previousCrossTrackErrorUpdateTime = currentTimeUs;
427+
previousCrossTrackError = navCrossTrackError;
428+
}
429+
430+
uint16_t trackingDeadband = METERS_TO_CENTIMETERS(navConfig()->fw.wp_tracking_accuracy);
431+
432+
if ((ABS(wrap_18000(virtualTargetBearing - posControl.actualState.cog)) < 9000 || posControl.wpDistance < 1000.0f) && navCrossTrackError > trackingDeadband) {
433+
float adjustmentFactor = wrap_18000(posControl.activeWaypoint.bearing - virtualTargetBearing);
434+
uint16_t angleLimit = DEGREES_TO_CENTIDEGREES(navConfig()->fw.wp_tracking_max_angle);
435+
436+
/* Apply heading adjustment to match crossTrackErrorRate with fixed convergence speed profile */
437+
float maxApproachSpeed = posControl.actualState.velXY * sin_approx(CENTIDEGREES_TO_RADIANS(angleLimit));
438+
float desiredApproachSpeed = constrainf(navCrossTrackError / 3.0f, 50.0f, maxApproachSpeed);
439+
adjustmentFactor = SIGN(adjustmentFactor) * navCrossTrackError * ((desiredApproachSpeed - crossTrackErrorRate) / desiredApproachSpeed);
440+
441+
/* Calculate final adjusted virtualTargetBearing */
442+
uint16_t limit = constrainf(navCrossTrackError, 1000.0f, angleLimit);
443+
adjustmentFactor = constrainf(adjustmentFactor, -limit, limit);
444+
virtualTargetBearing = wrap_36000(posControl.activeWaypoint.bearing - adjustmentFactor);
445+
}
431446
}
432447
}
433-
434448
/*
435449
* Calculate NAV heading error
436450
* Units are centidegrees

0 commit comments

Comments
 (0)