列车图例显示位置

This commit is contained in:
tiger_zhou 2023-04-23 18:04:14 +08:00
parent e83d5dfae6
commit 5fb422d3d0
9 changed files with 145 additions and 93 deletions

View File

@ -1,11 +1,14 @@
package club.joylink.rtss.simulation.cbtc.ATS; package club.joylink.rtss.simulation.cbtc.ATS;
import club.joylink.rtss.simulation.cbtc.ATS.data.StationDiagram; import club.joylink.rtss.simulation.cbtc.ATS.data.StationDiagram;
import club.joylink.rtss.simulation.cbtc.CTC.data.CtcStationRunPlanLog;
import club.joylink.rtss.simulation.cbtc.Simulation; import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.constant.SimulationConstants; import club.joylink.rtss.simulation.cbtc.constant.SimulationConstants;
import club.joylink.rtss.simulation.cbtc.constant.SimulationModule; import club.joylink.rtss.simulation.cbtc.constant.SimulationModule;
import club.joylink.rtss.simulation.cbtc.data.CalculateService; import club.joylink.rtss.simulation.cbtc.data.CalculateService;
import club.joylink.rtss.simulation.cbtc.data.map.Section; import club.joylink.rtss.simulation.cbtc.data.map.*;
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.SectionPosition; import club.joylink.rtss.simulation.cbtc.data.support.SectionPosition;
import club.joylink.rtss.simulation.cbtc.data.vo.TrainInfo; import club.joylink.rtss.simulation.cbtc.data.vo.TrainInfo;
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityTrain; import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityTrain;
@ -17,14 +20,14 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.io.BufferedReader;
import java.io.FileReader;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode; import java.math.RoundingMode;
import java.util.List; import java.util.*;
import java.util.Objects; import java.util.stream.Collectors;
import java.util.Optional; import java.util.stream.IntStream;
import java.util.Set;
/** /**
* 收集列车相关信息 * 收集列车相关信息
@ -36,110 +39,96 @@ public class ATSTrainMessageDiagram {
private StompMessageService stompMessageService; private StompMessageService stompMessageService;
public void collect(Simulation simulation){ public void collect(Simulation simulation){
List<StationDiagram> stationDiagramList = Lists.newArrayList();
KmStation kmStation = new KmStation(simulation);
List<StationDiagram> stationDiagramList = Lists.newArrayList();
for (VirtualRealityTrain train : simulation.getRepository().getOnlineTrainList()) { for (VirtualRealityTrain train : simulation.getRepository().getOnlineTrainList()) {
Section target = train.getTarget(); Section target = train.getTarget();
if(ObjectUtils.anyNull(target,train.getNextStation(),train.getTerminalStation())){ if(ObjectUtils.anyNull(target,train.getNextStation(),train.getTerminalStation())){
StationDiagram sd = new StationDiagram(train,0F,false);
stationDiagramList.add(sd);
continue; continue;
} }
TrainInfo trainInfo = simulation.getRepository().getSupervisedTrainByGroup(train.getGroupNumber()); TrainInfo trainInfo = simulation.getRepository().getSupervisedTrainByGroup(train.getGroupNumber());
if(Objects.nonNull(trainInfo) && trainInfo.isInbound()){ if(Objects.nonNull(trainInfo) && trainInfo.isInbound()){
StationDiagram sd = new StationDiagram(train,0F,false);
stationDiagramList.add(sd);
continue; continue;
} }
Station nextStation = train.getNextStation();
SectionPosition tailPos = train.getTailPosition();
if(nextStation.isDepot() && !tailPos.getSection().isStandTrack()){
//出站
StationDiagram sd = new StationDiagram(train,0F,false);
stationDiagramList.add(sd);
}else if(trainInfo.isTurnBack()){
//列车正在折返
StationDiagram sd = new StationDiagram(train,0F,true);
sd.setStartStation(train.getNextStation());
sd.setTurnBack(true);
stationDiagramList.add(sd);
}else{
Optional<StationDiagram> optionalDiagram = this.calculateRuning2(simulation,train,trainInfo,kmStation);
optionalDiagram.ifPresent(stationDiagramList::add);
Optional<StationDiagram> optionalDiagram = this.calculate(train); }
optionalDiagram.ifPresent(stationDiagramList::add);
} }
SocketMessageVO<List<StationDiagram>> messageVO = SocketMessageVO<List<StationDiagram>> messageVO =
SocketMessageFactory.buildAtsStationDiagram(simulation.getId(), stationDiagramList); SocketMessageFactory.buildAtsStationDiagram(simulation.getId(), stationDiagramList);
Set<String> sessions = simulation.getSimulationUserIds(); Set<String> sessions = simulation.getSimulationUserIds();
stompMessageService.sendToUser(sessions, messageVO); stompMessageService.sendToUser(sessions, messageVO);
} }
/*public void collect(Simulation simulation){
for (VirtualRealityTrain train : simulation.getRepository().getOnlineTrainList()) {
Section target = train.getTarget();
if(ObjectUtils.anyNull(target,train.getNextStation(),train.getTerminalStation())){
continue;
}
TrainInfo trainInfo = simulation.getRepository().getSupervisedTrainByGroup(train.getGroupNumber());
if(Objects.nonNull(trainInfo) && trainInfo.isInbound()){
continue;
}
if(train.isParkingAt()){
trainInfo.setStationDiagramRatio(1F);
}else {
Section endSeciont = target;
if(!Objects.equals(train.getNextStation().getCode(),train.getTerminalStation().getCode())) {
//车辆的下一站不是终点站,获取下一站的停车位置
SectionPosition sp = train.calculateNextStandStopPosition();
endSeciont = sp.getSection();
}
SectionPosition tailSP = train.getTailPosition();
Section tailSection = tailSP.getSection();
Section parent = tailSection;
if(!tailSection.isPhysical()){
parent = tailSection.getParent();
}
//如果车尾所在的区段是逻辑区段那么就查找车辆后方的车站
if(Objects.isNull(parent.getStation())){
SectionPosition sp1 = train.calculateBackStandStopPosition();
if(Objects.isNull(sp1)){
//未找到列车后面的车站
continue;
}
tailSection = sp1.getSection();
}
Float complateDis = this.calculateStationRatio(tailSection,endSeciont,train);
trainInfo.setStationDiagramRatio(complateDis); private Optional<StationDiagram> calculateRuning2(Simulation simulation,VirtualRealityTrain train,TrainInfo trainInfo,KmStation kmStation){
Section leaveSeaction = simulation.getRepository().getByCode(Objects.isNull(trainInfo.getEstimatedLeaveStandTrack()) ? trainInfo.getActualLeaveStandTrack() : trainInfo.getEstimatedLeaveStandTrack(),Section.class);
Section trainSection = train.getHeadPosition().getSection();
if(train.isParkingAt()){
if(trainSection.isStandTrack() && Objects.equals(trainSection.getStation().getCode(),trainInfo.getStartStation())){
//到达始发站
StationDiagram sd = new StationDiagram(train,true,0F,false);
sd.setStartStation(trainSection.getStation());
Station nextStation = kmStation.findNext(trainSection.getStation(),train.isRight());
sd.setEndStation(nextStation);
return Optional.of(sd);
}else if(trainSection.isStandTrack() || (trainSection.isStandTrack() && Objects.equals(trainSection.getStation().getCode(),trainInfo.getEndStation()))){
//列车停靠车站或到终点站
StationDiagram sd = new StationDiagram(train,true,1F,true);
Station preStation = kmStation.findPre(trainSection.getStation(),train.isRight());
sd.setStartStation(preStation);
sd.setEndStation(trainSection.getStation());
return Optional.of(sd);
} }
} }
}*/
private Optional<StationDiagram> calculate(VirtualRealityTrain train){
boolean finalStation = true; boolean finalStation = true;
Section targetSecion = train.getTarget(); Section targetStand = train.getTerminalStation().getStandOf(train.isRight()).get(0).getSection();
Section tailSection = train.getTailPosition().getSection(); if(!Objects.equals(train.getNextStation().getCode(),trainInfo.getEndStation())) {
if(!Objects.equals(train.getNextStation().getCode(),train.getTerminalStation().getCode())) {
//车辆的下一站不是终点站,获取下一站的停车位置 //车辆的下一站不是终点站,获取下一站的停车位置
finalStation = false; finalStation = false;
SectionPosition sp = train.calculateNextStandStopPosition(); targetStand = train.getNextStation().getStandOf(train.isRight()).get(0).getSection();
if(Objects.isNull(sp)){
StationDiagram sd = new StationDiagram(train,false);
return Optional.of(sd);
}
targetSecion = sp.getSection();
}
if(!tailSection.isStandTrack()){
//如果车尾所在的区段是逻辑区段那么就查找车辆后方的车站
SectionPosition sp1 = train.calculateBackStandStopPosition();
if(Objects.isNull(sp1)){
//未找到列车后面的车站,可能还未进始发站
StationDiagram sd = new StationDiagram(train,false);
return Optional.of(sd);
}
tailSection = sp1.getSection();
} }
Float complateDis = this.calculateStationRatio(leaveSeaction,targetStand,train);
Float complateDis = 1F;
if(!train.isParkingAt()){
complateDis = this.calculateStationRatio(tailSection,targetSecion,train);
}
StationDiagram stationDiagram = new StationDiagram(train,true,complateDis,finalStation); StationDiagram stationDiagram = new StationDiagram(train,true,complateDis,finalStation);
stationDiagram.setStartStation(tailSection.getStation()); stationDiagram.setStartStation(leaveSeaction.getStation());
stationDiagram.setEndStation(train.getNextStation()); stationDiagram.setEndStation(targetStand.getStation());
return Optional.of(stationDiagram); return Optional.of(stationDiagram);
} }
private Float calculateStationRatio(Section begin,Section end,VirtualRealityTrain train){ private Float calculateStationRatio(Section begin,Section end,VirtualRealityTrain train){
float totalDis = CalculateService.calculateDistance(begin,end,train.isRight()); float totalDis = CalculateService.calculateDistance(begin,end,train.isRight());
if(totalDis == 0F){ if(totalDis == 0F){
@ -151,19 +140,53 @@ public class ATSTrainMessageDiagram {
if(runDis > 0){ if(runDis > 0){
t = runDis / totalDis;; t = runDis / totalDis;;
} }
float d = new BigDecimal(t + "") float d = new BigDecimal(t).setScale(3, RoundingMode.HALF_UP).floatValue();
.setScale(3, RoundingMode.HALF_UP).floatValue();
log.debug("车次[{}] 方向[{}] 车头区段[{}] 车尾区段[{}] 是否停靠[{}] 查找开始区段[{}] 结束区段[{}] 距离总长[{}] 剩余距离[{}] 行驶完成度[{}]" log.debug("车次[{}] 方向[{}] 车头区段[{}] 车尾区段[{}] 是否停靠[{}] 查找开始区段[{}] 结束区段[{}] 距离总长[{}] 剩余距离[{}] 行驶完成度[{}]"
,train.getGroupNumber(),train.isRight(),train.getHeadPosition().getSection().getCode() ,train.getGroupNumber(),train.isRight(),train.getHeadPosition().getSection().getCode()
,train.getTailPosition().getSection().getCode(),train.isParkingAt(),begin.getCode(),end.getCode() , totalDis ,train.getTargetDistance() ,d); ,train.getTailPosition().getSection().getCode(),train.isParkingAt(),begin.getCode(),end.getCode() , totalDis ,train.getTargetDistance() ,d);
d = Math.abs(d); return Math.abs(d);
return d;
}catch (Exception e){ }catch (Exception e){
log.error("计算失败 groupNum:{},isRight:{},begin:{},end:{},totalDis:{},targetDis:{}",train.getGroupNumber() ,train.isRight(),begin.getCode() ,end.getCode() ,totalDis , train.getTargetDistance()); log.error("计算失败 groupNum:{},isRight:{},begin:{},end:{},totalDis:{},targetDis:{}",train.getGroupNumber() ,train.isRight(),begin.getCode() ,end.getCode() ,totalDis , train.getTargetDistance());
return null; return null;
} }
} }
public static class KmStation{
private List<Station> stationList;
public KmStation(Simulation simulation){
List<Station> list = simulation.getRepository().getListByType(MapElement.DeviceType.STATION,Station.class);
stationList = list.stream().sorted((o1, o2) -> Float.compare(o1.getKmPostVal(),o2.getKmPostVal())).filter(d->!d.isDepot()).collect(Collectors.toList());
}
public int findIndex(Station station){
return IntStream.range(0,stationList.size()).filter(d->Objects.equals(stationList.get(d).getCode(),station.getCode())).findFirst().getAsInt();
}
public Station findNext(Station station,boolean isRight){
int index = this.findIndex(station);
if(isRight){
return stationList.get(index + 1);
}else{
return stationList.get(index - 1);
}
}
public Station findPre(Station station,boolean isRight){
int index = this.findIndex(station);
if(isRight){
return stationList.get(index - 1);
}else{
return stationList.get(index + 1);
}
}
public Station find(Station station){
int index = this.findIndex(station);
return stationList.get(index);
}
}
public void addJobs(Simulation simulation){ public void addJobs(Simulation simulation){
simulation.addFixedRateJob(SimulationModule.TRAIN_DIAGRAM.name(), () -> collect(simulation), SimulationConstants.TRAIN_DIAGRAM_RATE); simulation.addFixedRateJob(SimulationModule.TRAIN_DIAGRAM.name(), () -> collect(simulation), SimulationConstants.TRAIN_DIAGRAM_RATE);
} }

View File

@ -4,12 +4,14 @@ import club.joylink.rtss.simulation.cbtc.data.map.Station;
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityTrain; import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityTrain;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.ToString;
/** /**
* ncc车站运行图例消息 * ncc车站运行图例消息
*/ */
@Data @Data
@NoArgsConstructor @NoArgsConstructor
@ToString
public class StationDiagram { public class StationDiagram {
@ -60,21 +62,23 @@ public class StationDiagram {
/** /**
* 运行开始车站 * 运行开始车站
*/ */
private String startStation; // private String startStation;
private String startStationCode; private String startStationCode;
/** /**
* 到达车站 * 到达车站
*/ */
private String targetStation; // private String targetStation;
private String targetStationCode; private String targetStationCode;
private boolean turnBack;
public void setStartStation(Station station){ public void setStartStation(Station station){
this.startStation = station.getName(); // this.startStation = station.getName();
this.startStationCode = station.getCode(); this.startStationCode = station.getCode();
} }
public void setEndStation(Station station){ public void setEndStation(Station station){
this.targetStation = station.getName(); // this.targetStation = station.getName();
this.targetStationCode = station.getCode(); this.targetStationCode = station.getCode();
} }
} }

View File

@ -0,0 +1,11 @@
package club.joylink.rtss.simulation.cbtc.ATS.service.diagram;
import club.joylink.rtss.simulation.cbtc.ATS.data.StationDiagram;
import club.joylink.rtss.simulation.cbtc.data.plan.TripPlan;
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityTrain;
import java.util.Optional;
public interface CalculateDiagram {
Optional<StationDiagram> calculate(VirtualRealityTrain train, TripPlan tripPlan);
}

View File

@ -465,7 +465,16 @@ public class Section extends DelayUnlockDevice {
} }
return null; return null;
} }
public Section findBackRunningSectionBaseRealSwitch(boolean right) {
if (right && Objects.nonNull(this.leftSection)) {
return this.leftSection;
} else if (!right && Objects.nonNull(this.rightSection)) {
return this.rightSection;
} else if (this.isSwitchTrack()) {
return this.getRelSwitch().getNextSectionBaseRealSwitch(this);
}
return null;
}
/** /**
* 获取左/右向关联的区段 * 获取左/右向关联的区段
* *

View File

@ -310,8 +310,8 @@ public class TrainInfo extends MapElement {
/** /**
* 车站之间的运行比例 * 车站之间的运行比例
*/ */
@Setter // @Setter
private Float stationDiagramRatio; // private Float stationDiagramRatio;
public TrainInfo(String groupNumber) { public TrainInfo(String groupNumber) {
super(groupNumber, DeviceType.TRAIN); super(groupNumber, DeviceType.TRAIN);
this.groupNumber = groupNumber; this.groupNumber = groupNumber;

View File

@ -851,10 +851,10 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
*/ */
public SectionPosition calculateBackStandStopPosition(){ public SectionPosition calculateBackStandStopPosition(){
SectionPosition tailPosition = this.tailPosition; SectionPosition tailPosition = this.tailPosition;
boolean right = !this.right; boolean right = this.right;
Section section = tailPosition.getSection(); Section section = tailPosition.getSection();
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++) {
section = section.findNextRunningSectionBaseRealSwitch(right); section = section.findBackRunningSectionBaseRealSwitch(right);
if (section == null) { if (section == null) {
break; break;
} }

View File

@ -20,7 +20,8 @@ public enum SimulationSubscribeTopic {
Room("/queue/room/{id}"), Room("/queue/room/{id}"),
Wgu3d("/topic/simulation/wgu3d/{id}"), Wgu3d("/topic/simulation/wgu3d/{id}"),
YJDDZH_TRAIN_POSITION("/topic/yjddzh/trainPosition/simulation/{id}"), YJDDZH_TRAIN_POSITION("/topic/yjddzh/trainPosition/simulation/{id}"),
RUN_FACT("/queue/simulation/{id}/runFact") RUN_FACT("/queue/simulation/{id}/runFact"),
NCC_DIAGRAM("/queue/diagram/simulation/{id}")
; ;
private String destPattern; private String destPattern;

View File

@ -213,7 +213,7 @@ public class MetroSimulationWorkServiceImpl implements SimulationWorkService {
atsLogicLoop.addJobs(simulation); atsLogicLoop.addJobs(simulation);
simulationRobotService.addJobs(simulation); simulationRobotService.addJobs(simulation);
vrTrainRunningService.addJobs(simulation); vrTrainRunningService.addJobs(simulation);
trainMessageDiagram.addJobs(simulation);
vrDeviceLogicLoop.addJobs(simulation); vrDeviceLogicLoop.addJobs(simulation);
ciLogic.addJobs(simulation); ciLogic.addJobs(simulation);
@ -221,6 +221,7 @@ public class MetroSimulationWorkServiceImpl implements SimulationWorkService {
faultGenerator.addJobs(simulation); faultGenerator.addJobs(simulation);
atsMessageCollectAndDispatcher.addJobs(simulation); atsMessageCollectAndDispatcher.addJobs(simulation);
nccAlarmService.addJobs(simulation); nccAlarmService.addJobs(simulation);
trainMessageDiagram.addJobs(simulation);
} }
@Override @Override

View File

@ -71,6 +71,10 @@ public class SocketMessageFactory {
private static List<String> getTopicsBy(WebSocketMessageType messageType, String group) { private static List<String> getTopicsBy(WebSocketMessageType messageType, String group) {
List<String> topicList = new ArrayList<>(); List<String> topicList = new ArrayList<>();
switch (messageType) { switch (messageType) {
case SIMULATION_NCC_STATION_DIAGRAM:{
topicList.add(SimulationSubscribeTopic.NCC_DIAGRAM.buildDestination(group));
break;
}
case YJDDZH_TRAIN_POSITION: { case YJDDZH_TRAIN_POSITION: {
topicList.add(SimulationSubscribeTopic.YJDDZH_TRAIN_POSITION.buildDestination(group)); topicList.add(SimulationSubscribeTopic.YJDDZH_TRAIN_POSITION.buildDestination(group));
@ -105,7 +109,6 @@ public class SocketMessageFactory {
case SIMULATION_RAIL_TICKET: case SIMULATION_RAIL_TICKET:
case Simulation_Alarm: case Simulation_Alarm:
case Simulation_Operation_Mode_Apply: case Simulation_Operation_Mode_Apply:
case SIMULATION_NCC_STATION_DIAGRAM:
case Simulation_Conversation_Group: { case Simulation_Conversation_Group: {
topicList.add(SimulationSubscribeTopic.Main.buildDestination(group)); topicList.add(SimulationSubscribeTopic.Main.buildDestination(group));
break; break;