diff --git a/opentcs-commadapter-loopback/src/main/java/org/opentcs/virtualvehicle/LoopbackCommunicationAdapter.java b/opentcs-commadapter-loopback/src/main/java/org/opentcs/virtualvehicle/LoopbackCommunicationAdapter.java index 972b51a..4588c56 100644 --- a/opentcs-commadapter-loopback/src/main/java/org/opentcs/virtualvehicle/LoopbackCommunicationAdapter.java +++ b/opentcs-commadapter-loopback/src/main/java/org/opentcs/virtualvehicle/LoopbackCommunicationAdapter.java @@ -5,10 +5,13 @@ import static java.util.Objects.requireNonNull; import com.google.inject.assistedinject.Assisted; import jakarta.inject.Inject; import java.beans.PropertyChangeEvent; +import java.util.ArrayList; import java.util.Arrays; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Objects; +import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -17,8 +20,15 @@ import org.opentcs.common.LoopbackAdapterConstants; import org.opentcs.communication.http.enums.Actions; import org.opentcs.communication.http.service.ExecuteAction; import org.opentcs.communication.http.service.ExecuteMove; +import org.opentcs.communication.http.service.ExecuteOperation; +import org.opentcs.components.kernel.services.TCSObjectService; +import org.opentcs.components.kernel.services.VehicleService; import org.opentcs.customizations.kernel.KernelExecutor; +import org.opentcs.data.TCSObjectReference; +import org.opentcs.data.model.Path; +import org.opentcs.data.model.Point; import org.opentcs.data.model.Pose; +import org.opentcs.data.model.TCSResourceReference; import org.opentcs.data.model.Triple; import org.opentcs.data.model.Vehicle; import org.opentcs.data.order.Route.Step; @@ -33,7 +43,6 @@ import org.opentcs.drivers.vehicle.management.VehicleProcessModelTO; import org.opentcs.manage.entity.AgvActionStatus; import org.opentcs.manage.entity.AgvInfo; import org.opentcs.manage.entity.AgvInfoParams; -import org.opentcs.manage.entity.AgvStatus; import org.opentcs.util.ExplainedBoolean; import org.opentcs.virtualvehicle.VelocityController.WayEntry; import org.slf4j.Logger; @@ -108,9 +117,27 @@ public class LoopbackCommunicationAdapter */ private static String CURRENT_POS; /** - * 订单任务key + * 订单任务key:记录当前订单执行的任务key */ - private int TASK_KEY = 1; +// private int TASK_KEY; + /** + * 记录最后经过点 + * 防止意外重启后,AGV控制器上报最终经过点为0无法执行任务 + */ + private String LAST_PASSED_POINT; + /** + * 记录车辆最后的姿态 + * 防止车辆重启后,AGV控制器上报最终经过点为0无法进行交管 + */ + private Pose LAST_POSE; + /** + * 车辆服务对象 + */ + private final VehicleService vehicleService; + /** + * + */ + private final TCSObjectService objectService; /** * Creates a new instance. @@ -125,7 +152,9 @@ public class LoopbackCommunicationAdapter @Assisted Vehicle vehicle, @KernelExecutor - ScheduledExecutorService kernelExecutor + ScheduledExecutorService kernelExecutor, + TCSObjectService objectService, // 注入对象服务 + VehicleService vehicleService ) { super( new LoopbackVehicleModel(vehicle), @@ -135,6 +164,8 @@ public class LoopbackCommunicationAdapter ); this.vehicle = requireNonNull(vehicle, "vehicle"); this.configuration = requireNonNull(configuration, "configuration"); + this.objectService = requireNonNull(objectService, "objectService"); + this.vehicleService = requireNonNull(vehicleService, "vehicleService"); } @Override @@ -228,6 +259,15 @@ public class LoopbackCommunicationAdapter } LOG.info("Loopback comm adapter is being disable: {}", getName()); super.disable(); + + //关闭连接后,更新车辆等级为不处理订单,但占用资源。 + getProcessModel().integrationLevelChangeRequested(Vehicle.IntegrationLevel.TO_BE_RESPECTED); + if (LAST_PASSED_POINT != null) { + getProcessModel().setPosition(LAST_PASSED_POINT); + } + if (LAST_POSE != null) { + getProcessModel().setPose(LAST_POSE); + } } @Override @@ -257,8 +297,8 @@ public class LoopbackCommunicationAdapter ORDER_NAME = cmd.getTransportOrder().getName(); //下发起点 CURRENT_POS = sourcePoint; - //当前执行taskKey - TASK_KEY = 1; +// //当前执行taskKey +// TASK_KEY = 1; // The command is added to the sent queue after this method returns. Therefore // we have to explicitly start the simulation like this. @@ -293,6 +333,7 @@ public class LoopbackCommunicationAdapter @Override public synchronized void initVehiclePosition(String newPos) { + LAST_PASSED_POINT = newPos; ((ExecutorService) getExecutor()).submit(() -> getProcessModel().setPosition(newPos)); } @@ -398,11 +439,33 @@ public class LoopbackCommunicationAdapter getProcessModel().setState(Vehicle.State.EXECUTING); Step step = command.getStep(); + Vehicle newVehicle = vehicleService.fetchObject(Vehicle.class, getProcessModel().getName()); + List>> allocatedResources = newVehicle.getAllocatedResources(); + + //使用副本更新车辆模型,防止异常情况 + List>> copiedResources = new ArrayList<>(allocatedResources); + copiedResources.clear(); + + if (step.getSourcePoint() != null) { + //下发起点不为空 + Point point = objectService.fetchObject(Point.class, step.getSourcePoint().getName()); + Set> resource = new HashSet<>(); + resource.add(point.getReference()); + copiedResources.add(resource); + } + if (step.getPath() != null) { + Path path = objectService.fetchObject(Path.class, step.getPath().getName()); + Set> resource = new HashSet<>(); + resource.add(path.getReference()); + copiedResources.add(resource); + } + newVehicle.withAllocatedResources(copiedResources); + if (step.getPath() == null) { actionExec(command); } else { - ExecuteMove.setExecTaskKey(getProcessModel().getName(), TASK_KEY); - TASK_KEY++; +// ExecuteOperation.setExecTaskKey(getProcessModel().getName(), TASK_KEY); +// TASK_KEY++; //todo 移动 movementExec(command); } @@ -432,9 +495,6 @@ public class LoopbackCommunicationAdapter //下发动作 ExecuteAction.sendCmd(getProcessModel().getName(), command.getOperation(), getSerialNum()); - // 结束动作 - finishCmd(command); - //进入阻塞 while (ACTION_STATUS) { try { @@ -444,6 +504,8 @@ public class LoopbackCommunicationAdapter } } + // 结束动作 + finishCmd(command); //继续执行动作 nextCmd(); } @@ -778,13 +840,19 @@ public class LoopbackCommunicationAdapter //更新车辆姿态 if (params.getPoint() != 0) { + LAST_PASSED_POINT = params.getPoint().toString(); //记录最终经过点 if (!Objects.equals(getProcessModel().getPosition(), params.getPoint().toString())) { getProcessModel().setPosition(params.getPoint().toString()); //更新最终经过点 } - getProcessModel().setPose(new Pose(new Triple(Math.round(params.getX() * 1000), Math.round(params.getY() * 1000), 0), params.getAngle())); + + LAST_POSE = new Pose(new Triple(Math.round(params.getX() * 1000), Math.round(params.getY() * 1000), 0), params.getAngle()); + getProcessModel().setPose(LAST_POSE); } else { - //最后经过点为0,应该是车辆重启过。车辆关机时应该正常对点位进行交管,防止车辆碰撞。 - //todo 可能需要实现原点自动定位,暂时不做处理 + //最后经过点为0,应该是车辆丢失定位或重启过。todo 可能需要自动找点 + } + + if (ACTION_STATUS) { + vehicleState = Vehicle.State.EXECUTING; } //更新电量 diff --git a/opentcs-common/src/main/java/org/opentcs/common/LoopbackAdapterConstants.java b/opentcs-common/src/main/java/org/opentcs/common/LoopbackAdapterConstants.java index 1299acb..4a1cc3c 100644 --- a/opentcs-common/src/main/java/org/opentcs/common/LoopbackAdapterConstants.java +++ b/opentcs-common/src/main/java/org/opentcs/common/LoopbackAdapterConstants.java @@ -53,5 +53,8 @@ public interface LoopbackAdapterConstants { * AGV 端口 */ String AGV_PORT = "AGV:PORT"; - + /** + * 对应路线车辆行驶姿态:0=正走,1=到走 + */ + String AGV_DRIVE_POSE = "PATH:DRIVE_POSE"; } diff --git a/opentcs-common/src/main/java/org/opentcs/communication/http/HttpClient.java b/opentcs-common/src/main/java/org/opentcs/communication/http/HttpClient.java index ba57f3e..0b7faf4 100644 --- a/opentcs-common/src/main/java/org/opentcs/communication/http/HttpClient.java +++ b/opentcs-common/src/main/java/org/opentcs/communication/http/HttpClient.java @@ -12,6 +12,7 @@ import org.opentcs.communication.http.dto.BaseRequestTo; import org.opentcs.communication.http.dto.kc.move.Path; import org.opentcs.communication.http.dto.kc.move.Point; import org.opentcs.communication.http.dto.kc.move.RequestAe; +import org.opentcs.communication.http.service.ExecuteOperation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -55,7 +56,23 @@ public class HttpClient { */ public static void main(String[] args) { - HttpClient httpClient = new HttpClient(); + + ExecuteOperation executeOperation = new ExecuteOperation(); + + { //暂停订单 + ExecuteOperation.pauseOrder("v1", 1); + } + + { //继续执行订单 + ExecuteOperation.continueOrder("v1", 1); + } + + { //撤销订单 + ExecuteOperation.cancelOrder("v1"); + } + + +// HttpClient httpClient = new HttpClient(); // { //0x02 // //变量成员 @@ -171,49 +188,49 @@ public class HttpClient { // httpClient.sendCommand(baseRequestTo); // } - { //0xAE - RequestAe ae = new RequestAe(); - ae.setWms_order_id(1); - ae.setOrder_id(1); - ae.setTask_key(1); - ae.setPoint_size(2); - ae.setPath_size(1); - - ArrayList pointList = new ArrayList<>(); - for (int i = 0; i < ae.getPoint_size(); i++) { - Point point = new Point(); - - if (i == 0) { - point.setPoint_id(1); - point.setPoint_serial(0); - } else { - point.setPoint_id(2); - point.setPoint_serial(2); - } - point.setPoint_angle(0); - - pointList.add(point); - } - ae.setPoint_info(pointList); - - ArrayList pathList = new ArrayList<>(); - for (int i = 0; i < ae.getPath_size(); i++) { - Path path = new Path(); - - path.setPath_id(12); - path.setPath_serial(1); - path.setPath_angle(0); - path.setDriver_pose(1); - path.setMax_speed(1); - path.setMax_angle_speed(1); - - pathList.add(path); - } - ae.setPath_info(pathList); - - BaseRequestTo baseRequestTo = new BaseRequestTo(2, "OPENTCS", "KC-CTRL", 1, "2025-6-6 10:00:00", ae); - - httpClient.sendCommand("http://192.168.124.121:2005", baseRequestTo); - } +// { //0xAE +// RequestAe ae = new RequestAe(); +// ae.setWms_order_id(1); +// ae.setOrder_id(1); +// ae.setTask_key(1); +// ae.setPoint_size(2); +// ae.setPath_size(1); +// +// ArrayList pointList = new ArrayList<>(); +// for (int i = 0; i < ae.getPoint_size(); i++) { +// Point point = new Point(); +// +// if (i == 0) { +// point.setPoint_id(1); +// point.setPoint_serial(0); +// } else { +// point.setPoint_id(2); +// point.setPoint_serial(2); +// } +// point.setPoint_angle(0); +// +// pointList.add(point); +// } +// ae.setPoint_info(pointList); +// +// ArrayList pathList = new ArrayList<>(); +// for (int i = 0; i < ae.getPath_size(); i++) { +// Path path = new Path(); +// +// path.setPath_id(12); +// path.setPath_serial(1); +// path.setPath_angle(0); +// path.setDriver_pose(1); +// path.setMax_speed(1); +// path.setMax_angle_speed(1); +// +// pathList.add(path); +// } +// ae.setPath_info(pathList); +// +// BaseRequestTo baseRequestTo = new BaseRequestTo(2, "OPENTCS", "KC-CTRL", 1, "2025-6-6 10:00:00", ae); +// +// httpClient.sendCommand("http://192.168.124.121:2005", baseRequestTo); +// } } } diff --git a/opentcs-common/src/main/java/org/opentcs/communication/http/service/BaseService.java b/opentcs-common/src/main/java/org/opentcs/communication/http/service/BaseService.java index d6cf91b..d60e3bf 100644 --- a/opentcs-common/src/main/java/org/opentcs/communication/http/service/BaseService.java +++ b/opentcs-common/src/main/java/org/opentcs/communication/http/service/BaseService.java @@ -1,12 +1,34 @@ package org.opentcs.communication.http.service; +import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.atomic.AtomicInteger; import org.opentcs.communication.http.enums.VehicleEnums; public class BaseService { + // 随机初始化起点,减少重复概率 + private static final AtomicInteger counter = new AtomicInteger( + ThreadLocalRandom.current().nextInt(1, Integer.MAX_VALUE / 2) + ); + public static String getUrl(String vehicleName) { VehicleEnums vehicleEnums = VehicleEnums.valueOf(vehicleName); return "http://" + vehicleEnums.getIp() + ":" + vehicleEnums.getPort(); } + /** + * 生成进程内唯一的int型ID + * 优点:简单高效 + * 限制: + * - 重启后可能重复 + * - 超过21亿后会回绕(正常应用很难达到) + */ + public static int generate() { + int id = counter.getAndIncrement(); + // 处理溢出(当接近int上限时重置为随机值) + return (id < 0) ? counter.getAndSet( + ThreadLocalRandom.current().nextInt(1, Integer.MAX_VALUE / 2) + ) : id; + } + } diff --git a/opentcs-common/src/main/java/org/opentcs/communication/http/service/ExecuteMove.java b/opentcs-common/src/main/java/org/opentcs/communication/http/service/ExecuteMove.java index 940432c..004dbad 100644 --- a/opentcs-common/src/main/java/org/opentcs/communication/http/service/ExecuteMove.java +++ b/opentcs-common/src/main/java/org/opentcs/communication/http/service/ExecuteMove.java @@ -5,6 +5,7 @@ import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.HashMap; import java.util.Objects; +import org.opentcs.common.LoopbackAdapterConstants; import org.opentcs.communication.http.HttpClient; import org.opentcs.communication.http.dto.BaseRequestTo; import org.opentcs.communication.http.dto.kc.move.Path; @@ -12,17 +13,19 @@ import org.opentcs.communication.http.dto.kc.move.Point; import org.opentcs.communication.http.dto.kc.move.RequestAe; import org.opentcs.communication.http.entity.OrderInfo; import org.opentcs.drivers.vehicle.MovementCommand; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class ExecuteMove extends BaseService { + /** + * LOG + */ + private static final Logger LOG = LoggerFactory.getLogger(ExecuteMove.class); /** * 订单名映射int类型数据. */ private static final HashMap orderInfoMap = new HashMap<>(); - /** - * 通讯适配器当前执行taskkey - */ - private static HashMap execTaskKeyMap = new HashMap<>(); /** * 发送移动指令 @@ -79,6 +82,8 @@ public class ExecuteMove extends BaseService { } maxVelocity = 5; + Integer drivePose = getDrivePose(pathInfo); //行驶姿态 + RequestAe ae = new RequestAe(); ae.setWms_order_id(1); //todo 测试填写 ae.setOrder_id(orderID); @@ -112,7 +117,7 @@ public class ExecuteMove extends BaseService { path.setPath_id(pathID); path.setPath_serial(orderInfo.getPathSerialNum()); path.setPath_angle(0); - path.setDriver_pose(0); + path.setDriver_pose(drivePose); path.setMax_speed(maxVelocity); path.setMax_angle_speed(maxVelocity); @@ -138,13 +143,8 @@ public class ExecuteMove extends BaseService { //当前车辆已存在集合中 OrderInfo orderInfo = orderInfoMap.get(vehicleName); - if (!Objects.equals(orderName, orderInfo.getName())) { - //订单名称不相等为执行下一个订单,初始化订单对应参数 - orderInfoMap.remove(vehicleName); - - Integer currentOrderId = orderInfo.getId() + 1; - - orderInfo.setId(currentOrderId); + if (!Objects.equals(orderName, orderInfo.getName()) && orderInfoMap.containsKey(vehicleName)) { + orderInfo.setId(generate()); orderInfo.setName(orderName); orderInfo.setState(1); orderInfo.setTaskKey(1); @@ -154,7 +154,7 @@ public class ExecuteMove extends BaseService { } else { //车辆不在集合中 OrderInfo orderInfo = new OrderInfo(); - orderInfo.setId(1); //todo 测试修改,正式上线应该为1 + orderInfo.setId(generate()); orderInfo.setName(orderName); orderInfo.setState(1); orderInfo.setTaskKey(1); @@ -165,28 +165,33 @@ public class ExecuteMove extends BaseService { } } - /** - * 设置当前执行任务key - */ - public static void setExecTaskKey(String vehicleName, Integer taskKey) { - if (execTaskKeyMap.containsKey(vehicleName)) { - execTaskKeyMap.put(vehicleName, taskKey); - } else { - execTaskKeyMap.put(vehicleName, 1); - } - } - - /** - * 获取任务key - */ - public static Integer getTaskKey(String vehicleName) { - return execTaskKeyMap.get(vehicleName); - } - /** * 获取当前订单ID */ public static Integer getOrderID(String vehicleName) { return orderInfoMap.get(vehicleName).getId(); } + + /** + * 返回行驶姿态 + */ + private static Integer getDrivePose(org.opentcs.data.model.Path path) { + String drivePost = path.getProperties().get(LoopbackAdapterConstants.AGV_DRIVE_POSE); + System.out.println("getDrivePose drivePost: " + drivePost); + + int pose = 0; + if (drivePost == null) { + return pose; + } + + switch (drivePost) { + case "1" -> pose = 1; + default -> { + LOG.error("getDrivePose UNKNOWN DRIVE POSE: {}", drivePost); + throw new IllegalArgumentException("UNKNOWN DRIVE POSE: " + drivePost); + } + } + + return pose; + } } diff --git a/opentcs-common/src/main/java/org/opentcs/communication/http/service/ExecuteOperation.java b/opentcs-common/src/main/java/org/opentcs/communication/http/service/ExecuteOperation.java index 6edc5eb..02909e3 100644 --- a/opentcs-common/src/main/java/org/opentcs/communication/http/service/ExecuteOperation.java +++ b/opentcs-common/src/main/java/org/opentcs/communication/http/service/ExecuteOperation.java @@ -2,6 +2,7 @@ package org.opentcs.communication.http.service; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; +import java.util.HashMap; import org.opentcs.communication.http.HttpClient; import org.opentcs.communication.http.dto.BaseRequestTo; import org.opentcs.communication.http.dto.kc.operation.Action01; @@ -18,6 +19,14 @@ public class ExecuteOperation extends BaseService{ * This class's Logger. */ private static final Logger LOG = LoggerFactory.getLogger(ExecuteOperation.class); + /** + * 通讯适配器当前执行taskkey + */ + private static HashMap execTaskKeyMap = new HashMap<>(); + /** + * 序列号 + */ + private static Integer serialNum = 0; /** * 暂停执行订单 @@ -32,7 +41,7 @@ public class ExecuteOperation extends BaseService{ b2.setParam_size(4); Action01 action01 = new Action01(); - action01.setIsStopImmediately(1); + action01.setIsStopImmediately(0); b2.setParam_data(action01); @@ -49,7 +58,7 @@ public class ExecuteOperation extends BaseService{ Integer orderId = ExecuteMove.getOrderID(vehicleName); //获取任务key - Integer taskKey = ExecuteMove.getTaskKey(vehicleName); + Integer taskKey = getTaskKey(vehicleName); RequestB2 b2 = new RequestB2(); @@ -69,9 +78,8 @@ public class ExecuteOperation extends BaseService{ /** * 撤销订单 * @param vehicleName 车辆名称 - * @param serialNum 序列号 */ - public static void cancelOrder(String vehicleName, Integer serialNum) { + public static void cancelOrder(String vehicleName) { //获取订单ID Integer orderId = ExecuteMove.getOrderID(vehicleName); @@ -84,11 +92,11 @@ public class ExecuteOperation extends BaseService{ Action03 action03 = new Action03(); action03.setOrderId(orderId); - action03.setIsStopImmediately(1); + action03.setIsStopImmediately(0); b2.setParam_data(action03); - sendCmd(vehicleName, b2, serialNum); + sendCmd(vehicleName, b2, getSerialNum()); } public static void sendCmd(String vehicleName, Object data, Integer serialNum) @@ -107,4 +115,26 @@ public class ExecuteOperation extends BaseService{ httpClient.sendCommand(url, baseRequestTo); } + /** + * 设置当前执行任务key + */ + public static void setExecTaskKey(String vehicleName, Integer taskKey) { + if (execTaskKeyMap.containsKey(vehicleName)) { + execTaskKeyMap.put(vehicleName, taskKey); + } else { + execTaskKeyMap.put(vehicleName, 1); + } + } + + /** + * 获取任务key + */ + public static Integer getTaskKey(String vehicleName) { + return execTaskKeyMap.get(vehicleName); + } + + private static int getSerialNum() { + return serialNum++; + } + } diff --git a/opentcs-common/src/main/java/org/opentcs/communication/mqtt/service/ExecuteAction.java b/opentcs-common/src/main/java/org/opentcs/communication/mqtt/service/ExecuteAction.java deleted file mode 100644 index b6c24c4..0000000 --- a/opentcs-common/src/main/java/org/opentcs/communication/mqtt/service/ExecuteAction.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.opentcs.communication.mqtt.service; - -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; -import org.opentcs.communication.mqtt.entity.BaseRequestTo; -import org.opentcs.communication.mqtt.entity.kc.action.RequestAction; - -public class ExecuteAction { - - /** - * 下发动作到平台 - * @param action 动作 - */ - public static void sendCmd(String action, Integer serialNum) { - - // 获取当前时间 - LocalDateTime now = LocalDateTime.now(); - DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); - String time = now.format(formatter); - - RequestAction requestAction = new RequestAction(); - requestAction.setAction(action); - - BaseRequestTo baseRequestTo = new BaseRequestTo( - 4, - "OPENTCS", - "KC-CTRL", - serialNum, - time, - requestAction - ); - - //发送mqtt消息 - } - -} diff --git a/opentcs-common/src/main/java/org/opentcs/communication/mqtt/service/ExecuteMove.java b/opentcs-common/src/main/java/org/opentcs/communication/mqtt/service/ExecuteMove.java deleted file mode 100644 index 239005c..0000000 --- a/opentcs-common/src/main/java/org/opentcs/communication/mqtt/service/ExecuteMove.java +++ /dev/null @@ -1,168 +0,0 @@ -package org.opentcs.communication.mqtt.service; - -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; -import java.util.ArrayList; -import java.util.HashMap; -import org.opentcs.communication.mqtt.entity.BaseRequestTo; -import org.opentcs.communication.mqtt.entity.kc.move.Path; -import org.opentcs.communication.mqtt.entity.kc.move.Point; -import org.opentcs.communication.mqtt.entity.kc.move.RequestAe; -import org.opentcs.drivers.vehicle.MovementCommand; - -public class ExecuteMove { - - /** - * 订单名映射int类型数据. - */ - private static final HashMap orderNameMap = new HashMap<>(); - /** - * 记录上次下发订单名称 - */ - private static String oldOrderName; - /** - * 当前订单名称对应唯一整数ID - */ - private static Integer currentOrderId = 0; - /** - * 任务ID - * 任务的唯一标识。与订单ID绑定,从1开始,当同一订单下发新的资源时加1;订单ID发生改变,任务KEY需要重新计数。 - */ - private static Integer taskKey; - /** - * 序列号 - * 用于定位点在整个任务中的位置。目的是区分同一个点ID是否在一个任务中出现多次。从0开始偶数递增,例如:0->2->4->6…… - */ - private static Integer pointSerialNum = 0; - /** - * 用于定位段在整个任务中的位置。目的是区分同一个段ID是否在一个任务中出现多次。从1开始奇数递增,例如:1->3->5->7…… - */ - private static Integer pathSerialNum = 1; - - public static void sendCmd(MovementCommand cmd, Integer serialNum) - { - // 获取当前时间 - LocalDateTime now = LocalDateTime.now(); - DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); - String time = now.format(formatter); - - RequestAe ae = buildCommand(cmd); - BaseRequestTo baseRequestTo = new BaseRequestTo(2, "OPENTCS", "KC-CTRL", serialNum, time, ae); - -// HttpClient httpClient = new HttpClient(); -// httpClient.sendCommand(baseRequestTo); - } - - private static RequestAe buildCommand(MovementCommand cmd) - { - //订单ID - int orderID = getUniqueOrderID(cmd.getTransportOrder().getName()); - //下发起点 - String sourcePoint = cmd.getStep().getSourcePoint().getName(); - int newSourcePoint = Integer.parseInt(sourcePoint); - //下发终点 - String destinationPoint = cmd.getStep().getDestinationPoint().getName(); - int newDestination = Integer.parseInt(destinationPoint); - - //获取路径ID - int pathID; - if (newSourcePoint < newDestination) { - pathID = Integer.parseInt(sourcePoint + destinationPoint); - } else { - pathID = Integer.parseInt(destinationPoint + sourcePoint); - } - - org.opentcs.data.model.Path pathInfo = cmd.getStep().getPath(); - int maxVelocity = 1; //获取最大速度 - int maxReverseVelocity = 1; //获取最大反向速度 - if (pathInfo != null) { - maxVelocity = pathInfo.getMaxVelocity(); //获取设置速度 - maxReverseVelocity = pathInfo.getMaxReverseVelocity(); - } - - RequestAe ae = new RequestAe(); - ae.setOrderId(orderID); - ae.setTaskKey(taskKey); - ae.setPointSize(2); - ae.setPathSize(1); - - ArrayList pointList = new ArrayList<>(); - for (int i = 0; i < ae.getPointSize(); i++) { - Point point = new Point(); - - if (i == 0) { - point.setPoint_id(newSourcePoint); - } else { - point.setPoint_id(newDestination); - } - point.setPoint_serial(pointSerialNum); - point.setPoint_angle(0); - - pointSerialNum = pointSerialNum + 2; - - pointList.add(point); - } - ae.setPoint(pointList); - - ArrayList pathList = new ArrayList<>(); - for (int i = 0; i < ae.getPathSize(); i++) { - Path path = new Path(); - - path.setPath_id(pathID); - path.setPath_serial(pathSerialNum); - path.setPath_angle(0); - path.setDrive_pose(1); - path.setMax_speed(maxVelocity); - path.setMax_angle_speed(maxVelocity); - - pathSerialNum = pathSerialNum + 2; - - pathList.add(path); - } - ae.setPath(pathList); - - return ae; - } - - /** - * 维护订单名对应int类型唯一ID--------todo 待优化:如果调度重启,控制器也需要重启。否则0xAE指令会因为重置订单ID和任务key下发失败。应改成wms数据库ID交互 - * @param orderName 订单名 - * @return Integer - */ - private static int getUniqueOrderID(String orderName){ - - Integer orderId; - - if (orderNameMap.containsKey(orderName)) { - //订单名已存在 - orderId = orderNameMap.get(orderName); - } else { //订单名不存在 - //初始化参数 - initParams(); - - if (oldOrderName != null) { - //删除上次订单映射唯一ID - orderNameMap.remove(oldOrderName); - } - - //更新记录订单名称 - oldOrderName = orderName; - - // 创建对应映射 - orderId = currentOrderId; - currentOrderId++; - orderNameMap.put(orderName, orderId); - } - - return orderId; - } - - /** - * 初始化参数 - */ - private static void initParams() { - taskKey = 1; - pointSerialNum = 0; - pathSerialNum = 1; - } -} diff --git a/opentcs-common/src/main/java/org/opentcs/communication/mqtt/service/ExecuteOperation.java b/opentcs-common/src/main/java/org/opentcs/communication/mqtt/service/ExecuteOperation.java deleted file mode 100644 index 32645a4..0000000 --- a/opentcs-common/src/main/java/org/opentcs/communication/mqtt/service/ExecuteOperation.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.opentcs.communication.mqtt.service; - -public class ExecuteOperation { - - - -} diff --git a/opentcs-common/src/main/java/org/opentcs/manage/AdapterManage.java b/opentcs-common/src/main/java/org/opentcs/manage/AdapterManage.java index ffb250f..9d62f7e 100644 --- a/opentcs-common/src/main/java/org/opentcs/manage/AdapterManage.java +++ b/opentcs-common/src/main/java/org/opentcs/manage/AdapterManage.java @@ -7,11 +7,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; -import org.opentcs.access.KernelServicePortal; -import org.opentcs.access.rmi.KernelServicePortalBuilder; import org.opentcs.common.GuestUserCredentials; -import org.opentcs.components.kernel.services.VehicleService; -import org.opentcs.data.model.Vehicle; import org.opentcs.manage.entity.AgvInfo; import org.opentcs.manage.entity.AgvInfoParams; import org.opentcs.manage.entity.AgvStatus; @@ -45,15 +41,6 @@ public class AdapterManage { * 设置自动关闭适配器时间阈值,单位:毫秒 */ private static final Long AUTO_CLOSE_TIME = 2000L; - /** - * 记录通讯适配器数据,实现异步不阻塞更新车辆模型 - * 基于线程安全HASHMAP - */ -// private static final ConcurrentHashMap adapterDataMap = new ConcurrentHashMap<>(); - /** - * 内核状态 - */ -// public static Boolean kernelStatus = false; //开启通讯信息 private static final String USER = GuestUserCredentials.USER; @@ -63,7 +50,7 @@ public class AdapterManage { //开启定时任务 public void START() { - scheduler.scheduleWithFixedDelay(task, 5000, 500, TimeUnit.MILLISECONDS); + scheduler.scheduleWithFixedDelay(task, 5000, 1000, TimeUnit.MILLISECONDS); } //关闭定时任务 @@ -87,9 +74,9 @@ public class AdapterManage { Date date = new Date(); long currentTime = date.getTime(); - System.out.println("autoManageAdapterStatus sout: " + adapterStatusMap); +// System.out.println("autoManageAdapterStatus sout: " + adapterStatusMap); adapterStatusMap.forEach((key, value) -> { - LOG.info("adapterStatusMap starts name: {}", key); +// LOG.info("adapterStatusMap starts name: {}", key); AgvStatus agvStatus = new AgvStatus(); agvStatus.setTime(value.getTime()); @@ -108,8 +95,7 @@ public class AdapterManage { //更新记录数据 adapterStatusMap.put(key, agvStatus); - - LOG.info("adapterStatusMap end name: {}", key); +// LOG.info("adapterStatusMap end name: {}", key); }); } @@ -151,7 +137,6 @@ public class AdapterManage { agvInfo.setTime(jsonObject.getString("time")); agvInfo.setParams(getAgvInfoParams(jsonObject.getString("params"))); -// adapterDataMap.put(name, agvInfo); return agvInfo; } @@ -181,44 +166,4 @@ public class AdapterManage { Boolean ENABLE = true; Boolean DISABLE = false; } - -// private void testSendMessage() { -// System.out.println("test"); -// AgvInfoParams agvInfoParams = new AgvInfoParams(); -// agvInfoParams.setX(0.5f); -// agvInfoParams.setY(0.5f); -// agvInfoParams.setAngle(0.5f); -// agvInfoParams.setPoint(12); -// agvInfoParams.setPower(0.52f); -// agvInfoParams.setAgv_status(0); -// agvInfoParams.setCargo_status(0); -// agvInfoParams.setAgv_model(0); -// agvInfoParams.setCharge_status(0); -// agvInfoParams.setAction_status(1); -// -// AgvInfo agvInfo = new AgvInfo(); -// agvInfo.setReceiver("OPENTCS"); -// agvInfo.setSender("KC-CTRL"); -// agvInfo.setSerial_num(1); -// agvInfo.setType(1); -// agvInfo.setTime("2020-07-07 09:09:09"); -// agvInfo.setVehicle_name("v2"); -// agvInfo.setParams(agvInfoParams); -// -// System.out.println("testSendMessage agvInfo: " + agvInfo); -// -// KernelServicePortal servicePortal = new KernelServicePortalBuilder(USER, PASSWORD).build(); -// servicePortal.login(IP, PORT); -// VehicleService vehicleService = servicePortal.getVehicleService(); -// Vehicle vehicle = vehicleService.fetchObject(Vehicle.class, "v2"); -// -// if (vehicle != null) { -// System.out.println("send success"); -// vehicleService.sendCommAdapterMessage(vehicle.getReference(), agvInfo); -// } else { -// System.out.println("send not fund"); -// } -// -//// kernel.sendToAdapter("v2", agvInfo); -// } } diff --git a/opentcs-common/src/main/java/org/opentcs/traffic/common/ContourAlgorithm.java b/opentcs-common/src/main/java/org/opentcs/traffic/common/ContourAlgorithm.java index 4940a13..e81077b 100644 --- a/opentcs-common/src/main/java/org/opentcs/traffic/common/ContourAlgorithm.java +++ b/opentcs-common/src/main/java/org/opentcs/traffic/common/ContourAlgorithm.java @@ -1,7 +1,8 @@ package org.opentcs.traffic.common; -import java.util.HashMap; -import org.opentcs.traffic.entity.VehicleAttr; +import java.awt.geom.Point2D; +import org.locationtech.jts.geom.Coordinate; +import org.locationtech.jts.geom.GeometryFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -30,9 +31,19 @@ public class ContourAlgorithm { * * @return true,可通过,false,不通过 */ - public boolean interferenceDetection() { + public boolean interferenceDetection(Point2D.Double center) { + +// center.setLocation(0.0, 0.0); + + GeometryFactory geometryFactory = new GeometryFactory(); + Coordinate[] coords = { + + }; + + +// new BezierCurve() + - // return true; } diff --git a/opentcs-kernel-extension-http-services/src/main/java/org/opentcs/kernel/extensions/servicewebapi/v1/VehicleHandler.java b/opentcs-kernel-extension-http-services/src/main/java/org/opentcs/kernel/extensions/servicewebapi/v1/VehicleHandler.java index 37a5953..c36e908 100644 --- a/opentcs-kernel-extension-http-services/src/main/java/org/opentcs/kernel/extensions/servicewebapi/v1/VehicleHandler.java +++ b/opentcs-kernel-extension-http-services/src/main/java/org/opentcs/kernel/extensions/servicewebapi/v1/VehicleHandler.java @@ -15,9 +15,6 @@ import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; -import org.opentcs.access.KernelServicePortal; -import org.opentcs.access.rmi.KernelServicePortalBuilder; -import org.opentcs.common.GuestUserCredentials; import org.opentcs.components.kernel.services.RouterService; import org.opentcs.components.kernel.services.VehicleService; import org.opentcs.data.ObjectUnknownException; @@ -74,8 +71,12 @@ public class VehicleHandler { System.out.println("jsonObject-----ssss: " + data.toString()); //截取平台响应的字符串 - String jsonStr = data.toString().split("=", 2)[1]; -// String jsonStr = data.toString(); + String jsonStr; + try { + jsonStr = data.toString().split("=", 2)[1]; + } catch (Exception e) { + jsonStr = data.toString(); + } JSONObject jsonObject = JSON.parseObject(jsonStr); String name = jsonObject.getString("vehicle_name"); Integer type = jsonObject.getInteger("type"); diff --git a/opentcs-modeleditor/src/guiceConfig/java/org/opentcs/modeleditor/DefaultPropertySuggestions.java b/opentcs-modeleditor/src/guiceConfig/java/org/opentcs/modeleditor/DefaultPropertySuggestions.java index c74327b..387831f 100644 --- a/opentcs-modeleditor/src/guiceConfig/java/org/opentcs/modeleditor/DefaultPropertySuggestions.java +++ b/opentcs-modeleditor/src/guiceConfig/java/org/opentcs/modeleditor/DefaultPropertySuggestions.java @@ -42,6 +42,7 @@ public class DefaultPropertySuggestions keySuggestions.add(LoopbackAdapterConstants.AGV_AUTHORIZE_CODE); keySuggestions.add(LoopbackAdapterConstants.AGV_IP); keySuggestions.add(LoopbackAdapterConstants.AGV_PORT); + keySuggestions.add(LoopbackAdapterConstants.AGV_DRIVE_POSE); } @Override diff --git a/opentcs-strategies-default/src/main/java/org/opentcs/strategies/basic/dispatching/TransportOrderUtil.java b/opentcs-strategies-default/src/main/java/org/opentcs/strategies/basic/dispatching/TransportOrderUtil.java index dc07408..1e739bb 100644 --- a/opentcs-strategies-default/src/main/java/org/opentcs/strategies/basic/dispatching/TransportOrderUtil.java +++ b/opentcs-strategies-default/src/main/java/org/opentcs/strategies/basic/dispatching/TransportOrderUtil.java @@ -10,6 +10,7 @@ import jakarta.inject.Inject; import java.util.Collections; import java.util.List; import java.util.Optional; +import org.opentcs.communication.http.service.ExecuteOperation; import org.opentcs.components.Lifecycle; import org.opentcs.components.kernel.Router; import org.opentcs.components.kernel.services.InternalTransportOrderService; @@ -355,6 +356,9 @@ public class TransportOrderUtil // vehicle reports the remaining movements as finished. updateTransportOrderState(order.getReference(), TransportOrder.State.WITHDRAWN); + //撤销订单 + ExecuteOperation.cancelOrder(vehicle.getName()); + VehicleController vehicleController = vehicleControllerPool.getVehicleController(vehicle.getName());