fix: freeze smoothing request snapshots
This commit is contained in:
@@ -8,6 +8,9 @@ namespace MultiWheelC.TrajectoryPlanning.PathSmoothing;
|
||||
/// <summary>路径平滑所需的原始粗路径、复核上下文和配置。</summary>
|
||||
public sealed class PathSmoothingRequest
|
||||
{
|
||||
private readonly VehicleParameters _vehicle;
|
||||
private readonly PathSmoothingConfiguration _configuration;
|
||||
|
||||
/// <summary>创建路径平滑请求,并复制粗路径和方向分段集合。</summary>
|
||||
public PathSmoothingRequest(
|
||||
IReadOnlyList<CoarsePathPoint> coarsePath,
|
||||
@@ -19,8 +22,8 @@ public sealed class PathSmoothingRequest
|
||||
CoarsePath = CopyReadOnly(coarsePath);
|
||||
Segments = CopyReadOnly(segments);
|
||||
Map = map;
|
||||
Vehicle = CopyVehicle(vehicle);
|
||||
Configuration = CopyConfiguration(configuration);
|
||||
_vehicle = CopyVehicle(vehicle);
|
||||
_configuration = CopyConfiguration(configuration);
|
||||
}
|
||||
|
||||
/// <summary>原始粗路径的不可变快照。</summary>
|
||||
@@ -32,11 +35,11 @@ public sealed class PathSmoothingRequest
|
||||
/// <summary>用于平滑后完整车体复核的规划栅格地图。</summary>
|
||||
public PlanningGridMap Map { get; }
|
||||
|
||||
/// <summary>车辆几何与最大曲率约束。</summary>
|
||||
public VehicleParameters Vehicle { get; }
|
||||
/// <summary>车辆几何与最大曲率约束的不可变快照副本。</summary>
|
||||
public VehicleParameters Vehicle => CopyVehicle(_vehicle);
|
||||
|
||||
/// <summary>本次平滑的配置。</summary>
|
||||
public PathSmoothingConfiguration Configuration { get; }
|
||||
/// <summary>本次平滑配置的不可变快照副本。</summary>
|
||||
public PathSmoothingConfiguration Configuration => CopyConfiguration(_configuration);
|
||||
|
||||
private static IReadOnlyList<T> CopyReadOnly<T>(IReadOnlyList<T> source)
|
||||
{
|
||||
|
||||
@@ -140,6 +140,7 @@ $method = [Enum]::Parse($methodType, 'CubicBSpline')
|
||||
$successMethod = $resultType.GetMethod('Success')
|
||||
Assert-True ($null -ne $successMethod) 'PathSmoothingResult must expose Success.'
|
||||
Assert-Throws { $successMethod.Invoke($null, @($method, $pointArray, $segmentArray, $diagnostics)) } 'Success factory must reject diagnostics that are not feasible.'
|
||||
Assert-Throws { $successMethod.Invoke($null, @($method, $pointArray, $segmentArray, $null)) } 'Success factory must reject null diagnostics.'
|
||||
Assert-Throws { $successMethod.Invoke($null, @([Enum]::ToObject($methodType, 99), $pointArray, $segmentArray, $feasibleDiagnostics)) } 'Success factory must reject undefined smoothing methods.'
|
||||
$success = $successMethod.Invoke($null, @($method, $pointArray, $segmentArray, $feasibleDiagnostics))
|
||||
Assert-Equal 'Success' $success.Status.ToString() 'Success factory must publish Success status.'
|
||||
@@ -160,6 +161,8 @@ $fallbackPath.SetValue($point, 0)
|
||||
$fallbackSegments = [Array]::CreateInstance($segmentType, 1)
|
||||
$fallbackSegments.SetValue($segmentA, 0)
|
||||
Assert-Throws { $fallbackMethod.Invoke($null, @($method, $fallbackPath, $fallbackSegments, $diagnostics)) } 'Fallback factory must reject diagnostics that are not feasible.'
|
||||
Assert-Throws { $fallbackMethod.Invoke($null, @($method, $fallbackPath, $fallbackSegments, $null)) } 'Fallback factory must reject null diagnostics.'
|
||||
Assert-Throws { $fallbackMethod.Invoke($null, @([Enum]::ToObject($methodType, 99), $fallbackPath, $fallbackSegments, $feasibleDiagnostics)) } 'Fallback factory must reject undefined smoothing methods.'
|
||||
$fallback = $fallbackMethod.Invoke($null, @($method, $fallbackPath, $fallbackSegments, $feasibleDiagnostics))
|
||||
Assert-Equal 'FallbackToCoarsePath' $fallback.Status.ToString() 'Fallback factory must publish an explicit fallback status.'
|
||||
Assert-Equal 1 $fallback.Path.Count 'Fallback factory must publish a validated fallback path.'
|
||||
@@ -177,6 +180,7 @@ Assert-ReadOnlyCollection $failed.Path 'Failure path must be immutable.'
|
||||
Assert-ReadOnlyCollection $failed.Segments 'Failure segments must be immutable.'
|
||||
Assert-Throws { $failureMethod.Invoke($null, @([Enum]::Parse($statusType, 'Success'), $diagnostics)) } 'Failure factory must reject Success.'
|
||||
Assert-Throws { $failureMethod.Invoke($null, @([Enum]::Parse($statusType, 'FallbackToCoarsePath'), $diagnostics)) } 'Failure factory must reject fallback status.'
|
||||
Assert-Throws { $failureMethod.Invoke($null, @([Enum]::ToObject($statusType, 99), $diagnostics)) } 'Failure factory must reject undefined statuses.'
|
||||
Assert-Throws { $successMethod.Invoke($null, @($method, [Array]::CreateInstance($pointType, 0), $fallbackSegments, $diagnostics)) } 'Success factory must reject an empty path.'
|
||||
Assert-Throws { $successMethod.Invoke($null, @($method, $fallbackPath, [Array]::CreateInstance($segmentType, 0), $diagnostics)) } 'Success factory must reject empty segments.'
|
||||
|
||||
@@ -228,5 +232,25 @@ Assert-Near 0.05 $request.Configuration.OutputSpacingMeters 'Request must snapsh
|
||||
Assert-Near (1.0 / 3.0) $request.Configuration.CubicBSpline.EndpointTangentScale 'Request must snapshot B-spline options.'
|
||||
Assert-Near (1.0 / 3.0) $request.Configuration.LocalCubicBezier.HandleLengthRatio 'Request must snapshot Bezier options.'
|
||||
Assert-Near 0.50 $request.Configuration.PiecewiseQuintic.KnotSpacingMeters 'Request must snapshot quintic options.'
|
||||
$request.Vehicle.WidthMeters = [double]9.99
|
||||
$request.Vehicle.SafetyMarginMeters = [double]9.99
|
||||
$request.Vehicle.MinimumTurningRadiusMeters = [double]9.99
|
||||
$request.Configuration.MaximumCollisionCheckStepMeters = [double]0.99
|
||||
$request.Configuration.MinimumClearanceReserveMeters = [double]0.99
|
||||
$request.Configuration.SmoothingStrength = [double]0.99
|
||||
$request.Configuration.AllowFallbackToCoarsePath = $false
|
||||
$request.Configuration.LocalCubicBezier.CornerHeadingThresholdRadians = [double]0.99
|
||||
$request.Configuration.LocalCubicBezier.MaximumWindowLengthMeters = [double]0.99
|
||||
$request.Configuration.PiecewiseQuintic.MinimumKnotSpacingMeters = [double]0.99
|
||||
Assert-Near 0.60 $request.Vehicle.WidthMeters 'Request vehicle getter must not expose mutable state.'
|
||||
Assert-Near 0.05 $request.Vehicle.SafetyMarginMeters 'Request vehicle getter must not expose mutable state.'
|
||||
Assert-True ($null -eq $request.Vehicle.MinimumTurningRadiusMeters) 'Request vehicle getter must not expose mutable nullable state.'
|
||||
Assert-Near 0.025 $request.Configuration.MaximumCollisionCheckStepMeters 'Request configuration getter must not expose mutable state.'
|
||||
Assert-Near 0.02 $request.Configuration.MinimumClearanceReserveMeters 'Request configuration getter must not expose mutable state.'
|
||||
Assert-Near 1.0 $request.Configuration.SmoothingStrength 'Request configuration getter must not expose mutable state.'
|
||||
Assert-Equal $true $request.Configuration.AllowFallbackToCoarsePath 'Request configuration getter must not expose mutable state.'
|
||||
Assert-Near ([Math]::PI / 18.0) $request.Configuration.LocalCubicBezier.CornerHeadingThresholdRadians 'Request configuration getter must not expose mutable Bezier options.'
|
||||
Assert-Near 0.60 $request.Configuration.LocalCubicBezier.MaximumWindowLengthMeters 'Request configuration getter must not expose mutable Bezier options.'
|
||||
Assert-Near 0.10 $request.Configuration.PiecewiseQuintic.MinimumKnotSpacingMeters 'Request configuration getter must not expose mutable quintic options.'
|
||||
|
||||
Write-Output 'Path smoothing contract checks passed.'
|
||||
|
||||
Reference in New Issue
Block a user