Merge remote-tracking branch 'origin/test' into test

This commit is contained in:
walker-sheng 2021-02-04 18:02:28 +08:00
commit 3f35c48cb3
46 changed files with 589 additions and 156 deletions

View File

@ -3,6 +3,7 @@ package club.joylink.rtss.controller.simulation;
import club.joylink.rtss.controller.advice.AuthenticateInterceptor;
import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
import club.joylink.rtss.services.IVirtualRealityIbpService;
import club.joylink.rtss.services.simulation.SimulationSupportService;
import club.joylink.rtss.simulation.cbtc.ATS.data.AtsAlarm;
import club.joylink.rtss.simulation.cbtc.ATS.data.SimulationLog;
import club.joylink.rtss.simulation.cbtc.GroupSimulationService;
@ -10,6 +11,7 @@ import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.command.CommandInitiateVO;
import club.joylink.rtss.simulation.cbtc.communication.vo.fault.DeviceFaultInfo;
import club.joylink.rtss.simulation.cbtc.data.status.IbpStatus;
import club.joylink.rtss.simulation.cbtc.data.vo.RoutePathVO;
import club.joylink.rtss.simulation.cbtc.data.vo.SimulationVO;
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityIbp;
import club.joylink.rtss.simulation.cbtc.member.SimulationMember;
@ -55,6 +57,9 @@ public class SimulationV1Controller {
@Autowired
private IVirtualRealityIbpService iVirtualRealityIBPService;
@Autowired
private SimulationSupportService simulationSupportService;
@ApiOperation(value = "根据产品类型创建仿真")
@GetMapping("")
public String simulation(Long mapId, String prdType,
@ -300,4 +305,10 @@ public class SimulationV1Controller {
public PageVO<SimulationLog> getLog(@PathVariable String group, SimulationLogPagedQueryVO queryVO) {
return groupSimulationService.getLog(group, queryVO);
}
@ApiOperation("查询进路路径")
@GetMapping("/{group}/queryRoutePaths")
public List<RoutePathVO> queryRoutePaths(@PathVariable String group, String groupNumber, String standCode, String signalCode) {
return simulationSupportService.queryRoutePaths(group, groupNumber, standCode, signalCode);
}
}

View File

@ -0,0 +1,45 @@
package club.joylink.rtss.services.simulation;
import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
import club.joylink.rtss.simulation.cbtc.GroupSimulationService;
import club.joylink.rtss.simulation.cbtc.Simulation;
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.Signal;
import club.joylink.rtss.simulation.cbtc.data.map.Stand;
import club.joylink.rtss.simulation.cbtc.data.support.RoutePath;
import club.joylink.rtss.simulation.cbtc.data.vo.RoutePathVO;
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityTrain;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.util.List;
/**
* 仿真运行支持
*/
@Service
public class SimulationSupportService {
@Autowired
private GroupSimulationService groupSimulationService;
public List<RoutePathVO> queryRoutePaths(String group, String groupNumber, String standCode, String signalCode) {
Simulation simulation = groupSimulationService.getSimulationByGroup(group);
Section destination;
if (StringUtils.hasText(standCode)) {
Stand stand = simulation.getRepository().getByCode(standCode, Stand.class);
destination = stand.getSection();
} else if (StringUtils.hasText(signalCode)) {
Signal signal = simulation.getRepository().getByCode(signalCode, Signal.class);
destination = signal.getSection();
} else {
throw BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.exception("站台和信号机必须选一个");
}
VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber);
Section startSection = train.getHeadPosition().getSection();
List<RoutePath> routePaths = CalculateService.queryRoutePathsOnDirection(startSection, destination, train.isRight());
return RoutePathVO.convert(routePaths);
}
}

View File

@ -1,22 +1,22 @@
package club.joylink.rtss.services.training.generatornew;
import club.joylink.rtss.constants.BusinessConsts;
import club.joylink.rtss.services.training.constant.TrainingConsts;
import club.joylink.rtss.services.training.data.GenerateConfig;
import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.data.map.*;
import club.joylink.rtss.simulation.cbtc.data.storage.StorageSimulation;
import club.joylink.rtss.constants.BusinessConsts;
import club.joylink.rtss.util.ReflectionUtils;
import club.joylink.rtss.vo.client.map.newmap.MapTurnBackStrategyVO;
import club.joylink.rtss.vo.client.training.definition.OperateDefinitionVO;
import club.joylink.rtss.vo.client.training.definition.OperatePlaceholderVO;
import club.joylink.rtss.vo.client.training.definition.OperateStepVO;
import club.joylink.rtss.vo.client.map.MapVO;
import club.joylink.rtss.vo.client.map.newmap.MapAutomaticRouteButtonVO;
import club.joylink.rtss.vo.client.map.newmap.MapCycleButtonVO;
import club.joylink.rtss.vo.client.map.newmap.MapTotalGuideLockButtonVO;
import club.joylink.rtss.vo.client.map.newmap.MapTurnBackStrategyVO;
import club.joylink.rtss.vo.client.training.TrainingNewVO;
import club.joylink.rtss.vo.client.training.TrainingStepVO;
import org.springframework.util.CollectionUtils;
import club.joylink.rtss.vo.client.training.definition.OperateDefinitionVO;
import club.joylink.rtss.vo.client.training.definition.OperatePlaceholderVO;
import club.joylink.rtss.vo.client.training.definition.OperateStepVO;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
@ -97,6 +97,9 @@ public interface GeneratorNew {
} else if (mapButton instanceof MapTurnBackStrategyVO) {
s.setDeviceCode(((MapTurnBackStrategyVO) mapButton).getCode());
break;
} else if (mapButton instanceof MapTotalGuideLockButtonVO) {
s.setDeviceCode(((MapTotalGuideLockButtonVO) mapButton).getCode());
break;
}
}
case NULL:
@ -128,6 +131,8 @@ public interface GeneratorNew {
trainingVO.setLocateDeviceCode(((MapAutomaticRouteButtonVO) mapButton).getCode());
} else if (mapButton instanceof MapTurnBackStrategyVO) {
trainingVO.setLocateDeviceCode(((MapTurnBackStrategyVO) mapButton).getCode());
} else if (mapButton instanceof MapTotalGuideLockButtonVO) {
trainingVO.setLocateDeviceCode(((MapTotalGuideLockButtonVO) mapButton).getCode());
}
}
}

View File

@ -5,8 +5,10 @@ import club.joylink.rtss.services.training.generatornew.GeneratorNew;
import club.joylink.rtss.services.training.generatornew.annotation.GeneratorSelectorNew;
import club.joylink.rtss.simulation.cbtc.ATS.operation.Operation;
import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.build.SimulationBuilder;
import club.joylink.rtss.simulation.cbtc.data.map.Cycle;
import club.joylink.rtss.simulation.cbtc.data.map.Route;
import club.joylink.rtss.simulation.cbtc.data.map.SectionPath;
import club.joylink.rtss.simulation.cbtc.data.map.Signal;
import club.joylink.rtss.simulation.cbtc.tool.DeviceStatusModifyTool;
import club.joylink.rtss.vo.client.training.definition.OperateDefinitionVO;
@ -179,17 +181,16 @@ public class SignalGeneratorNew implements GeneratorNew {
case Signal_Human_Release_Route: {
// 查询信号机为始端的进路列表设置背景为进路排列且进路接近区段占用
// todo 接近区段设置列车逻辑较复杂推迟实现
for (Route route : signal.getRouteList()) {
deviceStatusModifyTool.openRouteDirect(simulation, route);
deviceStatusModifyTool.closeSignalDirectly(route.getStart());
deviceStatusModifyTool.loadManualTrainOfGroup(simulation, "001", signal.getSection(), signal.isRight());
// todo 在接近区段设置一辆列车
trainingVOList.add(this.build(config, simulation, signal, null, operateDefinitionVO));
// 仿真重置
simulation.reset();
}
continue;
// List<Route> routeList = signal.getRouteList();
// for (Route route : routeList) {
// deviceStatusModifyTool.openRouteDirect(simulation, route);
// List<Section> approachSectionList = signal.getApproachSectionList();
// // todo 在接近区段设置一辆列车
// trainingVOList.add(this.build(config, simulation, signal, operateDefinitionVO));
// // 仿真重置
// simulation = SimulationBuilder.build(simulation.getBuildParams());
// }
// continue;
}
case Signal_Close_Signal: {
// 查询进路设置背景为进路已排列
@ -328,26 +329,28 @@ public class SignalGeneratorNew implements GeneratorNew {
}
case Signal_Set_Guide: {
// 若信号机可开引导信号则生成实训暂不设置背景暂时先简单处理此处业务比较复杂需明确后再生成各种情况的实训
// if (!signal.isCallOn()) { // 不是引导信号机不生成
// continue;
// } else {
// //非折返进路办理引导
// List<Route> notTurnBackRouteList = routeList.stream()
// .filter(route -> !route.isTurnBack())
// .collect(Collectors.toList());
// if (routeLikeHa1) {
// // 对于ATP进路地面联锁进路引导进路类的取引导进路
// notTurnBackRouteList = notTurnBackRouteList.stream()
// .filter(route -> route.isGuide())
// .collect(Collectors.toList());
// }
// for (Route route : notTurnBackRouteList) {
// trainingVOList.add(this.build(config, simulation, route, operateDefinitionVO));
// // 仿真重置
// simulation.reset();
// }
// continue;
// }
if (signal.isCallOn()) { // 不是引导信号机不生成
//非折返进路办理引导
List<Route> notTurnBackRouteList = routeList.stream()
.filter(route -> !route.isTurnBack())
.collect(Collectors.toList());
if (routeLikeHa1) {
// 对于ATP进路地面联锁进路引导进路类的取引导进路
notTurnBackRouteList = notTurnBackRouteList.stream()
.filter(route -> route.isGuide())
.collect(Collectors.toList());
}
for (Route route : notTurnBackRouteList) {
if(simulation.getRepository().getConfig().isGuideNeedRouteSettingFirst()){
deviceStatusModifyTool.openRouteDirect(simulation, route);
deviceStatusModifyTool.closeSignalDirectly(route.getStart());
}
deviceStatusModifyTool.loadManualTrainOfGroup(simulation, "001",signal.getSection(),signal.isRight());
trainingVOList.add(this.build(config, simulation, route,null, operateDefinitionVO));
// 仿真重置
simulation.reset();
}
}
continue;
}
case Signal_Close_Guide: {

View File

@ -6,15 +6,21 @@ import club.joylink.rtss.services.training.generatornew.annotation.GeneratorSele
import club.joylink.rtss.simulation.cbtc.ATS.operation.Operation;
import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.constant.TrainType;
import club.joylink.rtss.simulation.cbtc.data.SimulationDataRepository;
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.map.Stand;
import club.joylink.rtss.constants.MapPrdTypeEnum;
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.vo.TrainInfo;
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityDevice;
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityTrain;
import club.joylink.rtss.simulation.cbtc.tool.DeviceStatusModifyTool;
import club.joylink.rtss.vo.client.training.definition.OperateDefinitionVO;
import club.joylink.rtss.vo.client.training.TrainingNewVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import java.util.*;
@ -22,6 +28,8 @@ import java.util.*;
public class StandGeneratorNew implements GeneratorNew {
protected static final int PARKING_TIME = 20;
@Autowired
private DeviceStatusModifyTool deviceStatusModifyTool;
@Override
public List<TrainingNewVO> generate(GenerateConfig config, Simulation simulation, OperateDefinitionVO operateDefinitionVO) {
@ -43,9 +51,11 @@ public class StandGeneratorNew implements GeneratorNew {
stand.setTypeStrategy(Stand.TurnBackType.AUTO);
break;
case Stand_Set_Hold_Train_Auto:
stand.setTrainLimit(-1);
break;
case Stand_Cancel_Hold_Train_Auto:
// 功能暂未实现不生成
continue;
stand.setTrainLimit(3);
break;
case Stand_Set_Jump_Stop: {
// todo 应该设置列车在上一车站暂时简单处理
// 终点车站正常应不能设置跳停暂时也不处理
@ -69,9 +79,15 @@ public class StandGeneratorNew implements GeneratorNew {
standList.forEach(stand1 -> stand1.setCenterHoldTrain(true));
break;
}
case Stand_Early_Depart:{
// 提前发车需要列车暂不生成
continue;
case Stand_Early_Depart: {
List<Route> routeList = simulation.getRepository().getRouteList();
Route route = routeList.stream().filter(route1 ->
(route1.getStart().getSection() == stand.getSection() || route1.containSection(stand.getSection()) && !route1.routeLastSection(stand.getSection())) && Objects.equals(stand.isRight(), route1.getStart().isRight())).findAny().orElse(null);
if (Objects.nonNull(route)) {
deviceStatusModifyTool.openRouteDirect(simulation, route);
}
deviceStatusModifyTool.loadManualTrainOfGroup(simulation, "001", stand.getSection(), stand.isRight());
break;
}
case Stand_Cancel_Jump_Stop:{
// 设置背景为全部跳停

View File

@ -5,11 +5,14 @@ import club.joylink.rtss.services.training.generatornew.GeneratorNew;
import club.joylink.rtss.services.training.generatornew.annotation.GeneratorSelectorNew;
import club.joylink.rtss.simulation.cbtc.ATS.operation.Operation;
import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.data.map.Route;
import club.joylink.rtss.simulation.cbtc.data.map.Station;
import club.joylink.rtss.simulation.cbtc.data.map.*;
import club.joylink.rtss.simulation.cbtc.tool.DeviceStatusModifyTool;
import club.joylink.rtss.vo.client.training.definition.OperateDefinitionVO;
import club.joylink.rtss.vo.client.training.TrainingNewVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@ -17,7 +20,8 @@ import java.util.stream.Collectors;
@GeneratorSelectorNew(operateObject = Operation.Object.Station)
public class StationGeneratorNew implements GeneratorNew {
@Autowired
private DeviceStatusModifyTool deviceStatusModifyTool;
@Override
public List<TrainingNewVO> generate(GenerateConfig config, Simulation simulation, OperateDefinitionVO operateDefinitionVO) {
List<TrainingNewVO> trainingVOList = new ArrayList<>();
@ -105,14 +109,66 @@ public class StationGeneratorNew implements GeneratorNew {
});
continue;
}
// simulation.getRepository().getSignalList().stream()
// .filter(s -> Objects.equals(station.getCode(), s.getDeviceStation().getCode()))
// .forEach(signal -> {
// if (!signal.isBlockade()) {
// signal.setBlockade(false);
// }
// });
break;
case Station_Power_On_Unlock:
if(!station.isCentralized()) {
continue;
}
station.setControlMode(Station.ControlMode.Local);
station.setRestartTime(LocalTime.now());
List<Section> sections = simulation.getRepository().getSectionList();
sections.stream().filter(section -> Objects.equals(section.getDeviceStation(), station)).forEach(section -> section.setFaultLock(true));
break;
case Station_Set_Master_Guide_Lock:
if(!station.isCentralized()) {
continue;
}
station.setControlMode(Station.ControlMode.Local);
List<Switch> switchList = simulation.getRepository().getSwitchList();
List<Switch> collect = switchList.stream().filter(
aSwitch -> Objects.equals(aSwitch.getDeviceStation(), station)).collect(Collectors.toList());
collect.forEach(aSwitch -> aSwitch.setFault(Switch.SwitchFault.SPLIT));
station.setControlMode(Station.ControlMode.Center);
if (operateDefinitionVO.guideTotalLockButton()) {
simulation.getBuildParams().getMap().getGraphDataNew().getTotalGuideLockButtonVOList()
.stream().filter(guideLockButtonVO -> guideLockButtonVO.getStationCode().equals(station.getCode()))
.forEach(button -> {
trainingVOList.add(this.build(config, simulation, station, button, operateDefinitionVO));
simulation.reset();
});
continue;
}
break;
case Station_Cancel_Master_Guide_Lock:
if(station.isCentralized()) {
station.setTotalGuideLock(true);
station.setControlMode(Station.ControlMode.Local);
List<Switch> switchList1 = simulation.getRepository().getSwitchList();
switchList1.stream().filter(aSwitch -> Objects.equals(aSwitch.getDeviceStation(), station)).forEach(aSwitch -> aSwitch.setSingleLock(true));
List<Signal> signalList = simulation.getRepository().getSignalList();
signalList.stream().filter(signal -> Objects.equals(signal.getDeviceStation(), station)).forEach(signal -> {
if (signal.isCallOn()) {
List<Route> routeList = signal.getRouteList();
if (!CollectionUtils.isEmpty(routeList)) {
for (Route route : routeList) {
if (!route.isTurnBack()) {
this.deviceStatusModifyTool.openGuideRouteDirect(simulation, route);
trainingVOList.add(this.build(config, simulation, station, null, operateDefinitionVO));
// 仿真重置
simulation.reset();
break;
}
}
} else if (Objects.nonNull(signal.getAutoSignal())) { // 信号机是自动信号
this.deviceStatusModifyTool.openGuideSignalDirectly(signal);
trainingVOList.add(this.build(config, simulation, station, null, operateDefinitionVO));
// 仿真重置
simulation.reset();
}
}
});
}
continue;
default:
// 其他操作不生成
continue;

View File

@ -141,6 +141,13 @@ public class ZCLogicLoop {
int count = 0;
while (count < 50) {
++count;
// 区段未进路锁闭或延时解锁中转换轨除外因为出库列车加载到转换轨没有进路
if (!section.isTransferTrack()) {
if (!section.isRouteLockOn(right) || section.isDelayUnlock()) {
deviceEnd = new MovementAuthority.End(section, MovementAuthority.EndType.UNLOCK_SECTION);
break;
}
}
// 站台屏蔽门
MovementAuthority.End psdEnd = checkPsdOpen(section, tailPosition);
if (Objects.nonNull(psdEnd)) {

View File

@ -179,9 +179,9 @@ public class Operation {
Stand_Set_Hold_Train_Batch(),
/**批量取消扣车*/
Stand_Cancel_Hold_Train_Batch(),
/** 区间列车数量限制 */
/** 区间列车数量限制(自动扣车) */
Stand_Set_Hold_Train_Auto(),
/** 取消区间列车数量限制 */
/** 取消区间列车数量限制(取消自动扣车) */
Stand_Cancel_Hold_Train_Auto(),
/** 站台总取消 */
Stand_Total_Cancel,
@ -209,6 +209,8 @@ public class Operation {
CM_Surrender_Control(),
/** 连锁控 */
CM_Interlock_Control(),
/** 回复中控请求(同意/拒绝) */
CM_Reply_Interlock_Control(),
//--------------------------- 集中车站 ---------------------------
/** 设置折返策略 */
@ -305,6 +307,8 @@ public class Operation {
Train_Trust,
/** 连挂 */
Train_Link,
/** 排列进路到 */
Train_Set_Route,
//--------------------------- 司机 ---------------------------
/** 改变列车的牵引/制动力 */

View File

@ -59,7 +59,7 @@ public class DriverOperateHandler {
train.updateTBForce(0, 350);
} else {
throw new SimulationException(SimulationExceptionType.Illegal_Argument,
String.format("列车牵引/制动力可调整比例范围应该在[-1, 1]之间,或为紧急制动-2"));
String.format("数值[%s]超限,列车牵引/制动力可调整比例范围应该在[-1, 1]之间,或为紧急制动-2", percent));
}
if (train.isAtoOn()) {
this.ATOService.closeATO(train);

View File

@ -137,8 +137,8 @@ public class StandOperateHandler {
* 区间列车数量限制
*/
@OperateHandlerMapping(type = Operation.Type.Stand_Set_Hold_Train_Auto)
public void setHoldTrainAuto() {
throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL, "功能暂未实现");
public void setHoldTrainAuto(Simulation simulation, String standCode, int limit) {
atsStandService.setAutoHoldTrainLimit(simulation, standCode, limit);
}
@ -146,8 +146,8 @@ public class StandOperateHandler {
* 取消区间列车数量限制
*/
@OperateHandlerMapping(type = Operation.Type.Stand_Cancel_Hold_Train_Auto)
public void cancelHoldTrainAuto() {
throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL, "功能暂未实现");
public void cancelHoldTrainAuto(Simulation simulation, String standCode) {
atsStandService.setAutoHoldTrainLimit(simulation, standCode, -1);
}

View File

@ -102,9 +102,9 @@ public class StationOperateHandler {
* 上电解锁
*/
@OperateHandlerMapping(type = Operation.Type.Station_Power_On_Unlock)
public void powerOnUnlock() {
throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL, "功能暂未实现");
public void powerOnUnlock(Simulation simulation, String stationCode) {
SimulationDataRepository repository = simulation.getRepository();
ciApiService.powerOnUnlock(simulation, repository.getByCode(stationCode, Station.class));
}
/**
@ -143,6 +143,12 @@ public class StationOperateHandler {
atsStationService.applyForCenterControl(simulation, fromMember, stationCodes);
}
/**连锁控*/
@OperateHandlerMapping(type = Operation.Type.CM_Interlock_Control)
public void applyForInterlockControl(Simulation simulation, SimulationMember fromMember, List<String> stationCodes){
atsStationService.applyForInterlockControl(simulation, fromMember, stationCodes);
}
/**强制站控-l*/
@OperateHandlerMapping(type = Operation.Type.CM_Force_Station_Control)
public void forceForStationControl(Simulation simulation, SimulationMember fromMember, List<String> stationCodes){

View File

@ -13,6 +13,7 @@ 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.RoutePathVO;
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityTrain;
import club.joylink.rtss.simulation.cbtc.exception.SimulationException;
import club.joylink.rtss.simulation.cbtc.exception.SimulationExceptionType;
@ -316,4 +317,12 @@ public class TrainOperateHandler {
public void link(Simulation simulation, String groupNumber, String groupNumber2) {
atsTrainService.link(simulation, groupNumber, groupNumber2);
}
/**
* 排列进路到站台/信号机泰雷兹
*/
@OperateHandlerMapping(type = Operation.Type.Train_Link)
public void setRouteTo(Simulation simulation, RoutePathVO routePath) {
atsTrainService.setRouteTo(simulation, routePath);
}
}

View File

@ -159,7 +159,7 @@ public class AtsPlanService {
// 更新跳停状态
if (jump && Objects.equals(tripPlan.getLastStationPlan().getStation(), target.getStation())) {
// 最后一站不跳停
jump = false;
jump = true;
}
if (!Objects.equals(train.isJump(), jump)) {
if (jump) {

View File

@ -39,6 +39,7 @@ public class AtsRouteSettingService {
// 执行进路排列
for (TrainRoute trainRoute : waitSetList) {
Route route = trainRoute.getRoute();
route.setTrain(trainRoute.getTrain());
this.ciApiService.settingRoute(simulation, route.getCode());
}
}

View File

@ -240,10 +240,12 @@ public class AtsStandService {
*/
public void earlyDepart(Simulation simulation, String standCode) {
Stand stand = getStand(simulation, standCode);
if (!simulation.getRepository().getConfig().isAllowEarlyDepartureWhenHoldTrain()) {
if (stand.isHoldTrain()) {
throw new SimulationException(SimulationExceptionType.Operation_Conflict,
"站台处于扣车状态,不能提前发车");
}
}
if (!stand.isTrainParking()) {
throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL,
"没有列车在该站台停靠");
@ -277,6 +279,14 @@ public class AtsStandService {
stand.setRunLevelTimeForever(alwaysValid);
}
/**
* 设置站间列车数量
*/
public void setAutoHoldTrainLimit(Simulation simulation, String standCode, int limit) {
Stand stand = getStand(simulation, standCode);
stand.setTrainLimit(limit);
}
/**
* 设置人工折返策略
*/
@ -407,7 +417,7 @@ public class AtsStandService {
public void manualOpenPsd(Simulation simulation, String standCode) {
SimulationDataRepository repository = simulation.getRepository();
Stand stand = repository.getByCode(standCode, Stand.class);
stand.getPsd().getVirtualScreenDoor().updateLockAndClose(false, true);
stand.getPsd().getVirtualScreenDoor().updateOpen2End(true);
}
/**

View File

@ -61,7 +61,7 @@ public class AtsStationService {
station.setTotalGuideLock(true);
List<Switch> switches = simulation.getRepository().getSwitchListByDeviceStationCode(station.getCode());
if (!CollectionUtils.isEmpty(switches)) {
switches.forEach(s -> s.setMasterGuideLock(true));
switches.forEach(s -> s.setSingleLock(true));
}
}
@ -77,7 +77,7 @@ public class AtsStationService {
station.setTotalGuideLock(false);
List<Switch> switches = simulation.getRepository().getSwitchListByDeviceStationCode(station.getCode());
if (!CollectionUtils.isEmpty(switches)) {
switches.forEach(s -> s.setMasterGuideLock(false));
switches.forEach(s -> s.setSingleLock(false));
}
}
@ -217,6 +217,20 @@ public class AtsStationService {
}
/**
* 请求连锁控处理
*/
public void applyForInterlockControl(Simulation simulation, SimulationMember fromMember, List<String> stationCodes) {
if (CollectionUtils.isEmpty(stationCodes)) {
throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL, "连锁控的车站不能为空");
}
stationCodes.forEach(stationCode -> {
Station station = getStation(simulation, stationCode);
station.setControlMode(Station.ControlMode.Interlock);
});
atsMessageCollectAndDispatcher.handlerOperateMessage(simulation, new OperationMessage(fromMember.getId(), new HashSet<>(Collections.singleton(fromMember)), Operation.Type.CM_Reply_Interlock_Control, null, true, stationCodes));
}
/**
* 回复站控请求c
*/

View File

@ -1,6 +1,7 @@
package club.joylink.rtss.simulation.cbtc.ATS.service;
import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
import club.joylink.rtss.simulation.cbtc.CI.CiApiService;
import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.constant.SimulationModule;
import club.joylink.rtss.simulation.cbtc.constant.TrainType;
@ -11,6 +12,7 @@ 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.vo.RoutePathVO;
import club.joylink.rtss.simulation.cbtc.data.vo.TrainInfo;
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityTrain;
import club.joylink.rtss.simulation.cbtc.exception.SimulationException;
@ -36,6 +38,9 @@ public class AtsTrainService {
@Autowired
private AtsStandService atsStandService;
@Autowired
private CiApiService ciApiService;
@Autowired
private OnboardAtpApiService onboardAtpApiService;
@ -884,4 +889,11 @@ public class AtsTrainService {
}
activeTrain.setLinkTrain(passiveTrain);
}
/**
* 排列进路到站台/信号机
*/
public void setRouteTo(Simulation simulation, RoutePathVO routePath) {
routePath.getRouteList().forEach(routeCode -> ciApiService.settingRoute(simulation, routeCode));
}
}

View File

@ -305,6 +305,9 @@ public interface CiApiService {
*/
void restart(Simulation simulation, Station station);
/**上电解锁*/
void powerOnUnlock(Simulation simulation, Station station);
/**
* 站台紧急停车
*/

View File

@ -18,6 +18,7 @@ import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.time.LocalTime;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
@ -98,6 +99,9 @@ public class CiApiServiceImpl implements CiApiService {
String.format("进路[%s(%s)]联锁关系不满足,不能重开信号机", lockedRoute.getName(), lockedRoute.getCode()));
}
this.routeService.routeOpen(simulation, lockedRoute);
if (lockedRoute.isDelayUnlocking()) {
lockedRoute.cancelDelayUnlocking();
}
}
@Override
@ -397,7 +401,7 @@ public class CiApiServiceImpl implements CiApiService {
}
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertTrue(signal.isClose(), String.format("信号机[%s]需处于关闭状态", signal.getCode()));
boolean signalApproachOccupied = signal.getApproachPathList()
.stream().anyMatch(sectionPath -> sectionPath.getLogicList().stream().anyMatch(Section::isOccupied));
.stream().anyMatch(sectionPath -> sectionPath.getSectionList().stream().anyMatch(Section::isOccupied));
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertTrue(signalApproachOccupied,
String.format("对%s开放引导操作失败接近区段没有列车占用", signal.getName()));
//办理引导进路或开放引导信号
@ -468,8 +472,21 @@ public class CiApiServiceImpl implements CiApiService {
.filter(signal -> signal.getDeviceStation().equals(deviceStation)).collect(Collectors.toList());
signals.forEach(Signal::reset);
deviceStation.setInterlockMachineStarting(false);
deviceStation.setRestartTime(LocalTime.now());
}
@Override
public void powerOnUnlock(Simulation simulation, Station station){
if (!station.isCentralized()) {
station = station.getDeviceStation();
}
Station deviceStation = station;
if (Objects.nonNull(deviceStation.getRestartTime()) && deviceStation.getRestartTime().plusMinutes(8).isBefore(LocalTime.now())) {
List<Section> sections = simulation.getRepository().getSectionList();
sections.stream().filter(section -> Objects.equals(section.getDeviceStation(), deviceStation)).forEach(Section::faultUnlock);
}
throw BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.exception("无效操作或连锁机重启过8分钟需手动解锁");
}
@Override
public void standEB(Simulation simulation, Stand stand) {
if (stand.getEsp() == null)

View File

@ -703,7 +703,9 @@ public class RouteService {
} else {
route.setAtsControl(false);
}
if (!route.isDelayUnlocking()) {
this.cancelWithoutCheck(simulation, route);
}
} else {
log.info(String.format("进路[%s(%s)]未锁闭,不需要取消进路。",
route.getName(), route.getCode()));
@ -726,6 +728,8 @@ public class RouteService {
log.debug(String.format("取消进路,信号机[%s(%s)]关灯",
route.getStart().getName(), route.getStart().getCode()));
route.getStart().setLevel(Signal.LEVEL_1);
// 始端信号机锁闭进路置为null
route.getStart().setLockedRoute(null);
// 进路区段取消锁闭
boolean right = route.getStart().isRight();
List<Section> sectionList = route.getSectionList();

View File

@ -104,7 +104,7 @@ public class SectionService {
Signal start = lockedRoute.getStart();
this.signalService.close(simulation, start);
if (start.getLockedRoute() == lockedRoute) {
start.setLockedRoute(lockedRoute);
start.setLockedRoute(null);
}
}
section.faultUnlock();

View File

@ -29,10 +29,10 @@ public class SignalService {
public void blockade(Simulation simulation, Signal signal) {
if(!signal.isBlockade()) {
signal.setBlockade(true);
if (signal.getLockedRoute() != null) {
signal.setReblockade(true);
log.debug(signal.debugStr() + "因信号机封锁且有锁闭的进路而重复封锁");
}
// if (signal.getLockedRoute() != null) {
// signal.setReblockade(true);
// log.debug(signal.debugStr() + "因信号机封锁且有锁闭的进路而重复封锁");
// }
}
}

View File

@ -145,7 +145,7 @@ public class SwitchService {
Signal start = route.getStart();
route.setLock(false);
if (start.getLockedRoute() == route) {
start.setLockedRoute(route);
start.setLockedRoute(null);
}
}
}

View File

@ -1,5 +1,6 @@
package club.joylink.rtss.simulation.cbtc.competition;
import club.joylink.rtss.services.IVoiceService;
import club.joylink.rtss.simulation.cbtc.ATS.operation.Operation;
import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.SimulationLifeCycleService;
@ -18,7 +19,6 @@ import club.joylink.rtss.simulation.cbtc.exception.SimulationExceptionType;
import club.joylink.rtss.simulation.cbtc.member.SimulationMember;
import club.joylink.rtss.simulation.cbtc.script.ScriptActionBO;
import club.joylink.rtss.simulation.cbtc.script.ScriptBO;
import club.joylink.rtss.services.IVoiceService;
import club.joylink.rtss.vo.UserVO;
import club.joylink.rtss.vo.client.competition.OperationIndexStatistic;
import club.joylink.rtss.vo.client.competition.OperationStatisticVO;
@ -314,10 +314,10 @@ public class CompetitionAndScriptManager {
for (String num : split) {
switch (num) {
case "1":
sb.append("[1一幺妖腰摇要]");
sb.append("[1一幺妖腰摇要]");
break;
case "2":
sb.append("[两梁良亮辆]");
sb.append("[两梁良亮辆]");
break;
case "3":
sb.append("[3三]");

View File

@ -3,7 +3,10 @@ package club.joylink.rtss.simulation.cbtc.conversation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -37,7 +40,7 @@ public class SimulationVoiceHandler {
replacementList.add(new Replacement("(茼蒿)", "通号"));
replacementList.add(new Replacement("", ""));
replacementList.add(new Replacement("自动折法", "自动折返"));
replacementList.add(new Replacement("(倒插|刀叉|倒茶|倒叉|到插|倒闸)", "道岔"));
replacementList.add(new Replacement("(倒插|刀叉|倒茶|倒叉|到插|倒闸|到察|到厂|道碴)", "道岔"));
replacementList.add(new Replacement("(师表|手表|时表)", "失表"));
replacementList.add(new Replacement("攻作组", "工作组"));
replacementList.add(new Replacement("军事表", "均失表"));
@ -74,14 +77,16 @@ public class SimulationVoiceHandler {
replacementList.add(new Replacement("(首领处所)", "受令处所"));
replacementList.add(new Replacement("安全保护", "安全防护"));
replacementList.add(new Replacement("(手摇质|说杨智|受邀至)", "手摇至"));
replacementList.add(new Replacement("(反胃)", "反位"));
replacementList.add(new Replacement("(反胃|软位)", "反位"));
replacementList.add(new Replacement("所逼", "锁闭"));
replacementList.add(new Replacement("位直", "位置"));
replacementList.add(new Replacement("丞将|成强|成交|沉降", "乘降"));
replacementList.add(new Replacement("售电弓|售电工", "受电弓"));
replacementList.add(new Replacement("售电弓|售电工|收电弓|数电弓", "受电弓"));
replacementList.add(new Replacement("故障回复", "故障恢复"));
replacementList.add(new Replacement("(出入断线|出路段线)", "出入段线"));
replacementList.add(new Replacement("(控子权|控质权)", "控制权"));
replacementList.add(new Replacement("(控子权|控质权|放置权|矿质权|空置权)", "控制权"));
replacementList.add(new Replacement("(手机号)", "手信号"));
replacementList.add(new Replacement("(鼓掌|部长)", "故障"));
//------------- 设备相关 --------------
replacementList.add(new Replacement("(宇花祭|玉花祭|雨化寨|氯化钙|绿化带|优化钙)", "鱼化寨"));
replacementList.add(new Replacement("(保税局)", "保税区"));

View File

@ -301,7 +301,7 @@ public class CalculateService {
}
distance = isRight ?
distance - startSection.getStopPointByDirection(isRight) + endSection.getStopPointByDirection(isRight) :
distance - startSection.getLen() + startSection.getStopPointByDirection(isRight) + endSection.getLen()-endSection.getStopPointByDirection(isRight);
distance - startSection.getLen() + startSection.getStopPointByDirection(isRight) + endSection.getLen() - endSection.getStopPointByDirection(isRight);
return distance;
}
@ -718,7 +718,7 @@ public class CalculateService {
list.add(routePath);
} else {
routePath.addSections(sectionList);
queryRoutePaths(iter+1, route.getLastRouteSection(), routePath, list, warnList);
queryRoutePaths(iter + 1, route.getLastRouteSection(), routePath, list, warnList);
}
return;
}
@ -814,8 +814,9 @@ public class CalculateService {
/**
* 查找从startSection到destination的途径区段路径
*/
public static Set<List<Section>> querySectionPaths2Destination(Section startSection, Section destination,
Boolean right, boolean stop) {
@NonNull
public static Set<List<Section>> querySectionPaths2Destination(@NonNull Section startSection, @NonNull Section destination,
@NonNull Boolean right, @NonNull Boolean stop) {
long start = System.currentTimeMillis();
//从startSection开始寻找第一个同向信号机如果是折返轨两边的信号机都算并记录途径区段
List<Signal> signals = new ArrayList<>();
@ -889,6 +890,7 @@ public class CalculateService {
/**
* 从signal找到destination的进路并记录途径区段
* 用来找到某目的地码的路径
*
* @param destination 目的地码对应的区段
* @param followSettingRoute 是否要沿着已经/正在排列的进路找路径
*/
@ -1053,22 +1055,31 @@ public class CalculateService {
* 计算考虑时间的ato最大速度
*/
public static Float calculateAtoSpeedMax4RunTime(VirtualRealityTrain train, long runTime) {
if (train.getSpeed() != 0 || !train.getHeadPosition().getSection().isStandTrack()) {
if (train.getSpeed() != 0 /*|| !train.getHeadPosition().getSection().isStandTrack()*/) {
return null;
}
Section target = train.getTarget();
boolean right = train.isRight();
float stopPoint;
if (target.isStandTrack()) {
stopPoint = target.getStopPointByDirection(right);
} else {
stopPoint = right ? target.getMaxOffset() - 10 : 10;
}
SectionPosition endPosition = new SectionPosition(target, stopPoint);
Float distance2Target = calculateDistance(train.getHeadPosition(), endPosition, right);
if (distance2Target == null) {
// float stopPoint;
// if (target.isStandTrack()) {
// stopPoint = target.getStopPointByDirection(right);
// } else {
// stopPoint = right ? target.getMaxOffset() - 10 : 10;
// }
// SectionPosition endPosition = new SectionPosition(target, stopPoint);
// Float distance2Target = calculateDistance(train.getHeadPosition(), endPosition, right);
// if (distance == null) {
// return null;
// }
List<RoutePath> routePaths = queryRoutePathsOnDirection(train.getHeadPosition().getSection(), target, right);
if (CollectionUtils.isEmpty(routePaths)) {
return null;
}
Optional<Float> distanceOptional = routePaths.stream().map(RoutePath::getLength).min(Float::compareTo);
if (distanceOptional.isEmpty()) {
return null;
}
float distance = distanceOptional.get();
float atpSpeedMax = train.getAtpSpeedMax() * 0.9f;
float atoSpeed = atpSpeedMax;
float atoSpeedMax = atpSpeedMax;
@ -1081,7 +1092,7 @@ public class CalculateService {
float accelerateTime = calculateAccelerateTime(train, atoSpeed);
float accelerateDistance = calculateAccelerateDistance(train, atoSpeed);
//计算匀速段的距离和时间
float uniformDistance = (distance2Target - decelerateDistance - accelerateDistance);
float uniformDistance = (distance - decelerateDistance - accelerateDistance);
float uniformTime = uniformDistance / atoSpeed;
//计算总时间根据总时间与计划时间的差来调整atoSpeedMax的值
float totalTime = (decelerateTime + accelerateTime + uniformTime);

View File

@ -151,6 +151,21 @@ public class MapConfig {
*/
private boolean signalHumanControlBeforeSetAtsControlOrCIAutoTrigger;
/**
* 扣车时是否允许提前发车
*/
private boolean allowEarlyDepartureWhenHoldTrain;
/**
* 取消进路时列车紧急制动
*/
private boolean EBWhenCancelRoute;
/**
* ATS自动调整运行
*/
private boolean adjustOperationAutomatically;
private Set<SimulationMember.Type> needConfirmConnectMembers =
Stream.of(DISPATCHER, STATION_SUPERVISOR, MAINTAINER, ELECTRIC_DISPATCHER).collect(Collectors.toSet());
@ -182,6 +197,8 @@ public class MapConfig {
setUrmAtpSpeed(configVO.getUrmAtpSpeed() / 3.6f);
setCancelAtsControlOfAllRoutesWhenCancelRoute(configVO.isCancelAtsControlOfAllRoutesWhenCancelRoute());
setSignalHumanControlBeforeSetAtsControlOrCIAutoTrigger(configVO.isSignalHumanControlBeforeSetAtsControlOrCIAutoTrigger());
setAllowEarlyDepartureWhenHoldTrain(configVO.isAllowEarlyDepartureWhenHoldTrain());
setEBWhenCancelRoute(configVO.isEBWhenCancelRoute());
}
}

View File

@ -1,5 +1,6 @@
package club.joylink.rtss.simulation.cbtc.data.map;
import club.joylink.rtss.simulation.cbtc.data.vo.TrainInfo;
import club.joylink.rtss.simulation.cbtc.exception.SimulationException;
import club.joylink.rtss.simulation.cbtc.exception.SimulationExceptionType;
import club.joylink.rtss.util.JsonUtils;
@ -127,6 +128,9 @@ public class Route extends MapNamedElement {
/** 正常解锁到的区段 */
private Section unlockedSection;
/** 进路将要或上一次为哪辆列车排列 */
private TrainInfo train;
@Override
public void reset() {
this.cbtcMode = true;
@ -141,6 +145,7 @@ public class Route extends MapNamedElement {
this.delayUnlocking = false;
this.normalUnlock = false;
this.unlockedSection = null;
this.train = null;
}
/**
@ -538,6 +543,17 @@ public class Route extends MapNamedElement {
}
return sections;
}
public boolean routeLastSection(Section section) {
return Objects.equals(this.sectionList.get(sectionList.size()-1),section);
}
/**
* 取消延时解锁
*/
public void cancelDelayUnlocking() {
this.delayUnlocking = false;
this.start.setDelayTime(0);
getLogicSections().forEach(section -> section.setDelayUnlock(false));
}
/**
* 进路检查失败原因

View File

@ -109,6 +109,11 @@ public class Stand extends MayOutOfOrderDevice {
*/
private boolean runLevelTimeForever;
/**
* 区间列车数量限制自动扣车不限制-1
*/
private int trainLimit;
/*停站时间相关*/
/**
* 停车时间自动为-1
@ -155,6 +160,7 @@ public class Stand extends MayOutOfOrderDevice {
this.runLevelTimeForever = false;
this.parkingTime = -1;
this.parkingAlwaysValid = false;
this.typeStrategy = TurnBackType.DEFAULT;
this.noStatus = false;
}

View File

@ -12,6 +12,7 @@ import lombok.NonNull;
import lombok.Setter;
import org.springframework.util.CollectionUtils;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@ -156,6 +157,11 @@ public class Station extends MayOutOfOrderDevice {
*/
private boolean interlockMachineStarting;
/**
* 联锁机重启时间
*/
private LocalTime restartTime;
@Override
public void reset() {
super.reset();
@ -473,6 +479,7 @@ public class Station extends MayOutOfOrderDevice {
if (!Objects.equals(this, device.getFault()))
return;
station.setInterlockMachineStarting(true);
station.setRestartTime(null);
station.setFault(null);
}
}

View File

@ -63,6 +63,9 @@ public class StandStatus extends DeviceStatus {
@JsonSerialize(using = Boolean2NumSerializer.class)
private boolean runLevelTimeForever;
/**区间列车数量限制(不限制为-1*/
private int trainLimit;
/**停车时间(自动为-1*/
private int parkingTime;
@ -97,6 +100,7 @@ public class StandStatus extends DeviceStatus {
}
this.runLevelTime = stand.getRunLevelTime();
this.runLevelTimeForever = stand.isRunLevelTimeForever();
this.trainLimit = stand.getTrainLimit();
this.parkingTime = stand.getParkingTime();
this.parkingAlwaysValid = stand.isParkingAlwaysValid();
this.noStatus = stand.isNoStatus();
@ -170,6 +174,11 @@ public class StandStatus extends DeviceStatus {
status.setRunLevelTimeForever(this.runLevelTimeForever);
change = true;
}
if (!Objects.equals(this.trainLimit, stand.getTrainLimit())) {
this.trainLimit = stand.getTrainLimit();
status.setTrainLimit(this.trainLimit);
change = true;
}
if (!Objects.equals(this.parkingTime, stand.getParkingTime())) {
this.parkingTime = stand.getParkingTime();
status.setParkingTime(this.parkingTime);
@ -203,6 +212,7 @@ public class StandStatus extends DeviceStatus {
StandStatusVO statusVO = new StandStatusVO((Stand) device);
statusVO.setParkingAlwaysValid(parkingAlwaysValid);
statusVO.setParkingTime(parkingTime);
statusVO.setTrainLimit(trainLimit);
statusVO.setRunLevelTimeForever(runLevelTimeForever);
statusVO.setRunLevelTime(runLevelTime);
statusVO.setAssignSkip(assignSkip);

View File

@ -10,6 +10,7 @@ import club.joylink.rtss.util.jsonSerialize.Boolean2NumDeserializer;
import club.joylink.rtss.util.jsonSerialize.Boolean2NumSerializer;
import lombok.Getter;
import java.time.LocalTime;
import java.util.Objects;
/**
@ -50,6 +51,9 @@ public class StationStatus extends DeviceStatus {
*/
private Integer validDuration;
/**连锁机上电重启时间*/
private LocalTime restartTime;
public StationStatus(Station station) {
super(station.getCode(), station.getDeviceType());
this.controlMode = station.getControlMode();
@ -58,6 +62,7 @@ public class StationStatus extends DeviceStatus {
this.applicantId = station.getApplicantId();
this.apply2TheControlMode = station.getApply2TheControlMode();
this.validDuration = station.getValidDurationInSeconds();
this.restartTime = station.getRestartTime();
}
@Override
@ -95,6 +100,12 @@ public class StationStatus extends DeviceStatus {
this.validDuration = station.getValidDurationInSeconds();
}
status.setValidDuration(validDuration);
if (!Objects.equals(this.restartTime, station.getRestartTime())) {
change = true;
this.restartTime = station.getRestartTime();
status.setRestartTime(restartTime);
}
return change;
}
@ -107,6 +118,7 @@ public class StationStatus extends DeviceStatus {
statusVO.setApplicantId(applicantId);
statusVO.setApply2TheControlMode(apply2TheControlMode);
statusVO.setValidDuration(validDuration);
statusVO.setRestartTime(restartTime);
return statusVO;
}
}

View File

@ -0,0 +1,61 @@
package club.joylink.rtss.simulation.cbtc.data.vo;
import club.joylink.rtss.simulation.cbtc.data.map.MapElement;
import club.joylink.rtss.simulation.cbtc.data.support.RoutePath;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* 进路路径VO
*/
@Getter
@Setter
@NoArgsConstructor
public class RoutePathVO {
/** 起始区段 */
private String startSectionCode;
/** 结束区段 */
private String endSectionCode;
/** 路径的标识 */
private String key;
/** 信号机列表 */
private List<String> signalList;
/** 进路列表 */
private List<String> routeList;
/** 区段列表 */
private List<String> sectionList;
/** 方向 */
private boolean right;
/** 距离 */
private float length;
public RoutePathVO(RoutePath routePath) {
this.startSectionCode = routePath.getStart().getCode();
this.endSectionCode = routePath.getEnd().getCode();
this.key = routePath.getKey();
this.signalList = routePath.getSignalList().stream().map(MapElement::getCode).collect(Collectors.toList());
this.routeList = routePath.getRouteList().stream().map(MapElement::getCode).collect(Collectors.toList());
this.sectionList = routePath.getSectionList().stream().map(MapElement::getCode).collect(Collectors.toList());
this.right = routePath.isRight();
this.length = routePath.getLength();
}
public static List<RoutePathVO> convert(List<RoutePath> routePaths) {
if (CollectionUtils.isEmpty(routePaths))
return new ArrayList<>();
return routePaths.stream().map(RoutePathVO::new).collect(Collectors.toList());
}
}

View File

@ -60,6 +60,9 @@ public class StandStatusVO extends DeviceStatusVO {
@JsonSerialize(using = Boolean2NumSerializer.class)
private Boolean runLevelTimeForever;
/**区间列车数量限制(自不限制-1*/
private Integer trainLimit;
/**停车时间(自动为-1*/
private Integer parkingTime;

View File

@ -10,6 +10,7 @@ import lombok.Getter;
import lombok.Setter;
import java.time.LocalDateTime;
import java.time.LocalTime;
/**
* 车站状态
@ -49,6 +50,8 @@ public class StationStatusVO extends DeviceStatusVO {
@JsonInclude()
private Integer validDuration;
private LocalTime restartTime;
public StationStatusVO(Station station) {
super(station.getCode(), station.getDeviceType());
}

View File

@ -365,8 +365,6 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
*/
private VirtualRealityTrain linkTrain;
/**最近经过的两个应答器*/
private Queue<Responder> lastTwoPassedResponders = new FixedQueue<>(Responders_Record);

View File

@ -158,10 +158,10 @@ public class SpeedCurve {
float limitSpeed = recommendedSpeedMax;
boolean limit = false;
if (Objects.nonNull(tailPosition.getSection().getNeedLimitSpeed())) {
limitSpeed = Math.min(limitSpeed, tailPosition.getSection().getNeedLimitSpeed());
limitSpeed = Math.min(limitSpeed, tailPosition.getSection().getNeedLimitSpeed() * 0.9f);
limit = true;
} else if (Objects.nonNull(headPosition.getSection().getNeedLimitSpeed())) {
limitSpeed = Math.min(limitSpeed, headPosition.getSection().getNeedLimitSpeed());
limitSpeed = Math.min(limitSpeed, headPosition.getSection().getNeedLimitSpeed() * 0.9f);
limit = true;
}
SectionPosition endPosition = null;
@ -190,7 +190,7 @@ public class SpeedCurve {
if (Objects.nonNull(limitSpeed1)) {
if (ahead) {
// 车头前方
vt = Math.min(limitSpeed, limitSpeed1);
vt = Math.min(limitSpeed, limitSpeed1 * 0.9f);
endPosition = new SectionPosition(base, right ? 0 : base.getLen());
break;
} else {
@ -208,7 +208,7 @@ public class SpeedCurve {
if (Objects.isNull(distance) || distance > totalLen) {
return buildTargetSpeedCurve(totalLen, v0, 0, limitSpeed);
} else {
return buildTargetSpeedCurve(distance, v0, vt * 0.8f, limitSpeed);
return buildTargetSpeedCurve(distance, v0, vt, limitSpeed);
}
}
return buildTargetSpeedCurve(totalLen, v0, 0, limitSpeed);

View File

@ -7,6 +7,7 @@ import club.joylink.rtss.simulation.cbtc.constant.DriveMode;
import club.joylink.rtss.simulation.cbtc.constant.SimulationConstants;
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.Signal;
import club.joylink.rtss.simulation.cbtc.data.map.Stand;
import club.joylink.rtss.simulation.cbtc.data.support.MovementAuthority;
import club.joylink.rtss.simulation.cbtc.data.support.SectionPosition;
@ -156,7 +157,8 @@ public class ATOService {
// nextStation.getName(), nextStation.getCode(),
// nextStopStandSection.getName(), nextStopStandSection.getCode()));
boolean parking = true;
if (!train.isHold() && (train.isJump() || !train.isNextParking())) {
Signal signal = target.getSignalOf(right);
if (!train.isHold() && (train.isJump() && signal.isNormalOpen() || !train.isNextParking())) {
parking = false;
}
if (parking) {

View File

@ -3,7 +3,10 @@ package club.joylink.rtss.simulation.cbtc.onboard.ATP;
import club.joylink.rtss.simulation.cbtc.ATP.ground.GroundAtpApiService;
import club.joylink.rtss.simulation.cbtc.ATS.AtsApiService;
import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.constant.*;
import club.joylink.rtss.simulation.cbtc.constant.ControlGear;
import club.joylink.rtss.simulation.cbtc.constant.RunLevel;
import club.joylink.rtss.simulation.cbtc.constant.SimulationConstants;
import club.joylink.rtss.simulation.cbtc.constant.SimulationModule;
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.Signal;
@ -220,13 +223,19 @@ public class ATPLogicLoop {
}
break;
case BOARD: // 乘客乘降
if (simulation.getRepository().getConfig().isAdjustOperationAutomatically()) {
if (parkRemainTime < 10000) { // 小于10秒关门
train.nextParkedTrainActivity();
}
} else {
if (parkRemainTime <= 0) {
train.nextParkedTrainActivity();
}
}
break;
case CLOSE_DOOR: // 关门
Signal signal = train.getHeadPosition().getSection().getSignalOf(train.isRight());
if (!train.isHold()) { // 列车未扣车
if (!train.isHold() || simulation.getRepository().getConfig().isAllowEarlyDepartureWhenHoldTrain()) { // 列车未扣车或允许在扣车状态下提前发
// if (Objects.nonNull(signal) && !signal.isNormalOpen()) {
// if (!train.isRMMode() && !train.isNRMMode()) {
// // 信号机未正常开放
@ -287,45 +296,51 @@ public class ATPLogicLoop {
}
private boolean checkConditionToMove2(Simulation simulation, VirtualRealityTrain train) {
boolean safe = true;
if (train.isParkingAt() && !train.isStandReadyStart()) { // 站台停靠未完成
safe = false;
}
boolean right = train.isRight();
SectionPosition headPosition = train.getHeadPosition();
Section headSection = headPosition.getSection();
// 轨道前方信号机是否红灯
Signal signal = headSection.getSignalOf(right);
if (headSection.isSwitchTrack()) {
signal = headSection.querySwitchSectionRelatedSignalByDirection(right);
}
if (Objects.nonNull(signal) && !signal.isNormalOpen()) {
// log.debug(String.format("列车[%s]前方信号机[%s(%s)]未开放,不能动车",
// train.getGroupNumber(), signal.getName(), signal.getCode()));
safe = false;
}
if (safe) {
//
train.setDelayTime(Math.max(train.getDelayTime() - SimulationConstants.ATP_LOOP_RATE, 0));
if (train.getDelayTime() > 0) {
return false;
}
} else {
//RM可启动
if (!train.getDriveMode().equals(DriveMode.AM)) {
if (train.getDelayTime() > 0) {
train.setDelayTime(Math.max(train.getDelayTime() - SimulationConstants.ATP_LOOP_RATE, 0));
if (train.getDelayTime() > 0) {
return false;
}
}
} else {
train.setDelayTime(SimulationConstants.ATO_TRAIN_GET_SIGNAL_TO_START_DELAY);
return false;
}
}
return true;
// boolean safe = true;
// if (train.isParkingAt() && !train.isStandReadyStart()) { // 站台停靠未完成
// safe = false;
// }
// boolean right = train.isRight();
// SectionPosition headPosition = train.getHeadPosition();
// Section headSection = headPosition.getSection();
// // 轨道前方信号机是否红灯
// Signal signal = headSection.getSignalOf(right);
// if (headSection.isSwitchTrack()) {
// signal = headSection.querySwitchSectionRelatedSignalByDirection(right);
// }
// if (Objects.nonNull(signal) && !signal.isNormalOpen()) {
//// log.debug(String.format("列车[%s]前方信号机[%s(%s)]未开放,不能动车",
//// train.getGroupNumber(), signal.getName(), signal.getCode()));
// safe = false;
// }
// if (safe) {
// //
// train.setDelayTime(Math.max(train.getDelayTime() - SimulationConstants.ATP_LOOP_RATE, 0));
// if (train.getDelayTime() > 0) {
// return false;
// }
// } else {
//
// //RM可启动
// if (!train.getDriveMode().equals(DriveMode.AM)) {
// if (train.getDelayTime() > 0) {
// train.setDelayTime(Math.max(train.getDelayTime() - SimulationConstants.ATP_LOOP_RATE, 0));
// if (train.getDelayTime() > 0) {
// return false;
// }
// }
// } else {
// train.setDelayTime(SimulationConstants.ATO_TRAIN_GET_SIGNAL_TO_START_DELAY);
// return false;
// }
// }
// return true;
}
/**

View File

@ -54,10 +54,10 @@ public class ATPService {
// train.getTripNumber(), train.getDestinationCode()));
// this.cancelEB(train);
// }
log.info(String.format("列车[%s-%s|%s|%s]更新移动授权[%s],安全防护距离[%s]",
log.info(String.format("列车[%s-%s|%s|%s]更新移动授权[%s],位置[%s],安全防护距离[%s]",
train.getGroupNumber(),
train.getServiceNumber(), train.getTripNumber(), train.getDestinationCode(),
ma.getEnd(), protectDistance));
ma.getEnd(), ma.getEnd().getEndPosition().toString(), protectDistance));
// 重新生成速度曲线
SpeedCurve speedCurve = SpeedCurve.generateProtectSpeedCurve(protectDistance, train.getAtpSpeedMax()); //未考虑区段限速
// SpeedCurve speedCurve = SpeedCurve.generateProtectSpeedCurve(train); //考虑区段限速
@ -101,6 +101,7 @@ public class ATPService {
switch (driveMode) {
case RM: {
if (train.getSpeed() > simulation.getRepository().getConfig().getRmAtpSpeed()) {
log.warn(String.format("%s在RM模式下超速速度%s", train.debugStr(), train.getSpeed()));
this.triggerSignalEB(train);
}
break;

View File

@ -68,10 +68,10 @@ public class RobotLogicLoop {
if (!simulation.getRepository().isVrTrainOnline(train.getGroupNumber())) { //如果列车不在线
continue;
}
if (train.isAtoOn()) {
train.setRobotTargetPosition(null);
continue;
}
// if (train.isAtoOn()) { //为国赛剧本暂时注掉
// train.setRobotTargetPosition(null);
// continue;
// }
Float distance = CalculateService.calculateDistance(headPosition, targetPosition, right);
if (distance == null || distance <= SimulationConstants.PARK_POINT_MAX_OFFSET) { //如果列车已经抵达或越过目标位置
this.doBreakMax(simulation, train);
@ -244,7 +244,7 @@ public class RobotLogicLoop {
float fk = a * train.getMass();
float fkMax = train.getCurrentFkMax();
fk = Math.min(fk, fkMax);
driverOperateHandler.changeTrainForce(simulation, train.getGroupNumber(), fk / fkMax);
driverOperateHandler.changeTrainForce(simulation, train.getGroupNumber(), Math.min(fk / fkMax, 1));
}
private void doBreakMax(Simulation simulation, VirtualRealityTrain train) {
@ -258,7 +258,6 @@ public class RobotLogicLoop {
a = -Math.abs(a);
float fb = train.getMass() * a;
float fbMax = train.getCurrentFbMax();
fb = Math.min(fb, fbMax);
driverOperateHandler.changeTrainForce(simulation, train.getGroupNumber(), fb / fbMax);
driverOperateHandler.changeTrainForce(simulation, train.getGroupNumber(), Math.max(fb / fbMax, -1));
}
}

View File

@ -1,11 +1,14 @@
package club.joylink.rtss.simulation.cbtc.tool;
import club.joylink.rtss.simulation.cbtc.ATS.service.AtsTrainLoadService;
import club.joylink.rtss.simulation.cbtc.CI.service.RouteService;
import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.data.SimulationDataRepository;
import club.joylink.rtss.simulation.cbtc.data.map.*;
import club.joylink.rtss.simulation.cbtc.data.support.SectionPosition;
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealitySignal;
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealitySwitch;
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityTrain;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@ -25,6 +28,8 @@ public class DeviceStatusModifyTool {
@Autowired
private RouteService routeService;
@Autowired
private AtsTrainLoadService atsTrainLoadService;
/**
* 直接开放进路
@ -238,4 +243,8 @@ public class DeviceStatusModifyTool {
}
}
}
public void loadManualTrainOfGroup(Simulation simulation, String groupNumber, Section section , boolean right){
atsTrainLoadService.loadSpareTrain(simulation, groupNumber, section.getCode(),right);
}
}

View File

@ -61,4 +61,8 @@ public class MapLineVO {
@ApiModelProperty(value = "显示条件")
@NotBlank(message="显示条件不能为空")
private String showConditions;
private Integer offsetX;
private Integer offsetY;
}

View File

@ -90,6 +90,21 @@ public class RealLineConfigVO {
*/
private boolean signalHumanControlBeforeSetAtsControlOrCIAutoTrigger;
/**
* 扣车时是否允许提前发车
*/
private boolean allowEarlyDepartureWhenHoldTrain;
/**
* 取消进路时列车紧急制动
*/
private boolean EBWhenCancelRoute;
/**
* ATS自动调整运行
*/
private boolean adjustOperationAutomatically = true;
public static RealLineConfigVO parseJsonStr(String configData) {
if (StringUtils.hasText(configData)) {
return JsonUtils.read(configData, RealLineConfigVO.class);

View File

@ -22,6 +22,8 @@ public class OperateDefinitionConfig {
//折返策略按钮
private Boolean tbStrategyBT;
private Boolean guideTotalLockBT;
private List<String> sectionTypes;//区段生成指定类型
public boolean isAtp() {
@ -62,4 +64,10 @@ public class OperateDefinitionConfig {
}
return false;
}
public boolean guideTotalLockButton(){
if(Objects.nonNull(guideTotalLockBT)){
return guideTotalLockBT;
}
return false;
}
}

View File

@ -189,6 +189,14 @@ public class OperateDefinitionVO {
return false;
}
public boolean guideTotalLockButton() {
OperateDefinitionConfig routeSettingConfig = this.getRouteSettingConfig();
if (Objects.nonNull(routeSettingConfig)) {
return routeSettingConfig.guideTotalLockButton();
}
return false;
}
public List<String> getSectionTypes() {
OperateDefinitionConfig routeSettingConfig = this.getRouteSettingConfig();
if (Objects.nonNull(routeSettingConfig)) {