Compare commits
6 Commits
master
...
thailand_s
Author | SHA1 | Date |
---|---|---|
joylink_zhangsai | 8709ecab5b | |
joylink_zhangsai | e461a62552 | |
joylink_zhangsai | b653258e75 | |
joylink_zhangsai | ecdf9fdc84 | |
joylink_zhangsai | 2a08dab6c9 | |
joylink_zhangsai | 21afd1f82f |
|
@ -48,7 +48,9 @@ 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.SrSignalConfigVO;
|
||||||
import club.joylink.rtss.vo.client.project.sr.SrSwitchConfigVO;
|
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.sr.SrTrainConfigVO;
|
||||||
|
import club.joylink.rtss.vo.client.project.thailand.ThailandRunPlanConfigVO;
|
||||||
import club.joylink.rtss.vo.client.project.thailand.ThailandSectionConfigVO;
|
import club.joylink.rtss.vo.client.project.thailand.ThailandSectionConfigVO;
|
||||||
|
import club.joylink.rtss.vo.client.project.thailand.ThailandSignalConfigVO;
|
||||||
import club.joylink.rtss.vo.client.project.thailand.ThailandSwitchConfigVO;
|
import club.joylink.rtss.vo.client.project.thailand.ThailandSwitchConfigVO;
|
||||||
import club.joylink.rtss.vo.client.project.thailand.ThailandTrainConfigVO;
|
import club.joylink.rtss.vo.client.project.thailand.ThailandTrainConfigVO;
|
||||||
import club.joylink.rtss.vo.client.project.xty.XtyPsdConfigVO;
|
import club.joylink.rtss.vo.client.project.xty.XtyPsdConfigVO;
|
||||||
|
@ -62,6 +64,7 @@ import com.github.pagehelper.Page;
|
||||||
import com.github.pagehelper.PageHelper;
|
import com.github.pagehelper.PageHelper;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
@ -932,7 +935,7 @@ public class DeviceServiceImpl implements DeviceService {
|
||||||
signal.setType(ProjectDeviceType.SIGNAL.name());
|
signal.setType(ProjectDeviceType.SIGNAL.name());
|
||||||
signal.setCreator(accountVO.getId());
|
signal.setCreator(accountVO.getId());
|
||||||
signal.setCreateTime(now);
|
signal.setCreateTime(now);
|
||||||
SrSignalConfigVO configVO = new SrSignalConfigVO(mapSignalNewVO.getCode(),
|
ThailandSignalConfigVO configVO = new ThailandSignalConfigVO(mapSignalNewVO.getCode(),
|
||||||
mapSignalNewVO.getSrCode());
|
mapSignalNewVO.getSrCode());
|
||||||
signal.setConfig(JsonUtils.writeValueAsString(configVO));
|
signal.setConfig(JsonUtils.writeValueAsString(configVO));
|
||||||
list.add(signal);
|
list.add(signal);
|
||||||
|
@ -983,100 +986,120 @@ public class DeviceServiceImpl implements DeviceService {
|
||||||
train.setConfig(JsonUtils.writeValueAsString(configVO));
|
train.setConfig(JsonUtils.writeValueAsString(configVO));
|
||||||
list.add(train);
|
list.add(train);
|
||||||
}
|
}
|
||||||
|
//运行计划
|
||||||
|
ProjectDevice runPlan = new ProjectDevice();
|
||||||
|
runPlan.setProjectCode(projectCode);
|
||||||
|
runPlan.setCode("runPlan");
|
||||||
|
runPlan.setType(ProjectDeviceType.SAND_TABLE_RUN_PLAN.name());
|
||||||
|
runPlan.setCreator(accountVO.getId());
|
||||||
|
runPlan.setCreateTime(now);
|
||||||
|
ThailandRunPlanConfigVO configVO = new ThailandRunPlanConfigVO();
|
||||||
|
configVO.setStandTrackList(Arrays.asList("T85", "T158", "T205", "T247", "T206", "T157", "T84"));
|
||||||
|
runPlan.setConfig(JsonUtils.writeValueAsString(configVO));
|
||||||
|
list.add(runPlan);
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void thailandFillTime(ThailandSectionConfigVO configVO, MapSectionNewVO section) {
|
private void thailandFillTime(ThailandSectionConfigVO configVO, MapSectionNewVO section) {
|
||||||
Float headDelayTime = null;
|
Float headDelayTime = null;
|
||||||
Float tailDelayTime = null;
|
Float tailDelayTime = null;
|
||||||
if (section.isStandTrack()) { //站台轨默认为车尾出清立即停车
|
if (section.isStandTrack()) {
|
||||||
headDelayTime = 5f;
|
headDelayTime = 5f;
|
||||||
}
|
}
|
||||||
switch (section.getCode()) {
|
switch (section.getCode()) {
|
||||||
case "T233": //X302G
|
case "T1": //X301G
|
||||||
headDelayTime = 7.3f;
|
headDelayTime = 5f;
|
||||||
break;
|
break;
|
||||||
case "T232": //X303G
|
case "T2": //X302G
|
||||||
headDelayTime = 6.5f;
|
headDelayTime = 7.9f;
|
||||||
break;
|
break;
|
||||||
case "T231": //X304G
|
case "T3": //X303G
|
||||||
headDelayTime = 5.5f;
|
headDelayTime = 6.7f;
|
||||||
break;
|
break;
|
||||||
case "T178": //4站-3G
|
case "T4": //X304G
|
||||||
headDelayTime = 5.2f;
|
headDelayTime = 5.6f;
|
||||||
break;
|
break;
|
||||||
case "T177": //4站-IG
|
case "T5": //X305G
|
||||||
headDelayTime = 5.4f;
|
|
||||||
break;
|
|
||||||
case "T175": //4站-IIG
|
|
||||||
headDelayTime = 6.6f;
|
|
||||||
break;
|
|
||||||
case "T174": //4站-4G
|
|
||||||
headDelayTime = 6.2f;
|
|
||||||
break;
|
|
||||||
case "T176": //4站-6G
|
|
||||||
headDelayTime = 5.9f;
|
|
||||||
break;
|
|
||||||
case "T179": //4站-5G
|
|
||||||
headDelayTime = 6.5f;
|
|
||||||
break;
|
|
||||||
case "T123": //3站-3G
|
|
||||||
headDelayTime = 5.2f;
|
|
||||||
break;
|
|
||||||
case "T122": //3站-IG
|
|
||||||
headDelayTime = 5.3f;
|
headDelayTime = 5.3f;
|
||||||
break;
|
break;
|
||||||
case "T121": //3站-IIG
|
case "T6": //X306G
|
||||||
headDelayTime = 5.9f;
|
|
||||||
break;
|
|
||||||
case "T120": //3站-4G
|
|
||||||
headDelayTime = 5.5f;
|
headDelayTime = 5.5f;
|
||||||
break;
|
break;
|
||||||
case "T78": //2站-IG
|
case "T7": //X307G
|
||||||
|
headDelayTime = 5.3f;
|
||||||
|
break;
|
||||||
|
case "T8": //X308G
|
||||||
headDelayTime = 5.5f;
|
headDelayTime = 5.5f;
|
||||||
break;
|
break;
|
||||||
case "T77": //2站-IIG
|
case "T89": //1站6G
|
||||||
headDelayTime = 5.9f;
|
headDelayTime = 5.9f;
|
||||||
break;
|
break;
|
||||||
case "T76": //2站-4G
|
case "T90": //1站4G
|
||||||
|
headDelayTime = 6.4f;
|
||||||
|
break;
|
||||||
|
case "T85": //1站2G
|
||||||
|
headDelayTime = 6.8f;
|
||||||
|
break;
|
||||||
|
case "T84": //1站1G
|
||||||
|
headDelayTime = 5.9f;
|
||||||
|
break;
|
||||||
|
case "T94": //1站3G
|
||||||
|
headDelayTime = 5.2f;
|
||||||
|
break;
|
||||||
|
case "T95": //1站5G
|
||||||
|
headDelayTime = 6.5f;
|
||||||
|
break;
|
||||||
|
case "T160": //2站4G
|
||||||
|
headDelayTime = 5.5f;
|
||||||
|
break;
|
||||||
|
case "T158": //2站2G
|
||||||
|
headDelayTime = 5.2f;
|
||||||
|
break;
|
||||||
|
case "T157": //2站1G
|
||||||
|
headDelayTime = 5.8f;
|
||||||
|
break;
|
||||||
|
case "T159": //2站3G
|
||||||
|
headDelayTime = 5.2f;
|
||||||
|
break;
|
||||||
|
case "T204": //3站4G
|
||||||
headDelayTime = 5.7f;
|
headDelayTime = 5.7f;
|
||||||
break;
|
break;
|
||||||
case "T22": //1站-1G
|
case "T205": //3站2G
|
||||||
|
headDelayTime = 5.6f;
|
||||||
|
break;
|
||||||
|
case "T206": //3站1G
|
||||||
|
headDelayTime = 6f;
|
||||||
|
break;
|
||||||
|
case "T207": //3站3G
|
||||||
headDelayTime = 5.3f;
|
headDelayTime = 5.3f;
|
||||||
break;
|
break;
|
||||||
case "T23": //1站-IIG
|
case "T242": //4站6G
|
||||||
headDelayTime = 5.1f;
|
headDelayTime = 5.1f;
|
||||||
break;
|
break;
|
||||||
case "T27": //1站-5G
|
case "T243": //3站4G
|
||||||
headDelayTime = 4.9f;
|
headDelayTime = 5.1f;
|
||||||
break;
|
break;
|
||||||
case "T26": //1站-3G
|
case "T244": //3站2G
|
||||||
|
headDelayTime = 5.1f;
|
||||||
|
break;
|
||||||
|
case "T247": //3站1G
|
||||||
|
headDelayTime = 5.5f;
|
||||||
|
break;
|
||||||
|
case "T254": //3站3G
|
||||||
headDelayTime = 4.8f;
|
headDelayTime = 4.8f;
|
||||||
break;
|
break;
|
||||||
case "T24": //1站-4G
|
case "T255": //3站5G
|
||||||
headDelayTime = 5.1f;
|
headDelayTime = 4.9f;
|
||||||
break;
|
break;
|
||||||
case "T25": //1站-6G
|
case "T142": //QX04
|
||||||
headDelayTime = 5.1f;
|
|
||||||
break;
|
|
||||||
case "T145": //QX04
|
|
||||||
headDelayTime = 1.9f;
|
headDelayTime = 1.9f;
|
||||||
break;
|
break;
|
||||||
case "T146": //QS04
|
case "T141": //其它QX/QS区段
|
||||||
headDelayTime = 2.7f;
|
case "T183":
|
||||||
break;
|
case "T184":
|
||||||
case "T104": //QX03
|
case "T223":
|
||||||
|
case "T224":
|
||||||
tailDelayTime = 0f;
|
tailDelayTime = 0f;
|
||||||
break;
|
|
||||||
case "T105": //QS03
|
|
||||||
tailDelayTime = 0f;
|
|
||||||
break;
|
|
||||||
case "T62": //QX02
|
|
||||||
tailDelayTime = 0f;
|
|
||||||
break;
|
|
||||||
case "T63": //QS02
|
|
||||||
tailDelayTime = 0f;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
configVO.setHeadDelayTime(headDelayTime);
|
configVO.setHeadDelayTime(headDelayTime);
|
||||||
configVO.setTailDelayTime(tailDelayTime);
|
configVO.setTailDelayTime(tailDelayTime);
|
||||||
|
|
|
@ -3,12 +3,11 @@ package club.joylink.rtss.simulation.cbtc.data.support;
|
||||||
import club.joylink.rtss.simulation.cbtc.constant.SimulationConstants;
|
import club.joylink.rtss.simulation.cbtc.constant.SimulationConstants;
|
||||||
import club.joylink.rtss.simulation.cbtc.data.CalculateService;
|
import club.joylink.rtss.simulation.cbtc.data.CalculateService;
|
||||||
import club.joylink.rtss.simulation.cbtc.data.map.Section;
|
import club.joylink.rtss.simulation.cbtc.data.map.Section;
|
||||||
import lombok.Getter;
|
|
||||||
import org.springframework.util.CollectionUtils;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.math.RoundingMode;
|
import java.math.RoundingMode;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 地图位置坐标
|
* 地图位置坐标
|
||||||
|
@ -16,117 +15,131 @@ import java.util.Objects;
|
||||||
@Getter
|
@Getter
|
||||||
public class SectionPosition {
|
public class SectionPosition {
|
||||||
|
|
||||||
private Section section;
|
private Section section;
|
||||||
|
|
||||||
private float offset;
|
private float offset;
|
||||||
|
|
||||||
public SectionPosition(Section section, float offset) {
|
public SectionPosition(Section section, float offset) {
|
||||||
this.section = section;
|
this.section = section;
|
||||||
this.offset = offset;
|
this.offset = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSameSection(Section section) {
|
||||||
|
return this.section.getCode().equals(section.getCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前位置是否在other前面。更right的位置视为更前。
|
||||||
|
*
|
||||||
|
* @param other
|
||||||
|
* @param right
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean isAheadOf(SectionPosition other, boolean right) {
|
||||||
|
return isAheadOf(other.getSection(), other.getOffset(), right);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isAheadOf(Section section, float offset, boolean right) {
|
||||||
|
if (Objects.equals(this.getSection(), section)) {
|
||||||
|
// 同一根区段
|
||||||
|
if (right && this.getOffset() > offset) {
|
||||||
|
// 右向,此偏移量大于另一个偏移量
|
||||||
|
return true;
|
||||||
|
} else if (!right && this.getOffset() < offset) {
|
||||||
|
// 左向,此偏移量小于另一个偏移量
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else { // 不是同一区段,查询另一区段在指定方向上是否能找到此位置区段,如果找到,则在前
|
||||||
|
if (CalculateService.isTargetSectionOnDirectionExist(section, right,
|
||||||
|
this.getSection())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isSameSection(Section section) {
|
@Override
|
||||||
return this.section.getCode().equals(section.getCode());
|
public String toString() {
|
||||||
}
|
return "{" +
|
||||||
|
String.format("%s(%s)", section.getName(), section.getCode()) +
|
||||||
|
String.format(", %s", offset) +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isAheadOf(SectionPosition other, boolean right) {
|
public Section getLogicSection() {
|
||||||
return isAheadOf(other.getSection(), other.getOffset(), right);
|
if (!CollectionUtils.isEmpty(section.getLogicList())) {
|
||||||
}
|
for (Section logic : section.getLogicList()) {
|
||||||
|
if (this.offset > logic.getMinOffset() && this.offset <= logic.getMaxOffset()) {
|
||||||
public boolean isAheadOf(Section section, float offset, boolean right) {
|
return logic;
|
||||||
if (Objects.equals(this.getSection(), section)) {
|
|
||||||
// 同一根区段
|
|
||||||
if (right && this.getOffset() > offset) {
|
|
||||||
// 右向,此偏移量大于另一个偏移量
|
|
||||||
return true;
|
|
||||||
} else if (!right && this.getOffset() < offset) {
|
|
||||||
// 左向,此偏移量小于另一个偏移量
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else { // 不是同一区段,查询另一区段在指定方向上是否能找到此位置区段,如果找到,则在前
|
|
||||||
if (CalculateService.isTargetSectionOnDirectionExist(section, right, this.getSection())) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
}
|
||||||
}
|
}
|
||||||
|
return this.section;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public int hashCode() {
|
||||||
return "{" +
|
return section.hashCode() + Float.hashCode(offset);
|
||||||
String.format("%s(%s)", section.getName(), section.getCode()) +
|
}
|
||||||
String.format(", %s", offset) +
|
|
||||||
'}';
|
|
||||||
}
|
|
||||||
|
|
||||||
public Section getLogicSection() {
|
@Override
|
||||||
if (!CollectionUtils.isEmpty(section.getLogicList())) {
|
public boolean equals(Object obj) {
|
||||||
for (Section logic : section.getLogicList()) {
|
if (this == obj) {
|
||||||
if (this.offset > logic.getMinOffset() && this.offset <= logic.getMaxOffset()) {
|
return true;
|
||||||
return logic;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this.section;
|
|
||||||
}
|
}
|
||||||
|
if (obj == null || getClass() != obj.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
SectionPosition sp = (SectionPosition) obj;
|
||||||
|
return Objects.equals(this.getSection(), sp.getSection()) && offset == sp.getOffset();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
public float getPercent() {
|
||||||
public int hashCode() {
|
return BigDecimal.valueOf(this.offset / this.getSection().getLen())
|
||||||
return section.hashCode() + Float.hashCode(offset);
|
.setScale(4, RoundingMode.HALF_UP).floatValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public boolean isAvailable() {
|
||||||
public boolean equals(Object obj) {
|
return !(this.offset < 0 || this.offset > this.section.getLen());
|
||||||
if (this == obj) return true;
|
}
|
||||||
if (obj == null || getClass() != obj.getClass()) return false;
|
|
||||||
SectionPosition sp = (SectionPosition) obj;
|
|
||||||
return Objects.equals(this.getSection(), sp.getSection()) && offset == sp.getOffset();
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getPercent() {
|
public boolean isBetween(SectionPosition one, SectionPosition two) {
|
||||||
return BigDecimal.valueOf(this.offset / this.getSection().getLen())
|
if (one.equals(this) || two.equals(this)) {
|
||||||
.setScale(4, RoundingMode.HALF_UP).floatValue();
|
return true;
|
||||||
}
|
}
|
||||||
|
if (one.isAheadOf(this, true)) {
|
||||||
|
return this.isAheadOf(two, true);
|
||||||
|
} else if (this.isAheadOf(one, true)) {
|
||||||
|
return two.isAheadOf(this, true);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isAvailable() {
|
public SectionPosition convert2PhysicalSectionPosition() {
|
||||||
return !(this.offset < 0 || this.offset > this.section.getLen());
|
Section section = this.getSection();
|
||||||
|
if (section.isPhysical()) {
|
||||||
|
return this;
|
||||||
|
} else {
|
||||||
|
Section parent = section.getParent();
|
||||||
|
if (parent != null) {
|
||||||
|
return new SectionPosition(parent, section.getMinOffset() + this.getOffset());
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isBetween(SectionPosition one, SectionPosition two) {
|
/**
|
||||||
if (one.equals(this) || two.equals(this))
|
* 该位置位于对应区段的停车范围内
|
||||||
return true;
|
*/
|
||||||
if (one.isAheadOf(this, true)) {
|
public boolean isWithinParkingRange(boolean right) {
|
||||||
return this.isAheadOf(two, true);
|
SectionPosition targetPosition = new SectionPosition(this.section,
|
||||||
} else if (this.isAheadOf(one, true)) {
|
this.section.getStopPointByDirection(right));
|
||||||
return two.isAheadOf(this, true);
|
SectionPosition max = CalculateService.calculateNextPositionByStartAndLen(targetPosition,
|
||||||
} else {
|
right, SimulationConstants.PARK_POINT_MAX_OFFSET, false);
|
||||||
return false;
|
SectionPosition min = CalculateService.calculateNextPositionByStartAndLen(targetPosition,
|
||||||
}
|
!right, SimulationConstants.PARK_POINT_MAX_OFFSET, false);
|
||||||
}
|
return this.isAheadOf(min, right) && max.isAheadOf(this, right);
|
||||||
|
}
|
||||||
public SectionPosition convert2PhysicalSectionPosition() {
|
|
||||||
Section section = this.getSection();
|
|
||||||
if (section.isPhysical()) {
|
|
||||||
return this;
|
|
||||||
} else {
|
|
||||||
Section parent = section.getParent();
|
|
||||||
if (parent != null) {
|
|
||||||
return new SectionPosition(parent, section.getMinOffset() + this.getOffset());
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 该位置位于对应区段的停车范围内
|
|
||||||
*/
|
|
||||||
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, false);
|
|
||||||
SectionPosition min = CalculateService.calculateNextPositionByStartAndLen(targetPosition,
|
|
||||||
!right, SimulationConstants.PARK_POINT_MAX_OFFSET, false);
|
|
||||||
return this.isAheadOf(min, right) && max.isAheadOf(this, right);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,43 @@
|
||||||
package club.joylink.rtss.simulation.cbtc.device.real.udp;
|
package club.joylink.rtss.simulation.cbtc.device.real.udp;
|
||||||
|
|
||||||
import club.joylink.rtss.constants.ProjectCode;
|
import club.joylink.rtss.constants.ProjectCode;
|
||||||
|
import club.joylink.rtss.constants.ProjectDeviceType;
|
||||||
import club.joylink.rtss.dao.MapDataDAO;
|
import club.joylink.rtss.dao.MapDataDAO;
|
||||||
import club.joylink.rtss.entity.MapDataExample;
|
import club.joylink.rtss.entity.MapDataExample;
|
||||||
import club.joylink.rtss.entity.MapDataWithBLOBs;
|
import club.joylink.rtss.entity.MapDataWithBLOBs;
|
||||||
import club.joylink.rtss.simulation.cbtc.GroupSimulationService;
|
import club.joylink.rtss.simulation.cbtc.GroupSimulationService;
|
||||||
import club.joylink.rtss.simulation.cbtc.Simulation;
|
import club.joylink.rtss.simulation.cbtc.Simulation;
|
||||||
|
import club.joylink.rtss.simulation.cbtc.data.map.Section;
|
||||||
|
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.device.RealDeviceConfig;
|
||||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.sr.service.SrTrainServiceImpl;
|
import club.joylink.rtss.simulation.cbtc.device.real.udp.sr.service.SrTrainServiceImpl;
|
||||||
|
import club.joylink.rtss.simulation.cbtc.device.real.udp.thailand.config.ThailandRunPlanConfig;
|
||||||
|
import club.joylink.rtss.simulation.cbtc.device.real.udp.thailand.service.ThailandRunPlanServiceImpl;
|
||||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.thailand.service.ThailandTrainServiceImpl;
|
import club.joylink.rtss.simulation.cbtc.device.real.udp.thailand.service.ThailandTrainServiceImpl;
|
||||||
import club.joylink.rtss.util.JsonUtils;
|
import club.joylink.rtss.util.JsonUtils;
|
||||||
import club.joylink.rtss.vo.map.MapLogicDataNewVO;
|
import club.joylink.rtss.vo.client.project.thailand.ThailandRunPlanConfigVO;
|
||||||
|
import club.joylink.rtss.vo.client.project.thailand.ThailandRunPlanConfigVO.Param;
|
||||||
|
import club.joylink.rtss.vo.map.MapGraphDataNewVO;
|
||||||
|
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 java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.PutMapping;
|
import org.springframework.web.bind.annotation.PutMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 沙盘项目接口
|
||||||
|
*/
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/sandTable")
|
@RequestMapping("/api/sandTable")
|
||||||
public class SandTableTrainController {
|
public class SandTableTrainController {
|
||||||
|
@ -25,6 +47,8 @@ public class SandTableTrainController {
|
||||||
@Autowired
|
@Autowired
|
||||||
private ThailandTrainServiceImpl thailandTrainService;
|
private ThailandTrainServiceImpl thailandTrainService;
|
||||||
@Autowired
|
@Autowired
|
||||||
|
private ThailandRunPlanServiceImpl thailandRunPlanService;
|
||||||
|
@Autowired
|
||||||
private SrTrainServiceImpl srTrainService;
|
private SrTrainServiceImpl srTrainService;
|
||||||
|
|
||||||
@PutMapping("/{simulationId}/control")
|
@PutMapping("/{simulationId}/control")
|
||||||
|
@ -42,29 +66,89 @@ public class SandTableTrainController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按计划运行
|
||||||
|
*/
|
||||||
|
@PutMapping("/{simulationId}/runAsPlan")
|
||||||
|
public void runAsPlan(@PathVariable String simulationId,
|
||||||
|
@RequestBody @Validated List<Param> paramList) {
|
||||||
|
Simulation simulation = groupSimulationService.getSimulationByGroup(simulationId);
|
||||||
|
switch (simulation.getProject()) {
|
||||||
|
case ProjectCode.THAILAND_SANDBOX:
|
||||||
|
thailandRunPlanService.runAsPlan(simulation, paramList);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取运行计划详情
|
||||||
|
*/
|
||||||
|
@GetMapping("/{simulationId}/runPlanDetail")
|
||||||
|
public List<ThailandRunPlanConfigVO.Detail> getRunPlanDetail(@PathVariable String simulationId) {
|
||||||
|
Simulation simulation = groupSimulationService.getSimulationByGroup(simulationId);
|
||||||
|
List<RealDeviceConfig> runPlanConfigList = simulation.getRealDeviceByType(
|
||||||
|
ProjectDeviceType.SAND_TABLE_RUN_PLAN);
|
||||||
|
if (CollectionUtils.isEmpty(runPlanConfigList)) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
ThailandRunPlanConfig config = (ThailandRunPlanConfig) runPlanConfigList.get(0);
|
||||||
|
List<ThailandRunPlanConfigVO.Detail> list = new ArrayList<>();
|
||||||
|
Integer parkingDuration = config.getParkingDuration();
|
||||||
|
config.getDetailMap().forEach((train, detailList) -> {
|
||||||
|
String groupNumber = train.getGroupNumber();
|
||||||
|
List<ThailandRunPlanConfigVO.Detail> detailVOList = detailList.stream().map(detail -> {
|
||||||
|
String stationName = detail.getTrack().getStation().getName();
|
||||||
|
String trackName = detail.getTrack().getName();
|
||||||
|
boolean finished = detail.isFinished();
|
||||||
|
return new ThailandRunPlanConfigVO.Detail(groupNumber, stationName, trackName,
|
||||||
|
parkingDuration, finished);
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
detailVOList.get(0).setParkingDuration(0);
|
||||||
|
detailVOList.get(detailVOList.size() - 1).setParkingDuration(0);
|
||||||
|
list.addAll(detailVOList);
|
||||||
|
});
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/{simulationId}/occupy")
|
||||||
|
public void setOccupy(@PathVariable String simulationId, @RequestParam List<String> sectionCodes,
|
||||||
|
boolean occupy) {
|
||||||
|
Simulation simulation = groupSimulationService.getSimulationByGroup(simulationId);
|
||||||
|
for (String sectionCode : sectionCodes) {
|
||||||
|
Section section = simulation.getRepository().getByCode(sectionCode, Section.class);
|
||||||
|
section.findAxle().setOccupy(occupy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private MapDataDAO mapDataDAO;
|
private MapDataDAO mapDataDAO;
|
||||||
|
|
||||||
@PutMapping("/handle")
|
@PutMapping("/handle")
|
||||||
public void handle() {
|
public void handle() {
|
||||||
MapDataExample example = new MapDataExample();
|
MapDataExample example = new MapDataExample();
|
||||||
|
example.createCriteria().andMapIdEqualTo(183L);
|
||||||
example.setOrderByClause("id desc");
|
example.setOrderByClause("id desc");
|
||||||
example.setLimit(1);
|
example.setLimit(1);
|
||||||
MapDataWithBLOBs data = mapDataDAO.selectByExampleWithBLOBs(example).get(0);
|
MapDataWithBLOBs data = mapDataDAO.selectByExampleWithBLOBs(example).get(0);
|
||||||
MapLogicDataNewVO logicDataNewVO = JsonUtils.read(data.getLogicData(), MapLogicDataNewVO.class);
|
MapGraphDataNewVO graphDataNewVO = JsonUtils.read(data.getGraphData(), MapGraphDataNewVO.class);
|
||||||
logicDataNewVO.getRouteList().stream()
|
|
||||||
.filter(route -> route.getStartSignalCode().equals("X542") || route.getStartSignalCode()
|
String errSections = graphDataNewVO.getSectionList().stream()
|
||||||
.equals("X11357")
|
.filter(section -> section.getType().equals("04"))
|
||||||
|| route.getStartSignalCode().equals("X47820") || route.getStartSignalCode()
|
.filter(section -> !StringUtils.hasText(section.getSrCode()))
|
||||||
.equals("X4371")
|
.map(MapSectionNewVO::getCode)
|
||||||
|| route.getStartSignalCode().equals("X21134") || route.getStartSignalCode()
|
.collect(Collectors.joining(","));
|
||||||
.equals("X99402")
|
String errSignals = graphDataNewVO.getSignalList().stream()
|
||||||
|| route.getStartSignalCode().equals("X2670") || route.getStartSignalCode()
|
.filter(signal -> !StringUtils.hasText(signal.getSrCode()))
|
||||||
.equals("X49087"))
|
.map(MapSignalNewVO::getCode)
|
||||||
.forEach(route -> {
|
.collect(Collectors.joining(","));
|
||||||
route.setSignalAspect(3);
|
String errSwitches = graphDataNewVO.getSwitchList().stream()
|
||||||
});
|
.filter(aSwitch -> !StringUtils.hasText(aSwitch.getSrCode()) || aSwitch.getThroat() == null)
|
||||||
data.setLogicData(JsonUtils.writeValueAsString(logicDataNewVO));
|
.map(MapSwitchVO::getCode)
|
||||||
mapDataDAO.updateByPrimaryKeyWithBLOBs(data);
|
.collect(Collectors.joining(","));
|
||||||
|
System.out.println("异常区段:" + errSections);
|
||||||
|
System.out.println("异常信号机:" + errSignals);
|
||||||
|
System.out.println("异常区段:" + errSwitches);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,6 @@ import io.netty.channel.nio.NioEventLoopGroup;
|
||||||
import io.netty.channel.socket.DatagramPacket;
|
import io.netty.channel.socket.DatagramPacket;
|
||||||
import io.netty.channel.socket.nio.NioDatagramChannel;
|
import io.netty.channel.socket.nio.NioDatagramChannel;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
@ -60,16 +59,15 @@ public class UDPClient implements ApplicationRunner {
|
||||||
public void write(InetSocketAddress addr, byte[] msg) {
|
public void write(InetSocketAddress addr, byte[] msg) {
|
||||||
if (msg != null) {
|
if (msg != null) {
|
||||||
msgQueue.add(new Msg(addr, msg));
|
msgQueue.add(new Msg(addr, msg));
|
||||||
System.out.println(LocalDateTime.now());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Scheduled(fixedRate = 10)
|
@Scheduled(fixedRate = 10)
|
||||||
public void send() {
|
public void send() {
|
||||||
Msg msg = msgQueue.poll();
|
Msg msg = msgQueue.poll();
|
||||||
if (msg == null) {
|
if (msg == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
InetSocketAddress addr = msg.getAddr();
|
InetSocketAddress addr = msg.getAddr();
|
||||||
byte[] data = msg.getData();
|
byte[] data = msg.getData();
|
||||||
if (channel != null && channel.isWritable() && addr != null && data != null) {
|
if (channel != null && channel.isWritable() && addr != null && data != null) {
|
||||||
|
|
|
@ -72,7 +72,7 @@ public class UDPRealDeviceThread {
|
||||||
for (RealDeviceConfig config : realDeviceList) {
|
for (RealDeviceConfig config : realDeviceList) {
|
||||||
for (UDPRealDeviceService service : serviceList) {
|
for (UDPRealDeviceService service : serviceList) {
|
||||||
if (service.isMatch(udpLowConfig) && service.isMatch(config)
|
if (service.isMatch(udpLowConfig) && service.isMatch(config)
|
||||||
&& config.getMapElement() != null) {
|
/*&& config.getMapElement() != null*/) {
|
||||||
service.run(simulation, udpLowConfig, config);
|
service.run(simulation, udpLowConfig, config);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
package club.joylink.rtss.simulation.cbtc.device.real.udp.thailand.config;
|
||||||
|
|
||||||
|
import club.joylink.rtss.simulation.cbtc.data.map.Route;
|
||||||
|
import club.joylink.rtss.simulation.cbtc.data.map.Section;
|
||||||
|
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityTrain;
|
||||||
|
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.thailand.ThailandRunPlanConfigVO;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class ThailandRunPlanConfig extends RealDeviceConfig {
|
||||||
|
|
||||||
|
private ThailandRunPlanConfigVO configVO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置计划后生成的实际计划
|
||||||
|
*/
|
||||||
|
private LinkedHashMap<VirtualRealityTrain, List<Detail>> detailMap = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* key - 始终区段code连接 value - 始终区段间的进路
|
||||||
|
*/
|
||||||
|
private Map<String, Route[]> routeMap = new HashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表示是否按计划运行中
|
||||||
|
*/
|
||||||
|
private boolean running;
|
||||||
|
|
||||||
|
public ThailandRunPlanConfig(ProjectDeviceVO projectDevice) {
|
||||||
|
super(projectDevice);
|
||||||
|
if (Objects.nonNull(projectDevice.getConfig())) {
|
||||||
|
this.configVO = JsonUtils.read(projectDevice.getConfig(), ThailandRunPlanConfigVO.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String findDeviceCode() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getParkingDuration() {
|
||||||
|
return configVO.getParkingDuration();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getDepartureDuration() {
|
||||||
|
return configVO.getDepartureDuration();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addRoutes(String fromSectionCode, String toSectionCode, Route[] routes) {
|
||||||
|
routeMap.put(fromSectionCode + toSectionCode, routes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Route[] getRoutes(String fromSectionCode, String toSectionCode) {
|
||||||
|
return routeMap.get(fromSectionCode + toSectionCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class Detail {
|
||||||
|
|
||||||
|
private VirtualRealityTrain train;
|
||||||
|
private Section track;
|
||||||
|
private LocalDateTime departureTime;
|
||||||
|
/**
|
||||||
|
* 计划是否完成
|
||||||
|
*/
|
||||||
|
private boolean finished;
|
||||||
|
/**
|
||||||
|
* 进路是否已经办理
|
||||||
|
*/
|
||||||
|
private boolean routeSet;
|
||||||
|
|
||||||
|
public Detail(VirtualRealityTrain train, Section track, LocalDateTime departureTime) {
|
||||||
|
this.train = train;
|
||||||
|
this.track = track;
|
||||||
|
this.departureTime = departureTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,293 @@
|
||||||
|
package club.joylink.rtss.simulation.cbtc.device.real.udp.thailand.service;
|
||||||
|
|
||||||
|
import static club.joylink.rtss.constants.ProjectDeviceType.SAND_TABLE_RUN_PLAN;
|
||||||
|
|
||||||
|
import club.joylink.rtss.constants.ProjectDeviceType;
|
||||||
|
import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
|
||||||
|
import club.joylink.rtss.simulation.cbtc.ATS.service.AtsTrainLoadService;
|
||||||
|
import club.joylink.rtss.simulation.cbtc.CI.CiApiService;
|
||||||
|
import club.joylink.rtss.simulation.cbtc.Simulation;
|
||||||
|
import club.joylink.rtss.simulation.cbtc.data.SimulationDataRepository;
|
||||||
|
import club.joylink.rtss.simulation.cbtc.data.map.Route;
|
||||||
|
import club.joylink.rtss.simulation.cbtc.data.map.Section;
|
||||||
|
import club.joylink.rtss.simulation.cbtc.data.map.Signal;
|
||||||
|
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.UDPLowConfig;
|
||||||
|
import club.joylink.rtss.simulation.cbtc.device.real.udp.UDPRealDeviceService;
|
||||||
|
import club.joylink.rtss.simulation.cbtc.device.real.udp.thailand.config.ThailandRunPlanConfig;
|
||||||
|
import club.joylink.rtss.simulation.cbtc.device.real.udp.thailand.config.ThailandRunPlanConfig.Detail;
|
||||||
|
import club.joylink.rtss.simulation.cbtc.onboard.ATP.ATPService;
|
||||||
|
import club.joylink.rtss.vo.client.project.thailand.ThailandRunPlanConfigVO.Param;
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class ThailandRunPlanServiceImpl implements UDPRealDeviceService {
|
||||||
|
|
||||||
|
private AtsTrainLoadService atsTrainLoadService;
|
||||||
|
private CiApiService ciApiService;
|
||||||
|
private ATPService atpService;
|
||||||
|
|
||||||
|
public ThailandRunPlanServiceImpl(AtsTrainLoadService atsTrainLoadService,
|
||||||
|
CiApiService ciApiService, ATPService atpService) {
|
||||||
|
this.atsTrainLoadService = atsTrainLoadService;
|
||||||
|
this.ciApiService = ciApiService;
|
||||||
|
this.atpService = atpService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isMatch(UDPLowConfig udpLowConfig) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isMatch(RealDeviceConfig realDevice) {
|
||||||
|
return SAND_TABLE_RUN_PLAN.equals(realDevice.getDeviceType());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run(Simulation simulation, UDPLowConfig udpLowConfig, RealDeviceConfig realDevice) {
|
||||||
|
ThailandRunPlanConfig config = (ThailandRunPlanConfig) realDevice;
|
||||||
|
if (!config.isRunning()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SimulationDataRepository repository = simulation.getRepository();
|
||||||
|
LocalDateTime systemTime = simulation.getSystemTime();
|
||||||
|
List<Detail> previousTrainPlanDetails = new ArrayList<>();
|
||||||
|
boolean planCompleted = true;
|
||||||
|
for (Entry<VirtualRealityTrain, List<Detail>> entry : config.getDetailMap().entrySet()) {
|
||||||
|
VirtualRealityTrain train = entry.getKey();
|
||||||
|
if (!repository.isVrTrainOnline(train.getGroupNumber())) { //列车上线
|
||||||
|
Section firstTrack = entry.getValue().get(0).getTrack();
|
||||||
|
Section secondTrack = entry.getValue().get(1).getTrack();
|
||||||
|
Route[] routes = config.getRoutes(firstTrack.getCode(), secondTrack.getCode());
|
||||||
|
atsTrainLoadService.loadSpareTrain(simulation, train.getGroupNumber(),
|
||||||
|
firstTrack.getCode(), routes[0].isRight());
|
||||||
|
}
|
||||||
|
Section lastArriveTrack = null;
|
||||||
|
for (Detail detail : entry.getValue()) {
|
||||||
|
if (detail.isFinished()) {
|
||||||
|
lastArriveTrack = detail.getTrack();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Section track = detail.getTrack();
|
||||||
|
if (/*train.isStop() && */Objects.equals(train.getHeadPosition().getSection(), track)) {
|
||||||
|
lastArriveTrack = detail.getTrack();
|
||||||
|
detail.setFinished(true);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
planCompleted = false;
|
||||||
|
if (track.isOccupied()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (systemTime.isBefore(detail.getDepartureTime())) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Route[] routes = config.getRoutes(lastArriveTrack.getCode(), track.getCode());
|
||||||
|
if (routes == null) {
|
||||||
|
log.error("缺少[{}-{}]的进路路径", lastArriveTrack.getCode(), track.getCode());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (detail.isRouteSet()) {
|
||||||
|
if (routes[0].isRight() != train.isRight()) {
|
||||||
|
atpService.turnDirectionImmediately(train);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (previousTrainPlanDetails.stream()
|
||||||
|
.filter(pd -> pd.getTrack().equals(track))
|
||||||
|
.anyMatch(pd -> !pd.isFinished())) { //前一辆车到该股道的计划尚未完成
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean routeLocked = true;
|
||||||
|
for (int i = routes.length - 1; i >= 0; i--) {
|
||||||
|
Route route = routes[i];
|
||||||
|
if (!route.isLock()) {
|
||||||
|
routeLocked = false;
|
||||||
|
ciApiService.settingRoute(simulation, route.getCode());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (routeLocked) {
|
||||||
|
detail.setRouteSet(true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
previousTrainPlanDetails = entry.getValue();
|
||||||
|
}
|
||||||
|
if (planCompleted) {
|
||||||
|
planRunning(simulation, config, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(Simulation simulation, UDPLowConfig udpLowConfig, RealDeviceConfig realDevice) {
|
||||||
|
ThailandRunPlanConfig config = (ThailandRunPlanConfig) realDevice;
|
||||||
|
planRunning(simulation, config, false);
|
||||||
|
config.getDetailMap().clear();
|
||||||
|
|
||||||
|
SimulationDataRepository repository = simulation.getRepository();
|
||||||
|
repository.getStandList()
|
||||||
|
.forEach(stand -> {
|
||||||
|
if (stand.getSection().isParkingTrack()) {
|
||||||
|
stand.setParkingTime(0);
|
||||||
|
} else {
|
||||||
|
stand.setParkingTime(config.getParkingDuration());
|
||||||
|
}
|
||||||
|
stand.setParkingAlwaysValid(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
Map<String, Route[]> routeMap = config.getRouteMap();
|
||||||
|
if (CollectionUtils.isEmpty(routeMap)) {
|
||||||
|
List<Section> trackList = config.getConfigVO().getStandTrackList().stream()
|
||||||
|
.map(code -> repository.getByCode(code, Section.class))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
List<Section> potSections = repository.getSectionList().stream()
|
||||||
|
.filter(Section::isParkingTrack)
|
||||||
|
.collect(Collectors.toList()); //筛选出的都是停车场站台轨
|
||||||
|
boolean right = true;
|
||||||
|
for (Section potSection : potSections) {
|
||||||
|
right = fillRoutes(config, potSection, trackList.get(0), right);
|
||||||
|
}
|
||||||
|
for (int i = 0, trackListSize = trackList.size(); i < trackListSize - 1; i++) {
|
||||||
|
right = fillRoutes(config, trackList.get(i), trackList.get(i + 1), right);
|
||||||
|
}
|
||||||
|
for (Section potSection : potSections) {
|
||||||
|
right = fillRoutes(config, trackList.get(trackList.size() - 1), potSection, right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(Simulation simulation, ByteBuf msg) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean fillRoutes(ThailandRunPlanConfig config, Section from, Section to,
|
||||||
|
boolean right) {
|
||||||
|
Route[] routes = findRoutes(from, to, right);
|
||||||
|
if (routes != null) {
|
||||||
|
config.addRoutes(from.getCode(), to.getCode(), routes);
|
||||||
|
return right;
|
||||||
|
}
|
||||||
|
routes = findRoutes(from, to, !right);
|
||||||
|
if (routes == null) {
|
||||||
|
log.error("[{}-{}]的进路找不到", from.debugStr(), to.debugStr());
|
||||||
|
}
|
||||||
|
config.addRoutes(from.getCode(), to.getCode(), routes);
|
||||||
|
return !right;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Route[] findRoutes(Section from, Section to, boolean right) {
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
Signal departureSignal = from.getSignalOf(right);
|
||||||
|
if (departureSignal == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
List<Route> departureRoutes = departureSignal.getRouteList();
|
||||||
|
if (CollectionUtils.isEmpty(departureRoutes)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Route departureRoute = departureRoutes.stream()
|
||||||
|
.filter(Route::isTrainRoute)
|
||||||
|
.filter(route -> {
|
||||||
|
Signal destination = route.getDestination();
|
||||||
|
return destination.isDepartureSignal();
|
||||||
|
}).findFirst().orElse(null);
|
||||||
|
if (departureRoute == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Section interStationSection = departureRoute.getDestination().getSection();
|
||||||
|
Signal receiveSignal = interStationSection.getSignalOf(right);
|
||||||
|
if (receiveSignal == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
List<Route> receiveRoutes = receiveSignal.getRouteList();
|
||||||
|
if (CollectionUtils.isEmpty(receiveRoutes)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Optional<Route> receiveRouteOptional = receiveRoutes.stream()
|
||||||
|
.filter(Route::isTrainRoute)
|
||||||
|
.filter(route -> route.getLastRouteSection().equals(to))
|
||||||
|
.findFirst();
|
||||||
|
return receiveRouteOptional.map(route -> new Route[]{departureRoute, route}).orElse(null);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void runAsPlan(Simulation simulation, List<Param> paramList) {
|
||||||
|
SimulationDataRepository repository = simulation.getRepository();
|
||||||
|
List<String> errMsgList = new ArrayList<>();
|
||||||
|
Set<String> set = new HashSet<>();
|
||||||
|
for (Param param : paramList) {
|
||||||
|
Section section = repository.getByCode(param.getTrackCode(), Section.class);
|
||||||
|
if (!section.isOccupied()) {
|
||||||
|
errMsgList.add(String.format("The track named [%s] is unoccupied", section.getName()));
|
||||||
|
}
|
||||||
|
VirtualRealityTrain train = repository.queryOnlineTrainBy(param.getGroupNumber());
|
||||||
|
if (train != null && !train.getHeadPosition().getSection().equals(section)) {
|
||||||
|
errMsgList.add(String.format(
|
||||||
|
"The train with number [%s] is already in use and is not on the selected section.",
|
||||||
|
param.getGroupNumber()));
|
||||||
|
}
|
||||||
|
if (!set.add(param.getGroupNumber())) {
|
||||||
|
errMsgList.add(String.format("[%s] train number is duplicated", param.getGroupNumber()));
|
||||||
|
}
|
||||||
|
if (!set.add(param.getTrackCode())) {
|
||||||
|
errMsgList.add(String.format("[%s] section is duplicated", section.getName()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertCollectionEmpty(errMsgList,
|
||||||
|
String.join("\n", errMsgList));
|
||||||
|
List<RealDeviceConfig> runPlanList = simulation.getRealDeviceByType(
|
||||||
|
ProjectDeviceType.SAND_TABLE_RUN_PLAN);
|
||||||
|
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertCollectionNotEmpty(runPlanList,
|
||||||
|
"Configuration is missing, unable to set the running plan");
|
||||||
|
|
||||||
|
ThailandRunPlanConfig runPlanConfig = (ThailandRunPlanConfig) runPlanList.get(0);
|
||||||
|
List<Section> standTrackList = runPlanConfig.getConfigVO().getStandTrackList().stream()
|
||||||
|
.map(code -> repository.getByCode(code, Section.class))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
LocalDateTime now = simulation.getSystemTime();
|
||||||
|
Integer departureDuration = runPlanConfig.getDepartureDuration();
|
||||||
|
for (int i = 0, paramListSize = paramList.size(); i < paramListSize; i++) {
|
||||||
|
Param param = paramList.get(i);
|
||||||
|
VirtualRealityTrain train = repository.getVRByCode(param.getGroupNumber(),
|
||||||
|
VirtualRealityTrain.class);
|
||||||
|
Section section = repository.getByCode(param.getTrackCode(), Section.class);
|
||||||
|
LocalDateTime departureTime =
|
||||||
|
departureDuration == null ? now : now.plusSeconds(departureDuration * i);
|
||||||
|
|
||||||
|
List<Detail> detailList = new ArrayList<>();
|
||||||
|
detailList.add(new Detail(train, section, departureTime));
|
||||||
|
standTrackList.forEach(track -> {
|
||||||
|
Detail detail = new Detail(train, track, departureTime);
|
||||||
|
detailList.add(detail);
|
||||||
|
});
|
||||||
|
detailList.add(new Detail(train, section, departureTime));
|
||||||
|
runPlanConfig.getDetailMap().put(train, detailList);
|
||||||
|
}
|
||||||
|
planRunning(simulation, runPlanConfig, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void planRunning(Simulation simulation, ThailandRunPlanConfig config, boolean run) {
|
||||||
|
config.setRunning(run);
|
||||||
|
simulation.getRepository().getStationList().forEach(station -> station.setPlanControl(run));
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,12 +4,15 @@ import club.joylink.rtss.constants.ProjectCode;
|
||||||
import club.joylink.rtss.constants.ProjectDeviceType;
|
import club.joylink.rtss.constants.ProjectDeviceType;
|
||||||
import club.joylink.rtss.simulation.cbtc.Simulation;
|
import club.joylink.rtss.simulation.cbtc.Simulation;
|
||||||
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealitySectionAxleCounter;
|
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.modbustcp.device.RealDeviceConfig;
|
||||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.UDPClientConfig;
|
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.UDPLowConfig;
|
||||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.UDPRealDeviceService;
|
import club.joylink.rtss.simulation.cbtc.device.real.udp.UDPRealDeviceService;
|
||||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.thailand.config.ThailandSectionConfig;
|
import club.joylink.rtss.simulation.cbtc.device.real.udp.thailand.config.ThailandSectionConfig;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
@ -20,21 +23,41 @@ import org.springframework.stereotype.Service;
|
||||||
@Service
|
@Service
|
||||||
public class ThailandSectionServiceImpl implements UDPRealDeviceService {
|
public class ThailandSectionServiceImpl implements UDPRealDeviceService {
|
||||||
|
|
||||||
|
private Map<VirtualRealityTrain, LocalDateTime> map = new HashMap<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isMatch(RealDeviceConfig realDevice) {
|
public boolean isMatch(RealDeviceConfig realDevice) {
|
||||||
return realDevice instanceof UDPClientConfig && ProjectCode.THAILAND_SANDBOX
|
return (realDevice instanceof UDPClientConfig || realDevice instanceof ThailandSectionConfig)
|
||||||
.equals(realDevice.getProject());
|
&& ProjectCode.THAILAND_SANDBOX.equals(realDevice.getProject());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run(Simulation simulation, UDPLowConfig udpLowConfig, RealDeviceConfig realDevice) {
|
public void run(Simulation simulation, UDPLowConfig udpLowConfig, RealDeviceConfig realDevice) {
|
||||||
|
//本地测试模拟计轴占用
|
||||||
|
// List<VirtualRealityTrain> trainList = simulation.getRepository().getOnlineTrainList();
|
||||||
|
// LocalDateTime now = LocalDateTime.now();
|
||||||
|
// for (VirtualRealityTrain train : trainList) {
|
||||||
|
// LocalDateTime time = map.computeIfAbsent(train, K -> now.plusSeconds(7));
|
||||||
|
// Section section = train.getHeadPosition().getSection();
|
||||||
|
// VirtualRealitySectionAxleCounter currentAxle = section.findAxle();
|
||||||
|
// if (!train.isStop() && !now.isBefore(time)) {
|
||||||
|
// Section nextSection = section.getNextRunningSectionOf(train.isRight());
|
||||||
|
// if (nextSection == null) {
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
// VirtualRealitySectionAxleCounter nextAxle = nextSection.findAxle();
|
||||||
|
// if (nextAxle != currentAxle) {
|
||||||
|
// nextAxle.occupied(train.isRight());
|
||||||
|
// currentAxle.setOccupy(false);
|
||||||
|
// }
|
||||||
|
// map.put(train, time.plusSeconds(7));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(Simulation simulation, UDPLowConfig udpLowConfig, RealDeviceConfig realDevice) {
|
public void init(Simulation simulation, UDPLowConfig udpLowConfig, RealDeviceConfig realDevice) {
|
||||||
//沙盘不需要停太长时间
|
map.clear();
|
||||||
simulation.getRepository().getStandList().forEach(stand -> stand.setParkingTime(15));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -87,6 +87,23 @@ public class ThailandTrainServiceImpl implements UDPRealDeviceService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(Simulation simulation, UDPLowConfig udpLowConfig, RealDeviceConfig realDevice) {
|
||||||
|
ThailandTrainConfig config = (ThailandTrainConfig) 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) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新列车位置。
|
* 更新列车位置。
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -103,16 +120,22 @@ public class ThailandTrainServiceImpl implements UDPRealDeviceService {
|
||||||
ThailandSectionConfig sectionConfig = (ThailandSectionConfig) headSection.findAxle()
|
ThailandSectionConfig sectionConfig = (ThailandSectionConfig) headSection.findAxle()
|
||||||
.getRealDevice(); //车头区段的配置
|
.getRealDevice(); //车头区段的配置
|
||||||
if (nextSection != null) {
|
if (nextSection != null) {
|
||||||
VirtualRealitySectionAxleCounter nextAxle = nextSection.findAxle();
|
boolean notSwitchTrack = !nextSection.isSwitchTrack();
|
||||||
if (nextAxle.isOccupy()) {
|
boolean isSwitchRelSections =
|
||||||
train.setHeadPosition(
|
nextSection.isSwitchTrack() && nextSection.getRelSwitch().getSectionsByPosition()
|
||||||
new SectionPosition(nextSection, right ? 0 : nextSection.getMaxOffset()));
|
.contains(nextSection);
|
||||||
config.setTimeOfArriveStopPoint(null);
|
if (notSwitchTrack || isSwitchRelSections) {
|
||||||
sectionConfig = (ThailandSectionConfig) nextAxle.getRealDevice();
|
VirtualRealitySectionAxleCounter nextAxle = nextSection.findAxle();
|
||||||
//更新变量
|
if (nextAxle.isOccupy()) {
|
||||||
previousSection = headSection;
|
train.setHeadPosition(
|
||||||
headSection = train.getHeadPosition().getSection();
|
new SectionPosition(nextSection, right ? 0 : nextSection.getMaxOffset()));
|
||||||
nextSection = null;
|
config.setTimeOfArriveStopPoint(null);
|
||||||
|
sectionConfig = (ThailandSectionConfig) nextAxle.getRealDevice();
|
||||||
|
//更新变量
|
||||||
|
previousSection = headSection;
|
||||||
|
headSection = train.getHeadPosition().getSection();
|
||||||
|
nextSection = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//如果列车车头在进路首个区段,进路开始解锁。
|
//如果列车车头在进路首个区段,进路开始解锁。
|
||||||
|
@ -162,6 +185,12 @@ public class ThailandTrainServiceImpl implements UDPRealDeviceService {
|
||||||
if (config.getManualGear() != null) {
|
if (config.getManualGear() != null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (train.isStop() && headSection.isStandTrack()) {
|
||||||
|
if (headSection.getStandList().stream().anyMatch(stand -> stand.getRemainTime() > 0)) {
|
||||||
|
//此处自行控制停站时间以确保用户的感知和设置的一样
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (stopPosition != null) {
|
if (stopPosition != null) {
|
||||||
Float distance = CalculateService.calculateDistance(train.getHeadPosition(), stopPosition,
|
Float distance = CalculateService.calculateDistance(train.getHeadPosition(), stopPosition,
|
||||||
right, false);
|
right, false);
|
||||||
|
@ -215,23 +244,6 @@ public class ThailandTrainServiceImpl implements UDPRealDeviceService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void init(Simulation simulation, UDPLowConfig udpLowConfig, RealDeviceConfig realDevice) {
|
|
||||||
ThailandTrainConfig config = (ThailandTrainConfig) 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 byte[] buildData(VirtualRealityTrain train, ThailandTrainConfig config) {
|
private byte[] buildData(VirtualRealityTrain train, ThailandTrainConfig config) {
|
||||||
int gear;
|
int gear;
|
||||||
if (train.isStop()) {
|
if (train.isStop()) {
|
||||||
|
|
|
@ -196,11 +196,11 @@ public class SimulationRobotService {
|
||||||
doBreakMax(simulation, train);
|
doBreakMax(simulation, train);
|
||||||
}
|
}
|
||||||
} else if (train.isRobotNeedRun() && (train.isRMMode()
|
} else if (train.isRobotNeedRun() && (train.isRMMode()
|
||||||
|| train.isNRMMode())) { //CM应当根据推荐速度驾驶,待实现
|
|| train.isNRMMode())) { //CM应当根据推荐速度驾驶,待实现
|
||||||
VirtualRealityTrain linkTrain = train.getLinkTrain();
|
VirtualRealityTrain linkTrain = train.getLinkTrain();
|
||||||
if (linkTrain == null) {
|
if (linkTrain == null) {
|
||||||
Optional<SectionPosition> targetPositionOptional = calculateTargetPosition(simulation,
|
Optional<SectionPosition> targetPositionOptional = calculateTargetPosition(simulation,
|
||||||
train);
|
train);
|
||||||
targetPositionOptional.ifPresent(tp -> robotDrive(simulation, driver, train, tp));
|
targetPositionOptional.ifPresent(tp -> robotDrive(simulation, driver, train, tp));
|
||||||
} else {
|
} else {
|
||||||
robotDrive(simulation, driver, train, train.getRobotTargetPosition());
|
robotDrive(simulation, driver, train, train.getRobotTargetPosition());
|
||||||
|
@ -255,8 +255,10 @@ public class SimulationRobotService {
|
||||||
Signal throughSignal = robotDriveParam.getThroughSignal();
|
Signal throughSignal = robotDriveParam.getThroughSignal();
|
||||||
SignalAspect throughAspect = robotDriveParam.getThroughSignalAspect();
|
SignalAspect throughAspect = robotDriveParam.getThroughSignalAspect();
|
||||||
Section section = headPosition.getSection();
|
Section section = headPosition.getSection();
|
||||||
|
boolean parking = train.isParkingAt();
|
||||||
|
|
||||||
if (throughSignal != null && !Objects.equals(section, throughSignal.getSection())) { //当车头与要越过的信号机不在同一区段
|
if (throughSignal != null && !Objects.equals(section,
|
||||||
|
throughSignal.getSection())) { //当车头与要越过的信号机不在同一区段
|
||||||
throughSignal = null;
|
throughSignal = null;
|
||||||
throughAspect = null;
|
throughAspect = null;
|
||||||
robotDriveParam.setThrough(DriveParamVO.NO);
|
robotDriveParam.setThrough(DriveParamVO.NO);
|
||||||
|
@ -268,37 +270,25 @@ public class SimulationRobotService {
|
||||||
// 车头在正常的站台上
|
// 车头在正常的站台上
|
||||||
if (section.isNormalStandTrack() && !section.equals(train.getParkSection())) { //正常站台轨且未在此处停过车
|
if (section.isNormalStandTrack() && !section.equals(train.getParkSection())) { //正常站台轨且未在此处停过车
|
||||||
// 如果计划停车区段为空或者计划停车区段中有包含当前区段
|
// 如果计划停车区段为空或者计划停车区段中有包含当前区段
|
||||||
if (CollectionUtils.isEmpty(plannedParkingSections) || plannedParkingSections.contains(section)) {
|
if (CollectionUtils.isEmpty(plannedParkingSections) || plannedParkingSections.contains(
|
||||||
|
section)) {
|
||||||
SectionPosition stopPosition = section.buildStopPointPosition(right);
|
SectionPosition stopPosition = section.buildStopPointPosition(right);
|
||||||
if (targetPosition == null || stopPosition.isAheadOf(targetPosition, right)) {
|
if (targetPosition == null || stopPosition.isAheadOf(targetPosition, !right)) {
|
||||||
// 如果头部位置偏移小于停车点位置偏移,目标点为当前停车点
|
// 如果头部位置偏移小于停车点位置偏移,目标点为当前停车点
|
||||||
if (headPosition.getOffset() < (section.getStopPointByDirection(right) + SimulationConstants.PARK_POINT_MAX_OFFSET)) { //防止意外开过站后无法发车
|
if (headPosition.getOffset() < (section.getStopPointByDirection(right)
|
||||||
|
+ SimulationConstants.PARK_POINT_MAX_OFFSET)) { //防止意外开过站后无法发车
|
||||||
targetPosition = stopPosition;
|
targetPosition = stopPosition;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 取禁止信号前停车位置与当前目标停车位置中更近的一个
|
targetPosition = updateTargetPositionOfSignal(headPosition, right,
|
||||||
Signal signal = section.getSignalOf(right);
|
throughSignal, throughAspect, section, i, targetPosition, train.isParkingAt());
|
||||||
if (signal != null && !signal.isShunting()) { // 信号机不为调车信号机
|
|
||||||
VirtualRealitySignal vrSignal = signal.getVirtualSignal();
|
|
||||||
SectionPosition signalPosition = signal.getPosition();
|
|
||||||
if (vrSignal != null && (i != 0 || signalPosition.isAheadOf(headPosition, right))) { //有实体信号机且列车未越过信号机
|
|
||||||
if (Objects.equals(vrSignal.getAspect(), signal.getDefaultAspect()) //禁止信号
|
|
||||||
|| Objects.equals(vrSignal.getAspect(), signal.getGuideAspect())) { //引导信号
|
|
||||||
if (!Objects.equals(signal, throughSignal) || !Objects.equals(vrSignal.getAspect(), throughAspect)) {
|
|
||||||
SectionPosition noPassPosition = CalculateService.calculateNextPositionByStartAndLen(signalPosition, !right, 2, true);
|
|
||||||
if (targetPosition == null || noPassPosition.isAheadOf(targetPosition, right)) {
|
|
||||||
targetPosition = noPassPosition;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (targetPosition == null) {
|
if (targetPosition == null) {
|
||||||
if (selectedPosition != null && section.equals(selectedPosition.getSection())) { //不会有比选定位置更靠前的停车点了
|
if (selectedPosition != null && section.equals(
|
||||||
|
selectedPosition.getSection())) { //不会有比选定位置更靠前的停车点了
|
||||||
targetPosition = selectedPosition;
|
targetPosition = selectedPosition;
|
||||||
} else {
|
} else {
|
||||||
Section tempSection = section.findNextRunningSectionBaseRealSwitch(right);
|
Section tempSection = section.findNextRunningSectionBaseRealSwitch(right);
|
||||||
|
@ -310,13 +300,13 @@ public class SimulationRobotService {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (selectedPosition != null) {
|
if (selectedPosition != null) {
|
||||||
if (selectedPosition.isAheadOf(targetPosition, right)) {
|
if (selectedPosition.isAheadOf(targetPosition, !right)) {
|
||||||
targetPosition = selectedPosition;
|
targetPosition = selectedPosition;
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (selectedPosition != null && selectedPosition.isAheadOf(targetPosition, right)) {
|
if (selectedPosition != null && selectedPosition.isAheadOf(targetPosition, !right)) {
|
||||||
targetPosition = selectedPosition;
|
targetPosition = selectedPosition;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
@ -329,7 +319,50 @@ public class SimulationRobotService {
|
||||||
if (targetPosition == null) { //上方的区段遍历完后,即没有找到目标区段,也没有找到轨道尽头
|
if (targetPosition == null) { //上方的区段遍历完后,即没有找到目标区段,也没有找到轨道尽头
|
||||||
targetPosition = new SectionPosition(section, right ? 0 : section.getMaxOffset());
|
targetPosition = new SectionPosition(section, right ? 0 : section.getMaxOffset());
|
||||||
}
|
}
|
||||||
return Optional.ofNullable(targetPosition);
|
return Optional.of(targetPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取以信号机为依据的目标位置
|
||||||
|
*
|
||||||
|
* @param i 区段的索引
|
||||||
|
* @return 如果计算出的targetPosition比参数中的更近,则返回新的,否则返回原来的
|
||||||
|
*/
|
||||||
|
private SectionPosition updateTargetPositionOfSignal(SectionPosition headPosition, boolean right,
|
||||||
|
Signal throughSignal, SignalAspect throughAspect, Section section, int i,
|
||||||
|
SectionPosition targetPosition, boolean parking) {
|
||||||
|
Signal signal = section.getSignalOf(right);
|
||||||
|
if (signal == null || signal.isShunting()) {
|
||||||
|
return targetPosition;
|
||||||
|
}
|
||||||
|
VirtualRealitySignal vrSignal = signal.getVirtualSignal();
|
||||||
|
SectionPosition signalPosition = signal.getPosition();
|
||||||
|
if (vrSignal == null || (i == 0 && headPosition.isAheadOf(signalPosition, right))) {
|
||||||
|
//解释下||后面的条件,如果i!=0,则车头位置一定不可能在信号机前方,即i==0只是为了减少计算,对结果没有影响
|
||||||
|
return targetPosition;
|
||||||
|
}
|
||||||
|
if (targetPosition != null && signalPosition.isAheadOf(targetPosition, right)) {
|
||||||
|
//只要目标位置没有越过信号机,则没必要一定和信号机保持2m距离
|
||||||
|
return targetPosition;
|
||||||
|
}
|
||||||
|
if (!Objects.equals(vrSignal.getAspect(), signal.getDefaultAspect())
|
||||||
|
&& !Objects.equals(vrSignal.getAspect(), signal.getGuideAspect())) { //非禁止/引导信号
|
||||||
|
return targetPosition;
|
||||||
|
}
|
||||||
|
if (Objects.equals(signal, throughSignal)
|
||||||
|
&& Objects.equals(vrSignal.getAspect(), throughAspect)) {
|
||||||
|
return targetPosition;
|
||||||
|
}
|
||||||
|
if (parking && section.equals(headPosition.getSection())) { //避免停站结束后向前移动到信号机前
|
||||||
|
return headPosition;
|
||||||
|
}
|
||||||
|
SectionPosition newPosition = CalculateService.calculateNextPositionByStartAndLen(
|
||||||
|
signalPosition, !right, 2, true);
|
||||||
|
if (targetPosition == null || newPosition.isAheadOf(targetPosition, !right)) {
|
||||||
|
return newPosition;
|
||||||
|
} else {
|
||||||
|
return targetPosition;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void releaseEB(Simulation simulation, SimulationMember driver,
|
private void releaseEB(Simulation simulation, SimulationMember driver,
|
||||||
|
|
|
@ -34,6 +34,7 @@ import club.joylink.rtss.simulation.cbtc.device.real.udp.sr.config.SrSectionConf
|
||||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.sr.config.SrSignalConfig;
|
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.sr.config.SrSwitchConfig;
|
||||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.sr.config.SrTrainConfig;
|
import club.joylink.rtss.simulation.cbtc.device.real.udp.sr.config.SrTrainConfig;
|
||||||
|
import club.joylink.rtss.simulation.cbtc.device.real.udp.thailand.config.ThailandRunPlanConfig;
|
||||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.thailand.config.ThailandSectionConfig;
|
import club.joylink.rtss.simulation.cbtc.device.real.udp.thailand.config.ThailandSectionConfig;
|
||||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.thailand.config.ThailandSignalConfig;
|
import club.joylink.rtss.simulation.cbtc.device.real.udp.thailand.config.ThailandSignalConfig;
|
||||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.thailand.config.ThailandSwitchConfig;
|
import club.joylink.rtss.simulation.cbtc.device.real.udp.thailand.config.ThailandSwitchConfig;
|
||||||
|
@ -176,6 +177,9 @@ public class ProjectDeviceVO {
|
||||||
case TRAIN:
|
case TRAIN:
|
||||||
list.add(new ThailandTrainConfig(deviceVO));
|
list.add(new ThailandTrainConfig(deviceVO));
|
||||||
break;
|
break;
|
||||||
|
case SAND_TABLE_RUN_PLAN:
|
||||||
|
list.add(new ThailandRunPlanConfig(deviceVO));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return list;
|
return list;
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
package club.joylink.rtss.vo.client.project.thailand;
|
||||||
|
|
||||||
|
import club.joylink.rtss.vo.client.project.RealConfigVO;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class ThailandRunPlanConfigVO extends RealConfigVO {
|
||||||
|
|
||||||
|
private List<String> standTrackList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 停站时长/s
|
||||||
|
*/
|
||||||
|
private int parkingDuration = 15;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发车间隔/s。多辆车从停车场发车的间隔时长
|
||||||
|
*/
|
||||||
|
private Integer departureDuration;
|
||||||
|
|
||||||
|
public ThailandRunPlanConfigVO() {
|
||||||
|
super(null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ThailandRunPlanConfigVO(Integer addr, Integer quantity) {
|
||||||
|
super(addr, quantity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String findDeviceCode() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
public static class Detail {
|
||||||
|
|
||||||
|
private String groupNumber;
|
||||||
|
private String stationName;
|
||||||
|
private String trackName;
|
||||||
|
private Integer parkingDuration;
|
||||||
|
private boolean finished;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class Param {
|
||||||
|
|
||||||
|
@NotBlank(message = "groupNumber cannot be null")
|
||||||
|
private String groupNumber;
|
||||||
|
@NotBlank(message = "track cannot be null")
|
||||||
|
private String trackCode;
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,50 +3,49 @@ package club.joylink.rtss.websocket.interceptor;
|
||||||
import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
|
import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
|
||||||
import club.joylink.rtss.services.LoginSessionManager;
|
import club.joylink.rtss.services.LoginSessionManager;
|
||||||
import club.joylink.rtss.vo.LoginUserInfoVO;
|
import club.joylink.rtss.vo.LoginUserInfoVO;
|
||||||
|
import java.util.Map;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.server.ServerHttpRequest;
|
import org.springframework.http.server.ServerHttpRequest;
|
||||||
import org.springframework.http.server.ServerHttpResponse;
|
import org.springframework.http.server.ServerHttpResponse;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.web.socket.WebSocketHandler;
|
import org.springframework.web.socket.WebSocketHandler;
|
||||||
import org.springframework.web.socket.server.HandshakeInterceptor;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class SessionAuthHandshakeInterceptor extends BaseInterceptor {
|
public class SessionAuthHandshakeInterceptor extends BaseInterceptor {
|
||||||
private static final String Token_Key = "token";
|
|
||||||
public static final String ATTR_USER_KEY = "user";
|
|
||||||
private LoginSessionManager loginSessionManager;
|
|
||||||
|
|
||||||
public SessionAuthHandshakeInterceptor(LoginSessionManager loginSessionManager) {
|
private static final String Token_Key = "token";
|
||||||
this.loginSessionManager = loginSessionManager;
|
public static final String ATTR_USER_KEY = "user";
|
||||||
|
private LoginSessionManager loginSessionManager;
|
||||||
|
|
||||||
|
public SessionAuthHandshakeInterceptor(LoginSessionManager loginSessionManager) {
|
||||||
|
this.loginSessionManager = loginSessionManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response,
|
||||||
|
WebSocketHandler wsHandler,
|
||||||
|
Map<String, Object> attributes) throws Exception {
|
||||||
|
try {
|
||||||
|
LoginUserInfoVO loginUserInfoVO = getLoginUser(request);
|
||||||
|
attributes.put(ATTR_USER_KEY, loginUserInfoVO);
|
||||||
|
return true;
|
||||||
|
} catch (Throwable e) {
|
||||||
|
log.error("未登录或登陆已过期");
|
||||||
}
|
}
|
||||||
|
response.setStatusCode(HttpStatus.UNAUTHORIZED);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
private LoginUserInfoVO getLoginUser(ServerHttpRequest request) {
|
||||||
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
|
|
||||||
Map<String, Object> attributes) throws Exception {
|
|
||||||
try {
|
|
||||||
LoginUserInfoVO loginUserInfoVO = getLoginUser(request);
|
|
||||||
attributes.put(ATTR_USER_KEY, loginUserInfoVO);
|
|
||||||
return true;
|
|
||||||
} catch (Throwable e) {
|
|
||||||
log.error("未登录或登陆已过期", e);
|
|
||||||
}
|
|
||||||
response.setStatusCode(HttpStatus.UNAUTHORIZED);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private LoginUserInfoVO getLoginUser(ServerHttpRequest request) {
|
|
||||||
// String query = request.getURI().getQuery();
|
// String query = request.getURI().getQuery();
|
||||||
Map<String, String> map = this.findQueryParams(request);
|
Map<String, String> map = this.findQueryParams(request);
|
||||||
log.info(String.format("webSocket handshake query: [%s]", map));
|
log.info(String.format("webSocket handshake query: [%s]", map));
|
||||||
BusinessExceptionAssertEnum.NOT_LOGIN.assertTrue(StringUtils.hasText(map.get(Token_Key)));
|
BusinessExceptionAssertEnum.NOT_LOGIN.assertTrue(StringUtils.hasText(map.get(Token_Key)));
|
||||||
return this.loginSessionManager.getLoginInfoByToken(map.get(Token_Key));
|
return this.loginSessionManager.getLoginInfoByToken(map.get(Token_Key));
|
||||||
// AccountVO accountVO = loginInfoVO.getAccountVO();
|
// AccountVO accountVO = loginInfoVO.getAccountVO();
|
||||||
// BusinessExceptionAssertEnum.NOT_LOGIN.assertNotNull(accountVO);
|
// BusinessExceptionAssertEnum.NOT_LOGIN.assertNotNull(accountVO);
|
||||||
// return accountVO;
|
// return accountVO;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue