14 changed files with 798 additions and 38 deletions
@ -0,0 +1,422 @@ |
|||
[ |
|||
{ |
|||
"id": "rack1", |
|||
"t": "rack", |
|||
"v": true, |
|||
"tf": [ |
|||
[ |
|||
1.55, |
|||
0, |
|||
-1.5 |
|||
], |
|||
[ |
|||
0, |
|||
0, |
|||
0 |
|||
], |
|||
[ |
|||
2.2, |
|||
2.8, |
|||
1 |
|||
] |
|||
], |
|||
"dt": { |
|||
"rackDepth": 1, |
|||
"bottomBarHeight": 0.2, |
|||
"bottomLinkHeight": 0.2, |
|||
"topLinkDistance": 0.2, |
|||
"levelCount": 2, |
|||
"bayCount": 2, |
|||
"hideFloor": 0, |
|||
"extendColumns": 1, |
|||
"columnSpacing": 1, |
|||
"bays": [ |
|||
{ |
|||
"bayWidth": 1.1, |
|||
"levelHeight": [ |
|||
1.4, |
|||
1.4 |
|||
] |
|||
}, |
|||
{ |
|||
"bayWidth": 1.1, |
|||
"levelHeight": [ |
|||
1.4, |
|||
1.4 |
|||
] |
|||
} |
|||
], |
|||
"center": [], |
|||
"in": [], |
|||
"out": [], |
|||
"rackWidth": 2.2, |
|||
"rackHeight": 2.8 |
|||
}, |
|||
"_rid": "_2" |
|||
}, |
|||
{ |
|||
"id": "rack2", |
|||
"t": "rack", |
|||
"v": true, |
|||
"tf": [ |
|||
[ |
|||
3.9, |
|||
0, |
|||
-1.5 |
|||
], |
|||
[ |
|||
0, |
|||
0, |
|||
0 |
|||
], |
|||
[ |
|||
2.2, |
|||
2.8, |
|||
1 |
|||
] |
|||
], |
|||
"dt": { |
|||
"rackDepth": 1, |
|||
"bottomBarHeight": 0.2, |
|||
"bottomLinkHeight": 0.2, |
|||
"topLinkDistance": 0.2, |
|||
"levelCount": 2, |
|||
"bayCount": 2, |
|||
"hideFloor": 0, |
|||
"extendColumns": 1, |
|||
"columnSpacing": 1, |
|||
"bays": [ |
|||
{ |
|||
"bayWidth": 1.1, |
|||
"levelHeight": [ |
|||
1.4, |
|||
1.4 |
|||
] |
|||
}, |
|||
{ |
|||
"bayWidth": 1.1, |
|||
"levelHeight": [ |
|||
1.4, |
|||
1.4 |
|||
] |
|||
} |
|||
], |
|||
"center": [], |
|||
"in": [], |
|||
"out": [], |
|||
"rackWidth": 2.2, |
|||
"rackHeight": 2.8 |
|||
}, |
|||
"_rid": "_3" |
|||
}, |
|||
{ |
|||
"id": "1_2", |
|||
"t": "way", |
|||
"v": true, |
|||
"logicX": 1, |
|||
"logicY": 2, |
|||
"tf": [ |
|||
[ |
|||
1, |
|||
0.01, |
|||
0 |
|||
], |
|||
[ |
|||
0, |
|||
0, |
|||
0 |
|||
], |
|||
[ |
|||
0.25, |
|||
0.1, |
|||
0.25 |
|||
] |
|||
], |
|||
"dt": { |
|||
"in": [ |
|||
"2_2" |
|||
], |
|||
"out": [ |
|||
"2_2" |
|||
], |
|||
"center": [], |
|||
"linkStore": [ |
|||
{ |
|||
"item": "rack1", |
|||
"bay": 0, |
|||
"level": 0, |
|||
"cell": 0, |
|||
"direction": "up" |
|||
}, |
|||
{ |
|||
"item": "rack1", |
|||
"bay": 0, |
|||
"level": 1, |
|||
"cell": 0, |
|||
"direction": "up" |
|||
} |
|||
] |
|||
}, |
|||
"_rid": "_4" |
|||
}, |
|||
{ |
|||
"id": "2_2", |
|||
"t": "way", |
|||
"v": true, |
|||
"logicX": 2, |
|||
"logicY": 2, |
|||
"tf": [ |
|||
[ |
|||
2.1, |
|||
0.01, |
|||
0 |
|||
], |
|||
[ |
|||
0, |
|||
0, |
|||
0 |
|||
], |
|||
[ |
|||
0.25, |
|||
0.1, |
|||
0.25 |
|||
] |
|||
], |
|||
"dt": { |
|||
"in": [ |
|||
"1_2", |
|||
"3_2" |
|||
], |
|||
"out": [ |
|||
"1_2", |
|||
"3_2" |
|||
], |
|||
"center": [], |
|||
"linkStore": [ |
|||
{ |
|||
"item": "rack1", |
|||
"bay": 1, |
|||
"level": 0, |
|||
"cell": 0, |
|||
"direction": "up" |
|||
}, |
|||
{ |
|||
"item": "rack1", |
|||
"bay": 1, |
|||
"level": 1, |
|||
"cell": 0, |
|||
"direction": "up" |
|||
} |
|||
] |
|||
}, |
|||
"_rid": "_5" |
|||
}, |
|||
{ |
|||
"id": "3_2", |
|||
"t": "way", |
|||
"v": true, |
|||
"logicX": 3, |
|||
"logicY": 2, |
|||
"tf": [ |
|||
[ |
|||
3.39, |
|||
0.01, |
|||
0 |
|||
], |
|||
[ |
|||
0, |
|||
0, |
|||
0 |
|||
], |
|||
[ |
|||
0.25, |
|||
0.1, |
|||
0.25 |
|||
] |
|||
], |
|||
"dt": { |
|||
"in": [ |
|||
"2_2", |
|||
"4_2" |
|||
], |
|||
"out": [ |
|||
"2_2", |
|||
"4_2" |
|||
], |
|||
"center": [], |
|||
"linkStore": [ |
|||
{ |
|||
"item": "rack2", |
|||
"bay": 0, |
|||
"level": 0, |
|||
"cell": 0, |
|||
"direction": "up" |
|||
}, |
|||
{ |
|||
"item": "rack2", |
|||
"bay": 0, |
|||
"level": 1, |
|||
"cell": 0, |
|||
"direction": "up" |
|||
} |
|||
] |
|||
}, |
|||
"_rid": "_6" |
|||
}, |
|||
{ |
|||
"id": "4_2", |
|||
"t": "way", |
|||
"v": true, |
|||
"logicX": 4, |
|||
"logicY": 2, |
|||
"tf": [ |
|||
[ |
|||
4.44, |
|||
0.01, |
|||
0 |
|||
], |
|||
[ |
|||
0, |
|||
0, |
|||
0 |
|||
], |
|||
[ |
|||
0.25, |
|||
0.1, |
|||
0.25 |
|||
] |
|||
], |
|||
"dt": { |
|||
"in": [ |
|||
"3_2", |
|||
"5_2" |
|||
], |
|||
"out": [ |
|||
"3_2", |
|||
"5_2" |
|||
], |
|||
"center": [], |
|||
"linkStore": [ |
|||
{ |
|||
"item": "rack2", |
|||
"bay": 1, |
|||
"level": 0, |
|||
"cell": 0, |
|||
"direction": "up" |
|||
}, |
|||
{ |
|||
"item": "rack2", |
|||
"bay": 1, |
|||
"level": 1, |
|||
"cell": 0, |
|||
"direction": "up" |
|||
} |
|||
] |
|||
}, |
|||
"_rid": "_7" |
|||
}, |
|||
{ |
|||
"id": "5_2", |
|||
"t": "way", |
|||
"v": true, |
|||
"logicX": 5, |
|||
"logicY": 2, |
|||
"tf": [ |
|||
[ |
|||
5.44, |
|||
0.01, |
|||
0 |
|||
], |
|||
[ |
|||
0, |
|||
0, |
|||
0 |
|||
], |
|||
[ |
|||
0.25, |
|||
0.1, |
|||
0.25 |
|||
] |
|||
], |
|||
"dt": { |
|||
"in": [ |
|||
"4_2", |
|||
"6_2" |
|||
], |
|||
"out": [ |
|||
"4_2", |
|||
"6_2" |
|||
], |
|||
"center": [] |
|||
}, |
|||
"_rid": "_8" |
|||
}, |
|||
{ |
|||
"id": "6_2", |
|||
"t": "way", |
|||
"v": true, |
|||
"logicX": 6, |
|||
"logicY": 2, |
|||
"tf": [ |
|||
[ |
|||
6.44, |
|||
0.01, |
|||
0 |
|||
], |
|||
[ |
|||
0, |
|||
0, |
|||
0 |
|||
], |
|||
[ |
|||
0.25, |
|||
0.1, |
|||
0.25 |
|||
] |
|||
], |
|||
"dt": { |
|||
"in": [ |
|||
"5_2" |
|||
], |
|||
"out": [ |
|||
"5_2" |
|||
], |
|||
"center": [], |
|||
"agvRotation": [ |
|||
"cl2", |
|||
"clx" |
|||
] |
|||
}, |
|||
"_rid": "_9" |
|||
}, |
|||
{ |
|||
"id": "3", |
|||
"t": "cl2", |
|||
"v": true, |
|||
"tf": [ |
|||
[ |
|||
6.440, |
|||
0, |
|||
0 |
|||
], |
|||
[ |
|||
0, |
|||
0, |
|||
0 |
|||
], |
|||
[ |
|||
1.5, |
|||
1.98, |
|||
1.5 |
|||
] |
|||
], |
|||
"dt": { |
|||
"in": [], |
|||
"out": [], |
|||
"center": [], |
|||
"ptrWidth": 1.5, |
|||
"ptrDepth": 1.5, |
|||
"ptrHeight": 1.98 |
|||
} |
|||
} |
|||
] |
|||
@ -0,0 +1,8 @@ |
|||
package com.galaxis.rcs.plan.task; |
|||
|
|||
public record MoveTask( |
|||
String agv, |
|||
String targetWayPointId, |
|||
int priority |
|||
) { |
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
package com.yvan.workbench.controller; |
|||
|
|||
import com.galaxis.rcs.RCS; |
|||
import com.yvan.workbench.model.entity.Model; |
|||
import org.clever.core.Conv; |
|||
import org.clever.web.mvc.annotation.RequestBody; |
|||
|
|||
import java.util.Map; |
|||
|
|||
public class LccController { |
|||
|
|||
/** |
|||
* 支持前端 RCSScript.loadFloor 方法加载楼层数据 |
|||
*/ |
|||
Model<Boolean> loadFloor(@RequestBody Map<String, Object> params) { |
|||
String projectUUID = Conv.asString(params.get("projectUUID")); |
|||
String catalogCode = Conv.asString(params.get("catalogCode")); |
|||
Long envId = Conv.asLong(params.get("envId")); |
|||
boolean result = RCS.loadFloor(projectUUID, catalogCode, envId); |
|||
|
|||
return Model.newSuccess(result); |
|||
} |
|||
} |
|||
@ -0,0 +1,244 @@ |
|||
package com.yvan.workbench.controller; |
|||
|
|||
import com.galaxis.rcs.RCS; |
|||
import com.galaxis.rcs.common.entity.RcsTaskBiz; |
|||
import com.galaxis.rcs.common.entity.StoreLocation; |
|||
import com.galaxis.rcs.common.enums.BizTaskStatus; |
|||
import com.galaxis.rcs.common.enums.BizTaskType; |
|||
import com.galaxis.rcs.common.enums.LCCDirection; |
|||
import com.galaxis.rcs.plan.PlanTaskSequence; |
|||
import com.galaxis.rcs.plan.task.CarryTask; |
|||
import com.galaxis.rcs.plan.task.MoveTask; |
|||
import com.google.common.base.Strings; |
|||
import com.yvan.logisticsModel.*; |
|||
import com.yvan.workbench.model.entity.Model; |
|||
import org.apache.commons.lang3.NotImplementedException; |
|||
import org.clever.core.Conv; |
|||
import org.clever.core.id.SnowFlake; |
|||
import org.clever.web.mvc.annotation.RequestBody; |
|||
|
|||
import java.util.Map; |
|||
|
|||
public class RcsController { |
|||
// /**
|
|||
// * 后台机器人移动
|
|||
// * @param agvId 机器人ID
|
|||
// * @param targetWayPointId 目标路径点ID
|
|||
// * @param option 选项
|
|||
// */
|
|||
// agvMove(agvId: string, targetWayPointId: string, option: any = {}): Promise<ServerResponse<boolean>>
|
|||
//
|
|||
// /**
|
|||
// * 后台机器人搬运(库存点 -> 库存点)
|
|||
// * @param agvId 机器人ID
|
|||
// * @param fromStoreLoc 库存点ID
|
|||
// * @param targetStoreLoc 目标库存点ID
|
|||
// * @param option 其他选项
|
|||
// */
|
|||
// agvCarry(agvId: string, fromStoreLoc: string, targetStoreLoc: string, option: any = {}): Promise<ServerResponse<boolean>>
|
|||
//
|
|||
// /**
|
|||
// * 机器人充电
|
|||
// * @param agvId 机器人ID
|
|||
// * @param chargerId 充电桩ID
|
|||
// * @param option 其他选项
|
|||
// */
|
|||
// agvToCharger(agvId: string, chargerId: string, option: any = {}): Promise<ServerResponse<boolean>>
|
|||
|
|||
static final SnowFlake snowFlake = new SnowFlake(); |
|||
|
|||
public static Model<Object> agvMove(@RequestBody Map<String, Object> params) { |
|||
String projectUUID = Conv.asString(params.get("projectUUID")); |
|||
String catalogCode = Conv.asString(params.get("catalogCode")); |
|||
Long envId = Conv.asLong(params.get("envId")); |
|||
String agvId = Conv.asString(params.get("agvId")); |
|||
String targetWayPointId = Conv.asString(params.get("targetWayPointId")); |
|||
Map<String, Object> option = (Map<String, Object>) params.get("option"); |
|||
|
|||
if (Strings.isNullOrEmpty(agvId)) { |
|||
return Model.newFail("agvId Must not be empty"); |
|||
} |
|||
if (Strings.isNullOrEmpty(targetWayPointId)) { |
|||
return Model.newFail("targetWayPointId Must not be empty"); |
|||
} |
|||
|
|||
RCS.loadFloor(projectUUID, catalogCode, envId); |
|||
|
|||
LogisticsRuntime logisticsRuntime = LogisticsRuntimeService.INSTANCE.findByProjectFloor(projectUUID, catalogCode); |
|||
StaticItem toItem = logisticsRuntime.getStaticItemById(targetWayPointId); |
|||
if (toItem == null) { |
|||
return Model.newFail("target wayPoint not found!"); |
|||
} |
|||
|
|||
ExecutorItem executorItem = logisticsRuntime.executorItemMap.get(agvId); |
|||
if (executorItem == null) { |
|||
return Model.newFail("executor not found: " + agvId); |
|||
} |
|||
if (!(executorItem instanceof PtrAgvItem)) { |
|||
return Model.newFail("executor is not a PtrAgvItem id=" + agvId); |
|||
} |
|||
|
|||
// 获取机器人当前所在位置, 也可以前端强制指定
|
|||
// forceStartWayPointId: '6_2', forceStartDirectior: 'right'
|
|||
StaticItem fromItem = null; |
|||
LCCDirection fromDirection = null; |
|||
if (option.get("forceStartWayPointId") != null) { |
|||
fromItem = logisticsRuntime.getStaticItemById(Conv.asString(option.get("forceStartWayPointId"))); |
|||
} else { |
|||
fromItem = logisticsRuntime.getStaticItemByLogicXY(((PtrAgvItem) executorItem).logicX, ((PtrAgvItem) executorItem).logicY); |
|||
} |
|||
if (option.get("forceStartDirection") != null) { |
|||
fromDirection = LCCDirection.fromString(Conv.asString(option.get("forceStartDirection"))); |
|||
} else { |
|||
fromDirection = ((PtrAgvItem) executorItem).getLCCDirection(); |
|||
} |
|||
|
|||
if (fromItem == null) { |
|||
return Model.newFail("PtrAgvItem not found at current location: " + ((PtrAgvItem) executorItem).logicX + "_" + ((PtrAgvItem) executorItem).logicY + ", id=" + agvId); |
|||
} |
|||
if (fromDirection == null) { |
|||
return Model.newFail("PtrAgvItem unkown direction id=" + agvId); |
|||
} |
|||
|
|||
RcsTaskBiz bizTask = new RcsTaskBiz(); |
|||
bizTask.setBizTaskId(snowFlake.nextId()); |
|||
bizTask.setEnvId(envId); |
|||
bizTask.setBizType(BizTaskType.MOVE.toString()); |
|||
bizTask.setLpn("N/A"); |
|||
bizTask.setPriority(Conv.asInteger(option.get("priority"), 1)); |
|||
bizTask.setTaskFrom(fromItem.getId()); |
|||
bizTask.setTaskTo(targetWayPointId); |
|||
bizTask.setAllocatedExecutorId(agvId); |
|||
bizTask.setBizTaskPayload("N/A"); |
|||
bizTask.setBizTaskErrorInfo("N/A"); |
|||
bizTask.setBizTaskDescription("N/A"); |
|||
bizTask.setBizTaskStatus(BizTaskStatus.WAITING_FOR_DISPATCH.toString()); |
|||
|
|||
PlanTaskSequence planSequence = new PlanTaskSequence(agvId, logisticsRuntime, bizTask, "demo"); |
|||
|
|||
MoveTask moveTask = new MoveTask( |
|||
agvId, bizTask.getTaskTo(), bizTask.getPriority() |
|||
); |
|||
|
|||
logisticsRuntime.pathPlannerMap.get(executorItem.getT()) |
|||
.planMoveTask(planSequence, fromItem.getId(), fromDirection, moveTask); |
|||
return Model.newSuccess(planSequence.toPrettyMap()); |
|||
} |
|||
|
|||
public static Model<Object> agvInfo(@RequestBody Map<String, Object> params) { |
|||
String projectUUID = Conv.asString(params.get("projectUUID")); |
|||
String catalogCode = Conv.asString(params.get("catalogCode")); |
|||
Long envId = Conv.asLong(params.get("envId")); |
|||
String agvId = Conv.asString(params.get("agvId")); |
|||
|
|||
if (Strings.isNullOrEmpty(agvId)) { |
|||
return Model.newFail("agvId Must not be empty"); |
|||
} |
|||
|
|||
RCS.loadFloor(projectUUID, catalogCode, envId); |
|||
|
|||
LogisticsRuntime logisticsRuntime = LogisticsRuntimeService.INSTANCE.findByProjectFloor(projectUUID, catalogCode); |
|||
|
|||
ExecutorItem executorItem = logisticsRuntime.executorItemMap.get(agvId); |
|||
if (executorItem == null) { |
|||
return Model.newFail("executor not found: " + agvId); |
|||
} |
|||
if (!(executorItem instanceof PtrAgvItem)) { |
|||
return Model.newFail("executor is not a PtrAgvItem id=" + agvId); |
|||
} |
|||
|
|||
return Model.newSuccess(executorItem); |
|||
} |
|||
|
|||
public static Model<Object> agvCarry(@RequestBody Map<String, Object> params) { |
|||
String projectUUID = Conv.asString(params.get("projectUUID")); |
|||
String catalogCode = Conv.asString(params.get("catalogCode")); |
|||
Long envId = Conv.asLong(params.get("envId")); |
|||
String agvId = Conv.asString(params.get("agvId")); |
|||
String fromStoreLoc = Conv.asString(params.get("fromStoreLoc")); |
|||
String targetStoreLoc = Conv.asString(params.get("targetStoreLoc")); |
|||
Map<String, Object> option = (Map<String, Object>) params.get("option"); |
|||
|
|||
if (Strings.isNullOrEmpty(agvId)) { |
|||
return Model.newFail("agvId Must not be empty"); |
|||
} |
|||
if (Strings.isNullOrEmpty(fromStoreLoc)) { |
|||
return Model.newFail("fromStoreLoc Must not be empty"); |
|||
} |
|||
if (Strings.isNullOrEmpty(targetStoreLoc)) { |
|||
return Model.newFail("targetStoreLoc Must not be empty"); |
|||
} |
|||
|
|||
RCS.loadFloor(projectUUID, catalogCode, envId); |
|||
|
|||
LogisticsRuntime logisticsRuntime = LogisticsRuntimeService.INSTANCE.findByProjectFloor(projectUUID, catalogCode); |
|||
StaticItem sourceItem = logisticsRuntime.getStaticItemById(fromStoreLoc); |
|||
if (sourceItem == null) { |
|||
return Model.newFail("fromStoreLoc storePoint not found!"); |
|||
} |
|||
StaticItem targetItem = logisticsRuntime.getStaticItemById(targetStoreLoc); |
|||
if (targetItem == null) { |
|||
return Model.newFail("targetStoreLoc storePoint not found!"); |
|||
} |
|||
|
|||
ExecutorItem executorItem = logisticsRuntime.executorItemMap.get(agvId); |
|||
if (executorItem == null) { |
|||
return Model.newFail("executor not found: " + agvId); |
|||
} |
|||
if (!(executorItem instanceof PtrAgvItem)) { |
|||
return Model.newFail("executor is not a PtrAgvItem id=" + agvId); |
|||
} |
|||
|
|||
// 获取机器人当前所在位置, 也可以前端强制指定
|
|||
// forceStartWayPointId: '6_2', forceStartDirectior: 'right'
|
|||
StaticItem fromItem = null; |
|||
LCCDirection fromDirection = null; |
|||
if (option.get("forceStartWayPointId") != null) { |
|||
fromItem = logisticsRuntime.getStaticItemById(Conv.asString(option.get("forceStartWayPointId"))); |
|||
} else { |
|||
fromItem = logisticsRuntime.getStaticItemByLogicXY(((PtrAgvItem) executorItem).logicX, ((PtrAgvItem) executorItem).logicY); |
|||
} |
|||
if (option.get("forceStartDirection") != null) { |
|||
fromDirection = LCCDirection.fromString(Conv.asString(option.get("forceStartDirection"))); |
|||
} else { |
|||
fromDirection = ((PtrAgvItem) executorItem).getLCCDirection(); |
|||
} |
|||
|
|||
if (fromItem == null) { |
|||
return Model.newFail("PtrAgvItem not found at current location: " + ((PtrAgvItem) executorItem).logicX + "_" + ((PtrAgvItem) executorItem).logicY + ", id=" + agvId); |
|||
} |
|||
if (fromDirection == null) { |
|||
return Model.newFail("PtrAgvItem unkown direction id=" + agvId); |
|||
} |
|||
|
|||
RcsTaskBiz bizTask = new RcsTaskBiz(); |
|||
bizTask.setBizTaskId(snowFlake.nextId()); |
|||
bizTask.setEnvId(1L); |
|||
bizTask.setBizType(BizTaskType.MOVE.toString()); |
|||
bizTask.setLpn("N/A"); |
|||
bizTask.setPriority(Conv.asInteger(option.get("priority"), 1)); |
|||
bizTask.setTaskFrom(sourceItem.getId()); |
|||
bizTask.setTaskTo(targetItem.getId()); |
|||
bizTask.setAllocatedExecutorId(agvId); |
|||
bizTask.setBizTaskPayload("N/A"); |
|||
bizTask.setBizTaskErrorInfo("N/A"); |
|||
bizTask.setBizTaskDescription("N/A"); |
|||
bizTask.setBizTaskStatus(BizTaskStatus.WAITING_FOR_DISPATCH.toString()); |
|||
|
|||
PlanTaskSequence planSequence = new PlanTaskSequence(agvId, logisticsRuntime, bizTask, "demo"); |
|||
|
|||
CarryTask carryTask = new CarryTask( |
|||
agvId, "dummy", 1, |
|||
new StoreLocation("rack1", 0, 1, 0), |
|||
new StoreLocation("54", 0, 0, 0) |
|||
); |
|||
|
|||
logisticsRuntime.pathPlannerMap.get(executorItem.getT()) |
|||
.planCarryTask(planSequence, fromItem.getId(), fromDirection, carryTask); |
|||
return Model.newSuccess(planSequence.toPrettyMap()); |
|||
} |
|||
|
|||
public static Model<Boolean> agvToCharger(@RequestBody Map<String, Object> params) { |
|||
throw new NotImplementedException("agvToCharger not implemented yet"); |
|||
} |
|||
} |
|||
Loading…
Reference in new issue