| | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.zy.acs.common.utils.Utils; |
| | | import com.zy.acs.framework.common.Cools; |
| | | import com.zy.acs.framework.exception.CoolException; |
| | | import com.zy.acs.manager.common.config.RedisProperties; |
| | | import com.zy.acs.manager.common.utils.MapDataUtils; |
| | | import com.zy.acs.manager.core.constant.MapDataConstant; |
| | | import com.zy.acs.manager.core.domain.VehicleFootprint; |
| | | import com.zy.acs.manager.core.domain.VehicleRuntime; |
| | | import com.zy.acs.manager.core.service.astart.CodeNodeType; |
| | | import com.zy.acs.manager.core.service.astart.DynamicNodeType; |
| | | import com.zy.acs.manager.core.service.astart.MapDataDispatcher; |
| | | import com.zy.acs.manager.core.service.astart.NavigateNode; |
| | |
| | | import com.zy.acs.manager.manager.entity.AgvDetail; |
| | | import com.zy.acs.manager.manager.entity.AgvModel; |
| | | import com.zy.acs.manager.manager.entity.Code; |
| | | import com.zy.acs.manager.manager.enums.AgvModelType; |
| | | import com.zy.acs.manager.manager.service.AgvDetailService; |
| | | import com.zy.acs.manager.manager.service.AgvModelService; |
| | | import com.zy.acs.manager.manager.service.AgvService; |
| | |
| | | import java.io.InputStreamReader; |
| | | import java.nio.file.Files; |
| | | import java.nio.file.StandardCopyOption; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.concurrent.ExecutorService; |
| | | import java.util.concurrent.Executors; |
| | | import java.util.concurrent.TimeUnit; |
| | |
| | | } |
| | | |
| | | |
| | | public boolean calcWaveScope() { |
| | | public boolean calcWaveScope(AgvModel agvModel) { |
| | | Integer lev = MapDataDispatcher.MAP_DEFAULT_LEV; |
| | | boolean lockAcquired = false; |
| | | |
| | |
| | | } |
| | | |
| | | // return this.calcWaveScopeByPython(lev); |
| | | return this.calcWaveScopeByJava(lev); |
| | | return this.calcWaveScopeByJava(lev, agvModel); |
| | | |
| | | } catch (Exception e) { |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | private boolean calcWaveScopeByPython(Integer lev) throws Exception { |
| | | private boolean calcWaveScopeByPython(Integer lev, AgvModel agvModel) throws Exception { |
| | | if (null == agvModel.getDiameter() || agvModel.getDiameter() <= 0) { |
| | | log.warn("There is no diameter or diameter value was wrong..."); |
| | | } |
| | | |
| | | // python |
| | | AgvModel agvModel = agvModelService.selectByType(AgvModelType.CTU_BOX_TRANSPORT_AGV.toString()); // can be optimized |
| | | Double avoidDistance = MapDataUtils.getVehicleWaveSafeDistance(agvModel.getDiameter(), MapDataConstant.MAX_DISTANCE_BETWEEN_ADJACENT_AGV_FACTOR); |
| | | |
| | | if (null == pythonFile) { |
| | |
| | | return true; |
| | | } |
| | | |
| | | private boolean calcWaveScopeByJava(Integer lev) throws Exception { |
| | | |
| | | AgvModel agvModel = agvModelService.selectByType(AgvModelType.CTU_BOX_TRANSPORT_AGV.toString()); // can be optimized |
| | | Double avoidDistance = MapDataUtils.getVehicleWaveSafeDistance(agvModel.getDiameter(), MapDataConstant.MAX_DISTANCE_BETWEEN_ADJACENT_AGV_FACTOR); |
| | | |
| | | // java |
| | | private boolean calcWaveScopeByJava(Integer lev, AgvModel agvModel) { |
| | | assert null != agvModel.getDiameter(); |
| | | String[][] codeMatrix = mapDataDispatcher.getCodeMatrix(lev); |
| | | String[][] waveMatrix = mapDataDispatcher.initWaveMatrix(lev); |
| | | |
| | | // lock path |
| | | DynamicNode[][] dynamicMatrix = mapDataDispatcher.getDynamicMatrix(lev); |
| | | |
| | | // 当前调度车型的最大旋转半径 |
| | | double bufferRadius = buildFootprint(agvModel).maxExtent(); |
| | | |
| | | Map<String, VehicleRuntime> runtimeCache = new HashMap<>(); |
| | | for (int i = 0; i < dynamicMatrix.length; i++) { |
| | | for (int j = 0; j < dynamicMatrix[i].length; j++) { |
| | | DynamicNode dynamicNode = dynamicMatrix[i][j]; |
| | | String vehicle = dynamicNode.getVehicle(); |
| | | if (!DynamicNodeType.ACCESS.val.equals(vehicle) && !DynamicNodeType.BLOCK.val.equals(vehicle)) { |
| | | if (DynamicNodeType.ACCESS.val.equals(vehicle) || DynamicNodeType.BLOCK.val.equals(vehicle)) { |
| | | continue; |
| | | } |
| | | String codeData = codeMatrix[i][j]; |
| | | if (CodeNodeType.NONE.val.equals(codeData)) { |
| | | continue; |
| | | } |
| | | |
| | | List<NavigateNode> includeList = mapService.getWaveScopeByCode(lev, codeMatrix[i][j], avoidDistance); |
| | | // cache |
| | | VehicleRuntime runtime = runtimeCache.computeIfAbsent(vehicle, this::loadRuntime); |
| | | assert null != runtime; assert null != runtime.getFootprint(); |
| | | |
| | | for (NavigateNode navigateNode : includeList) { |
| | | String waveNode = waveMatrix[navigateNode.getX()][navigateNode.getY()]; // overlay |
| | | waveMatrix[navigateNode.getX()][navigateNode.getY()] = MapDataUtils.generateWaveNode(waveNode, vehicle); |
| | | } |
| | | List<NavigateNode> includeList = mapService.getWaveScopeByCode(lev, codeData, runtime.getFootprint(), runtime.getHeadingRad(), bufferRadius); |
| | | |
| | | for (NavigateNode navigateNode : includeList) { |
| | | String waveNode = waveMatrix[navigateNode.getX()][navigateNode.getY()]; |
| | | waveMatrix[navigateNode.getX()][navigateNode.getY()] = MapDataUtils.generateWaveNode(waveNode, vehicle); |
| | | } |
| | | } |
| | | } |
| | | |
| | | // mapDataDispatcher.printMatrix(waveMatrix); |
| | | mapDataDispatcher.setWaveMatrix(lev, waveMatrix); |
| | | |
| | | return true; |
| | | } |
| | | |
| | | private VehicleRuntime loadRuntime(String agvNo) { |
| | | AgvModel model = agvModelService.getByAgvNo(agvNo); |
| | | if (model == null) { |
| | | return null; |
| | | } |
| | | VehicleFootprint footprint = this.buildFootprint(model); |
| | | |
| | | AgvDetail detail = agvDetailService.selectByAgvNo(agvNo); |
| | | if (detail == null || null == detail.getAgvAngle()) { |
| | | throw new CoolException(agvNo + " does not have an agv angle"); |
| | | } |
| | | double headingDeg = detail.getAgvAngle(); |
| | | |
| | | return new VehicleRuntime(footprint, Math.toRadians(90 - headingDeg)); |
| | | } |
| | | |
| | | private double toMapLength(Integer mm) { |
| | | if (mm == null || mm <= 0) { |
| | | throw new IllegalArgumentException("Invalid map length: " + mm); |
| | | } |
| | | return MapDataUtils.getVehicleWaveSafeDistance(mm, MapDataConstant.MAX_DISTANCE_BETWEEN_ADJACENT_AGV_FACTOR); |
| | | } |
| | | |
| | | private double resolveAvoidDistance(AgvModel agvModel) { |
| | | if (agvModel == null || agvModel.getDiameter() == null || agvModel.getDiameter() <= 0) { |
| | | return 0D; |
| | | } |
| | | return MapDataUtils.getVehicleWaveSafeDistance(agvModel.getDiameter(), MapDataConstant.MAX_DISTANCE_BETWEEN_ADJACENT_AGV_FACTOR); |
| | | } |
| | | |
| | | private VehicleFootprint buildFootprint(AgvModel agvModel) { |
| | | if (null == agvModel) { |
| | | throw new IllegalArgumentException("AgvModel is null"); |
| | | } |
| | | if (agvModel.getHeadOffset() == null || agvModel.getHeadOffset() <= 0) { |
| | | throw new IllegalArgumentException("Invalid head offset: " + agvModel.getHeadOffset()); |
| | | } |
| | | if (agvModel.getTailOffset() == null || agvModel.getTailOffset() <= 0) { |
| | | throw new IllegalArgumentException("Invalid tail offset: " + agvModel.getTailOffset()); |
| | | } |
| | | if (agvModel.getWidth() == null || agvModel.getWidth() <= 0) { |
| | | throw new IllegalArgumentException("Invalid width: " + agvModel.getWidth()); |
| | | } |
| | | |
| | | double head = toMapLength(agvModel.getHeadOffset()); |
| | | double tail = toMapLength(agvModel.getTailOffset()); |
| | | double halfWidth = toMapLength(agvModel.getWidth()) / 2; |
| | | |
| | | return new VehicleFootprint(head, tail, halfWidth); |
| | | } |
| | | |
| | | private File loadPythonFile() { |
| | | File scriptFile = null; |
| | | try { |