zy-acs-flow/src/map/constants.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
zy-acs-manager/src/main/java/com/zy/acs/manager/common/config/BeanConfig.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
zy-acs-manager/src/main/java/com/zy/acs/manager/core/DemoController.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
zy-acs-manager/src/main/java/com/zy/acs/manager/core/domain/UnlockPathTask.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
zy-acs-manager/src/main/java/com/zy/acs/manager/core/scheduler/MapDataWsScheduler.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/AgvDataService.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/MapService.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/PathQueueConsumer.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
zy-acs-flow/src/map/constants.js
@@ -1,5 +1,5 @@ export const ANIMATE_DURING_TIME = 800; export const ANIMATE_DURING_TIME = 600; export const MAP_DEFAULT_ROTATION = 270; zy-acs-manager/src/main/java/com/zy/acs/manager/common/config/BeanConfig.java
@@ -1,7 +1,11 @@ package com.zy.acs.manager.common.config; import com.zy.acs.manager.core.domain.UnlockPathTask; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import java.util.concurrent.LinkedBlockingQueue; /** * Created by vincent on 12/19/2023 @@ -9,4 +13,10 @@ @Configuration @ComponentScan(value = "com.zy.acs.common.config") public class BeanConfig { @Bean public LinkedBlockingQueue<UnlockPathTask> unlockTaskQueue() { return new LinkedBlockingQueue<>(); } } zy-acs-manager/src/main/java/com/zy/acs/manager/core/DemoController.java
@@ -69,6 +69,52 @@ return R.ok("RCS-FLOW-1.0.0"); } // {"msg":"Success","code":200,"data":[[38,2],[38,3],[38,4],[38,5],[38,6],[37,6],[36,6],[35,6],[34,6],[33,6],[32,6],[31,6],[30,6],[29,6],[28,6],[27,6],[26,6],[25,6]]} // {"msg":"Success","code":200,"data":[[38,2],[38,3],[38,4],[38,5],[38,6],[37,6],[36,6],[35,6],[34,6],[33,6],[32,6],[31,6],[30,6],[29,6],[28,6],[27,6],[26,6],[25,6]]} @RequestMapping(value = "/system/demo", method = {RequestMethod.GET, RequestMethod.POST}) public R demo() { long startTime = System.currentTimeMillis(); for (int i = 0; i < 1000; i++) { this.demo1(); } System.out.println(System.currentTimeMillis() - startTime); return R.ok(); } private R demo1() { List<String> path = new ArrayList<>(); path.add("00000035"); path.add("00000085"); path.add("00000135"); path.add("00000185"); path.add("00000235"); path.add("00000234"); path.add("00000233"); path.add("00000232"); path.add("00000231"); path.add("00000230"); path.add("00000229"); path.add("00000228"); path.add("00000227"); path.add("00000226"); path.add("00000225"); path.add("00000224"); path.add("00000223"); path.add("00000222"); // List<int[]> codeMatrixIdxList = new ArrayList<>(); // for (String pathStr : path) { // int[] codeMatrixIdx = mapDataDispatcher.getCodeMatrixIdx(null, pathStr); // codeMatrixIdxList.add(codeMatrixIdx); // } List<int[]> codeMatrixIdxList = mapDataDispatcher.getCodeMatrixIdxList(null, path); // System.out.println(codeMatrixIdxList.toString()); return R.ok().add(codeMatrixIdxList); } // @RequestMapping(value = "/system/route/generate", method = {RequestMethod.GET, RequestMethod.POST}) // public R generate() { // String[][] codeMatrix = mapDataDispatcher.getCodeMatrix(null); zy-acs-manager/src/main/java/com/zy/acs/manager/core/domain/UnlockPathTask.java
New file @@ -0,0 +1,20 @@ package com.zy.acs.manager.core.domain; import lombok.Data; @Data public class UnlockPathTask { private String agvNo; private String codeData; public UnlockPathTask() { } public UnlockPathTask(String agvNo, String codeData) { this.agvNo = agvNo; this.codeData = codeData; } } zy-acs-manager/src/main/java/com/zy/acs/manager/core/scheduler/MapDataWsScheduler.java
@@ -33,7 +33,7 @@ @Component public class MapDataWsScheduler { public static final int WEBSOCKET_BROADCAST_INTERVAL = 800; public static final int WEBSOCKET_BROADCAST_INTERVAL = 600; private ExecutorService singleThreadExecutor; zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/AgvDataService.java
@@ -84,9 +84,10 @@ AGV_12_UP agv_12_up = (AGV_12_UP) msgBody; // unlock path threadPoolRegulator.getInstance().execute(() -> { mapService.unlockPath(protocol.getAgvNo(), agv_12_up.getQrCode()); }); // threadPoolRegulator.getInstance().execute(() -> { // // }); // finish jam threadPoolRegulator.getInstance().execute(() -> jamService.checkIfFinish(agvId, agv_12_up.getQrCode())); zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/MapService.java
@@ -5,9 +5,9 @@ import com.zy.acs.framework.common.Cools; import com.zy.acs.manager.common.utils.MapDataUtils; import com.zy.acs.manager.core.constant.MapDataConstant; import com.zy.acs.manager.core.domain.UnlockPathTask; import com.zy.acs.manager.core.service.astart.*; import com.zy.acs.manager.core.service.astart.domain.AStarNavigateNode; import com.zy.acs.manager.core.service.astart.domain.DynamicNode; import com.zy.acs.manager.core.service.floyd.FloydNavigateService; import com.zy.acs.manager.manager.entity.Code; import com.zy.acs.manager.manager.entity.Loc; @@ -16,12 +16,13 @@ import com.zy.acs.manager.manager.service.CodeService; import com.zy.acs.manager.system.service.ConfigService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.time.StopWatch; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import java.util.*; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; /** @@ -45,6 +46,8 @@ private ConfigService configService; @Autowired private ActionService actionService; @Autowired private LinkedBlockingQueue<UnlockPathTask> unlockTaskQueue; /** * 寻址 ===>> A Star @@ -177,58 +180,12 @@ mapDataDispatcher.modifyDynamicMatrix(lev, codeMatrixIdxList, agvNo); } public synchronized void unlockPath(String agvNo, String codeData) { public void unlockPath(String agvNo, String codeData) { try { StopWatch stopWatch = new StopWatch(); stopWatch.start(); if (Cools.isEmpty(agvNo, codeData)) { return; unlockTaskQueue.offer(new UnlockPathTask(agvNo, codeData), 5, TimeUnit.SECONDS); } catch (InterruptedException e) { log.error("unlockTaskQueue", e); } Integer lev = null; String[][] codeMatrix = mapDataDispatcher.getCodeMatrix(null); int[] codeMatrixIdx = mapDataDispatcher.getCodeMatrixIdx(lev, codeData); DynamicNode[][] dynamicMatrix = mapDataDispatcher.getDynamicMatrix(lev); DynamicNode dynamicNode = dynamicMatrix[codeMatrixIdx[0]][codeMatrixIdx[1]]; int serial = dynamicNode.getSerial(); List<int[]> resetCodeIdxList = new ArrayList<>(); for (int i = 0; i < dynamicMatrix.length; i++) { for (int j = 0; j < dynamicMatrix[i].length; j++) { // if (i == codeMatrixIdx[0] && j == codeMatrixIdx[1]) { continue; } DynamicNode node = dynamicMatrix[i][j]; if (node.getVehicle().equals(agvNo)) { if (node.getSerial() < serial) { resetCodeIdxList.add(new int[] {i, j}); } } } } if (!Cools.isEmpty(resetCodeIdxList)) { mapDataDispatcher.clearDynamicMatrixByCodeList(lev, resetCodeIdxList); } stopWatch.stop(); if (stopWatch.getTime() > 50) { log.info("解锁路径函数花费时间为:{}毫秒......", stopWatch.getTime()); } } catch (Exception e) { log.error("MapService.unlockPath", e); } } public List<String> getWaveScopeByCodeList(Integer lev, List<String> codeList, Double radiusLen) { zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/PathQueueConsumer.java
New file @@ -0,0 +1,220 @@ package com.zy.acs.manager.core.service; import com.zy.acs.framework.common.Cools; import com.zy.acs.manager.core.domain.UnlockPathTask; import com.zy.acs.manager.core.service.astart.MapDataDispatcher; import com.zy.acs.manager.core.service.astart.domain.DynamicNode; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import java.util.*; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @Slf4j @Service public class PathQueueConsumer { private ExecutorService consumerExecutor; @Autowired private LinkedBlockingQueue<UnlockPathTask> unlockTaskQueue; @Autowired private MapDataDispatcher mapDataDispatcher; @PostConstruct public void init() { Integer lev = MapDataDispatcher.MAP_DEFAULT_LEV; this.consumerExecutor = Executors.newSingleThreadExecutor(); this.consumerExecutor.execute(() -> { while (!Thread.currentThread().isInterrupted()) { try { List<UnlockPathTask> tasks = new ArrayList<>(); // if unlockTaskQueue was empty, then block // tasks.add(unlockTaskQueue.take()); unlockTaskQueue.drainTo(tasks); if (tasks.isEmpty()) { Thread.sleep(30); } else { long startTime = System.currentTimeMillis(); List<int[]> resetCodeIdxList = null; if (tasks.size() == 1) { resetCodeIdxList = this.getResetCodeList(lev, tasks.get(0)); } else if (tasks.size() > 1) { log.info("consumer task count:{}", tasks.size()); resetCodeIdxList = this.getResetCodeList(lev,tasks); } if (!Cools.isEmpty(resetCodeIdxList)) { this.dealResetCodeList(lev, resetCodeIdxList); } log.info("consumer unlock path spend time:{}", System.currentTimeMillis() - startTime); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); log.error("PathQueueConsumer[Thread.currentThread.interrupt]", e); break; } catch (Exception e) { log.error("PathQueueConsumer", e); } } }); } private List<int[]> getResetCodeList(Integer lev, List<UnlockPathTask> tasks) { if (Cools.isEmpty(tasks)) { return new ArrayList<>(); } // 1.整理预处理数据 String[][] codeMatrix = mapDataDispatcher.getCodeMatrix(lev); DynamicNode[][] dynamicMatrix = mapDataDispatcher.getDynamicMatrix(lev); // Set<String> codeDataSet = tasks.stream().map(UnlockPathTask::getCodeData).collect(Collectors.toSet()); Set<String> agvNoSet = tasks.stream().map(UnlockPathTask::getAgvNo).collect(Collectors.toSet()); Map<String, Set<String>> agvNoCodeDataMap = new HashMap<>(); tasks.forEach(task -> agvNoCodeDataMap.computeIfAbsent(task.getAgvNo(), k -> new HashSet<>()).add(task.getCodeData())); // 2.获取agv的所有dynamic node,并且记录agv当前的dynamic node serial // agvNo : List<{code, serial}> Map<String, List<CodeSerial>> codeSerialMap = new HashMap<>(); // agvNo : serial Map<String, Integer> agvNoSerialMap = new HashMap<>(); for (int i = 0; i < dynamicMatrix.length; i++) { for (int j = 0; j < dynamicMatrix[i].length; j++) { DynamicNode dynamicNode = dynamicMatrix[i][j]; if (agvNoSet.contains(dynamicNode.getVehicle())) { String codeData = codeMatrix[i][j]; String vehicle = dynamicNode.getVehicle(); int serial = dynamicNode.getSerial(); List<CodeSerial> codeSerials = codeSerialMap.computeIfAbsent(vehicle, k -> new ArrayList<>()); codeSerials.add(new CodeSerial(new int[] {i, j}, serial)); if (agvNoCodeDataMap.get(vehicle).contains(codeData)) { Integer agvNoSerial = agvNoSerialMap.get(vehicle); if (null == agvNoSerial) { agvNoSerialMap.put(vehicle, serial); } else { if (serial > agvNoSerial) { agvNoSerialMap.put(vehicle, serial); } } } } } } // 3.处理codeSerialMap,获取所有agv需要释放的code matrix list List<int[]> resetCodeIdxList = new ArrayList<>(); for (Map.Entry<String, List<CodeSerial>> entry : codeSerialMap.entrySet()) { String agvNo = entry.getKey(); List<CodeSerial> codeSerials = entry.getValue(); Integer maxSerial = agvNoSerialMap.get(agvNo); for (CodeSerial codeSerial : codeSerials) { if (codeSerial.getSerial() < maxSerial) { resetCodeIdxList.add(codeSerial.getCodeMatrixIdx()); } } } return resetCodeIdxList; } private List<int[]> getResetCodeList(Integer lev, UnlockPathTask task) { if (null == task) { return new ArrayList<>(); } DynamicNode[][] dynamicMatrix = mapDataDispatcher.getDynamicMatrix(lev); String agvNo = task.getAgvNo(); int[] codeMatrixIdx = mapDataDispatcher.getCodeMatrixIdx(lev, task.getCodeData()); DynamicNode dynamicNode = dynamicMatrix[codeMatrixIdx[0]][codeMatrixIdx[1]]; int serial = dynamicNode.getSerial(); List<int[]> resetCodeIdxList = new ArrayList<>(); for (int i = 0; i < dynamicMatrix.length; i++) { for (int j = 0; j < dynamicMatrix[i].length; j++) { DynamicNode node = dynamicMatrix[i][j]; if (node.getVehicle().equals(agvNo)) { if (node.getSerial() < serial) { resetCodeIdxList.add(new int[] {i, j}); } } } } return resetCodeIdxList; } private void dealResetCodeList(Integer lev, List<int[]> resetCodeIdxList) { if (Cools.isEmpty(resetCodeIdxList)) { return; } mapDataDispatcher.clearDynamicMatrixByCodeList(lev, resetCodeIdxList); } @Data public static class CodeSerial { private String codeData; private int[] codeMatrixIdx; private int serial; public CodeSerial(int[] codeMatrixIdx, int serial) { this.codeMatrixIdx = codeMatrixIdx; this.serial = serial; } } @PreDestroy public void destroy() { if (this.consumerExecutor != null) { this.consumerExecutor.shutdown(); try { if (!this.consumerExecutor.awaitTermination(5, TimeUnit.SECONDS)) { this.consumerExecutor.shutdownNow(); if (!this.consumerExecutor.awaitTermination(5, TimeUnit.SECONDS)) { log.error("this.consumerExecutor failed to shutdown"); } } } catch (InterruptedException ie) { this.consumerExecutor.shutdownNow(); Thread.currentThread().interrupt(); } } } }