fix: align smoothing feasibility and option flow
This commit is contained in:
+31
-35
@@ -12,6 +12,7 @@ namespace MultiWheelC.TrajectoryPlanning.PathSmoothing.Algorithms;
|
||||
/// <summary>在有限强度计划内运行单一算法,并以共享分析和安全复核决定是否接受候选。</summary>
|
||||
internal sealed class SmoothingAlgorithmRunner
|
||||
{
|
||||
private static readonly double[] RetryStrengthScales = { 1d, 0.75d, 0.50d, 0.25d };
|
||||
private readonly PathGeometryAnalyzer _analyzer;
|
||||
private readonly SmoothedPathValidator _validator;
|
||||
|
||||
@@ -28,7 +29,7 @@ internal sealed class SmoothingAlgorithmRunner
|
||||
|
||||
/// <summary>
|
||||
/// 依次尝试配置的有限强度比例。取消直接向上传播,由门面转换为最终状态;
|
||||
/// 数值失败和几何分析失败均不重试,以避免以较低强度掩盖算法退化。
|
||||
/// 只有算法明确标记为可重试的不可行性才会使用较低强度;终止失败和统一复核失败均不重试。
|
||||
/// </summary>
|
||||
internal AlgorithmRunResult Run(
|
||||
IPathSmoother smoother,
|
||||
@@ -38,13 +39,10 @@ internal sealed class SmoothingAlgorithmRunner
|
||||
{
|
||||
var attemptedStrengths = new List<double>();
|
||||
var failureReasons = new List<string>();
|
||||
if (smoother == null || input == null || configuration == null)
|
||||
if (smoother == null || input == null || input.Options == null || configuration == null)
|
||||
return AlgorithmRunResult.Failed("平滑算法、输入或配置无效。", attemptedStrengths, failureReasons);
|
||||
if (configuration.RetryStrengthScales == null || configuration.RetryStrengthScales.Count == 0)
|
||||
return AlgorithmRunResult.Failed("平滑强度重试计划为空。", attemptedStrengths, failureReasons);
|
||||
|
||||
SmoothingCandidate rejectedCandidate = null;
|
||||
foreach (double scale in configuration.RetryStrengthScales)
|
||||
foreach (double scale in RetryStrengthScales)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
double effectiveStrength = configuration.SmoothingStrength * scale;
|
||||
@@ -55,11 +53,22 @@ internal sealed class SmoothingAlgorithmRunner
|
||||
SmoothingCandidate candidate = smoother.Smooth(input, effectiveStrength, cancellationToken);
|
||||
if (candidate == null)
|
||||
return AlgorithmRunResult.Failed("平滑算法未返回候选。", attemptedStrengths, failureReasons);
|
||||
if (!candidate.Succeeded)
|
||||
if (candidate.Status == SmoothingCandidateStatus.RetryableInfeasible)
|
||||
{
|
||||
failureReasons.Add(candidate.Reason);
|
||||
continue;
|
||||
}
|
||||
if (candidate.Status == SmoothingCandidateStatus.Failed)
|
||||
{
|
||||
failureReasons.Add(candidate.Reason);
|
||||
return AlgorithmRunResult.Failed(candidate.Reason, attemptedStrengths, failureReasons);
|
||||
}
|
||||
if (candidate.Status != SmoothingCandidateStatus.Success)
|
||||
{
|
||||
const string unknownStatusReason = "平滑算法返回未知候选状态。";
|
||||
failureReasons.Add(unknownStatusReason);
|
||||
return AlgorithmRunResult.Failed(unknownStatusReason, attemptedStrengths, failureReasons);
|
||||
}
|
||||
|
||||
if (!_analyzer.TryAnalyze(candidate.Segments, configuration.OutputSpacingMeters,
|
||||
out PathGeometryAnalysis analysis, out string reason))
|
||||
@@ -77,11 +86,11 @@ internal sealed class SmoothingAlgorithmRunner
|
||||
attemptedStrengths, failureReasons);
|
||||
}
|
||||
|
||||
rejectedCandidate = candidate;
|
||||
failureReasons.Add(reason);
|
||||
return AlgorithmRunResult.Failed(reason, attemptedStrengths, failureReasons);
|
||||
}
|
||||
|
||||
return AlgorithmRunResult.Infeasible(rejectedCandidate, attemptedStrengths, failureReasons);
|
||||
return AlgorithmRunResult.Infeasible(null, attemptedStrengths, failureReasons);
|
||||
}
|
||||
|
||||
private static PathQualityMetrics CreateMetrics(PathGeometryAnalysis analysis, double minimumClearanceMeters)
|
||||
@@ -195,9 +204,9 @@ internal sealed class SmoothingAlgorithmRunner
|
||||
|
||||
private enum TestScenario
|
||||
{
|
||||
RejectAll,
|
||||
RetryableInfeasible,
|
||||
AcceptFirst,
|
||||
NumericalFailure,
|
||||
TerminalFailed,
|
||||
CancelBeforeNextAttempt,
|
||||
}
|
||||
|
||||
@@ -223,23 +232,22 @@ internal sealed class SmoothingAlgorithmRunner
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
AttemptedStrengths.Add(effectiveStrength);
|
||||
if (_scenario == TestScenario.NumericalFailure)
|
||||
if (_scenario == TestScenario.TerminalFailed)
|
||||
return SmoothingCandidate.Failed("确定性数值退化。");
|
||||
if (_scenario == TestScenario.AcceptFirst)
|
||||
return CreateAcceptedCandidate();
|
||||
|
||||
SmoothingCandidate rejected = CreateRejectedCandidate();
|
||||
if (_scenario == TestScenario.CancelBeforeNextAttempt)
|
||||
_cancellationSource.Cancel();
|
||||
return rejected;
|
||||
return SmoothingCandidate.RetryableInfeasible("确定性可重试不可行。" );
|
||||
}
|
||||
}
|
||||
|
||||
private static TestScenario ParseScenario(string scenario)
|
||||
{
|
||||
if (string.Equals(scenario, nameof(TestScenario.RejectAll), StringComparison.Ordinal)) return TestScenario.RejectAll;
|
||||
if (string.Equals(scenario, nameof(TestScenario.RetryableInfeasible), StringComparison.Ordinal)) return TestScenario.RetryableInfeasible;
|
||||
if (string.Equals(scenario, nameof(TestScenario.AcceptFirst), StringComparison.Ordinal)) return TestScenario.AcceptFirst;
|
||||
if (string.Equals(scenario, nameof(TestScenario.NumericalFailure), StringComparison.Ordinal)) return TestScenario.NumericalFailure;
|
||||
if (string.Equals(scenario, nameof(TestScenario.TerminalFailed), StringComparison.Ordinal)) return TestScenario.TerminalFailed;
|
||||
if (string.Equals(scenario, nameof(TestScenario.CancelBeforeNextAttempt), StringComparison.Ordinal)) return TestScenario.CancelBeforeNextAttempt;
|
||||
throw new ArgumentOutOfRangeException(nameof(scenario));
|
||||
}
|
||||
@@ -277,7 +285,13 @@ internal sealed class SmoothingAlgorithmRunner
|
||||
MaximumCurvaturePerMeter = 100d,
|
||||
MinimumTurningRadiusMeters = 0.01d,
|
||||
};
|
||||
return new SmoothingAlgorithmInput(new PreparedPath(originalSegments), mapResult.Map, vehicle, 0.05d, 0.02d);
|
||||
return new SmoothingAlgorithmInput(
|
||||
new PreparedPath(originalSegments),
|
||||
mapResult.Map,
|
||||
vehicle,
|
||||
0.05d,
|
||||
0.02d,
|
||||
new SmoothingOptionsSnapshot(new PathSmoothingConfiguration()));
|
||||
}
|
||||
|
||||
private static SmoothingCandidate CreateAcceptedCandidate()
|
||||
@@ -297,24 +311,6 @@ internal sealed class SmoothingAlgorithmRunner
|
||||
});
|
||||
}
|
||||
|
||||
private static SmoothingCandidate CreateRejectedCandidate()
|
||||
{
|
||||
return SmoothingCandidate.Success(new List<PreparedDirectionSegment>
|
||||
{
|
||||
new PreparedDirectionSegment(
|
||||
0,
|
||||
TravelDirection.Forward,
|
||||
new List<SmoothingPoint2D>
|
||||
{
|
||||
CreatePoint(0.5d, 0.5d, 0d),
|
||||
CreatePoint(0.05d, 0.5d, 0.45d),
|
||||
CreatePoint(1.5d, 0.5d, 1.90d),
|
||||
},
|
||||
false,
|
||||
false),
|
||||
});
|
||||
}
|
||||
|
||||
private static SmoothingPoint2D CreatePoint(double x, double y, double arcLength)
|
||||
{
|
||||
return new SmoothingPoint2D(
|
||||
|
||||
Reference in New Issue
Block a user