#
luxiaotao1123
2025-01-07 e14f937fac9ba2c9af1fffd4d37f0eba86292575
#
6个文件已修改
2个文件已添加
368 ■■■■ 已修改文件
zy-acs-flow/src/map/constants.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/common/config/BeanConfig.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/core/DemoController.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/core/domain/UnlockPathTask.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/core/scheduler/MapDataWsScheduler.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/AgvDataService.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/MapService.java 61 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/PathQueueConsumer.java 220 ●●●●● 补丁 | 查看 | 原始文档 | 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());
            });
            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;
            }
            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);
            unlockTaskQueue.offer(new UnlockPathTask(agvNo, codeData), 5, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            log.error("unlockTaskQueue", 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();
            }
        }
    }
}