| | |
| | | import com.alibaba.fastjson.JSONArray; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.zy.asrs.framework.common.SpringUtils; |
| | | import com.zy.asrs.wcs.core.entity.ShuttleStandby; |
| | | import com.zy.asrs.wcs.core.model.MapNode; |
| | | import com.zy.asrs.wcs.core.model.NavigateNode; |
| | | import com.zy.asrs.wcs.core.model.PythonResult; |
| | | import com.zy.asrs.wcs.core.model.PythonSimilarityResult; |
| | | import com.zy.asrs.wcs.core.model.enums.MapNodeType; |
| | | import com.zy.asrs.wcs.core.model.enums.NavigationMapType; |
| | | import com.zy.asrs.wcs.core.service.ShuttleStandbyService; |
| | | import com.zy.asrs.wcs.rcs.News; |
| | | import com.zy.asrs.wcs.system.entity.Dict; |
| | | import com.zy.asrs.wcs.system.service.DictService; |
| | | import com.zy.asrs.wcs.rcs.entity.Device; |
| | | import com.zy.asrs.wcs.rcs.thread.LiftThread; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import java.io.BufferedReader; |
| | | import java.io.IOException; |
| | | import java.io.InputStreamReader; |
| | | import java.util.ArrayList; |
| | | import java.util.Collections; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | |
| | |
| | | |
| | | @Value("${pythonCalcPath}") |
| | | private String pythonCalcPath; |
| | | |
| | | @Value("${pythonCalcSimilarity}") |
| | | private String pythonCalcSimilarity; |
| | | @Autowired |
| | | private LiftDispatcher liftDispatcher; |
| | | @Autowired |
| | | private ShuttleStandbyService shuttleStandbyService; |
| | | |
| | | public List<NavigateNode> calcWhiteList(String startPoint, String endPoint, Integer mapType, List<int[]> shuttlePoints) { |
| | | //通过开始编号和结束编号获取对应的xy轴坐标 |
| | | int[] startArr = NavigatePositionConvert.positionToXY(startPoint);//开始节点 |
| | | int[] endArr = NavigatePositionConvert.positionToXY(endPoint);//结束节点 |
| | | |
| | | ArrayList<int[]> whiteList = new ArrayList<>();//设置计算节点的白名单 |
| | | whiteList.add(startArr);//将开始节点设置为白名单,以防被过滤 |
| | | whiteList.add(endArr);//将结束节点设置为白名单,以防被过滤 |
| | | |
| | | //获取当前节点计算的层高,并赋值到每一个节点中 |
| | | int lev = Utils.getLev(startPoint); |
| | | |
| | | //初始化开始节点 |
| | | NavigateNode start = new NavigateNode(startArr[0], startArr[1]); |
| | | //开始节点无父节点 |
| | | start.setFather(null); |
| | | |
| | | NavigateNode end = new NavigateNode(endArr[0], endArr[1]); |
| | | NavigateSolution solution = new NavigateSolution(mapType, lev, whiteList, shuttlePoints); |
| | | //开始节点,不纳入禁用节点内计算 |
| | | |
| | | String pathStr = solution.astarSearch(start, end, pythonCalcPath); |
| | | if (pathStr == null) { |
| | | News.error("{} dash {} can't find navigate path!", startPoint, endPoint); |
| | | return null; |
| | | } |
| | | |
| | | List<NavigateNode> list = new ArrayList<>(); |
| | | |
| | | NavigateNode fatherNode = null;//当前循环上一节点,用于拐点计算 |
| | | JSONArray rows = JSON.parseArray(pathStr); |
| | | |
| | | for (int i = 0; i < rows.size(); i++) { |
| | | Object currentObj = rows.get(i); |
| | | |
| | | NavigateNode nextNode = null; |
| | | if ((i + 1) < rows.size()) { |
| | | Object object = rows.get(i + 1); |
| | | nextNode = pythonObjTransferNode(object, lev); |
| | | } |
| | | |
| | | NavigateNode node = pythonObjTransferNode(currentObj, lev); |
| | | |
| | | //寻找拐点 |
| | | HashMap<String, Object> result = searchInflectionPoint(node, fatherNode, nextNode);//分别传入当前节点、父节点、下一节点 |
| | | //判断当前节点是否为拐点 |
| | | if (Boolean.parseBoolean(result.get("result").toString())) { |
| | | //当前为拐点 |
| | | node.setIsInflectionPoint(true); |
| | | //拐点方向 |
| | | node.setDirection(result.get("direction").toString()); |
| | | } |
| | | |
| | | list.add(node); |
| | | |
| | | fatherNode = node;//把当前节点保存成一个父节点 |
| | | } |
| | | |
| | | //将每个节点里面的fatherNode至为null(方便后续计算时父节点过多导致显示的节点太多) |
| | | for (NavigateNode navigateNode : list) { |
| | | //父节点设置为null,不影响计算结果,不影响后续操作。 |
| | | //此操作仅为后续排查处理提供视觉方便。 |
| | | navigateNode.setFather(null); |
| | | } |
| | | |
| | | //起始节点计算方向 |
| | | String direction = calcDirection(list.get(0), list.get(1)); |
| | | NavigateNode startNode = list.get(0); |
| | | startNode.setDirection(direction); |
| | | //更新节点列表 |
| | | list.set(0, startNode); |
| | | return list; |
| | | } |
| | | |
| | | public List<NavigateNode> calc(String startPoint, String endPoint, Integer mapType, List<int[]> shuttlePoints) { |
| | | //通过开始编号和结束编号获取对应的xy轴坐标 |
| | |
| | | |
| | | public Double similarityPath(List<NavigateNode> firstPath, List<NavigateNode> secondPath) { |
| | | try { |
| | | ProcessBuilder processBuilder = new ProcessBuilder("python", pythonCalcSimilarity, JSON.toJSONString(firstPath), JSON.toJSONString(secondPath)); |
| | | List<int[]> first = new ArrayList<>(); |
| | | for (NavigateNode node : firstPath) { |
| | | first.add(new int[]{node.getX(), node.getY()}); |
| | | } |
| | | |
| | | List<int[]> second = new ArrayList<>(); |
| | | for (NavigateNode node : secondPath) { |
| | | second.add(new int[]{node.getX(), node.getY()}); |
| | | } |
| | | |
| | | ProcessBuilder processBuilder = new ProcessBuilder("python", pythonCalcSimilarity, JSON.toJSONString(first), JSON.toJSONString(second)); |
| | | processBuilder.redirectErrorStream(true); |
| | | |
| | | Process process = processBuilder.start(); |
| | |
| | | return 0D; |
| | | } |
| | | |
| | | //检测库位路径是否可用(用于库位是否可移动检测) |
| | | public boolean checkLocPathIsAvailable(String startLocNo, Long hostId) { |
| | | //获取距离目标位置最近的可换层提升机(可能不空闲) |
| | | LiftThread liftThread = liftDispatcher.searchLift(startLocNo, hostId, true); |
| | | if (liftThread == null) { |
| | | return false; |
| | | } |
| | | Device transferLiftDevice = liftThread.getDevice(); |
| | | |
| | | ShuttleStandby shuttleStandbyTo = shuttleStandbyService.getOne(new LambdaQueryWrapper<ShuttleStandby>() |
| | | .eq(ShuttleStandby::getDeviceId, transferLiftDevice.getId()) |
| | | .eq(ShuttleStandby::getDeviceLev, Utils.getLev(startLocNo)) |
| | | .eq(ShuttleStandby::getStatus, 1)); |
| | | |
| | | //提升机库位号 |
| | | String liftLocNo = shuttleStandbyTo.getDeviceLoc(); |
| | | |
| | | //计算库位到提升机库位,路径是否可用 |
| | | List<NavigateNode> nodeList = this.calc(startLocNo, liftLocNo, NavigationMapType.DFX.id, null); |
| | | if (nodeList == null) { |
| | | return false; |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | public static void main(String[] args) { |
| | | // //计算路径 |
| | | // List<NavigateNode> calc = calc("1000901", "1800201", NavigationMapType.NONE.id, null); |