From 8c8ce89978354e9544dec91c82813c3b6a2e7faf Mon Sep 17 00:00:00 2001 From: tian <11429339@qq.com> Date: Sat, 20 Sep 2025 11:06:13 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=B8=80=E4=B8=AA=E7=BD=91?= =?UTF-8?q?=E6=A0=BC=E7=94=9F=E6=88=90=E6=97=B6=E7=9A=84=E5=8D=95=E4=BD=8D?= =?UTF-8?q?=E8=BD=AC=E6=8D=A2bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/PathPlanning/GridMapGenerator.cs | 75 +++++++++++++++------------- 1 file changed, 40 insertions(+), 35 deletions(-) diff --git a/src/PathPlanning/GridMapGenerator.cs b/src/PathPlanning/GridMapGenerator.cs index 09e8911..7880466 100644 --- a/src/PathPlanning/GridMapGenerator.cs +++ b/src/PathPlanning/GridMapGenerator.cs @@ -62,11 +62,23 @@ namespace NavisworksTransport.PathPlanning { LogManager.Info("【生成网格地图】开始生成网格地图"); var startTime = DateTime.Now; - - // 重要:将米制网格大小转换为模型单位 + + // 第一步:统一转换所有米制参数为模型单位 double metersToModelUnitsConversionFactor = UnitsConverter.GetMetersToUnitsConversionFactor(Application.ActiveDocument.Units); double cellSizeInModelUnits = cellSize * metersToModelUnitsConversionFactor; - LogManager.Info($"【生成网格地图】网格大小单位转换: {cellSize}米 → {cellSizeInModelUnits:F2}模型单位 (转换系数: {metersToModelUnitsConversionFactor:F2})"); + double vehicleRadiusInModelUnits = vehicleRadius * metersToModelUnitsConversionFactor; + double safetyMarginInModelUnits = safetyMargin * metersToModelUnitsConversionFactor; + double vehicleHeightInModelUnits = vehicleHeight * metersToModelUnitsConversionFactor; + double scanHeightInModelUnits = vehicleHeightInModelUnits + safetyMarginInModelUnits; // 扫描高度 = 车辆高度 + 安全间隙 + double totalInflationRadiusInModelUnits = vehicleRadiusInModelUnits + safetyMarginInModelUnits; // 膨胀半径 = 车辆半径 + 安全间隙 + + LogManager.Info($"【生成网格地图】参数单位转换完成 (转换系数: {metersToModelUnitsConversionFactor:F2}):"); + LogManager.Info($" 网格大小: {cellSize}米 → {cellSizeInModelUnits:F2}模型单位"); + LogManager.Info($" 车辆半径: {vehicleRadius}米 → {vehicleRadiusInModelUnits:F2}模型单位"); + LogManager.Info($" 安全间隙: {safetyMargin}米 → {safetyMarginInModelUnits:F2}模型单位"); + LogManager.Info($" 车辆高度: {vehicleHeight}米 → {vehicleHeightInModelUnits:F2}模型单位"); + LogManager.Info($" 扫描高度: {scanHeightInModelUnits:F2}模型单位"); + LogManager.Info($" 膨胀半径: {totalInflationRadiusInModelUnits:F2}模型单位"); // 1. 使用通道构建器构建基础通道覆盖网格 LogManager.Info("【生成网格地图】步骤1: 构建通道覆盖网格"); @@ -88,15 +100,14 @@ namespace NavisworksTransport.PathPlanning // 2. 直接遍历处理障碍物(包围盒检测) - 使用高性能优化版本 LogManager.Info("【生成网格地图】步骤2: 高性能包围盒遍历处理障碍物"); - double scanHeight = vehicleHeight + safetyMargin; // 扫描高度 = 车辆高度 + 安全间隙 - double minChannelTopZ = channelCoverage.MinChannelTopZ; // 提取最小通道顶面高度 - ProcessObstaclesWithBoundingBoxOptimized(document, channelCoverage.GridMap, channelRelatedItems, scanHeight, minChannelTopZ); + double minChannelTopZ = channelCoverage.MinChannelTopZ; // 提取最小通道顶面高度(模型单位) + ProcessObstaclesWithBoundingBoxOptimized(document, channelCoverage.GridMap, channelRelatedItems, scanHeightInModelUnits, minChannelTopZ); LogManager.Info($"【阶段2完成】障碍物处理后网格统计: {channelCoverage.GridMap.GetStatistics()}"); // 2.5. 为所有可通行网格设置PassableHeights确保高度约束检查 LogManager.Info("【生成网格地图】步骤2.5: 为可通行网格设置高度约束"); - SetChannelPassableHeights(channelCoverage.GridMap, scanHeight); + SetChannelPassableHeights(channelCoverage.GridMap, scanHeightInModelUnits); LogManager.Info($"【阶段2.5完成】高度约束设置后网格统计: {channelCoverage.GridMap.GetStatistics()}"); // 2.6. 单独处理门元素,设置为可通行,并设置通行高度 @@ -108,10 +119,8 @@ namespace NavisworksTransport.PathPlanning if (vehicleRadius > 0 || safetyMargin > 0) { LogManager.Info("【生成网格地图】步骤3: 应用车辆膨胀"); - double metersToModelUnits = UnitsConverter.GetMetersToUnitsConversionFactor(Application.ActiveDocument.Units); - double totalInflationRadius = (vehicleRadius + safetyMargin) * metersToModelUnits; - ApplyVehicleInflation(channelCoverage.GridMap, totalInflationRadius); - LogManager.Info($"【生成网格地图】车辆膨胀完成,膨胀半径: {totalInflationRadius:F2}模型单位"); + ApplyVehicleInflation(channelCoverage.GridMap, totalInflationRadiusInModelUnits); + LogManager.Info($"【生成网格地图】车辆膨胀完成,膨胀半径: {totalInflationRadiusInModelUnits:F2}模型单位"); LogManager.Info($"【阶段3完成】车辆膨胀后网格统计: {channelCoverage.GridMap.GetStatistics()}"); } @@ -195,7 +204,7 @@ namespace NavisworksTransport.PathPlanning // 获取门的限高属性 string heightLimitStr = CategoryAttributeManager.GetLogisticsPropertyValue(doorItem, CategoryAttributeManager.LogisticsProperties.HEIGHT_LIMIT); - double configuredHeight = CategoryAttributeManager.ParseLogisticsLimitValue(heightLimitStr, "限高"); + double configuredHeight = CategoryAttributeManager.ParseLogisticsLimitValue(heightLimitStr, "限高"); // 计算门的实际物理高度 double actualDoorHeight = bbox.Max.Z - bbox.Min.Z; @@ -270,14 +279,10 @@ namespace NavisworksTransport.PathPlanning /// 为所有可通行网格设置PassableHeights确保高度约束检查 /// /// 网格地图 - /// 扫描高度(车辆高度+安全间隙) - private void SetChannelPassableHeights(GridMap gridMap, double scanHeight) + /// 扫描高度(模型单位) + private void SetChannelPassableHeights(GridMap gridMap, double scanHeightInModelUnits) { - // scanHeight是米,需要转换为模型单位 - double metersToModelUnits = UnitsConverter.GetMetersToUnitsConversionFactor(Application.ActiveDocument.Units); - double scanHeightInModelUnits = scanHeight * metersToModelUnits; - - LogManager.Info($"【高度约束设置】开始为所有可通行网格设置高度约束,扫描高度: {scanHeight:F2}米 ({scanHeightInModelUnits:F2}模型单位)"); + LogManager.Info($"【高度约束设置】开始为所有可通行网格设置高度约束,扫描高度: {scanHeightInModelUnits:F2}模型单位"); int processedCount = 0; for (int x = 0; x < gridMap.Width; x++) @@ -563,17 +568,17 @@ namespace NavisworksTransport.PathPlanning /// 在障碍物周围扩展不可通行区域,考虑车辆尺寸 /// /// 网格地图 - /// 车辆半径 - public void ApplyVehicleInflation(GridMap gridMap, double vehicleRadius) + /// 车辆半径(模型单位) + private void ApplyVehicleInflation(GridMap gridMap, double vehicleRadiusInModelUnits) { - if (vehicleRadius <= 0) return; + if (vehicleRadiusInModelUnits <= 0) return; try - { + { // 计算膨胀半径(网格单元格数) - int inflationRadius = (int)Math.Ceiling(vehicleRadius / gridMap.CellSize); + int inflationRadius = (int)Math.Ceiling(vehicleRadiusInModelUnits / gridMap.CellSize); LogManager.Info($"[高效膨胀] 膨胀半径: {inflationRadius}个网格单元"); - + // 使用高效的距离变换算法 ApplyVehicleInflationOptimized(gridMap, inflationRadius); } @@ -977,7 +982,7 @@ namespace NavisworksTransport.PathPlanning List geometryItems, HashSet channelItemsSet, GridMap gridMap, - double scanHeight, + double scanHeightInModelUnits, double minChannelTopZ) { LogManager.Info("[轻量级后处理] 开始处理Search API筛选结果"); @@ -1038,7 +1043,7 @@ namespace NavisworksTransport.PathPlanning } // 快速计算:高度范围检查(纯数值计算,无API调用) - properties.IsInScanHeightRange = IsInScanHeightRange(properties.BoundingBox, minChannelTopZ, scanHeight); + properties.IsInScanHeightRange = IsInScanHeightRange(properties.BoundingBox, minChannelTopZ, scanHeightInModelUnits); if (!properties.IsInScanHeightRange) { skippedByHeight++; @@ -1068,9 +1073,9 @@ namespace NavisworksTransport.PathPlanning /// Navisworks文档 /// 网格地图 /// 通道模型项列表 - /// 扫描高度范围 + /// 扫描高度范围(模型单位) /// 最小通道顶面高度,用作扫描基准 - private void ProcessObstaclesWithBoundingBoxOptimized(Document document, GridMap gridMap, HashSet channelItems, double scanHeight, double minChannelTopZ) + private void ProcessObstaclesWithBoundingBoxOptimized(Document document, GridMap gridMap, HashSet channelItems, double scanHeightInModelUnits, double minChannelTopZ) { try { @@ -1085,7 +1090,7 @@ namespace NavisworksTransport.PathPlanning LogManager.Info($"[高性能障碍物处理] 输入统计 - 几何体项目: {geometryItems.Count}, 通道元素: {channelItemsSet.Count}"); // 阶段2:轻量级后处理(只对预筛选结果进行必要的API调用) - var itemCache = PostProcessGeometryItems(geometryItems, channelItemsSet, gridMap, scanHeight, minChannelTopZ); + var itemCache = PostProcessGeometryItems(geometryItems, channelItemsSet, gridMap, scanHeightInModelUnits, minChannelTopZ); // 阶段3:条件过滤(并行数值计算)- 使用50%CPU核心优化 LogManager.Info("[高性能障碍物处理] 阶段3: 并行条件过滤"); @@ -1354,16 +1359,16 @@ namespace NavisworksTransport.PathPlanning /// 检查包围盒是否在扫描高度范围内 /// /// 包围盒 - /// 最小通道顶面高度,用作扫描基准 - /// 扫描高度范围 + /// 最小通道顶面高度,用作扫描基准(模型单位) + /// 扫描高度范围(模型单位) /// 是否在高度范围内 - private bool IsInScanHeightRange(BoundingBox3D bbox, double minChannelTopZ, double scanHeight) + private bool IsInScanHeightRange(BoundingBox3D bbox, double minChannelTopZ, double scanHeightInModelUnits) { try { // 使用最低通道顶面高度作为扫描基准,避免门高度干扰 - var scanMinZ = minChannelTopZ; // 最低通道顶面 - var scanMaxZ = minChannelTopZ + scanHeight; // 从最低通道顶面向上扫描 + var scanMinZ = minChannelTopZ; // 最低通道顶面(模型单位) + var scanMaxZ = minChannelTopZ + scanHeightInModelUnits; // 从最低通道顶面向上扫描(模型单位) // 检查包围盒的Z范围是否与扫描范围有重叠 return !(bbox.Max.Z < scanMinZ || bbox.Min.Z > scanMaxZ);