fix: harden Local G2 stabilization regressions

This commit is contained in:
梁薄云
2026-07-31 16:38:21 +08:00
parent 49c7e5b0c0
commit 24af39de74
5 changed files with 234 additions and 15 deletions
@@ -133,10 +133,12 @@ function New-CoarsePathPoint(
[double]$ArcLength,
$Direction,
[bool]$IsGearSwitch = $false,
[string]$SourceName = 'MotionPrimitive') {
[string]$SourceName = 'MotionPrimitive',
[double]$Heading = 0.0,
[double]$VehicleCurvature = 0.0) {
return [Activator]::CreateInstance($coarsePointType, @(
$X, $Y, [double]0.0, [double]0.0, $ArcLength,
$Direction, [double]0.0, [double]1.0, $IsGearSwitch,
$X, $Y, $Heading, $Heading, $ArcLength,
$Direction, $VehicleCurvature, [double]1.0, $IsGearSwitch,
[Enum]::Parse($coarsePointSourceType, $SourceName)))
}
@@ -284,6 +286,7 @@ $boundsType = Get-RequiredType 'MultiWheelC.TrajectoryPlanning.Mapping.MapBounds
$mapRequestType = Get-RequiredType 'MultiWheelC.TrajectoryPlanning.Mapping.PlanningMapRequest'
$mapFactoryType = Get-RequiredType 'MultiWheelC.TrajectoryPlanning.Mapping.PlanningMapFactory'
$validatorType = Get-RequiredType ($root + 'Validation.SmoothedPathValidator')
$rawBaselineBuilderType = Get-RequiredType ($processing + 'RawPathBaselineBuilder')
Assert-True ($null -ne $preparedPathType) 'PreparedPath must be discoverable for smoothing algorithms.'
Assert-True ($null -ne $preprocessorType) 'PathSmoothingPreprocessor must be discoverable for request preparation.'
@@ -299,6 +302,10 @@ $validator = [Activator]::CreateInstance($validatorType)
$validateMethod = $validatorType.GetMethod('TryValidate')
Assert-True ($null -ne $validateMethod) 'SmoothedPathValidator must expose TryValidate.'
Assert-Equal 9 $validateMethod.GetParameters().Length 'SmoothedPathValidator.TryValidate must retain its public contract.'
$rawBaselineMethod = $rawBaselineBuilderType.GetMethod(
'TryCreate',
[Reflection.BindingFlags]'Static,NonPublic')
Assert-True ($null -ne $rawBaselineMethod) 'RawPathBaselineBuilder must expose its internal TryCreate path.'
$forward = [Enum]::Parse($directionType, 'Forward')
$reverse = [Enum]::Parse($directionType, 'Reverse')
@@ -331,6 +338,61 @@ Assert-True ($overLimitAnalysis.MaximumAbsoluteVehicleCurvaturePerMeter -gt $max
$overLimitValidation = Invoke-GeometryValidation $overLimitAnalysis @($overLimitCircle) $circleVehicle
Assert-False $overLimitValidation.Accepted 'The validator must reject an analyzed over-limit circle.'
# Trusted raw fallback must apply the exact vehicle-curvature gate before reconstruction.
$trustedLimit = 0.80
$trustedOverLimit = $trustedLimit + 0.0000005
$analyzedCurvature = $trustedLimit + 0.01
$chordLength = 0.05
$headingStep = 2.0 * [Math]::Asin($analyzedCurvature * $chordLength / 2.0)
$radius = 1.0 / $analyzedCurvature
$trustedPoints = [Array]::CreateInstance($coarsePointType, 21)
for ($index = 0; $index -le 20; $index++) {
$theta = $headingStep * $index
$trustedPoints.SetValue((New-CoarsePathPoint `
(1.0 + $radius * [Math]::Sin($theta)) `
(1.0 + $radius * (1.0 - [Math]::Cos($theta))) `
($index * $chordLength) `
$forward `
$false `
$(if ($index -eq 0) { 'Start' } else { 'MotionPrimitive' }) `
$theta `
$trustedOverLimit), $index)
}
$trustedSegments = [Array]::CreateInstance($coarseSegmentType, 1)
$trustedSegments.SetValue(
[Activator]::CreateInstance($coarseSegmentType, @(0, $forward, 0, 20, $false, $false)),
0)
$trustedVehicle = [Activator]::CreateInstance($vehicleType)
$trustedVehicle.LengthMeters = 0.20
$trustedVehicle.WidthMeters = 0.20
$trustedVehicle.SafetyMarginMeters = 0.0
$trustedVehicle.MaximumCurvaturePerMeter = $trustedLimit
$trustedConfiguration = [Activator]::CreateInstance($smoothingConfigurationType)
$trustedRequest = [Activator]::CreateInstance($smoothingRequestType, @(
$trustedPoints,
$trustedSegments,
(New-EmptyGeometryMap),
$trustedVehicle,
$trustedConfiguration))
$trustedPreprocessor = [Activator]::CreateInstance($preprocessorType)
$trustedPrepareMethod = $preprocessorType.GetMethod('TryPrepare')
$trustedPrepareArguments = [object[]]@($trustedRequest, $null, $null)
Assert-True $trustedPrepareMethod.Invoke($trustedPreprocessor, $trustedPrepareArguments) `
('Trusted raw fallback regression must prepare successfully. Reason=' + $trustedPrepareArguments[2])
$trustedBaselineArguments = [object[]]@(
$trustedRequest,
$trustedPrepareArguments[1],
$analyzer,
$trustedConfiguration.OutputSpacingMeters,
$validator,
$trustedConfiguration.MaximumCollisionCheckStepMeters,
$null,
$null)
Assert-False $rawBaselineMethod.Invoke($null, $trustedBaselineArguments) `
'Trusted raw fallback must not publish a coarse curvature above the exact vehicle maximum.'
Assert-Equal $overLimitValidation.Reason $trustedBaselineArguments[7] `
'Rejecting trusted raw fallback must preserve the original analyzed-path validation failure.'
# The chord-corrected estimator must not under-estimate these smooth references more than the former polyline estimator.
foreach ($quinticCase in @(
[pscustomobject]@{ Name = 'SBend'; C2 = 0.0; C3 = 0.30; C4 = -0.45; C5 = 0.18; Power = 1.0 },
@@ -80,14 +80,22 @@ Assert-True $twoRegions.WorkOrderDescending `
Assert-True $twoRegions.FrontArcPreservedAfterBackReplacement `
'Replacing the back region must preserve the front region original arc coordinates.'
Assert-True $twoRegions.BothReplacementsRetained `
'Back-then-front replacement must retain both length-changing local replacements.'
'Back-then-front replacement must retain the exact LocalG2Transition interiors at (0.75, 0.20) and (2.25, 0.20).'
Assert-True $twoRegions.ForwardOrderRejected `
'The regression fixture must prove that front-first invalidates the original back absolute arc.'
Assert-True $twoRegions.DeterministicWorkOrder `
'Work ordering must repeat exactly without mutating report order.'
Assert-True $twoRegions.DeterministicReplacementGeometry `
'Repeated back-then-front replacement must preserve count and every point X, Y, source, and direction.'
Assert-True $twoRegions.InvalidWorkOrderRejected `
'Work ordering must reject null regions and cross-segment event contents.'
$ordering = Invoke-Scenario 'MultiSegmentWorkOrder'
Assert-True $ordering.SegmentOrderAscending `
'Region work ordering must process segment indices in ascending order.'
Assert-True $ordering.EqualArcUsesReportOrder `
'Equal first-local-arc regions must retain their original report-index order.'
$evaluatorType = Get-RequiredType 'MultiWheelC.TrajectoryPlanning.PathSmoothing.LocalG2.LocalG2CandidateEvaluator'
$evaluatorHooksType = $evaluatorType.GetNestedType('TestHooks', [Reflection.BindingFlags]'Public,NonPublic')
Assert-True ($null -ne $evaluatorHooksType) 'LocalG2CandidateEvaluator must expose narrowly scoped deterministic TestHooks.'