chore: save current workspace progress
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using MultiWheelC.TrajectoryPlanning.Utils;
|
||||
|
||||
namespace MultiWheelC.TrajectoryPlanning.Mapping;
|
||||
|
||||
/// <summary>以 m 表示的障碍物净距离保守下界。</summary>
|
||||
internal sealed class ObstacleDistanceField
|
||||
{
|
||||
private readonly double[] _conservativeDistances;
|
||||
private ObstacleDistanceField(double[] conservativeDistances) { _conservativeDistances = conservativeDistances; }
|
||||
/// <summary>
|
||||
/// 从占据栅格创建距离场。
|
||||
///
|
||||
/// 参数:occupied 为行主序占据数组;rows、cols 为其尺寸;resolutionMeters 为格边长,单位 m。
|
||||
/// 返回:每个格到最近障碍物的保守净距离下界,单位 m;全空地图中的每项为正无穷。
|
||||
/// </summary>
|
||||
public static ObstacleDistanceField Create(byte[] occupied, int rows, int cols, double resolutionMeters)
|
||||
{
|
||||
if (!TryCreate(occupied, rows, cols, resolutionMeters, PlanningOperationBudget.Unlimited(CancellationToken.None),
|
||||
out ObstacleDistanceField field, out _))
|
||||
throw new InvalidOperationException("Unbounded distance-field creation unexpectedly stopped.");
|
||||
return field;
|
||||
}
|
||||
|
||||
/// <summary>使用共享预算创建距离场;停止时不返回部分距离数据。</summary>
|
||||
internal static bool TryCreate(byte[] occupied, int rows, int cols, double resolutionMeters,
|
||||
PlanningOperationBudget budget, out ObstacleDistanceField field, out PlanningOperationStopReason stopReason)
|
||||
{
|
||||
if (occupied == null) throw new ArgumentNullException(nameof(occupied));
|
||||
if (budget == null) throw new ArgumentNullException(nameof(budget));
|
||||
field = null;
|
||||
stopReason = budget.GetStopReason();
|
||||
if (stopReason != PlanningOperationStopReason.None) return false;
|
||||
bool hasObstacle = false;
|
||||
int workItemCount = 0;
|
||||
for (int i = 0; i < occupied.Length; i++)
|
||||
{
|
||||
stopReason = budget.CheckEvery(ref workItemCount);
|
||||
if (stopReason != PlanningOperationStopReason.None) return false;
|
||||
if (occupied[i] != 0) { hasObstacle = true; break; }
|
||||
}
|
||||
var distances = new double[occupied.Length];
|
||||
if (!hasObstacle)
|
||||
{
|
||||
for (int i = 0; i < distances.Length; i++)
|
||||
{
|
||||
stopReason = budget.CheckEvery(ref workItemCount);
|
||||
if (stopReason != PlanningOperationStopReason.None) return false;
|
||||
distances[i] = double.PositiveInfinity;
|
||||
}
|
||||
field = new ObstacleDistanceField(distances);
|
||||
stopReason = PlanningOperationStopReason.None;
|
||||
return true;
|
||||
}
|
||||
if (!EuclideanDistanceTransform.TryComputeSquaredDistances(occupied, rows, cols, budget, out double[] squared, out stopReason))
|
||||
return false;
|
||||
double conservativeOffset = Math.Sqrt(2d) * resolutionMeters;
|
||||
for (int i = 0; i < distances.Length; i++)
|
||||
{
|
||||
stopReason = budget.CheckEvery(ref workItemCount);
|
||||
if (stopReason != PlanningOperationStopReason.None) return false;
|
||||
distances[i] = Math.Max(0d, Math.Sqrt(squared[i]) * resolutionMeters - conservativeOffset);
|
||||
}
|
||||
field = new ObstacleDistanceField(distances);
|
||||
stopReason = PlanningOperationStopReason.None;
|
||||
return true;
|
||||
}
|
||||
internal double[] CopyDistances() { return (double[])_conservativeDistances.Clone(); }
|
||||
}
|
||||
Reference in New Issue
Block a user