package com.zy.acs.manager.core.service;
|
|
import com.zy.acs.framework.common.Cools;
|
import com.zy.acs.common.utils.RedisSupport;
|
import com.zy.acs.manager.common.domain.MockAgvDto;
|
import com.zy.acs.manager.common.domain.MockDto;
|
import com.zy.acs.manager.common.domain.MockStepDto;
|
import com.zy.acs.manager.common.domain.MockVo;
|
import com.zy.acs.manager.common.exception.BusinessException;
|
import com.zy.acs.manager.core.domain.AgvMockDto;
|
import com.zy.acs.manager.core.domain.TaskPosDto;
|
import com.zy.acs.manager.core.service.astart.AStarNavigateService;
|
import com.zy.acs.manager.core.service.astart.MapDataDispatcher;
|
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.entity.CodeGap;
|
import com.zy.acs.manager.manager.service.AgvDetailService;
|
import com.zy.acs.manager.manager.service.AgvService;
|
import com.zy.acs.manager.manager.service.CodeGapService;
|
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.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
|
import java.util.*;
|
|
/**
|
* Created by vincent on 2023/7/29
|
*/
|
@Slf4j
|
@Service
|
public class MockService {
|
|
private final RedisSupport redis = RedisSupport.defaultRedisSupport;
|
|
@Autowired
|
private MapService mapService;
|
@Autowired
|
private AgvService agvService;
|
@Autowired
|
private AgvDetailService agvDetailService;
|
@Autowired
|
private CodeService codeService;
|
@Autowired
|
private CodeGapService codeGapService;
|
@Autowired
|
private MapDataDispatcher mapDataDispatcher;
|
@Autowired
|
private AStarNavigateService aStarNavigateService;
|
@Autowired
|
private ConfigService configService;
|
|
public void astarMock() {
|
Code startCode = codeService.selectByData("00000028");
|
Code endCode = codeService.selectByData("00000057");
|
|
List<String> strings = mapService.checkoutPath("1", startCode, endCode, false);
|
|
List<String> pathList = mapService.validFeasibility(startCode, endCode);
|
|
System.out.println("end");
|
}
|
|
@Transactional
|
public List<MockVo> submit(List<MockAgvDto> agvList, List<MockDto> taskList) {
|
final String sameGroupXy = configService.getVal("sameGroupXy", String.class);
|
List<MockVo> result = new ArrayList<>();
|
|
if (Cools.isEmpty(taskList)) {
|
throw new BusinessException("请添加 MOCK 任务");
|
}
|
taskList.sort((o1, o2) -> o2.getPriority() - o1.getPriority());
|
|
// 以 agv 分组
|
List<AgvMockDto> taskDtos = new ArrayList<>();
|
for (MockDto task : taskList) {
|
AgvMockDto taskDto = new AgvMockDto(task.getAgv(), task);
|
if (AgvMockDto.has(taskDtos, taskDto)) {
|
AgvMockDto dto = AgvMockDto.find(taskDtos, taskDto);
|
assert dto != null;
|
dto.getTaskList().add(task);
|
} else {
|
taskDtos.add(taskDto);
|
}
|
}
|
|
// 重组当前 agv 的所有任务
|
for (AgvMockDto taskDto : taskDtos) {
|
|
/**
|
* key:y 坐标 + 任务类别(货架取货、站点取货、货架放货、站点放货)
|
* val:任务id + 任务坐标 + 条码 + 任务类别
|
*/
|
Map<String, List<TaskPosDto>> groups = new HashMap<>();
|
|
for (MockDto mockDto : taskDto.getTaskList()) {
|
Code startCode = codeService.selectByData(mockDto.getStart());
|
Code endCode = codeService.selectByData(mockDto.getEnd());
|
|
TaskPosDto.packagePosGroup(groups, null, startCode, TaskPosDto.PosType.ORI_LOC, sameGroupXy);
|
TaskPosDto.packagePosGroup(groups, null, endCode, TaskPosDto.PosType.DEST_LOC, sameGroupXy);
|
}
|
|
// 二维数组 ( 每组的 y坐标 和 任务类别 一致)
|
ArrayList<List<TaskPosDto>> list = new ArrayList<>(groups.values());
|
// 二位数组 子数组 已经能确定 y坐标为一致。所有 get(0).xy[1] 为排序(就是一排一排任务进行排序),对 一排排任务以 y坐标 就行降序排序
|
list.sort((o1, o2) -> {
|
double o1CompVal = (o1.get(0).getFirstWeight(sameGroupXy) * 100) + o1.get(0).getPosType().compOffset;
|
double o2CompVal = (o2.get(0).getFirstWeight(sameGroupXy) * 100) + o2.get(0).getPosType().compOffset;
|
return (int) (o1CompVal - o2CompVal);
|
});
|
|
// 对一排任务进行 x坐标 顺序排序,防止来回走行
|
for (List<TaskPosDto> taskPosDtoList : list) {
|
taskPosDtoList.sort((o1, o2) -> (int) (o1.getSecondWeight(sameGroupXy) * 100 - o2.getSecondWeight(sameGroupXy) * 100));
|
}
|
|
// 上一次的 code, 第一次为 agv 当前code
|
String lastCodeData = this.getPosCode(agvList, taskDto.getAgvId());
|
if (Cools.isEmpty(lastCodeData)) {
|
throw new BusinessException(taskDto.getAgvId() + "号 agv 不在条码定位上!");
|
}
|
Code lastCode = codeService.selectByData(lastCodeData);
|
|
// 走行路径集合
|
List<MockStepDto> stepList = new ArrayList<>();
|
stepList.add(new MockStepDto(lastCodeData, Boolean.FALSE));
|
|
for (List<TaskPosDto> taskPosDtoList : list) {
|
|
for (TaskPosDto dto : taskPosDtoList) {
|
|
// 目标 code
|
Code code = codeService.getById(dto.getCodeId());
|
|
if (!lastCode.getData().equals(code.getData())) {
|
|
// 计算路径节点
|
List<String> pathList = mapService.checkoutPath(taskDto.getAgvId(), lastCode, code, true);
|
mapDataDispatcher.clearDynamicMatrixByCodeList(null, pathList);
|
// List<String> pathList = mapService.validFeasibility(lastCode, code);
|
|
if (Cools.isEmpty(pathList)) {
|
throw new BusinessException(lastCode.getData() + " 至 " + code.getData() + "没有路径!");
|
}
|
|
// 第一个节点为本身, 所以从 下标1 开始
|
for (int i = 1; i < pathList.size(); i++) {
|
|
String next = pathList.get(i);
|
Code nextCode = codeService.selectByData(next);
|
|
boolean pause = nextCode.getId().equals(dto.getCodeId());
|
String action = "";
|
if (pause) {
|
switch (dto.getPosType()){
|
case ORI_LOC:
|
case ORI_STA:
|
action = "PICK";
|
break;
|
case DEST_LOC:
|
case DEST_STA:
|
action = "DROP";
|
break;
|
default:
|
break;
|
}
|
}
|
|
stepList.add(new MockStepDto(nextCode.getData(), pause, action));
|
|
lastCode = nextCode;
|
}
|
|
}
|
}
|
}
|
|
result.add(new MockVo(taskDto.getAgvId(), stepList));
|
}
|
|
plusData(result);
|
|
|
|
for (MockVo mockVo : result) {
|
// redis.setObject("PATH", mockVo.getAgv(), mockVo.getStepList().stream().map(MockStepDto::getCode).collect(Collectors.toList()));
|
}
|
|
return result;
|
}
|
|
|
private String getPosCode(List<MockAgvDto> agvList, String agv) {
|
for (MockAgvDto agvDto : agvList) {
|
if (agv.equals(agvDto.getAgv())) {
|
return agvDto.getPos();
|
}
|
}
|
return null;
|
}
|
|
private void plusData(List<MockVo> result) {
|
for (MockVo mockVo : result) {
|
int size = mockVo.getStepList().size();
|
int time = size * 500;
|
|
Code lastCode = null;
|
double totalDistance = 0;
|
for (MockStepDto stepDto : mockVo.getStepList()) {
|
Code code = codeService.selectByData(stepDto.getCode());
|
|
if (null != lastCode) {
|
CodeGap gap = codeGapService.findByCodeOfBoth(code.getId(), lastCode.getId());
|
if (null != gap) {
|
totalDistance += gap.getDistance();
|
stepDto.setDistance(gap.getDistance());
|
}
|
}
|
|
lastCode = code;
|
}
|
|
for (MockStepDto stepDto : mockVo.getStepList()) {
|
if (null != stepDto.getDistance()) {
|
double rate = stepDto.getDistance() / totalDistance;
|
stepDto.setTime((int)(rate * time));
|
}
|
}
|
|
|
}
|
|
|
}
|
|
|
|
public List<MockVo> imitate() {
|
Agv agv = agvService.selectByUuid("1");
|
AgvDetail agvDetail = agvDetailService.selectByAgvId(agv.getId());
|
MockAgvDto mockAgvDto = new MockAgvDto();
|
mockAgvDto.setAgv(agv.getUuid());
|
mockAgvDto.setPos(codeService.getById(agvDetail.getCode()).getData());
|
List<MockAgvDto> mockAgvDtos = new ArrayList<>();
|
mockAgvDtos.add(mockAgvDto);
|
|
List<MockDto> taskList = new ArrayList<>();
|
List<Code> codeList = codeService.list();
|
Random random = new Random();
|
List<Integer> exitCodes = new ArrayList<>();
|
for (int i = 0; i < agv.getStage(); i++) {
|
MockDto mockDto = new MockDto();
|
mockDto.setAgv(agv.getUuid());
|
|
int startIdx;
|
do {
|
startIdx = random.nextInt(codeList.size());
|
} while (exitCodes.contains(startIdx));
|
exitCodes.add(startIdx);
|
Code startCode = codeList.get(startIdx);
|
|
int endIdx;
|
do {
|
endIdx = random.nextInt(codeList.size());
|
} while (exitCodes.contains(endIdx));
|
exitCodes.add(endIdx);
|
Code endCode = codeList.get(endIdx);
|
|
mockDto.setStart(startCode.getData());
|
mockDto.setEnd(endCode.getData());
|
taskList.add(mockDto);
|
}
|
return this.submit(mockAgvDtos, taskList);
|
}
|
|
|
}
|