Merge branch 'test' into master-huawei
This commit is contained in:
commit
65572dd3b0
@ -42,6 +42,8 @@ public enum Project {
|
||||
RICHOR_JOINT,
|
||||
/** 上饶沙盘 */
|
||||
SR_SANDBOX,
|
||||
/** 江西工贸 */
|
||||
JXGM,
|
||||
;
|
||||
|
||||
public static boolean isDefault(Project project) {
|
||||
|
@ -34,6 +34,8 @@ public enum ProjectDeviceType {
|
||||
UDP_LOW,
|
||||
/** UDP客户端 */
|
||||
UDP_CLIENT,
|
||||
/** 列车 */
|
||||
TRAIN,
|
||||
/* -----------plc device end---------- */
|
||||
|
||||
/* -----------client device start---------- */
|
||||
@ -79,6 +81,7 @@ public enum ProjectDeviceType {
|
||||
SIGNAL,
|
||||
DCU,
|
||||
UDP_LOW,
|
||||
UDP_CLIENT);
|
||||
UDP_CLIENT,
|
||||
TRAIN);
|
||||
}
|
||||
}
|
||||
|
@ -189,6 +189,14 @@ public class DeviceController {
|
||||
this.deviceService.updateIlwConfig(id, configVO);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改配置,以json的形式
|
||||
*/
|
||||
@PutMapping("/config/updateConfig")
|
||||
public void updateConfig(@RequestBody ProjectDeviceVO projectDeviceVO) {
|
||||
this.deviceService.updateConfig(projectDeviceVO);
|
||||
}
|
||||
|
||||
/**
|
||||
*删除设备
|
||||
*/
|
||||
|
@ -44,6 +44,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
@ -109,7 +110,11 @@ public class CompetitionPracticalService implements ICompetitionPracticalService
|
||||
@Override
|
||||
public PageVO<CompetitionVO> pagedQueryCompetition(CompetitionPagedQueryVO queryVO) {
|
||||
PageHelper.startPage(queryVO.getPageNum(), queryVO.getPageSize());
|
||||
Page<Competition> page = (Page<Competition>) this.competitionDAO.selectByExample(null);
|
||||
CompetitionExample competitionExample = new CompetitionExample();
|
||||
if (StringUtils.hasText(queryVO.getName())) {
|
||||
competitionExample.createCriteria().andNameLike(String.format("%%%s%%", queryVO.getName()));
|
||||
}
|
||||
Page<Competition> page = (Page<Competition>) this.competitionDAO.selectByExample(competitionExample);
|
||||
List<CompetitionVO> list = page.getResult().stream().map(CompetitionVO::new).collect(Collectors.toList());
|
||||
return PageVO.convert(page, list);
|
||||
}
|
||||
|
@ -148,6 +148,11 @@ public interface DeviceService {
|
||||
*/
|
||||
void updateIlwConfig(Long id, RelationLoginConfigVO configVO);
|
||||
|
||||
/**
|
||||
* 更新(以json直接更新)
|
||||
*/
|
||||
void updateConfig(ProjectDeviceVO projectDeviceVO);
|
||||
|
||||
/**
|
||||
* 删除设备
|
||||
* @param id
|
||||
|
@ -7,6 +7,7 @@ import club.joylink.rtss.entity.ProjectDevice;
|
||||
import club.joylink.rtss.entity.ProjectDeviceExample;
|
||||
import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
|
||||
import club.joylink.rtss.services.IMapService;
|
||||
import club.joylink.rtss.simulation.cbtc.data.map.Section;
|
||||
import club.joylink.rtss.util.JsonUtils;
|
||||
import club.joylink.rtss.vo.AccountVO;
|
||||
import club.joylink.rtss.vo.LoginUserInfoVO;
|
||||
@ -22,12 +23,14 @@ import club.joylink.rtss.vo.client.project.sdy.SdyPslConfigVO;
|
||||
import club.joylink.rtss.vo.client.project.sr.SrSectionConfigVO;
|
||||
import club.joylink.rtss.vo.client.project.sr.SrSignalConfigVO;
|
||||
import club.joylink.rtss.vo.client.project.sr.SrSwitchConfigVO;
|
||||
import club.joylink.rtss.vo.client.project.sr.SrTrainConfigVO;
|
||||
import club.joylink.rtss.vo.client.project.xty.XtyPsdConfigVO;
|
||||
import club.joylink.rtss.vo.map.MapGraphDataNewVO;
|
||||
import club.joylink.rtss.vo.map.MapVO;
|
||||
import club.joylink.rtss.vo.map.graph.MapSectionNewVO;
|
||||
import club.joylink.rtss.vo.map.graph.MapSignalNewVO;
|
||||
import club.joylink.rtss.vo.map.graph.MapSwitchVO;
|
||||
import club.joylink.rtss.vo.map.graph.MapTrainVO;
|
||||
import com.github.pagehelper.Page;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -269,6 +272,24 @@ public class DeviceServiceImpl implements DeviceService {
|
||||
this.projectDeviceDAO.updateByPrimaryKeySelective(device);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateConfig(ProjectDeviceVO projectDeviceVO) {
|
||||
ProjectDevice entity = getEntityById(projectDeviceVO.getId());
|
||||
check(entity, projectDeviceVO);
|
||||
entity.setConfig(projectDeviceVO.getConfig());
|
||||
projectDeviceDAO.updateByPrimaryKeyWithBLOBs(entity);
|
||||
}
|
||||
|
||||
private ProjectDevice getEntityById(long id) {
|
||||
return projectDeviceDAO.selectByPrimaryKey(id);
|
||||
}
|
||||
|
||||
private void check(ProjectDevice entity, ProjectDeviceVO projectDeviceVO) {
|
||||
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertEquals(entity.getProjectCode(), projectDeviceVO.getProject().name());
|
||||
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertEquals(entity.getCode(), projectDeviceVO.getCode());
|
||||
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertEquals(entity.getType(), projectDeviceVO.getType().name());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(Long id) {
|
||||
this.projectDeviceDAO.deleteByPrimaryKey(id);
|
||||
@ -436,7 +457,7 @@ public class DeviceServiceImpl implements DeviceService {
|
||||
udp.setType(ProjectDeviceType.UDP_LOW.name());
|
||||
udp.setCreator(accountVO.getId());
|
||||
udp.setCreateTime(now);
|
||||
UDPLowConfigVO udpConfigVO = new UDPLowConfigVO("", 10086);
|
||||
UDPLowConfigVO udpConfigVO = new UDPLowConfigVO("192.168.0.110", 44449);
|
||||
udp.setConfig(udpConfigVO.toJson());
|
||||
list.add(udp);
|
||||
//UDP客户端
|
||||
@ -446,7 +467,7 @@ public class DeviceServiceImpl implements DeviceService {
|
||||
udpClient.setType(ProjectDeviceType.UDP_CLIENT.name());
|
||||
udpClient.setCreator(accountVO.getId());
|
||||
udpClient.setCreateTime(now);
|
||||
UDPClientConfigVO udpClientConfigVO = new UDPClientConfigVO("192.168.8.109", 10000);
|
||||
UDPClientConfigVO udpClientConfigVO = new UDPClientConfigVO("192.168.0.110", 44449);
|
||||
udpClient.setConfig(JsonUtils.writeValueAsString(udpClientConfigVO));
|
||||
list.add(udpClient);
|
||||
/*-------------------- 地图设备 --------------------*/
|
||||
@ -490,13 +511,82 @@ public class DeviceServiceImpl implements DeviceService {
|
||||
section.setCreator(accountVO.getId());
|
||||
section.setCreateTime(now);
|
||||
SrSectionConfigVO configVO = new SrSectionConfigVO(mapSectionNewVO.getCode(), mapSectionNewVO.getSrCode());
|
||||
fillTime(configVO, mapSectionNewVO);
|
||||
section.setConfig(JsonUtils.writeValueAsString(configVO));
|
||||
list.add(section);
|
||||
}
|
||||
}
|
||||
//列车
|
||||
List<MapTrainVO> trainList = graphDataNew.getTrainList();
|
||||
for (MapTrainVO mapTrainVO : trainList) {
|
||||
ProjectDevice train = new ProjectDevice();
|
||||
train.setProjectCode(Project.SR_SANDBOX.name());
|
||||
train.setCode("sr-train-" + mapTrainVO.getGroupNumber());
|
||||
train.setType(ProjectDeviceType.TRAIN.name());
|
||||
train.setCreator(accountVO.getId());
|
||||
train.setCreateTime(now);
|
||||
SrTrainConfigVO configVO = new SrTrainConfigVO(mapTrainVO.getGroupNumber(), String.valueOf(Integer.parseInt(mapTrainVO.getGroupNumber())));
|
||||
train.setConfig(JsonUtils.writeValueAsString(configVO));
|
||||
list.add(train);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 填充区段延时停车时间
|
||||
*/
|
||||
private void fillTime(SrSectionConfigVO configVO, MapSectionNewVO section) {
|
||||
Float headDelayTime = null;
|
||||
Float tailDelayTime = null;
|
||||
switch (section.getCode()) {
|
||||
//以车头到目标位置作为停车标志的区段
|
||||
case "T141": //49G
|
||||
case "T142":
|
||||
headDelayTime = 1.0f;
|
||||
break;
|
||||
case "T1": //1G
|
||||
headDelayTime = 3.7f;
|
||||
break;
|
||||
case "T11":
|
||||
headDelayTime = 3.7f;
|
||||
break;
|
||||
case "T73":
|
||||
case "T75":
|
||||
headDelayTime = 3.4f;
|
||||
break;
|
||||
//以车尾解除占用作为停车标志的区段
|
||||
case "T5": //1x
|
||||
break;
|
||||
case "T7": //2x
|
||||
break;
|
||||
case "T45": //3x
|
||||
break;
|
||||
case "T53": //4x
|
||||
break;
|
||||
case "T61": //5x
|
||||
break;
|
||||
case "T67": //6x
|
||||
break;
|
||||
case "T33": //1s
|
||||
tailDelayTime = 2.0f;
|
||||
break;
|
||||
case "T35": //2s
|
||||
tailDelayTime = 2.5f;
|
||||
break;
|
||||
case "T46": //3s
|
||||
break;
|
||||
case "T54": //4s
|
||||
break;
|
||||
case "T62": //5s
|
||||
break;
|
||||
case "T68": //6s
|
||||
tailDelayTime = 2.0f;
|
||||
break;
|
||||
}
|
||||
configVO.setHeadDelayTime(headDelayTime);
|
||||
configVO.setTailDelayTime(tailDelayTime);
|
||||
}
|
||||
|
||||
private List<ProjectDevice> buildZjdProjectDevices(AccountVO accountVO) {
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
List<ProjectDevice> list = new ArrayList<>();
|
||||
@ -584,7 +674,7 @@ public class DeviceServiceImpl implements DeviceService {
|
||||
private ProjectDevice buildIm(Project project, Long creatorId) {
|
||||
ProjectDevice im = new ProjectDevice();
|
||||
im.setProjectCode(project.name());
|
||||
im.setCode(project.name().toLowerCase() + "-" +"im");
|
||||
im.setCode(project.name().toLowerCase() + "-" + "im");
|
||||
im.setType(ProjectDeviceType.IM.name());
|
||||
im.setCreator(creatorId);
|
||||
im.setCreateTime(LocalDateTime.now());
|
||||
|
@ -239,7 +239,7 @@ public class RunPlanGenerator {
|
||||
List<RunPlanRoutingSection> inSectionList = inRouting.getParkSectionCodeList();
|
||||
RunPlanRoutingSection inSection = inSectionList.get(inSectionList.size() - 2);
|
||||
return Objects.equals(parkSection.getSectionCode(), inSection.getSectionCode());
|
||||
}).sorted(Comparator.comparing(routingVO -> runLevelMap.get(parkSection.getSectionCode() + "-" + routingVO.getEndSectionCode()))).findFirst().orElse(null);
|
||||
}).min(Comparator.comparing(routingVO -> runLevelMap.get(parkSection.getSectionCode() + "-" + routingVO.getEndSectionCode()))).orElse(null);
|
||||
if (Objects.nonNull(inboundRouting)) {
|
||||
r = runningRouting.getStartTbFront() ? i + 1 : i;
|
||||
break t;
|
||||
|
@ -84,7 +84,7 @@ public class AtpSectionService {
|
||||
if (train.isCommunicable()) { // 通信车占用
|
||||
// 车尾位置追加不确定性距离:(速度*2)m
|
||||
SectionPosition trainTailPosition = CalculateService
|
||||
.calculateNextPositionByStartAndLen(trainHeadPosition, !right, train.getLen() + train.getSpeed() * 2);
|
||||
.calculateNextPositionByStartAndLen(trainHeadPosition, !right, train.getLen() + train.getSpeed() * 2, false);
|
||||
atpSectionList = CalculateService.getAtpSections(trainHeadPosition, trainTailPosition,
|
||||
right, switchSingleHandle);
|
||||
List<Section> removes = new ArrayList<>();
|
||||
@ -171,11 +171,11 @@ public class AtpSectionService {
|
||||
SectionPosition headPosition = train.getHeadPosition();
|
||||
float offset = 50;
|
||||
SectionPosition head = CalculateService
|
||||
.calculateNextPositionByStartAndLen(headPosition, right, offset);
|
||||
.calculateNextPositionByStartAndLen(headPosition, right, offset, false);
|
||||
// 考虑列车最大可能占用区间,用于判断ARB区段
|
||||
SectionPosition tail = CalculateService
|
||||
.calculateNextPositionByStartAndLen(headPosition,
|
||||
!right, train.getLen() + offset);
|
||||
!right, train.getLen() + offset, false);
|
||||
List<Section> sectionList = CalculateService.getTrainOccupyAxleSection(head, tail, right);
|
||||
if (!CollectionUtils.isEmpty(sectionList)) {
|
||||
for (Section section : sectionList) {
|
||||
@ -209,26 +209,4 @@ public class AtpSectionService {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果有非通信车接近故障区段,将故障区段设为非通信车占用
|
||||
*/
|
||||
public void judgeFaultSectionAsNctOccupied(Map<VirtualRealityTrain, Signal> nctApproachSignalMap) {
|
||||
if (CollectionUtils.isEmpty(nctApproachSignalMap)) {
|
||||
return;
|
||||
}
|
||||
nctApproachSignalMap.forEach((k, v) -> {
|
||||
v.getRouteList().forEach(route -> {
|
||||
if (v.equals(route.getStart())) { //如果该信号机是某进路的始端信号机
|
||||
route.getSectionList().forEach(section -> {
|
||||
if (section.isFault()) {
|
||||
section.setNctOccupied(true); //设为非通信车占用
|
||||
if (section.isInvalid()) {
|
||||
section.setInvalid(false); //去掉ARB状态
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -134,7 +134,7 @@ public class MaService {
|
||||
end = signal.getSection().buildStopPointPosition(right);
|
||||
} else {
|
||||
SectionPosition sectionPosition = new SectionPosition(signal.getSection(), signal.getOffset());
|
||||
end = CalculateService.calculateNextPositionByStartAndLen(sectionPosition, !right, 5);
|
||||
end = CalculateService.calculateNextPositionByStartAndLen(sectionPosition, !right, 5, false);
|
||||
}
|
||||
Float distance = CalculateService.calculateDistance(this.train.getHeadPosition(), end, right);
|
||||
if (distance == null) {
|
||||
@ -165,7 +165,7 @@ public class MaService {
|
||||
} else {
|
||||
eoa = frontTrain.getHeadPosition();
|
||||
}
|
||||
eoa = CalculateService.calculateNextPositionByStartAndLen(eoa, !right, 10);
|
||||
eoa = CalculateService.calculateNextPositionByStartAndLen(eoa, !right, 10, false);
|
||||
break;
|
||||
}
|
||||
case Axle_Occupy_Section:{
|
||||
@ -202,7 +202,7 @@ public class MaService {
|
||||
Section section = (Section) this.device;
|
||||
float offset = section.getStopPointByDirection(right);
|
||||
offset = right ? offset - train.getLen() - 20 : offset + train.getLen() + 20;
|
||||
eoa = CalculateService.getAvailableSectionPositionOf(new SectionPosition(section, offset));
|
||||
eoa = CalculateService.getAvailableSectionPositionOf(new SectionPosition(section, offset), false);
|
||||
break;
|
||||
}
|
||||
case ITC_Signal:{
|
||||
@ -222,7 +222,7 @@ public class MaService {
|
||||
physicalSection = physicalSection.getParent();
|
||||
}
|
||||
eoa = new SectionPosition(physicalSection, right ? section.getMinOffset() : section.getMaxOffset());
|
||||
eoa = CalculateService.calculateNextPositionByStartAndLen(eoa, !right, 10);
|
||||
eoa = CalculateService.calculateNextPositionByStartAndLen(eoa, !right, 10, false);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -550,7 +550,7 @@ public class MaService {
|
||||
SwitchElement switchElement = route.getRouteSwitchElement(routeSection.getRelSwitch());
|
||||
Switch aSwitch = switchElement.getASwitch();
|
||||
handledSwitchSet.add(aSwitch.getCode());
|
||||
if (route.equals(aSwitch.getRoute())) {
|
||||
if (aSwitch.getRoutes().contains(route)) {
|
||||
if (aSwitch.isLoss()) {
|
||||
switchFault = true;
|
||||
break;
|
||||
|
@ -67,6 +67,12 @@ public class DriverOperateHandler {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改工况手轮档位
|
||||
* @param simulation
|
||||
* @param groupNumber
|
||||
* @param gear
|
||||
*/
|
||||
@OperateHandlerMapping(type = Operation.Type.Driver_Gear_Change)
|
||||
public void changeTrainGear(Simulation simulation, String groupNumber, VirtualRealityTrain.Handwheel gear) {
|
||||
Objects.requireNonNull(gear);
|
||||
|
@ -615,7 +615,7 @@ public class AtsTrainLoadService {
|
||||
// 与上一辆车距离一个安全距离
|
||||
SectionPosition headPosition = CalculateService
|
||||
.calculateNextPositionByStartAndLen(frontTrain.getHeadPosition(),
|
||||
!train.isRight(), frontTrain.getLen() + 2 * SimulationConstants.TRAIN_SAFE_DISTANCE);
|
||||
!train.isRight(), frontTrain.getLen() + 2 * SimulationConstants.TRAIN_SAFE_DISTANCE, false);
|
||||
train.setHeadPosition(headPosition);
|
||||
}
|
||||
}
|
||||
@ -664,7 +664,7 @@ public class AtsTrainLoadService {
|
||||
for (VirtualRealityTrain train : loadedList) {
|
||||
Section headSection = train.getHeadPosition().getSection();
|
||||
boolean right = train.isRight();
|
||||
SectionPosition tailPosition = CalculateService.calculateNextPositionByStartAndLen(train.getHeadPosition(), !right, train.getLen());
|
||||
SectionPosition tailPosition = CalculateService.calculateNextPositionByStartAndLen(train.getHeadPosition(), !right, train.getLen(), false);
|
||||
TripPlan tripPlan = repository.getTripPlan(train.getServiceNumber(), train.getTripNumber());
|
||||
// 取进路所有经过的区段
|
||||
List<Section> viaSectionList = tripPlan.getAllViaStoppedSectionList();
|
||||
@ -850,7 +850,7 @@ public class AtsTrainLoadService {
|
||||
"列车需加载到物理区段上");
|
||||
//重叠检测
|
||||
SectionPosition headPosition = new SectionPosition(section, section.getStopPointByDirection(right));
|
||||
SectionPosition tailPosition = CalculateService.calculateNextPositionByStartAndLen(headPosition, !right, train.getLen());
|
||||
SectionPosition tailPosition = CalculateService.calculateNextPositionByStartAndLen(headPosition, !right, train.getLen(), false);
|
||||
boolean willOverlap = vrTrainRunningService.willOverlap(simulation, headPosition, tailPosition);
|
||||
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertNotTrue(willOverlap, "列车重叠");
|
||||
// 列车上线并构建ATS监控列车信息
|
||||
@ -861,8 +861,19 @@ public class AtsTrainLoadService {
|
||||
* 人工车上线并监控
|
||||
*/
|
||||
private void manualTrainOnlineAndSupervise(Simulation simulation, VirtualRealityTrain train, SectionPosition headPosition, boolean right) {
|
||||
train.initManualTrain(headPosition, 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();
|
||||
}
|
||||
}
|
||||
TrainInfo trainInfo = TrainInfo.constructManualTrain(train);
|
||||
trainInfo.tracking(train);
|
||||
repository.addOnlineTrain(train);
|
||||
|
@ -8,8 +8,6 @@ import club.joylink.rtss.simulation.cbtc.ATS.service.stage.AtsHeadTrainStageServ
|
||||
import club.joylink.rtss.simulation.cbtc.ATS.service.stage.AtsPlanTrainStageService;
|
||||
import club.joylink.rtss.simulation.cbtc.CI.CiApiService;
|
||||
import club.joylink.rtss.simulation.cbtc.Simulation;
|
||||
import club.joylink.rtss.simulation.cbtc.constant.SimulationConstants;
|
||||
import club.joylink.rtss.simulation.cbtc.constant.SimulationModule;
|
||||
import club.joylink.rtss.simulation.cbtc.constant.TrainType;
|
||||
import club.joylink.rtss.simulation.cbtc.data.CalculateService;
|
||||
import club.joylink.rtss.simulation.cbtc.data.SimulationDataRepository;
|
||||
@ -18,7 +16,6 @@ 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.StationTurnBackStrategyOption;
|
||||
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;
|
||||
@ -63,6 +60,9 @@ public class AtsTrainService {
|
||||
@Autowired
|
||||
private AtsHeadTrainStageService atsHeadTrainStageService;
|
||||
|
||||
@Autowired
|
||||
private AtsTrainService atsTrainService;
|
||||
|
||||
/**
|
||||
* 添加列车追踪
|
||||
*
|
||||
@ -100,6 +100,8 @@ public class AtsTrainService {
|
||||
BusinessExceptionAssertEnum.OPERATION_FAIL.assertNotTrue(tripRepeat, "车次计划已在运行");
|
||||
ti = new TrainInfo(groupNumber, TrainType.PLAN);
|
||||
ti.init(section, tripPlan, dn, cn);
|
||||
} else if (StringUtils.hasText(dn)) {
|
||||
ti = new TrainInfo(groupNumber, TrainType.HEAD);
|
||||
} else {
|
||||
ti = new TrainInfo(groupNumber, TrainType.MANUAL);
|
||||
}
|
||||
@ -360,355 +362,6 @@ public class AtsTrainService {
|
||||
onboardAtpApiService.resetAtoSpeedMax(simulation, groupNumber);
|
||||
}
|
||||
|
||||
/**
|
||||
* 头码车和人工车运行逻辑
|
||||
*
|
||||
* @param simulation
|
||||
* @param train
|
||||
*/
|
||||
public void runContinue(Simulation simulation, TrainInfo train) {
|
||||
if (train.isPlanTrain() || !train.hasPositionAndDirection()) {
|
||||
return;
|
||||
}
|
||||
SimulationDataRepository repository = simulation.getRepository();
|
||||
if (train.isInbound()) { // 准备回库列车
|
||||
int deleteRemain = train.getDeleteRemain();
|
||||
deleteRemain -= SimulationModule.ATS.getRateMs();
|
||||
if (deleteRemain <= 0) { // 删除列车
|
||||
repository.deleteOnlineTrain(train.getGroupNumber());
|
||||
repository.deleteSuperviseTrain(train.getGroupNumber());
|
||||
} else {
|
||||
train.updateDeleteRemain(deleteRemain);
|
||||
}
|
||||
return;
|
||||
}
|
||||
Long mapId = simulation.getBuildParams().getMap().getId();
|
||||
LocalTime systemTime = simulation.getSystemTime().toLocalTime();
|
||||
Section headSection = repository.getByCode(train.getPhysicalSection(), Section.class);
|
||||
Station headStation = headSection.getStation();
|
||||
float offset = train.getOffsetp() * headSection.getLen();
|
||||
SectionPosition headPosition = new SectionPosition(headSection, offset);
|
||||
Boolean trainRight = train.getRight();
|
||||
TrainType type = train.getType();
|
||||
String estimatedArriveStandTrack = train.getEstimatedArriveStandTrack();
|
||||
Section targetSection = null;
|
||||
Station targetStation = null;
|
||||
if (estimatedArriveStandTrack != null) {
|
||||
targetSection = repository.getByCode(estimatedArriveStandTrack, Section.class);
|
||||
targetStation = targetSection.getStation();
|
||||
}
|
||||
boolean stop = train.isStop();
|
||||
Section nextTarget = null;
|
||||
long runningTime = 0;
|
||||
|
||||
switch (type) {
|
||||
case MANUAL: {
|
||||
Section base = headSection;
|
||||
boolean right = trainRight;
|
||||
if (!CollectionUtils.isEmpty(headSection.getStandList())) {
|
||||
Optional<Stand> onStand = headSection.getStandList().stream().filter(stand -> Objects.equals(stand.isRight(), train.getRight())).findFirst();
|
||||
if (onStand.isPresent()) {
|
||||
runningTime = onStand.get().getRunLevelTime();
|
||||
}
|
||||
}
|
||||
if (train.isParking()) {
|
||||
if (train.getSpeed() > 0) { // 列车出发了
|
||||
// 站台停站状态取消
|
||||
this.atsStandService.trainLeaveStand(headSection);
|
||||
// 更新列车实际离开信息
|
||||
train.updateLeaveInfo(headSection, systemTime);
|
||||
}
|
||||
// 站台停靠
|
||||
Signal tdSignal = headSection.getSignalOf(trainRight); // 列车方向信号机
|
||||
if (Objects.nonNull(tdSignal) && tdSignal.isMainAspect()) {
|
||||
base = headSection.getNextRunningSectionOf(trainRight);
|
||||
} else {
|
||||
Signal trdSignal = headSection.getSignalOf(!trainRight);
|
||||
if (Objects.nonNull(trdSignal) && trdSignal.isMainAspect()) {
|
||||
right = !trainRight;
|
||||
base = headSection.getNextRunningSectionOf(right);
|
||||
}
|
||||
}
|
||||
} else if (stop) {
|
||||
// 列车停车中
|
||||
Signal trdSignal = headSection.getSignalOf(!trainRight);
|
||||
if (Objects.nonNull(trdSignal) && trdSignal.isMainAspect()) {
|
||||
right = !trainRight;
|
||||
}
|
||||
if (headSection.isNormalStandTrack() || headSection.isTransferTrack()) {
|
||||
float stopPointOffset = headSection.getStopPointByDirection(right);
|
||||
SectionPosition standPosition = new SectionPosition(headSection, stopPointOffset);
|
||||
if (headPosition.isAheadOf(standPosition, right)) {
|
||||
base = headSection.getNextRunningSectionOf(right);
|
||||
}
|
||||
}
|
||||
}
|
||||
int count = 0;
|
||||
while (Objects.nonNull(base)) {
|
||||
if ((base.isNormalStandTrack() || base.isTransferTrack())) {
|
||||
nextTarget = base;
|
||||
break;
|
||||
}
|
||||
Signal signal = base.getSignalOf(right);
|
||||
if (Objects.nonNull(signal) && !signal.isMainAspect()) {
|
||||
nextTarget = base;
|
||||
break;
|
||||
}
|
||||
Section section = base.getNextRunningSectionOf(right);
|
||||
if (Objects.isNull(section)) {
|
||||
nextTarget = base;
|
||||
break;
|
||||
} else {
|
||||
base = section;
|
||||
}
|
||||
if (count > 20) {
|
||||
log.warn(String.format("人工列车[%s]前方20个区段都通畅", train.getGroupNumber()));
|
||||
break;
|
||||
}
|
||||
++count;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case HEAD: {
|
||||
String destinationCode = train.getDestinationCode();
|
||||
if (!stop) {
|
||||
if (train.isParking()) {
|
||||
// 站台停站状态取消
|
||||
this.atsStandService.trainLeaveStand(headSection);
|
||||
// 更新列车实际离开信息
|
||||
train.updateLeaveInfo(headSection, systemTime);
|
||||
}
|
||||
} else {
|
||||
/* 判断是否需要更新下一目标区段 */
|
||||
if (trainRight == null)
|
||||
return;
|
||||
Map<String, DestinationCodeDefinition> destinationMap = repository.getDestinationMap();
|
||||
if (CollectionUtils.isEmpty(destinationMap))
|
||||
return;
|
||||
DestinationCodeDefinition destDefinition = destinationMap.get(destinationCode);
|
||||
if (destDefinition == null) {
|
||||
log.error("地图[{}}]目的地码[{}]不存在", simulation.getBuildParams().getMap().getName(), destinationCode);
|
||||
return;
|
||||
}
|
||||
Section destSection = destDefinition.getSection();
|
||||
if (headSection.equals(destSection)) { //列车已到达目的地区段
|
||||
VirtualRealityTrain vrTrain = repository.getOnlineTrainBy(train.getGroupNumber());
|
||||
if (vrTrain.isStopAtThePosition(new SectionPosition(destSection, destSection.getStopPointByDirection(trainRight)))) {
|
||||
if (repository.getConfig().isSetManualWhenHeadTrainArriveTarget()) {
|
||||
setManualTrain(simulation, vrTrain.getGroupNumber());
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (targetSection != null) {
|
||||
SectionPosition targetPosition = new SectionPosition(targetSection, targetSection.getStopPointByDirection(trainRight));
|
||||
// TODO: 2021/5/28 这里列车越过目标停车点的判断逻辑不严谨,如果开过头并换端了,以此逻辑判断并不正确
|
||||
SectionPosition minStopPosition = CalculateService
|
||||
.calculateNextPositionByStartAndLen(targetPosition, !trainRight, SimulationConstants.PARK_POINT_MAX_OFFSET);
|
||||
if (!headPosition.isAheadOf(minStopPosition, trainRight)) //没有越过最小停车位置
|
||||
return;
|
||||
}
|
||||
/* 寻找下一目标区段 */
|
||||
nextTarget = findNextTarget4HeadTrain(simulation, train, repository, headSection, headStation, destDefinition);
|
||||
/* 判断换端并更新目标 */
|
||||
if (nextTarget != null) {
|
||||
if (nextTarget.getCode().equals(estimatedArriveStandTrack)) {
|
||||
return;
|
||||
}
|
||||
boolean isPark = true;
|
||||
if (repository.getConfig().isNoParkingServiceNumber(train.getServiceNumber())) {
|
||||
isPark = false;
|
||||
}
|
||||
if (!nextTarget.isAheadOf(repository, headSection, trainRight)) //下一目标区段不在当前车头方向的前方
|
||||
atpService.turnDirectionImmediately(repository.getOnlineTrainBy(train.getGroupNumber())); //调头
|
||||
SectionPosition stopPosition = new SectionPosition(nextTarget, nextTarget.getStopPointByDirection(trainRight));
|
||||
Float distance = CalculateService.calculateDistance(headPosition, stopPosition, trainRight);
|
||||
if (distance == null) {
|
||||
distance = CalculateService.calculateDistance(headPosition, stopPosition, !trainRight);
|
||||
|
||||
}
|
||||
if (distance != null) {
|
||||
runningTime = (int) (distance / (45 / 3.6));
|
||||
}
|
||||
train.updateEstimatedArriveInfo(nextTarget, simulation.getSystemTime().plusSeconds(runningTime).toLocalTime());
|
||||
this.onboardAtpApiService.updateNextStation(simulation, train.getGroupNumber(),
|
||||
nextTarget.getStation().getCode(), nextTarget.getCode(), runningTime, isPark);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (Objects.nonNull(nextTarget)) {
|
||||
//非计划车跟踪目标轨
|
||||
train.setPlanStandTrack(nextTarget.getCode());
|
||||
String standTrackCode = null;
|
||||
if (train.isParking()) {
|
||||
standTrackCode = train.getActualArriveStandTrack();
|
||||
}
|
||||
if (!stop) {
|
||||
standTrackCode = estimatedArriveStandTrack;
|
||||
}
|
||||
if (standTrackCode == null) {
|
||||
return;
|
||||
}
|
||||
boolean jump = this.atsStandService.isJump(repository.getByCode(standTrackCode, Section.class),
|
||||
train.getGroupNumber());
|
||||
boolean hold = this.atsStandService.isHoldTrain(repository.getByCode(standTrackCode, Section.class));
|
||||
// 更新跳停状态
|
||||
if (!Objects.equals(train.isJump(), jump)) {
|
||||
if (jump) {
|
||||
this.onboardAtpApiService.setJump(simulation, train.getGroupNumber());
|
||||
} else {
|
||||
this.onboardAtpApiService.cancelJump(simulation, train.getGroupNumber());
|
||||
}
|
||||
}
|
||||
// 更新扣车状态
|
||||
if (!Objects.equals(train.isHold(), hold)) {
|
||||
if (hold) {
|
||||
this.onboardAtpApiService.standHoldTrain(simulation, train.getGroupNumber());
|
||||
} else {
|
||||
this.onboardAtpApiService.standCancelHoldTrain(simulation, train.getGroupNumber());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 寻找头码车的下一个目标区段
|
||||
*/
|
||||
public static Section findNextTarget4HeadTrain(Simulation simulation, TrainInfo train, SimulationDataRepository repository, Section headSection,
|
||||
Station headStation, DestinationCodeDefinition destinationCodeDefinition) {
|
||||
Section nextTarget = null;
|
||||
Boolean destinationRight = destinationCodeDefinition.getRight();
|
||||
switch (destinationCodeDefinition.getType()) {
|
||||
case NORMAL_OPERATION: {
|
||||
nextTarget = destinationCodeDefinition.queryNextTargetSection(headSection);
|
||||
if (nextTarget != null) {
|
||||
break;
|
||||
}
|
||||
Station leftStation = destinationCodeDefinition.getLeftStation();
|
||||
Station rightStation = destinationCodeDefinition.getRightStation();
|
||||
if (destinationCodeDefinition.isBorder(headStation)) { //到达边界车站
|
||||
boolean rightEnd = headStation.equals(rightStation); //是否右端车站
|
||||
if (headSection.isNormalStandTrack()) {
|
||||
boolean standRight = headStation.isStandOfSectionRight(headSection); //是否是右行站台
|
||||
if (rightEnd == standRight && !destinationCodeDefinition.isFrontTurnBack(headStation)) { //需要站后折返
|
||||
//查询目的地码定义指定的折返轨
|
||||
nextTarget = destinationCodeDefinition.getNecessarySections().stream()
|
||||
.filter(section -> section.isTurnBackTrack() && !section.isStandTrack() && section.getStation().equals(headStation))
|
||||
.findAny().orElse(null);
|
||||
//查询车站指定的折返轨
|
||||
if (nextTarget == null) {
|
||||
if (!CollectionUtils.isEmpty(headStation.getTbStrategyMap()) && headStation.getTbStrategyId() != null) {
|
||||
StationTurnBackStrategyOption strategy = headStation.getCurrentTurnBackStrategy();
|
||||
Section tbSection = strategy.getSectionList().get(0);
|
||||
switch (strategy.getType()) {
|
||||
case FIRST:
|
||||
List<RoutePath> routePaths = CalculateService.queryRoutePathsOnDirection(headSection, tbSection, standRight, 10);
|
||||
if (routePaths.stream().anyMatch(path -> !path.isOccupied())) {
|
||||
nextTarget = tbSection;
|
||||
}
|
||||
break;
|
||||
case ONLY:
|
||||
nextTarget = tbSection;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//随意选择能用的折返轨
|
||||
if (nextTarget == null) {
|
||||
for (Section section : headStation.getTurnBackList()) {
|
||||
if (section.isNormalStandTrack()) {
|
||||
continue;
|
||||
}
|
||||
List<RoutePath> routePaths = CalculateService.queryRoutePathsOnDirection(headSection, section, standRight, 10);
|
||||
if (routePaths.stream().anyMatch(path -> !path.isOccupied())) {
|
||||
nextTarget = section;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else { //站前折返或已到站后折返轨
|
||||
Station adjacentStation = simulation.getRepository().findAdjacentStation(headStation, !rightEnd);
|
||||
BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertNotNull(adjacentStation,
|
||||
String.format("%s的%s侧相邻车站不存在", headStation.debugStr(), rightEnd ? "左" : "右"));
|
||||
nextTarget = adjacentStation.getNormalStand(!rightEnd).get(0).getSection();
|
||||
}
|
||||
} else if (headSection.isTurnBackTrack()) { //认为是站后折返轨
|
||||
nextTarget = headStation.getNormalStand(!rightEnd).get(0).getSection();
|
||||
}
|
||||
} else { //不在边界车站
|
||||
if (!headSection.isNormalStandTrack()) { //认为此时列车一定在站台轨(如果是在折返轨不好处理,故略过)
|
||||
break;
|
||||
}
|
||||
boolean standRight = headStation.isStandOfSectionRight(headSection);
|
||||
Station adjacentStation = simulation.getRepository().findAdjacentStation(headStation, standRight);
|
||||
if (destinationCodeDefinition.isBorder(adjacentStation)) {
|
||||
if (destinationCodeDefinition.isFrontTurnBack(adjacentStation)) {
|
||||
nextTarget = destinationCodeDefinition.getNecessarySections().stream()
|
||||
.filter(section -> section.isStandTrack() && adjacentStation.equals(section.getStation()))
|
||||
.limit(1).findAny().orElse(null);
|
||||
if (nextTarget != null) {
|
||||
break;
|
||||
}
|
||||
nextTarget = adjacentStation.getNormalStand(!standRight).get(0).getSection();
|
||||
if (CollectionUtils.isEmpty(CalculateService.queryRoutePathsOnDirection(headSection, nextTarget, standRight, 10))) {
|
||||
nextTarget = adjacentStation.getNormalStand(standRight).get(0).getSection();
|
||||
}
|
||||
} else {
|
||||
nextTarget = adjacentStation.getNormalStand(standRight).get(0).getSection();
|
||||
}
|
||||
} else {
|
||||
nextTarget = adjacentStation.getNormalStand(standRight).get(0).getSection();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LAST_OPERATION:
|
||||
case NON_OPERATION:
|
||||
case LAST_NON_OPERATION:
|
||||
nextTarget = destinationCodeDefinition.queryNextTargetSection(headSection);
|
||||
if (nextTarget == null) {
|
||||
nextTarget = headStation.getNormalStand(destinationRight).get(0).getSection();
|
||||
if (!headSection.equals(nextTarget)) {
|
||||
List<RoutePath> routePaths = CalculateService.queryRoutePathsOnDirection(headSection, nextTarget, destinationRight, 10);
|
||||
if (!CollectionUtils.isEmpty(routePaths)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Station adjacentStation = simulation.getRepository().findAdjacentStation(headStation, destinationRight);
|
||||
nextTarget = adjacentStation.getNormalStand(destinationRight).get(0).getSection();
|
||||
}
|
||||
break;
|
||||
case OTHER:
|
||||
List<Section> path = train.getHctPath().getSections();
|
||||
if (path != null) {
|
||||
int index = path.indexOf(headSection);
|
||||
if (index == -1) {
|
||||
break;
|
||||
}
|
||||
for (int i = index + 1; i < path.size(); i++) {
|
||||
Section section = path.get(i);
|
||||
if (section.isSpecialSection()) {
|
||||
List<RoutePath> routePaths = repository.queryRoutePathsByEnd(section);
|
||||
if (routePaths.stream().anyMatch(rp -> rp.containsSection(headSection))) {
|
||||
nextTarget = section;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nextTarget == null) {
|
||||
nextTarget = path.get(path.size() - 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return nextTarget;
|
||||
}
|
||||
|
||||
/**
|
||||
* 扣车
|
||||
*/
|
||||
@ -772,7 +425,7 @@ public class AtsTrainService {
|
||||
if (distance == null) {
|
||||
throw new SimulationException(SimulationExceptionType.Illegal_Argument, "无法到达的位置");
|
||||
}
|
||||
targetPosition = CalculateService.calculateNextPositionByStartAndLen(train.getHeadPosition(), right, distance);
|
||||
targetPosition = CalculateService.calculateNextPositionByStartAndLen(train.getHeadPosition(), right, distance, false);
|
||||
} else {
|
||||
targetPosition = new SectionPosition(section, section.getStopPointByDirection(right));
|
||||
}
|
||||
@ -783,7 +436,7 @@ public class AtsTrainService {
|
||||
VirtualRealityTrain targetTrain = repository.getVRByCode(targetDeviceCode, VirtualRealityTrain.class);
|
||||
SectionPosition targetTrainTailPosition = targetTrain.calculateTailPosition();
|
||||
boolean targetIsRight = targetTrain.isRight();
|
||||
targetPosition = CalculateService.calculateNextPositionByStartAndLen(targetTrainTailPosition, !targetIsRight, 2);
|
||||
targetPosition = CalculateService.calculateNextPositionByStartAndLen(targetTrainTailPosition, !targetIsRight, 2, false);
|
||||
}
|
||||
SectionPosition physicalPosition = targetPosition.convert2PhysicalSectionPosition();
|
||||
train.setRobotTargetPosition(physicalPosition);
|
||||
|
@ -86,6 +86,8 @@ public class AtsHeadTrainStageService implements AtsStageService {
|
||||
* 处理列车到达目的地
|
||||
*/
|
||||
private void handleArriveDestination(Simulation simulation, TrainInfo trainInfo) {
|
||||
// 先回库,后设置为人工车
|
||||
trainInfo.finishPlanPrepareInbound();
|
||||
if (simulation.getRepository().getConfig().isSetManualWhenHeadTrainArriveTarget()) {
|
||||
atsTrainService.setManualTrain(simulation, trainInfo.getGroupNumber());
|
||||
}
|
||||
|
@ -41,11 +41,15 @@ public class AtsPlanTrainStageService implements AtsStageService {
|
||||
TripPlan tripPlan = repository.getTripPlan(trainInfo.getServiceNumber(), trainInfo.getTripNumber());
|
||||
List<RoutePath> routePathList = repository.queryRoutePathsByEnd(parkSection);
|
||||
if (routePathList.get(0).isRight() == trainInfo.getRight()) { //准备回库
|
||||
trainInfo.finishPlanPrepareInbound();
|
||||
if (!parkSection.isTurnBackTrack()) { //针对上饶沙盘
|
||||
trainInfo.finishPlanPrepareInbound();
|
||||
}
|
||||
} else if (tripPlan.getEndSection().equals(parkSection) ||
|
||||
tripPlan.getEndSection().getStation().equals(parkSection.getStation())) {
|
||||
// 列车到达计划终点,准备回库
|
||||
trainInfo.finishPlanPrepareInbound();
|
||||
if (!parkSection.isTurnBackTrack()) { //针对上饶沙盘
|
||||
trainInfo.finishPlanPrepareInbound();
|
||||
}
|
||||
} else if (tripPlan.getStartSection().equals(parkSection)) {
|
||||
// 出库列车
|
||||
if (trainInfo.getPlanStandTrack() != null) {
|
||||
|
@ -75,7 +75,9 @@ public class AtsTrainStageHandler {
|
||||
this.onboardAtpApiService.departure(simulation, trainInfo.getGroupNumber());
|
||||
}
|
||||
} else { // 折返轨
|
||||
stageService.handleTurnBackTrackParking(simulation, trainInfo, parkSection);
|
||||
if (!(parkSection.getStation() != null && parkSection.getStation().isDepot())) { //上饶
|
||||
stageService.handleTurnBackTrackParking(simulation, trainInfo, parkSection);
|
||||
}
|
||||
}
|
||||
if (!trainInfo.isStop()) {
|
||||
trainInfo.updateParking(false);
|
||||
|
@ -15,9 +15,7 @@ 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;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@ -246,21 +244,23 @@ public class CiApiServiceImpl2 implements CiApiService {
|
||||
@Override
|
||||
public void switchSectionFaultUnlock(Simulation simulation, String switchCode) {
|
||||
Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class);
|
||||
if (!aSwitch.isLocked() && aSwitch.getAllSections().stream().noneMatch(Section::isFaultLock))
|
||||
if (!aSwitch.isLocked() && aSwitch.getAllSections().stream().noneMatch(Section::isLocked))
|
||||
return;
|
||||
List<Route> lockedRouteList = simulation.getRepository().queryAllLockedRoute();
|
||||
Route lockedRoute = null;
|
||||
Set<Route> lockSwitchRoutes = new HashSet<>();
|
||||
if (aSwitch.isRouteLock()) {
|
||||
lockedRoute = aSwitch.getRoute();
|
||||
lockSwitchRoutes = aSwitch.getRoutes();
|
||||
} else if (aSwitch.isOverlapLock()) {
|
||||
for (Route route : lockedRouteList) {
|
||||
if (route.overlapContainSwitch(aSwitch)) {
|
||||
lockedRoute = route;
|
||||
lockSwitchRoutes.add(route);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.routeService.switchFaultUnlock(simulation, aSwitch, lockedRoute);
|
||||
for (Route lockedRoute : lockSwitchRoutes) {
|
||||
this.routeService.switchFaultUnlock(simulation, aSwitch, lockedRoute);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -44,7 +44,7 @@ public class CiRouteService {
|
||||
}
|
||||
}
|
||||
// 进路中道岔没有被征用或锁定在相反位置
|
||||
Route.CheckFailMessage failMessage = setSwitchCheck(route.getSwitchList());
|
||||
Route.CheckFailMessage failMessage = setSwitchCheck(simulation, route.getSwitchList());
|
||||
if (failMessage != null) {
|
||||
return failMessage;
|
||||
}
|
||||
@ -110,7 +110,7 @@ public class CiRouteService {
|
||||
RouteOverlap overlap = route.getOverlap();
|
||||
if (Objects.nonNull(overlap)) {
|
||||
SectionPath sectionPath = overlap.selectPath();
|
||||
failMessage = setSwitchCheck(sectionPath.getSwitchList());
|
||||
failMessage = setSwitchCheck(simulation, sectionPath.getSwitchList());
|
||||
}
|
||||
}
|
||||
return failMessage;
|
||||
@ -133,7 +133,7 @@ public class CiRouteService {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Route.CheckFailMessage setSwitchCheck(List<SwitchElement> switchList) {
|
||||
private static Route.CheckFailMessage setSwitchCheck(Simulation simulation, List<SwitchElement> switchList) {
|
||||
if (switchList != null) {
|
||||
for (SwitchElement switchElement : switchList) {
|
||||
Switch aSwitch = switchElement.getASwitch();
|
||||
@ -147,6 +147,13 @@ public class CiRouteService {
|
||||
if (aSwitch.isCiUseOnOppositePosition(switchElement.isNormal())) { // 道岔征用在相反位置
|
||||
return new Route.CheckFailMessage(Route.CheckFailReason.SwitchCiUseOnOppositePosition, aSwitch);
|
||||
}
|
||||
// 非预先锁闭,道岔相应位置失表则不排进路
|
||||
if (!simulation.getRepository().getConfig().isLockFirst() && aSwitch.isLoss()) {
|
||||
if ((Switch.SwitchFault.NORMAL_SPLIT.equals(aSwitch.getFault()) && switchElement.isNormal())
|
||||
|| (Switch.SwitchFault.REVERSE_SPLIT.equals(aSwitch.getFault()) && !switchElement.isNormal())) {
|
||||
return new Route.CheckFailMessage(Route.CheckFailReason.SwitchFault, aSwitch);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@ -310,12 +317,19 @@ public class CiRouteService {
|
||||
return;
|
||||
}
|
||||
if (section.isSwitchTrack()) {
|
||||
//解锁道岔
|
||||
Switch relSwitch = section.getRelSwitch();
|
||||
relSwitch.routeUnlock(route);
|
||||
//解锁道岔侧防
|
||||
RouteFls routeFls = route.queryRouteFlsOfSwitch(relSwitch);
|
||||
if (routeFls != null) {
|
||||
routeFls.unlock();
|
||||
}
|
||||
//解锁联动道岔
|
||||
Switch linkedSwitch = relSwitch.queryLinkedSwitch();
|
||||
if (linkedSwitch != null) {
|
||||
linkedSwitch.routeUnlock(route);
|
||||
}
|
||||
} else {
|
||||
section.routeUnlocking(route);
|
||||
}
|
||||
|
@ -27,11 +27,23 @@ public class CiService {
|
||||
if (overlap.getSection().isRouteLock()) {
|
||||
SectionPath sectionPath = overlap.selectPath();
|
||||
for (SwitchElement switchElement : sectionPath.getSwitchList()) {
|
||||
if (switchElement.getASwitch().isLocked() && !switchElement.isOnPosition()) {
|
||||
Switch aSwitch = switchElement.getASwitch();
|
||||
if (aSwitch.isLocked() && !switchElement.isOnPosition()) {
|
||||
log.debug("延续保护进路[{}]道岔[{}]锁闭在相反位置,不触发办理", overlap.debugStr(),
|
||||
switchElement.getASwitch().debugStr());
|
||||
aSwitch.debugStr());
|
||||
return;
|
||||
}
|
||||
// 非预先锁闭,道岔相应位置失表则不排延续保护
|
||||
if (!simulation.getRepository().getConfig().isLockFirst() && aSwitch.isLoss()) {
|
||||
if ((Switch.SwitchFault.NORMAL_SPLIT.equals(aSwitch.getFault())
|
||||
&& switchElement.isNormal())
|
||||
|| (Switch.SwitchFault.REVERSE_SPLIT.equals(aSwitch.getFault())
|
||||
&& !switchElement.isNormal())) {
|
||||
log.debug("延续保护进路[{}]道岔[{}]位置失表,不触发办理", overlap.debugStr(),
|
||||
aSwitch.debugStr());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
overlap.startSetting(simulation.getSystemTime());
|
||||
}
|
||||
|
@ -17,10 +17,11 @@ import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.heb.device.Heb1Ps
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.richor.ZjdIbpConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.richor.ZjdPslConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.xty.XtyPsdConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.Sr.SrSectionConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.Sr.SrSignalConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.Sr.SrSwitchConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.sr.config.SrSectionConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.sr.config.SrSignalConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.sr.config.SrSwitchConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.UDPRealDeviceThread;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.sr.config.SrTrainConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.event.SimulationUserEnterEvent;
|
||||
import club.joylink.rtss.simulation.cbtc.member.MemberManager;
|
||||
import club.joylink.rtss.simulation.cbtc.member.SimulationMember;
|
||||
@ -161,6 +162,8 @@ public class ProjectJointSimulationServiceImpl implements ProjectJointSimulation
|
||||
return ((SrSectionConfig) config).getConfigVO().getVrCode();
|
||||
case SWITCH:
|
||||
return ((SrSwitchConfig) config).getConfigVO().getVrCode();
|
||||
case TRAIN:
|
||||
return ((SrTrainConfig) config).getConfigVO().getVrCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1291,7 +1291,8 @@ public class MapDeviceBuilder {
|
||||
}
|
||||
elementMap.put(station.getCode(), station);
|
||||
station.setCentralized(stationVO.isCentralized());
|
||||
if (station.isCentralized()) {
|
||||
station.setDepot(stationVO.isDepot());
|
||||
if (station.isCentralized() && !station.isDepot()) {
|
||||
ZC zc = (ZC) elementMap.get(stationVO.getZcCode());
|
||||
if (Objects.isNull(zc)) {
|
||||
errMsgList.add(String.format("车站[%s(%s)]未关联ZC或ZC不存在,请在ZC设备处选择管理的集中站列表", station.getName(), station.getCode()));
|
||||
|
@ -516,6 +516,9 @@ public class CommandBO {
|
||||
public Step execute(Simulation simulation, CommandBO command) {
|
||||
SimulationMember driver = command.getTargetMember();
|
||||
VirtualRealityTrain train = (VirtualRealityTrain) driver.getDevice();
|
||||
if (!train.isAtpOn()) {
|
||||
return buildDriverATPChangeOperationStep(train.getGroupNumber(), false);
|
||||
}
|
||||
if (train.isSignalEB()) {
|
||||
return getStep4ReleaseEB(train);
|
||||
}
|
||||
@ -531,6 +534,27 @@ public class CommandBO {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 转NRM模式
|
||||
*/
|
||||
Apply_NRM(List.of(), SimulationMember.Type.DRIVER) {
|
||||
@Override
|
||||
public List<Step> buildStepList(Simulation simulation, SimulationMember targetMember, Map<String, Object> params) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Step execute(Simulation simulation, CommandBO command) {
|
||||
SimulationMember driver = command.getTargetMember();
|
||||
VirtualRealityTrain train = (VirtualRealityTrain) driver.getDevice();
|
||||
if (train.isNRMMode()) {
|
||||
driver.setCommand(null);
|
||||
return null;
|
||||
}
|
||||
return buildDriverATPChangeOperationStep(train.getGroupNumber(), true);
|
||||
}
|
||||
};
|
||||
|
||||
public enum ParamName {
|
||||
@ -754,7 +778,7 @@ public class CommandBO {
|
||||
} else {
|
||||
return buildPreselectionModeDownOperationStep(groupNumber);
|
||||
}
|
||||
} else if (ConfirmationMessage.Confirm_Preselection.equals(train.findFirstMessage())) {
|
||||
} else /*if (ConfirmationMessage.Confirm_Preselection.equals(train.findFirstMessage()))*/ {
|
||||
return buildConfirmOperationStep(groupNumber);
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ import java.util.*;
|
||||
@Slf4j
|
||||
public class CalculateService {
|
||||
|
||||
public static SectionPosition getAvailableSectionPositionOf(SectionPosition sectionPosition) {
|
||||
public static SectionPosition getAvailableSectionPositionOf(SectionPosition sectionPosition, boolean baseReal) {
|
||||
if (!sectionPosition.isAvailable()) {
|
||||
float offset = sectionPosition.getOffset();
|
||||
Section baseSection = sectionPosition.getSection();
|
||||
@ -25,7 +25,12 @@ public class CalculateService {
|
||||
while (offset < 0 || offset > baseSection.getLen()) {
|
||||
++count;
|
||||
if (offset < 0) { // 向左
|
||||
Section leftSection = baseSection.getNextRunningSectionOf(false);
|
||||
Section leftSection;
|
||||
if (baseReal) {
|
||||
leftSection = baseSection.getNextRunningSectionBaseRealSwitch(false);
|
||||
} else {
|
||||
leftSection = baseSection.getNextRunningSectionOf(false);
|
||||
}
|
||||
if (Objects.nonNull(leftSection)) { // 左区段存在
|
||||
offset = leftSection.getLen() + offset;
|
||||
baseSection = leftSection;
|
||||
@ -34,7 +39,12 @@ public class CalculateService {
|
||||
offset = 0;
|
||||
}
|
||||
} else { // 向右
|
||||
Section rightSection = baseSection.getNextRunningSectionOf(true);
|
||||
Section rightSection;
|
||||
if (baseReal) {
|
||||
rightSection = baseSection.getNextRunningSectionBaseRealSwitch(true);
|
||||
} else {
|
||||
rightSection = baseSection.getNextRunningSectionOf(true);
|
||||
}
|
||||
if (Objects.nonNull(rightSection)) { // 右向区段存在
|
||||
offset = offset - baseSection.getLen();
|
||||
baseSection = rightSection;
|
||||
@ -61,13 +71,13 @@ public class CalculateService {
|
||||
* 根据开始位置、方向、距离计算到达的位置(不会超出正线轨道范围,不会冲过位置不合适道岔)
|
||||
*/
|
||||
public static SectionPosition calculateNextPositionByStartAndLen(SectionPosition startPosition,
|
||||
boolean right, float len) {
|
||||
boolean right, float len, boolean baseReal) {
|
||||
if (!right) {
|
||||
len = -len;
|
||||
}
|
||||
float offset = startPosition.getOffset();
|
||||
float offsetNew = offset + len;
|
||||
return getAvailableSectionPositionOf(new SectionPosition(startPosition.getSection(), offsetNew));
|
||||
return getAvailableSectionPositionOf(new SectionPosition(startPosition.getSection(), offsetNew), baseReal);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -509,7 +519,7 @@ public class CalculateService {
|
||||
Section section = source;
|
||||
while (!section.getCode().equals(target.getCode()) && loop < 20) {
|
||||
loop++;
|
||||
Section temp = section.getNextRunningSectionOf(right);
|
||||
Section temp = section.getNextRunningSectionBaseRealSwitch(right);
|
||||
if (Objects.nonNull(temp)) { // 不为空
|
||||
section = temp;
|
||||
occupySectionList.add(section);
|
||||
@ -1010,7 +1020,7 @@ public class CalculateService {
|
||||
this.headPosition = train.getHeadPosition();
|
||||
this.right = train.isRight();
|
||||
this.tailPosition = CalculateService
|
||||
.calculateNextPositionByStartAndLen(headPosition, !right, train.getLen());
|
||||
.calculateNextPositionByStartAndLen(headPosition, !right, train.getLen(), false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1020,7 +1030,7 @@ public class CalculateService {
|
||||
this.headPosition = train.getHeadPosition();
|
||||
this.right = train.isRight();
|
||||
this.tailPosition = CalculateService
|
||||
.calculateNextPositionByStartAndLen(headPosition, !right, train.getLen() + append);
|
||||
.calculateNextPositionByStartAndLen(headPosition, !right, train.getLen() + append, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -802,6 +802,22 @@ public class SimulationDataRepository {
|
||||
return next;
|
||||
}
|
||||
|
||||
public TripPlan findNextTripPlan(TripPlan tripPlan) {
|
||||
Section endSection = tripPlan.getEndSection();
|
||||
List<TripPlan> planList = this.endTripMap.get(endSection.getCode());
|
||||
TripPlan next = null;
|
||||
if (!CollectionUtils.isEmpty(planList)) {
|
||||
for (TripPlan plan : planList) {
|
||||
if (plan.isDeparture()) {
|
||||
continue;
|
||||
}
|
||||
next = plan;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
/**
|
||||
* 此方法只能用于计划车次号唯一的线路(比如西门子风格的运行计划)
|
||||
* @param tripNumber
|
||||
|
@ -10,10 +10,7 @@ import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 区段
|
||||
@ -363,7 +360,7 @@ public class Section extends DelayUnlockDevice {
|
||||
} else { // B或C
|
||||
if (right && a.getLeftSection() != null) {
|
||||
return this.rightSection;
|
||||
} else if(!right && a.getRightSection() != null) {
|
||||
} else if (!right && a.getRightSection() != null) {
|
||||
return this.leftSection;
|
||||
} else if ((relSwitch.isPosN() && relSwitch.isB(this)) ||
|
||||
(relSwitch.isPosR() && relSwitch.isC(this))) {
|
||||
@ -463,6 +460,9 @@ public class Section extends DelayUnlockDevice {
|
||||
public void axleCounterOccupy(boolean right) {
|
||||
this.trainRight = right;
|
||||
this.setNctOccupied(true);
|
||||
if (isSwitchAxleCounterSection()) {
|
||||
nctOccupiedBySwitchPosition();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -764,10 +764,19 @@ public class Section extends DelayUnlockDevice {
|
||||
}
|
||||
|
||||
public void nonCommunicateTrainOccupy(boolean right) {
|
||||
this.trainRight = right;
|
||||
this.setNctOccupied(true);
|
||||
// this.nctOccupied = true;
|
||||
// setCtOccupied(false);
|
||||
VirtualRealitySectionAxleCounter axle = findAxle();
|
||||
if (axle != null && axle.isOccupy()) {
|
||||
this.trainRight = right;
|
||||
this.setNctOccupied(true);
|
||||
}
|
||||
}
|
||||
|
||||
public VirtualRealitySectionAxleCounter findAxle() {
|
||||
VirtualRealitySectionAxleCounter axle = this.virtualAxleCounter;
|
||||
if (axle == null && this.parent != null) {
|
||||
return this.parent.findAxle();
|
||||
}
|
||||
return axle;
|
||||
}
|
||||
|
||||
public boolean isOccupiedOn(boolean right) {
|
||||
@ -813,24 +822,7 @@ public class Section extends DelayUnlockDevice {
|
||||
}
|
||||
this.setNctOccupied(true);
|
||||
if (this.isSwitchAxleCounterSection()) { // 道岔计轴区段
|
||||
List<Switch> relSwitchList = this.getRelSwitchList();
|
||||
for (Switch aSwitch : relSwitchList) {
|
||||
aSwitch.getA().setNctOccupied(true);
|
||||
if (aSwitch.isPosN()) {
|
||||
aSwitch.getB().setNctOccupied(true);
|
||||
aSwitch.getC().setNctOccupied(false);
|
||||
} else if (aSwitch.isPosR()) {
|
||||
aSwitch.getC().setNctOccupied(true);
|
||||
aSwitch.getB().setNctOccupied(false);
|
||||
} else {
|
||||
aSwitch.getB().setNctOccupied(true);
|
||||
aSwitch.getC().setNctOccupied(true);
|
||||
}
|
||||
}
|
||||
Section cross = queryCross();
|
||||
if (cross != null) {
|
||||
cross.crossJudgeInvalid();
|
||||
}
|
||||
nctOccupiedBySwitchPosition();
|
||||
} else if (!CollectionUtils.isEmpty(this.logicList)) {
|
||||
for (Section logic : this.logicList) {
|
||||
logic.setNctOccupied(true);
|
||||
@ -838,6 +830,30 @@ public class Section extends DelayUnlockDevice {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据道岔位置设置非通信车占用
|
||||
*/
|
||||
private void nctOccupiedBySwitchPosition() {
|
||||
List<Switch> relSwitchList = this.getRelSwitchList();
|
||||
for (Switch aSwitch : relSwitchList) {
|
||||
aSwitch.getA().setNctOccupied(true);
|
||||
if (aSwitch.isPosN()) {
|
||||
aSwitch.getB().setNctOccupied(true);
|
||||
aSwitch.getC().setNctOccupied(false);
|
||||
} else if (aSwitch.isPosR()) {
|
||||
aSwitch.getC().setNctOccupied(true);
|
||||
aSwitch.getB().setNctOccupied(false);
|
||||
} else {
|
||||
aSwitch.getB().setNctOccupied(true);
|
||||
aSwitch.getC().setNctOccupied(true);
|
||||
}
|
||||
}
|
||||
Section cross = queryCross();
|
||||
if (cross != null) {
|
||||
cross.crossJudgeInvalid();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 岔心判断失效
|
||||
*/
|
||||
@ -1092,7 +1108,7 @@ public class Section extends DelayUnlockDevice {
|
||||
if (!CollectionUtils.isEmpty(zcs)) {
|
||||
return zcs.stream().anyMatch(zc -> !zc.isFault());
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setInvalid(boolean invalid) {
|
||||
@ -1168,6 +1184,31 @@ public class Section extends DelayUnlockDevice {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取道岔计轴区段被道岔连接起来的区段
|
||||
*/
|
||||
public List<Section> findConnectedSections() {
|
||||
if (!isSwitchAxleCounterSection())
|
||||
return Collections.emptyList();
|
||||
Switch relSwitch = getLogicList().get(0).getRelSwitch();
|
||||
List<Section> sections = new ArrayList<>();
|
||||
sections.add(relSwitch.getA());
|
||||
if (relSwitch.isPosN()) {
|
||||
sections.add(relSwitch.getB());
|
||||
} else if (relSwitch.isPosR()) {
|
||||
sections.add(relSwitch.getC());
|
||||
}
|
||||
return sections;
|
||||
}
|
||||
|
||||
public Section findPhysicalSection() {
|
||||
if (this.isPhysical())
|
||||
return this;
|
||||
if (this.parent != null)
|
||||
return this.parent.findPhysicalSection();
|
||||
return null;
|
||||
}
|
||||
|
||||
public enum SectionRoadType {
|
||||
/**
|
||||
* 左行线
|
||||
|
@ -440,6 +440,10 @@ public class Signal extends DelayUnlockDevice {
|
||||
return SignalType.TRANSMISSION.equals(this.type);
|
||||
}
|
||||
|
||||
public boolean isOutboundSignal() {
|
||||
return SignalType.OUTBOUND.equals(this.type);
|
||||
}
|
||||
|
||||
public boolean isDepotSameSignal(Signal signal) {
|
||||
return this.type.equals(signal.getType())
|
||||
|| (this.type.equals(SignalType.SHUNTING2) && signal.getType().equals(SignalType.SHUNTING));
|
||||
|
@ -5,9 +5,7 @@ import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealitySwitch;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@ -74,7 +72,7 @@ public class Switch extends DelayUnlockDevice {
|
||||
/**
|
||||
* 锁闭该道岔的进路
|
||||
*/
|
||||
private Route route;
|
||||
private final Set<Route> routes = new HashSet<>();
|
||||
|
||||
/**
|
||||
* 是否进路侧防锁闭
|
||||
@ -141,7 +139,7 @@ public class Switch extends DelayUnlockDevice {
|
||||
this.blockade = false;
|
||||
this.usePosition = No_Use;
|
||||
this.routeLock = false;
|
||||
this.route = null;
|
||||
this.routes.clear();
|
||||
this.fpLock = false;
|
||||
this.overlapLock = false;
|
||||
this.masterGuideLock = false;
|
||||
@ -207,22 +205,22 @@ public class Switch extends DelayUnlockDevice {
|
||||
|
||||
public void routeLock(Route route) {
|
||||
this.routeLock = true;
|
||||
this.route = route;
|
||||
this.routes.add(route);
|
||||
}
|
||||
|
||||
public void routeUnlock(Route route) {
|
||||
if (this.isRouteLockBy(route)) {
|
||||
this.a.routeUnlocking(this.route);
|
||||
this.b.routeUnlocking(this.route);
|
||||
this.c.routeUnlocking(this.route);
|
||||
this.routeLock = false;
|
||||
this.route = null;
|
||||
this.a.routeUnlocking(route);
|
||||
this.b.routeUnlocking(route);
|
||||
this.c.routeUnlocking(route);
|
||||
this.routes.remove(route);
|
||||
this.routeLock = !this.routes.isEmpty();
|
||||
this.checkAndResetUsePosition();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isRouteLockBy(Route route) {
|
||||
return this.routeLock && this.route.equals(route);
|
||||
return this.routeLock && this.routes.contains(route);
|
||||
}
|
||||
|
||||
private void checkAndResetUsePosition() {
|
||||
@ -393,7 +391,9 @@ public class Switch extends DelayUnlockDevice {
|
||||
}
|
||||
|
||||
public void faultUnlock() {
|
||||
this.routeUnlock(this.route);
|
||||
for (Route route : routes) {
|
||||
this.routeUnlock(route);
|
||||
}
|
||||
this.overlapUnLock();
|
||||
this.fpUnlock();
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package club.joylink.rtss.simulation.cbtc.data.storage;
|
||||
|
||||
import club.joylink.rtss.simulation.cbtc.Simulation;
|
||||
import club.joylink.rtss.simulation.cbtc.build.RunPlanBuilder;
|
||||
import club.joylink.rtss.simulation.cbtc.data.SimulationDataRepository;
|
||||
import club.joylink.rtss.simulation.cbtc.data.map.*;
|
||||
import club.joylink.rtss.simulation.cbtc.data.plan.SchedulingTrainPlan;
|
||||
@ -18,6 +19,7 @@ import lombok.Setter;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
@ -379,8 +381,12 @@ public class StorageSimulationDataRepository {
|
||||
// 恢复服务-车次计划列表map
|
||||
if (!CollectionUtils.isEmpty(this.serviceTripList)) {
|
||||
List<TripPlan> plans = StorageTripPlan.convert2SimulationObjList(repository, this.serviceTripList);
|
||||
Map<String, List<TripPlan>> tripPlanMap = plans.stream().collect(Collectors.groupingBy(TripPlan::getServiceNumber));
|
||||
repository.setServiceTripsMap(tripPlanMap);
|
||||
RunPlanBuilder.RunPlanBuildResult runPlanBuildResult = new RunPlanBuilder.RunPlanBuildResult();
|
||||
plans.forEach(runPlanBuildResult::addTripPlan);
|
||||
runPlanBuildResult.sort();
|
||||
repository.setServiceTripsMap(runPlanBuildResult.getServerTripMap());
|
||||
repository.setStandTripMap(runPlanBuildResult.getStandTripMap());
|
||||
repository.setEndTripMap(runPlanBuildResult.getEndTripMap());
|
||||
// for (StorageTripPlan storageTripPlan : this.serviceTripList) {
|
||||
// TripPlan tripPlan = repository.getTripPlan(storageTripPlan.getServiceNumber(), storageTripPlan.getTripNumber());
|
||||
// tripPlan.use();
|
||||
|
@ -14,6 +14,11 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@ -43,6 +48,8 @@ public class StorageSwitch extends StorageDelayUnlockDevice {
|
||||
|
||||
private String route;
|
||||
|
||||
private Set<String> routes;
|
||||
|
||||
/**
|
||||
* 是否进路侧防锁闭
|
||||
*/
|
||||
@ -95,10 +102,16 @@ public class StorageSwitch extends StorageDelayUnlockDevice {
|
||||
change = true;
|
||||
storageSwitch.setRouteLock(s.isRouteLock());
|
||||
}
|
||||
Route route = s.getRoute();
|
||||
if (route != null) {
|
||||
// Route route = s.getRoutes();
|
||||
// if (route != null) {
|
||||
// change = true;
|
||||
// storageSwitch.setRoute(route.getCode());
|
||||
// }
|
||||
Set<Route> routes = s.getRoutes();
|
||||
if (!CollectionUtils.isEmpty(routes)) {
|
||||
change = true;
|
||||
storageSwitch.setRoute(route.getCode());
|
||||
Set<String> routeCodes = routes.stream().map(MapElement::getCode).collect(Collectors.toSet());
|
||||
storageSwitch.setRoutes(routeCodes);
|
||||
}
|
||||
if (s.isFpLock()) {
|
||||
change = true;
|
||||
@ -141,7 +154,18 @@ public class StorageSwitch extends StorageDelayUnlockDevice {
|
||||
s.setSingleLock(singleLock != null ? singleLock : false);
|
||||
s.setBlockade(blockade != null ? blockade : false);
|
||||
s.setRouteLock(routeLock != null ? routeLock : false);
|
||||
s.setRoute(route == null ? null : repository.getByCode(route, Route.class));
|
||||
if (route != null) {
|
||||
Route route = repository.getByCode(this.route, Route.class);
|
||||
s.getRoutes().add(route);
|
||||
} else if (!CollectionUtils.isEmpty(routes)) {
|
||||
for (String code : routes) {
|
||||
Route route = repository.getByCode(code, Route.class);
|
||||
s.getRoutes().add(route);
|
||||
}
|
||||
} else {
|
||||
s.getRoutes().clear();
|
||||
}
|
||||
// s.setRoutes(route == null ? null : repository.getByCode(route, Route.class));
|
||||
s.setOverlapLock(overlapLock != null ? overlapLock : false);
|
||||
s.setMasterGuideLock(masterGuideLock != null ? masterGuideLock : false);
|
||||
if (pos != null) {
|
||||
|
@ -11,9 +11,6 @@ import club.joylink.rtss.simulation.cbtc.onboard.ATO.SpeedCurve;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import javax.script.ScriptEngine;
|
||||
import javax.script.ScriptEngineManager;
|
||||
import javax.script.ScriptException;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@ -99,7 +96,7 @@ public class MovementAuthority {
|
||||
case CLOSED_STAND:{
|
||||
Section section = baseSection;
|
||||
SectionPosition stopPosition = new SectionPosition(section, section.getStopPointByDirection(right));
|
||||
return CalculateService.calculateNextPositionByStartAndLen(stopPosition, !right, 180);
|
||||
return CalculateService.calculateNextPositionByStartAndLen(stopPosition, !right, 180, false);
|
||||
}
|
||||
case CLOSED_SIGNAL: {
|
||||
Signal signal = (Signal) this.device;
|
||||
@ -117,10 +114,10 @@ public class MovementAuthority {
|
||||
section = section.getParent();
|
||||
SectionPosition sectionPosition = new SectionPosition(section, offset);
|
||||
if (section.isStandTrack() && section.getStandList().get(0).isTrainParking()) {
|
||||
return CalculateService.calculateNextPositionByStartAndLen(sectionPosition, !right, 10);
|
||||
return CalculateService.calculateNextPositionByStartAndLen(sectionPosition, !right, 10, false);
|
||||
} else {
|
||||
return CalculateService.calculateNextPositionByStartAndLen(sectionPosition,
|
||||
!right, 2 * SimulationConstants.TRAIN_SAFE_DISTANCE);
|
||||
!right, 2 * SimulationConstants.TRAIN_SAFE_DISTANCE, false);
|
||||
}
|
||||
|
||||
// VirtualRealityTrain train = (VirtualRealityTrain) this.device;
|
||||
@ -154,7 +151,7 @@ public class MovementAuthority {
|
||||
Section section = this.baseSection;
|
||||
float offset = right ? section.getLen() : 0;
|
||||
SectionPosition stopPosition = new SectionPosition(section, offset);
|
||||
return CalculateService.calculateNextPositionByStartAndLen(stopPosition, !right, 100);
|
||||
return CalculateService.calculateNextPositionByStartAndLen(stopPosition, !right, 100, false);
|
||||
}
|
||||
case UNLOCK_SECTION:
|
||||
case FAULT_SECTION:
|
||||
@ -197,7 +194,7 @@ public class MovementAuthority {
|
||||
if (Objects.isNull(this.endPosition)) {
|
||||
SectionPosition sectionPosition = this.computeEndPosition(right);
|
||||
if (!sectionPosition.isAvailable()) {
|
||||
sectionPosition = CalculateService.getAvailableSectionPositionOf(sectionPosition);
|
||||
sectionPosition = CalculateService.getAvailableSectionPositionOf(sectionPosition, false);
|
||||
}
|
||||
this.endPosition = sectionPosition;
|
||||
}
|
||||
|
@ -120,9 +120,9 @@ public class SectionPosition {
|
||||
public boolean isWithinParkingRange(boolean right) {
|
||||
SectionPosition targetPosition = new SectionPosition(this.section, this.section.getStopPointByDirection(right));
|
||||
SectionPosition max = CalculateService.calculateNextPositionByStartAndLen(targetPosition,
|
||||
right, SimulationConstants.PARK_POINT_MAX_OFFSET);
|
||||
right, SimulationConstants.PARK_POINT_MAX_OFFSET, false);
|
||||
SectionPosition min = CalculateService.calculateNextPositionByStartAndLen(targetPosition,
|
||||
!right, SimulationConstants.PARK_POINT_MAX_OFFSET);
|
||||
!right, SimulationConstants.PARK_POINT_MAX_OFFSET, false);
|
||||
return this.isAheadOf(min, right) && max.isAheadOf(this, right);
|
||||
}
|
||||
}
|
||||
|
@ -365,6 +365,9 @@ public class TrainInfo extends MapElement {
|
||||
|
||||
public void init(Section section, String dn, String sn, String tn, String cn) {
|
||||
this.section = section.getCode();
|
||||
Section ps = section.findPhysicalSection();
|
||||
if (ps != null)
|
||||
this.physicalSection = ps.getCode();
|
||||
this.destinationCode = dn;
|
||||
this.serviceNumber = sn;
|
||||
this.tripNumber = tn;
|
||||
@ -426,6 +429,7 @@ public class TrainInfo extends MapElement {
|
||||
public boolean isHeadCodeTrain() {
|
||||
return Objects.equals(this.type, TrainType.HEAD);
|
||||
}
|
||||
|
||||
public boolean isManualTrain() {
|
||||
return TrainType.MANUAL.equals(this.type);
|
||||
}
|
||||
|
@ -63,6 +63,24 @@ public class VirtualRealityScreenDoor extends ControllableVrDevice<VirtualRealit
|
||||
this.fault = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean checkConditionBeforeControl(Operation command) {
|
||||
//已是关门到位状态,发送关门指令依然会进入转换中状态,导致门又开启,遂加此限制
|
||||
switch (command) {
|
||||
case K:{
|
||||
if (this.isOpen2End())
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case G: {
|
||||
if (this.isLockAndClose())
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doTurn() {
|
||||
this.setClose(false);
|
||||
|
@ -73,13 +73,6 @@ public class VirtualRealitySectionAxleCounter extends VirtualRealityDevice {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断计轴器的占用情况
|
||||
*/
|
||||
private void judgeOccupy() {
|
||||
this.occupy = leftCount != 0 || rightCount != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 列车车头进入该计轴区段
|
||||
* @param trainRight 列车运行方向
|
||||
|
@ -377,7 +377,7 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
|
||||
private boolean backUp;
|
||||
|
||||
/**
|
||||
* 关门后的延迟发车时间(单位s)
|
||||
* 关门后的延迟发车时间(单位ms)
|
||||
*/
|
||||
private int delayTime = 0;
|
||||
|
||||
@ -766,7 +766,7 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
|
||||
}
|
||||
|
||||
public SectionPosition calculateTailPosition() {
|
||||
this.tailPosition = CalculateService.calculateNextPositionByStartAndLen(this.headPosition, !right, this.getLen());
|
||||
this.tailPosition = CalculateService.calculateNextPositionByStartAndLen(this.headPosition, !right, this.getLen(), true);
|
||||
return this.tailPosition;
|
||||
}
|
||||
|
||||
@ -825,9 +825,9 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
|
||||
SectionPosition headPosition = this.headPosition;
|
||||
boolean right = this.right;
|
||||
SectionPosition max = CalculateService.calculateNextPositionByStartAndLen(targetPosition,
|
||||
right, SimulationConstants.PARK_POINT_MAX_OFFSET);
|
||||
right, SimulationConstants.PARK_POINT_MAX_OFFSET, true);
|
||||
SectionPosition min = CalculateService.calculateNextPositionByStartAndLen(targetPosition,
|
||||
!right, SimulationConstants.PARK_POINT_MAX_OFFSET);
|
||||
!right, SimulationConstants.PARK_POINT_MAX_OFFSET, true);
|
||||
return headPosition.isAheadOf(min, right) && max.isAheadOf(headPosition, right);
|
||||
}
|
||||
|
||||
@ -1132,6 +1132,23 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
|
||||
return isCBTC() && VirtualRealityTrain.DoorMode.AA.equals(doorMode);
|
||||
}
|
||||
|
||||
public void initAsAM_I() {
|
||||
this.setCommunication(false);
|
||||
this.setPreselectionMode(PreselectionMode.AM_I);
|
||||
this.setTempPreselectionMode(this.preselectionMode);
|
||||
this.setDriveMode(DriveMode.AM);
|
||||
this.setRunLevel(RunLevel.ITC);
|
||||
}
|
||||
|
||||
public void initAsRM() {
|
||||
this.setCommunication(false);
|
||||
this.setPreselectionMode(PreselectionMode.RM);
|
||||
this.setTempPreselectionMode(this.preselectionMode);
|
||||
this.setDriveMode(DriveMode.RM);
|
||||
this.setRunLevel(RunLevel.IL);
|
||||
this.setAtoOn(false);
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public static class Door extends ControllableVrDevice<Door.Operation> {
|
||||
|
@ -36,7 +36,7 @@ public class SimulationRealDeviceConnectManager {
|
||||
|
||||
public void connectDevice(Simulation simulation, String deviceCode, Long projectDeviceId) {
|
||||
RealDeviceConfig realDevice = simulation.getRealDeviceById(projectDeviceId);
|
||||
MapElement mapElement = simulation.getRepository().getByCode(deviceCode);
|
||||
MapElement mapElement = simulation.getRepository().findByCode(deviceCode);
|
||||
boolean typeEqual = false;
|
||||
switch (realDevice.getProjectDevice().getType()) {
|
||||
case SWITCH:{
|
||||
@ -102,6 +102,7 @@ public class SimulationRealDeviceConnectManager {
|
||||
typeEqual = true;
|
||||
realDevice.connect(vrDevice);
|
||||
}
|
||||
vrDevice.updateRealDevice(realDevice);
|
||||
break;
|
||||
}
|
||||
case IBP:{
|
||||
@ -111,7 +112,18 @@ public class SimulationRealDeviceConnectManager {
|
||||
}
|
||||
if (MapElement.DeviceType.IBP.equals(mapElement.getDeviceType())) {
|
||||
typeEqual = true;
|
||||
realDevice.connect((VirtualRealityIbp) mapElement);
|
||||
VirtualRealityIbp vrIbp = (VirtualRealityIbp) mapElement;
|
||||
realDevice.connect(vrIbp);
|
||||
vrIbp.updateRealDevice(realDevice);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TRAIN:{
|
||||
VirtualRealityDevice vrDevice = simulation.getRepository().getVRByCode(deviceCode);
|
||||
if (MapElement.DeviceType.TRAIN.equals(vrDevice.getDeviceType())) {
|
||||
typeEqual = true;
|
||||
realDevice.connect(vrDevice);
|
||||
vrDevice.updateRealDevice(realDevice);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1,58 +0,0 @@
|
||||
package club.joylink.rtss.simulation.cbtc.device.real.udp.Sr;
|
||||
|
||||
import club.joylink.rtss.constants.ProjectDeviceType;
|
||||
import club.joylink.rtss.simulation.cbtc.Simulation;
|
||||
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealitySectionAxleCounter;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.device.RealDeviceConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.UDPClientConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.UDPLowConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.UDPRealDeviceService;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class SrSectionServiceImpl implements UDPRealDeviceService {
|
||||
@Override
|
||||
public boolean isMatch(RealDeviceConfig realDevice) {
|
||||
return realDevice instanceof UDPClientConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void control(Simulation simulation, UDPLowConfig udpLowConfig, RealDeviceConfig realDevice) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Simulation simulation, UDPLowConfig udpConfig, RealDeviceConfig realDevice) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(Simulation simulation, ByteBuf msg) {
|
||||
byte[] data = new byte[msg.readableBytes()];
|
||||
if (data.length < 4)
|
||||
return;
|
||||
msg.readBytes(data);
|
||||
if (Byte.toUnsignedInt(data[1]) != 137)
|
||||
return;
|
||||
Map<String, VirtualRealitySectionAxleCounter> map = simulation.queryAllRealDevice(ProjectDeviceType.SECTION).stream()
|
||||
.map(config -> (SrSectionConfig) config)
|
||||
.collect(Collectors.toMap(config -> config.getConfigVO().getSandboxCode(),
|
||||
config -> (VirtualRealitySectionAxleCounter) config.getMapElement()));
|
||||
for (int i = 3, dataLength = data.length; i < dataLength; i+=2) {
|
||||
int code = Byte.toUnsignedInt(data[i - 1]);
|
||||
VirtualRealitySectionAxleCounter axle = map.get(String.valueOf(code));
|
||||
if (axle != null) {
|
||||
int n = Byte.toUnsignedInt(data[i]);
|
||||
if (n == 170) {
|
||||
axle.setOccupy(true);
|
||||
} else if (n == 85) {
|
||||
axle.setOccupy(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package club.joylink.rtss.simulation.cbtc.device.real.udp.sr;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
public class SrTrainControlParam {
|
||||
@NotBlank(message = "车组号不能为空")
|
||||
private String groupNumber;
|
||||
|
||||
@NotNull(message = "方向不能为null")
|
||||
private Boolean right;
|
||||
|
||||
@NotNull(message = "速度不能为null")
|
||||
private Integer speed;
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package club.joylink.rtss.simulation.cbtc.device.real.udp.sr;
|
||||
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.sr.service.SrTrainServiceImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/sr")
|
||||
public class SrTrainController {
|
||||
@Autowired
|
||||
private SrTrainServiceImpl srTrainService;
|
||||
|
||||
// @PutMapping("/{simulationId}/control")
|
||||
// public void control(@PathVariable String simulationId, @RequestBody @Validated SrTrainControlParam controlParam) {
|
||||
// srTrainService.control(simulationId, controlParam.getGroupNumber(), controlParam.getRight(), controlParam.getSpeed());
|
||||
// }
|
||||
|
||||
@PutMapping("/{simulationId}/control")
|
||||
public void control(@PathVariable String simulationId, String groupNumber, boolean right, int speed) {
|
||||
srTrainService.controlTrain(simulationId, groupNumber, right, speed);
|
||||
}
|
||||
}
|
@ -1,10 +1,11 @@
|
||||
package club.joylink.rtss.simulation.cbtc.device.real.udp.Sr;
|
||||
package club.joylink.rtss.simulation.cbtc.device.real.udp.sr.config;
|
||||
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.device.RealDeviceConfig;
|
||||
import club.joylink.rtss.util.JsonUtils;
|
||||
import club.joylink.rtss.vo.client.project.ProjectDeviceVO;
|
||||
import club.joylink.rtss.vo.client.project.sr.SrSectionConfigVO;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@ -12,6 +13,12 @@ import java.util.Objects;
|
||||
public class SrSectionConfig extends RealDeviceConfig {
|
||||
private SrSectionConfigVO configVO;
|
||||
|
||||
/**
|
||||
* 连续无占用次数
|
||||
*/
|
||||
@Setter
|
||||
private int timesOfRelease;
|
||||
|
||||
public SrSectionConfig(ProjectDeviceVO projectDevice) {
|
||||
super(projectDevice);
|
||||
if (Objects.nonNull(projectDevice.getConfig())) {
|
@ -1,10 +1,13 @@
|
||||
package club.joylink.rtss.simulation.cbtc.device.real.udp.Sr;
|
||||
package club.joylink.rtss.simulation.cbtc.device.real.udp.sr.config;
|
||||
|
||||
import club.joylink.rtss.simulation.cbtc.constant.SignalAspect;
|
||||
import club.joylink.rtss.simulation.cbtc.data.map.Signal;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.device.RealDeviceConfig;
|
||||
import club.joylink.rtss.util.JsonUtils;
|
||||
import club.joylink.rtss.vo.client.project.ProjectDeviceVO;
|
||||
import club.joylink.rtss.vo.client.project.sr.SrSignalConfigVO;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@ -12,6 +15,9 @@ import java.util.Objects;
|
||||
public class SrSignalConfig extends RealDeviceConfig {
|
||||
private SrSignalConfigVO configVO;
|
||||
|
||||
@Setter
|
||||
private SignalAspect aspect;
|
||||
|
||||
public SrSignalConfig(ProjectDeviceVO projectDevice) {
|
||||
super(projectDevice);
|
||||
if (Objects.nonNull(projectDevice.getConfig())) {
|
@ -1,10 +1,12 @@
|
||||
package club.joylink.rtss.simulation.cbtc.device.real.udp.Sr;
|
||||
package club.joylink.rtss.simulation.cbtc.device.real.udp.sr.config;
|
||||
|
||||
import club.joylink.rtss.simulation.cbtc.constant.SwitchIndication;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.device.RealDeviceConfig;
|
||||
import club.joylink.rtss.util.JsonUtils;
|
||||
import club.joylink.rtss.vo.client.project.ProjectDeviceVO;
|
||||
import club.joylink.rtss.vo.client.project.sr.SrSwitchConfigVO;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@ -12,6 +14,8 @@ import java.util.Objects;
|
||||
public class SrSwitchConfig extends RealDeviceConfig {
|
||||
private SrSwitchConfigVO configVO;
|
||||
|
||||
@Setter
|
||||
private SwitchIndication p;
|
||||
public SrSwitchConfig(ProjectDeviceVO projectDevice) {
|
||||
super(projectDevice);
|
||||
if (Objects.nonNull(projectDevice.getConfig())) {
|
@ -0,0 +1,51 @@
|
||||
package club.joylink.rtss.simulation.cbtc.device.real.udp.sr.config;
|
||||
|
||||
import club.joylink.rtss.simulation.cbtc.data.map.Section;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.device.RealDeviceConfig;
|
||||
import club.joylink.rtss.util.JsonUtils;
|
||||
import club.joylink.rtss.vo.client.project.ProjectDeviceVO;
|
||||
import club.joylink.rtss.vo.client.project.sr.SrSwitchConfigVO;
|
||||
import club.joylink.rtss.vo.client.project.sr.SrTrainConfigVO;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.apache.ibatis.annotations.Update;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Objects;
|
||||
|
||||
@Getter
|
||||
public class SrTrainConfig extends RealDeviceConfig {
|
||||
private SrTrainConfigVO configVO;
|
||||
|
||||
@Setter
|
||||
private Integer gear;
|
||||
|
||||
/**
|
||||
* 列车需要在这个轨道停车
|
||||
*/
|
||||
private Section headSection;
|
||||
|
||||
/**
|
||||
* 列车在headSection停车的时间
|
||||
*/
|
||||
@Setter
|
||||
private LocalDateTime timeOfStop;
|
||||
|
||||
/**
|
||||
* 人为驾驶的档位
|
||||
*/
|
||||
@Setter
|
||||
private Integer manualGear;
|
||||
|
||||
public void updateHeadSection(Section headSection) {
|
||||
this.headSection = headSection;
|
||||
this.timeOfStop = null;
|
||||
}
|
||||
|
||||
public SrTrainConfig(ProjectDeviceVO projectDevice) {
|
||||
super(projectDevice);
|
||||
if (Objects.nonNull(projectDevice.getConfig())) {
|
||||
this.configVO = JsonUtils.read(projectDevice.getConfig(), SrTrainConfigVO.class);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,192 @@
|
||||
package club.joylink.rtss.simulation.cbtc.device.real.udp.sr.service;
|
||||
|
||||
import club.joylink.rtss.constants.ProjectDeviceType;
|
||||
import club.joylink.rtss.simulation.cbtc.ATP.ground.MaService;
|
||||
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.support.SectionPosition;
|
||||
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealitySectionAxleCounter;
|
||||
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityTrain;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.device.RealDeviceConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.UDPClientConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.UDPLowConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.UDPRealDeviceService;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.sr.config.SrSectionConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.sr.config.SrTrainConfig;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class SrSectionServiceImpl implements UDPRealDeviceService {
|
||||
@Autowired
|
||||
private SrTrainServiceImpl srTrainService;
|
||||
|
||||
@Autowired
|
||||
private MaService maService;
|
||||
|
||||
@Override
|
||||
public boolean isMatch(RealDeviceConfig realDevice) {
|
||||
return realDevice instanceof UDPClientConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(Simulation simulation, UDPLowConfig udpLowConfig, RealDeviceConfig realDevice) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Simulation simulation, UDPLowConfig udpLowConfig, RealDeviceConfig realDevice) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(Simulation simulation, ByteBuf msg) {
|
||||
//检查数据
|
||||
byte[] data = new byte[msg.readableBytes()];
|
||||
if (data.length < 4)
|
||||
return;
|
||||
msg.readBytes(data);
|
||||
if (Byte.toUnsignedInt(data[1]) != 137) {
|
||||
return;
|
||||
}
|
||||
//处理数据
|
||||
Map<String, SrSectionConfig> configMap = simulation.queryAllRealDevice(ProjectDeviceType.SECTION).stream()
|
||||
.map(config -> (SrSectionConfig) config)
|
||||
.collect(Collectors.toMap(config -> config.getConfigVO().getSandboxCode(), Function.identity()));
|
||||
for (int i = 3, dataLength = data.length; i < dataLength; i += 2) {
|
||||
int code = Byte.toUnsignedInt(data[i - 1]);
|
||||
String key = String.valueOf(code);
|
||||
SrSectionConfig config = configMap.get(key);
|
||||
if (config == null)
|
||||
continue;
|
||||
VirtualRealitySectionAxleCounter axle = (VirtualRealitySectionAxleCounter) config.getMapElement();
|
||||
if (axle != null) {
|
||||
int n = Byte.toUnsignedInt(data[i]);
|
||||
if (n == 170) {
|
||||
updateTrainPosition(simulation, axle);
|
||||
config.setTimesOfRelease(0);
|
||||
axle.setOccupy(true);
|
||||
} else if (n == 85) {
|
||||
config.setTimesOfRelease(config.getTimesOfRelease() + 1);
|
||||
if (config.getTimesOfRelease() > 3) { //连续4次该计轴都是无占用状态,才视为确实无占用
|
||||
config.setTimesOfRelease(0);
|
||||
axle.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//设置停车信息
|
||||
stop(simulation);
|
||||
}
|
||||
|
||||
/**
|
||||
* 列车到达特殊轨道,设置延迟停车时间
|
||||
*/
|
||||
private void stop(Simulation simulation) {
|
||||
for (VirtualRealityTrain train : simulation.getRepository().getOnlineTrainList()) {
|
||||
Section headSection = train.getHeadPosition().getSection();
|
||||
SrTrainConfig config = (SrTrainConfig) train.getRealDevice();
|
||||
if (!Objects.equals(headSection, config.getHeadSection())) //列车无需在该站台停车
|
||||
continue;
|
||||
if (config.getTimeOfStop() != null) //已经设置过停车时间
|
||||
continue;
|
||||
if (!headSection.isFunctionTrack())
|
||||
continue;
|
||||
VirtualRealitySectionAxleCounter headAxle = headSection.findAxle();
|
||||
if (headAxle == null)
|
||||
continue;
|
||||
SrSectionConfig sectionConfig = (SrSectionConfig) headAxle.getRealDevice();
|
||||
//设置延时停车时间
|
||||
long m = 1000000000;
|
||||
long nanos;
|
||||
if (sectionConfig.getConfigVO().getHeadDelayTime() != null) {
|
||||
nanos = (long) (sectionConfig.getConfigVO().getHeadDelayTime() * m);
|
||||
config.setTimeOfStop(LocalDateTime.now().plusNanos(nanos));
|
||||
continue;
|
||||
}
|
||||
//以前一个区段无占用作为停车标志的区段
|
||||
boolean right = train.isRight();
|
||||
Section behindSection = headSection.getNextRunningSectionOf(!right);
|
||||
if (behindSection == null)
|
||||
continue;
|
||||
VirtualRealitySectionAxleCounter behindAxle = behindSection.findAxle();
|
||||
if (behindAxle == null)
|
||||
continue;
|
||||
if (!behindAxle.isOccupy()) { //车头后方区段所属计轴无占用状态
|
||||
nanos = 0;
|
||||
if (sectionConfig.getConfigVO().getTailDelayTime() != null) {
|
||||
nanos = (long) (sectionConfig.getConfigVO().getTailDelayTime() * m);
|
||||
}
|
||||
if (nanos == 0) {
|
||||
train.setHeadPosition(headSection.buildStopPointPosition(right));
|
||||
} else {
|
||||
config.setTimeOfStop(LocalDateTime.now().plusNanos(nanos));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateTrainPosition(Simulation simulation, VirtualRealitySectionAxleCounter axle) {
|
||||
for (Section section : simulation.getRepository().getAxleSectionList()) {
|
||||
if (section.getVirtualAxleCounter().equals(axle)) {
|
||||
List<Section> pSection;
|
||||
if (section.isPhysical()) {
|
||||
pSection = Collections.singletonList(section);
|
||||
} else if (section.isSwitchAxleCounterSection()) {
|
||||
pSection = section.findConnectedSections();
|
||||
} else {
|
||||
pSection = Collections.emptyList();
|
||||
}
|
||||
for (Section sec : pSection) {
|
||||
check4UpdateHeadPosition(simulation, sec, false);
|
||||
check4UpdateHeadPosition(simulation, sec, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否有right向的列车可以更新车头位置
|
||||
*/
|
||||
private void check4UpdateHeadPosition(Simulation simulation, Section occupiedSection, boolean right) {
|
||||
Section section = occupiedSection.getNextRunningSectionOf(!right); //找反向的区段
|
||||
if (section != null) {
|
||||
for (VirtualRealityTrain train : simulation.getRepository().getOnlineTrainList()) {
|
||||
Section headSection = train.getHeadPosition().getSection();
|
||||
boolean trainRight = train.isRight();
|
||||
if (trainRight == right && section.equals(headSection)) { //列车到达occupiedSection
|
||||
//判断更新ITC ma
|
||||
if (headSection.getSignalOf(trainRight) != null) {
|
||||
maService.calculateAndUpdateItcMa(simulation, train);
|
||||
}
|
||||
//更新位置
|
||||
SectionPosition headPosition;
|
||||
SectionPosition stopPointPosition;
|
||||
if (occupiedSection.isFunctionTrack()) {
|
||||
stopPointPosition = occupiedSection.buildStopPointPosition(right);
|
||||
headPosition = CalculateService.calculateNextPositionByStartAndLen(stopPointPosition, !right, 1, true);
|
||||
} else {
|
||||
stopPointPosition = new SectionPosition(occupiedSection, occupiedSection.getEndOffsetByDirection(right));
|
||||
headPosition = CalculateService.calculateNextPositionByStartAndLen(stopPointPosition, !right, 3, true);
|
||||
}
|
||||
train.setHeadPosition(headPosition); //更新位置
|
||||
if (occupiedSection.isFunctionTrack()) { //功能轨可能需要停车
|
||||
SrTrainConfig config = (SrTrainConfig) train.getRealDevice();
|
||||
config.updateHeadSection(occupiedSection);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package club.joylink.rtss.simulation.cbtc.device.real.udp.Sr;
|
||||
package club.joylink.rtss.simulation.cbtc.device.real.udp.sr.service;
|
||||
|
||||
import club.joylink.rtss.simulation.cbtc.Simulation;
|
||||
import club.joylink.rtss.simulation.cbtc.constant.SignalAspect;
|
||||
@ -8,6 +8,7 @@ import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.device.RealDevice
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.UDPClient;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.UDPLowConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.UDPRealDeviceService;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.sr.config.SrSignalConfig;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
@ -25,7 +26,7 @@ public class SrSignalServiceImpl implements UDPRealDeviceService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void control(Simulation simulation, UDPLowConfig udpLowConfig, RealDeviceConfig realDevice) {
|
||||
public void run(Simulation simulation, UDPLowConfig udpLowConfig, RealDeviceConfig realDevice) {
|
||||
SrSignalConfig config = (SrSignalConfig) realDevice;
|
||||
//控制vr设备
|
||||
VirtualRealitySignal vrSignal = (VirtualRealitySignal) realDevice.getMapElement();
|
||||
@ -34,12 +35,12 @@ public class SrSignalServiceImpl implements UDPRealDeviceService {
|
||||
if (Objects.equals(aspect, command)) {
|
||||
return;
|
||||
}
|
||||
if (vrSignal.getRemain() > 0) {
|
||||
if (vrSignal.isTurning()) {
|
||||
vrSignal.turning(SimulationConstants.VRD_LOOP_RATE);
|
||||
}
|
||||
//控制沙盘设备
|
||||
aspect = vrSignal.getAspect();
|
||||
if (aspect == null || udpLowConfig == null) {
|
||||
if (aspect == null || udpLowConfig == null || Objects.equals(aspect, config.getAspect())) {
|
||||
return;
|
||||
}
|
||||
byte[] data = buildData(aspect, config);
|
||||
@ -49,11 +50,11 @@ public class SrSignalServiceImpl implements UDPRealDeviceService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Simulation simulation, UDPLowConfig udpConfig, RealDeviceConfig realDevice) {
|
||||
SrSignalConfig config = (SrSignalConfig) realDevice;
|
||||
VirtualRealitySignal vrSignal = (VirtualRealitySignal) config.getMapElement();
|
||||
byte[] data = buildData(vrSignal.getAspect(), config);
|
||||
udpClient.write(udpConfig.getAddr(), data);
|
||||
public void init(Simulation simulation, UDPLowConfig udpLowConfig, RealDeviceConfig realDevice) {
|
||||
// SrSignalConfig config = (SrSignalConfig) realDevice;
|
||||
// VirtualRealitySignal vrSignal = (VirtualRealitySignal) config.getMapElement();
|
||||
// byte[] data = buildData(vrSignal.getAspect(), config);
|
||||
// udpClient.write(udpLowConfig.getAddr(), data);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -64,6 +65,7 @@ public class SrSignalServiceImpl implements UDPRealDeviceService {
|
||||
private byte[] buildData(SignalAspect aspect, SrSignalConfig config) {
|
||||
if (aspect == null)
|
||||
return null;
|
||||
config.setAspect(aspect);
|
||||
byte[] data = new byte[5];
|
||||
data[1] = (byte) 203;
|
||||
data[2] = (byte) Integer.parseInt(config.getConfigVO().getSandboxCode());
|
@ -1,4 +1,4 @@
|
||||
package club.joylink.rtss.simulation.cbtc.device.real.udp.Sr;
|
||||
package club.joylink.rtss.simulation.cbtc.device.real.udp.sr.service;
|
||||
|
||||
import club.joylink.rtss.simulation.cbtc.Simulation;
|
||||
import club.joylink.rtss.simulation.cbtc.constant.SimulationConstants;
|
||||
@ -8,10 +8,13 @@ import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.device.RealDevice
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.UDPClient;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.UDPLowConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.UDPRealDeviceService;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.sr.config.SrSwitchConfig;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@Service
|
||||
public class SrSwitchServiceImpl implements UDPRealDeviceService {
|
||||
@Autowired
|
||||
@ -23,16 +26,16 @@ public class SrSwitchServiceImpl implements UDPRealDeviceService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void control(Simulation simulation, UDPLowConfig udpLowConfig, RealDeviceConfig realDevice) {
|
||||
public void run(Simulation simulation, UDPLowConfig udpLowConfig, RealDeviceConfig realDevice) {
|
||||
SrSwitchConfig config = (SrSwitchConfig) realDevice;
|
||||
//控制vr设备
|
||||
VirtualRealitySwitch vrSwitch = (VirtualRealitySwitch) realDevice.getMapElement();
|
||||
if (vrSwitch.getRemain() > 0) {
|
||||
if (vrSwitch.isTurning()) {
|
||||
vrSwitch.turning(SimulationConstants.VRD_LOOP_RATE);
|
||||
}
|
||||
//控制沙盘设备
|
||||
SwitchIndication p = vrSwitch.getP();
|
||||
if (p == null || udpLowConfig == null) {
|
||||
if (p == null || udpLowConfig == null || Objects.equals(p, config.getP())) {
|
||||
return;
|
||||
}
|
||||
byte[] data = buildData(p, config);
|
||||
@ -42,8 +45,20 @@ public class SrSwitchServiceImpl implements UDPRealDeviceService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Simulation simulation, UDPLowConfig udpConfig, RealDeviceConfig realDevice) {
|
||||
|
||||
public void init(Simulation simulation, UDPLowConfig udpLowConfig, RealDeviceConfig realDevice) {
|
||||
// SrSwitchConfig config = (SrSwitchConfig) realDevice;
|
||||
// //控制vr设备
|
||||
// VirtualRealitySwitch vrSwitch = (VirtualRealitySwitch) realDevice.getMapElement();
|
||||
// if (vrSwitch.getRemain() > 0) {
|
||||
// vrSwitch.turning(SimulationConstants.VRD_LOOP_RATE);
|
||||
// }
|
||||
// //控制沙盘设备
|
||||
// SwitchIndication p = vrSwitch.getP();
|
||||
// if (p == null || udpLowConfig == null) {
|
||||
// return;
|
||||
// }
|
||||
// byte[] data = buildData(p, config);
|
||||
// udpClient.write(udpLowConfig.getAddr(), data);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -54,6 +69,7 @@ public class SrSwitchServiceImpl implements UDPRealDeviceService {
|
||||
private byte[] buildData(SwitchIndication p, SrSwitchConfig config) {
|
||||
if (p == null)
|
||||
return null;
|
||||
config.setP(p);
|
||||
byte[] data = new byte[4];
|
||||
data[1] = (byte) 208;
|
||||
data[2] = (byte) Integer.parseInt(config.getConfigVO().getSandboxCode());
|
@ -0,0 +1,296 @@
|
||||
package club.joylink.rtss.simulation.cbtc.device.real.udp.sr.service;
|
||||
|
||||
import club.joylink.rtss.constants.ProjectDeviceType;
|
||||
import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
|
||||
import club.joylink.rtss.simulation.cbtc.ATS.operation.AtsOperationDispatcher;
|
||||
import club.joylink.rtss.simulation.cbtc.ATS.operation.Operation;
|
||||
import club.joylink.rtss.simulation.cbtc.ATS.service.AtsTrainLoadService;
|
||||
import club.joylink.rtss.simulation.cbtc.GroupSimulationService;
|
||||
import club.joylink.rtss.simulation.cbtc.Simulation;
|
||||
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.Section;
|
||||
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.vo.TrainInfo;
|
||||
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityTrain;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.device.RealDeviceConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.UDPClient;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.UDPLowConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.UDPRealDeviceService;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.sr.config.SrTrainConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.member.SimulationMember;
|
||||
import club.joylink.rtss.simulation.cbtc.onboard.ATO.SpeedCurve;
|
||||
import club.joylink.rtss.simulation.cbtc.onboard.ATP.ATPService;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class SrTrainServiceImpl implements UDPRealDeviceService {
|
||||
@Autowired
|
||||
private UDPClient udpClient;
|
||||
|
||||
@Autowired
|
||||
private ATPService atpService;
|
||||
|
||||
@Autowired
|
||||
private AtsOperationDispatcher atsOperationDispatcher;
|
||||
|
||||
@Autowired
|
||||
private GroupSimulationService groupSimulationService;
|
||||
|
||||
@Autowired
|
||||
private AtsTrainLoadService atsTrainLoadService;
|
||||
|
||||
@Override
|
||||
public boolean isMatch(RealDeviceConfig realDevice) {
|
||||
return realDevice instanceof SrTrainConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(Simulation simulation, UDPLowConfig udpLowConfig, RealDeviceConfig realDevice) {
|
||||
SrTrainConfig config = (SrTrainConfig) realDevice;
|
||||
//控制vr设备
|
||||
VirtualRealityTrain train = (VirtualRealityTrain) config.getMapElement();
|
||||
SimulationDataRepository repository = simulation.getRepository();
|
||||
String groupNumber = train.getGroupNumber();
|
||||
if (repository.isVrTrainOnline(groupNumber)) {
|
||||
removeVrTrainIfNotSupervised(repository, groupNumber);
|
||||
if (train.isEB()) {
|
||||
train.setSpeed(0);
|
||||
} else {
|
||||
if (train.getRobotTargetPosition() != null || train.isAMMode()) {
|
||||
config.setManualGear(null);
|
||||
}
|
||||
if (config.getManualGear() == null) {
|
||||
change2RMWhenStopAtPlanEnd(simulation, train);
|
||||
trainRunning(simulation, train, config);
|
||||
}
|
||||
if (train.getDelayTime() > 3000) {
|
||||
train.setDelayTime(3000);
|
||||
}
|
||||
}
|
||||
//控制沙盘设备
|
||||
byte[] data = buildData(train, config);
|
||||
udpClient.write(udpLowConfig.getAddr(), data);
|
||||
} else {
|
||||
addVrTrainIfSupervised(simulation, repository, groupNumber);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果有监控,添加一个vrTrain
|
||||
*/
|
||||
private void addVrTrainIfSupervised(Simulation simulation, SimulationDataRepository repository, String groupNumber) {
|
||||
TrainInfo trainInfo = repository.findSupervisedTrainByGroup(groupNumber);
|
||||
if (trainInfo != null) {
|
||||
Section section = repository.getByCode(trainInfo.getSection(), Section.class);
|
||||
if (section.isSwitchAxleCounterSection()) {
|
||||
section = section.getLogicList().get(0).getRelSwitch().getA();
|
||||
}
|
||||
atsTrainLoadService.loadSpareTrain(simulation, groupNumber, section.getCode(), false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除vrTrain,如果没有被监控
|
||||
*/
|
||||
private void removeVrTrainIfNotSupervised(SimulationDataRepository repository, String groupNumber) {
|
||||
TrainInfo trainInfo = repository.findSupervisedTrainByGroup(groupNumber);
|
||||
if (trainInfo == null) {
|
||||
repository.deleteOnlineTrain(groupNumber);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 当到达计划终点时,将列车驾驶模式转为RM
|
||||
*/
|
||||
private void change2RMWhenStopAtPlanEnd(Simulation simulation, VirtualRealityTrain train) {
|
||||
if (!train.isStop())
|
||||
return;
|
||||
if (!train.getHeadPosition().getSection().isTransferTrack()) //不是转换轨
|
||||
return;
|
||||
SimulationDataRepository repository = simulation.getRepository();
|
||||
String groupNumber = train.getGroupNumber();
|
||||
TrainInfo trainInfo = repository.getSupervisedTrainByGroup(groupNumber);
|
||||
if (!trainInfo.isPlanTrain())
|
||||
return;
|
||||
TripPlan tripPlan = repository.getTripPlan(trainInfo.getServiceNumber(), trainInfo.getTripNumber());
|
||||
if (!Objects.equals(train.getHeadPosition().getSection(), tripPlan.getEndSection())) //不是计划最后一个区段
|
||||
return;
|
||||
TripPlan nextTripPlan = repository.queryServiceNextTripPlan(trainInfo.getServiceNumber(), trainInfo.getTripNumber());
|
||||
if (nextTripPlan != null)
|
||||
return;
|
||||
//无下一计划(要回车辆段)
|
||||
VirtualRealityTrain.PreselectionMode preselectionMode = VirtualRealityTrain.PreselectionMode.RM;
|
||||
VirtualRealityTrain.PreselectionMode trainMode = train.getPreselectionMode();
|
||||
if (trainMode == preselectionMode) //已是RM
|
||||
return;
|
||||
VirtualRealityTrain.PreselectionMode tempMode = train.getTempPreselectionMode();
|
||||
SimulationMember driver = simulation.getSimulationMembersByDevice(train).get(0);
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
String operation;
|
||||
params.put("groupNumber", groupNumber);
|
||||
if (tempMode != preselectionMode) { //临时级别不对
|
||||
if (preselectionMode.isHigherThan(tempMode)) {
|
||||
operation = Operation.Type.Driver_Preselection_Mode_Up.name();
|
||||
} else {
|
||||
operation = Operation.Type.Driver_Preselection_Mode_Down.name();
|
||||
}
|
||||
} else {
|
||||
operation = Operation.Type.Driver_Confirm.name();
|
||||
}
|
||||
atsOperationDispatcher.execute(simulation, driver, operation, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Simulation simulation, UDPLowConfig udpLowConfig, RealDeviceConfig realDevice) {
|
||||
SrTrainConfig config = (SrTrainConfig) realDevice;
|
||||
//控制vr设备
|
||||
VirtualRealityTrain train = (VirtualRealityTrain) config.getMapElement();
|
||||
//控制沙盘设备
|
||||
byte[] data = buildData(train, config);
|
||||
udpClient.write(udpLowConfig.getAddr(), data);
|
||||
//清除状态
|
||||
config.updateHeadSection(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(Simulation simulation, ByteBuf msg) {
|
||||
|
||||
}
|
||||
|
||||
private void trainRunning(Simulation simulation, VirtualRealityTrain train, SrTrainConfig config) {
|
||||
//判断到停车时间,将列车位置更新到停车点
|
||||
boolean right = train.isRight();
|
||||
SectionPosition headPosition = train.getHeadPosition();
|
||||
Section headSection = headPosition.getSection();
|
||||
if (Objects.equals(headSection, config.getHeadSection())) {
|
||||
LocalDateTime timeOfStop = config.getTimeOfStop();
|
||||
if (timeOfStop != null && LocalDateTime.now().isAfter(timeOfStop)) {
|
||||
headPosition = headSection.buildStopPointPosition(right);
|
||||
train.setHeadPosition(headPosition);
|
||||
config.updateHeadSection(null);
|
||||
}
|
||||
}
|
||||
//更新速度
|
||||
SimulationDataRepository repository = simulation.getRepository();
|
||||
SectionPosition tailPosition = train.calculateTailPosition();
|
||||
float speed = train.getSpeed();
|
||||
float newSpeed;
|
||||
if (train.isAMMode() || train.isCMMode()) {
|
||||
newSpeed = train.getAtoSpeed();
|
||||
} else {
|
||||
SectionPosition targetPosition = train.getRobotTargetPosition();
|
||||
if (targetPosition == null
|
||||
|| (Objects.equals(headSection, targetPosition.getSection()) && !headSection.isFunctionTrack())) {
|
||||
newSpeed = 0;
|
||||
} else {
|
||||
float recommendedSpeedMax;
|
||||
if (train.isRMMode()) {
|
||||
recommendedSpeedMax = Math.min(repository.getConfig().getRmAtpSpeed(), train.getSpeedLimit()) * 0.9f;
|
||||
} else if (train.isNRMMode()) {
|
||||
recommendedSpeedMax = Math.min(repository.getConfig().getUrmAtpSpeed(), train.getSpeedLimit()) * 0.9f;
|
||||
} else {
|
||||
recommendedSpeedMax = 0;
|
||||
}
|
||||
Float distance = CalculateService.calculateDistance(headPosition, targetPosition, right);
|
||||
if (distance == null || distance <= SimulationConstants.PARK_POINT_MAX_OFFSET) { //如果列车已经抵达或越过目标位置
|
||||
newSpeed = 0;
|
||||
} else {
|
||||
SpeedCurve speedCurve = SpeedCurve.buildTargetSpeedCurve(headPosition, tailPosition, right,
|
||||
distance, speed, recommendedSpeedMax);
|
||||
newSpeed = speedCurve.getSpeedOf(speedCurve.getTotalDistance());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (newSpeed == 0) {
|
||||
train.setSpeed(0);
|
||||
} else {
|
||||
newSpeed = 20f / 3.6f;
|
||||
}
|
||||
Float speedMax = null;
|
||||
if (headSection.isStandTrack()) { //车头在站台轨
|
||||
speedMax = 10f / 3.6f;
|
||||
} else {
|
||||
//(车尾未离开站台轨)
|
||||
Section behindStandTrack = null;
|
||||
Section behindSection = headSection;
|
||||
for (int i = 0; i < 5; i++) {
|
||||
behindSection = behindSection.getNextRunningSectionOf(!right);
|
||||
if (behindSection == null)
|
||||
break;
|
||||
if (behindSection.isStandTrack()) {
|
||||
behindStandTrack = behindSection;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (behindStandTrack != null && behindStandTrack.isOccupied()) {
|
||||
speedMax = 10f / 3.6f;
|
||||
}
|
||||
}
|
||||
if (speedMax != null) {
|
||||
train.setSpeed(Math.min(newSpeed, speedMax));
|
||||
} else {
|
||||
train.setSpeed(newSpeed);
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] buildData(VirtualRealityTrain train, SrTrainConfig config) {
|
||||
int gear;
|
||||
if (train.isStop()) {
|
||||
gear = 0;
|
||||
} else {
|
||||
float speedKmPh = train.getSpeedKmPh();
|
||||
if (train.isStop()) {
|
||||
gear = 0;
|
||||
} else {
|
||||
gear = (int) Math.ceil(speedKmPh / 10);
|
||||
gear = Math.max(1, gear);
|
||||
}
|
||||
if (train.isRight()) {
|
||||
gear += 5;
|
||||
}
|
||||
}
|
||||
if (Objects.equals(config.getGear(), gear)) {
|
||||
return null;
|
||||
}
|
||||
config.setGear(gear);
|
||||
byte[] data = new byte[4];
|
||||
data[1] = (byte) 1;
|
||||
data[2] = (byte) Integer.parseInt(config.getConfigVO().getSandboxCode());
|
||||
data[3] = (byte) gear;
|
||||
return data;
|
||||
}
|
||||
|
||||
public void controlTrain(String simulationId, String groupNumber, boolean right, int speed) {
|
||||
Simulation simulation = groupSimulationService.getSimulationByGroup(simulationId);
|
||||
VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber);
|
||||
SrTrainConfig config = (SrTrainConfig) train.getRealDevice();
|
||||
if (right != train.isRight()) { //调头
|
||||
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED
|
||||
.assertTrue(train.getSpeed() == 0, "换端需先停车");
|
||||
atpService.turnDirectionImmediately(train);
|
||||
}
|
||||
train.setRobotTargetPosition(null); //终止机器人司机驾驶
|
||||
//加减速
|
||||
if (train.isEB())
|
||||
return;
|
||||
atpService.changeGear(train, VirtualRealityTrain.Handwheel.MANUAL);
|
||||
int manualGear = speed / 10;
|
||||
config.setManualGear(manualGear);
|
||||
train.setSpeed(speed / 3.6f);
|
||||
byte[] data = buildData(train, config);
|
||||
UDPLowConfig udpLowConfig = (UDPLowConfig) simulation.queryOneRealDevice(ProjectDeviceType.UDP_LOW);
|
||||
udpClient.write(udpLowConfig.getAddr(), data);
|
||||
}
|
||||
}
|
@ -10,15 +10,18 @@ import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.DatagramPacket;
|
||||
import io.netty.channel.socket.nio.NioDatagramChannel;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.ApplicationArguments;
|
||||
import org.springframework.boot.ApplicationRunner;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
@ -28,6 +31,8 @@ public class UDPClient implements ApplicationRunner {
|
||||
|
||||
private Channel channel;
|
||||
|
||||
private final ConcurrentLinkedQueue<Msg> msgQueue = new ConcurrentLinkedQueue<>();
|
||||
|
||||
@Override
|
||||
public void run(ApplicationArguments args) throws Exception {
|
||||
this.start();
|
||||
@ -46,31 +51,40 @@ public class UDPClient implements ApplicationRunner {
|
||||
ChannelFuture future = bootstrap.bind(udpConfig.getClientPort()).sync();
|
||||
Channel channel = future.channel();
|
||||
this.channel = channel;
|
||||
if(future.isSuccess()) {
|
||||
if (future.isSuccess()) {
|
||||
log.info(String.format("udp client start on port [%s]", this.udpConfig.getClientPort()));
|
||||
} else {
|
||||
log.error("udp server start failed", future.cause());
|
||||
}
|
||||
}
|
||||
|
||||
public void write(byte[] ip, int port, byte[] msg) {
|
||||
try {
|
||||
if (channel != null && channel.isWritable()) {
|
||||
InetAddress inetAddress = InetAddress.getByAddress(ip);
|
||||
InetSocketAddress addr = new InetSocketAddress(inetAddress, port);
|
||||
write(addr, msg);
|
||||
}
|
||||
} catch (UnknownHostException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void write(InetSocketAddress addr, byte[] msg) {
|
||||
if (channel != null && channel.isWritable() && addr != null) {
|
||||
ByteBuf byteBuf = Unpooled.copiedBuffer(msg);
|
||||
DatagramPacket data = new DatagramPacket(byteBuf, addr);
|
||||
channel.writeAndFlush(data);
|
||||
msgQueue.add(new Msg(addr, msg));
|
||||
}
|
||||
|
||||
@Scheduled(fixedRate = 10)
|
||||
public void send() {
|
||||
Msg msg = msgQueue.poll();
|
||||
if (msg == null)
|
||||
return;
|
||||
InetSocketAddress addr = msg.getAddr();
|
||||
byte[] data = msg.getData();
|
||||
if (channel != null && channel.isWritable() && addr != null && data != null) {
|
||||
ByteBuf byteBuf = Unpooled.copiedBuffer(data);
|
||||
DatagramPacket datagramPacket = new DatagramPacket(byteBuf, addr);
|
||||
channel.writeAndFlush(datagramPacket);
|
||||
}
|
||||
}
|
||||
|
||||
@Getter
|
||||
class Msg {
|
||||
private InetSocketAddress addr;
|
||||
|
||||
private byte[] data;
|
||||
|
||||
public Msg(InetSocketAddress addr, byte[] data) {
|
||||
this.addr = addr;
|
||||
this.data = data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,14 +12,15 @@ import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
@Getter
|
||||
public class UDPLowConfig extends RealDeviceConfig {
|
||||
@Getter
|
||||
private UDPLowConfigVO configVO;
|
||||
|
||||
private byte[] ip;
|
||||
|
||||
private Integer port;
|
||||
|
||||
@Getter
|
||||
private InetSocketAddress addr;
|
||||
|
||||
public UDPLowConfig(ProjectDeviceVO projectDevice) {
|
||||
|
@ -7,9 +7,9 @@ import io.netty.buffer.ByteBuf;
|
||||
public interface UDPRealDeviceService {
|
||||
boolean isMatch(RealDeviceConfig realDevice);
|
||||
|
||||
void control(Simulation simulation, UDPLowConfig udpLowConfig, RealDeviceConfig realDevice);
|
||||
void run(Simulation simulation, UDPLowConfig udpLowConfig, RealDeviceConfig realDevice);
|
||||
|
||||
void init(Simulation simulation, UDPLowConfig udpConfig, RealDeviceConfig realDevice);
|
||||
void init(Simulation simulation, UDPLowConfig udpLowConfig, RealDeviceConfig realDevice);
|
||||
|
||||
void handle(Simulation simulation, ByteBuf msg);
|
||||
}
|
||||
|
@ -63,8 +63,8 @@ public class UDPRealDeviceThread {
|
||||
}
|
||||
for (RealDeviceConfig config : realDeviceList) {
|
||||
for (UDPRealDeviceService service : serviceList) {
|
||||
if (service.isMatch(config)) {
|
||||
service.control(simulation, udpLowConfig, config);
|
||||
if (service.isMatch(config) && config.getMapElement() != null) {
|
||||
service.run(simulation, udpLowConfig, config);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -84,7 +84,6 @@ public class UDPRealDeviceThread {
|
||||
udpRealDeviceService.handle(simulation, data);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,8 +22,5 @@ public class UDPMessageHandler extends SimpleChannelInboundHandler<DatagramPacke
|
||||
int port = sender.getPort();
|
||||
ByteBuf content = datagramPacket.content();
|
||||
udpRealDeviceThread.handleData(ip, port, content);
|
||||
// System.out.println("收到消息:" + datagramPacket.content().toString(StandardCharsets.UTF_8));
|
||||
// ByteBuf byteBuf = Unpooled.copiedBuffer("hi".getBytes());
|
||||
// ctx.writeAndFlush(new DatagramPacket(byteBuf, datagramPacket.sender()));
|
||||
}
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ public class VRDeviceLogicLoop {
|
||||
for (VirtualRealityTrain train : onlineTrainList) {
|
||||
SectionPosition headPosition = train.getHeadPosition();
|
||||
boolean right = train.isRight();
|
||||
SectionPosition tailPosition = CalculateService.calculateNextPositionByStartAndLen(headPosition, !right, train.getLen());
|
||||
SectionPosition tailPosition = CalculateService.calculateNextPositionByStartAndLen(headPosition, !right, train.getLen(), true);
|
||||
List<Section> occupyAxleSectionList = CalculateService
|
||||
.getTrainOccupyAxleSection(headPosition, tailPosition, right);
|
||||
// 更新占用区段的占用状态
|
||||
|
@ -29,7 +29,11 @@ public class VRTrainRunningService {
|
||||
|
||||
public void trainRunning(Simulation simulation) {
|
||||
List<VirtualRealityTrain> trainList = simulation.getRepository().getOnlineTrainList();
|
||||
trainList.forEach(train -> this.trainRunning(simulation,train));
|
||||
trainList.forEach(train -> {
|
||||
if (!train.isConnectReal()) {
|
||||
this.trainRunning(simulation, train);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -57,8 +61,6 @@ public class VRTrainRunningService {
|
||||
float fr = (float) (2.27 + 0.00156f * originSpeed * 3.6); // 基本阻力
|
||||
float f = train.getFk() - train.getFb() - fr; // 合力
|
||||
float a = f / train.getMass(); // f=ma, a = f/m
|
||||
// System.out.println(String.format("fk-[%s], fb-[%s], fr-[%s], f-[%s], a[%s]",
|
||||
// train.getFk(), train.getFb(), fr, f, a));
|
||||
float time = SimulationModule.TR.getRateS();
|
||||
float increment = a * time;
|
||||
// 现在的速度
|
||||
@ -66,14 +68,6 @@ public class VRTrainRunningService {
|
||||
if (currentSpeed < 0) {
|
||||
currentSpeed = 0;
|
||||
}
|
||||
// else if (currentSpeed > train.getSpeedMax()) {
|
||||
// currentSpeed = train.getSpeedMax();
|
||||
// }
|
||||
// 更新列车速度
|
||||
|
||||
// System.out.println(String.format("当前车速:[%s]", currentSpeed));
|
||||
// 根据速度计算并更新列车所在区段位置
|
||||
// float s = (float) (currentSpeed * time - acceleration * Math.pow(time, 2) / 2);
|
||||
float s;
|
||||
if (VirtualRealityTrain.Handwheel.REVERSE.equals(train.getGear())) { // 倒车挡
|
||||
currentSpeed = Math.min(train.getReverseSpeedMax(), currentSpeed);
|
||||
@ -91,8 +85,7 @@ public class VRTrainRunningService {
|
||||
}
|
||||
boolean right = train.isRight();
|
||||
SectionPosition headPosition = train.getHeadPosition();
|
||||
SectionPosition headPositionNew = CalculateService.calculateNextPositionByStartAndLen(headPosition, right, s);
|
||||
// todo 碰撞检测?如果撞车,不修改位置
|
||||
SectionPosition headPositionNew = CalculateService.calculateNextPositionByStartAndLen(headPosition, right, s, true);
|
||||
//更新车头区段(不会碰撞才更新)
|
||||
boolean change = true;
|
||||
for (VirtualRealityTrain aTrain : simulation.getRepository().getOnlineTrainList()) {
|
||||
@ -102,7 +95,7 @@ public class VRTrainRunningService {
|
||||
if (s > 0) { //向前行驶
|
||||
checkPosition = headPositionNew;
|
||||
} else { //向后行驶
|
||||
checkPosition = CalculateService.calculateNextPositionByStartAndLen(headPositionNew, !right, train.getLen());
|
||||
checkPosition = CalculateService.calculateNextPositionByStartAndLen(headPositionNew, !right, train.getLen(), true);
|
||||
}
|
||||
Section checkSection = checkPosition.getSection();
|
||||
SectionPosition aTrainHeadPosition = aTrain.getHeadPosition();
|
||||
@ -157,13 +150,13 @@ public class VRTrainRunningService {
|
||||
}
|
||||
}
|
||||
//离开计轴区段判断
|
||||
SectionPosition tailPositionOld = CalculateService.calculateNextPositionByStartAndLen(headPosition, !trainRight, train.getLen());
|
||||
SectionPosition tailPositionOld = CalculateService.calculateNextPositionByStartAndLen(headPosition, !trainRight, train.getLen(), true);
|
||||
Section tailAxleCounterSection = tailPositionOld.getSection();
|
||||
if (!tailAxleCounterSection.isAxleCounter()) {
|
||||
tailAxleCounterSection = tailAxleCounterSection.getParent();
|
||||
}
|
||||
if (tailAxleCounterSection != null && tailAxleCounterSection.isAxleCounter()) { //老的车尾区段是计轴区段
|
||||
SectionPosition tailPositionNew = CalculateService.calculateNextPositionByStartAndLen(headPositionNew, !trainRight, train.getLen());
|
||||
SectionPosition tailPositionNew = CalculateService.calculateNextPositionByStartAndLen(headPositionNew, !trainRight, train.getLen(), true);
|
||||
Section tailSectionNew = tailPositionNew.getSection();
|
||||
if (!tailAxleCounterSection.equals(tailSectionNew) && !tailAxleCounterSection.equals(tailSectionNew.getParent())) { //老车尾计轴区段和新车尾区段不一样
|
||||
tailAxleCounterSection.getVirtualAxleCounter().trainOut(trainRight);
|
||||
|
@ -1,5 +1,6 @@
|
||||
package club.joylink.rtss.simulation.cbtc.onboard.ATP;
|
||||
|
||||
import club.joylink.rtss.constants.Project;
|
||||
import club.joylink.rtss.simulation.cbtc.ATP.ground.MaService;
|
||||
import club.joylink.rtss.simulation.cbtc.Simulation;
|
||||
import club.joylink.rtss.simulation.cbtc.constant.DriveMode;
|
||||
@ -7,6 +8,7 @@ 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.MapConfig;
|
||||
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;
|
||||
@ -66,10 +68,10 @@ public class ATPLogicLoop {
|
||||
* 更新列车运行级别
|
||||
*/
|
||||
private void updateRunLevel(Simulation simulation, VirtualRealityTrain train, VirtualRealityTrain.PreselectionMode preselectionMode) {
|
||||
// //如果当前级别高于预选,降至IL
|
||||
// if (!preselectionMode.isMatchTheRunLevel(train.getRunLevel())) {
|
||||
// atpService.updateRunLevel(train, RunLevel.IL, preselectionMode);
|
||||
// }
|
||||
//如果当前级别高于预选,降至IL
|
||||
if (!preselectionMode.isMatchTheRunLevel(train.getRunLevel())) {
|
||||
atpService.updateRunLevel(train, RunLevel.IL, preselectionMode);
|
||||
}
|
||||
|
||||
RunLevel defaultRunLevel = simulation.getRepository().getConfig().getRunMode();
|
||||
//更新移动授权丢失时长
|
||||
@ -140,7 +142,7 @@ public class ATPLogicLoop {
|
||||
// this.sendStopMessage2GroundAtp(simulation, train);
|
||||
// // 检查列车是否在转换轨
|
||||
// this.checkOnTransferAndSend2Ats(simulation, train, headPosition, tailPosition);
|
||||
if (!train.isBreaking()) { // 制动状态
|
||||
if (!train.isBreaking() && !train.isRMMode() && !train.isNRMMode()) { // 制动状态
|
||||
// 施加常规制动,防止倒溜
|
||||
this.atoService.openBreaking(train);
|
||||
}
|
||||
@ -153,6 +155,10 @@ public class ATPLogicLoop {
|
||||
if (train.isRMMode() && train.isLeverNotInTractionGear()) { //停车、RM模式、操纵杆非牵引位
|
||||
atpService.cancelSignalEB(train);
|
||||
}
|
||||
// if (Project.SR_SANDBOX.name().equals(simulation.getBuildParams().getMap().getProjectCode())) {
|
||||
// atpService.cancelSignalEB(train);
|
||||
// atpService.openATO(train);
|
||||
// }
|
||||
}
|
||||
|
||||
if (this.checkConditionToMove2(simulation, train)) { // 可以启动
|
||||
@ -268,13 +274,14 @@ public class ATPLogicLoop {
|
||||
|
||||
private void handlePreselectionMode(Simulation simulation, VirtualRealityTrain train) {
|
||||
VirtualRealityTrain.PreselectionMode preselectionMode = train.getPreselectionMode();
|
||||
MapConfig config = simulation.getRepository().getConfig();
|
||||
switch (preselectionMode) {
|
||||
case AM_C:
|
||||
if (!train.isCBTC())
|
||||
if (!train.isCBTC() && config.getRunMode().isNotLowerThan(RunLevel.CBTC))
|
||||
train.setCommunication(true);
|
||||
break;
|
||||
case SM_C:
|
||||
if (!train.isCBTC())
|
||||
if (!train.isCBTC() && config.getRunMode().isNotLowerThan(RunLevel.CBTC))
|
||||
train.setCommunication(true);
|
||||
atpService.closeATO(train);
|
||||
break;
|
||||
|
@ -175,6 +175,7 @@ public class ATPService {
|
||||
if (train.isAtoOn()) {
|
||||
closeATO(train);
|
||||
}
|
||||
train.initAsRM(); //简单粗暴
|
||||
train.setAtpOn(false);
|
||||
train.setSignalEB(false);
|
||||
train.setDriveMode(DriveMode.NRM);
|
||||
@ -185,6 +186,7 @@ public class ATPService {
|
||||
*/
|
||||
public void openAtp(VirtualRealityTrain train) {
|
||||
train.setAtpOn(true);
|
||||
train.setDriveMode(DriveMode.RM);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -271,7 +273,7 @@ public class ATPService {
|
||||
newHeadPosition = new SectionPosition(section, offset);
|
||||
} else {
|
||||
newHeadPosition = CalculateService
|
||||
.calculateNextPositionByStartAndLen(headPosition, !right, train.getLen());
|
||||
.calculateNextPositionByStartAndLen(headPosition, !right, train.getLen(), false);
|
||||
}
|
||||
// 车尾变车头,车头变车尾
|
||||
train.setHeadPosition(newHeadPosition);
|
||||
|
@ -71,7 +71,7 @@ public class TrainTargetUpdateService {
|
||||
if (!temp.getCode().equals(trainInfo.getActualArriveStandTrack())) { //列车未在该区段停车
|
||||
SectionPosition maxStopPosition = CalculateService
|
||||
.calculateNextPositionByStartAndLen(temp.buildStopPointPosition(right),
|
||||
right, SimulationConstants.PARK_POINT_MAX_OFFSET); //最远停车点
|
||||
right, SimulationConstants.PARK_POINT_MAX_OFFSET, false); //最远停车点
|
||||
if (maxStopPosition.isAheadOf(headPosition, right)) { //该区段最远停车点在车头前方
|
||||
newTarget = temp;
|
||||
break;
|
||||
|
@ -192,7 +192,7 @@ public class RobotLogicLoop {
|
||||
// operationParams.put("percent", 0);
|
||||
// atsOperationDispatcher.execute(simulation, driver, Operation.Type.Driver_Force_Change.name(), operationParams);
|
||||
// }
|
||||
SectionPosition tailPosition = CalculateService.calculateNextPositionByStartAndLen(headPosition, !right, train.getLen());
|
||||
SectionPosition tailPosition = CalculateService.calculateNextPositionByStartAndLen(headPosition, !right, train.getLen(), true);
|
||||
SpeedCurve speedCurve = null;
|
||||
switch (train.getDriveMode()) {
|
||||
case AM: //AM模式下不需要司机驾驶
|
||||
|
@ -1,9 +1,15 @@
|
||||
package club.joylink.rtss.vo.client.competition;
|
||||
|
||||
import club.joylink.rtss.vo.client.PageQueryVO;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* 竞赛分页查询
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class CompetitionPagedQueryVO extends PageQueryVO {
|
||||
|
||||
private String name;
|
||||
}
|
||||
|
@ -15,11 +15,12 @@ import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.richor.ZjdPslConf
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.sdy.SdyPsdConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.sdy.SdyPslConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.xty.XtyPsdConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.Sr.SrSectionConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.Sr.SrSignalConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.Sr.SrSwitchConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.sr.config.SrSectionConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.sr.config.SrSignalConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.sr.config.SrSwitchConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.UDPClientConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.UDPLowConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.sr.config.SrTrainConfig;
|
||||
import club.joylink.rtss.util.JsonUtils;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import lombok.Getter;
|
||||
@ -143,6 +144,9 @@ public class ProjectDeviceVO {
|
||||
case SWITCH:
|
||||
list.add(new SrSwitchConfig(deviceVO));
|
||||
break;
|
||||
case TRAIN:
|
||||
list.add(new SrTrainConfig(deviceVO));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return list;
|
||||
|
@ -12,6 +12,16 @@ public class SrSectionConfigVO {
|
||||
|
||||
private String sandboxCode;
|
||||
|
||||
/**
|
||||
* 车头到达区段延迟停车时间/s
|
||||
*/
|
||||
private Float headDelayTime;
|
||||
|
||||
/**
|
||||
* 车尾解除占用延迟停车时间/s
|
||||
*/
|
||||
private Float tailDelayTime;
|
||||
|
||||
public SrSectionConfigVO(String vrCode, String sandboxCode) {
|
||||
this.vrCode = vrCode;
|
||||
this.sandboxCode = sandboxCode;
|
||||
|
@ -0,0 +1,19 @@
|
||||
package club.joylink.rtss.vo.client.project.sr;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
public class SrTrainConfigVO {
|
||||
private String vrCode;
|
||||
|
||||
private String sandboxCode;
|
||||
|
||||
public SrTrainConfigVO(String vrCode, String sandboxCode) {
|
||||
this.vrCode = vrCode;
|
||||
this.sandboxCode = sandboxCode;
|
||||
}
|
||||
}
|
@ -123,8 +123,8 @@ public class RunPlanTripVO {
|
||||
|
||||
public RunPlanTripVO(RunPlanRoutingVO routingVO) {
|
||||
this.right = routingVO.getRight();
|
||||
this.isOutbound = routingVO.isInBoundRoute();
|
||||
this.isInbound = routingVO.isOutBoundRoute();
|
||||
this.isOutbound = routingVO.isOutBoundRoute();
|
||||
this.isInbound = routingVO.isInBoundRoute();
|
||||
this.destinationCode = Objects.isNull(routingVO.getDestinationCode()) ? "" : routingVO.getDestinationCode();
|
||||
this.startSectionCode = routingVO.getStartSectionCode();
|
||||
this.endSectionCode = routingVO.getEndSectionCode();
|
||||
|
@ -167,7 +167,7 @@ common:
|
||||
spring:
|
||||
profiles: local
|
||||
datasource:
|
||||
url: jdbc:mysql://192.168.1.254:3306/joylink?useSSL=false&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
|
||||
url: jdbc:mysql://192.168.0.254:3306/joylink?useSSL=false&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
|
||||
username: root
|
||||
password: localdb
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user