update
This commit is contained in:
parent
503771fe7c
commit
2cc6f2906b
@ -30,6 +30,7 @@ import org.opentcs.drivers.vehicle.SimVehicleCommAdapter;
|
|||||||
import org.opentcs.drivers.vehicle.VehicleCommAdapter;
|
import org.opentcs.drivers.vehicle.VehicleCommAdapter;
|
||||||
import org.opentcs.drivers.vehicle.VehicleProcessModel;
|
import org.opentcs.drivers.vehicle.VehicleProcessModel;
|
||||||
import org.opentcs.drivers.vehicle.management.VehicleProcessModelTO;
|
import org.opentcs.drivers.vehicle.management.VehicleProcessModelTO;
|
||||||
|
import org.opentcs.manage.entity.ActionStatus;
|
||||||
import org.opentcs.manage.entity.AgvInfo;
|
import org.opentcs.manage.entity.AgvInfo;
|
||||||
import org.opentcs.manage.entity.AgvInfoParams;
|
import org.opentcs.manage.entity.AgvInfoParams;
|
||||||
import org.opentcs.manage.entity.AgvStatus;
|
import org.opentcs.manage.entity.AgvStatus;
|
||||||
@ -106,6 +107,10 @@ public class LoopbackCommunicationAdapter
|
|||||||
* 记录当前车辆位置
|
* 记录当前车辆位置
|
||||||
*/
|
*/
|
||||||
private static String CURRENT_POS;
|
private static String CURRENT_POS;
|
||||||
|
/**
|
||||||
|
* 订单任务key
|
||||||
|
*/
|
||||||
|
private int TASK_KEY = 1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance.
|
* Creates a new instance.
|
||||||
@ -212,6 +217,7 @@ public class LoopbackCommunicationAdapter
|
|||||||
if (isEnabled()) {
|
if (isEnabled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
LOG.info("Loopback comm adapter is being enabled: {}", getName());
|
||||||
super.enable();
|
super.enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,6 +226,7 @@ public class LoopbackCommunicationAdapter
|
|||||||
if (!isEnabled()) {
|
if (!isEnabled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
LOG.info("Loopback comm adapter is being disable: {}", getName());
|
||||||
super.disable();
|
super.disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,12 +239,13 @@ public class LoopbackCommunicationAdapter
|
|||||||
public synchronized void sendCommand(MovementCommand cmd) {
|
public synchronized void sendCommand(MovementCommand cmd) {
|
||||||
requireNonNull(cmd, "cmd");
|
requireNonNull(cmd, "cmd");
|
||||||
|
|
||||||
//下发起点
|
|
||||||
String sourcePoint = null;
|
String sourcePoint = null;
|
||||||
if (cmd.getStep().getSourcePoint() != null) {
|
if (cmd.getStep().getSourcePoint() != null) {
|
||||||
|
//下发起点不为空
|
||||||
sourcePoint = cmd.getStep().getSourcePoint().getName();
|
sourcePoint = cmd.getStep().getSourcePoint().getName();
|
||||||
|
|
||||||
//下发AGV移动指令
|
//下发AGV移动指令
|
||||||
ExecuteMove.sendCmd(cmd, getSerialNum());
|
ExecuteMove.sendCmd(getProcessModel().getName(), cmd, getSerialNum());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start the simulation task if we're not in single step mode and not simulating already.
|
// Start the simulation task if we're not in single step mode and not simulating already.
|
||||||
@ -249,6 +257,8 @@ public class LoopbackCommunicationAdapter
|
|||||||
ORDER_NAME = cmd.getTransportOrder().getName();
|
ORDER_NAME = cmd.getTransportOrder().getName();
|
||||||
//下发起点
|
//下发起点
|
||||||
CURRENT_POS = sourcePoint;
|
CURRENT_POS = sourcePoint;
|
||||||
|
//当前执行taskKey
|
||||||
|
TASK_KEY = 1;
|
||||||
|
|
||||||
// The command is added to the sent queue after this method returns. Therefore
|
// The command is added to the sent queue after this method returns. Therefore
|
||||||
// we have to explicitly start the simulation like this.
|
// we have to explicitly start the simulation like this.
|
||||||
@ -275,9 +285,9 @@ public class LoopbackCommunicationAdapter
|
|||||||
if (message instanceof AgvInfo agvInfo) {
|
if (message instanceof AgvInfo agvInfo) {
|
||||||
//通讯适配器车辆模型更新
|
//通讯适配器车辆模型更新
|
||||||
handleCallbacks(agvInfo.getParams());
|
handleCallbacks(agvInfo.getParams());
|
||||||
} else if (message instanceof AgvStatus agvStatus) {
|
} else if (message instanceof ActionStatus actionStatus) {
|
||||||
//自动管理通讯适配器状态和适配器动作执行状态
|
//自动管理通讯适配器状态和适配器动作执行状态
|
||||||
handleAdapterAuthEnable(agvStatus);
|
handleActionStatus(actionStatus);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -385,12 +395,14 @@ public class LoopbackCommunicationAdapter
|
|||||||
*/
|
*/
|
||||||
private void startVehicleExec(MovementCommand command) {
|
private void startVehicleExec(MovementCommand command) {
|
||||||
LOG.debug("VEHICLE: {} BEGINS TO EXECUTE THE COMMAND: {}", getProcessModel().getName(),command);
|
LOG.debug("VEHICLE: {} BEGINS TO EXECUTE THE COMMAND: {}", getProcessModel().getName(),command);
|
||||||
Step step = command.getStep();
|
|
||||||
getProcessModel().setState(Vehicle.State.EXECUTING);
|
getProcessModel().setState(Vehicle.State.EXECUTING);
|
||||||
|
Step step = command.getStep();
|
||||||
|
|
||||||
if (step.getPath() == null) {
|
if (step.getPath() == null) {
|
||||||
actionExec(command);
|
actionExec(command);
|
||||||
} else {
|
} else {
|
||||||
|
ExecuteMove.setExecTaskKey(getProcessModel().getName(), TASK_KEY);
|
||||||
|
TASK_KEY++;
|
||||||
//todo 移动
|
//todo 移动
|
||||||
movementExec(command);
|
movementExec(command);
|
||||||
}
|
}
|
||||||
@ -418,7 +430,7 @@ public class LoopbackCommunicationAdapter
|
|||||||
ACTION_STATUS = true;
|
ACTION_STATUS = true;
|
||||||
|
|
||||||
//下发动作
|
//下发动作
|
||||||
ExecuteAction.sendCmd(command.getOperation(), getSerialNum());
|
ExecuteAction.sendCmd(getProcessModel().getName(), command.getOperation(), getSerialNum());
|
||||||
|
|
||||||
// 结束动作
|
// 结束动作
|
||||||
finishCmd(command);
|
finishCmd(command);
|
||||||
@ -769,7 +781,7 @@ public class LoopbackCommunicationAdapter
|
|||||||
if (!Objects.equals(getProcessModel().getPosition(), params.getPoint().toString())) {
|
if (!Objects.equals(getProcessModel().getPosition(), params.getPoint().toString())) {
|
||||||
getProcessModel().setPosition(params.getPoint().toString()); //更新最终经过点
|
getProcessModel().setPosition(params.getPoint().toString()); //更新最终经过点
|
||||||
}
|
}
|
||||||
getProcessModel().setPose(new Pose(new Triple(Math.round(params.getX()), Math.round(params.getY()), 0), params.getAngle()));
|
getProcessModel().setPose(new Pose(new Triple(Math.round(params.getX() * 1000), Math.round(params.getY() * 1000), 0), params.getAngle()));
|
||||||
} else {
|
} else {
|
||||||
//最后经过点为0,应该是车辆重启过。车辆关机时应该正常对点位进行交管,防止车辆碰撞。
|
//最后经过点为0,应该是车辆重启过。车辆关机时应该正常对点位进行交管,防止车辆碰撞。
|
||||||
//todo 可能需要实现原点自动定位,暂时不做处理
|
//todo 可能需要实现原点自动定位,暂时不做处理
|
||||||
@ -793,15 +805,9 @@ public class LoopbackCommunicationAdapter
|
|||||||
return serialNum;
|
return serialNum;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleAdapterAuthEnable(AgvStatus agvStatus) {
|
private void handleActionStatus(ActionStatus actionStatus) {
|
||||||
if (agvStatus.getActionStatus()) {
|
if (actionStatus.getStatus()) {
|
||||||
ACTION_STATUS = false;
|
ACTION_STATUS = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (agvStatus.getStatus()) {
|
|
||||||
enable();
|
|
||||||
} else {
|
|
||||||
disable();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,8 @@ dependencies {
|
|||||||
implementation 'io.moquette:moquette-broker:0.15'
|
implementation 'io.moquette:moquette-broker:0.15'
|
||||||
// MQTT 客户端
|
// MQTT 客户端
|
||||||
implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.5'
|
implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.5'
|
||||||
|
//JTS
|
||||||
|
implementation 'org.locationtech.jts:jts-core:1.18.2'
|
||||||
}
|
}
|
||||||
|
|
||||||
processResources.doLast {
|
processResources.doLast {
|
||||||
|
@ -44,13 +44,13 @@ public class ChargeStrategy {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//如果 (电池为放电状态)
|
if (batteryStatus == 0) { //放电状态
|
||||||
if (batteryStatus == 0) {
|
//判断是否执行充电
|
||||||
|
|
||||||
} else { //释放充电中的车辆
|
} else { //充电状态
|
||||||
|
//判断是否释放车辆
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,16 @@ package org.opentcs.communication.http;
|
|||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import okhttp3.MediaType;
|
import okhttp3.MediaType;
|
||||||
import okhttp3.OkHttpClient;
|
import okhttp3.OkHttpClient;
|
||||||
import okhttp3.Request;
|
import okhttp3.Request;
|
||||||
import okhttp3.RequestBody;
|
import okhttp3.RequestBody;
|
||||||
import okhttp3.Response;
|
import okhttp3.Response;
|
||||||
|
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.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@ -21,7 +26,7 @@ public class HttpClient {
|
|||||||
|
|
||||||
private final OkHttpClient client;
|
private final OkHttpClient client;
|
||||||
|
|
||||||
private final String url = "http://192.168.124.121:2005";
|
// private final String url = "http://192.168.124.121:2005";
|
||||||
|
|
||||||
public HttpClient() {
|
public HttpClient() {
|
||||||
this.client = new OkHttpClient();
|
this.client = new OkHttpClient();
|
||||||
@ -31,7 +36,7 @@ public class HttpClient {
|
|||||||
* 发送 POST 请求
|
* 发送 POST 请求
|
||||||
* @return ApiResponse 对象
|
* @return ApiResponse 对象
|
||||||
*/
|
*/
|
||||||
public String sendCommand(Object data) {
|
public String sendCommand(String url, Object data) {
|
||||||
String jsonBody = JSON.toJSONString(data);
|
String jsonBody = JSON.toJSONString(data);
|
||||||
System.out.println("SENDING POST REQUEST data:" + jsonBody);
|
System.out.println("SENDING POST REQUEST data:" + jsonBody);
|
||||||
LOG.debug("SENDING POST REQUEST data: {}", jsonBody);
|
LOG.debug("SENDING POST REQUEST data: {}", jsonBody);
|
||||||
@ -166,67 +171,49 @@ public class HttpClient {
|
|||||||
// httpClient.sendCommand(baseRequestTo);
|
// httpClient.sendCommand(baseRequestTo);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// { //0xAE
|
{ //0xAE
|
||||||
// RequestAe ae = new RequestAe();
|
RequestAe ae = new RequestAe();
|
||||||
// ae.setOrderId(1);
|
ae.setWms_order_id(1);
|
||||||
// ae.setTaskKey(1);
|
ae.setOrder_id(1);
|
||||||
// ae.setPointSize(2);
|
ae.setTask_key(1);
|
||||||
// ae.setPathSize(1);
|
ae.setPoint_size(2);
|
||||||
//
|
ae.setPath_size(1);
|
||||||
// ArrayList<Point> pointList = new ArrayList<>();
|
|
||||||
// for (int i = 0; i < ae.getPointSize(); i++) {
|
ArrayList<Point> pointList = new ArrayList<>();
|
||||||
// Point point = new Point();
|
for (int i = 0; i < ae.getPoint_size(); i++) {
|
||||||
// if (i == 0) {
|
Point point = new Point();
|
||||||
// point.setPointId(1);
|
|
||||||
// point.setPointSerialNumber(0);
|
if (i == 0) {
|
||||||
// point.setType(0);
|
point.setPoint_id(1);
|
||||||
// point.setIsFrontAngle(0);
|
point.setPoint_serial(0);
|
||||||
// point.setFrontAngle(0);
|
} else {
|
||||||
// point.setPointActionSize(0);
|
point.setPoint_id(2);
|
||||||
// point.setPointActionList(new ArrayList<>());
|
point.setPoint_serial(2);
|
||||||
// } else {
|
}
|
||||||
// point.setPointId(2);
|
point.setPoint_angle(0);
|
||||||
// point.setPointSerialNumber(2);
|
|
||||||
// point.setType(1);
|
pointList.add(point);
|
||||||
// point.setIsFrontAngle(0);
|
}
|
||||||
// point.setFrontAngle(0);
|
ae.setPoint_info(pointList);
|
||||||
// point.setPointActionSize(1);
|
|
||||||
// for (int j = 0; j < point.getPointActionSize(); j++) {
|
ArrayList<Path> pathList = new ArrayList<>();
|
||||||
// //实际代码中修改为实际逻辑
|
for (int i = 0; i < ae.getPath_size(); i++) {
|
||||||
// point.setPointActionList(new ArrayList<>(Arrays.asList("LOAD")));
|
Path path = new Path();
|
||||||
// }
|
|
||||||
// }
|
path.setPath_id(12);
|
||||||
// pointList.add(point);
|
path.setPath_serial(1);
|
||||||
// }
|
path.setPath_angle(0);
|
||||||
//
|
path.setDriver_pose(1);
|
||||||
// ArrayList<Path> pathList = new ArrayList<>();
|
path.setMax_speed(1);
|
||||||
// for (int i = 0; i < ae.getPathSize(); i++) {
|
path.setMax_angle_speed(1);
|
||||||
// Path path = new Path();
|
|
||||||
// path.setPathId(12);
|
pathList.add(path);
|
||||||
// path.setPathSerialNumber(1);
|
}
|
||||||
// path.setFixedAngle(0);
|
ae.setPath_info(pathList);
|
||||||
// path.setIsFixedAngle(0);
|
|
||||||
// path.setDrivePosture(1);
|
BaseRequestTo baseRequestTo = new BaseRequestTo(2, "OPENTCS", "KC-CTRL", 1, "2025-6-6 10:00:00", ae);
|
||||||
// path.setPathActionSize(0);
|
|
||||||
// path.setMaximumSpeed(1);
|
httpClient.sendCommand("http://192.168.124.121:2005", baseRequestTo);
|
||||||
// path.setMaximumAngularVelocity(1);
|
}
|
||||||
// for (int j = 0; j < path.getPathActionSize(); j++) {
|
|
||||||
// path.setPathActionList(new ArrayList<>(Arrays.asList("test")));
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (path.getPathActionSize() == 0) {
|
|
||||||
// path.setPathActionList(new ArrayList<>());
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// pathList.add(path);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// ae.setPoint(pointList);
|
|
||||||
// ae.setPath(pathList);
|
|
||||||
//
|
|
||||||
// BaseRequestTo baseRequestTo = new BaseRequestTo(KcCmdEnum.getValueByKey(0xAE), "OPENTCS", "KC-CTRL", ae);
|
|
||||||
//
|
|
||||||
// httpClient.sendCommand(baseRequestTo);
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package org.opentcs.communication.http.dto;
|
package org.opentcs.communication.http.dto;
|
||||||
|
|
||||||
import jakarta.annotation.Nonnull;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -12,33 +11,30 @@ import lombok.Data;
|
|||||||
public class BaseRequestTo {
|
public class BaseRequestTo {
|
||||||
|
|
||||||
public BaseRequestTo(
|
public BaseRequestTo(
|
||||||
@Nonnull Integer type,
|
Integer type,
|
||||||
@Nonnull String sender,
|
String sender,
|
||||||
@Nonnull String receiver,
|
String receiver,
|
||||||
@Nonnull Integer serial_num,
|
Integer serial_num,
|
||||||
@Nonnull String time,
|
String time,
|
||||||
@Nonnull Object data
|
Object params
|
||||||
) {
|
) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.sender = sender;
|
this.sender = sender;
|
||||||
this.receiver = receiver;
|
this.receiver = receiver;
|
||||||
this.data = data;
|
this.serial_num = serial_num;
|
||||||
|
this.time = time;
|
||||||
|
this.params = params;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
private Integer type;
|
private Integer type;
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
private String sender;
|
private String sender;
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
private String receiver;
|
private String receiver;
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
private Integer serial_num;
|
private Integer serial_num;
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
private String time;
|
private String time;
|
||||||
|
|
||||||
private Object data;
|
private Object params;
|
||||||
}
|
}
|
||||||
|
@ -1,70 +0,0 @@
|
|||||||
package org.opentcs.communication.http.dto.kc.cmdb2;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author xuzhiheng
|
|
||||||
* @date 2025/5/14
|
|
||||||
* @desc 实体类
|
|
||||||
*/
|
|
||||||
public class RequestB2 {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 动作类型-》填写动作命令码
|
|
||||||
*/
|
|
||||||
private Integer actionType;
|
|
||||||
/**
|
|
||||||
* 执行动作并行方式: 0x00:为移动和动作间都可并行, 0x01:为动作间可以并行,不能移动, 0x02 只能执行当前动作
|
|
||||||
*/
|
|
||||||
private Integer actionParallelManner;
|
|
||||||
/**
|
|
||||||
* 参数内容长度
|
|
||||||
*/
|
|
||||||
private Integer paramSize;
|
|
||||||
/**
|
|
||||||
* 参数内容
|
|
||||||
*/
|
|
||||||
private ArrayList<?> paramData;
|
|
||||||
|
|
||||||
public Integer getActionType() {
|
|
||||||
return actionType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setActionType(Integer actionType) {
|
|
||||||
this.actionType = actionType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Integer getActionParallelManner() {
|
|
||||||
return actionParallelManner;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setActionParallelManner(Integer actionParallelManner) {
|
|
||||||
this.actionParallelManner = actionParallelManner;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Integer getParamSize() {
|
|
||||||
return paramSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setParamSize(Integer paramSize) {
|
|
||||||
this.paramSize = paramSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ArrayList<?> getParamData() {
|
|
||||||
return paramData;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setParamData(ArrayList<?> paramData) {
|
|
||||||
this.paramData = paramData;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "RequestB2{" +
|
|
||||||
"actionType=" + actionType +
|
|
||||||
", actionParallelManner=" + actionParallelManner +
|
|
||||||
", paramSize=" + paramSize +
|
|
||||||
", paramData=" + paramData +
|
|
||||||
'}';
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
package org.opentcs.communication.http.dto.kc.cmdb2.action;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author xuzhiheng
|
|
||||||
* @date 2025/5/14
|
|
||||||
* @desc 实体类
|
|
||||||
*/
|
|
||||||
public class Action01 {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否立即停止移动: 0:机器人正常移动到点上停止(停不下来就移动到下一个点), 1:立刻停止(缓停);
|
|
||||||
*/
|
|
||||||
private Integer isStopImmediately;
|
|
||||||
|
|
||||||
public Integer getIsStopImmediately() {
|
|
||||||
return isStopImmediately;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setIsStopImmediately(Integer isStopImmediately) {
|
|
||||||
this.isStopImmediately = isStopImmediately;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "Action01{" +
|
|
||||||
"isStopImmediately=" + isStopImmediately +
|
|
||||||
'}';
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
package org.opentcs.communication.http.dto.kc.cmdb2.action;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author xuzhiheng
|
|
||||||
* @date 2025/5/13
|
|
||||||
* @desc 实体类
|
|
||||||
*/
|
|
||||||
public class Action02 {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 订单ID
|
|
||||||
*/
|
|
||||||
private Integer orderId;
|
|
||||||
/**
|
|
||||||
* 任务key
|
|
||||||
*/
|
|
||||||
private Integer taskKey;
|
|
||||||
|
|
||||||
public Integer getOrderId() {
|
|
||||||
return orderId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOrderId(Integer orderId) {
|
|
||||||
this.orderId = orderId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Integer getTaskKey() {
|
|
||||||
return taskKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTaskKey(Integer taskKey) {
|
|
||||||
this.taskKey = taskKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "Action02{" +
|
|
||||||
"orderId=" + orderId +
|
|
||||||
", taskKey=" + taskKey +
|
|
||||||
'}';
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
package org.opentcs.communication.http.dto.kc.cmdb2.action;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author xuzhiheng
|
|
||||||
* @date 2025/5/13
|
|
||||||
* @desc 实体类
|
|
||||||
*/
|
|
||||||
public class Action03 {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 订单ID
|
|
||||||
*/
|
|
||||||
private Integer orderId;
|
|
||||||
/**
|
|
||||||
* 是否立即停止移动: 1 立刻停止(缓停);0 AGV 正常移动到点上停止(停不下来就移动到下一个点)
|
|
||||||
*/
|
|
||||||
private Integer isStopImmediately;
|
|
||||||
|
|
||||||
public Integer getOrderId() {
|
|
||||||
return orderId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOrderId(Integer orderId) {
|
|
||||||
this.orderId = orderId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Integer getIsStopImmediately() {
|
|
||||||
return isStopImmediately;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setIsStopImmediately(Integer isStopImmediately) {
|
|
||||||
this.isStopImmediately = isStopImmediately;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "Action03{" +
|
|
||||||
"orderId=" + orderId +
|
|
||||||
", isStopImmediately=" + isStopImmediately +
|
|
||||||
'}';
|
|
||||||
}
|
|
||||||
}
|
|
@ -26,7 +26,7 @@ public class Path {
|
|||||||
/**
|
/**
|
||||||
* 行驶姿态: 0x0 正走,0x1 倒走,0x02 左横移(支持横移类底盘进,行二维码导航时生效),0x03 右横移(支持横移类底盘进行二维码导航时生效)
|
* 行驶姿态: 0x0 正走,0x1 倒走,0x02 左横移(支持横移类底盘进,行二维码导航时生效),0x03 右横移(支持横移类底盘进行二维码导航时生效)
|
||||||
*/
|
*/
|
||||||
private Integer drive_pose;
|
private Integer driver_pose;
|
||||||
/**
|
/**
|
||||||
* 指定的目标最大速度
|
* 指定的目标最大速度
|
||||||
*/
|
*/
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package org.opentcs.communication.http.dto.kc.move;
|
package org.opentcs.communication.http.dto.kc.move;
|
||||||
|
|
||||||
import jakarta.annotation.Nonnull;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@ -14,32 +13,32 @@ public class RequestAe {
|
|||||||
|
|
||||||
public RequestAe() {}
|
public RequestAe() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单ID wms_order_id
|
||||||
|
*/
|
||||||
|
private Integer wms_order_id;
|
||||||
/**
|
/**
|
||||||
* 订单ID
|
* 订单ID
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
private Integer order_id;
|
||||||
private Integer orderId;
|
|
||||||
/**
|
/**
|
||||||
* 任务ID task_key: 任务的唯一标识。与订单 ID 绑定,从 1 开始,当同一订单下发新的资源时加 1;
|
* 任务ID task_key: 任务的唯一标识。与订单 ID 绑定,从 1 开始,当同一订单下发新的资源时加 1;
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
private Integer task_key;
|
||||||
private Integer taskKey;
|
|
||||||
/**
|
/**
|
||||||
* 点个数 point_size
|
* 点个数 point_size
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
private Integer point_size;
|
||||||
private Integer pointSize;
|
|
||||||
/**
|
/**
|
||||||
* 路径个数 path_size
|
* 路径个数 path_size
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
private Integer path_size;
|
||||||
private Integer pathSize;
|
|
||||||
/**
|
/**
|
||||||
* 点信息结构
|
* 点信息结构
|
||||||
*/
|
*/
|
||||||
private ArrayList<Point> point;
|
private ArrayList<Point> point_info;
|
||||||
/**
|
/**
|
||||||
* 路线信息结构
|
* 路线信息结构
|
||||||
*/
|
*/
|
||||||
private ArrayList<Path> path;
|
private ArrayList<Path> path_info;
|
||||||
}
|
}
|
||||||
|
@ -13,13 +13,17 @@ public class RequestB2 {
|
|||||||
/**
|
/**
|
||||||
* 动作类型-》填写动作命令码
|
* 动作类型-》填写动作命令码
|
||||||
*/
|
*/
|
||||||
private Integer actionType;
|
private Integer action_type;
|
||||||
/**
|
/**
|
||||||
* 执行动作并行方式: 0x00:为移动和动作间都可并行, 0x01:为动作间可以并行,不能移动, 0x02 只能执行当前动作
|
* 执行动作并行方式: 0x00:为移动和动作间都可并行, 0x01:为动作间可以并行,不能移动, 0x02 只能执行当前动作
|
||||||
*/
|
*/
|
||||||
private Integer actionParallelManner;
|
private Integer action_parallel_manner;
|
||||||
/**
|
/**
|
||||||
* 参数内容长度
|
* 参数内容长度
|
||||||
*/
|
*/
|
||||||
private Integer paramSize;
|
private Integer param_size;
|
||||||
|
/**
|
||||||
|
* 参数内容
|
||||||
|
*/
|
||||||
|
private Object param_data;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
package org.opentcs.communication.http.entity;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class OrderInfo {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单ID
|
||||||
|
*/
|
||||||
|
private Integer id;
|
||||||
|
/**
|
||||||
|
* 订单名称
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
/**
|
||||||
|
* 订单状态: 1=执行中,2=暂停,3=撤销
|
||||||
|
*/
|
||||||
|
private Integer state;
|
||||||
|
/**
|
||||||
|
* 任务唯一键
|
||||||
|
*/
|
||||||
|
private Integer taskKey;
|
||||||
|
/**
|
||||||
|
* 点序列号
|
||||||
|
* 用于定位点在整个任务中的位置。目的是区分同一个点ID是否在一个任务中出现多次。从0开始偶数递增,例如:0->2->4->6……
|
||||||
|
*/
|
||||||
|
private Integer pointSerialNum;
|
||||||
|
/**
|
||||||
|
* 路线序列号
|
||||||
|
* 用于定位段在整个任务中的位置。目的是区分同一个段ID是否在一个任务中出现多次。从1开始奇数递增,例如:1->3->5->7……
|
||||||
|
*/
|
||||||
|
private Integer pathSerialNum;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package org.opentcs.communication.http.enums;
|
||||||
|
|
||||||
|
public enum Operations {
|
||||||
|
|
||||||
|
PAUSED(1), //暂停订单
|
||||||
|
CONTINUE(2), //继续订单
|
||||||
|
CANCEL(3) //撤销订单
|
||||||
|
;
|
||||||
|
|
||||||
|
private final int type;
|
||||||
|
|
||||||
|
Operations(int type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package org.opentcs.communication.http.enums;
|
||||||
|
|
||||||
|
public enum VehicleEnums {
|
||||||
|
|
||||||
|
// 定义枚举常量(车辆名称),并传入对应的ip和port
|
||||||
|
v1("192.168.124.221", 2005),
|
||||||
|
v2("192.168.124.222", 2005)
|
||||||
|
;
|
||||||
|
|
||||||
|
// 枚举的属性
|
||||||
|
private final String ip;
|
||||||
|
private final int port;
|
||||||
|
|
||||||
|
VehicleEnums(String ip, int port) {
|
||||||
|
this.ip = ip;
|
||||||
|
this.port = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 获取IP
|
||||||
|
public String getIp() {
|
||||||
|
return ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取端口
|
||||||
|
public int getPort() {
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
package org.opentcs.communication.http.service;
|
||||||
|
|
||||||
|
import org.opentcs.communication.http.enums.VehicleEnums;
|
||||||
|
|
||||||
|
public class BaseService {
|
||||||
|
|
||||||
|
public static String getUrl(String vehicleName) {
|
||||||
|
VehicleEnums vehicleEnums = VehicleEnums.valueOf(vehicleName);
|
||||||
|
return "http://" + vehicleEnums.getIp() + ":" + vehicleEnums.getPort();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -5,14 +5,17 @@ import java.time.format.DateTimeFormatter;
|
|||||||
import org.opentcs.communication.http.HttpClient;
|
import org.opentcs.communication.http.HttpClient;
|
||||||
import org.opentcs.communication.http.dto.BaseRequestTo;
|
import org.opentcs.communication.http.dto.BaseRequestTo;
|
||||||
import org.opentcs.communication.http.dto.kc.action.RequestAction;
|
import org.opentcs.communication.http.dto.kc.action.RequestAction;
|
||||||
|
import org.opentcs.communication.http.enums.VehicleEnums;
|
||||||
|
|
||||||
public class ExecuteAction {
|
public class ExecuteAction extends BaseService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 下发动作到平台
|
* 下发动作到平台
|
||||||
* @param action 动作
|
* @param action 动作
|
||||||
*/
|
*/
|
||||||
public static void sendCmd(String action, Integer serialNum) {
|
public static void sendCmd(String vehicleName, String action, Integer serialNum) {
|
||||||
|
|
||||||
|
String url = getUrl(vehicleName);
|
||||||
|
|
||||||
// 获取当前时间
|
// 获取当前时间
|
||||||
LocalDateTime now = LocalDateTime.now();
|
LocalDateTime now = LocalDateTime.now();
|
||||||
@ -32,7 +35,7 @@ public class ExecuteAction {
|
|||||||
);
|
);
|
||||||
|
|
||||||
HttpClient httpClient = new HttpClient();
|
HttpClient httpClient = new HttpClient();
|
||||||
httpClient.sendCommand(baseRequestTo);
|
httpClient.sendCommand(url, baseRequestTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3,62 +3,58 @@ package org.opentcs.communication.http.service;
|
|||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.Objects;
|
||||||
import org.opentcs.communication.http.HttpClient;
|
import org.opentcs.communication.http.HttpClient;
|
||||||
import org.opentcs.communication.http.dto.BaseRequestTo;
|
import org.opentcs.communication.http.dto.BaseRequestTo;
|
||||||
import org.opentcs.communication.http.dto.kc.move.Path;
|
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.Point;
|
||||||
import org.opentcs.communication.http.dto.kc.move.RequestAe;
|
import org.opentcs.communication.http.dto.kc.move.RequestAe;
|
||||||
|
import org.opentcs.communication.http.entity.OrderInfo;
|
||||||
import org.opentcs.drivers.vehicle.MovementCommand;
|
import org.opentcs.drivers.vehicle.MovementCommand;
|
||||||
|
|
||||||
public class ExecuteMove {
|
public class ExecuteMove extends BaseService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 订单名映射int类型数据.
|
* 订单名映射int类型数据.
|
||||||
*/
|
*/
|
||||||
private static final HashMap<String, Integer> orderNameMap = new HashMap<>();
|
private static final HashMap<String, OrderInfo> orderInfoMap = new HashMap<>();
|
||||||
/**
|
/**
|
||||||
* 记录上次下发订单名称
|
* 通讯适配器当前执行taskkey
|
||||||
*/
|
*/
|
||||||
private static String oldOrderName;
|
private static HashMap<String, Integer> execTaskKeyMap = new HashMap<>();
|
||||||
/**
|
|
||||||
* 当前订单名称对应唯一整数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)
|
/**
|
||||||
|
* 发送移动指令
|
||||||
|
* @param vehicleName 车辆名称
|
||||||
|
* @param cmd 订单
|
||||||
|
* @param serialNum 序列号
|
||||||
|
*/
|
||||||
|
public static void sendCmd(String vehicleName, MovementCommand cmd, Integer serialNum)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
String url = getUrl(vehicleName);
|
||||||
|
|
||||||
// 获取当前时间
|
// 获取当前时间
|
||||||
LocalDateTime now = LocalDateTime.now();
|
LocalDateTime now = LocalDateTime.now();
|
||||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||||
String time = now.format(formatter);
|
String time = now.format(formatter);
|
||||||
|
|
||||||
RequestAe ae = buildCommand(cmd);
|
RequestAe ae = buildCommand(vehicleName, cmd);
|
||||||
BaseRequestTo baseRequestTo = new BaseRequestTo(2, "OPENTCS", "KC-CTRL", serialNum, time, ae);
|
BaseRequestTo baseRequestTo = new BaseRequestTo(2, "OPENTCS", "KC-CTRL", serialNum, time, ae);
|
||||||
|
|
||||||
HttpClient httpClient = new HttpClient();
|
HttpClient httpClient = new HttpClient();
|
||||||
httpClient.sendCommand(baseRequestTo);
|
httpClient.sendCommand(url, baseRequestTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static RequestAe buildCommand(MovementCommand cmd)
|
private static RequestAe buildCommand(String vehicleName, MovementCommand cmd)
|
||||||
{
|
{
|
||||||
|
// 自动维护订单ID和任务key
|
||||||
|
getUniqueOrderID(vehicleName, cmd.getTransportOrder().getName());
|
||||||
|
OrderInfo orderInfo = orderInfoMap.get(vehicleName);
|
||||||
|
|
||||||
//订单ID
|
//订单ID
|
||||||
int orderID = getUniqueOrderID(cmd.getTransportOrder().getName());
|
int orderID = orderInfo.getId();
|
||||||
//下发起点
|
//下发起点
|
||||||
String sourcePoint = cmd.getStep().getSourcePoint().getName();
|
String sourcePoint = cmd.getStep().getSourcePoint().getName();
|
||||||
int newSourcePoint = Integer.parseInt(sourcePoint);
|
int newSourcePoint = Integer.parseInt(sourcePoint);
|
||||||
@ -74,87 +70,122 @@ public class ExecuteMove {
|
|||||||
pathID = Integer.parseInt(destinationPoint + sourcePoint);
|
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();
|
RequestAe ae = new RequestAe();
|
||||||
ae.setOrderId(orderID);
|
ae.setWms_order_id(1); //todo 测试填写
|
||||||
ae.setTaskKey(taskKey);
|
ae.setOrder_id(orderID);
|
||||||
ae.setPointSize(2);
|
orderInfo.setTaskKey(orderInfo.getTaskKey() + 1);
|
||||||
ae.setPathSize(1);
|
ae.setTask_key(orderInfo.getTaskKey());
|
||||||
|
ae.setPoint_size(2);
|
||||||
|
ae.setPath_size(1);
|
||||||
|
|
||||||
ArrayList<Point> pointList = new ArrayList<>();
|
ArrayList<Point> pointList = new ArrayList<>();
|
||||||
for (int i = 0; i < ae.getPointSize(); i++) {
|
for (int i = 0; i < ae.getPoint_size(); i++) {
|
||||||
Point point = new Point();
|
Point point = new Point();
|
||||||
|
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
point.setPoint_id(newSourcePoint);
|
point.setPoint_id(newSourcePoint);
|
||||||
|
point.setPoint_serial(orderInfo.getPointSerialNum());
|
||||||
|
orderInfo.setPointSerialNum(orderInfo.getPointSerialNum() + 2);
|
||||||
} else {
|
} else {
|
||||||
point.setPoint_id(newDestination);
|
point.setPoint_id(newDestination);
|
||||||
|
point.setPoint_serial(orderInfo.getPointSerialNum());
|
||||||
}
|
}
|
||||||
point.setPoint_serial(pointSerialNum);
|
|
||||||
point.setPoint_angle(0);
|
point.setPoint_angle(0);
|
||||||
|
|
||||||
pointSerialNum = pointSerialNum + 2;
|
|
||||||
|
|
||||||
pointList.add(point);
|
pointList.add(point);
|
||||||
}
|
}
|
||||||
ae.setPoint(pointList);
|
ae.setPoint_info(pointList);
|
||||||
|
|
||||||
ArrayList<Path> pathList = new ArrayList<>();
|
ArrayList<Path> pathList = new ArrayList<>();
|
||||||
for (int i = 0; i < ae.getPathSize(); i++) {
|
for (int i = 0; i < ae.getPath_size(); i++) {
|
||||||
Path path = new Path();
|
Path path = new Path();
|
||||||
|
|
||||||
path.setPath_id(pathID);
|
path.setPath_id(pathID);
|
||||||
path.setPath_serial(pathSerialNum);
|
path.setPath_serial(orderInfo.getPathSerialNum());
|
||||||
path.setPath_angle(0);
|
path.setPath_angle(0);
|
||||||
path.setDrive_pose(1);
|
path.setDriver_pose(1);
|
||||||
path.setMax_speed(1f);
|
path.setMax_speed(maxVelocity);
|
||||||
path.setMax_angle_speed(1f);
|
path.setMax_angle_speed(maxVelocity);
|
||||||
|
|
||||||
pathSerialNum = pathSerialNum + 2;
|
orderInfo.setPathSerialNum(orderInfo.getPathSerialNum() + 2);
|
||||||
|
|
||||||
pathList.add(path);
|
pathList.add(path);
|
||||||
}
|
}
|
||||||
ae.setPath(pathList);
|
ae.setPath_info(pathList);
|
||||||
|
|
||||||
return ae;
|
return ae;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 维护订单名对应int类型唯一ID--------todo 待优化:如果调度重启,控制器也需要重启。否则0xAE指令会因为重置订单ID和任务key下发失败。应改成wms数据库ID交互
|
* 维护订单名对应int类型唯一ID--------todo 待优化:如果调度重启,控制器也需要重启。否则0xAE指令会因为重置订单ID和任务key下发失败。应改成wms数据库ID交互
|
||||||
* @param orderName 订单名
|
* @param vehicleName 车辆名称
|
||||||
|
* @param orderName 订单名称
|
||||||
* @return Integer
|
* @return Integer
|
||||||
*/
|
*/
|
||||||
private static int getUniqueOrderID(String orderName){
|
private static void getUniqueOrderID(String vehicleName, String orderName){
|
||||||
|
|
||||||
Integer orderId;
|
|
||||||
|
|
||||||
if (orderNameMap.containsKey(orderName)) {
|
if (orderInfoMap.containsKey(vehicleName)) {
|
||||||
//订单名已存在
|
//当前车辆已存在集合中
|
||||||
orderId = orderNameMap.get(orderName);
|
OrderInfo orderInfo = orderInfoMap.get(vehicleName);
|
||||||
} else { //订单名不存在
|
|
||||||
//初始化参数
|
|
||||||
initParams();
|
|
||||||
|
|
||||||
//删除上次订单映射唯一ID
|
if (!Objects.equals(orderName, orderInfo.getName())) {
|
||||||
orderNameMap.remove(oldOrderName);
|
//订单名称不相等为执行下一个订单,初始化订单对应参数
|
||||||
|
orderInfoMap.remove(vehicleName);
|
||||||
|
|
||||||
//更新记录订单名称
|
Integer currentOrderId = orderInfo.getId() + 1;
|
||||||
oldOrderName = orderName;
|
|
||||||
|
|
||||||
// 创建对应映射
|
orderInfo.setId(currentOrderId);
|
||||||
orderId = currentOrderId;
|
orderInfo.setName(orderName);
|
||||||
currentOrderId++;
|
orderInfo.setState(1);
|
||||||
orderNameMap.put(orderName, orderId);
|
orderInfo.setTaskKey(1);
|
||||||
|
orderInfo.setPointSerialNum(0);
|
||||||
|
orderInfo.setPathSerialNum(1);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
//车辆不在集合中
|
||||||
|
OrderInfo orderInfo = new OrderInfo();
|
||||||
|
orderInfo.setId(1);
|
||||||
|
orderInfo.setName(orderName);
|
||||||
|
orderInfo.setState(1);
|
||||||
|
orderInfo.setTaskKey(1);
|
||||||
|
orderInfo.setPointSerialNum(0);
|
||||||
|
orderInfo.setPathSerialNum(1);
|
||||||
|
|
||||||
return orderId;
|
orderInfoMap.put(vehicleName, orderInfo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 初始化参数
|
* 设置当前执行任务key
|
||||||
*/
|
*/
|
||||||
private static void initParams() {
|
public static void setExecTaskKey(String vehicleName, Integer taskKey) {
|
||||||
taskKey = 1;
|
if (execTaskKeyMap.containsKey(vehicleName)) {
|
||||||
pointSerialNum = 0;
|
execTaskKeyMap.put(vehicleName, taskKey);
|
||||||
pathSerialNum = 1;
|
} 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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,110 @@
|
|||||||
package org.opentcs.communication.http.service;
|
package org.opentcs.communication.http.service;
|
||||||
|
|
||||||
public class ExecuteOperation {
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import org.opentcs.communication.http.HttpClient;
|
||||||
|
import org.opentcs.communication.http.dto.BaseRequestTo;
|
||||||
|
import org.opentcs.communication.http.dto.kc.operation.Action01;
|
||||||
|
import org.opentcs.communication.http.dto.kc.operation.Action02;
|
||||||
|
import org.opentcs.communication.http.dto.kc.operation.Action03;
|
||||||
|
import org.opentcs.communication.http.dto.kc.operation.RequestB2;
|
||||||
|
import org.opentcs.communication.http.enums.Operations;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class ExecuteOperation extends BaseService{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class's Logger.
|
||||||
|
*/
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(ExecuteOperation.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 暂停执行订单
|
||||||
|
* @param vehicleName 车辆名称
|
||||||
|
* @param serialNum 序列号
|
||||||
|
*/
|
||||||
|
public static void pauseOrder(String vehicleName, Integer serialNum) {
|
||||||
|
RequestB2 b2 = new RequestB2();
|
||||||
|
|
||||||
|
b2.setAction_parallel_manner(2);
|
||||||
|
b2.setAction_type(Operations.PAUSED.getType());
|
||||||
|
b2.setParam_size(4);
|
||||||
|
|
||||||
|
Action01 action01 = new Action01();
|
||||||
|
action01.setIsStopImmediately(1);
|
||||||
|
|
||||||
|
b2.setParam_data(action01);
|
||||||
|
|
||||||
|
sendCmd(vehicleName, b2, serialNum);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 继续执行订单
|
||||||
|
* @param vehicleName 车辆名称
|
||||||
|
* @param serialNum 序列号
|
||||||
|
*/
|
||||||
|
public static void continueOrder(String vehicleName, Integer serialNum) {
|
||||||
|
//获取订单ID
|
||||||
|
Integer orderId = ExecuteMove.getOrderID(vehicleName);
|
||||||
|
|
||||||
|
//获取任务key
|
||||||
|
Integer taskKey = ExecuteMove.getTaskKey(vehicleName);
|
||||||
|
|
||||||
|
RequestB2 b2 = new RequestB2();
|
||||||
|
|
||||||
|
b2.setAction_parallel_manner(2);
|
||||||
|
b2.setAction_type(Operations.CONTINUE.getType());
|
||||||
|
b2.setParam_size(8);
|
||||||
|
|
||||||
|
Action02 action02 = new Action02();
|
||||||
|
action02.setOrderId(orderId);
|
||||||
|
action02.setTaskKey(taskKey);
|
||||||
|
|
||||||
|
b2.setParam_data(action02);
|
||||||
|
|
||||||
|
sendCmd(vehicleName, b2, serialNum);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 撤销订单
|
||||||
|
* @param vehicleName 车辆名称
|
||||||
|
* @param serialNum 序列号
|
||||||
|
*/
|
||||||
|
public static void cancelOrder(String vehicleName, Integer serialNum) {
|
||||||
|
|
||||||
|
//获取订单ID
|
||||||
|
Integer orderId = ExecuteMove.getOrderID(vehicleName);
|
||||||
|
|
||||||
|
RequestB2 b2 = new RequestB2();
|
||||||
|
|
||||||
|
b2.setAction_parallel_manner(2);
|
||||||
|
b2.setAction_type(Operations.CANCEL.getType());
|
||||||
|
b2.setParam_size(8);
|
||||||
|
|
||||||
|
Action03 action03 = new Action03();
|
||||||
|
action03.setOrderId(orderId);
|
||||||
|
action03.setIsStopImmediately(1);
|
||||||
|
|
||||||
|
b2.setParam_data(action03);
|
||||||
|
|
||||||
|
sendCmd(vehicleName, b2, serialNum);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void sendCmd(String vehicleName, Object data, Integer serialNum)
|
||||||
|
{
|
||||||
|
String url = getUrl(vehicleName);
|
||||||
|
|
||||||
|
// 获取当前时间
|
||||||
|
LocalDateTime now = LocalDateTime.now();
|
||||||
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||||
|
String time = now.format(formatter);
|
||||||
|
|
||||||
|
// RequestB2 b2 = buildCommand(operation, orderId, taskKey);
|
||||||
|
BaseRequestTo baseRequestTo = new BaseRequestTo(2, "OPENTCS", "KC-CTRL", serialNum, time, data);
|
||||||
|
|
||||||
|
HttpClient httpClient = new HttpClient();
|
||||||
|
httpClient.sendCommand(url, baseRequestTo);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -22,13 +22,12 @@ import org.slf4j.LoggerFactory;
|
|||||||
public class BrokerInterceptor implements InterceptHandler {
|
public class BrokerInterceptor implements InterceptHandler {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 客户端ID-定义为车辆名称
|
* LOG
|
||||||
*/
|
*/
|
||||||
private String clientID;
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(BrokerInterceptor.class);
|
private static final Logger LOG = LoggerFactory.getLogger(BrokerInterceptor.class);
|
||||||
|
|
||||||
@Override public String getID() {
|
@Override public String getID() {
|
||||||
return clientID;
|
return "BrokerInterceptor_" + hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -46,17 +45,17 @@ public class BrokerInterceptor implements InterceptHandler {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onConnect(InterceptConnectMessage msg) {
|
public void onConnect(InterceptConnectMessage msg) {
|
||||||
LOG.info("[连接] 客户端ID: {} 连接到服务端", msg.getClientID());
|
LOG.info("[connect] client ID: {} connect to server", msg.getClientID());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDisconnect(InterceptDisconnectMessage msg) {
|
public void onDisconnect(InterceptDisconnectMessage msg) {
|
||||||
LOG.info("[断开] 客户端ID: {} 断开连接", msg.getClientID());
|
LOG.info("[disconnect] client ID: {} disconnect", msg.getClientID());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onConnectionLost(InterceptConnectionLostMessage interceptConnectionLostMessage) {
|
public void onConnectionLost(InterceptConnectionLostMessage interceptConnectionLostMessage) {
|
||||||
|
LOG.info("[lost] client ID: {} lost connection", interceptConnectionLostMessage.getClientID());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -75,21 +74,19 @@ public class BrokerInterceptor implements InterceptHandler {
|
|||||||
|
|
||||||
// 必须保留引用计数,防止内存泄漏
|
// 必须保留引用计数,防止内存泄漏
|
||||||
payload.retain();
|
payload.retain();
|
||||||
|
|
||||||
|
MqttBrokerServer mqttBrokerServer = new MqttBrokerServer();
|
||||||
|
mqttBrokerServer.sendToClient("v1", MqttQoS.AT_LEAST_ONCE, "hello mqtt client");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 其他需要实现的接口方法(可以留空)
|
// 其他需要实现的接口方法(可以留空)
|
||||||
@Override public void onSubscribe(InterceptSubscribeMessage msg) {}
|
@Override public void onSubscribe(InterceptSubscribeMessage msg) {
|
||||||
@Override public void onUnsubscribe(InterceptUnsubscribeMessage msg) {}
|
LOG.info("[subscribe] client ID: {} subscribe topic: {}", msg.getClientID(), msg.getTopicFilter());
|
||||||
@Override public void onMessageAcknowledged(InterceptAcknowledgedMessage msg) {}
|
}
|
||||||
|
@Override public void onUnsubscribe(InterceptUnsubscribeMessage msg) {
|
||||||
/**
|
LOG.info("[unsubscribe] client ID: {} unsubscribe topic: {}", msg.getClientID(), msg.getTopicFilter());
|
||||||
* 解析消息内容
|
}
|
||||||
* @param msg InterceptPublishMessage
|
@Override public void onMessageAcknowledged(InterceptAcknowledgedMessage msg) {
|
||||||
* @return String
|
LOG.info("[acknowledged] topic: {} acknowledged message: {}", msg.getTopic(), msg.getMsg());
|
||||||
*/
|
|
||||||
private String parsePayload(InterceptPublishMessage msg) {
|
|
||||||
byte[] payloadBytes = new byte[msg.getPayload().readableBytes()];
|
|
||||||
msg.getPayload().getBytes(0, payloadBytes);
|
|
||||||
return new String(payloadBytes, StandardCharsets.UTF_8);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import io.moquette.broker.Server;
|
|||||||
import io.moquette.broker.config.IConfig;
|
import io.moquette.broker.config.IConfig;
|
||||||
import io.moquette.broker.config.MemoryConfig;
|
import io.moquette.broker.config.MemoryConfig;
|
||||||
import io.moquette.broker.subscriptions.Topic;
|
import io.moquette.broker.subscriptions.Topic;
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
import io.netty.handler.codec.mqtt.MqttFixedHeader;
|
import io.netty.handler.codec.mqtt.MqttFixedHeader;
|
||||||
import io.netty.handler.codec.mqtt.MqttMessageType;
|
import io.netty.handler.codec.mqtt.MqttMessageType;
|
||||||
@ -72,36 +73,47 @@ public class MqttBrokerServer {
|
|||||||
* @param message 消息
|
* @param message 消息
|
||||||
*/
|
*/
|
||||||
public void sendToClient(String clientId, MqttQoS qosLevel, String message) {
|
public void sendToClient(String clientId, MqttQoS qosLevel, String message) {
|
||||||
// LOG.info("Sending message to client: {}, MqttQoS: {}, message: {}", clientId, qosLevel, message);
|
LOG.info("Sending message to client: {}, MqttQoS: {}, message: {}", clientId, qosLevel, message);
|
||||||
//
|
|
||||||
// String topicPath = TopicBuilder.buildCommandTopic(clientId);
|
|
||||||
// Topic topic = new Topic(topicPath);
|
String topicPath = TopicBuilder.buildCommandTopic(clientId);
|
||||||
//
|
Topic topic = new Topic(topicPath);
|
||||||
// MqttFixedHeader fixedHeader = new MqttFixedHeader(
|
|
||||||
// MqttMessageType.PUBLISH, // 消息类型
|
MqttFixedHeader fixedHeader = new MqttFixedHeader(
|
||||||
// false, // 是否重复发送
|
MqttMessageType.PUBLISH, // 消息类型
|
||||||
// qosLevel, // 服务质量等级: QoS 0 – 最多交付一次,可能丢失消息; QoS 1 – 至少交付一次,可以保证收到消息,但消息可能重复; QoS 2 – 只交付一次,使用 QoS 2 可以保证消息既不丢失也不重复,开销最高
|
false, // 是否重复发送
|
||||||
// false, // 是否保留消息
|
qosLevel, // 服务质量等级: QoS 0 – 最多交付一次,可能丢失消息; QoS 1 – 至少交付一次,可以保证收到消息,但消息可能重复; QoS 2 – 只交付一次,使用 QoS 2 可以保证消息既不丢失也不重复,开销最高
|
||||||
// 0 // 剩余长度(自动计算)
|
false, // 是否保留消息
|
||||||
// );
|
0 // 剩余长度(自动计算)
|
||||||
//
|
);
|
||||||
// MqttPublishVariableHeader variableHeader = new MqttPublishVariableHeader(
|
|
||||||
// topic.toString(), // 主题
|
MqttPublishVariableHeader variableHeader = new MqttPublishVariableHeader(
|
||||||
// MqttQoS.AT_LEAST_ONCE.value() // 消息ID(QoS>0时需要)
|
topic.toString(), // 主题
|
||||||
// );
|
qosLevel.value() // 服务质量等级
|
||||||
//
|
);
|
||||||
// // 将消息内容转换为ByteBuf
|
|
||||||
// byte[] payload = message.getBytes(StandardCharsets.UTF_8);
|
// 将消息内容转换为ByteBuf
|
||||||
// MqttPublishMessage publishMessage = new MqttPublishMessage(
|
byte[] payload = message.getBytes(StandardCharsets.UTF_8);
|
||||||
// fixedHeader,
|
ByteBuf payloadBuf = Unpooled.copiedBuffer(payload);
|
||||||
// variableHeader,
|
MqttPublishMessage publishMessage = new MqttPublishMessage(
|
||||||
// Unpooled.wrappedBuffer(payload)
|
fixedHeader,
|
||||||
// );
|
variableHeader,
|
||||||
//
|
payloadBuf
|
||||||
// // 发布消息到指定客户端
|
);
|
||||||
// mqttServer.internalPublish(
|
|
||||||
// publishMessage,
|
|
||||||
// clientId // 指定接收客户端ID
|
try {
|
||||||
// );
|
// 发布消息到指定客户端
|
||||||
|
mqttServer.internalPublish(
|
||||||
|
publishMessage,
|
||||||
|
clientId // 指定接收客户端ID
|
||||||
|
);
|
||||||
|
LOG.debug("Sent to {} ,topic {} QoS:{} message {}",
|
||||||
|
clientId, topic, qosLevel, message);
|
||||||
|
} finally {
|
||||||
|
if (!publishMessage.payload().isReadable()) {
|
||||||
|
publishMessage.payload().release(); // 确保释放
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,8 +35,11 @@ public class MqttClientExample {
|
|||||||
|
|
||||||
// 发布消息
|
// 发布消息
|
||||||
String content = "Hello, MQTT";
|
String content = "Hello, MQTT";
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
client.publish(topic, content.getBytes(), qos, false);
|
client.publish(topic, content.getBytes(), qos, false);
|
||||||
System.out.println("Published message: " + content);
|
Thread.sleep(300);
|
||||||
|
}
|
||||||
|
|
||||||
// 等待接收消息
|
// 等待接收消息
|
||||||
Thread.sleep(5000);
|
Thread.sleep(5000);
|
||||||
|
@ -0,0 +1,44 @@
|
|||||||
|
package org.opentcs.communication.mqtt.entity;
|
||||||
|
|
||||||
|
import jakarta.annotation.Nonnull;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author xuzhiheng
|
||||||
|
* @date 2025/5/12
|
||||||
|
* @desc 实体基类
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class BaseRequestTo {
|
||||||
|
|
||||||
|
public BaseRequestTo(
|
||||||
|
@Nonnull Integer type,
|
||||||
|
@Nonnull String sender,
|
||||||
|
@Nonnull String receiver,
|
||||||
|
@Nonnull Integer serial_num,
|
||||||
|
@Nonnull String time,
|
||||||
|
@Nonnull Object data
|
||||||
|
) {
|
||||||
|
this.type = type;
|
||||||
|
this.sender = sender;
|
||||||
|
this.receiver = receiver;
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
private Integer type;
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
private String sender;
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
private String receiver;
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
private Integer serial_num;
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
private String time;
|
||||||
|
|
||||||
|
private Object data;
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
package org.opentcs.communication.mqtt.entity.kc.action;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author xuzhiheng
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class RequestAction {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 动作
|
||||||
|
*/
|
||||||
|
private String action;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
package org.opentcs.communication.mqtt.entity.kc.move;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author xuzhiheng
|
||||||
|
* @date 2025/5/12
|
||||||
|
* @desc 实体类
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class Path {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 路径ID
|
||||||
|
*/
|
||||||
|
private Integer path_id;
|
||||||
|
/**
|
||||||
|
* 路径序列号: 从 1 开始奇数递增,例如:1->3->5->7……
|
||||||
|
*/
|
||||||
|
private Integer path_serial;
|
||||||
|
/**
|
||||||
|
* 机器人固定角度: 0 = 不指定
|
||||||
|
*/
|
||||||
|
private float path_angle;
|
||||||
|
/**
|
||||||
|
* 行驶姿态: 0x0 正走,0x1 倒走,0x02 左横移(支持横移类底盘进,行二维码导航时生效),0x03 右横移(支持横移类底盘进行二维码导航时生效)
|
||||||
|
*/
|
||||||
|
private Integer drive_pose;
|
||||||
|
/**
|
||||||
|
* 指定的目标最大速度
|
||||||
|
*/
|
||||||
|
private float max_speed;
|
||||||
|
/**
|
||||||
|
* 指定的目标最大角速度
|
||||||
|
*/
|
||||||
|
private float max_angle_speed;
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package org.opentcs.communication.mqtt.entity.kc.move;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author xuzhiheng
|
||||||
|
* @date 2025/5/12
|
||||||
|
* @desc 实体类
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class Point {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 点ID
|
||||||
|
*/
|
||||||
|
private Integer point_id;
|
||||||
|
/**
|
||||||
|
* 点序列号: 从 0开始偶数递增,例如:0->2->4->6……
|
||||||
|
*/
|
||||||
|
private Integer point_serial;
|
||||||
|
/**
|
||||||
|
* 角度:0=不指定角度
|
||||||
|
*/
|
||||||
|
private double point_angle;
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
package org.opentcs.communication.mqtt.entity.kc.move;
|
||||||
|
|
||||||
|
import jakarta.annotation.Nonnull;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author xuzhiheng
|
||||||
|
* @date 2025/5/12
|
||||||
|
* @desc 实体类
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class RequestAe {
|
||||||
|
|
||||||
|
public RequestAe() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单ID
|
||||||
|
*/
|
||||||
|
@Nonnull
|
||||||
|
private Integer orderId;
|
||||||
|
/**
|
||||||
|
* 任务ID task_key: 任务的唯一标识。与订单 ID 绑定,从 1 开始,当同一订单下发新的资源时加 1;
|
||||||
|
*/
|
||||||
|
@Nonnull
|
||||||
|
private Integer taskKey;
|
||||||
|
/**
|
||||||
|
* 点个数 point_size
|
||||||
|
*/
|
||||||
|
@Nonnull
|
||||||
|
private Integer pointSize;
|
||||||
|
/**
|
||||||
|
* 路径个数 path_size
|
||||||
|
*/
|
||||||
|
@Nonnull
|
||||||
|
private Integer pathSize;
|
||||||
|
/**
|
||||||
|
* 点信息结构
|
||||||
|
*/
|
||||||
|
private ArrayList<Point> point;
|
||||||
|
/**
|
||||||
|
* 路线信息结构
|
||||||
|
*/
|
||||||
|
private ArrayList<Path> path;
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package org.opentcs.communication.mqtt.entity.kc.operation;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author xuzhiheng
|
||||||
|
* @date 2025/5/14
|
||||||
|
* @desc 实体类
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class Action01 {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否立即停止移动: 0:机器人正常移动到点上停止(停不下来就移动到下一个点), 1:立刻停止(缓停);
|
||||||
|
*/
|
||||||
|
private Integer isStopImmediately;
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package org.opentcs.communication.mqtt.entity.kc.operation;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author xuzhiheng
|
||||||
|
* @date 2025/5/13
|
||||||
|
* @desc 实体类
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class Action02 {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单ID
|
||||||
|
*/
|
||||||
|
private Integer orderId;
|
||||||
|
/**
|
||||||
|
* 任务key
|
||||||
|
*/
|
||||||
|
private Integer taskKey;
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package org.opentcs.communication.mqtt.entity.kc.operation;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author xuzhiheng
|
||||||
|
* @date 2025/5/13
|
||||||
|
* @desc 实体类
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class Action03 {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单ID
|
||||||
|
*/
|
||||||
|
private Integer orderId;
|
||||||
|
/**
|
||||||
|
* 是否立即停止移动: 1 立刻停止(缓停);0 AGV 正常移动到点上停止(停不下来就移动到下一个点)
|
||||||
|
*/
|
||||||
|
private Integer isStopImmediately;
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package org.opentcs.communication.mqtt.entity.kc.operation;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author xuzhiheng
|
||||||
|
* @date 2025/5/14
|
||||||
|
* @desc 实体类
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class RequestB2 {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 动作类型-》填写动作命令码
|
||||||
|
*/
|
||||||
|
private Integer actionType;
|
||||||
|
/**
|
||||||
|
* 执行动作并行方式: 0x00:为移动和动作间都可并行, 0x01:为动作间可以并行,不能移动, 0x02 只能执行当前动作
|
||||||
|
*/
|
||||||
|
private Integer actionParallelManner;
|
||||||
|
/**
|
||||||
|
* 参数内容长度
|
||||||
|
*/
|
||||||
|
private Integer paramSize;
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
package org.opentcs.communication.mqtt.enums;
|
||||||
|
|
||||||
|
public enum Actions {
|
||||||
|
|
||||||
|
//取请求
|
||||||
|
PICK_UP_REQUEST,
|
||||||
|
//放请求
|
||||||
|
RELEASE_REQUEST,
|
||||||
|
//充电
|
||||||
|
CHARGE,
|
||||||
|
//取消充电
|
||||||
|
CANCEL_CHARGE
|
||||||
|
;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断是否存在当前动作
|
||||||
|
* @param value
|
||||||
|
* @return 存在返回true,不存在返回false
|
||||||
|
*/
|
||||||
|
public static boolean contains(String value) {
|
||||||
|
for (Actions actions : Actions.values()) {
|
||||||
|
if (actions.name().equals(value)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,75 @@
|
|||||||
|
package org.opentcs.communication.mqtt.enums;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author xuzhiheng
|
||||||
|
* @date 2025/5/14
|
||||||
|
* @desc 将十进制value,绑定到小端模式16进制key
|
||||||
|
*/
|
||||||
|
public enum KcActionCmdEnum {
|
||||||
|
|
||||||
|
CMD_ACTION_0x01(0x01, 1), //暂停车辆
|
||||||
|
CMD_ACTION_0x02(0x02, 2), //恢复订单执行
|
||||||
|
CMD_ACTION_0x03(0x03, 3); //取消任务
|
||||||
|
|
||||||
|
private Integer key;
|
||||||
|
private Integer value;
|
||||||
|
|
||||||
|
KcActionCmdEnum(Integer key, Integer value) {
|
||||||
|
this.key = key;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getKey() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setKey(Integer key) {
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(Integer value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 静态缓存,提升查询性能
|
||||||
|
private static final Map<Integer, KcActionCmdEnum> KEY_MAP = new HashMap<>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
// 初始化时将所有枚举实例的键值存入Map
|
||||||
|
for (KcActionCmdEnum entry : values()) {
|
||||||
|
if (KEY_MAP.containsKey(entry.key)) {
|
||||||
|
throw new IllegalStateException("REPEATED KEY: " + entry.key);
|
||||||
|
}
|
||||||
|
KEY_MAP.put(entry.key, entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据key获取对应的value
|
||||||
|
* @param key 要查找的键
|
||||||
|
* @return 对应的值
|
||||||
|
* @throws IllegalArgumentException 如果key不存在
|
||||||
|
*/
|
||||||
|
public static Integer getValueByKey(Integer key) {
|
||||||
|
KcActionCmdEnum entry = KEY_MAP.get(key);
|
||||||
|
if (entry == null) {
|
||||||
|
throw new IllegalArgumentException("无效的key: " + key);
|
||||||
|
}
|
||||||
|
return entry.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据key获取完整的枚举实例
|
||||||
|
*/
|
||||||
|
public static KcActionCmdEnum getEntryByKey(Integer key) {
|
||||||
|
return KEY_MAP.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,86 @@
|
|||||||
|
package org.opentcs.communication.mqtt.enums;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author xuzhiheng
|
||||||
|
* @date 2025/5/14
|
||||||
|
* @desc 将十进制value,绑定到小端模式16进制key
|
||||||
|
*/
|
||||||
|
public enum KcCmdEnum {
|
||||||
|
|
||||||
|
CMD_0x02(0x02, 2), //读多变量
|
||||||
|
CMD_0x03(0x03, 3), //写多变量
|
||||||
|
CMD_0x14(0x14, 20), //执行机器人手动定位
|
||||||
|
CMD_0x17(0x17, 23), //查询机器人运行状态
|
||||||
|
CMD_0x1F(0x1F, 31), //确认初始位置
|
||||||
|
CMD_0xAE(0xAE, 174), //导航指令
|
||||||
|
CMD_0xAF(0xAF, 175), //获取AGV详细信息
|
||||||
|
CMD_0xB0(0xB0, 176), //查询载货状态
|
||||||
|
CMD_0xB2(0xB2, 178); //订阅AGV信息
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小端模式十六进制命令码
|
||||||
|
*/
|
||||||
|
private Integer key;
|
||||||
|
/**
|
||||||
|
* 十进制命令码
|
||||||
|
*/
|
||||||
|
private Integer value;
|
||||||
|
|
||||||
|
KcCmdEnum(Integer key, Integer value) {
|
||||||
|
this.key = key;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getKey() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setKey(Integer key) {
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(Integer value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 静态缓存,提升查询性能
|
||||||
|
private static final Map<Integer, KcCmdEnum> KEY_MAP = new HashMap<>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
// 初始化时将所有枚举实例的键值存入Map
|
||||||
|
for (KcCmdEnum entry : values()) {
|
||||||
|
if (KEY_MAP.containsKey(entry.key)) {
|
||||||
|
throw new IllegalStateException("REPEATED KEY: " + entry.key);
|
||||||
|
}
|
||||||
|
KEY_MAP.put(entry.key, entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据key获取对应的value
|
||||||
|
* @param key 要查找的键
|
||||||
|
* @return 对应的值
|
||||||
|
* @throws IllegalArgumentException 如果key不存在
|
||||||
|
*/
|
||||||
|
public static Integer getValueByKey(Integer key) {
|
||||||
|
KcCmdEnum entry = KEY_MAP.get(key);
|
||||||
|
if (entry == null) {
|
||||||
|
throw new IllegalArgumentException("无效的key: " + key);
|
||||||
|
}
|
||||||
|
return entry.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据key获取完整的枚举实例
|
||||||
|
*/
|
||||||
|
public static KcCmdEnum getEntryByKey(Integer key) {
|
||||||
|
return KEY_MAP.get(key);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
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消息
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,168 @@
|
|||||||
|
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<String, Integer> 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<Point> 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<Path> 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;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package org.opentcs.communication.mqtt.service;
|
||||||
|
|
||||||
|
public class ExecuteOperation {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -8,7 +8,11 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import org.opentcs.access.KernelServicePortal;
|
||||||
|
import org.opentcs.access.rmi.KernelServicePortalBuilder;
|
||||||
import org.opentcs.common.GuestUserCredentials;
|
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.AgvInfo;
|
||||||
import org.opentcs.manage.entity.AgvInfoParams;
|
import org.opentcs.manage.entity.AgvInfoParams;
|
||||||
import org.opentcs.manage.entity.AgvStatus;
|
import org.opentcs.manage.entity.AgvStatus;
|
||||||
@ -41,7 +45,7 @@ public class AdapterManage {
|
|||||||
/**
|
/**
|
||||||
* 设置自动关闭适配器时间阈值,单位:毫秒
|
* 设置自动关闭适配器时间阈值,单位:毫秒
|
||||||
*/
|
*/
|
||||||
private final Long AUTO_CLOSE_TIME = 2000L;
|
private static final Long AUTO_CLOSE_TIME = 2000L;
|
||||||
/**
|
/**
|
||||||
* 记录通讯适配器数据,实现异步不阻塞更新车辆模型
|
* 记录通讯适配器数据,实现异步不阻塞更新车辆模型
|
||||||
* 基于线程安全HASHMAP
|
* 基于线程安全HASHMAP
|
||||||
@ -54,10 +58,12 @@ public class AdapterManage {
|
|||||||
private static final String IP = GuestUserCredentials.IP;
|
private static final String IP = GuestUserCredentials.IP;
|
||||||
private static final Integer PORT = GuestUserCredentials.PORT;
|
private static final Integer PORT = GuestUserCredentials.PORT;
|
||||||
|
|
||||||
|
private int i = 1;
|
||||||
|
|
||||||
|
|
||||||
//开启定时任务
|
//开启定时任务
|
||||||
public void START() {
|
public void START() {
|
||||||
scheduler.scheduleWithFixedDelay(task, 0, 500, TimeUnit.MILLISECONDS);
|
scheduler.scheduleWithFixedDelay(task, 5000, 500, TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//关闭定时任务
|
//关闭定时任务
|
||||||
@ -66,51 +72,88 @@ public class AdapterManage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Runnable task = () -> {
|
Runnable task = () -> {
|
||||||
kernel = new KernelCommunication(USER, PASSWORD, IP, PORT);
|
// kernel = new KernelCommunication(USER, PASSWORD, IP, PORT);
|
||||||
|
|
||||||
autoManageAdapterStatus();
|
// autoManageAdapterStatus();
|
||||||
updateAdapterVehicleModel();
|
// updateAdapterVehicleModel();
|
||||||
|
|
||||||
kernel.logout();
|
kernel.logout();
|
||||||
|
|
||||||
|
// System.out.println("end task");
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 自动管理通讯适配器
|
* 自动管理通讯适配器
|
||||||
*/
|
*/
|
||||||
private void autoManageAdapterStatus() {
|
private static boolean autoManageAdapterStatus(String name) {
|
||||||
Date date = new Date();
|
Date date = new Date();
|
||||||
long currentTime = date.getTime();
|
long currentTime = date.getTime();
|
||||||
|
|
||||||
adapterStatusMap.forEach((key, value) -> {
|
System.out.println("autoManageAdapterStatus: " + adapterStatusMap);
|
||||||
Long time = value.getTime();
|
|
||||||
AgvStatus agvStatus = new AgvStatus();
|
|
||||||
agvStatus.setTime(value.getTime());
|
|
||||||
agvStatus.setActionStatus(value.getActionStatus());
|
|
||||||
|
|
||||||
if (currentTime - time > AUTO_CLOSE_TIME) {
|
AgvStatus oldData = adapterStatusMap.get(name);
|
||||||
|
|
||||||
|
if (oldData == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
AgvStatus agvStatus = new AgvStatus();
|
||||||
|
agvStatus.setTime(oldData.getTime());
|
||||||
|
|
||||||
|
if (currentTime - oldData.getTime() > AUTO_CLOSE_TIME) {
|
||||||
|
System.out.println("adapterStatusMap first DISABLE");
|
||||||
agvStatus.setStatus(AdapterStatus.DISABLE);
|
agvStatus.setStatus(AdapterStatus.DISABLE);
|
||||||
} else {
|
} else {
|
||||||
|
System.out.println("adapterStatusMap first ENABLE");
|
||||||
agvStatus.setStatus(AdapterStatus.ENABLE);
|
agvStatus.setStatus(AdapterStatus.ENABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG.info("update the adapter: {} status:{}", key, value);
|
|
||||||
kernel.sendToAdapter(key, agvStatus);
|
|
||||||
|
|
||||||
if (agvStatus.getActionStatus()) {
|
|
||||||
//动作执行结束,修改数据
|
|
||||||
agvStatus.setActionStatus(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
//更新记录数据
|
//更新记录数据
|
||||||
adapterStatusMap.put(key, agvStatus);
|
adapterStatusMap.put(name, agvStatus);
|
||||||
});
|
|
||||||
|
return agvStatus.getStatus();
|
||||||
}
|
}
|
||||||
|
// private void autoManageAdapterStatus() {
|
||||||
|
// Date date = new Date();
|
||||||
|
// long currentTime = date.getTime();
|
||||||
|
//
|
||||||
|
// System.out.println("autoManageAdapterStatus: " + adapterStatusMap);
|
||||||
|
// adapterStatusMap.forEach((key, value) -> {
|
||||||
|
// System.out.println("adapterStatusMap first");
|
||||||
|
// Long time = value.getTime();
|
||||||
|
// AgvStatus agvStatus = new AgvStatus();
|
||||||
|
// agvStatus.setTime(value.getTime());
|
||||||
|
// agvStatus.setActionStatus(value.getActionStatus());
|
||||||
|
//
|
||||||
|
// if (currentTime - time > AUTO_CLOSE_TIME) {
|
||||||
|
// System.out.println("adapterStatusMap first DISABLE");
|
||||||
|
// agvStatus.setStatus(AdapterStatus.DISABLE);
|
||||||
|
// kernel.disableAdapter(key);
|
||||||
|
// } else {
|
||||||
|
// System.out.println("adapterStatusMap first ENABLE");
|
||||||
|
// agvStatus.setStatus(AdapterStatus.ENABLE);
|
||||||
|
// kernel.enableAdapter(key);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// LOG.info("update the adapter: {} status:{}", key, value);
|
||||||
|
//
|
||||||
|
// if (agvStatus.getActionStatus()) {
|
||||||
|
// kernel.sendToAdapter(key, agvStatus);
|
||||||
|
// //动作执行结束,修改数据
|
||||||
|
// agvStatus.setActionStatus(false);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// //更新记录数据
|
||||||
|
// adapterStatusMap.put(key, agvStatus);
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新适配器车辆模型
|
* 更新适配器车辆模型
|
||||||
*/
|
*/
|
||||||
private void updateAdapterVehicleModel() {
|
private void updateAdapterVehicleModel() {
|
||||||
adapterDataMap.forEach((key, value) -> {
|
adapterDataMap.forEach((key, value) -> {
|
||||||
|
System.out.println("updateAdapterVehicleModel first");
|
||||||
kernel.sendToAdapter(key, value);
|
kernel.sendToAdapter(key, value);
|
||||||
adapterDataMap.remove(key);
|
adapterDataMap.remove(key);
|
||||||
});
|
});
|
||||||
@ -125,45 +168,48 @@ public class AdapterManage {
|
|||||||
long time = date.getTime();
|
long time = date.getTime();
|
||||||
|
|
||||||
AgvStatus newAgvStatus = new AgvStatus();
|
AgvStatus newAgvStatus = new AgvStatus();
|
||||||
|
|
||||||
if (adapterStatusMap.containsKey(name)) {
|
|
||||||
//已记录,只更新时间
|
|
||||||
AgvStatus agvStatus = adapterStatusMap.get(name);
|
|
||||||
newAgvStatus.setTime(time);
|
newAgvStatus.setTime(time);
|
||||||
newAgvStatus.setStatus(agvStatus.getStatus());
|
|
||||||
|
if (!adapterStatusMap.isEmpty() && adapterStatusMap.containsKey(name)) {
|
||||||
|
//已记录,只更新时间
|
||||||
|
newAgvStatus.setStatus(AdapterStatus.ENABLE);
|
||||||
} else {
|
} else {
|
||||||
//未记录,初始化
|
//未记录,初始化
|
||||||
newAgvStatus.setTime(time);
|
|
||||||
newAgvStatus.setStatus(AdapterStatus.DISABLE);
|
newAgvStatus.setStatus(AdapterStatus.DISABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
adapterStatusMap.put(name, newAgvStatus);
|
adapterStatusMap.put(name, newAgvStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean getAdapterStatus(String name) {
|
||||||
|
|
||||||
|
AgvStatus agvStatus = adapterStatusMap.get(name);
|
||||||
|
if (agvStatus != null) {
|
||||||
|
return agvStatus.getStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置动作完成状态
|
* 设置动作完成状态
|
||||||
* @param name 车辆名称
|
* @param name 车辆名称
|
||||||
*/
|
*/
|
||||||
public static void setActionStatus(String name) {
|
// public static void setActionStatus(String name) {
|
||||||
AgvStatus agvStatus = adapterStatusMap.get(name);
|
// AgvStatus agvStatus = adapterStatusMap.get(name);
|
||||||
agvStatus.setActionStatus(true);
|
// agvStatus.setActionStatus(true);
|
||||||
adapterStatusMap.put(name, agvStatus);
|
// adapterStatusMap.put(name, agvStatus);
|
||||||
}
|
// }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 记录对应通讯适配器最后一次上报数据
|
* 记录对应通讯适配器最后一次上报数据
|
||||||
* @param name 车辆名称
|
* @param name 车辆名称
|
||||||
* @param data 数据
|
* @param data 数据
|
||||||
*/
|
*/
|
||||||
public static void setAdapterVehicleModel(String name, String data) {
|
public static AgvInfo setAdapterVehicleModel(String name, String data) {
|
||||||
|
|
||||||
JSONObject jsonObject = JSON.parseObject(data);
|
JSONObject jsonObject = JSON.parseObject(data);
|
||||||
|
|
||||||
//因为是异步上报。所以需要校验序列号。防止旧数据覆盖新数据
|
|
||||||
if (adapterDataMap.get(name).getSerial_num() > jsonObject.getInteger("serial_num")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
AgvInfo agvInfo = new AgvInfo();
|
AgvInfo agvInfo = new AgvInfo();
|
||||||
agvInfo.setSender(jsonObject.getString("sender"));
|
agvInfo.setSender(jsonObject.getString("sender"));
|
||||||
agvInfo.setReceiver(jsonObject.getString("receiver"));
|
agvInfo.setReceiver(jsonObject.getString("receiver"));
|
||||||
@ -172,7 +218,7 @@ public class AdapterManage {
|
|||||||
agvInfo.setTime(jsonObject.getString("time"));
|
agvInfo.setTime(jsonObject.getString("time"));
|
||||||
agvInfo.setParams(getAgvInfoParams(jsonObject.getString("params")));
|
agvInfo.setParams(getAgvInfoParams(jsonObject.getString("params")));
|
||||||
|
|
||||||
adapterDataMap.put(name, agvInfo);
|
return agvInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static AgvInfoParams getAgvInfoParams(String paramsStr) {
|
private static AgvInfoParams getAgvInfoParams(String paramsStr) {
|
||||||
@ -202,4 +248,13 @@ public class AdapterManage {
|
|||||||
Boolean DISABLE = false;
|
Boolean DISABLE = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void test() {
|
||||||
|
KernelServicePortal build = new KernelServicePortalBuilder(USER, PASSWORD).build();
|
||||||
|
build.login(IP, PORT);
|
||||||
|
VehicleService vehicleService = build.getVehicleService();
|
||||||
|
Vehicle vehicle = vehicleService.fetchObject(Vehicle.class, "v1");
|
||||||
|
vehicleService.enableCommAdapter(vehicle.getReference());
|
||||||
|
vehicleService.sendCommAdapterMessage(vehicle.getReference(), "test");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,13 @@
|
|||||||
|
package org.opentcs.manage.entity;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class ActionStatus {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 动作执行状态,true表示执行完成,false表示执行中
|
||||||
|
*/
|
||||||
|
private Boolean status;
|
||||||
|
|
||||||
|
}
|
@ -13,9 +13,5 @@ public class AgvStatus {
|
|||||||
* 通讯适配器状态:trye=开启,false=关闭
|
* 通讯适配器状态:trye=开启,false=关闭
|
||||||
*/
|
*/
|
||||||
private Boolean status;
|
private Boolean status;
|
||||||
/**
|
|
||||||
* 动作状态:true=上报状态,false=无任务
|
|
||||||
*/
|
|
||||||
private Boolean actionStatus;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,20 @@
|
|||||||
package org.opentcs.park;
|
package org.opentcs.park;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
|
||||||
import org.opentcs.park.entity.Park;
|
import org.opentcs.park.entity.Park;
|
||||||
|
|
||||||
public class ParkStrategy {
|
public class ParkStrategy {
|
||||||
|
|
||||||
private static ArrayList<Park> AllPark = new ArrayList<>();
|
private static ArrayList<Park> allPark = new ArrayList<>();
|
||||||
|
|
||||||
|
|
||||||
public static void setPark(Park park) {
|
public static void setPark(Park park) {
|
||||||
AllPark.add(park);
|
allPark.add(park);
|
||||||
printPark();
|
printPark();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void printPark() {
|
private static void printPark() {
|
||||||
for (Park park : AllPark) {
|
for (Park park : allPark) {
|
||||||
System.out.println("print park:" + park.getName() + ", status:" + park.getStatus());
|
System.out.println("print park:" + park.getName() + ", status:" + park.getStatus());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
package org.opentcs.traffic;
|
package org.opentcs.traffic;
|
||||||
|
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
import org.opentcs.traffic.common.AvoidanceAlgorithm;
|
import org.opentcs.traffic.common.AvoidanceAlgorithm;
|
||||||
import org.opentcs.traffic.common.ContourAlgorithm;
|
import org.opentcs.traffic.common.ContourAlgorithm;
|
||||||
import org.opentcs.traffic.common.ResourceLock;
|
import org.opentcs.traffic.common.ResourceLock;
|
||||||
|
import org.opentcs.util.KernelCommunication;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@ -29,6 +33,26 @@ public class TrafficControl {
|
|||||||
* 交管避让权重算法
|
* 交管避让权重算法
|
||||||
*/
|
*/
|
||||||
private static final AvoidanceAlgorithm avoidanceAlgorithm = new AvoidanceAlgorithm();
|
private static final AvoidanceAlgorithm avoidanceAlgorithm = new AvoidanceAlgorithm();
|
||||||
|
/**
|
||||||
|
* 创建调度线程池(单线程)
|
||||||
|
*/
|
||||||
|
private static final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
|
||||||
|
|
||||||
|
//开启定时任务
|
||||||
|
public void START() {
|
||||||
|
scheduler.scheduleWithFixedDelay(task, 0, 500, TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
//关闭定时任务
|
||||||
|
public void STOP() {
|
||||||
|
scheduler.shutdownNow();
|
||||||
|
}
|
||||||
|
|
||||||
|
Runnable task = () -> {
|
||||||
|
//轮廓避障算法
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 交通管制策略
|
* 交通管制策略
|
||||||
@ -41,25 +65,25 @@ public class TrafficControl {
|
|||||||
public static boolean trafficControlStrategy(String vehiclePosition, String finalOccupiedPosition, String resource, String type) {
|
public static boolean trafficControlStrategy(String vehiclePosition, String finalOccupiedPosition, String resource, String type) {
|
||||||
|
|
||||||
//进行资源占用
|
//进行资源占用
|
||||||
boolean lockStatus = resourceLock.trafficControlOccupy(vehiclePosition, finalOccupiedPosition, resource, type);
|
// boolean lockStatus = resourceLock.trafficControlOccupy(vehiclePosition, finalOccupiedPosition, resource, type);
|
||||||
if (!lockStatus) {
|
// if (!lockStatus) {
|
||||||
LOG.debug("trafficControlStrategy Failed to lock resource: {} type: {}", resource, type);
|
// LOG.debug("trafficControlStrategy Failed to lock resource: {} type: {}", resource, type);
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
|
|
||||||
//todo: 轮廓算法,判断下一个点位是否会被其他车辆干涉
|
//todo: 轮廓算法,判断下一个点位是否会被其他车辆干涉
|
||||||
boolean contourStatus = contourAlgorithm.interferenceDetection();
|
// boolean contourStatus = contourAlgorithm.interferenceDetection();
|
||||||
if (!contourStatus) {
|
// if (!contourStatus) {
|
||||||
LOG.debug("trafficControlStrategy Contour algorithm failed: resource: {} type: {}", resource, type);
|
// LOG.debug("trafficControlStrategy Contour algorithm failed: resource: {} type: {}", resource, type);
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
|
|
||||||
//todo: 订单避让算法,根据权重计算车辆优先级执行避让算法
|
//todo: 订单避让算法,根据权重计算车辆优先级执行避让算法
|
||||||
boolean avoidanceStatus = avoidanceAlgorithm.weightCalculation();
|
// boolean avoidanceStatus = avoidanceAlgorithm.weightCalculation();
|
||||||
if (!avoidanceStatus) {
|
// if (!avoidanceStatus) {
|
||||||
LOG.debug("trafficControlStrategy Avoidance algorithm failed: resource: {} type: {}", resource, type);
|
// LOG.debug("trafficControlStrategy Avoidance algorithm failed: resource: {} type: {}", resource, type);
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
|
|
||||||
//有所有校验通过,返回true
|
//有所有校验通过,返回true
|
||||||
return true;
|
return true;
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package org.opentcs.traffic.common;
|
package org.opentcs.traffic.common;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import org.opentcs.traffic.entity.VehicleAttr;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -0,0 +1,100 @@
|
|||||||
|
package org.opentcs.traffic.common;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import org.locationtech.jts.geom.Coordinate;
|
||||||
|
import org.locationtech.jts.geom.GeometryFactory;
|
||||||
|
import org.locationtech.jts.geom.Polygon;
|
||||||
|
import org.opentcs.traffic.entity.VehicleAttr;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author xuzhiheng
|
||||||
|
* @desc 车辆轮廓检测
|
||||||
|
*/
|
||||||
|
public class VehicleCollisionAvoidance {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LOG
|
||||||
|
*/
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(VehicleCollisionAvoidance.class);
|
||||||
|
/**
|
||||||
|
* 车辆对象轮廓避障信息集合: key:车辆名称 value:车辆对象轮廓信息
|
||||||
|
*/
|
||||||
|
private static ArrayList<VehicleAttr> vehicleAttrs = new ArrayList<>();
|
||||||
|
/**
|
||||||
|
* 两台车之间最小距离
|
||||||
|
*/
|
||||||
|
private final Integer minDistance = 100;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 轮廓避障检测
|
||||||
|
* @param vehicleName 当前车辆名称
|
||||||
|
*/
|
||||||
|
public void interferenceDetection(String vehicleName) {
|
||||||
|
|
||||||
|
GeometryFactory geometryFactory = new GeometryFactory();
|
||||||
|
|
||||||
|
//计算当前车辆的
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Vehicle {
|
||||||
|
private final Long x; // 中心X坐标(米)
|
||||||
|
private final Long y; // 中心Y坐标(米)
|
||||||
|
private final double angle; // 方向角(弧度,0弧度指向东)
|
||||||
|
private final Integer length; // 长度(米)
|
||||||
|
private final Integer width; // 宽度(米)
|
||||||
|
private final Coordinate[] vertices; // 四个顶点坐标
|
||||||
|
|
||||||
|
public Vehicle(Long x, Long y, double angle, Integer length, Integer width) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.angle = angle;
|
||||||
|
this.length = length;
|
||||||
|
this.width = width;
|
||||||
|
this.vertices = calculateVertices();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算旋转矩形的四个顶点
|
||||||
|
*/
|
||||||
|
private Coordinate[] calculateVertices() {
|
||||||
|
double halfLength = length / 2;
|
||||||
|
double halfWidth = width / 2;
|
||||||
|
double cosTheta = Math.cos(angle);
|
||||||
|
double sinTheta = Math.sin(angle);
|
||||||
|
|
||||||
|
return new Coordinate[]{
|
||||||
|
// 顶点1
|
||||||
|
new Coordinate(
|
||||||
|
x + halfLength * cosTheta - halfWidth * sinTheta,
|
||||||
|
y + halfLength * sinTheta + halfWidth * cosTheta
|
||||||
|
),
|
||||||
|
// 顶点2
|
||||||
|
new Coordinate(
|
||||||
|
x - halfLength * cosTheta - halfWidth * sinTheta,
|
||||||
|
y - halfLength * sinTheta + halfWidth * cosTheta
|
||||||
|
),
|
||||||
|
// 顶点3
|
||||||
|
new Coordinate(
|
||||||
|
x - halfLength * cosTheta + halfWidth * sinTheta,
|
||||||
|
y - halfLength * sinTheta - halfWidth * cosTheta
|
||||||
|
),
|
||||||
|
// 顶点4
|
||||||
|
new Coordinate(
|
||||||
|
x + halfLength * cosTheta + halfWidth * sinTheta,
|
||||||
|
y + halfLength * sinTheta - halfWidth * cosTheta
|
||||||
|
)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转换为JTS多边形
|
||||||
|
*/
|
||||||
|
public Polygon toPolygon(GeometryFactory geomFactory) {
|
||||||
|
return geomFactory.createPolygon(vertices);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package org.opentcs.traffic.entity;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.opentcs.data.model.Pose;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author xuzhiheng
|
||||||
|
* @desc 车辆属性,用于计算轮廓避障
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class VehicleAttr {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 车辆名称
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
/**
|
||||||
|
* 长度/cm(单位厘米)
|
||||||
|
*/
|
||||||
|
private Integer length;
|
||||||
|
/**
|
||||||
|
* 宽度/cm(单位厘米)
|
||||||
|
*/
|
||||||
|
private Integer width;
|
||||||
|
/**
|
||||||
|
* 车辆姿态
|
||||||
|
*/
|
||||||
|
private Pose pose;
|
||||||
|
|
||||||
|
}
|
@ -34,7 +34,34 @@ public class KernelCommunication {
|
|||||||
throw new ObjectUnknownException("sendToAdapter Unknown vehicle: " + name);
|
throw new ObjectUnknownException("sendToAdapter Unknown vehicle: " + name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
System.out.println("sendToAdapter: " + message);
|
||||||
vehicleService.sendCommAdapterMessage(vehicle.getReference(), message);
|
vehicleService.sendCommAdapterMessage(vehicle.getReference(), message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启用车辆通讯适配器
|
||||||
|
* @param name 车辆名称
|
||||||
|
*/
|
||||||
|
public void enableAdapter(String name) {
|
||||||
|
VehicleService vehicleService = servicePortal.getVehicleService();
|
||||||
|
Vehicle vehicle = vehicleService.fetchObject(Vehicle.class, name);
|
||||||
|
if (vehicle == null) {
|
||||||
|
throw new ObjectUnknownException("enableAdapter Unknown vehicle: " + name);
|
||||||
|
}
|
||||||
|
vehicleService.enableCommAdapter(vehicle.getReference());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 禁用车辆通讯适配器
|
||||||
|
* @param name 车辆名称
|
||||||
|
*/
|
||||||
|
public void disableAdapter(String name) {
|
||||||
|
VehicleService vehicleService = servicePortal.getVehicleService();
|
||||||
|
Vehicle vehicle = vehicleService.fetchObject(Vehicle.class, name);
|
||||||
|
if (vehicle == null) {
|
||||||
|
throw new ObjectUnknownException("disableAdapter Unknown vehicle: " + name);
|
||||||
|
}
|
||||||
|
vehicleService.disableCommAdapter(vehicle.getReference());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -37,6 +37,8 @@ import org.opentcs.kernel.extensions.servicewebapi.v1.binding.PostVehicleRoutesR
|
|||||||
import org.opentcs.kernel.extensions.servicewebapi.v1.binding.PutVehicleAllowedOrderTypesTO;
|
import org.opentcs.kernel.extensions.servicewebapi.v1.binding.PutVehicleAllowedOrderTypesTO;
|
||||||
import org.opentcs.kernel.extensions.servicewebapi.v1.binding.PutVehicleEnergyLevelThresholdSetTO;
|
import org.opentcs.kernel.extensions.servicewebapi.v1.binding.PutVehicleEnergyLevelThresholdSetTO;
|
||||||
import org.opentcs.manage.AdapterManage;
|
import org.opentcs.manage.AdapterManage;
|
||||||
|
import org.opentcs.manage.entity.ActionStatus;
|
||||||
|
import org.opentcs.manage.entity.AgvInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles requests related to vehicles.
|
* Handles requests related to vehicles.
|
||||||
@ -69,22 +71,38 @@ public class VehicleHandler {
|
|||||||
* 接收平台异步回调处理
|
* 接收平台异步回调处理
|
||||||
*/
|
*/
|
||||||
public void postReceiveCallback(Object data) {
|
public void postReceiveCallback(Object data) {
|
||||||
System.out.println("jsonObject-----ssss: " + data.toString());
|
// System.out.println("jsonObject-----ssss: " + data.toString());
|
||||||
|
|
||||||
//截取平台响应的字符串
|
//截取平台响应的字符串
|
||||||
// String jsonStr = data.toString().split("=", 2)[1];
|
String jsonStr = data.toString().split("=", 2)[1];
|
||||||
String jsonStr = data.toString();
|
// String jsonStr = data.toString();
|
||||||
JSONObject jsonObject = JSON.parseObject(jsonStr);
|
JSONObject jsonObject = JSON.parseObject(jsonStr);
|
||||||
String name = jsonObject.getString("name");
|
String name = jsonObject.getString("vehicle_name");
|
||||||
Integer type = jsonObject.getInteger("type");
|
Integer type = jsonObject.getInteger("type");
|
||||||
|
|
||||||
|
Vehicle vehicle = vehicleService.fetchObject(Vehicle.class, name);
|
||||||
|
if (vehicle == null) {
|
||||||
|
throw new ObjectUnknownException("postReceiveCallback Unknown vehicle: " + name);
|
||||||
|
}
|
||||||
|
|
||||||
//将数据更新到线程安全的集合中,防止线程阻塞
|
//将数据更新到线程安全的集合中,防止线程阻塞
|
||||||
AdapterManage.setAdapterStatus(name);
|
AdapterManage.setAdapterStatus(name);
|
||||||
if (type == 1) {
|
|
||||||
AdapterManage.setAdapterVehicleModel(name, jsonStr);
|
if (AdapterManage.getAdapterStatus(name)) {
|
||||||
} else if (type == 5) {
|
vehicleService.enableCommAdapter(vehicle.getReference());
|
||||||
|
} else {
|
||||||
|
//todo 关闭暂时有问题
|
||||||
|
vehicleService.disableCommAdapter(vehicle.getReference());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == 1) { //上报agv详细信息
|
||||||
|
AgvInfo agvInfo = AdapterManage.setAdapterVehicleModel(name, jsonStr);
|
||||||
|
vehicleService.sendCommAdapterMessage(vehicle.getReference(), agvInfo);
|
||||||
|
} else if (type == 5) { //上报动作完成
|
||||||
//动作完成上报
|
//动作完成上报
|
||||||
AdapterManage.setActionStatus(name);
|
ActionStatus actionStatus = new ActionStatus();
|
||||||
|
actionStatus.setStatus(true);
|
||||||
|
vehicleService.sendCommAdapterMessage(vehicle.getReference(), actionStatus);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,6 @@ import static java.util.Objects.requireNonNull;
|
|||||||
import com.google.common.util.concurrent.Uninterruptibles;
|
import com.google.common.util.concurrent.Uninterruptibles;
|
||||||
import com.google.inject.Provider;
|
import com.google.inject.Provider;
|
||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -15,10 +14,8 @@ import java.util.concurrent.ScheduledExecutorService;
|
|||||||
import java.util.concurrent.Semaphore;
|
import java.util.concurrent.Semaphore;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import org.opentcs.access.Kernel;
|
import org.opentcs.access.Kernel;
|
||||||
import org.opentcs.access.Kernel.State;
|
|
||||||
import org.opentcs.access.KernelStateTransitionEvent;
|
import org.opentcs.access.KernelStateTransitionEvent;
|
||||||
import org.opentcs.access.LocalKernel;
|
import org.opentcs.access.LocalKernel;
|
||||||
import org.opentcs.communication.mqtt.MqttBrokerServer;
|
|
||||||
import org.opentcs.components.kernel.KernelExtension;
|
import org.opentcs.components.kernel.KernelExtension;
|
||||||
import org.opentcs.components.kernel.services.NotificationService;
|
import org.opentcs.components.kernel.services.NotificationService;
|
||||||
import org.opentcs.customizations.ApplicationEventBus;
|
import org.opentcs.customizations.ApplicationEventBus;
|
||||||
@ -73,14 +70,10 @@ public class StandardKernel
|
|||||||
* The kernel implementing the actual functionality for the current mode.
|
* The kernel implementing the actual functionality for the current mode.
|
||||||
*/
|
*/
|
||||||
private KernelState kernelState;
|
private KernelState kernelState;
|
||||||
/**
|
|
||||||
* MQTT 服务
|
|
||||||
*/
|
|
||||||
private MqttBrokerServer mqttBrokerServer = new MqttBrokerServer();
|
|
||||||
/**
|
/**
|
||||||
* 通讯适配器管理类
|
* 通讯适配器管理类
|
||||||
*/
|
*/
|
||||||
private AdapterManage adapterManage = new AdapterManage();
|
private final AdapterManage adapterManage = new AdapterManage();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new kernel.
|
* Creates a new kernel.
|
||||||
@ -122,14 +115,14 @@ public class StandardKernel
|
|||||||
//开启MQTT服务
|
//开启MQTT服务
|
||||||
// mqttBrokerServer.startMqtt();
|
// mqttBrokerServer.startMqtt();
|
||||||
|
|
||||||
//开启通讯适配器自动管理
|
|
||||||
adapterManage.START();
|
|
||||||
LOG.info("Communication adapter auto management started successfully");
|
|
||||||
|
|
||||||
initialized = true;
|
initialized = true;
|
||||||
LOG.debug("Starting kernel thread");
|
LOG.debug("Starting kernel thread");
|
||||||
Thread kernelThread = new Thread(this, "kernelThread");
|
Thread kernelThread = new Thread(this, "kernelThread");
|
||||||
kernelThread.start();
|
kernelThread.start();
|
||||||
|
|
||||||
|
//开启通讯适配器自动管理
|
||||||
|
// adapterManage.START();
|
||||||
|
// LOG.info("Communication adapter auto management started successfully");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -149,8 +142,8 @@ public class StandardKernel
|
|||||||
//关闭MQTT服务
|
//关闭MQTT服务
|
||||||
// mqttBrokerServer.stopMqtt();
|
// mqttBrokerServer.stopMqtt();
|
||||||
|
|
||||||
//关闭通讯适配器管理类
|
//关闭通讯适配器自动管理
|
||||||
adapterManage.STOP();
|
// adapterManage.STOP();
|
||||||
|
|
||||||
initialized = false;
|
initialized = false;
|
||||||
terminationSemaphore.release();
|
terminationSemaphore.release();
|
||||||
|
@ -1385,14 +1385,6 @@ public class PlantModelManager
|
|||||||
private Point createPoint(PointCreationTO to)
|
private Point createPoint(PointCreationTO to)
|
||||||
throws ObjectExistsException {
|
throws ObjectExistsException {
|
||||||
// Get a unique ID for the new point and create an instance.
|
// Get a unique ID for the new point and create an instance.
|
||||||
if (to.getType() == Point.Type.PARK_POSITION) {
|
|
||||||
//是休息点,记录
|
|
||||||
Park park = new Park();
|
|
||||||
park.setName(to.getName());
|
|
||||||
park.setStatus(false);
|
|
||||||
ParkStrategy.setPark(park);
|
|
||||||
}
|
|
||||||
|
|
||||||
Point newPoint = new Point(to.getName())
|
Point newPoint = new Point(to.getName())
|
||||||
.withPose(new Pose(to.getPose().getPosition(), to.getPose().getOrientationAngle()))
|
.withPose(new Pose(to.getPose().getPosition(), to.getPose().getOrientationAngle()))
|
||||||
.withType(to.getType())
|
.withType(to.getType())
|
||||||
|
Loading…
Reference in New Issue
Block a user