#
vincentlu
2025-12-31 6e28ed413a6adfa60000c092aae2464ab2e43fd4
#
2个文件已添加
6个文件已修改
339 ■■■■ 已修改文件
version/doc/RCS输送线逻辑梳理.xmind 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/core/domain/AgvCntDto.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/core/domain/FilterLaneDto.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/AllocateService.java 257 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/MainService.java 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/TrafficService.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/manager/service/StaService.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/manager/service/impl/StaServiceImpl.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
version/doc/RCSÊäËÍÏßÂß¼­ÊáÀí.xmind
Binary files differ
zy-acs-manager/src/main/java/com/zy/acs/manager/core/domain/AgvCntDto.java
New file
@@ -0,0 +1,37 @@
package com.zy.acs.manager.core.domain;
import lombok.Data;
import java.util.List;
@Data
public class AgvCntDto {
    private Long agvId;
    private Integer count;
    public AgvCntDto(Long agvId) {
        this.agvId = agvId;
        this.count = 1;
    }
    public static boolean has(List<AgvCntDto> list, AgvCntDto dto) {
        for (AgvCntDto cntDto : list) {
            if (cntDto.getAgvId().equals(dto.getAgvId())) {
                return true;
            }
        }
        return false;
    }
    public static AgvCntDto find(List<AgvCntDto> list, AgvCntDto dto) {
        for (AgvCntDto cntDto : list) {
            if (cntDto.getAgvId().equals(dto.getAgvId())) {
                return cntDto;
            }
        }
        return null;
    }
}
zy-acs-manager/src/main/java/com/zy/acs/manager/core/domain/FilterLaneDto.java
New file
@@ -0,0 +1,23 @@
package com.zy.acs.manager.core.domain;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
@Data
public class FilterLaneDto {
    private Lane originLane;
    private Lane destinationLane;
    private List<String> actualAvailableAgvNos = new ArrayList<>();
    public FilterLaneDto(Lane originLane, Lane destinationLane, List<String> actualAvailableAgvNos) {
        this.originLane = originLane;
        this.destinationLane = destinationLane;
        this.actualAvailableAgvNos = actualAvailableAgvNos;
    }
}
zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/AllocateService.java
@@ -3,9 +3,12 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zy.acs.framework.common.Cools;
import com.zy.acs.manager.common.utils.CommonUtil;
import com.zy.acs.manager.core.domain.AgvCntDto;
import com.zy.acs.manager.core.domain.Lane;
import com.zy.acs.manager.core.domain.FilterLaneDto;
import com.zy.acs.manager.core.domain.TaskPosDto;
import com.zy.acs.manager.manager.entity.*;
import com.zy.acs.manager.manager.enums.StaTypeType;
import com.zy.acs.manager.manager.enums.StatusType;
import com.zy.acs.manager.manager.enums.TaskStsType;
import com.zy.acs.manager.manager.enums.TaskTypeType;
@@ -24,6 +27,8 @@
@Slf4j
@Service
public class AllocateService {
    public static final Integer OUTBOUND_TASKS_ALLOCATE_LIMIT = 5;
    @Autowired
    private AgvService agvService;
@@ -45,40 +50,31 @@
    private LaneService laneService;
    @Autowired
    private AgvAreaDispatcher agvAreaDispatcher;
    @Autowired
    private SegmentService segmentService;
    /**
     * get available agv list which is idle
     */
    private List<String> getAvailableAgvNos(List<Long> agvIds) {
//        List<Agv> agvList = new ArrayList<>();
//        if (Cools.isEmpty(agvNos)) {
//            // global
//            agvList = agvService.list(new LambdaQueryWrapper<Agv>().eq(Agv::getStatus, StatusType.ENABLE.val));
//        } else {
//            // local
//            for (String agvNo : agvNos) {
//                Agv agv = agvService.selectByUuid(agvNo);
//                if (agv.getStatusBool()) {
//                    agvList.add(agv);
//                }
//            }
//        }
    private List<String> getAvailableAgvNos(List<Long> agvIds, boolean hasRunning) {
        List<Agv> agvList = Cools.isEmpty(agvIds)
                ? agvService.list(new LambdaQueryWrapper<Agv>().eq(Agv::getStatus, StatusType.ENABLE.val))
                : agvIds.stream().map(agvService::getById).filter(Agv::getStatusBool).collect(Collectors.toList());
        List<String> result = new ArrayList<>();
        for (Agv agv : agvList) {
            if (!hasRunning) {
            // 1. without running tasks
            if (0 < taskService.count(new LambdaQueryWrapper<Task>()
                    .eq(Task::getAgvId, agv.getId())
                    .and(i ->
                            i.eq(Task::getTaskSts, TaskStsType.ASSIGN.val())
                            .or().eq(Task::getTaskSts, TaskStsType.PROGRESS.val())
                        .and(i -> i
                                .eq(Task::getTaskSts, TaskStsType.ASSIGN.val())
                                .or()
                                .eq(Task::getTaskSts, TaskStsType.PROGRESS.val())
                    )
            )) {
                continue;
                }
            }
            // 2. in idle status
            if (!agvService.judgeEnable(agv.getId(), true)) {
@@ -89,11 +85,42 @@
        }
        if (!Cools.isEmpty(result)) {
            // todo: è½®è¯¢æƒé‡
            Collections.shuffle(result);
        }
        return result;
    }
    public synchronized Agv execute(Task task) {
        Sta rollerOriSta = getInboundRollerSta(task);
        if (rollerOriSta != null) {
            List<String> availableAgvNos = this.getAvailableAgvNos(agvAreaDispatcher.getAgvNosByTask(task), true);
            FilterLaneDto filterLaneDto = this.filterThroughLane(task, availableAgvNos);
            if (null != filterLaneDto) {
                String agvNo = this.checkoutAgvForInboundRoller(task, rollerOriSta, filterLaneDto.getActualAvailableAgvNos());
                if (!Cools.isEmpty(agvNo)) {
                    task.setOriLaneHash(filterLaneDto.getOriginLane().getHashCode());
                    task.setDestLaneHash(filterLaneDto.getDestinationLane().getHashCode());
                    return agvService.selectByUuid(agvNo);
                }
            }
        }
        Sta rollerDestSta = getOutboundRollerSta(task);
        if (rollerDestSta != null) {
            List<String> availableAgvNos = this.getAvailableAgvNos(agvAreaDispatcher.getAgvNosByTask(task), true);
            FilterLaneDto filterLaneDto = this.filterThroughLane(task, availableAgvNos);
            if (null != filterLaneDto) {
                String agvNo = this.checkoutAgvForOutboundRoller(task, rollerDestSta, filterLaneDto.getActualAvailableAgvNos());
                if (!Cools.isEmpty(agvNo)) {
                    task.setOriLaneHash(filterLaneDto.getOriginLane().getHashCode());
                    task.setDestLaneHash(filterLaneDto.getDestinationLane().getHashCode());
                    return agvService.selectByUuid(agvNo);
                }
            }
        }
        return this.normalExecute(task);
    }
    /**
@@ -105,13 +132,135 @@
     *
     *      it can break the limit of the number of agv backpack
     */
    public synchronized Agv execute(Task task) {
        List<String> availableAgvNos = this.getAvailableAgvNos(agvAreaDispatcher.getAgvNosByTask(task));
    public synchronized Agv normalExecute(Task task) {
        List<String> availableAgvNos = this.getAvailableAgvNos(agvAreaDispatcher.getAgvNosByTask(task), false);
//        List<String> availableAgvNos = this.getAvailableAgvNos(null);
        if (Cools.isEmpty(availableAgvNos)) {
//            log.warn("No available agv to assign the task[{}]", task.getSeqNum());
            return null;
        }
        // calc lane
        FilterLaneDto filterLaneDto = this.filterThroughLane(task, availableAgvNos);
        if (null == filterLaneDto) {
            return null;
        }
        Lane originLane = filterLaneDto.getOriginLane();
        Lane destinationLane = filterLaneDto.getDestinationLane();
        List<String> actualAvailableAgvNos = filterLaneDto.getActualAvailableAgvNos();
        // choose min number of running task
        actualAvailableAgvNos.sort(new Comparator<String>() {
            @Override
            public int compare(String agvNo1, String agvNo2) {
                return calcAllocateWeight(agvNo1, task) - calcAllocateWeight(agvNo2, task);
            }
        });
        if (null != originLane) {
            task.setOriLaneHash(originLane.getHashCode());
        }
        if (null != destinationLane) {
            task.setDestLaneHash(destinationLane.getHashCode());
        }
        return agvService.selectByUuid(actualAvailableAgvNos.stream().findFirst().orElse(null));
    }
    private String checkoutAgvForInboundRoller(Task task, Sta sta, List<String> availableAgvNos) {
        if (Cools.isEmpty(availableAgvNos, task, sta)) {
            return null;
        }
        for (String agvNo : availableAgvNos) {
            Long agvId = agvService.getAgvId(agvNo);
            Code currentCode = agvDetailService.getCurrentCode(agvId);
            if (null == currentCode) {
                continue;
            }
            // only checkout the agv which at sta code position
            if (!sta.getCode().equals(currentCode.getId())) {
                continue;
            }
            // has running task and within oriSta
//            List<Segment> currSeg = segmentService.getByAgvAndState(agvId, SegmentStateType.WAITING.toString());
            int taskCnt = taskService.count(new LambdaQueryWrapper<Task>()
                    .eq(Task::getAgvId, agvId)
                    .eq(Task::getOriSta, sta.getId())
                    .and(wrapper -> wrapper
                            .eq(Task::getTaskSts, TaskStsType.ASSIGN.val())
                            .or()
                            .eq(Task::getTaskSts, TaskStsType.PROGRESS.val())
                    )
            );
            if (taskCnt == 0) {
                break;
            }
            // has enough backpack space to load
            Integer backpack = agvService.getBackpack(agvId);
            int countRemainingBackpack = segmentService.countRemainingBackpack(null, agvId);
            if (countRemainingBackpack >= backpack) {
                break;
            }
            return agvNo;
        }
        return null;
    }
    private String checkoutAgvForOutboundRoller(Task task, Sta sta, List<String> availableAgvNos) {
        if (Cools.isEmpty(availableAgvNos, task, sta)) {
            return null;
        }
        List<Task> taskList = taskService.list(new LambdaQueryWrapper<Task>()
                .eq(Task::getDestSta, sta.getId())
                .eq(Task::getTaskSts, TaskStsType.WAITING.val())
                .isNotNull(Task::getAgvId)
        );
        if (Cools.isEmpty(taskList)) {
            return null;
        }
        List<AgvCntDto> cntDtoList = new ArrayList<>();
        for (Task t : taskList) {
            AgvCntDto cntDto = new AgvCntDto(t.getAgvId());
            if (AgvCntDto.has(cntDtoList, cntDto)) {
                AgvCntDto dto = AgvCntDto.find(cntDtoList, cntDto);
                assert null != dto;
                dto.setCount(dto.getCount() + 1);
            } else {
                cntDtoList.add(cntDto);
            }
        }
        cntDtoList.sort(new Comparator<AgvCntDto>() {
            @Override
            public int compare(AgvCntDto o1, AgvCntDto o2) {
                return o1.getCount() - o2.getCount();
            }
        });
        for (AgvCntDto cntDto : cntDtoList) {
            if (cntDto.getAgvId() >= OUTBOUND_TASKS_ALLOCATE_LIMIT) {
                continue;
            }
            return agvService.getAgvNo(cntDto.getAgvId());
        }
        return null;
    }
    public FilterLaneDto filterThroughLane(Task task, List<String> availableAgvNos) {
        if (Cools.isEmpty(availableAgvNos, task)) {
            return null;
        }
        Integer maxAgvCountInLane = configService.getVal("maxAgvCountInLane", Integer.class);
        // checkout lane
@@ -158,23 +307,7 @@
            return null;
        }
        // choose min number of running task
        actualAvailableAgvNos.sort(new Comparator<String>() {
            @Override
            public int compare(String agvNo1, String agvNo2) {
                return calcAllocateWeight(agvNo1, task) - calcAllocateWeight(agvNo2, task);
            }
        });
        if (null != originLane) {
            task.setOriLaneHash(originLane.getHashCode());
        }
        if (null != destinationLane) {
            task.setDestLaneHash(destinationLane.getHashCode());
        }
        return agvService.selectByUuid(actualAvailableAgvNos.stream().findFirst().orElse(null));
        return new FilterLaneDto(originLane, destinationLane, actualAvailableAgvNos);
    }
    public List<String> findAgvNosByLane(Lane lane) {
@@ -314,4 +447,52 @@
        return theLastOne.get(theLastOne.size() - 1).getXy();
    }
    // about roller --------------------------------------------
    private Sta getInboundRollerSta(Task task) {
        TaskTypeType type = TaskTypeType.get(task.getTaskTypeEl());
        switch (Objects.requireNonNull(type)) {
            case STA_TO_LOC:
            case STA_TO_STA:
                Long oriStaId = task.getOriSta();
                if (null == oriStaId) {
                    return null;
                }
                Sta oriSta = staService.getById(oriStaId);
                if (oriSta == null || Cools.isEmpty(oriSta.getStaType())) {
                    return null;
                }
                if (StaTypeType.ROLLER.val() != oriSta.getStaType()) {
                    return null;
                }
                return oriSta;
            default:
                return null;
        }
    }
    private Sta getOutboundRollerSta(Task task) {
        TaskTypeType type = TaskTypeType.get(task.getTaskTypeEl());
        switch (Objects.requireNonNull(type)) {
            case LOC_TO_STA:
            case STA_TO_STA:
                Long destStaId = task.getDestSta();
                if (null == destStaId) {
                    return null;
                }
                Sta destSta = staService.getById(destStaId);
                if (destSta == null || Cools.isEmpty(destSta.getStaType())) {
                    return null;
                }
                if (StaTypeType.ROLLER.val() != destSta.getStaType()) {
                    return null;
                }
                return destSta;
            default:
                return null;
        }
    }
}
zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/MainService.java
@@ -247,7 +247,9 @@
            List<Long> taskIds = taskList.stream().map(Task::getId).distinct().collect(Collectors.toList());
            for (Task task : taskList) {
                Agv agv = allocateService.execute(task);
                Agv agv = allocateService.execute(task, () => {
                });
                if (null == agv) {
//                    log.warn("Task[{}] has an issue, because it failed to check out agv which is idle...", task.getSeqNum());
                    continue;
zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/TrafficService.java
@@ -700,6 +700,10 @@
            if (!Cools.isEmpty(jamService.getUnfinishedAvoSegByAvo(blockVehicleDto.getVehicle(), null))) {
                continue;
            }
            // å½“前vehicle正在进行滚筒输送线等待
            if () {
                continue;
            }
            return blockVehicleDto.getVehicle();
        }
        return null;
zy-acs-manager/src/main/java/com/zy/acs/manager/manager/service/StaService.java
@@ -16,4 +16,6 @@
    List<Sta> queryAvailableInSta(Integer minAvailableQty);
    boolean isRoller(Long staId);
}
zy-acs-manager/src/main/java/com/zy/acs/manager/manager/service/impl/StaServiceImpl.java
@@ -41,4 +41,16 @@
        return this.baseMapper.selectAvailableInSta(minAvailableQty);
    }
    @Override
    public boolean isRoller(Long staId) {
        if (staId == null) {
            return false;
        }
        Sta sta = this.getById(staId);
        if (sta == null || Cools.isEmpty(sta.getStaType())) {
            return false;
        }
        return StaTypeType.ROLLER.val() == sta.getStaType();
    }
}