zy-acs-common/src/main/java/com/zy/acs/common/enums/AgvCompleteType.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/PatrolService.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
zy-acs-manager/src/main/java/com/zy/acs/manager/fake/AgvSimulatorTask.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
zy-acs-manager/src/main/java/com/zy/acs/manager/fake/FakeProcessor.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
zy-acs-common/src/main/java/com/zy/acs/common/enums/AgvCompleteType.java
@@ -50,4 +50,11 @@ return null; } public int getCode() { return code; } public String getDesc() { return desc; } } zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/PatrolService.java
@@ -34,8 +34,11 @@ public class PatrolService { private static final int SCHEDULE_TIME_INTERVAL = 1; private static final Map<String, ScheduledFuture<?>> AGV_PATROL_MAP = new ConcurrentHashMap<>(); private final RedisSupport redis = RedisSupport.defaultRedisSupport; private ScheduledExecutorService scheduler = null; @Autowired zy-acs-manager/src/main/java/com/zy/acs/manager/fake/AgvSimulatorTask.java
New file @@ -0,0 +1,170 @@ 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.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 lombok.extern.slf4j.Slf4j; import java.util.List; import java.util.Objects; /** * Created by vincent on 11/11/2024 */ @Slf4j public class AgvSimulatorTask implements Runnable { private final Agv agv; private final AgvDetailService agvDetailService; private final ActionService actionService; private final CodeService codeService; private final List<Action> actionList; private final RedisSupport redis; private final String groupId; public AgvSimulatorTask( Agv agv , RedisSupport redis , AgvDetailService agvDetailService , ActionService actionService , CodeService codeService , List<Action> actionList ) { this.agv = agv; this.redis = redis; this.agvDetailService = agvDetailService; this.actionService = actionService; this.codeService = codeService; this.actionList = actionList; this.groupId = actionList.get(0).getGroupId(); } @Override public void run() { try { FakeProcessor.AGV_PROCESSING_MAP.put(agv.getId(), true); String qrCode = null; for (Action action : actionList) { processAction(agv, action); qrCode = action.getCode(); } this.finishActionList(qrCode); } catch (Exception e) { log.error("AgvSimulatorTask AGV[{}]", agv.getUuid(), e); } finally { FakeProcessor.AGV_PROCESSING_MAP.put(agv.getId(), false); } } 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); break; case StraightBackUnturnable: case StraightBackTurnable: case StraightAheadUnturnable: case StraightAheadTurnable: simulateWalking(agv, agvDetail, action); break; case ReadyTakeFromShelvesLoc: case ReadyReleaseToShelvesLoc: break; default: log.warn("Unknown action type {} for AGV ID {}.", action.getActionType(), agv.getId()); break; } } 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()); // 模拟电量消耗 // agvDetail.setVol(agvDetail.getVol() - 0.1 * distanceToMove); // 根据距离消耗电量 agvDetailService.updateById(agvDetail); Thread.sleep(1000); 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()); 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; } // 动作完成,更新状态 action.setActionSts(ActionStsType.FINISH.val()); actionService.updateById(action); } private void finishActionList(String qrCode) { // 1.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()); agv_11_up.setCompleteType(AgvCompleteType.ENTIRE_PATH_COMPLETE); agv_11_up.setQrCode(qrCode); AgvProtocol agvProtocol = AgvProtocol.build(this.agv.getUuid()).setMessageBody(agv_11_up); redis.push(RedisConstant.AGV_COMPLETE_FLAG, agvProtocol); } } zy-acs-manager/src/main/java/com/zy/acs/manager/fake/FakeProcessor.java
@@ -3,30 +3,42 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.zy.acs.common.constant.RedisConstant; import com.zy.acs.common.domain.AgvProtocol; import com.zy.acs.common.domain.protocol.AGV_01_DOWN; import com.zy.acs.common.domain.protocol.AGV_01_UP; import com.zy.acs.common.utils.RedisSupport; import com.zy.acs.framework.common.Cools; 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.enums.ActionStsType; import com.zy.acs.manager.manager.enums.StatusType; import com.zy.acs.manager.manager.service.ActionService; import com.zy.acs.manager.manager.service.AgvDetailService; import com.zy.acs.manager.manager.service.AgvService; import com.zy.acs.manager.manager.service.CodeService; import com.zy.acs.manager.system.service.ConfigService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * Created by vincent on 11/9/2024 */ @Slf4j @Component public class FakeProcessor { private final RedisSupport redis = RedisSupport.defaultRedisSupport; public static final Map<Long, Boolean> AGV_PROCESSING_MAP = new ConcurrentHashMap<>(); private ExecutorService executorService; @Autowired private AgvService agvService; @@ -36,6 +48,8 @@ private ActionService actionService; @Autowired private ConfigService configService; @Autowired private CodeService codeService; /** * 1.AgvDataService.dataProcess [ agvDetail: vol, code, agvAngle, agvStatus ] @@ -52,22 +66,33 @@ } List<Agv> agvList = agvService.list(new LambdaQueryWrapper<Agv>().eq(Agv::getStatus, StatusType.ENABLE.val)); for (Agv agv : agvList) { AgvDetail agvDetail = agvDetailService.selectByAgvId(agv.getId()); // init executorService if (null == this.executorService) { int count = agvList.size() > 30 ? agvList.size() : 20; this.executorService = Executors.newFixedThreadPool(count); } this.processRunning(agv); this.responseTheRequest(); for (Agv agv : agvList) { AGV_PROCESSING_MAP.putIfAbsent(agv.getId(), false); this.processOnline(agv); } } private void processRunning(Agv agv) { List<Action> actionList = actionService.queryLatestGroup(agv.getId(), ActionStsType.ISSUED); if (!Cools.isEmpty(actionList)) { for (Action action : actionList) { if (!AGV_PROCESSING_MAP.get(agv.getId())) { List<Action> actionList = actionService.queryLatestGroup(agv.getId(), ActionStsType.ISSUED); if (!Cools.isEmpty(actionList)) { executorService.submit(new AgvSimulatorTask( agv , redis , agvDetailService , actionService , codeService , actionList )); } } } } @@ -82,11 +107,14 @@ Thread.sleep(100); } catch (InterruptedException ignore) {} AGV_01_DOWN agv_01_down = (AGV_01_DOWN) protocol.getMessageBody(); // redis.setObject(RedisConstant.AGV_PATH_UP_FLAG // , protocol.getAgvNo() + "_" + agv_01_up.getSerialNo() // , agv_01_up); AGV_01_UP agv_01_up = new AGV_01_UP(); agv_01_up.setSerialNo(agv_01_down.getSerialNo()); redis.setObject(RedisConstant.AGV_PATH_UP_FLAG , protocol.getAgvNo() + "_" + agv_01_up.getSerialNo() , agv_01_up); } }