| package com.zy.acs.manager.core.service; | 
|   | 
| import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | 
| import com.zy.acs.framework.common.Cools; | 
| import com.zy.acs.common.utils.Utils; | 
| import com.zy.acs.manager.common.utils.MapDataUtils; | 
| import com.zy.acs.manager.core.constant.MapDataConstant; | 
| 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.core.service.astart.domain.DynamicNode; | 
| import com.zy.acs.manager.manager.entity.Agv; | 
| 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.service.AgvDetailService; | 
| import com.zy.acs.manager.manager.service.AgvModelService; | 
| import com.zy.acs.manager.manager.service.AgvService; | 
| import com.zy.acs.manager.manager.service.CodeService; | 
| import lombok.extern.slf4j.Slf4j; | 
| import org.apache.commons.lang.time.StopWatch; | 
| import org.springframework.beans.factory.annotation.Autowired; | 
| import org.springframework.stereotype.Component; | 
|   | 
| import javax.annotation.PostConstruct; | 
| import javax.annotation.PreDestroy; | 
| import java.util.List; | 
| import java.util.concurrent.ExecutorService; | 
| import java.util.concurrent.Executors; | 
| import java.util.concurrent.TimeUnit; | 
| import java.util.concurrent.locks.ReentrantLock; | 
|   | 
| /** | 
|  * Created by vincent on 8/6/2024 | 
|  */ | 
| @Slf4j | 
| @Component | 
| public class AvoidWaveCalculator { | 
|   | 
|     private static final ReentrantLock lock = new ReentrantLock(Boolean.TRUE); | 
|   | 
|     private static final int LOCK_TIMEOUT = 5; | 
|   | 
|     private ExecutorService singleThreadExecutor; | 
|   | 
|     @Autowired | 
|     private MapDataDispatcher mapDataDispatcher; | 
|     @Autowired | 
|     private AgvService agvService; | 
|     @Autowired | 
|     private AgvDetailService agvDetailService; | 
|     @Autowired | 
|     private AgvModelService agvModelService; | 
|     @Autowired | 
|     private CodeService codeService; | 
|     @Autowired | 
|     private MapService mapService; | 
|   | 
|     @PostConstruct | 
|     @SuppressWarnings("all") | 
|     public void execute() { | 
|         this.singleThreadExecutor = Executors.newSingleThreadExecutor(); | 
|         this.singleThreadExecutor.execute(() -> { | 
|   | 
|             try { Thread.sleep(200); } catch (InterruptedException ignore) {} | 
|   | 
|             this.calcDynamicNodeWhenBoot(); | 
|   | 
|             while (!Thread.currentThread().isInterrupted()) { | 
|   | 
|                 this.calcWaveScope(); | 
|   | 
|                 try { Thread.sleep(500); } catch (InterruptedException ignore) {} | 
|             } | 
|   | 
|         }); | 
|     } | 
|   | 
|     public void calcWaveScope() { | 
|         Integer lev = MapDataDispatcher.MAP_DEFAULT_LEV; | 
|         boolean lockAcquired = false; | 
|   | 
|         StopWatch stopWatch = new StopWatch(); | 
|         stopWatch.start(); | 
|   | 
|         try { | 
|             if (!(lockAcquired = lock.tryLock(LOCK_TIMEOUT, TimeUnit.SECONDS))) { | 
|                 log.warn("AvoidWaveCalculator execute fail, cause can not acquire lock ..."); | 
|                 return; | 
|             } | 
|   | 
|             String[][] codeMatrix = mapDataDispatcher.getCodeMatrix(lev); | 
|             String[][] waveMatrix = mapDataDispatcher.initWaveMatrix(lev); | 
|   | 
|             // vehicle | 
| //            for (Agv agv : agvService.list(new LambdaQueryWrapper<>())) { | 
| //                AgvDetail agvDetail = agvDetailService.selectByAgvId(agv.getId()); | 
| //                AgvModel agvModel = agvModelService.getById(agv.getAgvModel()); | 
| //                Code code = codeService.getById(agvDetail.getRecentCode()); | 
| // | 
| //                Double avoidDistance = MapDataUtils.getVehicleWaveSafeDistance(agvModel.getDiameter(), MapDataConstant.IDLE_DISTANCE_COE); | 
| //                List<NavigateNode> includeList = mapService.getWaveScopeByCode(lev, code.getData(), avoidDistance); | 
| // | 
| //                for (NavigateNode navigateNode : includeList) { | 
| //                    String waveNode = waveMatrix[navigateNode.getX()][navigateNode.getY()]; | 
| //                    waveMatrix[navigateNode.getX()][navigateNode.getY()] = MapDataUtils.generateWaveNode(waveNode, agv.getUuid()); | 
| //                } | 
| // | 
| //            } | 
|   | 
|             // lock path | 
|             DynamicNode[][] dynamicMatrix = mapDataDispatcher.getDynamicMatrix(lev); | 
|             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)) { | 
|                         AgvModel agvModel = agvModelService.getById(agvService.selectByUuid(vehicle).getAgvModel()); | 
|   | 
|                         Double avoidDistance = MapDataUtils.getVehicleWaveSafeDistance(agvModel.getDiameter(), MapDataConstant.IDLE_DISTANCE_COE); | 
|                         List<NavigateNode> includeList = mapService.getWaveScopeByCode(lev, codeMatrix[i][j], avoidDistance); | 
|   | 
|                         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); | 
|   | 
|         } catch (Exception e) { | 
|   | 
|             log.error(this.getClass().getSimpleName(), e); | 
|         } finally { | 
|   | 
|             if (lockAcquired) { | 
|                 lock.unlock(); | 
|             } | 
|   | 
|             stopWatch.stop(); | 
|             if (stopWatch.getTime() > 50) { | 
|                 log.info("滤波函数花费时间为:{}毫秒......", stopWatch.getTime()); | 
|             } | 
|   | 
|         } | 
|     } | 
|   | 
|     public void syncWaveBySingleVeh(String agvNo, String codeData) { | 
|         if (Cools.isEmpty(agvNo, codeData)) { | 
|             return; | 
|         } | 
|   | 
|         boolean lockAcquired = false; | 
|         Integer lev = MapDataDispatcher.MAP_DEFAULT_LEV; | 
|   | 
|         try { | 
|             if (!(lockAcquired = lock.tryLock(LOCK_TIMEOUT, TimeUnit.SECONDS))) { | 
|                 log.warn("AvoidWaveCalculator syncWaveBySingleVeh fail, cause can not acquire lock ..."); | 
|                 return; | 
|             } | 
|   | 
|             Agv agv = agvService.selectByUuid(agvNo); | 
|             AgvModel agvModel = agvModelService.getById(agv.getAgvModel()); | 
|             Double avoidDistance = MapDataUtils.getVehicleWaveSafeDistance(agvModel.getDiameter(), MapDataConstant.IDLE_DISTANCE_COE); | 
|   | 
|             String[][] waveMatrix = mapDataDispatcher.getWaveMatrix(lev); | 
|   | 
|             List<NavigateNode> includeList = mapService.getWaveScopeByCode(lev, codeData, avoidDistance); | 
|   | 
|             for (NavigateNode navigateNode : includeList) { | 
|                 String waveNode = waveMatrix[navigateNode.getX()][navigateNode.getY()]; | 
|                 waveMatrix[navigateNode.getX()][navigateNode.getY()] = MapDataUtils.generateWaveNode(waveNode, agv.getUuid()); | 
|             } | 
|   | 
|             mapDataDispatcher.setWaveMatrix(lev, waveMatrix); | 
|   | 
|         } catch (Exception e) { | 
|             log.error("AvoidWaveCalculator.syncWaveBySingleVeh fail", e); | 
|         } finally { | 
|   | 
|             if (lockAcquired) { | 
|                 lock.unlock(); | 
|             } | 
|         } | 
|     } | 
|   | 
|     public void calcDynamicNodeWhenBoot() { | 
|         List<Agv> agvList = agvService.list(new LambdaQueryWrapper<>()); | 
|         DynamicNode[][] dynamicMatrix = mapDataDispatcher.getDynamicMatrix(null); | 
|   | 
|         for (Agv agv : agvList) { | 
|             calcDynamicNodeByVehicle(agv, dynamicMatrix); | 
|         } | 
|     } | 
|   | 
|     public void calcDynamicNodeByVehicle(Agv agv, DynamicNode[][] dynamicMatrix) { | 
|         if (null == dynamicMatrix) { | 
|             dynamicMatrix = mapDataDispatcher.getDynamicMatrix(null); | 
|         } | 
|         AgvDetail agvDetail = agvDetailService.selectByAgvId(agv.getId()); | 
|         if (null == agvDetail) { | 
|             return; | 
|         } | 
|         if (agvDetail.getPos() == null || agvDetail.getPos() != 1) { | 
|             return; | 
|         } | 
|         Long recentCode = agvDetail.getRecentCode(); | 
|         if (null == recentCode) { | 
|             return; | 
|         } | 
|         Code code = codeService.getById(recentCode); | 
|         if (null == code) { | 
|             return; | 
|         } | 
|         int[] codeMatrixIdx = mapDataDispatcher.getCodeMatrixIdx(null, code.getData()); | 
|         DynamicNode dynamicNode = dynamicMatrix[codeMatrixIdx[0]][codeMatrixIdx[1]]; | 
|         String vehicle = dynamicNode.getVehicle(); | 
|         if (vehicle.equals(DynamicNodeType.ACCESS.val)) { | 
|             mapDataDispatcher.modifyDynamicMatrix(null, Utils.singletonList(code.getData()), agv.getUuid()); | 
|         } | 
|     } | 
|   | 
|     @PreDestroy | 
|     public void destroy() { | 
|         this.singleThreadExecutor.shutdownNow(); | 
|     } | 
|   | 
| } |