zhang
2025-05-20 1313906bb1eb983d3beece810035e7fc28d6a92f
zy-acs-manager/src/main/java/com/zy/acs/manager/fake/AgvSimulatorTask.java
@@ -1,19 +1,21 @@
package com.zy.acs.manager.fake;
import com.zy.acs.common.constant.RedisConstant;
import com.zy.acs.common.domain.AgvProtocol;
import com.zy.acs.common.domain.protocol.AGV_11_UP;
import com.zy.acs.common.enums.AgvCompleteType;
import com.zy.acs.common.utils.RedisSupport;
import com.zy.acs.manager.core.cache.CoreCache;
import com.zy.acs.manager.core.domain.CodeStepDto;
import com.zy.acs.manager.core.domain.type.JobType;
import com.zy.acs.manager.core.scheduler.MapDataWsScheduler;
import com.zy.acs.manager.core.service.MainService;
import com.zy.acs.manager.core.service.MapService;
import com.zy.acs.manager.manager.entity.Action;
import com.zy.acs.manager.manager.entity.Agv;
import com.zy.acs.manager.manager.entity.AgvDetail;
import com.zy.acs.manager.manager.entity.Code;
import com.zy.acs.manager.manager.enums.ActionStsType;
import com.zy.acs.manager.manager.enums.ActionTypeType;
import com.zy.acs.manager.manager.service.ActionService;
import com.zy.acs.manager.manager.service.AgvDetailService;
import com.zy.acs.manager.manager.service.CodeService;
import com.zy.acs.manager.manager.service.*;
import lombok.extern.slf4j.Slf4j;
import java.util.List;
@@ -27,8 +29,12 @@
    private final Agv agv;
    private final AgvDetailService agvDetailService;
    private final AgvModelService agvModelService;
    private final ActionService actionService;
    private final CodeService codeService;
    private final MapService mapService;
    private final JamService jamService;
    private final MainService mainService;
    private final List<Action> actionList;
    private final RedisSupport redis;
@@ -39,15 +45,23 @@
            Agv agv
            , RedisSupport redis
            , AgvDetailService agvDetailService
            , AgvModelService agvModelService
            , ActionService actionService
            , CodeService codeService
            , MapService mapService
            , JamService jamService
            , MainService mainService
            , List<Action> actionList
    ) {
        this.agv = agv;
        this.redis = redis;
        this.agvDetailService = agvDetailService;
        this.agvModelService = agvModelService;
        this.actionService = actionService;
        this.codeService = codeService;
        this.mapService = mapService;
        this.jamService = jamService;
        this.mainService = mainService;
        this.actionList = actionList;
        this.groupId = actionList.get(0).getGroupId();
@@ -56,7 +70,6 @@
    @Override
    public void run() {
        try {
            FakeProcessor.AGV_PROCESSING_MAP.put(agv.getId(), true);
            String qrCode = null;
            for (Action action : actionList) {
                processAction(agv, action);
@@ -71,20 +84,19 @@
    }
    private void processAction(Agv agv, Action action) throws InterruptedException {
        AgvDetail agvDetail = agvDetailService.selectByAgvId(agv.getId());
        if (agvDetail == null) {
            return;
        }
        switch (Objects.requireNonNull(ActionTypeType.get(action.getActionTypeEl()))) {
            case TurnCorner:
                simulateRotating(agv, agvDetail, action);
                simulateWalking(agv, action);
                simulateRotating(agv, action);
                break;
            case StraightBackUnturnable:
            case StraightBackTurnable:
            case StraightAheadUnturnable:
            case StraightAheadTurnable:
                simulateWalking(agv, agvDetail, action);
            case FinishPath:
            case DockingCharge:
                simulateWalking(agv, action);
                break;
            case ReadyTakeFromShelvesLoc:
            case ReadyReleaseToShelvesLoc:
@@ -96,68 +108,89 @@
    }
    private void simulateWalking(Agv agv, AgvDetail agvDetail, Action action) throws InterruptedException {
        Code currCode = codeService.getById(agvDetail.getRecentCode());
        Code code = codeService.selectByData(action.getCode());
        agvDetail.setPos(1);
        agvDetail.setCode(code.getId());
    private void simulateWalking(Agv agv, Action action) throws InterruptedException {
        Code code = codeService.getCacheByData(action.getCode());
//        agvDetail.setPos(1);
//        agvDetail.setCode(code.getId());
        // 模拟电量消耗
//        agvDetail.setVol(agvDetail.getVol() - 0.1 * distanceToMove); // 根据距离消耗电量
        agvDetailService.updateById(agvDetail);
        Thread.sleep(MapDataWsScheduler.WEBSOCKET_BROADCAST_INTERVAL);
        Thread.sleep(1000);
        agvDetailService.updatePosCodeByAgvId(agv.getId(), code.getId());
//        agvDetailService.updateById(agvDetail);
        mapService.unlockPath(agv.getUuid(), code.getData());
        jamService.checkIfFinish(agv.getId(), code.getData());
        action.setActionSts(ActionStsType.FINISH.val());
        actionService.updateById(action);
    }
    /**
     * 模拟AGV旋转
     *
     * @param agv        当前AGV
     * @param agvDetail  AGV详细信息
     * @param action     当前动作
     */
    private void simulateRotating(Agv agv, AgvDetail agvDetail, Action action) throws InterruptedException {
//        Double agvAngle = agvDetail.getAgvAngle();
//        double actionAngle = Double.parseDouble(action.getParams());
    private void simulateRotating(Agv agv, Action action) throws InterruptedException {
        double actionAngle = Double.parseDouble(action.getParams());
//        agvDetail.setAgvAngle(actionAngle);
        // 模拟电量消耗?
//        agvDetail.setVol(agvDetail.getVol() - 0.05 * (angleToRotate / 15.0)); // 根据角度消耗电量
        double totalAngle = Double.parseDouble(action.getParams()); // 假设Action有angle属性
        double stepAngle = 45.0; // 每秒旋转15度,具体值根据需求调整
        double actionProgress = 0.0;
        while (actionProgress < totalAngle) {
            double angleToRotate = Math.min(stepAngle, totalAngle - actionProgress);
            // 更新AGV的角度
            double newAngle = (agvDetail.getAgvAngle() + angleToRotate) % 360;
            agvDetail.setAgvAngle(newAngle);
            // 模拟电量消耗
//            agvDetail.setVol(agvDetail.getVol() - 0.05 * (angleToRotate / 15.0)); // 根据角度消耗电量
            // 更新AGV详细信息
            agvDetailService.updateById(agvDetail);
            // 模拟实际执行时间
            Thread.sleep(1000); // 每秒执行一次
            actionProgress += angleToRotate;
        }
        // 动作完成,更新状态
        Thread.sleep(MapDataWsScheduler.WEBSOCKET_BROADCAST_INTERVAL);
        agvDetailService.updateAngleByAgvId(agv.getId(), actionAngle);
        action.setActionSts(ActionStsType.FINISH.val());
        actionService.updateById(action);
    }
    private void finishActionList(String qrCode) {
        // 1.complete data
        Long agvId = this.agv.getId();
        String agvNo = this.agv.getUuid();
        // 1.show effect
        CodeStepDto codeStepDto = CoreCache.AGV_MOCK_STEP_CACHE.get(agvId);
        if (null != codeStepDto && qrCode.equals(codeStepDto.getCodeData())) {
//            Code currentCode = agvDetailService.getCurrentCode(this.agv.getId());
            try { Thread.sleep(codeStepDto.getJobType().waitTime); } catch (InterruptedException ignore) {}
            CoreCache.AGV_MOCK_STEP_CACHE.remove(this.agv.getId());
            JobType jobType = CoreCache.AGV_MOCK_JOB_CACHE.get(this.agv.getUuid());
            switch (jobType) {
                case LOC_PICK:
                    Integer usedSlotsByLocPick = CoreCache.AGV_BACKPACK_USED_CACHE.get(agvId);
                    usedSlotsByLocPick++;
                    CoreCache.AGV_BACKPACK_USED_CACHE.put(agvId, usedSlotsByLocPick);
                    if (Objects.equals(agvModelService.getByAgvId(agvId).getBackpack(), usedSlotsByLocPick)) {
                        CoreCache.AGV_MOCK_JOB_CACHE.put(agvNo, JobType.CONVEYOR_DROP);
                    }
                    break;
                case CONVEYOR_DROP:
                    CoreCache.AGV_BACKPACK_USED_CACHE.put(agvId, 0);
                    CoreCache.AGV_MOCK_JOB_CACHE.put(agvNo, JobType.CONVEYOR_PICK);
                    break;
                case CONVEYOR_PICK:
                    CoreCache.AGV_BACKPACK_USED_CACHE.put(agvId, agvModelService.getByAgvId(agvId).getBackpack());
                    CoreCache.AGV_MOCK_JOB_CACHE.put(agvNo, JobType.LOCK_DROP);
                    break;
                case LOCK_DROP:
                    Integer usedSlotsByLocDrop = CoreCache.AGV_BACKPACK_USED_CACHE.get(agvId);
                    usedSlotsByLocDrop--;
                    CoreCache.AGV_BACKPACK_USED_CACHE.put(agvId, usedSlotsByLocDrop);
                    if (usedSlotsByLocDrop == 0) {
                        CoreCache.AGV_MOCK_JOB_CACHE.put(agvNo, JobType.LOC_PICK);
                    }
                    break;
                default:
                    break;
            }
        }
        // 2.complete data
        AGV_11_UP agv_11_up = new AGV_11_UP();
        agv_11_up.setSerialNo(groupId);
        agv_11_up.setCompleteCode(AgvCompleteType.ENTIRE_PATH_COMPLETE.getCode());
@@ -165,6 +198,7 @@
        agv_11_up.setQrCode(qrCode);
        AgvProtocol agvProtocol = AgvProtocol.build(this.agv.getUuid()).setMessageBody(agv_11_up);
        redis.push(RedisConstant.AGV_COMPLETE_FLAG, agvProtocol);
        mainService.upDataSubscribe(agvProtocol);
//        redis.push(RedisConstant.AGV_COMPLETE_FLAG, agvProtocol);
    }
}