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 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()); // can be optimized Double avoidDistance = MapDataUtils.getVehicleWaveSafeDistance(agvModel.getDiameter(), MapDataConstant.IDLE_DISTANCE_COE); List includeList = mapService.getWaveScopeByCode(lev, codeMatrix[i][j], avoidDistance); for (NavigateNode navigateNode : includeList) { String waveNode = waveMatrix[navigateNode.getX()][navigateNode.getY()]; // overlay 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 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 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(); } }