zy-acs-manager/src/main/java/com/zy/acs/manager/core/domain/FilterLaneDto.java
@@ -8,15 +8,15 @@ @Data public class FilterLaneDto { private Lane originLane; private LaneDto originLaneDto; private Lane destinationLane; private LaneDto destinationLaneDto; private List<String> actualAvailableAgvNos = new ArrayList<>(); public FilterLaneDto(Lane originLane, Lane destinationLane, List<String> actualAvailableAgvNos) { this.originLane = originLane; this.destinationLane = destinationLane; public FilterLaneDto(LaneDto originLaneDto, LaneDto destinationLaneDto, List<String> actualAvailableAgvNos) { this.originLaneDto = originLaneDto; this.destinationLaneDto = destinationLaneDto; this.actualAvailableAgvNos = actualAvailableAgvNos; } zy-acs-manager/src/main/java/com/zy/acs/manager/core/domain/LaneDto.java
File was renamed from zy-acs-manager/src/main/java/com/zy/acs/manager/core/domain/Lane.java @@ -1,6 +1,8 @@ package com.zy.acs.manager.core.domain; import com.alibaba.fastjson.JSON; import com.zy.acs.framework.common.Cools; import com.zy.acs.manager.manager.entity.Lane; import lombok.Data; import java.util.*; @@ -9,18 +11,18 @@ * Created by vincent on 10/24/2024 */ @Data public class Lane { public class LaneDto { private String laneId; private Long laneId; private String hashCode; private List<String> codes = new ArrayList<>(); public Lane() { public LaneDto() { } public Lane(String laneId) { public LaneDto(Long laneId) { this.laneId = laneId; } @@ -96,4 +98,15 @@ this.codes.removeIf(code -> adjacencyCodeMap.get(code).size() > 2); } public static LaneDto parse(Lane lane) { if (null == lane) { return null; } LaneDto laneDto = new LaneDto(); laneDto.setLaneId(lane.getId()); laneDto.setHashCode(lane.getHashCode()); laneDto.setCodes(JSON.parseArray(lane.getCodes(), String.class)); return laneDto; } } zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/AllocateService.java
@@ -5,7 +5,7 @@ import com.zy.acs.manager.common.utils.CommonUtil; import com.zy.acs.manager.core.domain.AgvCntDto; import com.zy.acs.manager.core.domain.FilterLaneDto; import com.zy.acs.manager.core.domain.Lane; import com.zy.acs.manager.core.domain.LaneDto; import com.zy.acs.manager.core.domain.TaskPosDto; import com.zy.acs.manager.manager.entity.*; import com.zy.acs.manager.manager.enums.*; @@ -135,11 +135,11 @@ } // record lane hash for later dispatch/traffic-control logic if (filterLaneDto.getOriginLane() != null) { task.setOriLaneHash(filterLaneDto.getOriginLane().getHashCode()); if (filterLaneDto.getOriginLaneDto() != null) { task.setOriLaneHash(filterLaneDto.getOriginLaneDto().getHashCode()); } if (filterLaneDto.getDestinationLane() != null) { task.setDestLaneHash(filterLaneDto.getDestinationLane().getHashCode()); if (filterLaneDto.getDestinationLaneDto() != null) { task.setDestLaneHash(filterLaneDto.getDestinationLaneDto().getHashCode()); } return agvNo; @@ -167,8 +167,8 @@ if (null == filterLaneDto) { return null; } Lane originLane = filterLaneDto.getOriginLane(); Lane destinationLane = filterLaneDto.getDestinationLane(); LaneDto originLaneDto = filterLaneDto.getOriginLaneDto(); LaneDto destinationLaneDto = filterLaneDto.getDestinationLaneDto(); List<String> actualAvailableAgvNos = filterLaneDto.getActualAvailableAgvNos(); if (Cools.isEmpty(actualAvailableAgvNos)) { return null; @@ -180,11 +180,11 @@ calcAllocateWeight(o1, task) )); if (null != originLane) { task.setOriLaneHash(originLane.getHashCode()); if (null != originLaneDto) { task.setOriLaneHash(originLaneDto.getHashCode()); } if (null != destinationLane) { task.setDestLaneHash(destinationLane.getHashCode()); if (null != destinationLaneDto) { task.setDestLaneHash(destinationLaneDto.getHashCode()); } return actualAvailableAgvNos.get(0); @@ -291,13 +291,13 @@ Integer maxAgvCountInLane = configService.getVal("maxAgvCountInLane", Integer.class); // checkout lane Lane originLane = taskService.checkoutOriginLane(task); Lane destinationLane = taskService.checkoutDestinationLane(task); LaneDto originLaneDto = taskService.checkoutOriginLane(task); LaneDto destinationLaneDto = taskService.checkoutDestinationLane(task); // allocate about origin List<String> availableAgvNosByOriLane = new ArrayList<>(availableAgvNos); if (null != originLane) { List<String> agvNosByOriLane = findAgvNosByLane(originLane); // the agv list that had tasks in this lane if (null != originLaneDto) { List<String> agvNosByOriLane = findAgvNosByLane(originLaneDto); // the agv list that had tasks in this lane // if full lane if (agvNosByOriLane.size() >= maxAgvCountInLane) { @@ -310,8 +310,8 @@ // allocate about destination List<String> availableAgvNosByDestLane = new ArrayList<>(availableAgvNos); if (null != destinationLane) { List<String> agvNosByDestLane = findAgvNosByLane(destinationLane); if (null != destinationLaneDto) { List<String> agvNosByDestLane = findAgvNosByLane(destinationLaneDto); if (agvNosByDestLane.size() >= maxAgvCountInLane) { availableAgvNosByDestLane = Cools.getIntersection(agvNosByDestLane, availableAgvNos); @@ -334,14 +334,14 @@ return null; } return new FilterLaneDto(originLane, destinationLane, actualAvailableAgvNos); return new FilterLaneDto(originLaneDto, destinationLaneDto, actualAvailableAgvNos); } public List<String> findAgvNosByLane(Lane lane) { if (null == lane) { public List<String> findAgvNosByLane(LaneDto laneDto) { if (null == laneDto) { return new ArrayList<>(); } List<Task> taskList = taskService.findRunningTasksByLaneHash(lane.getHashCode()); List<Task> taskList = taskService.findRunningTasksByLaneHash(laneDto.getHashCode()); if (Cools.isEmpty(taskList)) { return new ArrayList<>(); } @@ -412,11 +412,11 @@ } public Boolean validCapacityOfLane(String agvNo, Code code) { Lane lane = laneBuilder.search(code.getData()); if (null != lane) { LaneDto laneDto = laneBuilder.search(code.getData()); if (null != laneDto) { Integer maxAgvCountInLane = configService.getVal("maxAgvCountInLane", Integer.class); List<String> agvNosByLane = this.findAgvNosByLane(lane); List<String> agvNosByLane = this.findAgvNosByLane(laneDto); agvNosByLane.remove(agvNo); if (agvNosByLane.size() >= maxAgvCountInLane) { return false; zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/LaneBuilder.java
@@ -1,16 +1,14 @@ package com.zy.acs.manager.core.service; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.zy.acs.common.constant.RedisConstant; import com.zy.acs.common.utils.GsonUtils; import com.zy.acs.common.utils.RedisSupport; import com.zy.acs.framework.common.Cools; import com.zy.acs.framework.common.SnowflakeIdWorker; import com.zy.acs.manager.core.domain.Lane; import com.zy.acs.manager.core.domain.LaneDto; import com.zy.acs.manager.core.service.astart.MapDataDispatcher; import com.zy.acs.manager.manager.entity.Code; import com.zy.acs.manager.manager.entity.Lane; import com.zy.acs.manager.manager.enums.StatusType; import com.zy.acs.manager.manager.service.CodeService; import com.zy.acs.manager.manager.service.LaneService; import com.zy.acs.manager.manager.service.RouteService; import com.zy.acs.manager.system.service.ConfigService; import lombok.extern.slf4j.Slf4j; @@ -32,24 +30,25 @@ @Service public class LaneBuilder { private final RedisSupport redis = RedisSupport.defaultRedisSupport; // private final RedisSupport redis = RedisSupport.defaultRedisSupport; private List<Lane> lanes = new ArrayList<>(); private final List<LaneDto> laneDtoList = new ArrayList<>(); private final Map<String, List<String>> adjacencyCodeMap = new HashMap<>(); private final Map<String, List<int[]>> laneCodeIdxMap = new HashMap<>(); private final Map<String, Lane> codeLaneMap = new HashMap<>(); private final Map<String, LaneDto> codeLaneMap = new HashMap<>(); private boolean initialized = Boolean.FALSE; @Autowired private LaneService laneService; @Autowired private CodeService codeService; @Autowired private RouteService routeService; @Autowired private SnowflakeIdWorker snowflakeIdWorker; @Autowired private ConfigService configService; @Autowired @@ -61,7 +60,7 @@ return this.initialized; } public Lane search(String codeData) { public LaneDto search(String codeData) { if (Cools.isEmpty(codeData) || !this.initialized) { return null; } @@ -91,25 +90,31 @@ @EventListener(ApplicationReadyEvent.class) public void init() { Integer lev = MapDataDispatcher.MAP_DEFAULT_LEV; String laneDataStr = redis.getValue(RedisConstant.MAP_LANE_DATA, String.valueOf(lev)); if (!Cools.isEmpty(laneDataStr)) { this.lanes = GsonUtils.fromJsonToList(laneDataStr, Lane.class); } else { // String laneDataStr = redis.getValue(RedisConstant.MAP_LANE_DATA, String.valueOf(lev)); List<Lane> lanes = laneService.list(new LambdaQueryWrapper<Lane>() // .eq(Lane::getZoneId, zoneId) .eq(Lane::getStatus, StatusType.ENABLE.val) .orderByAsc(Lane::getId) ); if (!Cools.isEmpty(lanes)) { lanes.forEach(lane -> this.laneDtoList.add(LaneDto.parse(lane))); // this.laneDtoList = GsonUtils.fromJsonToList(laneDataStr, LaneDto.class); } else { StopWatch stopWatch = new StopWatch(); stopWatch.start(); this.initLaneData(); stopWatch.stop(); log.info("the rcs system calculated lane data which has spend {} millisecond......", stopWatch.getTime()); redis.setValue(RedisConstant.MAP_LANE_DATA, String.valueOf(lev), GsonUtils.toJson(this.lanes)); if (!Cools.isEmpty(this.laneDtoList)) { laneService.batchSaveByLaneDtoList(null, this.laneDtoList); // redis.setValue(RedisConstant.MAP_LANE_DATA, String.valueOf(lev), GsonUtils.toJson(this.laneDtoList)); } } this.generateLaneCodeIdx(null); this.initialized = Boolean.TRUE; // System.out.println(GsonUtils.toJson(this.lanes)); } private void initLaneData() { @@ -149,10 +154,10 @@ List<String> neighbors = this.adjacencyCodeMap.get(codeData); for (String neighbor : neighbors) { if (this.adjacencyCodeMap.get(neighbor).size() == 2 && !visited.contains(neighbor)) { Lane lane = new Lane(String.valueOf(snowflakeIdWorker.nextId()).substring(3)); lane.getCodes().add(codeData); // 包含起点 this.dfsCalcIncludingEnd(codeData, neighbor, lane, visited); this.lanes.add(lane); LaneDto laneDto = new LaneDto(); laneDto.getCodes().add(codeData); // 包含起点 this.dfsCalcIncludingEnd(codeData, neighbor, laneDto, visited); this.laneDtoList.add(laneDto); } } } @@ -161,17 +166,17 @@ for (String codeData : codeDataList) { if (this.adjacencyCodeMap.get(codeData).size() == 2 && !visited.contains(codeData)) { // 检查是否为环路的一部分 Lane lane = new Lane(String.valueOf(snowflakeIdWorker.nextId()).substring(3)); this.dfsCalcForLoop(codeData, null, lane, visited); this.lanes.add(lane); LaneDto laneDto = new LaneDto(); this.dfsCalcForLoop(codeData, null, laneDto, visited); this.laneDtoList.add(laneDto); } } } private void dfsCalcIncludingEnd(String start, String current, Lane lane, Set<String> visited) { lane.getCodes().add(current); private void dfsCalcIncludingEnd(String start, String current, LaneDto laneDto, Set<String> visited) { laneDto.getCodes().add(current); visited.add(current); List<String> neighbors = this.adjacencyCodeMap.get(current); @@ -188,19 +193,19 @@ int degree = this.adjacencyCodeMap.get(neighbor).size(); if (degree == 2) { if (this.isSameDirection(current, neighbor, start)) { this.dfsCalcIncludingEnd(current, neighbor, lane, visited); this.dfsCalcIncludingEnd(current, neighbor, laneDto, visited); } } else { // 终点或拐弯点,包含并停止 lane.getCodes().add(neighbor); laneDto.getCodes().add(neighbor); visited.add(neighbor); } } } } private void dfsCalcForLoop(String current, String parent, Lane lane, Set<String> visited) { lane.getCodes().add(current); private void dfsCalcForLoop(String current, String parent, LaneDto laneDto, Set<String> visited) { laneDto.getCodes().add(current); visited.add(current); List<String> neighbors = this.adjacencyCodeMap.get(current); @@ -217,10 +222,10 @@ int degree = this.adjacencyCodeMap.get(neighbor).size(); if (degree == 2) { if (this.isSameDirection(current, neighbor, parent)) { this.dfsCalcForLoop(current, neighbor, lane, visited); this.dfsCalcForLoop(current, neighbor, laneDto, visited); } } else { lane.getCodes().add(neighbor); laneDto.getCodes().add(neighbor); visited.add(neighbor); } } @@ -262,10 +267,10 @@ * 3.then merge above two lane because they can connect each other */ private void mergeDeadEndLane() { Iterator<Lane> iterator = this.lanes.iterator(); Iterator<LaneDto> iterator = this.laneDtoList.iterator(); while (iterator.hasNext()) { Lane lane = iterator.next(); String[] endPoints = lane.queryEndPoints(); LaneDto laneDto = iterator.next(); String[] endPoints = laneDto.queryEndPoints(); if (null == endPoints) { continue; } @@ -294,15 +299,15 @@ String anotherPoint = deadEndPoint.equals(startPoint) ? endPoint : startPoint; List<String> anotherPointNears = this.adjacencyCodeMap.get(anotherPoint); for (String anotherPointNear : anotherPointNears) { if (!lane.getCodes().contains(anotherPointNear) && this.adjacencyCodeMap.get(anotherPointNear).size() == 2) { if (!laneDto.getCodes().contains(anotherPointNear) && this.adjacencyCodeMap.get(anotherPointNear).size() == 2) { for (Lane lane0 : new ArrayList<>(lanes)) { if (lane0.getCodes().contains(anotherPointNear)) { for (LaneDto laneDto0 : new ArrayList<>(laneDtoList)) { if (laneDto0.getCodes().contains(anotherPointNear)) { lane0.getCodes().addAll(lane.getCodes()); laneDto0.getCodes().addAll(laneDto.getCodes()); iterator.remove(); lane0.sortUsingDfs(this.adjacencyCodeMap); laneDto0.sortUsingDfs(this.adjacencyCodeMap); } } @@ -315,21 +320,21 @@ } private void deleteInteractionPoint() { for (Lane lane : this.lanes) { lane.removeInteraction(this.adjacencyCodeMap); for (LaneDto laneDto : this.laneDtoList) { laneDto.removeInteraction(this.adjacencyCodeMap); } } private void filterLanesWithFewPoints() { Integer maxAgvCountInLane = configService.getVal("maxAgvCountInLane", Integer.class); this.lanes.removeIf(next -> next.getCodes().size() <= Optional.ofNullable(maxAgvCountInLane).orElse(2)); this.laneDtoList.removeIf(next -> next.getCodes().size() <= Optional.ofNullable(maxAgvCountInLane).orElse(2)); } private void generateLaneHash() { for (Lane lane : this.lanes) { String hashCode = generateDigest(lane.getCodes()); lane.setHashCode(hashCode); for (LaneDto laneDto : this.laneDtoList) { String hashCode = generateDigest(laneDto.getCodes()); laneDto.setHashCode(hashCode); } } @@ -353,16 +358,16 @@ public void generateLaneCodeIdx(Integer lev) { log.info("There is initializing Lane CodeIdxMap......"); if (Cools.isEmpty(this.lanes)) { if (Cools.isEmpty(this.laneDtoList)) { return; } for (Lane lane : this.lanes) { for (LaneDto laneDto : this.laneDtoList) { List<int[]> codeIdxList = new ArrayList<>(); for (String code : lane.getCodes()) { for (String code : laneDto.getCodes()) { int[] codeMatrixIdx = mapDataDispatcher.getCodeMatrixIdx(lev, code); codeIdxList.add(codeMatrixIdx); this.laneCodeIdxMap.put(code, codeIdxList); this.codeLaneMap.put(code, lane); this.codeLaneMap.put(code, laneDto); } } } zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/MainService.java
@@ -21,7 +21,7 @@ import com.zy.acs.manager.common.domain.param.HandlerPublishParam; import com.zy.acs.manager.common.exception.BusinessException; import com.zy.acs.manager.core.domain.AgvBackpackDto; import com.zy.acs.manager.core.domain.Lane; import com.zy.acs.manager.core.domain.LaneDto; import com.zy.acs.manager.core.domain.TaskPosDto; import com.zy.acs.manager.core.integrate.conveyor.ConveyorStationService; import com.zy.acs.manager.core.service.astart.MapDataDispatcher; @@ -792,9 +792,9 @@ task.setOriCode(agvDetail.getCode()); task.setDestCode(endCode.getId()); // lane Lane destLane = laneBuilder.search(endCode.getData()); if (null != destLane) { task.setDestLaneHash(destLane.getHashCode()); LaneDto destLaneDto = laneBuilder.search(endCode.getData()); if (null != destLaneDto) { task.setDestLaneHash(destLaneDto.getHashCode()); } task.setPriority(taskType.equals(TaskTypeType.TO_CHARGE)?2:1); task.setTaskSts(TaskStsType.ASSIGN.val()); zy-acs-manager/src/main/java/com/zy/acs/manager/manager/service/LaneService.java
@@ -1,8 +1,13 @@ package com.zy.acs.manager.manager.service; import com.baomidou.mybatisplus.extension.service.IService; import com.zy.acs.manager.core.domain.LaneDto; import com.zy.acs.manager.manager.entity.Lane; import java.util.List; public interface LaneService extends IService<Lane> { List<Lane> batchSaveByLaneDtoList(Long zonedId, List<LaneDto> laneDtoList); } zy-acs-manager/src/main/java/com/zy/acs/manager/manager/service/TaskService.java
@@ -4,7 +4,7 @@ import com.zy.acs.manager.common.domain.BaseParam; import com.zy.acs.manager.common.domain.PageParam; import com.zy.acs.manager.common.domain.PageResult; import com.zy.acs.manager.core.domain.Lane; import com.zy.acs.manager.core.domain.LaneDto; import com.zy.acs.manager.manager.entity.Task; import com.zy.acs.manager.manager.enums.TaskStsType; @@ -31,9 +31,9 @@ Boolean cancel(Long taskId, Long userId); Lane checkoutOriginLane(Task task); LaneDto checkoutOriginLane(Task task); Lane checkoutDestinationLane(Task task); LaneDto checkoutDestinationLane(Task task); List<Task> findRunningTasksByLaneHash(String laneHash); zy-acs-manager/src/main/java/com/zy/acs/manager/manager/service/impl/LaneServiceImpl.java
@@ -1,12 +1,58 @@ package com.zy.acs.manager.manager.service.impl; import com.zy.acs.manager.manager.mapper.LaneMapper; import com.zy.acs.manager.manager.entity.Lane; import com.zy.acs.manager.manager.service.LaneService; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.zy.acs.framework.common.Cools; import com.zy.acs.framework.common.SnowflakeIdWorker; import com.zy.acs.framework.exception.CoolException; import com.zy.acs.manager.core.domain.LaneDto; import com.zy.acs.manager.manager.entity.Lane; import com.zy.acs.manager.manager.enums.StatusType; import com.zy.acs.manager.manager.mapper.LaneMapper; import com.zy.acs.manager.manager.service.LaneService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; import java.util.Date; import java.util.List; @Service("laneService") public class LaneServiceImpl extends ServiceImpl<LaneMapper, Lane> implements LaneService { @Autowired private SnowflakeIdWorker snowflakeIdWorker; @Override @Transactional(rollbackFor = Exception.class) public List<Lane> batchSaveByLaneDtoList(Long zonedId, List<LaneDto> laneDtoList) { List<Lane> lanes = new ArrayList<>(); if (Cools.isEmpty(laneDtoList)) { return lanes; } Date now = new Date(); for (LaneDto laneDto : laneDtoList) { Lane lane = new Lane(); if (null != zonedId) { lane.setZoneId(zonedId); } lane.setHashCode(laneDto.getHashCode()); lane.setUuid(String.valueOf(snowflakeIdWorker.nextId()).substring(3)); if (!Cools.isEmpty(laneDto.getCodes())) { lane.setCodes(JSON.toJSONString(laneDto.getCodes())); } lane.setStatus(StatusType.ENABLE.val); lane.setCreateTime(now); lane.setUpdateTime(now); if (!this.save(lane)) { throw new CoolException("failed to save lane"); } else { lanes.add(lane); laneDto.setLaneId(lane.getId()); } } return lanes; } } zy-acs-manager/src/main/java/com/zy/acs/manager/manager/service/impl/TaskServiceImpl.java
@@ -11,7 +11,7 @@ import com.zy.acs.manager.common.domain.PageParam; import com.zy.acs.manager.common.domain.PageResult; import com.zy.acs.manager.common.exception.BusinessException; import com.zy.acs.manager.core.domain.Lane; import com.zy.acs.manager.core.domain.LaneDto; import com.zy.acs.manager.core.service.LaneBuilder; import com.zy.acs.manager.manager.entity.*; import com.zy.acs.manager.manager.enums.*; @@ -180,7 +180,7 @@ } @Override public Lane checkoutOriginLane(Task task) { public LaneDto checkoutOriginLane(Task task) { Long codeId = null; TaskTypeType typeType = TaskTypeType.get(task.getTaskTypeEl()); switch (Objects.requireNonNull(typeType)) { @@ -203,7 +203,7 @@ } @Override public Lane checkoutDestinationLane(Task task) { public LaneDto checkoutDestinationLane(Task task) { Long codeId = null; TaskTypeType typeType = TaskTypeType.get(task.getTaskTypeEl()); switch (Objects.requireNonNull(typeType)) {