Browse Source

Merge remote-tracking branch 'origin/master'

master
lizw-2015 6 months ago
parent
commit
41c1cdfbdc
  1. 4
      servo/src/main/java/com/galaxis/rcs/RCSService.java
  2. 9
      servo/src/main/java/com/galaxis/rcs/connector/cl2/Cl2DeviceConnector.java
  3. 56
      servo/src/main/java/com/galaxis/rcs/plan/PlanTaskSequence.java
  4. 20
      servo/src/main/java/com/galaxis/rcs/ptr/AmrMessageHandler.java
  5. 82
      servo/src/main/java/com/galaxis/rcs/ptr/AmrTaskMode.java
  6. 91
      servo/src/main/java/com/galaxis/rcs/ptr/PtrMqttClient.java
  7. 1
      servo/src/main/java/com/yvan/logisticsEnv/EnvPayload.java
  8. 2
      servo/src/main/java/com/yvan/logisticsEnv/EnvStartParam.java
  9. 2
      servo/src/main/java/com/yvan/logisticsModel/LogisticsRuntime.java
  10. 2
      servo/src/main/java/com/yvan/logisticsModel/PtrAgvDeviceTask.java
  11. 133
      servo/src/main/java/com/yvan/logisticsModel/PtrAgvItem.java

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

@ -28,6 +28,8 @@ import org.clever.data.jdbc.DaoFactory;
import org.clever.data.jdbc.QueryDSL; import org.clever.data.jdbc.QueryDSL;
import org.clever.data.jdbc.querydsl.utils.QueryDslUtils; import org.clever.data.jdbc.querydsl.utils.QueryDslUtils;
import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.util.Map; import java.util.Map;
import static com.galaxis.rcs.common.query.QLccEnvInfo.lccEnvInfo; import static com.galaxis.rcs.common.query.QLccEnvInfo.lccEnvInfo;
@ -52,6 +54,7 @@ public class RCSService {
* 加载所有自动启动的环境和楼层数据 * 加载所有自动启动的环境和楼层数据
* 并启动对应的环境 * 并启动对应的环境
*/ */
@SneakyThrows
private void createAutoStartEnv() { private void createAutoStartEnv() {
QueryDSL queryDSL = DaoFactory.getQueryDSL(); QueryDSL queryDSL = DaoFactory.getQueryDSL();
var list = queryDSL.select(QueryDslUtils.linkedMap( var list = queryDSL.select(QueryDslUtils.linkedMap(
@ -98,6 +101,7 @@ public class RCSService {
param.setTimeRate(1); param.setTimeRate(1);
param.setVirtual(false); param.setVirtual(false);
param.setEnvPayload(envPayload); param.setEnvPayload(envPayload);
param.setClientId(InetAddress.getLocalHost().getHostName());
runtime.start(param); runtime.start(param);
} }

9
servo/src/main/java/com/galaxis/rcs/connector/cl2/Cl2DeviceConnector.java

@ -27,11 +27,10 @@ public class Cl2DeviceConnector {
} }
public void sendTask(String vehicleId, RcsTaskMessage rcsTaskMessage) throws MqttException, JsonProcessingException { public void sendTask(String vehicleId, RcsTaskMessage rcsTaskMessage) throws MqttException, JsonProcessingException {
var list = Splitter.on("\n").splitToList(JsonWrapper.toJsonPretty(rcsTaskMessage)); // var list = Splitter.on("\n").splitToList(JsonWrapper.toJsonPretty(rcsTaskMessage));
String[] ar = new String[list.size()]; // String[] ar = new String[list.size()];
list.toArray(ar); // list.toArray(ar);
BannerUtils.printConfig(log, "CL2 发送报文", ar); // BannerUtils.printConfig(log, "CL2 发送报文", ar);
amrMessageHandler.sendCmdTask(vehicleId, rcsTaskMessage); amrMessageHandler.sendCmdTask(vehicleId, rcsTaskMessage);
} }

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

@ -5,8 +5,12 @@ import com.galaxis.rcs.common.entity.RcsTaskBiz;
import com.galaxis.rcs.common.entity.RcsTaskPlan; import com.galaxis.rcs.common.entity.RcsTaskPlan;
import com.galaxis.rcs.common.enums.PlanTaskStatus; import com.galaxis.rcs.common.enums.PlanTaskStatus;
import com.galaxis.rcs.common.enums.PlanTaskType; import com.galaxis.rcs.common.enums.PlanTaskType;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.yvan.logisticsModel.LogisticsRuntime; import com.yvan.logisticsModel.LogisticsRuntime;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.clever.core.BannerUtils;
import org.clever.core.id.SnowFlake; import org.clever.core.id.SnowFlake;
import org.clever.core.json.JsonWrapper; import org.clever.core.json.JsonWrapper;
@ -15,6 +19,7 @@ import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@Slf4j
public class PlanTaskSequence { public class PlanTaskSequence {
@JsonIgnore @JsonIgnore
public static final SnowFlake snowFlake = new SnowFlake(); public static final SnowFlake snowFlake = new SnowFlake();
@ -27,7 +32,6 @@ public class PlanTaskSequence {
public String lastWayPointId; public String lastWayPointId;
public Float lastRotationAngle = null; public Float lastRotationAngle = null;
public boolean isFinished = false;
public String lastLoadLpn = ""; public String lastLoadLpn = "";
public PlanTaskSequence(String executorId, LogisticsRuntime logisticsRuntime, RcsTaskBiz bizTask, String createBy) { public PlanTaskSequence(String executorId, LogisticsRuntime logisticsRuntime, RcsTaskBiz bizTask, String createBy) {
@ -103,7 +107,6 @@ public class PlanTaskSequence {
// 添加完成动作 // 添加完成动作
public RcsTaskPlan addFinish() { public RcsTaskPlan addFinish() {
RcsTaskPlan task = this.createTaskPlanEntity(PlanTaskType.FINISH.toString()); RcsTaskPlan task = this.createTaskPlanEntity(PlanTaskType.FINISH.toString());
this.isFinished = true;
return task; return task;
} }
@ -139,10 +142,59 @@ public class PlanTaskSequence {
taskStr = "FINISH"; taskStr = "FINISH";
break; break;
} }
taskStr = taskStr + " STATE:" + task.getPlanTaskStatus();
list.add(taskStr); list.add(taskStr);
} }
jw.set("items", list); jw.set("items", list);
return jw.getInnerMap(); return jw.getInnerMap();
} }
/**
* 是不是所有的任务都完成了
*/
public boolean isAllCompleted() {
boolean isAllComplete = true;
for (RcsTaskPlan task : taskList) {
if (PlanTaskType.valueOf(task.getPlanType()) != PlanTaskType.FINISH) {
if (!PlanTaskStatus.FINISHED.toString().equals(task.getPlanTaskStatus())) {
isAllComplete = false;
break;
}
}
}
return isAllComplete;
}
public RcsTaskPlan getByPlanTaskId(Long planTaskId) {
for (RcsTaskPlan task : taskList) {
if (task.getPlanTaskId().equals(planTaskId)) {
return task;
}
}
return null;
}
@SneakyThrows
public void savePlanTask(RcsTaskPlan planTask) {
//TODO: 保存数据库
var jw = new JsonWrapper(planTask);
jw.set("isAllCompleted", this.isAllCompleted());
var list = Splitter.on("\n").splitToList(jw.toString());
String[] ar = new String[list.size()];
list.toArray(ar);
// log.info("3-Received message: " + json);
BannerUtils.printConfig(log, "保存业务任务 planTask", ar);
}
public boolean isEmpty() {
return this.taskList.isEmpty();
}
public int size() {
return this.taskList.size();
}
} }

20
servo/src/main/java/com/galaxis/rcs/ptr/AmrMessageHandler.java

@ -14,17 +14,15 @@ import com.yvan.logisticsModel.LogisticsRuntime;
import com.yvan.logisticsModel.PtrAgvItem; import com.yvan.logisticsModel.PtrAgvItem;
import lombok.SneakyThrows; import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.clever.core.AppContextHolder;
import org.clever.core.BannerUtils; import org.clever.core.BannerUtils;
import org.clever.core.json.JsonWrapper; import org.clever.core.json.JsonWrapper;
import org.clever.core.mapper.BeanCopyUtils; import org.clever.core.mapper.BeanCopyUtils;
import org.clever.data.redis.Redis; import org.clever.data.redis.Redis;
import org.eclipse.paho.mqttv5.client.MqttClient; import org.clever.data.redis.RedisAdmin;
import org.eclipse.paho.mqttv5.common.MqttException; import org.eclipse.paho.mqttv5.common.MqttException;
import org.eclipse.paho.mqttv5.common.MqttMessage; import org.eclipse.paho.mqttv5.common.MqttMessage;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
@ -65,10 +63,10 @@ public class AmrMessageHandler {
private static final TypeReference<AmrMessage<AmrExceptionMessage>> typeRef20250Message = new TypeReference<AmrMessage<AmrExceptionMessage>>() { private static final TypeReference<AmrMessage<AmrExceptionMessage>> typeRef20250Message = new TypeReference<AmrMessage<AmrExceptionMessage>>() {
}; };
private static final Redis redis = AppContextHolder.getBean("defaultRedis", Redis.class, true); private static final Redis redis = RedisAdmin.getRedis();
public final LogisticsRuntime runtime; public final LogisticsRuntime runtime;
public volatile PtrMqttClient ptrMqttClient; private volatile PtrMqttClient ptrMqttClient;
public int getNewSeqNo() { public int getNewSeqNo() {
String redisKey = "lcc:rcs:" + runtime.projectUUID + ":" + runtime.envId + ":seqNo"; String redisKey = "lcc:rcs:" + runtime.projectUUID + ":" + runtime.envId + ":seqNo";
@ -84,8 +82,8 @@ public class AmrMessageHandler {
this.runtime = runtime; this.runtime = runtime;
} }
public void start(EnvPayload.MqttConfig mqttConfig) { public void start(EnvPayload.MqttConfig mqttConfig, String clientId) {
this.ptrMqttClient = new PtrMqttClient(this, mqttConfig); this.ptrMqttClient = new PtrMqttClient(this, mqttConfig, clientId);
} }
public void stop() { public void stop() {
@ -162,7 +160,7 @@ public class AmrMessageHandler {
break; break;
case AMR_HEARTBEAT: case AMR_HEARTBEAT:
AmrMessage<AmrHeartbeatMessage> heartbeatMessage = JacksonUtils.parse(json, typeRef20100Message); AmrMessage<AmrHeartbeatMessage> heartbeatMessage = JacksonUtils.parse(json, typeRef20100Message);
sendCmdHeartBeat(heartbeatMessage.content.VehicleId + ""); // sendCmdHeartBeat(heartbeatMessage.content.VehicleId + "");
handleHeartbeatMessage(agvItem, heartbeatMessage.content); handleHeartbeatMessage(agvItem, heartbeatMessage.content);
break; break;
case AMR_BOOT: case AMR_BOOT:
@ -209,7 +207,7 @@ public class AmrMessageHandler {
BannerUtils.printConfig(log, "MQTT 发送报文 [" + id + "] RcsMessageType." + RcsMessageType.fromValue(id) + " - " + RcsMessageType.fromValue(id).description, ar); BannerUtils.printConfig(log, "MQTT 发送报文 [" + id + "] RcsMessageType." + RcsMessageType.fromValue(id) + " - " + RcsMessageType.fromValue(id).description, ar);
} }
ptrMqttClient.client.publish(topic, payload.getBytes(StandardCharsets.UTF_8), 0, false); ptrMqttClient.publish(topic, payload);
} }
/** /**
@ -229,7 +227,7 @@ public class AmrMessageHandler {
baseMessage.content = rcsTaskMessage; baseMessage.content = rcsTaskMessage;
String json = JacksonUtils.toJson(baseMessage); String json = JacksonUtils.toJson(baseMessage);
log.info("sendCmd10010: {}", json); // log.info("sendCmd10010: {}", json);
// log.debug("Sending task to {}: {}", vehicleId, json); // log.debug("Sending task to {}: {}", vehicleId, json);
publish("/wcs_server/" + vehicleId, json, baseMessage.id); publish("/wcs_server/" + vehicleId, json, baseMessage.id);
@ -425,6 +423,7 @@ public class AmrMessageHandler {
// 这是源逻辑,CurLogicX / CurLogicY / CurDirection 需要到 PtrAgvItem 中更新, 因为要触发事件 // 这是源逻辑,CurLogicX / CurLogicY / CurDirection 需要到 PtrAgvItem 中更新, 因为要触发事件
agvItem.x = message.X; agvItem.x = message.X;
agvItem.y = message.Y; agvItem.y = message.Y;
agvItem.orientation = message.CurOrientation;
agvItem.updatePosition(message.CurLogicX, message.CurLogicY, message.CurDirection); agvItem.updatePosition(message.CurLogicX, message.CurLogicY, message.CurDirection);
} }
@ -479,6 +478,7 @@ public class AmrMessageHandler {
AmrMessage<AmrTaskStatusMessage<TaskModeChangeData>> taskModeChange = JacksonUtils.parse(json, typeRef20011_1Message); AmrMessage<AmrTaskStatusMessage<TaskModeChangeData>> taskModeChange = JacksonUtils.parse(json, typeRef20011_1Message);
AmrTaskStatusMessage<TaskModeChangeData> modeMessage = taskModeChange.content; AmrTaskStatusMessage<TaskModeChangeData> modeMessage = taskModeChange.content;
agvItem.updateDeviceTaskStatus((int) modeMessage.SeqNo, 0, 0, modeMessage.EventId); agvItem.updateDeviceTaskStatus((int) modeMessage.SeqNo, 0, 0, modeMessage.EventId);
agvItem.updateTaskMode(modeMessage.Info.TaskMode);
break; break;
case 4: case 4:
AmrMessage<AmrTaskStatusMessage<TaskCompletedData>> taskCompleted = JacksonUtils.parse(json, typeRef20011_4Message); AmrMessage<AmrTaskStatusMessage<TaskCompletedData>> taskCompleted = JacksonUtils.parse(json, typeRef20011_4Message);

82
servo/src/main/java/com/galaxis/rcs/ptr/AmrTaskMode.java

@ -0,0 +1,82 @@
package com.galaxis.rcs.ptr;
import com.google.common.collect.Maps;
import java.util.Collections;
import java.util.Map;
/**
* AMR 任务模式
*/
public enum AmrTaskMode {
/**
* 空闲模式
*/
AMR_FREE_MODE(0, "空闲模式"),
/**
* 初始化模式
*/
AMR_INIT_MODE(1, "初始化模式"),
/**
* 任务模式
*/
AMR_TASK_MODE(2, "任务模式"),
/**
* 单动作模式
*/
AMR_SINGLE_ACTION_MODE(3, "单动作模式"),
/**
* 手动模式
*/
AMR_MANUAL_MODE(4, "手动模式"),
/**
* 遥控器模式
*/
AMR_HANDSET_MODE(5, "遥控器模式"),
/**
* 充电模式
*/
AMR_CHARGE_MODE(6, "充电模式"),
/**
* 任务被中断模式
*/
AMR_TASK_INTERRUPT_MODE (7, "任务被中断模式"),
/**
* 自定义模式
*/
AMR_CUSTOMIZE_MODE(8, "自定义模式"),
/**
* 主程序退出关机或关服务时会进入这个模式
*/
AMR_SHUTDOWN_MODE(8, "主程序退出");
// 枚举值映射
private static final Map<Integer, AmrTaskMode> VALUE_MAP;
static {
Map<Integer, AmrTaskMode> map = Maps.newHashMap();
for (AmrTaskMode message : values()) {
map.put(message.value, message);
}
VALUE_MAP = Collections.unmodifiableMap(map);
}
public final int value;
public final String description;
AmrTaskMode(int value, String description) {
this.value = value;
this.description = description;
}
/**
* 从整数值获取对应的枚举
*
* @param value 整数值
* @return 对应的枚举如果找不到则返回 null
*/
public static AmrTaskMode fromValue(int value) {
return VALUE_MAP.get(value);
}
}

91
servo/src/main/java/com/galaxis/rcs/ptr/PtrMqttClient.java

@ -1,45 +1,92 @@
package com.galaxis.rcs.ptr; package com.galaxis.rcs.ptr;
import com.google.common.base.Splitter;
import com.yvan.logisticsEnv.EnvPayload; import com.yvan.logisticsEnv.EnvPayload;
import com.yvan.logisticsModel.LogisticsRuntime;
import lombok.SneakyThrows; import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.clever.core.BannerUtils; import org.clever.core.BannerUtils;
import org.clever.core.json.JsonWrapper;
import org.eclipse.paho.mqttv5.client.*; import org.eclipse.paho.mqttv5.client.*;
import org.eclipse.paho.mqttv5.common.MqttException; import org.eclipse.paho.mqttv5.common.MqttException;
import org.eclipse.paho.mqttv5.common.MqttMessage; import org.eclipse.paho.mqttv5.common.MqttMessage;
import org.eclipse.paho.mqttv5.common.packet.MqttProperties; import org.eclipse.paho.mqttv5.common.packet.MqttProperties;
import java.net.InetAddress;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.CountDownLatch;
@Slf4j @Slf4j
public class PtrMqttClient implements MqttCallback { public class PtrMqttClient implements MqttCallback {
public final AmrMessageHandler amrMessageHandler; public final AmrMessageHandler amrMessageHandler;
public final EnvPayload.MqttConfig mqttConfig; public final EnvPayload.MqttConfig mqttConfig;
public final MqttClient client; private final MqttClient clientForSend;
private final MqttClient client;
private final String clientId;
private CountDownLatch connectLatch = new CountDownLatch(1);
@SneakyThrows @SneakyThrows
public PtrMqttClient(AmrMessageHandler handler, EnvPayload.MqttConfig mqttConfig) { public PtrMqttClient(AmrMessageHandler handler, EnvPayload.MqttConfig mqttConfig, String clientId) {
this.amrMessageHandler = handler; this.amrMessageHandler = handler;
this.mqttConfig = mqttConfig; this.mqttConfig = mqttConfig;
this.clientId = clientId;
String brokerUrl = mqttConfig.getBrokerUrl(); String brokerUrl = mqttConfig.getBrokerUrl(); // "tcp://10.10.203.239:1885"
String username = mqttConfig.getUsername(); String username = mqttConfig.getUsername(); // admin
String password = mqttConfig.getPassword(); String password = mqttConfig.getPassword(); // admin
client = new MqttClient(brokerUrl, mqttConfig.getClientId());
client.setCallback(this);
clientForSend = new MqttClient(brokerUrl, clientId + "_send"); // String clientId = "LUOYIFAN-PC_send"
client = new MqttClient(brokerUrl, clientId); // String clientId = "LUOYIFAN-PC"
MqttConnectionOptions options = new MqttConnectionOptions(); MqttConnectionOptions options = new MqttConnectionOptions();
options.setServerURIs(new String[]{brokerUrl}); options.setServerURIs(new String[]{brokerUrl});
options.setAutomaticReconnect(true); // 启用自动重连 options.setAutomaticReconnect(true);
options.setUserName(username); options.setUserName(username);
options.setPassword(password.getBytes()); options.setPassword(password.getBytes());
options.setConnectionTimeout(1);
options.setKeepAliveInterval(20);
options.setExecutorServiceTimeout(1);
client.setCallback(this);
client.connect(options); client.connect(options);
clientForSend.connect(options);
connectLatch.await();
BannerUtils.printConfig(log, "MQTT 开启监听成功", new String[]{
"brokerUrl: " + brokerUrl,
"userName: " + username,
"clientId: " + clientId,
"topic: /agv_robot/status"});
client.subscribe("/agv_robot/status", 0); client.subscribe("/agv_robot/status", 0);
} }
@SneakyThrows
public void publish(String topic, String payloadString) {
MqttMessage message = new MqttMessage(payloadString.getBytes(StandardCharsets.UTF_8));
message.setQos(0);
message.setRetained(false);
if (this.clientForSend.isConnected()) {
this.clientForSend.publish(topic, message);
} else {
throw new RuntimeException("MQTT client is not connected, cannot publish message.");
}
log.info("Message published to topic {}: finish", topic);
}
@SneakyThrows
public static void main(String[] args) {
var config = new EnvPayload.MqttConfig();
config.setBrokerUrl("tcp://10.10.203.239:1885");
config.setUsername("admin");
config.setPassword("admin");
PtrMqttClient mqttClient = new PtrMqttClient(null, config, "LUOYIFAN-PC");
for (int i = 0; i < 100; i++) {
mqttClient.publish("/agv_robot/status", "Hello from Java " + i);
}
log.info("Message published successfully.");
}
@Override @Override
public void disconnected(MqttDisconnectResponse disconnectResponse) { public void disconnected(MqttDisconnectResponse disconnectResponse) {
log.info("mqtt disconnected"); log.info("mqtt disconnected");
@ -55,7 +102,11 @@ public class PtrMqttClient implements MqttCallback {
switch (topic) { switch (topic) {
case "/agv_robot/status": case "/agv_robot/status":
try { try {
amrMessageHandler.handleAgvRobotStatusMessage(message); if (this.amrMessageHandler == null) {
log.info("amrMessageHandler is null, skipping message handling {}", new String(message.getPayload(), StandardCharsets.UTF_8));
return;
}
this.amrMessageHandler.handleAgvRobotStatusMessage(message);
} catch (Exception e) { } catch (Exception e) {
log.error("amrMessageHandler.handleAgvRobotStatusMessage 异常", e); log.error("amrMessageHandler.handleAgvRobotStatusMessage 异常", e);
@ -68,11 +119,14 @@ public class PtrMqttClient implements MqttCallback {
@Override @Override
public void deliveryComplete(IMqttToken token) { public void deliveryComplete(IMqttToken token) {
log.info("Message delivery complete: {}", token);
} }
@Override @Override
public void connectComplete(boolean reconnect, String serverURI) { public void connectComplete(boolean reconnect, String serverURI) {
BannerUtils.printConfig(log, "MQTT 开启监听", new String[]{serverURI + " topic: /agv_robot/status"}); // BannerUtils.printConfig(log, "MQTT 开启监听", new String[]{serverURI + " topic: /agv_robot/status"});
log.info("MQTT client connected to server: {}", serverURI);
connectLatch.countDown(); // 放行
} }
@Override @Override
@ -81,10 +135,13 @@ public class PtrMqttClient implements MqttCallback {
@SneakyThrows @SneakyThrows
public void stop() { public void stop() {
if (client.isConnected()) { if (client != null && client.isConnected()) {
client.disconnect(); client.disconnect();
}
client.close(); client.close();
log.info("MQTT client stopped"); log.info("MQTT client disconnected and closed.");
} else {
log.warn("MQTT client is not connected, no action taken.");
} }
}
} }

1
servo/src/main/java/com/yvan/logisticsEnv/EnvPayload.java

@ -12,7 +12,6 @@ public class EnvPayload implements Serializable {
@Data @Data
public static class MqttConfig { public static class MqttConfig {
private String brokerUrl; private String brokerUrl;
private String clientId;
private String username; private String username;
private String password; private String password;
} }

2
servo/src/main/java/com/yvan/logisticsEnv/EnvStartParam.java

@ -10,6 +10,8 @@ import lombok.Setter;
@Setter @Setter
public class EnvStartParam { public class EnvStartParam {
public String clientId;
/** /**
* 是否虚拟仿真环境 * 是否虚拟仿真环境
*/ */

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

@ -176,7 +176,7 @@ public class LogisticsRuntime {
this.logisticsEnv.start(param); this.logisticsEnv.start(param);
// 启动 MQTT 监听 // 启动 MQTT 监听
this.amrMessageHandler.start(param.getEnvPayload().getMqtt()); this.amrMessageHandler.start(param.getEnvPayload().getMqtt(), param.clientId);
// 开启所有机器人的任务处理 // 开启所有机器人的任务处理
Set<String> executorTypes = Sets.newHashSet(); Set<String> executorTypes = Sets.newHashSet();

2
servo/src/main/java/com/yvan/logisticsModel/PtrAgvDeviceTask.java

@ -38,4 +38,6 @@ public class PtrAgvDeviceTask {
// 是否最后任务 // 是否最后任务
public boolean isLastTask = false; public boolean isLastTask = false;
public int checkLogicX;
public int checkLogicY;
} }

133
servo/src/main/java/com/yvan/logisticsModel/PtrAgvItem.java

@ -4,21 +4,21 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
import com.galaxis.rcs.common.entity.RcsTaskPlan; import com.galaxis.rcs.common.entity.RcsTaskPlan;
import com.galaxis.rcs.common.enums.AgvEventType; import com.galaxis.rcs.common.enums.AgvEventType;
import com.galaxis.rcs.common.enums.LCCDirection; import com.galaxis.rcs.common.enums.LCCDirection;
import com.galaxis.rcs.common.enums.PlanTaskStatus;
import com.galaxis.rcs.common.enums.PlanTaskType; import com.galaxis.rcs.common.enums.PlanTaskType;
import com.galaxis.rcs.connector.cl2.Cl2DeviceConnector; import com.galaxis.rcs.connector.cl2.Cl2DeviceConnector;
import com.galaxis.rcs.plan.PlanTaskSequence; import com.galaxis.rcs.plan.PlanTaskSequence;
import com.galaxis.rcs.ptr.AgvEventListener; import com.galaxis.rcs.ptr.*;
import com.galaxis.rcs.ptr.AmrMessageHandler;
import com.galaxis.rcs.ptr.ControlMode;
import com.galaxis.rcs.ptr.PosDirection;
import com.galaxis.rcs.ptr.receiveEntity.AmrHeartbeatMessage; import com.galaxis.rcs.ptr.receiveEntity.AmrHeartbeatMessage;
import com.galaxis.rcs.ptr.receiveEntity.base.CurBatteryData; import com.galaxis.rcs.ptr.receiveEntity.base.CurBatteryData;
import com.galaxis.rcs.ptr.sendEntity.RcsConfigMessage; import com.galaxis.rcs.ptr.sendEntity.RcsConfigMessage;
import com.galaxis.rcs.ptr.sendEntity.RcsSRMessage; import com.galaxis.rcs.ptr.sendEntity.RcsSRMessage;
import com.galaxis.rcs.ptr.sendEntity.RcsSetLocationMessage; import com.galaxis.rcs.ptr.sendEntity.RcsSetLocationMessage;
import com.google.common.base.Joiner;
import com.google.common.collect.Queues; import com.google.common.collect.Queues;
import lombok.SneakyThrows; import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.clever.core.BannerUtils;
import org.clever.core.json.JsonWrapper; import org.clever.core.json.JsonWrapper;
import org.clever.data.redis.Redis; import org.clever.data.redis.Redis;
import org.clever.data.redis.RedisAdmin; import org.clever.data.redis.RedisAdmin;
@ -63,6 +63,9 @@ public abstract class PtrAgvItem extends ExecutorItem {
// agv当前转动角度值 // agv当前转动角度值
public double orientation; public double orientation;
// 任务模式
public AmrTaskMode taskMode;
private volatile boolean isManualMode = false; private volatile boolean isManualMode = false;
private volatile boolean isPaused = false; private volatile boolean isPaused = false;
private volatile PosDirection lastPausedPosition; private volatile PosDirection lastPausedPosition;
@ -221,7 +224,19 @@ public abstract class PtrAgvItem extends ExecutorItem {
public boolean isFree() { public boolean isFree() {
// return (this.logisticsRuntime.isRunning() && this.deviceTaskQueue.isEmpty() && this.connectorThread.isRunning()); // return (this.logisticsRuntime.isRunning() && this.deviceTaskQueue.isEmpty() && this.connectorThread.isRunning());
return this.runtime.isRunning() && planTaskSequence == null && deviceTaskQueue.isEmpty() && !isPaused; if (!this.runtime.isRunning()) {
return false;
}
if (planTaskSequence != null && !planTaskSequence.isAllCompleted()) {
return false;
}
if (!deviceTaskQueue.isEmpty()) {
return false;
}
if (this.isPaused) {
return false;
}
return true;
} }
public void updatePosition(int logicX, int logicY, short direction) { public void updatePosition(int logicX, int logicY, short direction) {
@ -247,6 +262,62 @@ public abstract class PtrAgvItem extends ExecutorItem {
fireEvent(AgvEventType.DIRECTION_CHANGED, this, fireEvent(AgvEventType.DIRECTION_CHANGED, this,
oldDirection, direction); oldDirection, direction);
} }
boolean needCompute = false;
// 从 runningDeviceTaskList 里面,找到完成到什么阶段
// 比如 (1,2) -> (2,2) -> (3,2) , 如果 updatePosition=3,2 ,那么前2个任务都要完成
int finishTargetIndex = -1;
if (this.runningDeviceTaskList != null && !this.runningDeviceTaskList.isEmpty() &&
this.planTaskSequence != null && !this.planTaskSequence.isEmpty()) {
for (int i = 0; i < runningDeviceTaskList.size(); i++) {
PtrAgvDeviceTask task = runningDeviceTaskList.get(i);
if (task.checkLogicX == logicX && task.checkLogicY == logicY) {
finishTargetIndex = i;
break;
}
}
if (finishTargetIndex >= 0) {
needCompute = true;
// 标记前面的任务都完成了
for (int i = 0; i <= finishTargetIndex; i++) {
PtrAgvDeviceTask task = runningDeviceTaskList.get(i);
task.taskStatus = 4; // 标记为完成
task.taskGroupStatus = 4; // 标记为任务组完成
fireEvent(AgvEventType.DEVICE_TASK_COMPLETE, this, task);
// 更新计划任务
RcsTaskPlan planTask = planTaskSequence.getByPlanTaskId(task.planTaskId);
if (planTask != null) {
planTask.setPlanTaskStatus(PlanTaskStatus.FINISHED.toString());
planTaskSequence.savePlanTask(planTask);
}
}
if (planTaskSequence.isAllCompleted()) {
fireEvent(AgvEventType.PLAN_COMPLETE, this);
planTaskSequence = null;
}
}
}
BannerUtils.printConfig(log, "updatePosition", new String[]{
"logicX: " + logicX,
"logicY: " + logicY,
"direction: " + direction,
"finishTargetIndex: " + finishTargetIndex,
"runningDeviceSize:" + (this.runningDeviceTaskList == null ? "null" : this.runningDeviceTaskList.size()),
"planTask:" + (this.planTaskSequence == null ? "null" :
("\n" + Joiner.on("\n").join((List) this.planTaskSequence.toPrettyMap().get("items")))
)
});
if (needCompute) {
LockSupport.unpark(connectorThread);
}
} }
/** /**
@ -263,46 +334,11 @@ public abstract class PtrAgvItem extends ExecutorItem {
return; return;
} }
boolean needCompute = true; // 任务完成逻辑,在地标检查里
for (PtrAgvDeviceTask task : runningDeviceTaskList) {
if (task.seqNo == seqNo) {
task.taskGroupStatus = messageStatus;
if (task.x == x && task.y == y) {
task.taskStatus = 4;
}
}
if (task.taskGroupStatus < 3 /*|| task.taskStatus < 4*/) {
needCompute = false;
}
} }
if (needCompute) {
LockSupport.unpark(connectorThread);
}
// 如果是任务完成事件
if (messageStatus == 4) {
fireEvent(AgvEventType.DEVICE_TASK_COMPLETE, this, this.connectorThread.__currentTask);
if (isTaskSequenceComplete()) { public void updateTaskMode(int taskMode) {
fireEvent(AgvEventType.PLAN_COMPLETE, this);
planTaskSequence = null;
}
}
}
/**
* 检查当前任务序列是否完成
*/
public boolean isTaskSequenceComplete() {
if (planTaskSequence == null) {
return false;
}
for (PtrAgvDeviceTask task : runningDeviceTaskList) {
if (task.taskGroupStatus < 3 /*|| task.taskStatus < 4*/) {
return false;
}
}
return true;
} }
public void updateRedisStatus() { public void updateRedisStatus() {
@ -451,6 +487,9 @@ public abstract class PtrAgvItem extends ExecutorItem {
deviceTask.endPoint = pointItem; deviceTask.endPoint = pointItem;
deviceTask.bizTaskId = plan.getBizTaskId(); deviceTask.bizTaskId = plan.getBizTaskId();
deviceTask.planTaskId = plan.getPlanTaskId(); deviceTask.planTaskId = plan.getPlanTaskId();
// 行走任务完成后,检查用的字段
deviceTask.checkLogicX = pointItem.logicX;
deviceTask.checkLogicY = pointItem.logicY;
deviceTaskList.add(deviceTask); deviceTaskList.add(deviceTask);
// 设置新的起点 // 设置新的起点
startPoint = pointItem; startPoint = pointItem;
@ -626,6 +665,16 @@ public abstract class PtrAgvItem extends ExecutorItem {
}; };
} }
public short getAmrDirection(LCCDirection lccDirection) {
return switch (lccDirection) {
case RIGHT -> 0;
case DOWN -> 1;
case LEFT -> 2;
case UP -> 3;
default -> -1; // 未知方向
};
}
private String getRedisKey(String type) { private String getRedisKey(String type) {
return String.format("lcc:%s:%s:rcs:%s_%s", return String.format("lcc:%s:%s:rcs:%s_%s",
runtime.projectUUID, runtime.envId, type, this.getId()); runtime.projectUUID, runtime.envId, type, this.getId());

Loading…
Cancel
Save