Browse Source

Load / Unload 记库存

master
修宁 6 months ago
parent
commit
a751106535
  1. 2
      servo/src/main/java/com/galaxis/rcs/RCSService.java
  2. 41
      servo/src/main/java/com/galaxis/rcs/inv/InvManager.java
  3. 15
      servo/src/main/java/com/galaxis/rcs/plan/PlanTaskSequence.java
  4. 4
      servo/src/main/java/com/galaxis/rcs/plan/path/PtrPathPlanner.java
  5. 1
      servo/src/main/java/com/galaxis/rcs/plan/task/CarryTask.java
  6. 13
      servo/src/main/java/com/galaxis/rcs/ptr/PtrAgvItem.java
  7. 60
      servo/src/main/java/com/yvan/entity/BasLocationVo.java
  8. 2
      servo/src/main/java/com/yvan/entity/LccProject.java
  9. 2
      servo/src/main/java/com/yvan/entity/LccProjectEnv.java
  10. 2
      servo/src/main/java/com/yvan/entity/Vector2.java
  11. 6
      servo/src/main/java/com/yvan/logisticsModel/ExecutorItem.java
  12. 60
      servo/src/main/java/com/yvan/logisticsModel/LogisticsRuntime.java
  13. 4
      servo/src/main/java/com/yvan/logisticsModel/LogisticsRuntimeService.java
  14. 13
      servo/src/main/java/com/yvan/pusher/FrontendMessagePushService.java
  15. 2
      servo/src/main/java/com/yvan/workbench/controller/LccModelManager.java
  16. 222
      servo/src/main/java/com/yvan/workbench/controller/RcsController.java
  17. 7
      servo/src/main/java/com/yvan/workbench/service/LccMapService.java

2
servo/src/main/java/com/galaxis/rcs/RCSService.java

@ -10,7 +10,7 @@ import com.yvan.logisticsModel.LogisticsRuntime;
import com.yvan.logisticsModel.LogisticsRuntimeService; import com.yvan.logisticsModel.LogisticsRuntimeService;
import com.yvan.logisticsModel.StaticItem; import com.yvan.logisticsModel.StaticItem;
import com.yvan.workbench.SpringContext; import com.yvan.workbench.SpringContext;
import com.yvan.workbench.model.entity.LccProject; import com.yvan.entity.LccProject;
import com.yvan.workbench.service.LccMapService; import com.yvan.workbench.service.LccMapService;
import lombok.SneakyThrows; import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;

41
servo/src/main/java/com/galaxis/rcs/inv/InvManager.java

@ -2,6 +2,7 @@ package com.galaxis.rcs.inv;
import com.galaxis.rcs.common.entity.LccInvLpn; import com.galaxis.rcs.common.entity.LccInvLpn;
import com.querydsl.core.util.StringUtils; import com.querydsl.core.util.StringUtils;
import org.clever.core.id.SnowFlake;
import org.clever.data.jdbc.DaoFactory; import org.clever.data.jdbc.DaoFactory;
import org.clever.data.jdbc.QueryDSL; import org.clever.data.jdbc.QueryDSL;
@ -15,6 +16,7 @@ public class InvManager {
/** /**
* 记录库存 * 记录库存
*
* @param envId 环境ID * @param envId 环境ID
* @param lpn 容器号 * @param lpn 容器号
* @param locCode 库位号 * @param locCode 库位号
@ -23,7 +25,7 @@ public class InvManager {
* @param qtyIn 入库数量 >0 减数量 <0 减数量 * @param qtyIn 入库数量 >0 减数量 <0 减数量
* @param qtyOut 出库数量 >0 减数量 <0 减数量 * @param qtyOut 出库数量 >0 减数量 <0 减数量
*/ */
public static void invSave(Long envId, String lpn, String locCode, Integer layerIndex, int qty, int qtyIn, int qtyOut) { public static void invSave(Long envId, Long bizTaskId, String lpn, String locCode, Integer layerIndex, int qty, int qtyIn, int qtyOut) {
if (envId == null || envId <= 0 if (envId == null || envId <= 0
|| lpn == null || StringUtils.isNullOrEmpty(lpn) || lpn.equals("N/A") || lpn == null || StringUtils.isNullOrEmpty(lpn) || lpn.equals("N/A")
|| locCode == null || StringUtils.isNullOrEmpty(locCode) || locCode.equals("N/A") || locCode == null || StringUtils.isNullOrEmpty(locCode) || locCode.equals("N/A")
@ -73,20 +75,23 @@ public class InvManager {
} }
} }
queryDSL.beginTX(status -> {
if (lccInvLpnData != null) { if (lccInvLpnData != null) {
queryDSL.update(lccInvLpn) queryDSL.update(lccInvLpn)
.set(lccInvLpn.qty, lccInvLpn.qty.add(qty)) .set(lccInvLpn.qty, lccInvLpn.qty.add(qty))
.set(lccInvLpn.qtyIn, lccInvLpn.qtyIn.add(qtyIn)) .set(lccInvLpn.qtyIn, lccInvLpn.qtyIn.add(qtyIn))
.set(lccInvLpn.qtyOut, lccInvLpn.qtyOut.add(qtyOut)) .set(lccInvLpn.qtyOut, lccInvLpn.qtyOut.add(qtyOut))
.set(lccInvLpn.layerIndex, layerIndex) .set(lccInvLpn.layerIndex, layerIndex)
// .set(lccInvLpn.updateAt, ) .set(lccInvLpn.updateAt, new Date(System.currentTimeMillis()))
.set(lccInvLpn.updateBy, "system")
.where(lccInvLpn.envId.eq(envId).and(lccInvLpn.locCode.eq(locCode)).and(lccInvLpn.lpn.eq(lpn))) .where(lccInvLpn.envId.eq(envId).and(lccInvLpn.locCode.eq(locCode)).and(lccInvLpn.lpn.eq(lpn)))
.execute(); .execute();
// 记录账页 // 记录账页
queryDSL.insert(lccInvLedger) queryDSL.insert(lccInvLedger)
.set(lccInvLedger.ledgerId, SnowFlake.SNOW_FLAKE.nextId())
.set(lccInvLedger.envId, envId) .set(lccInvLedger.envId, envId)
.set(lccInvLedger.lpn, lpn) .set(lccInvLedger.lpn, lpn)
.set(lccInvLedger.bizTaskId, bizTaskId)
.set(lccInvLedger.locCode, locCode) .set(lccInvLedger.locCode, locCode)
.set(lccInvLedger.layerIndex, layerIndex) .set(lccInvLedger.layerIndex, layerIndex)
.set(lccInvLedger.qtyChange, qty) .set(lccInvLedger.qtyChange, qty)
@ -97,6 +102,10 @@ public class InvManager {
.set(lccInvLedger.qtyOut, lccInvLpnData.getQtyOut() + qtyOut) .set(lccInvLedger.qtyOut, lccInvLpnData.getQtyOut() + qtyOut)
.set(lccInvLedger.ledgerType, "记账") .set(lccInvLedger.ledgerType, "记账")
.set(lccInvLedger.ledgerRemark, "N/A") .set(lccInvLedger.ledgerRemark, "N/A")
.set(lccInvLedger.createAt, new Date(System.currentTimeMillis()))
.set(lccInvLedger.createBy, "system")
.set(lccInvLedger.updateAt, new Date(System.currentTimeMillis()))
.set(lccInvLedger.updateBy, "system")
.execute(); .execute();
} else { } else {
queryDSL.insert(lccInvLpn) queryDSL.insert(lccInvLpn)
@ -107,11 +116,17 @@ public class InvManager {
.set(lccInvLpn.qty, qty) .set(lccInvLpn.qty, qty)
.set(lccInvLpn.qtyIn, qtyIn) .set(lccInvLpn.qtyIn, qtyIn)
.set(lccInvLpn.qtyOut, qtyOut) .set(lccInvLpn.qtyOut, qtyOut)
.set(lccInvLpn.createAt, new Date(System.currentTimeMillis()))
.set(lccInvLpn.createBy, "system")
.set(lccInvLpn.updateAt, new Date(System.currentTimeMillis()))
.set(lccInvLpn.updateBy, "system")
.execute(); .execute();
// 记录账页 // 记录账页
queryDSL.insert(lccInvLedger) queryDSL.insert(lccInvLedger)
.set(lccInvLedger.ledgerId, SnowFlake.SNOW_FLAKE.nextId())
.set(lccInvLedger.envId, envId) .set(lccInvLedger.envId, envId)
.set(lccInvLedger.lpn, lpn) .set(lccInvLedger.lpn, lpn)
.set(lccInvLedger.bizTaskId, bizTaskId)
.set(lccInvLedger.locCode, locCode) .set(lccInvLedger.locCode, locCode)
.set(lccInvLedger.layerIndex, layerIndex) .set(lccInvLedger.layerIndex, layerIndex)
.set(lccInvLedger.qtyChange, qty) .set(lccInvLedger.qtyChange, qty)
@ -122,17 +137,21 @@ public class InvManager {
.set(lccInvLedger.qtyOut, qtyOut) .set(lccInvLedger.qtyOut, qtyOut)
.set(lccInvLedger.ledgerType, "记账") .set(lccInvLedger.ledgerType, "记账")
.set(lccInvLedger.ledgerRemark, "N/A") .set(lccInvLedger.ledgerRemark, "N/A")
.set(lccInvLedger.createAt, new Date(System.currentTimeMillis()))
.set(lccInvLedger.createBy, "system")
.set(lccInvLedger.updateAt, new Date(System.currentTimeMillis()))
.set(lccInvLedger.updateBy, "system")
.execute(); .execute();
} }
// 删除所有数量预占预扣都为0的库存 // 删除所有数量预占预扣都为0的库存
queryDSL.delete(lccInvLpn).where(lccInvLpn.qty.eq(0).and(lccInvLpn.qtyIn.eq(0)).and(lccInvLpn.qtyOut.eq(0))).execute(); queryDSL.delete(lccInvLpn).where(lccInvLpn.qty.eq(0).and(lccInvLpn.qtyIn.eq(0)).and(lccInvLpn.qtyOut.eq(0))).execute();
});
} }
/** /**
* 记录库存 * 记录库存
*
* @param envId 环境ID * @param envId 环境ID
* @param lpn 容器号 * @param lpn 容器号
* @param locCode 库位号 * @param locCode 库位号
@ -140,31 +159,33 @@ public class InvManager {
* @param qtyIn 入库数量 >0 减数量 <0 减数量 * @param qtyIn 入库数量 >0 减数量 <0 减数量
* @param qtyOut 出库数量 >0 减数量 <0 减数量 * @param qtyOut 出库数量 >0 减数量 <0 减数量
*/ */
public static void invSave(Long envId, String lpn, String locCode, int qty, int qtyIn, int qtyOut) { public static void invSave(Long envId, Long bizTaskId, String lpn, String locCode, int qty, int qtyIn, int qtyOut) {
invSave(envId, lpn, locCode, 0, qty, qtyIn, qtyOut); invSave(envId, bizTaskId, lpn, locCode, 0, qty, qtyIn, qtyOut);
} }
/** /**
* 保存库存 * 保存库存
*
* @param envId 环境ID * @param envId 环境ID
* @param lpn 容器号 * @param lpn 容器号
* @param locCode 库位号 * @param locCode 库位号
* @param layerIndex 堆叠层 * @param layerIndex 堆叠层
* @param qty 数量 >0 减数量 <0 减数量 * @param qty 数量 >0 减数量 <0 减数量
*/ */
public static void invSave(Long envId, String lpn, String locCode, int layerIndex, int qty) { public static void invSave(Long envId, Long bizTaskId, String lpn, String locCode, int layerIndex, int qty) {
invSave(envId, lpn, locCode, layerIndex, qty, 0, 0); invSave(envId, bizTaskId, lpn, locCode, layerIndex, qty, 0, 0);
} }
/** /**
* 保存库存 * 保存库存
*
* @param envId 环境ID * @param envId 环境ID
* @param lpn 容器号 * @param lpn 容器号
* @param locCode 库位号 * @param locCode 库位号
* @param qty 数量 >0 减数量 <0 减数量 * @param qty 数量 >0 减数量 <0 减数量
*/ */
public static void invSave(Long envId, String lpn, String locCode, int qty) { public static void invSave(Long envId, Long bizTaskId, String lpn, String locCode, int qty) {
invSave(envId, lpn, locCode, 0, qty, 0, 0); invSave(envId, bizTaskId, lpn, locCode, 0, qty, 0, 0);
} }
} }

15
servo/src/main/java/com/galaxis/rcs/plan/PlanTaskSequence.java

@ -6,12 +6,10 @@ import com.galaxis.rcs.common.entity.RcsTaskPlan;
import com.galaxis.rcs.common.enums.PlanTaskStatus; import com.galaxis.rcs.common.enums.PlanTaskStatus;
import com.galaxis.rcs.common.enums.PlanTaskType; import com.galaxis.rcs.common.enums.PlanTaskType;
import com.google.common.base.Joiner; import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.yvan.entity.BasLocationVo;
import com.yvan.logisticsModel.LogisticsRuntime; import com.yvan.logisticsModel.LogisticsRuntime;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.clever.core.BannerUtils;
import org.clever.core.id.SnowFlake; import org.clever.core.id.SnowFlake;
import org.clever.core.json.JsonWrapper; import org.clever.core.json.JsonWrapper;
@ -33,7 +31,12 @@ public class PlanTaskSequence {
public String lastWayPointId; public String lastWayPointId;
public Float lastRotationAngle = null; public Float lastRotationAngle = null;
public String lastLoadLpn = "";
public String carryLpn;
public BasLocationVo loadBasLocationVo;
public BasLocationVo unloadBasLocationVo;
public BasLocationVo executorVo;
public int carryQty;
public PlanTaskSequence(String executorId, LogisticsRuntime logisticsRuntime, RcsTaskBiz bizTask, String createBy) { public PlanTaskSequence(String executorId, LogisticsRuntime logisticsRuntime, RcsTaskBiz bizTask, String createBy) {
this.executorId = executorId; this.executorId = executorId;
@ -90,13 +93,12 @@ public class PlanTaskSequence {
} }
// 添加取货动作 // 添加取货动作
public RcsTaskPlan addLoad(String lpn, String rackId, int bay, int level, int cell) { public RcsTaskPlan addLoad( String rackId, int bay, int level, int cell) {
RcsTaskPlan task = this.createTaskPlanEntity(PlanTaskType.LOAD.toString()); RcsTaskPlan task = this.createTaskPlanEntity(PlanTaskType.LOAD.toString());
task.setTargetId(rackId); task.setTargetId(rackId);
task.setTargetBay(bay); task.setTargetBay(bay);
task.setTargetLevel(level); task.setTargetLevel(level);
task.setTargetCell(cell); task.setTargetCell(cell);
this.lastLoadLpn = lpn;
return task; return task;
} }
@ -107,7 +109,6 @@ public class PlanTaskSequence {
task.setTargetBay(bay); task.setTargetBay(bay);
task.setTargetLevel(level); task.setTargetLevel(level);
task.setTargetCell(cell); task.setTargetCell(cell);
this.lastLoadLpn = "";
return task; return task;
} }

4
servo/src/main/java/com/galaxis/rcs/plan/path/PtrPathPlanner.java

@ -123,7 +123,7 @@ public class PtrPathPlanner {
// 生成指令序列 // 生成指令序列
generateMoves(plan, toLoadPath); generateMoves(plan, toLoadPath);
plan.addLoad(task.lpn(), loadRackId, pickupBay, task.from().level(), task.from().cell()); plan.addLoad(loadRackId, pickupBay, task.from().level(), task.from().cell());
generateMoves(plan, toUnloadPath); generateMoves(plan, toUnloadPath);
plan.addUnload(unloadRackId, task.to().level(), task.to().bay(), task.to().cell()); plan.addUnload(unloadRackId, task.to().level(), task.to().bay(), task.to().cell());
@ -218,7 +218,7 @@ public class PtrPathPlanner {
// 生成指令序列 // 生成指令序列
generateMoves(plan, toLoadPath); generateMoves(plan, toLoadPath);
plan.addLoad("N/A", loadRackId, task.to().level(), task.to().bay(), task.to().cell()); plan.addLoad(loadRackId, task.to().level(), task.to().bay(), task.to().cell());
plan.addFinish(); plan.addFinish();
} }

1
servo/src/main/java/com/galaxis/rcs/plan/task/CarryTask.java

@ -26,7 +26,6 @@ import com.galaxis.rcs.common.entity.StoreLocation;
*/ */
public record CarryTask( public record CarryTask(
String agv, String agv,
String lpn,
int priority, int priority,
StoreLocation from, StoreLocation from,
StoreLocation to StoreLocation to

13
servo/src/main/java/com/galaxis/rcs/ptr/PtrAgvItem.java

@ -136,6 +136,19 @@ public abstract class PtrAgvItem extends ExecutorItem {
public synchronized void dispatchTask(PlanTaskSequence taskSequence) { public synchronized void dispatchTask(PlanTaskSequence taskSequence) {
if (!isFree()) { if (!isFree()) {
if (!this.runtime.isRunning()) {
throw new IllegalStateException("runtime is not running!");
}
if (planTaskSequence != null && !planTaskSequence.isAllCompleted()) {
throw new IllegalStateException("AGV is busy with an existing task sequence");
}
if (!deviceTaskQueue.isEmpty()) {
throw new IllegalStateException("AGV has pending device tasks in the queue");
}
if (!isOnline) {
throw new IllegalStateException("AGV is not online and cannot accept new tasks");
}
throw new IllegalStateException("AGV is not free to accept new tasks"); throw new IllegalStateException("AGV is not free to accept new tasks");
} }

60
servo/src/main/java/com/yvan/entity/BasLocationVo.java

@ -0,0 +1,60 @@
package com.yvan.entity;
import com.galaxis.rcs.common.entity.LccBasLocation;
import com.yvan.logisticsModel.ExecutorItem;
import lombok.Data;
/**
* 用于表示货位的值对象
*/
@Data
public class BasLocationVo {
/**
* 位置编码
*/
String locCode;
/**
* 货位类型
*/
String locType;
/**
* 货位
*/
String rack;
/**
*
*/
int bay;
/**
*
*/
int level;
/**
*
*/
int cell;
public BasLocationVo(LccBasLocation basLocation) {
this.locCode = basLocation.getLocCode();
this.locType = basLocation.getLocType();
this.rack = basLocation.getRack();
this.bay = basLocation.getBay();
this.level = basLocation.getLevel();
this.cell = basLocation.getCell();
}
public BasLocationVo(ExecutorItem executorItem) {
// 从 ExecutorItem 中提取信息并赋值给 BasLocationVo
this.locCode = "AGV_" + executorItem.getId();
this.locType = executorItem.getT();
this.rack = "N/A";
this.bay = 0;
this.level = 0;
this.cell = 0;
}
}

2
servo/src/main/java/com/yvan/workbench/model/entity/LccProject.java → servo/src/main/java/com/yvan/entity/LccProject.java

@ -1,4 +1,4 @@
package com.yvan.workbench.model.entity; package com.yvan.entity;
import lombok.Data; import lombok.Data;

2
servo/src/main/java/com/yvan/workbench/model/entity/LccProjectEnv.java → servo/src/main/java/com/yvan/entity/LccProjectEnv.java

@ -1,4 +1,4 @@
package com.yvan.workbench.model.entity; package com.yvan.entity;
import com.yvan.logisticsEnv.EnvConfig; import com.yvan.logisticsEnv.EnvConfig;
import lombok.Data; import lombok.Data;

2
servo/src/main/java/com/yvan/workbench/model/entity/Vector2.java → servo/src/main/java/com/yvan/entity/Vector2.java

@ -1,4 +1,4 @@
package com.yvan.workbench.model.entity; package com.yvan.entity;
public record Vector2( public record Vector2(
/** /**

6
servo/src/main/java/com/yvan/logisticsModel/ExecutorItem.java

@ -1,14 +1,8 @@
package com.yvan.logisticsModel; package com.yvan.logisticsModel;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.galaxis.rcs.common.entity.RcsTaskPlan;
import com.galaxis.rcs.plan.PlanTaskSequence; import com.galaxis.rcs.plan.PlanTaskSequence;
import com.google.common.collect.Queues;
import com.yvan.workbench.model.entity.Vector2;
import java.util.Map; import java.util.Map;
import java.util.Queue;
import java.util.concurrent.BlockingQueue;
/** /**
* 物流任务执行单元(如拣货台小车AGV堆垛机人等) * 物流任务执行单元(如拣货台小车AGV堆垛机人等)

60
servo/src/main/java/com/yvan/logisticsModel/LogisticsRuntime.java

@ -1,6 +1,10 @@
package com.yvan.logisticsModel; package com.yvan.logisticsModel;
import com.galaxis.rcs.common.entity.RcsTaskPlan;
import com.galaxis.rcs.common.enums.PlanTaskType;
import com.galaxis.rcs.connector.cl2.Cl2Item; import com.galaxis.rcs.connector.cl2.Cl2Item;
import com.galaxis.rcs.inv.InvManager;
import com.galaxis.rcs.plan.PlanTaskSequence;
import com.galaxis.rcs.plan.path.NavigationGraph; import com.galaxis.rcs.plan.path.NavigationGraph;
import com.galaxis.rcs.plan.path.PtrPathPlanner; import com.galaxis.rcs.plan.path.PtrPathPlanner;
import com.galaxis.rcs.ptr.AmrMessageHandler; import com.galaxis.rcs.ptr.AmrMessageHandler;
@ -12,26 +16,27 @@ import com.google.common.collect.Maps;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.yvan.event.AgvEventManager; import com.yvan.event.AgvEventManager;
import com.yvan.event.AgvEventType; import com.yvan.event.AgvEventType;
import com.yvan.mqtt.FrontendMessagePushService; import com.yvan.pusher.FrontendMessagePushService;
import com.yvan.redis.LccRedisService; import com.yvan.redis.LccRedisService;
import com.yvan.workbench.model.entity.LccProject; import com.yvan.entity.LccProject;
import com.yvan.workbench.model.entity.LccProjectEnv; import com.yvan.entity.LccProjectEnv;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.clever.core.BannerUtils; import org.clever.core.BannerUtils;
import org.clever.core.Conv; import org.clever.core.Conv;
import org.clever.data.jdbc.DaoFactory;
import org.clever.data.jdbc.QueryDSL;
import org.clever.data.redis.Redis; import org.clever.data.redis.Redis;
import org.clever.data.redis.RedisAdmin; import org.clever.data.redis.RedisAdmin;
import java.util.Date; import java.util.*;
import java.util.List;
import java.util.Map;
import java.util.Set;
/** /**
* 物流运行时 * 物流运行时
*/ */
@Slf4j @Slf4j
public class LogisticsRuntime { public class LogisticsRuntime {
public final QueryDSL queryDSL = DaoFactory.getQueryDSL();
/** /**
* 项目UUID * 项目UUID
*/ */
@ -134,12 +139,53 @@ public class LogisticsRuntime {
for (int i = 1; i < args.length; i++) { for (int i = 1; i < args.length; i++) {
eventArgs[i - 1] = Conv.asString(args[i]); eventArgs[i - 1] = Conv.asString(args[i]);
} }
if (type == AgvEventType.PLAN_TASK_COMPLETE) {
PlanTaskSequence taskSequence = (PlanTaskSequence) args[1];
RcsTaskPlan taskPlan = (RcsTaskPlan) args[2];
PlanTaskType planType = PlanTaskType.valueOf(taskPlan.getPlanType());
if (planType == PlanTaskType.LOAD) {
// 处理库存变化 rack-> agv
changeInvOfLoad(taskSequence, taskPlan);
} else if (planType == PlanTaskType.UNLOAD) {
// 处理库存变化 agv -> rack
changeInvOfUnload(taskSequence, taskPlan);
}
}
BannerUtils.printConfig(log, this.projectUuid + "(" + this.envId + ") " + type + " AGV:" + sender.getId(), eventArgs); BannerUtils.printConfig(log, this.projectUuid + "(" + this.envId + ") " + type + " AGV:" + sender.getId(), eventArgs);
}); });
} }
/** /**
* 库存转移 AGV->货架
*/
private void changeInvOfUnload(PlanTaskSequence taskSequence, RcsTaskPlan taskPlan) {
queryDSL.beginTX(status -> {
String lpn = taskSequence.carryLpn;
InvManager.invSave(this.envId, taskSequence.bizTask.getBizTaskId(), lpn, taskSequence.executorVo.getLocCode(), -taskSequence.carryQty);
InvManager.invSave(this.envId, taskSequence.bizTask.getBizTaskId(), lpn, taskSequence.unloadBasLocationVo.getLocCode(), taskSequence.carryQty);
this.frontendMessagePushService.pushInventoryUpdate(lpn, taskSequence.executorVo, taskSequence.unloadBasLocationVo, taskSequence.carryQty);
});
}
/**
* 库存转移 货架->AGV
*/
private void changeInvOfLoad(PlanTaskSequence taskSequence, RcsTaskPlan taskPlan) {
queryDSL.beginTX(status -> {
String lpn = taskSequence.carryLpn;
InvManager.invSave(this.envId, taskSequence.bizTask.getBizTaskId(), lpn, taskSequence.loadBasLocationVo.getLocCode(), -taskSequence.carryQty);
InvManager.invSave(this.envId, taskSequence.bizTask.getBizTaskId(), lpn, taskSequence.executorVo.getLocCode(), taskSequence.carryQty);
this.frontendMessagePushService.pushInventoryUpdate(lpn, taskSequence.loadBasLocationVo, taskSequence.executorVo, taskSequence.carryQty);
});
}
/**
* 获取当前空闲的执行器列表 * 获取当前空闲的执行器列表
*/ */
public List<ExecutorItem> getFreeExecutorList() { public List<ExecutorItem> getFreeExecutorList() {

4
servo/src/main/java/com/yvan/logisticsModel/LogisticsRuntimeService.java

@ -1,8 +1,8 @@
package com.yvan.logisticsModel; package com.yvan.logisticsModel;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.yvan.workbench.model.entity.LccProject; import com.yvan.entity.LccProject;
import com.yvan.workbench.model.entity.LccProjectEnv; import com.yvan.entity.LccProjectEnv;
import lombok.SneakyThrows; import lombok.SneakyThrows;
import java.net.InetAddress; import java.net.InetAddress;

13
servo/src/main/java/com/yvan/mqtt/FrontendMessagePushService.java → servo/src/main/java/com/yvan/pusher/FrontendMessagePushService.java

@ -1,5 +1,6 @@
package com.yvan.mqtt; package com.yvan.pusher;
import com.yvan.entity.BasLocationVo;
import com.yvan.logisticsEnv.EnvConfig; import com.yvan.logisticsEnv.EnvConfig;
import com.yvan.logisticsModel.LogisticsRuntime; import com.yvan.logisticsModel.LogisticsRuntime;
import lombok.Getter; import lombok.Getter;
@ -165,18 +166,20 @@ public class FrontendMessagePushService implements MqttCallback {
/** /**
* 推送库存更新 * 推送库存更新
* /lcc/{proj_id}/{env_id}/inv/{catalogCode} * /lcc/{proj_id}/{env_id}/inv
* *
* @param catalogCode 货位目录编码 * @param lpn 容器号
* @param before 更新前库存 * @param before 更新前库存
* @param after 更新后库存 * @param after 更新后库存
*/ */
public void pushInventoryUpdate(String catalogCode, Object before, Object after) { public void pushInventoryUpdate(String lpn, BasLocationVo before, BasLocationVo after, int qty) {
String topic = buildTopic("inv/" + catalogCode); String topic = buildTopic("inv");
Map<String, Object> data = new HashMap<>(); Map<String, Object> data = new HashMap<>();
data.put("lpn", lpn);
data.put("before", before); data.put("before", before);
data.put("after", after); data.put("after", after);
data.put("qty", qty);
publishJson(topic, data); publishJson(topic, data);
} }

2
servo/src/main/java/com/yvan/workbench/controller/LccModelManager.java

@ -4,7 +4,7 @@ import com.galaxis.rcs.common.entity.LccBasLocation;
import com.galaxis.rcs.common.entity.StoreLocation; import com.galaxis.rcs.common.entity.StoreLocation;
import com.galaxis.rcs.ptr.JacksonUtils; import com.galaxis.rcs.ptr.JacksonUtils;
import com.yvan.workbench.SpringContext; import com.yvan.workbench.SpringContext;
import com.yvan.workbench.model.entity.LccProject; import com.yvan.entity.LccProject;
import com.yvan.workbench.service.LccMapService; import com.yvan.workbench.service.LccMapService;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import lombok.SneakyThrows; import lombok.SneakyThrows;

222
servo/src/main/java/com/yvan/workbench/controller/RcsController.java

@ -1,6 +1,6 @@
package com.yvan.workbench.controller; package com.yvan.workbench.controller;
import com.galaxis.rcs.RCSService; import com.galaxis.rcs.common.entity.LccBasLocation;
import com.galaxis.rcs.common.entity.RcsTaskBiz; import com.galaxis.rcs.common.entity.RcsTaskBiz;
import com.galaxis.rcs.common.entity.StoreLocation; import com.galaxis.rcs.common.entity.StoreLocation;
import com.galaxis.rcs.common.enums.BizTaskStatus; import com.galaxis.rcs.common.enums.BizTaskStatus;
@ -11,6 +11,7 @@ import com.galaxis.rcs.plan.task.*;
import com.galaxis.rcs.ptr.PtrAgvItem; import com.galaxis.rcs.ptr.PtrAgvItem;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.yvan.entity.BasLocationVo;
import com.yvan.logisticsModel.ExecutorItem; import com.yvan.logisticsModel.ExecutorItem;
import com.yvan.logisticsModel.LogisticsRuntime; import com.yvan.logisticsModel.LogisticsRuntime;
import com.yvan.logisticsModel.LogisticsRuntimeService; import com.yvan.logisticsModel.LogisticsRuntimeService;
@ -22,6 +23,9 @@ import org.clever.web.mvc.annotation.RequestBody;
import java.util.Map; import java.util.Map;
import static com.galaxis.rcs.common.query.QLccBasLocation.lccBasLocation;
import static com.galaxis.rcs.common.query.QLccInvLpn.lccInvLpn;
public class RcsController { public class RcsController {
static final SnowFlake snowFlake = new SnowFlake(); static final SnowFlake snowFlake = new SnowFlake();
@ -130,6 +134,101 @@ public class RcsController {
return R.success(executorItem); return R.success(executorItem);
} }
public static R<?> agvCarry(@RequestBody Map<String, Object> params) {
Object ret = getCommonParamAndCreateBizTask(params);
if (ret instanceof R) {
// 异常
return (R<?>) ret;
}
RcsCommonParam ps = (RcsCommonParam) ret;
// ==================== 查找来源货位 ====================
String fromStoreLoc = Conv.asString(params.get("fromStoreLoc"));
if (Strings.isNullOrEmpty(fromStoreLoc)) {
return R.fail("fromStoreLoc Must not be empty");
}
StoreLocation sourceLocation = StoreLocation.of(fromStoreLoc, "/");
StaticItem sourceItem = ps.runtime.getStaticItemById(sourceLocation.rackId());
if (sourceItem == null) {
return R.fail("fromStoreLoc storePoint not found!");
}
// 查找货位基础资料
LccBasLocation loadBasLocation = ps.runtime.queryDSL.selectFrom(
lccBasLocation
)
.where(lccBasLocation.envId.eq(ps.envId))
.where(lccBasLocation.rack.eq(sourceLocation.rackId()))
.where(lccBasLocation.bay.eq(sourceLocation.bay()))
.where(lccBasLocation.level.eq(sourceLocation.level()))
.where(lccBasLocation.cell.eq(sourceLocation.cell()))
.fetchFirst();
if (loadBasLocation == null) {
return R.fail("fromStoreLoc location not found!");
}
// ==================== 查找卸货货位 ====================
String targetStoreLoc = Conv.asString(params.get("targetStoreLoc"));
if (Strings.isNullOrEmpty(targetStoreLoc)) {
return R.fail("targetStoreLoc Must not be empty");
}
StoreLocation targetLocation = StoreLocation.of(targetStoreLoc, "/");
StaticItem targetItem = ps.runtime.getStaticItemById(targetLocation.rackId());
if (targetItem == null) {
return R.fail("targetStoreLoc storePoint not found!");
}
// 查找货位基础资料
LccBasLocation unloadBasLocation = ps.runtime.queryDSL.selectFrom(
lccBasLocation
)
.where(lccBasLocation.envId.eq(ps.envId))
.where(lccBasLocation.rack.eq(targetLocation.rackId()))
.where(lccBasLocation.bay.eq(targetLocation.bay()))
.where(lccBasLocation.level.eq(targetLocation.level()))
.where(lccBasLocation.cell.eq(targetLocation.cell()))
.fetchFirst();
if (unloadBasLocation == null) {
return R.fail("targetStoreLoc location not found!");
}
// ==================== 找到托盘号 ====================
String lpn = ps.runtime.queryDSL
.select(lccInvLpn.lpn)
.from(lccInvLpn)
.where(lccInvLpn.envId.eq(ps.envId))
.where(lccInvLpn.locCode.eq(loadBasLocation.getLocCode()))
.fetchFirst();
if (Strings.isNullOrEmpty(lpn)) {
return R.fail("LPN not found at fromStoreLoc: " + fromStoreLoc);
}
// ==================== 布置任务 ====================
ps.bizTask.setLpn(lpn);
ps.bizTask.setTaskFrom(loadBasLocation.getCatalogCode());
ps.bizTask.setTaskTo(unloadBasLocation.getLocCode());
CarryTask carryTask = new CarryTask(
ps.agvId, ps.bizTask.getPriority(),
sourceLocation,
targetLocation
);
ps.planSequence.executorVo = new BasLocationVo(ps.agv);
ps.planSequence.loadBasLocationVo = new BasLocationVo(loadBasLocation);
ps.planSequence.unloadBasLocationVo = new BasLocationVo(unloadBasLocation);
ps.planSequence.carryLpn = lpn;
ps.planSequence.carryQty = 1;
ps.runtime.pathPlannerMap.get(ps.agv.getT())
.planCarryTask(ps.planSequence, ps.fromItem.getId(), ps.fromDirection, carryTask);
ps.agv.logicX = ps.fromItem.logicX;
ps.agv.logicY = ps.fromItem.logicY;
ps.agv.dispatchTask(ps.planSequence);
return R.success(ps.planSequence.toPrettyMap());
}
public static R<Object> agvUnload(@RequestBody Map<String, Object> params) { public static R<Object> agvUnload(@RequestBody Map<String, Object> params) {
Object ret = getCommonParamAndCreateBizTask(params); Object ret = getCommonParamAndCreateBizTask(params);
if (ret instanceof R) { if (ret instanceof R) {
@ -138,16 +237,52 @@ public class RcsController {
} }
RcsCommonParam ps = (RcsCommonParam) ret; RcsCommonParam ps = (RcsCommonParam) ret;
// ==================== 查找卸货货位 ====================
String targetStoreLoc = Conv.asString(params.get("targetStoreLoc")); String targetStoreLoc = Conv.asString(params.get("targetStoreLoc"));
if (Strings.isNullOrEmpty(targetStoreLoc)) { if (Strings.isNullOrEmpty(targetStoreLoc)) {
return R.fail("targetStoreLoc Must not be empty"); return R.fail("targetStoreLoc Must not be empty");
} }
StoreLocation targetLocation = StoreLocation.of(targetStoreLoc, "/"); StoreLocation targetLocation = StoreLocation.of(targetStoreLoc, "/");
// 查找货位基础资料
LccBasLocation unloadBasLocation = ps.runtime.queryDSL.selectFrom(
lccBasLocation
)
.where(lccBasLocation.envId.eq(ps.envId))
.where(lccBasLocation.rack.eq(targetLocation.rackId()))
.where(lccBasLocation.bay.eq(targetLocation.bay()))
.where(lccBasLocation.level.eq(targetLocation.level()))
.where(lccBasLocation.cell.eq(targetLocation.cell()))
.fetchFirst();
if (unloadBasLocation == null) {
return R.fail("targetStoreLoc location not found!");
}
// ==================== 找到托盘号 ====================
BasLocationVo executorVo = new BasLocationVo(ps.agv);
String lpn = ps.runtime.queryDSL
.select(lccInvLpn.lpn)
.from(lccInvLpn)
.where(lccInvLpn.envId.eq(ps.envId))
.where(lccInvLpn.locCode.eq(executorVo.getLocCode()))
.fetchFirst();
if (Strings.isNullOrEmpty(lpn)) {
return R.fail("LPN not found at StoreLoc: " + executorVo.getLocCode());
}
// ==================== 布置任务 ====================
ps.bizTask.setLpn(lpn);
ps.bizTask.setTaskFrom(ps.fromItem.getId());
ps.bizTask.setTaskTo(unloadBasLocation.getLocCode());
UnloadTask unloadTask = new UnloadTask( UnloadTask unloadTask = new UnloadTask(
ps.agvId, ps.bizTask.getPriority(), ps.agvId, ps.bizTask.getPriority(),
targetLocation targetLocation
); );
ps.planSequence.executorVo = executorVo;
ps.planSequence.loadBasLocationVo = null;
ps.planSequence.unloadBasLocationVo = new BasLocationVo(unloadBasLocation);
ps.planSequence.carryLpn = lpn;
ps.planSequence.carryQty = 1;
ps.runtime.pathPlannerMap.get(ps.agv.getT()) ps.runtime.pathPlannerMap.get(ps.agv.getT())
.planUnloadTask(ps.planSequence, ps.fromItem.getId(), ps.fromDirection, unloadTask); .planUnloadTask(ps.planSequence, ps.fromItem.getId(), ps.fromDirection, unloadTask);
@ -167,16 +302,51 @@ public class RcsController {
} }
RcsCommonParam ps = (RcsCommonParam) ret; RcsCommonParam ps = (RcsCommonParam) ret;
// ==================== 查找来源货位 ====================
String targetStoreLoc = Conv.asString(params.get("targetStoreLoc")); String targetStoreLoc = Conv.asString(params.get("targetStoreLoc"));
if (Strings.isNullOrEmpty(targetStoreLoc)) { if (Strings.isNullOrEmpty(targetStoreLoc)) {
return R.fail("targetStoreLoc Must not be empty"); return R.fail("targetStoreLoc Must not be empty");
} }
StoreLocation targetLocation = StoreLocation.of(targetStoreLoc, "/"); StoreLocation targetLocation = StoreLocation.of(targetStoreLoc, "/");
// 查找货位基础资料
LccBasLocation loadBasLocation = ps.runtime.queryDSL.selectFrom(
lccBasLocation
)
.where(lccBasLocation.envId.eq(ps.envId))
.where(lccBasLocation.rack.eq(targetLocation.rackId()))
.where(lccBasLocation.bay.eq(targetLocation.bay()))
.where(lccBasLocation.level.eq(targetLocation.level()))
.where(lccBasLocation.cell.eq(targetLocation.cell()))
.fetchFirst();
if (loadBasLocation == null) {
return R.fail("targetStoreLoc location not found!");
}
// ==================== 找到托盘号 ====================
String lpn = ps.runtime.queryDSL
.select(lccInvLpn.lpn)
.from(lccInvLpn)
.where(lccInvLpn.envId.eq(ps.envId))
.where(lccInvLpn.locCode.eq(loadBasLocation.getLocCode()))
.fetchFirst();
if (Strings.isNullOrEmpty(lpn)) {
return R.fail("LPN not found at targetStoreLoc: " + loadBasLocation.getLocCode());
}
// ==================== 布置任务 ====================
ps.bizTask.setLpn(lpn);
ps.bizTask.setTaskFrom(ps.fromItem.getId());
ps.bizTask.setTaskTo(loadBasLocation.getLocCode());
LoadTask loadTask = new LoadTask( LoadTask loadTask = new LoadTask(
ps.agvId, ps.bizTask.getPriority(), ps.agvId, ps.bizTask.getPriority(),
targetLocation targetLocation
); );
ps.planSequence.executorVo = new BasLocationVo(ps.agv);
ps.planSequence.loadBasLocationVo = new BasLocationVo(loadBasLocation);
ps.planSequence.unloadBasLocationVo = null;
ps.planSequence.carryLpn = lpn;
ps.planSequence.carryQty = 1;
ps.runtime.pathPlannerMap.get(ps.agv.getT()) ps.runtime.pathPlannerMap.get(ps.agv.getT())
.planLoadTask(ps.planSequence, ps.fromItem.getId(), ps.fromDirection, loadTask); .planLoadTask(ps.planSequence, ps.fromItem.getId(), ps.fromDirection, loadTask);
@ -224,56 +394,6 @@ public class RcsController {
return R.success(cost); return R.success(cost);
} }
public static R<?> agvCarry(@RequestBody Map<String, Object> params) {
Object ret = getCommonParamAndCreateBizTask(params);
if (ret instanceof R) {
// 异常
return (R<?>) ret;
}
RcsCommonParam ps = (RcsCommonParam) ret;
String fromStoreLoc = Conv.asString(params.get("fromStoreLoc"));
String targetStoreLoc = Conv.asString(params.get("targetStoreLoc"));
if (Strings.isNullOrEmpty(fromStoreLoc)) {
return R.fail("fromStoreLoc Must not be empty");
}
if (Strings.isNullOrEmpty(targetStoreLoc)) {
return R.fail("targetStoreLoc Must not be empty");
}
StoreLocation sourceLocation = StoreLocation.of(fromStoreLoc, "/");
StoreLocation targetLocation = StoreLocation.of(targetStoreLoc, "/");
StaticItem sourceItem = ps.runtime.getStaticItemById(sourceLocation.rackId());
if (sourceItem == null) {
return R.fail("fromStoreLoc storePoint not found!");
}
StaticItem targetItem = ps.runtime.getStaticItemById(targetLocation.rackId());
if (targetItem == null) {
return R.fail("targetStoreLoc storePoint not found!");
}
ps.bizTask.setTaskFrom(fromStoreLoc);
ps.bizTask.setTaskTo(targetStoreLoc);
CarryTask carryTask = new CarryTask(
ps.agvId, "N/A", ps.bizTask.getPriority(),
sourceLocation,
targetLocation
);
ps.runtime.pathPlannerMap.get(ps.agv.getT())
.planCarryTask(ps.planSequence, ps.fromItem.getId(), ps.fromDirection, carryTask);
ps.agv.logicX = ps.fromItem.logicX;
ps.agv.logicY = ps.fromItem.logicY;
ps.agv.dispatchTask(ps.planSequence);
return R.success(ps.planSequence.toPrettyMap());
}
public static Object getCommonParamAndCreateBizTask(@RequestBody Map<String, Object> params) { public static Object getCommonParamAndCreateBizTask(@RequestBody Map<String, Object> params) {
String projectUUID = Conv.asString(params.get("projectUUID")); String projectUUID = Conv.asString(params.get("projectUUID"));
Long envId = Conv.asLong(params.get("envId")); Long envId = Conv.asLong(params.get("envId"));

7
servo/src/main/java/com/yvan/workbench/service/LccMapService.java

@ -1,21 +1,18 @@
package com.yvan.workbench.service; package com.yvan.workbench.service;
import com.google.common.base.Joiner;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.yvan.LccUtils; import com.yvan.LccUtils;
import com.yvan.workbench.autoconfigure.LccConfigProperties; import com.yvan.workbench.autoconfigure.LccConfigProperties;
import com.yvan.workbench.model.entity.LccProject; import com.yvan.entity.LccProject;
import com.yvan.workbench.model.entity.LccProjectEnv; import com.yvan.entity.LccProjectEnv;
import lombok.SneakyThrows; import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.FilenameUtils;
import org.clever.core.Conv; import org.clever.core.Conv;
import org.clever.core.mapper.JacksonMapper; import org.clever.core.mapper.JacksonMapper;
import java.io.File; import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;

Loading…
Cancel
Save