武汉8号线列车位置显示功能

This commit is contained in:
tiger_zhou 2022-09-07 16:39:55 +08:00
parent 753c314292
commit 41fe8bba1c
4 changed files with 244 additions and 32 deletions

View File

@ -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<VirtualRealityTrain> allVrTrain = repository.getAllVrTrain();
if(Objects.nonNull(trainInfo)){
//存在列车需要更新位置
Optional<VirtualRealityTrain> 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<VirtualRealityTrain> 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);
}
}
}

View File

@ -6,71 +6,110 @@ import club.joylink.rtss.simulation.SimulationManager;
import club.joylink.rtss.simulation.cbtc.Simulation; import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.build.SimulationBuildParams; import club.joylink.rtss.simulation.cbtc.build.SimulationBuildParams;
import club.joylink.rtss.simulation.cbtc.data.map.Section; import club.joylink.rtss.simulation.cbtc.data.map.Section;
import club.joylink.rtss.util.JsonUtils;
import club.joylink.rtss.vo.ws.TrainPosition; import club.joylink.rtss.vo.ws.TrainPosition;
import com.google.common.cache.Cache; import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheBuilder;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.*; import java.util.Comparator;
import java.util.concurrent.ConcurrentHashMap; import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Service @Service
@Slf4j @Slf4j
public class TrainPositionService { public class TrainPositionService {
@Resource @Resource
AtsTrainLoadService atsTrainLoadService; private NewAtsTrainLoadService newAtsTrainLoadService;
@Resource @Resource
SimulationManager simulationManager; private SimulationManager simulationManager;
private final static Cache<Section.SectionRoadType,List<Section>> ROAD_TYPE_CACHE = CacheBuilder.newBuilder().build(); /**
* 数据过期时间
public void initTrainOrUpdate(String mapName,TrainPosition tp){ */
private final static long EXPIRE_SECTION_TIME_MIN = 10;
/**
* 区段的缓存
* key 对应的方向类型
* EXPIRE_SECTION_TIME_MIN 数据过期时间
*/
private final static Cache<Section.SectionRoadType,List<Section>> 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<Simulation> simulationList = this.findSimulationList(mapName); List<Simulation> simulationList = this.findSimulationList(mapName);
if(Objects.equals(true, CollectionUtils.isEmpty(simulationList))){ if(Objects.equals(true, CollectionUtils.isEmpty(simulationList))){
log.error(""); log.error("未找到对应的类型的仿真,无法渲染列车位置 param:{}",json);
return; return;
} }
List<Section> sectionList = findDirectionAllSection(simulationList.get(0),tp.getRoadType()); List<Section> 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) { for (Simulation sim : simulationList) {
this.newAtsTrainLoadService.loadTripNumberTrain(sim,tp,section);
} }
} }
private void findSecion(List<Section> sectionList,TrainPosition tp){ /**
* 根据传入的参数 定位对应的所在的区段
* @param sectionList
* @param tp
* @return
*/
private Section findSecion(List<Section> sectionList,TrainPosition tp){
int i = 0; int i = 0;
Section findSection; // Section findSection;
for (Section section : sectionList) { for (Section section : sectionList) {
if(tp.isRight()){ if(tp.isRight()){
if(tp.getLocation() <= section.getKmMax()){ if(tp.getLocation() <= section.getKmMax()){
findSection = section; return section;
break;
} }
}else{ }else{
if(tp.getLocation() <= section.getKmMax() && tp.getLocation() >= section.getKmMin()){
return section;
}
} }
i++; i++;
} }
return null;
} }
/**
* 根据车辆方向获取对应的区段并升序排序
* @param sim
* @param roadType
* @return
*/
private static synchronized List<Section> findDirectionAllSection(Simulation sim,Section.SectionRoadType roadType){ private static synchronized List<Section> findDirectionAllSection(Simulation sim,Section.SectionRoadType roadType){
List<Section> list = ROAD_TYPE_CACHE.getIfPresent(roadType); List<Section> list = ROAD_TYPE_CACHE.getIfPresent(roadType);
if(Objects.equals(true,CollectionUtils.isEmpty(list))){ if(Objects.equals(true,CollectionUtils.isEmpty(list))){
list = sim.getRepository().getSectionList(); list = sim.getRepository().getSectionList();
list = list.stream().filter(d->d.getRoadType() == roadType) 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); ROAD_TYPE_CACHE.put(roadType,list);
} }
return list; return list;
} }
/**
* 获取对应线路的仿真并且地图类型为 MapPrdTypeEnum.BIG_SCREEN_TRAIN_POSITION
* @param mapName
* @return
*/
private List<Simulation> findSimulationList(String mapName){ private List<Simulation> findSimulationList(String mapName){
return this.simulationManager.getSimulationList().stream().filter(d->{ return this.simulationManager.getSimulationList().stream().filter(d->{
if(d instanceof Simulation){ if(d instanceof Simulation){

View File

@ -1,15 +1,20 @@
package club.joylink.rtss.websocket; 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.GroupSimulationCache;
import club.joylink.rtss.simulation.cbtc.Simulation; 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.SocketMessageVO;
import club.joylink.rtss.vo.client.factory.SocketMessageFactory; import club.joylink.rtss.vo.client.factory.SocketMessageFactory;
import club.joylink.rtss.vo.ws.TrainPosition;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.DestinationVariable; import org.springframework.messaging.handler.annotation.DestinationVariable;
import org.springframework.messaging.handler.annotation.MessageMapping; import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import javax.annotation.Resource;
import java.security.Principal; import java.security.Principal;
@Controller @Controller
@ -21,7 +26,8 @@ public class WebSocketController {
@Autowired @Autowired
private GroupSimulationCache groupSimulationCache; private GroupSimulationCache groupSimulationCache;
@Resource
private TrainPositionService trainPositionService;
@MessageMapping("/simulation/{group}/vr") @MessageMapping("/simulation/{group}/vr")
public void routingData(Principal user, String json, @DestinationVariable String group) { public void routingData(Principal user, String json, @DestinationVariable String group) {
Simulation simulation = groupSimulationCache.getSimulationByGroup(group); Simulation simulation = groupSimulationCache.getSimulationByGroup(group);
@ -29,11 +35,8 @@ public class WebSocketController {
stompMessageService.sendToUser(simulation.getSimulationUserIds(), message); stompMessageService.sendToUser(simulation.getSimulationUserIds(), message);
} }
@MessageMapping("/{mapId}/trainPosition") @MessageMapping("/{mapName}/trainPosition")
public void mlbs( String json,@DestinationVariable String mapId) { public void mlbs( String json,@DestinationVariable String mapName) {
// Simulation simulation = groupSimulationCache.getSimulationByGroup(group); this.trainPositionService.initTrainOrUpdate(mapName,json);
// SocketMessageVO<String> message = SocketMessageFactory.buildVrMessage(group, json);
// stompMessageService.sendToUser(simulation.getSimulationUserIds(), message);
System.out.println("aaaaaaaaaaaaa");
} }
} }

View File

@ -12,6 +12,7 @@ import java.nio.charset.StandardCharsets;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
@Slf4j @Slf4j
public class StompClientManager { public class StompClientManager {
@ -26,14 +27,50 @@ public class StompClientManager {
.connect("ws://127.0.0.1:9000/joylink-tbi-websocket",handler, "null"); .connect("ws://127.0.0.1:9000/joylink-tbi-websocket",handler, "null");
StompSession stompSession = future.get(); StompSession stompSession = future.get();
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<String,Object> dataMap = new HashMap<>(); Map<String,Object> dataMap = new HashMap<>();
dataMap.put("trainTripNum","train001"); dataMap.put("trainTripNum",tripNum);
dataMap.put("direction",1); // dataMap.put("direction",1);
dataMap.put("location",19.99); dataMap.put("direction",0);
ObjectMapper om = new ObjectMapper(); dataMap.put("location",location);
String val = JsonUtils.writeValueNullableFieldAsString(dataMap); String val = JsonUtils.writeValueNullableFieldAsString(dataMap);
System.out.println(val); System.out.println(val);
stompSession.send("/app/测试中文/trainPosition",val.getBytes(StandardCharsets.UTF_8)); 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<String,Object> 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();
}
}
} }
} }