diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/service/NewAtsTrainLoadService.java b/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/service/NewAtsTrainLoadService.java new file mode 100644 index 000000000..4b58317b2 --- /dev/null +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/service/NewAtsTrainLoadService.java @@ -0,0 +1,133 @@ +package club.joylink.rtss.simulation.cbtc.ATS.service; + +import club.joylink.rtss.exception.BusinessExceptionAssertEnum; +import club.joylink.rtss.simulation.cbtc.ATP.ground.MaService; +import club.joylink.rtss.simulation.cbtc.ATS.service.ars.AtsRouteSelectService; +import club.joylink.rtss.simulation.cbtc.CI.CiApiService; +import club.joylink.rtss.simulation.cbtc.CI.CiLogic; +import club.joylink.rtss.simulation.cbtc.Simulation; +import club.joylink.rtss.simulation.cbtc.SimulationLifeCycleService; +import club.joylink.rtss.simulation.cbtc.constant.RunLevel; +import club.joylink.rtss.simulation.cbtc.constant.SimulationConstants; +import club.joylink.rtss.simulation.cbtc.data.CalculateService; +import club.joylink.rtss.simulation.cbtc.data.SimulationDataRepository; +import club.joylink.rtss.simulation.cbtc.data.map.MapConfig; +import club.joylink.rtss.simulation.cbtc.data.map.Route; +import club.joylink.rtss.simulation.cbtc.data.map.Section; +import club.joylink.rtss.simulation.cbtc.data.plan.StationPlan; +import club.joylink.rtss.simulation.cbtc.data.plan.TripPlan; +import club.joylink.rtss.simulation.cbtc.data.support.RoutePath; +import club.joylink.rtss.simulation.cbtc.data.support.SectionPosition; +import club.joylink.rtss.simulation.cbtc.data.support.TrainLoadParam2; +import club.joylink.rtss.simulation.cbtc.data.vo.TrainInfo; +import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityTrain; +import club.joylink.rtss.simulation.cbtc.device.virtual.VRDeviceLogicLoop; +import club.joylink.rtss.simulation.cbtc.device.virtual.VRTrainRunningService; +import club.joylink.rtss.simulation.cbtc.event.SimulationRunAsPlanEvent; +import club.joylink.rtss.simulation.cbtc.exception.SimulationException; +import club.joylink.rtss.simulation.cbtc.exception.SimulationExceptionType; +import club.joylink.rtss.simulation.cbtc.onboard.ATP.ATPService; +import club.joylink.rtss.simulation.cbtc.tool.DeviceStatusModifyTool; +import club.joylink.rtss.vo.ws.TrainPosition; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.ApplicationContext; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import javax.annotation.Resource; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; + +@Slf4j +@Component +public class NewAtsTrainLoadService extends AtsTrainLoadService { + + @Resource + private VRTrainRunningService vrTrainRunningService; + + + + + + public void loadTripNumberTrain(Simulation simulation, TrainPosition tp,Section section) { + SimulationDataRepository repository = simulation.getRepository(); + String tripNumber = tp.getTrainTripNum(); + TrainInfo trainInfo = repository.getTrainInfoMap().values().stream().filter(train -> tripNumber.equals(train.getTripNumber())).findFirst().orElse(null); + +// List allVrTrain = repository.getAllVrTrain(); + + if(Objects.nonNull(trainInfo)){ + //存在列车需要更新位置 + Optional virtualRealityTrainOptional = repository.getAllVrTrain().stream().filter(d->Objects.equals(d.getTripNumber(),tripNumber)).findFirst(); + VirtualRealityTrain virtualRealityTrain = virtualRealityTrainOptional.get(); + trainOnline(simulation, section, tp, virtualRealityTrain); +// virtualRealityTrain.initManualTrain(headPosition, tp.isRight()); + }else{ + + Optional virtualRealityTrainOptional = repository.getAllVrTrain().stream() + .filter(vrTrain -> !repository.isVrTrainOnline(vrTrain.getGroupNumber())) + .findFirst(); + VirtualRealityTrain virtualRealityTrain = virtualRealityTrainOptional.get(); + // 设置列车车次 + virtualRealityTrain.setTripNumber(tripNumber); + trainOnline(simulation, section, tp, virtualRealityTrain); +// SectionPosition headPosition = new SectionPosition(section, tp.getLocation() - section.getKmMin()); +// virtualRealityTrain.initManualTrain(headPosition, tp.isRight()); + } + + } + + + /** + * 列车上线并构建ATS监控列车信息 + * @param simulation + * @param section + * @param tp + * @param train + */ + private void trainOnline(Simulation simulation, Section section, TrainPosition tp, VirtualRealityTrain train) { + boolean right = tp.isRight(); + if (!section.isPhysical()) { + section = section.getParent(); + } + BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertNotNull(section.isPhysical(), "列车需加载到物理区段上"); + //重叠检测 + SectionPosition headPosition = new SectionPosition(section, tp.getLocation() - section.getKmMin()); +// SectionPosition headPosition = new SectionPosition(section, section.getStopPointByDirection(right)); + SectionPosition tailPosition = CalculateService.calculateNextPositionByStartAndLen(headPosition, !right, train.getLen(), false); + boolean willOverlap = vrTrainRunningService.willOverlap(simulation, headPosition, tailPosition); + BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertNotTrue(willOverlap, "列车重叠"); + // 列车上线并构建ATS监控列车信息 + manualTrainOnlineAndSupervise(simulation, train, headPosition, right); + } + + /** + * 人工车上线并监控 + */ + private void manualTrainOnlineAndSupervise(Simulation simulation, VirtualRealityTrain train, SectionPosition headPosition, boolean right) { + train.initManualTrain(headPosition, right); + SimulationDataRepository repository = simulation.getRepository(); + //设置列车预选模式、驾驶模式、运行级别 + if (!headPosition.getSection().anyZcWorking()) { + train.initAsRM(); + } else { + MapConfig config = repository.getConfig(); + if (RunLevel.ITC.equals(config.getRunMode())) { + train.initAsAM_I(); + } else if (RunLevel.IL.equals(config.getRunMode())) { + train.initAsRM(); + } + } + if (!repository.getConfig().isHandleDepot()) { + TrainInfo trainInfo = TrainInfo.constructManualTrain(train); + trainInfo.tracking(train); + repository.addOnlineTrain(train); + repository.addTrainInfo(trainInfo); + } + } +} diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/service/TrainPositionService.java b/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/service/TrainPositionService.java index ef2cdafe4..a83cb1c57 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/service/TrainPositionService.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/service/TrainPositionService.java @@ -6,71 +6,110 @@ import club.joylink.rtss.simulation.SimulationManager; import club.joylink.rtss.simulation.cbtc.Simulation; import club.joylink.rtss.simulation.cbtc.build.SimulationBuildParams; import club.joylink.rtss.simulation.cbtc.data.map.Section; +import club.joylink.rtss.util.JsonUtils; import club.joylink.rtss.vo.ws.TrainPosition; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; -import org.springframework.util.StringUtils; import javax.annotation.Resource; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; +import java.util.Comparator; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @Service @Slf4j public class TrainPositionService { @Resource - AtsTrainLoadService atsTrainLoadService; + private NewAtsTrainLoadService newAtsTrainLoadService; @Resource - SimulationManager simulationManager; - private final static Cache> ROAD_TYPE_CACHE = CacheBuilder.newBuilder().build(); - - public void initTrainOrUpdate(String mapName,TrainPosition tp){ + private SimulationManager simulationManager; + /** + * 数据过期时间 + */ + private final static long EXPIRE_SECTION_TIME_MIN = 10; + /** + * 区段的缓存 + * key 对应的方向类型 + * EXPIRE_SECTION_TIME_MIN 数据过期时间 + */ + private final static Cache> ROAD_TYPE_CACHE = CacheBuilder.newBuilder().expireAfterWrite(EXPIRE_SECTION_TIME_MIN, TimeUnit.MINUTES).build(); + /** + * 初始化或更新列车的位置 + * @param mapName + * @param json + */ + public void initTrainOrUpdate(String mapName,String json){ + TrainPosition tp = JsonUtils.read(json, TrainPosition.class); List simulationList = this.findSimulationList(mapName); if(Objects.equals(true, CollectionUtils.isEmpty(simulationList))){ - log.error(""); + log.error("未找到对应的类型的仿真,无法渲染列车位置 param:{}",json); return; } List
sectionList = findDirectionAllSection(simulationList.get(0),tp.getRoadType()); + Section section = this.findSecion(sectionList,tp); + if(Objects.isNull(section)){ + log.error("未找到对应的区段 param:{}",json); + return; + } for (Simulation sim : simulationList) { - + this.newAtsTrainLoadService.loadTripNumberTrain(sim,tp,section); } } - private void findSecion(List
sectionList,TrainPosition tp){ + /** + * 根据传入的参数 定位对应的所在的区段 + * @param sectionList + * @param tp + * @return + */ + private Section findSecion(List
sectionList,TrainPosition tp){ int i = 0; - Section findSection; +// Section findSection; for (Section section : sectionList) { if(tp.isRight()){ if(tp.getLocation() <= section.getKmMax()){ - findSection = section; - break; + return section; } }else{ - + if(tp.getLocation() <= section.getKmMax() && tp.getLocation() >= section.getKmMin()){ + return section; + } } i++; } + return null; } + /** + * 根据车辆方向获取对应的区段并升序排序 + * @param sim + * @param roadType + * @return + */ private static synchronized List
findDirectionAllSection(Simulation sim,Section.SectionRoadType roadType){ List
list = ROAD_TYPE_CACHE.getIfPresent(roadType); if(Objects.equals(true,CollectionUtils.isEmpty(list))){ list = sim.getRepository().getSectionList(); list = list.stream().filter(d->d.getRoadType() == roadType) - .sorted(Comparator.comparing(Section::getKmMin)/*.reversed()*/).collect(Collectors.toList()); + .sorted(Comparator.comparing(Section::getKmMin)).collect(Collectors.toList()); ROAD_TYPE_CACHE.put(roadType,list); } return list; } + /** + * 获取对应线路的仿真,并且地图类型为 MapPrdTypeEnum.BIG_SCREEN_TRAIN_POSITION + * @param mapName + * @return + */ private List findSimulationList(String mapName){ return this.simulationManager.getSimulationList().stream().filter(d->{ if(d instanceof Simulation){ diff --git a/src/main/java/club/joylink/rtss/websocket/WebSocketController.java b/src/main/java/club/joylink/rtss/websocket/WebSocketController.java index b9f34914c..d4b711d26 100644 --- a/src/main/java/club/joylink/rtss/websocket/WebSocketController.java +++ b/src/main/java/club/joylink/rtss/websocket/WebSocketController.java @@ -1,15 +1,20 @@ package club.joylink.rtss.websocket; +import club.joylink.rtss.simulation.cbtc.ATS.service.TrainPositionService; import club.joylink.rtss.simulation.cbtc.GroupSimulationCache; import club.joylink.rtss.simulation.cbtc.Simulation; + +import club.joylink.rtss.util.JsonUtils; import club.joylink.rtss.vo.client.SocketMessageVO; import club.joylink.rtss.vo.client.factory.SocketMessageFactory; +import club.joylink.rtss.vo.ws.TrainPosition; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.messaging.handler.annotation.DestinationVariable; import org.springframework.messaging.handler.annotation.MessageMapping; import org.springframework.stereotype.Controller; +import javax.annotation.Resource; import java.security.Principal; @Controller @@ -21,7 +26,8 @@ public class WebSocketController { @Autowired private GroupSimulationCache groupSimulationCache; - + @Resource + private TrainPositionService trainPositionService; @MessageMapping("/simulation/{group}/vr") public void routingData(Principal user, String json, @DestinationVariable String group) { Simulation simulation = groupSimulationCache.getSimulationByGroup(group); @@ -29,11 +35,8 @@ public class WebSocketController { stompMessageService.sendToUser(simulation.getSimulationUserIds(), message); } - @MessageMapping("/{mapId}/trainPosition") - public void mlbs( String json,@DestinationVariable String mapId) { -// Simulation simulation = groupSimulationCache.getSimulationByGroup(group); -// SocketMessageVO message = SocketMessageFactory.buildVrMessage(group, json); -// stompMessageService.sendToUser(simulation.getSimulationUserIds(), message); - System.out.println("aaaaaaaaaaaaa"); + @MessageMapping("/{mapName}/trainPosition") + public void mlbs( String json,@DestinationVariable String mapName) { + this.trainPositionService.initTrainOrUpdate(mapName,json); } } diff --git a/src/main/java/club/joylink/rtss/websocket/client/StompClientManager.java b/src/main/java/club/joylink/rtss/websocket/client/StompClientManager.java index 47f57cc14..87a43bbc6 100644 --- a/src/main/java/club/joylink/rtss/websocket/client/StompClientManager.java +++ b/src/main/java/club/joylink/rtss/websocket/client/StompClientManager.java @@ -12,6 +12,7 @@ import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; @Slf4j public class StompClientManager { @@ -26,14 +27,50 @@ public class StompClientManager { .connect("ws://127.0.0.1:9000/joylink-tbi-websocket",handler, "null"); StompSession stompSession = future.get(); - Map dataMap = new HashMap<>(); - dataMap.put("trainTripNum","train001"); - dataMap.put("direction",1); - dataMap.put("location",19.99); - ObjectMapper om = new ObjectMapper(); - String val = JsonUtils.writeValueNullableFieldAsString(dataMap); - System.out.println(val); - stompSession.send("/app/测试中文/trainPosition",val.getBytes(StandardCharsets.UTF_8)); + runToLeft(stompSession,"train001"); +// runToRight(stompSession,"train002"); + + } + + public static void runToLeft(StompSession stompSession,String tripNum){ + int step = 80; + int location = 40000; + while(true){ + location -= step; + Map dataMap = new HashMap<>(); + dataMap.put("trainTripNum",tripNum); +// dataMap.put("direction",1); + dataMap.put("direction",0); + dataMap.put("location",location); + String val = JsonUtils.writeValueNullableFieldAsString(dataMap); + System.out.println(val); + stompSession.send("/app/武汉8号线/trainPosition",val.getBytes(StandardCharsets.UTF_8)); + try { + TimeUnit.MILLISECONDS.sleep(500); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + public static void runToRight(StompSession stompSession,String tripNum){ + int step = 20; + int location = 0; + while(true){ + location += step; + Map dataMap = new HashMap<>(); + dataMap.put("trainTripNum",tripNum); + dataMap.put("direction",1); +// dataMap.put("direction",0); + dataMap.put("location",location); + String val = JsonUtils.writeValueNullableFieldAsString(dataMap); + System.out.println(val); + stompSession.send("/app/武汉8号线/trainPosition",val.getBytes(StandardCharsets.UTF_8)); + try { + TimeUnit.MILLISECONDS.sleep(500); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } } }