[重写]计轴的组件、实体、系统、预复位/复位逻辑

This commit is contained in:
thesai 2024-07-31 17:08:53 +08:00
parent 8c6bfb2aee
commit 3182e867c1
16 changed files with 694 additions and 586 deletions

View File

@ -1,113 +1,134 @@
package component
import (
"fmt"
"joylink.club/ecs"
)
//计轴设备,管理联锁集中站内的所有计轴区段
//计轴直接复位:计轴的轮对计数清零,区段转换为空闲状态
//计轴预复位:将计轴的轮对计数清零,但是区段不会立即变成空闲区段,而是处于一种“占用”状态,在压道车通过之后确认区段空闲且计轴正常后,区段转换为空闲状态
//
//当CI系统给计轴设备发送计轴直接复零/预复零命令时,连续发送一定时间(具体发送时间调试后确定)的复零/预复零命令。
//当RACRJORJT任意一个不为0时终止发送复零/预复零命令。
import "joylink.club/ecs"
var (
PhysicalSectionCircuitType = ecs.NewComponentType[PhysicalSectionCircuit]()
AxleSectionTag = ecs.NewTag()
AxleSectionCircuitType = ecs.NewComponentType[AxleSectionCircuit]()
AxleManagerType = ecs.NewComponentType[AxleManager]()
)
var AxleSectionForceOccupied = ecs.NewTag() //区段强制占用(故障占用)
type PhysicalSectionCircuit struct {
// AxleManager 计轴管理器。我自己起的名字,计轴逻辑的载体
type AxleManager struct {
Count int //轴数(简化版)。目前此轴数计数只与区段上有无列车有关,故障占用等状态不会影响此计数
Occupied bool //占用
PDRST bool //预复位
//RAC bool //计轴复位反馈。主要指计轴设备发送给CI系统的直接复零/预复零命令反馈表示计轴设备已收到CI系统发送的直接复零/预复零命令。
//RJO bool //运营原因拒绝直接复位/预复位。如区段空闲时下发复位命令;或车轮压住传感器时收到复位命令。
//RJT bool //技术原因拒绝直接复位/预复位。主要指计轴相关设备故障时收到复位命令如车轮传感器的导线断开、AEB之间的通信故障等。
}
// AxleSectionCircuit 计轴区段电路
type AxleSectionCircuit struct {
GJ *ecs.Entry
}
// PhysicalSectionState 物理区段
type PhysicalSectionState struct {
//true-占用false-出清
Occ bool
}
// AxlePhysicalSection 计轴物理区段
type AxlePhysicalSection struct {
//计轴区段内车轴数
Count int
//记录Count变化波形
countPulse uint8
}
type AxleDeviceRuntime struct {
//true-计轴复位反馈,表示计轴设备已收到CI系统发送的直接复零/预复零命令。
Rac bool
//true-运营原因拒绝计轴复位,如区段空闲时下发复位命令;或车轮压住传感器时收到复位命令。
Rjo bool
//true-技术原因拒绝计轴复位,主要指计轴相关设备故障时收到复位命令如车轮传感器的导线断开、AEB之间的通信故障等
Rjt bool
//true-计轴直接复位
//计轴的轮对计数清零,区段转换为空闲状态
Drst bool
//true-计轴预复位
//将计轴的轮对计数清零,但是区段不会立即变成空闲区段,而是处于一种“占用”状态,在压道车通过之后确认区段空闲且计轴正常后,区段转换为空闲状态
Pdrst bool
//true-计轴系统正在执行直接预复位操作
DoingPdrst bool
}
func NewAxleDeviceRuntime() *AxleDeviceRuntime {
return &AxleDeviceRuntime{}
}
// AxleManageDevice 计轴管理设备
type AxleManageDevice struct {
CentralizedStation string //所属集中站编号code
Adrs map[string]*AxleDeviceRuntime //key-sectionId
}
func (d *AxleManageDevice) FindAdr(sectionId string) *AxleDeviceRuntime {
return d.Adrs[sectionId]
}
func NewAxleManageDevice(centralizedStation string) *AxleManageDevice {
return &AxleManageDevice{CentralizedStation: centralizedStation, Adrs: make(map[string]*AxleDeviceRuntime)}
}
var (
PhysicalSectionStateType = ecs.NewComponentType[PhysicalSectionState]()
AxlePhysicalSectionType = ecs.NewComponentType[AxlePhysicalSection]()
AxleSectionFaultTag = ecs.NewTag()
AxleManageDeviceType = ecs.NewComponentType[AxleManageDevice]()
)
/////////////////////////////AxlePhysicalSection/////////////////////////////////
func NewAxlePhysicalSection() *AxlePhysicalSection {
return &AxlePhysicalSection{Count: 0, countPulse: 0}
}
func (c *AxlePhysicalSection) UpdateCount(count int) {
cp := to1(c.Count)
np := to1(count)
////计轴设备,管理联锁集中站内的所有计轴区段
////计轴直接复位:计轴的轮对计数清零,区段转换为空闲状态
////计轴预复位:将计轴的轮对计数清零,但是区段不会立即变成空闲区段,而是处于一种“占用”状态,在压道车通过之后确认区段空闲且计轴正常后,区段转换为空闲状态
////
////当CI系统给计轴设备发送计轴直接复零/预复零命令时,连续发送一定时间(具体发送时间调试后确定)的复零/预复零命令。
////当RACRJORJT任意一个不为0时终止发送复零/预复零命令。
//
if cp != np {
c.countPulse <<= 1
if np > 0 {
c.countPulse |= np
}
}
c.Count = count
}
func (c *AxlePhysicalSection) ResetCountPulse() {
c.countPulse = 0x00
}
func (c *AxlePhysicalSection) ShowCountWave() string {
return fmt.Sprintf("%08b", c.countPulse)
}
// IsCount010Pulse true-车进入计轴区段后出清计轴区段
func (c *AxlePhysicalSection) IsCount010Pulse() bool {
return c.countPulse&0x01 == 0 && c.countPulse&0x02 > 0 && c.countPulse&0x04 == 0
}
// 归1
func to1(c int) uint8 {
if c > 0 {
return 0x01
} else {
return 0x00
}
}
//var (
// PhysicalSectionCircuitType = ecs.NewComponentType[PhysicalSectionCircuit]()
//)
//
//type PhysicalSectionCircuit struct {
// GJ *ecs.Entry
//}
//
//// PhysicalSectionState 物理区段
//type PhysicalSectionState struct {
// //true-占用false-出清
// Occ bool
//}
//
//// AxlePhysicalSection 计轴物理区段
//type AxlePhysicalSection struct {
// //计轴区段内车轴数
// Count int
// //记录Count变化波形
// countPulse uint8
//}
//type AxleDeviceRuntime struct {
// //true-计轴复位反馈,表示计轴设备已收到CI系统发送的直接复零/预复零命令。
// RAC bool
// //true-运营原因拒绝计轴复位,如区段空闲时下发复位命令;或车轮压住传感器时收到复位命令。
// RJO bool
// //true-技术原因拒绝计轴复位,主要指计轴相关设备故障时收到复位命令如车轮传感器的导线断开、AEB之间的通信故障等
// RJT bool
// //true-计轴直接复位
// //计轴的轮对计数清零,区段转换为空闲状态
// Drst bool
// //true-计轴预复位
// //将计轴的轮对计数清零,但是区段不会立即变成空闲区段,而是处于一种“占用”状态,在压道车通过之后确认区段空闲且计轴正常后,区段转换为空闲状态
// PDRST bool
// //true-计轴系统正在执行直接预复位操作
// DoingPdrst bool
//}
//
//func NewAxleDeviceRuntime() *AxleDeviceRuntime {
// return &AxleDeviceRuntime{}
//}
//
//// AxleManageDevice 计轴管理设备
//type AxleManageDevice struct {
// CentralizedStation string //所属集中站编号code
// Adrs map[string]*AxleDeviceRuntime //key-sectionId
//}
//
//func (d *AxleManageDevice) FindAdr(sectionId string) *AxleDeviceRuntime {
// return d.Adrs[sectionId]
//}
//func NewAxleManageDevice(centralizedStation string) *AxleManageDevice {
// return &AxleManageDevice{CentralizedStation: centralizedStation, Adrs: make(map[string]*AxleDeviceRuntime)}
//}
//
//var (
// PhysicalSectionStateType = ecs.NewComponentType[PhysicalSectionState]()
// AxlePhysicalSectionType = ecs.NewComponentType[AxlePhysicalSection]()
// AxleSectionFaultTag = ecs.NewTag()
// AxleManageDeviceType = ecs.NewComponentType[AxleManageDevice]()
//)
//
///////////////////////////////AxlePhysicalSection/////////////////////////////////
//
//func NewAxlePhysicalSection() *AxlePhysicalSection {
// return &AxlePhysicalSection{Count: 0, countPulse: 0}
//}
//func (c *AxlePhysicalSection) UpdateCount(count int) {
// cp := to1(c.Count)
// np := to1(count)
// //
// if cp != np {
// c.countPulse <<= 1
// if np > 0 {
// c.countPulse |= np
// }
// }
// c.Count = count
//}
//func (c *AxlePhysicalSection) ResetCountPulse() {
// c.countPulse = 0x00
//}
//func (c *AxlePhysicalSection) ShowCountWave() string {
// return fmt.Sprintf("%08b", c.countPulse)
//}
//
//// IsCount010Pulse true-车进入计轴区段后出清计轴区段
//func (c *AxlePhysicalSection) IsCount010Pulse() bool {
// return c.countPulse&0x01 == 0 && c.countPulse&0x02 > 0 && c.countPulse&0x04 == 0
//}
//
//// 归1
//func to1(c int) uint8 {
// if c > 0 {
// return 0x01
// } else {
// return 0x00
// }
//}

View File

@ -12,6 +12,7 @@ type TrainPositionInfo struct {
Up bool
//列车长度 mm
Len int64
//列车所在轨道link
HeadLink string
//列车所在link偏移量mm
@ -20,6 +21,15 @@ type TrainPositionInfo struct {
TailLink string
//列车所在link偏移量mm
TailLinkOffset int64
//车头所在物理区段
HeadSectionId string
//车头所在物理区段偏移量
HeadSectionOffset uint32
//车尾所在物理区段
TailSectionId string
//车尾所在物理区段偏移量
TailSectionOffset uint32
}
func (t *TrainPositionInfo) ToString() string {

View File

@ -1,75 +1,34 @@
package entity
import (
"fmt"
"joylink.club/ecs"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/repository"
"strings"
"unsafe"
)
func newAxleManageDevice(w ecs.World, data *component.WorldData, centralizedStation string) *ecs.Entry {
entry := w.Entry(w.Create(component.AxleManageDeviceType))
component.AxleManageDeviceType.Set(entry, component.NewAxleManageDevice(centralizedStation))
data.AxleManageDeviceEntities = append(data.AxleManageDeviceEntities, entry)
return entry
}
var AxleSectionBaseComponentTypes = []ecs.IComponentType{component.UidType, component.AxleSectionTag, component.AxleManagerType}
// LoadAxlePhysicalSections 加载计轴区段
func LoadAxlePhysicalSections(w ecs.World) error {
data := GetWorldData(w)
sections := data.Repo.PhysicalSectionList()
wd := GetWorldData(w)
sections := wd.Repo.PhysicalSectionList()
for _, section := range sections {
if is, se := section.IsAxleSection(); se == nil && is {
if len(strings.TrimSpace(section.CentralizedStation())) == 0 {
return fmt.Errorf("区段[%s]未设置所属集中站", section.Id())
}
amdEntry := FindAxleManageDevice(data, section.CentralizedStation())
if amdEntry == nil {
amdEntry = newAxleManageDevice(w, data, section.CentralizedStation())
}
amd := component.AxleManageDeviceType.Get(amdEntry)
//
createAxleSectionEntity(w, section, data)
//
amd.Adrs[section.Id()] = component.NewAxleDeviceRuntime()
}
}
return nil
}
func FindAxleManageDevice(data *component.WorldData, centralizedStation string) *ecs.Entry {
for _, entry := range data.AxleManageDeviceEntities {
amd := component.AxleManageDeviceType.Get(entry)
if amd != nil && amd.CentralizedStation == centralizedStation {
return entry
}
}
return nil
}
// 计轴区段实体
func createAxleSectionEntity(w ecs.World, axleSection *repository.PhysicalSection, worldData *component.WorldData) *ecs.Entry {
uid := axleSection.Id()
entry, ok := worldData.EntityMap[uid]
if !ok {
entry = w.Entry(w.Create(component.UidType, component.PhysicalSectionStateType, component.AxlePhysicalSectionType))
//
component.UidType.SetValue(entry, component.Uid{Id: uid})
component.PhysicalSectionStateType.Set(entry, &component.PhysicalSectionState{Occ: false})
component.AxlePhysicalSectionType.Set(entry, component.NewAxlePhysicalSection())
//
for _, group := range axleSection.ComponentGroups() {
if is, err := section.IsAxleSection(); err == nil && is {
entry := w.Entry(w.Create(AxleSectionBaseComponentTypes...))
component.UidType.SetValue(entry, component.Uid{Id: section.Id()})
for _, group := range section.ComponentGroups() {
for _, ec := range group.Components() {
if ec.Code() == "GJ" {
relay := ec.(*repository.Relay)
gjEntry := NewRelayEntity(w, relay, worldData.EntityMap)
circuit := &component.PhysicalSectionCircuit{GJ: gjEntry}
entry.AddComponent(component.PhysicalSectionCircuitType, unsafe.Pointer(circuit))
gjEntry := NewRelayEntity(w, relay, wd.EntityMap)
circuit := &component.AxleSectionCircuit{GJ: gjEntry}
entry.AddComponent(component.AxleSectionCircuitType, unsafe.Pointer(circuit))
}
}
}
worldData.EntityMap[uid] = entry
wd.EntityMap[section.Id()] = entry
}
return entry
}
return nil
}

View File

@ -47,9 +47,10 @@ func newBaliseEntity(w ecs.World, td *repository.Transponder, worldData *compone
if proto.Transponder_IB == td.BaliseType() || proto.Transponder_VB == td.BaliseType() {
entry.AddComponent(component.BaliseVariableTelegramType)
}
linkPosition := td.LinkPosition()
component.LinkPositionType.SetValue(entry, component_data.LinkPosition{
LinkId: td.LinkPosition().Link().Id(),
Offset: td.LinkPosition().Offset(),
LinkId: linkPosition.Link().Id(),
Offset: linkPosition.Offset(),
})
component.KmType.Set(entry, td.Km())
worldData.EntityMap[uid] = entry

120
fi/axle_section.go Normal file
View File

@ -0,0 +1,120 @@
package fi
import (
"fmt"
"joylink.club/ecs"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/entity"
"strings"
)
// AxleSectionFaultOccDrive 区段故障占用设置
func AxleSectionFaultOccDrive(w ecs.World, sectionId string, set bool) error {
r := <-ecs.Request[ecs.EmptyType](w, func() ecs.Result[ecs.EmptyType] {
wd := entity.GetWorldData(w)
sectionModel := wd.Repo.FindPhysicalSection(sectionId)
if sectionModel == nil {
return ecs.NewErrResult(fmt.Errorf("区段模型[%s]不存实体", sectionId))
}
//
sectionEntry := wd.EntityMap[sectionId]
if sectionEntry == nil {
return ecs.NewErrResult(fmt.Errorf("区段[%s]实体不存在", sectionId))
}
if set { //计轴故障设置
if !sectionEntry.HasComponent(component.AxleSectionForceOccupied) {
sectionEntry.AddComponent(component.AxleSectionForceOccupied)
}
} else { //计轴故障取消
if sectionEntry.HasComponent(component.AxleSectionForceOccupied) {
sectionEntry.RemoveComponent(component.AxleSectionForceOccupied)
}
}
return ecs.NewOkEmptyResult()
})
return r.Err
}
// AxleSectionDrstDrive 直接复位
func AxleSectionDrstDrive(w ecs.World, sectionId string) (*AxleSectionState, error) {
r := <-ecs.Request[*AxleSectionState](w, func() ecs.Result[*AxleSectionState] {
wd := entity.GetWorldData(w)
entry := wd.EntityMap[sectionId]
if entry == nil {
return ecs.NewResult[*AxleSectionState](nil, fmt.Errorf("区段[%s]实体不存在", sectionId))
}
axleManager := component.AxleManagerType.Get(entry)
state := &AxleSectionState{}
if axleManager.Count != 0 {
state.Rjo = true
} else {
entry.RemoveComponent(component.AxleSectionForceOccupied)
state.Rac = true
}
return ecs.NewOkResult(state)
})
return r.Val, r.Err
}
// AxleSectionPdrstDrive 预复位
func AxleSectionPdrstDrive(w ecs.World, sectionId string) (*AxleSectionState, error) {
r := <-ecs.Request[*AxleSectionState](w, func() ecs.Result[*AxleSectionState] {
wd := entity.GetWorldData(w)
entry := wd.EntityMap[sectionId]
if entry == nil {
return ecs.NewResult[*AxleSectionState](nil, fmt.Errorf("区段[%s]实体不存在", sectionId))
}
axleManager := component.AxleManagerType.Get(entry)
state := &AxleSectionState{}
if axleManager.Count != 0 {
state.Rjo = true
} else {
state.Rac = true
}
return ecs.NewOkResult(state)
})
return r.Val, r.Err
}
// FindAxleSectionsStatus 获取计轴区段的相关状态
func FindAxleSectionsStatus(w ecs.World, sectionIds []string) ([]*AxleSectionState, error) {
r := <-ecs.Request[[]*AxleSectionState](w, func() ecs.Result[[]*AxleSectionState] {
wd := entity.GetWorldData(w)
var msg []*AxleSectionState
var esb = strings.Builder{} //收集未找到的区段的id
for _, sectionId := range sectionIds {
entry := wd.EntityMap[sectionId]
if entry == nil {
esb.WriteString(fmt.Sprintf("%s,", sectionId))
continue
}
axleManager := component.AxleManagerType.Get(entry)
msg = append(msg, &AxleSectionState{
Id: sectionId,
Clr: !axleManager.Occupied,
Occ: axleManager.Occupied,
})
}
if esb.Len() > 0 {
return ecs.NewResult(msg, fmt.Errorf("区段非计轴区段或计轴区段状态不存在:[%s]", esb.String()))
} else {
return ecs.NewResult(msg, nil)
}
})
return r.Val, r.Err
}
type AxleSectionState struct {
//uid
Id string
//0-bit7 计轴出清
Clr bool
//0-bit6 计轴占用
Occ bool
//1-bit6 计轴复位反馈
Rac bool
//1-bit5 运营原因拒绝计轴复位
Rjo bool
//1-bit4 技术原因拒绝计轴复位
Rjt bool
}

View File

@ -1,239 +1,173 @@
package fi
import (
"fmt"
"strings"
"joylink.club/ecs"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/entity"
)
// AxleSectionDrstDrive 计轴直接复位操作
//
// set : true-设置false-取消
func AxleSectionDrstDrive(w ecs.World, sectionId string, set bool) error {
r := <-ecs.Request[ecs.EmptyType](w, func() ecs.Result[ecs.EmptyType] {
wd := entity.GetWorldData(w)
//import (
// "fmt"
// "strings"
//
sectionModel := wd.Repo.FindPhysicalSection(sectionId)
if sectionModel == nil {
return ecs.NewErrResult(fmt.Errorf("区段模型[%s]不存实体", sectionId))
}
// if set {
// axleSectionEntry := wd.EntityMap[sectionId]
// if !axleSectionEntry.HasComponent(component.AxleSectionFaultTag) {
// return ecs.NewErrResult(fmt.Errorf("区段[%s]非故障占用,无法进行复位操作", sectionId))
// "joylink.club/ecs"
// "joylink.club/rtsssimulation/component"
// "joylink.club/rtsssimulation/entity"
//)
//
//// AxleSectionDrstDrive 计轴直接复位操作
////
//// set : true-设置false-取消
//func AxleSectionDrstDrive(w ecs.World, sectionId string, set bool) error {
// r := <-ecs.Request[ecs.EmptyType](w, func() ecs.Result[ecs.EmptyType] {
// wd := entity.GetWorldData(w)
// //
// sectionModel := wd.Repo.FindPhysicalSection(sectionId)
// if sectionModel == nil {
// return ecs.NewErrResult(fmt.Errorf("区段模型[%s]不存实体", sectionId))
// }
// // if set {
// // axleSectionEntry := wd.EntityMap[sectionId]
// // if !axleSectionEntry.HasComponent(component.AxleSectionFaultTag) {
// // return ecs.NewErrResult(fmt.Errorf("区段[%s]非故障占用,无法进行复位操作", sectionId))
// // }
// // }
// //
// faDcAxleDeviceEntry := entity.FindAxleManageDevice(wd, sectionModel.CentralizedStation())
//
// if faDcAxleDeviceEntry == nil {
// return ecs.NewErrResult(fmt.Errorf("计轴管理设备[%s]实体不存在", sectionModel.CentralizedStation()))
// }
// faDcAxleDevice := component.AxleManageDeviceType.Get(faDcAxleDeviceEntry)
// axleRuntime := faDcAxleDevice.FindAdr(sectionId)
// if axleRuntime == nil {
// return ecs.NewErrResult(fmt.Errorf("计轴管理设备[%s]中不存在区段[%s]的计轴设备", sectionModel.CentralizedStation(), sectionId))
// }
// axleRuntime.Drst = set
// //
// return ecs.NewOkEmptyResult()
// })
// return r.Err
//}
//
faDcAxleDeviceEntry := entity.FindAxleManageDevice(wd, sectionModel.CentralizedStation())
if faDcAxleDeviceEntry == nil {
return ecs.NewErrResult(fmt.Errorf("计轴管理设备[%s]实体不存在", sectionModel.CentralizedStation()))
}
faDcAxleDevice := component.AxleManageDeviceType.Get(faDcAxleDeviceEntry)
axleRuntime := faDcAxleDevice.FindAdr(sectionId)
if axleRuntime == nil {
return ecs.NewErrResult(fmt.Errorf("计轴管理设备[%s]中不存在区段[%s]的计轴设备", sectionModel.CentralizedStation(), sectionId))
}
axleRuntime.Drst = set
//
return ecs.NewOkEmptyResult()
})
return r.Err
}
// AxleSectionPdrstDrive 计轴预复位操作
//
// set : true-设置false-取消
func AxleSectionPdrstDrive(w ecs.World, sectionId string, set bool) error {
r := <-ecs.Request[ecs.EmptyType](w, func() ecs.Result[ecs.EmptyType] {
wd := entity.GetWorldData(w)
sectionModel := wd.Repo.FindPhysicalSection(sectionId)
if sectionModel == nil {
return ecs.NewErrResult(fmt.Errorf("区段模型[%s]不存实体", sectionId))
}
// if set {
// axleSectionEntry := wd.EntityMap[sectionId]
// if !axleSectionEntry.HasComponent(component.AxleSectionFaultTag) {
// return ecs.NewErrResult(fmt.Errorf("区段[%s]非故障占用,无法进行复位操作", sectionId))
//// AxleSectionPdrstDrive 计轴预复位操作
////
//// set : true-设置false-取消
//func AxleSectionPdrstDrive(w ecs.World, sectionId string, set bool) error {
// r := <-ecs.Request[ecs.EmptyType](w, func() ecs.Result[ecs.EmptyType] {
// wd := entity.GetWorldData(w)
// sectionModel := wd.Repo.FindPhysicalSection(sectionId)
// if sectionModel == nil {
// return ecs.NewErrResult(fmt.Errorf("区段模型[%s]不存实体", sectionId))
// }
// // if set {
// // axleSectionEntry := wd.EntityMap[sectionId]
// // if !axleSectionEntry.HasComponent(component.AxleSectionFaultTag) {
// // return ecs.NewErrResult(fmt.Errorf("区段[%s]非故障占用,无法进行复位操作", sectionId))
// // }
// // }
// //
// faDcAxleDeviceEntry := entity.FindAxleManageDevice(wd, sectionModel.CentralizedStation())
//
// if faDcAxleDeviceEntry == nil {
// return ecs.NewErrResult(fmt.Errorf("计轴管理设备[%s]实体不存在", sectionModel.CentralizedStation()))
// }
// faDcAxleDevice := component.AxleManageDeviceType.Get(faDcAxleDeviceEntry)
// axleRuntime, ok := faDcAxleDevice.Adrs[sectionId]
// if !ok {
// return ecs.NewErrResult(fmt.Errorf("计轴管理设备[%s]中不存在区段[%s]的计轴设备", sectionModel.CentralizedStation(), sectionId))
// }
// axleRuntime.Pdrst = set
// //
// return ecs.NewOkEmptyResult()
// })
// return r.Err
//}
//
faDcAxleDeviceEntry := entity.FindAxleManageDevice(wd, sectionModel.CentralizedStation())
if faDcAxleDeviceEntry == nil {
return ecs.NewErrResult(fmt.Errorf("计轴管理设备[%s]实体不存在", sectionModel.CentralizedStation()))
}
faDcAxleDevice := component.AxleManageDeviceType.Get(faDcAxleDeviceEntry)
axleRuntime, ok := faDcAxleDevice.Adrs[sectionId]
if !ok {
return ecs.NewErrResult(fmt.Errorf("计轴管理设备[%s]中不存在区段[%s]的计轴设备", sectionModel.CentralizedStation(), sectionId))
}
axleRuntime.Pdrst = set
//// AxleSectionFaultOccDrive 区段故障占用设置
////
//// set : true - 设置故障占用false - 取消故障占用
//func AxleSectionFaultOccDrive(w ecs.World, sectionId string, set bool) error {
// r := <-ecs.Request[ecs.EmptyType](w, func() ecs.Result[ecs.EmptyType] {
// wd := entity.GetWorldData(w)
// sectionModel := wd.Repo.FindPhysicalSection(sectionId)
// if sectionModel == nil {
// return ecs.NewErrResult(fmt.Errorf("区段模型[%s]不存实体", sectionId))
// }
// //
// sectionEntry := wd.EntityMap[sectionId]
// if sectionEntry == nil {
// return ecs.NewErrResult(fmt.Errorf("区段[%s]实体不存在", sectionId))
// }
// if set { //计轴故障设置
// if !sectionEntry.HasComponent(component.AxleSectionFaultTag) {
// sectionEntry.AddComponent(component.AxleSectionFaultTag)
// }
// } else { //计轴故障取消
// if sectionEntry.HasComponent(component.AxleSectionFaultTag) {
// sectionEntry.RemoveComponent(component.AxleSectionFaultTag)
// }
// }
// //
// return ecs.NewOkEmptyResult()
// })
// return r.Err
//}
//
return ecs.NewOkEmptyResult()
})
return r.Err
}
// AxleSectionFaultOccDrive 区段故障占用设置
//// FindAxleSectionsStatus 获取计轴区段的相关状态
//func FindAxleSectionsStatus(w ecs.World, sectionIds []string) ([]*AxleSectionState, error) {
// r := <-ecs.Request[[]*AxleSectionState](w, func() ecs.Result[[]*AxleSectionState] {
// wd := entity.GetWorldData(w)
// var msg []*AxleSectionState
// var esb = strings.Builder{} //收集未找到的区段的id
// for _, sectionId := range sectionIds {
// find := false
// sectionModel := wd.Repo.FindPhysicalSection(sectionId)
// if sectionModel != nil {
// faDcAxleDeviceEntry := entity.FindAxleManageDevice(wd, sectionModel.CentralizedStation())
// if faDcAxleDeviceEntry != nil {
// faDcAxleDevice := component.AxleManageDeviceType.Get(faDcAxleDeviceEntry)
// axleDevice := faDcAxleDevice.FindAdr(sectionId)
// if axleDevice != nil {
// sectionEntry, _ := entity.GetEntityByUid(w, sectionId)
// if sectionEntry != nil {
// if sectionEntry.HasComponent(component.AxlePhysicalSectionType) { //计轴物理区段实体
// as := &AxleSectionState{}
// state := component.PhysicalSectionStateType.Get(sectionEntry)
// as.Id = component.UidType.Get(sectionEntry).Id
// as.Clr = !state.Occ
// as.Occ = state.Occ
// as.Rac = axleDevice.Rac
// as.Rjt = axleDevice.Rjt
// as.Rjo = axleDevice.Rjo
// //
// msg = append(msg, as)
// find = true
// }
// }
// }
// }
// }
// //
// if !find {
// esb.WriteString(fmt.Sprintf("%s,", sectionId))
// }
// } //for
// if esb.Len() > 0 {
// return ecs.NewResult(msg, fmt.Errorf("区段非计轴区段或计轴区段状态不存在:[%s]", esb.String()))
// } else {
// return ecs.NewResult(msg, nil)
// }
// })
// return r.Val, r.Err
//}
//
// set : true - 设置故障占用false - 取消故障占用
func AxleSectionFaultOccDrive(w ecs.World, sectionId string, set bool) error {
r := <-ecs.Request[ecs.EmptyType](w, func() ecs.Result[ecs.EmptyType] {
wd := entity.GetWorldData(w)
sectionModel := wd.Repo.FindPhysicalSection(sectionId)
if sectionModel == nil {
return ecs.NewErrResult(fmt.Errorf("区段模型[%s]不存实体", sectionId))
}
//
sectionEntry := wd.EntityMap[sectionId]
if sectionEntry == nil {
return ecs.NewErrResult(fmt.Errorf("区段[%s]实体不存在", sectionId))
}
if set { //计轴故障设置
if !sectionEntry.HasComponent(component.AxleSectionFaultTag) {
sectionEntry.AddComponent(component.AxleSectionFaultTag)
}
} else { //计轴故障取消
if sectionEntry.HasComponent(component.AxleSectionFaultTag) {
sectionEntry.RemoveComponent(component.AxleSectionFaultTag)
}
}
//
return ecs.NewOkEmptyResult()
})
return r.Err
}
// AxleSectionTrainDrive 计轴区段内车进入出清设置
//
// trainIn : true - 计轴区段内有车false-计轴区段出清
func AxleSectionTrainDrive(w ecs.World, sectionId string, trainIn bool) error {
r := <-ecs.Request[ecs.EmptyType](w, func() ecs.Result[ecs.EmptyType] {
wd := entity.GetWorldData(w)
sectionModel := wd.Repo.FindPhysicalSection(sectionId)
if sectionModel == nil {
return ecs.NewErrResult(fmt.Errorf("区段模型[%s]不存实体", sectionId))
}
//
sectionEntry := wd.EntityMap[sectionId]
if sectionEntry == nil {
return ecs.NewErrResult(fmt.Errorf("区段[%s]实体不存在", sectionId))
}
axleDevice := component.AxlePhysicalSectionType.Get(sectionEntry)
if trainIn {
axleDevice.UpdateCount(1)
} else {
axleDevice.UpdateCount(0)
}
//
return ecs.NewOkEmptyResult()
})
return r.Err
}
// FindAxleSectionsStatus 获取计轴区段的相关状态
func FindAxleSectionsStatus(w ecs.World, sectionIds []string) ([]*AxleSectionState, error) {
r := <-ecs.Request[[]*AxleSectionState](w, func() ecs.Result[[]*AxleSectionState] {
wd := entity.GetWorldData(w)
var msg []*AxleSectionState
var esb = strings.Builder{} //收集未找到的区段的id
for _, sectionId := range sectionIds {
find := false
sectionModel := wd.Repo.FindPhysicalSection(sectionId)
if sectionModel != nil {
faDcAxleDeviceEntry := entity.FindAxleManageDevice(wd, sectionModel.CentralizedStation())
if faDcAxleDeviceEntry != nil {
faDcAxleDevice := component.AxleManageDeviceType.Get(faDcAxleDeviceEntry)
axleDevice := faDcAxleDevice.FindAdr(sectionId)
if axleDevice != nil {
sectionEntry, _ := entity.GetEntityByUid(w, sectionId)
if sectionEntry != nil {
if sectionEntry.HasComponent(component.AxlePhysicalSectionType) { //计轴物理区段实体
as := &AxleSectionState{}
state := component.PhysicalSectionStateType.Get(sectionEntry)
as.Id = component.UidType.Get(sectionEntry).Id
as.Clr = !state.Occ
as.Occ = state.Occ
as.Rac = axleDevice.Rac
as.Rjt = axleDevice.Rjt
as.Rjo = axleDevice.Rjo
//
msg = append(msg, as)
find = true
}
}
}
}
}
//
if !find {
esb.WriteString(fmt.Sprintf("%s,", sectionId))
}
} //for
if esb.Len() > 0 {
return ecs.NewResult(msg, fmt.Errorf("区段非计轴区段或计轴区段状态不存在:[%s]", esb.String()))
} else {
return ecs.NewResult(msg, nil)
}
})
return r.Val, r.Err
}
type AxleSectionState struct {
//uid
Id string
//0-bit7 计轴出清
Clr bool
//0-bit6 计轴占用
Occ bool
//1-bit6 计轴复位反馈
Rac bool
//1-bit5 运营原因拒绝计轴复位
Rjo bool
//1-bit4 技术原因拒绝计轴复位
Rjt bool
}
// AxleSectionRstDrive 复位(直接复位、预复位)
func AxleSectionRstDrive(w ecs.World, cmds []*AxleSectionCmd) error {
r := <-ecs.Request[ecs.EmptyType](w, func() ecs.Result[ecs.EmptyType] {
wd := entity.GetWorldData(w)
var esb = strings.Builder{} //收集未找到的区段的id
find := false
for _, cmd := range cmds {
sectionId := cmd.SectionId
sectionModel := wd.Repo.FindPhysicalSection(sectionId)
if sectionModel != nil {
faDcAxleDeviceEntry := entity.FindAxleManageDevice(wd, sectionModel.CentralizedStation())
if faDcAxleDeviceEntry != nil {
faDcAxleDevice := component.AxleManageDeviceType.Get(faDcAxleDeviceEntry)
axleRuntime := faDcAxleDevice.FindAdr(sectionId)
if axleRuntime != nil {
axleRuntime.Pdrst = cmd.Pdrst
axleRuntime.Drst = cmd.Drst
find = true
}
}
}
if !find {
esb.WriteString(fmt.Sprintf("%s,", sectionId))
}
} //for
if esb.Len() > 0 {
return ecs.NewErrResult(fmt.Errorf("计轴区段复位操作,失败列表[%s]", esb.String()))
} else {
return ecs.NewOkEmptyResult()
}
})
return r.Err
}
type AxleSectionCmd struct {
SectionId string
Drst bool
Pdrst bool
}
//type AxleSectionState struct {
// //uid
// Id string
// //0-bit7 计轴出清
// Clr bool
// //0-bit6 计轴占用
// Occ bool
// //1-bit6 计轴复位反馈
// Rac bool
// //1-bit5 运营原因拒绝计轴复位
// Rjo bool
// //1-bit4 技术原因拒绝计轴复位
// Rjt bool
//}

View File

@ -9,7 +9,7 @@ type CheckPoint struct {
km *proto.Kilometer
pointType proto.CheckPointType //检测点类型
devicePorts []DevicePort //检测点关联的设备及其端口
linkPosition *LinkPosition
linkPosition LinkPosition
}
func NewCheckPoint(id string, km *proto.Kilometer, pointType proto.CheckPointType) *CheckPoint {
@ -20,10 +20,14 @@ func NewCheckPoint(id string, km *proto.Kilometer, pointType proto.CheckPointTyp
}
}
func (c *CheckPoint) LinkPosition() LinkPosition {
return c.linkPosition
}
func (c *CheckPoint) bindDevicePort(devicePort DevicePort) {
c.devicePorts = append(c.devicePorts, devicePort)
}
func (c *CheckPoint) bindLinkPosition(position *LinkPosition) {
func (c *CheckPoint) bindLinkPosition(position LinkPosition) {
c.linkPosition = position
}

View File

@ -18,8 +18,8 @@ type Link struct {
aKm *proto.Kilometer
bKm *proto.Kilometer
//Link上的模型非区段边界检测点、应答器、信号机
devices []Identity
//按偏移量小到大排序的、此Link上的模型非区段边界检测点、应答器、信号机
devices []LinkPositionDevice
////Link关联的模型包含LinkNode
//devicePositions []*DeviceLinkPosition
@ -59,7 +59,7 @@ func (l *Link) BRelation() *TurnoutPort {
return l.bRelation
}
func (l *Link) Devices() []Identity {
func (l *Link) Devices() []LinkPositionDevice {
return l.devices
}
@ -102,7 +102,7 @@ func (l *Link) bindKm(km *proto.Kilometer, port proto.Port) {
}
}
func (l *Link) bindDevices(devices ...Identity) {
func (l *Link) bindDevices(devices ...LinkPositionDevice) {
for _, device := range devices {
l.devices = append(l.devices, device)
}
@ -138,15 +138,15 @@ type LinkPosition struct {
func NewLinkPosition(link *Link, offset int64) *LinkPosition {
return &LinkPosition{link: link, offset: offset}
}
func (l *LinkPosition) Link() *Link {
func (l LinkPosition) Link() *Link {
return l.link
}
func (l *LinkPosition) Offset() int64 {
func (l LinkPosition) Offset() int64 {
return l.offset
}
func (l *LinkPosition) String() string {
func (l LinkPosition) String() string {
return fmt.Sprintf("[LinkPosition:{%s-%d]", l.link.Id(), l.offset)
}

View File

@ -22,6 +22,13 @@ func (m identity) Type() proto.DeviceType {
return m.deviceType
}
// LinkPositionDevice 有link位置的设备
type LinkPositionDevice interface {
Identity
LinkPosition() LinkPosition
bindLinkPosition(position LinkPosition)
}
//////////////////////////system中使用///////////////////////////////////
// IRelayCRole 获取继电器在具体电路中的角色(组合类型、功能名称)

View File

@ -836,6 +836,10 @@ func relateDevicesAndLink(repo *Repository, link *Link, startKm *proto.Kilometer
if visitedModelMap[device.Id()] {
continue
}
linkPositionDevice, ok := device.(LinkPositionDevice)
if !ok {
return fmt.Errorf("device [%s:%s] not implements LinkPositionDevice", device.Id(), device.Type().String())
}
km := findModelKm(device)
if km == nil || km.CoordinateSystem == "" {
continue
@ -845,19 +849,12 @@ func relateDevicesAndLink(repo *Repository, link *Link, startKm *proto.Kilometer
return err
}
offset := int64(math.Abs(float64(convertedKm.Value - startKm.Value)))
linkPosition := &LinkPosition{
linkPosition := LinkPosition{
link: link,
offset: offset,
}
switch device.Type() {
case proto.DeviceType_DeviceType_CheckPoint:
device.(*CheckPoint).bindLinkPosition(linkPosition)
case proto.DeviceType_DeviceType_Signal:
device.(*Signal).bindLinkPosition(linkPosition)
case proto.DeviceType_DeviceType_Transponder:
device.(*Transponder).bindLinkPosition(linkPosition)
}
link.bindDevices(device)
linkPositionDevice.bindLinkPosition(linkPosition)
link.bindDevices(linkPositionDevice)
}
return nil
}

View File

@ -8,7 +8,7 @@ type Signal struct {
km *proto.Kilometer
//section *PhysicalSection
//turnoutPort TurnoutPort
linkPosition *LinkPosition
linkPosition LinkPosition
//信号机电路系统电子元器件
componentGroups []*ElectronicComponentGroup
model proto.Signal_Model
@ -23,23 +23,21 @@ func NewSignal(id string, km *proto.Kilometer, code string, model proto.Signal_M
}
}
func (s *Signal) bindLinkPosition(position *LinkPosition) {
s.linkPosition = position
}
// func (s *Signal) bindSection(section *PhysicalSection) {
// s.section = section
// }
//
// func (s *Signal) bindTurnoutPort(tp TurnoutPort) {
// s.turnoutPort = tp
// }
func (s *Signal) RelayGroups() []*ElectronicComponentGroup {
return s.componentGroups
}
func (s *Signal) Code() string {
return s.code
}
func (s *Signal) Model() proto.Signal_Model {
return s.model
}
func (s *Signal) LinkPosition() LinkPosition {
return s.linkPosition
}
func (s *Signal) bindLinkPosition(position LinkPosition) {
s.linkPosition = position
}

View File

@ -8,7 +8,7 @@ type Transponder struct {
km *proto.Kilometer
//section *PhysicalSection
//turnoutPort TurnoutPort
linkPosition *LinkPosition //此位置是应答器初始位置,当前位置需从应答器实体中获取
linkPosition LinkPosition //此位置是应答器初始位置,当前位置需从应答器实体中获取
fixedTelegram []byte //应答器固定报文
fixedUserTelegram []byte //应答器固定用户报文
baliseType proto.Transponder_Type //应答器类型
@ -38,10 +38,10 @@ func (t *Transponder) FixedTelegram() []byte {
func (t *Transponder) FixedUserTelegram() []byte {
return t.fixedUserTelegram
}
func (t *Transponder) bindLinkPosition(position *LinkPosition) {
func (t *Transponder) bindLinkPosition(position LinkPosition) {
t.linkPosition = position
}
func (t *Transponder) LinkPosition() *LinkPosition {
func (t *Transponder) LinkPosition() LinkPosition {
return t.linkPosition
}

View File

@ -39,8 +39,9 @@ func BindSystem(w ecs.World) {
circuit_sys.NewIBPSys(),
device_sys.NewAlarmSys(),
//物理区段
device_sys.NewFaDcAxleDeviceSystem(),
device_sys.NewSectionDetectSystem(),
//device_sys.NewFaDcAxleDeviceSystem(),
//device_sys.NewSectionDetectSystem(),
device_sys.NewAxleSectionSystem(),
//应答器
device_sys.NewBaliseSystem(),
//电机

View File

@ -0,0 +1,57 @@
package device_sys
import (
"github.com/yohamta/donburi"
"joylink.club/ecs"
"joylink.club/ecs/filter"
"joylink.club/rtsssimulation/component"
)
type AxleSectionSystem struct {
trainQuery *ecs.Query //简化列车经过计轴时的计轴逻辑,后续有需要了再拆出去
axleSectionQuery *ecs.Query
}
func NewAxleSectionSystem() *AxleSectionSystem {
return &AxleSectionSystem{
trainQuery: ecs.NewQuery(filter.Contains(component.UidType, component.TrainPositionInfoType)),
axleSectionQuery: ecs.NewQuery(filter.Contains(component.UidType, component.AxleSectionTag, component.AxleManagerType)),
}
}
// Update
// 预复位逻辑:目前仅在区段上无车且占用时,才能成功设置预复位/复位,也就是说,区段会有【强制占用】状态且无车。
// 那么当预复位设置成功之后等待一次区段计数从非0变成0清除预复位和【强制占用】状态
func (s *AxleSectionSystem) Update(w ecs.World) {
sectionTrainCountMap := make(map[string]int)
s.trainQuery.Each(w, func(entry *donburi.Entry) {
trainPositionInfo := component.TrainPositionInfoType.Get(entry)
sectionIds := DoSearchTrainOccupiedSections(w, trainPositionInfo)
for _, id := range sectionIds {
sectionTrainCountMap[id]++
}
})
s.axleSectionQuery.Each(w, func(entry *donburi.Entry) {
sectionId := component.UidType.Get(entry).Id
axleManager := component.AxleManagerType.Get(entry)
count := axleManager.Count
axleManager.Count = sectionTrainCountMap[sectionId]
//预复位逻辑。
if axleManager.PDRST && count != 0 && axleManager.Count == 0 {
axleManager.PDRST = false
entry.RemoveComponent(component.AxleSectionForceOccupied)
}
//区段占用判定
var gj *ecs.Entry
if entry.HasComponent(component.AxleSectionCircuitType) {
gj = component.AxleSectionCircuitType.Get(entry).GJ
}
occupied := axleManager.Count != 0 || entry.HasComponent(component.AxleSectionForceOccupied)
if gj != nil {
component.RelayDriveType.Get(entry).Td = !occupied
axleManager.Occupied = !component.BitStateType.Get(gj).Val
} else {
axleManager.Occupied = occupied
}
})
}

View File

@ -1,100 +1,101 @@
package device_sys
import (
"log/slog"
"joylink.club/ecs"
"joylink.club/ecs/filter"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/entity"
)
// FaDcAxleDeviceSystem FaDc计轴设备管理器系统
type FaDcAxleDeviceSystem struct {
query *ecs.Query
}
func NewFaDcAxleDeviceSystem() *FaDcAxleDeviceSystem {
return &FaDcAxleDeviceSystem{
query: ecs.NewQuery(filter.Contains(component.AxleManageDeviceType)),
}
}
func (s *FaDcAxleDeviceSystem) Update(w ecs.World) {
data := entity.GetWorldData(w)
s.query.Each(w, func(entry *ecs.Entry) {
faDcDevice := component.AxleManageDeviceType.Get(entry)
for axleSectionId, axleRuntime := range faDcDevice.Adrs {
axleSectionEntry := data.EntityMap[axleSectionId]
sectionState := component.PhysicalSectionStateType.Get(axleSectionEntry)
axleDevice := component.AxlePhysicalSectionType.Get(axleSectionEntry)
//
sectionFault := axleSectionEntry.HasComponent(component.AxleSectionFaultTag)
s.calculateHf(sectionFault, axleSectionEntry, sectionState, axleDevice, axleRuntime)
s.calculateDrst(axleSectionEntry, sectionState, axleDevice, axleRuntime)
s.calculatePdrst(axleSectionEntry, sectionState, axleDevice, axleRuntime)
s.calculateSectionState(sectionFault, sectionState, axleDevice, axleRuntime)
if axleSectionEntry.HasComponent(component.PhysicalSectionCircuitType) {
sectionCircuit := component.PhysicalSectionCircuitType.Get(axleSectionEntry)
relayDrive := component.RelayDriveType.Get(sectionCircuit.GJ)
relayDrive.Td = !sectionState.Occ
}
if "北京_12_酒仙桥_15G" == axleSectionId && false {
sectionFault := axleSectionEntry.HasComponent(component.AxleSectionFaultTag)
slog.Info(axleSectionId,
"Drst", axleRuntime.Drst,
"Pdrst", axleRuntime.Pdrst,
"DoingPdrst", axleRuntime.DoingPdrst,
"Rac", axleRuntime.Rac,
"Rjo", axleRuntime.Rjo,
"Rjt", axleRuntime.Rjt,
"SectionFault", sectionFault,
"Occ", sectionState.Occ,
"Count", axleDevice.Count,
"Wave", axleDevice.ShowCountWave())
}
}
})
}
// 计算计轴区段状态
func (s *FaDcAxleDeviceSystem) calculateSectionState(sectionFault bool, sectionState *component.PhysicalSectionState, axleDevice *component.AxlePhysicalSection, axleRuntime *component.AxleDeviceRuntime) {
sectionState.Occ = axleDevice.Count > 0 || sectionFault
}
// 计轴直接复位
func (s *FaDcAxleDeviceSystem) calculateDrst(axleSectionEntry *ecs.Entry, sectionState *component.PhysicalSectionState, axleDevice *component.AxlePhysicalSection, axleRuntime *component.AxleDeviceRuntime) {
isFault := axleSectionEntry.HasComponent(component.AxleSectionFaultTag)
if axleRuntime.Drst && !axleRuntime.Rjo && !axleRuntime.Rjt && isFault { //直接复位且没有拒绝原因
axleDevice.UpdateCount(0)
axleDevice.ResetCountPulse()
axleRuntime.DoingPdrst = false
//清除故障
if axleSectionEntry.HasComponent(component.AxleSectionFaultTag) {
axleSectionEntry.RemoveComponent(component.AxleSectionFaultTag)
}
}
}
// 计轴预复位
func (s *FaDcAxleDeviceSystem) calculatePdrst(axleSectionEntry *ecs.Entry, sectionState *component.PhysicalSectionState, axleDevice *component.AxlePhysicalSection, axleRuntime *component.AxleDeviceRuntime) {
isFault := axleSectionEntry.HasComponent(component.AxleSectionFaultTag)
if axleRuntime.Pdrst && !axleRuntime.Rjo && !axleRuntime.Rjt && !axleRuntime.DoingPdrst && isFault { //预复位且没有拒绝原因
axleDevice.UpdateCount(0)
axleDevice.ResetCountPulse()
axleRuntime.DoingPdrst = true
}
//压道车通过该计轴区段,完成计轴预复位
if axleRuntime.DoingPdrst && isFault && axleDevice.IsCount010Pulse() {
axleRuntime.DoingPdrst = false
//清除故障
axleSectionEntry.RemoveComponent(component.AxleSectionFaultTag)
}
}
// 复位回复运算
func (s *FaDcAxleDeviceSystem) calculateHf(sectionFault bool, axleSectionEntry *ecs.Entry, sectionState *component.PhysicalSectionState, axleDevice *component.AxlePhysicalSection, axleRuntime *component.AxleDeviceRuntime) {
axleRuntime.Rac = axleRuntime.Drst || axleRuntime.Pdrst
axleRuntime.Rjo = axleRuntime.Rac && !sectionState.Occ && !axleRuntime.DoingPdrst //空闲拒绝复位(排除预复位过程中)
axleRuntime.Rjt = false // 技术原因拒绝复位
}
//import (
// "log/slog"
//
// "joylink.club/ecs"
// "joylink.club/ecs/filter"
// "joylink.club/rtsssimulation/component"
// "joylink.club/rtsssimulation/entity"
//)
//
//// FaDcAxleDeviceSystem FaDc计轴设备管理器系统
//type FaDcAxleDeviceSystem struct {
// query *ecs.Query
//}
//
//func NewFaDcAxleDeviceSystem() *FaDcAxleDeviceSystem {
// return &FaDcAxleDeviceSystem{
// query: ecs.NewQuery(filter.Contains(component.AxleManageDeviceType)),
// }
//}
//func (s *FaDcAxleDeviceSystem) Update(w ecs.World) {
// data := entity.GetWorldData(w)
// s.query.Each(w, func(entry *ecs.Entry) {
// faDcDevice := component.AxleManageDeviceType.Get(entry)
// for axleSectionId, axleRuntime := range faDcDevice.Adrs {
// axleSectionEntry := data.EntityMap[axleSectionId]
// sectionState := component.PhysicalSectionStateType.Get(axleSectionEntry)
// axleDevice := component.AxlePhysicalSectionType.Get(axleSectionEntry)
// //
// sectionFault := axleSectionEntry.HasComponent(component.AxleSectionFaultTag)
// s.calculateHf(sectionFault, axleSectionEntry, sectionState, axleDevice, axleRuntime)
// s.calculateDrst(axleSectionEntry, sectionState, axleDevice, axleRuntime)
// s.calculatePdrst(axleSectionEntry, sectionState, axleDevice, axleRuntime)
// s.calculateSectionState(sectionFault, sectionState, axleDevice, axleRuntime)
// if axleSectionEntry.HasComponent(component.PhysicalSectionCircuitType) {
// sectionCircuit := component.PhysicalSectionCircuitType.Get(axleSectionEntry)
// relayDrive := component.RelayDriveType.Get(sectionCircuit.GJ)
// relayDrive.Td = !sectionState.Occ
// }
//
// if "北京_12_酒仙桥_15G" == axleSectionId && false {
// sectionFault := axleSectionEntry.HasComponent(component.AxleSectionFaultTag)
// slog.Info(axleSectionId,
// "Drst", axleRuntime.Drst,
// "PDRST", axleRuntime.Pdrst,
// "DoingPdrst", axleRuntime.DoingPdrst,
// "RAC", axleRuntime.Rac,
// "RJO", axleRuntime.Rjo,
// "RJT", axleRuntime.Rjt,
// "SectionFault", sectionFault,
// "Occ", sectionState.Occ,
// "Count", axleDevice.Count,
// "Wave", axleDevice.ShowCountWave())
// }
// }
// })
//}
//
//// 计算计轴区段状态
//func (s *FaDcAxleDeviceSystem) calculateSectionState(sectionFault bool, sectionState *component.PhysicalSectionState, axleDevice *component.AxlePhysicalSection, axleRuntime *component.AxleDeviceRuntime) {
// sectionState.Occ = axleDevice.Count > 0 || sectionFault
//}
//
//// 计轴直接复位
//func (s *FaDcAxleDeviceSystem) calculateDrst(axleSectionEntry *ecs.Entry, sectionState *component.PhysicalSectionState, axleDevice *component.AxlePhysicalSection, axleRuntime *component.AxleDeviceRuntime) {
// isFault := axleSectionEntry.HasComponent(component.AxleSectionFaultTag)
// if axleRuntime.Drst && !axleRuntime.Rjo && !axleRuntime.Rjt && isFault { //直接复位且没有拒绝原因
// axleDevice.UpdateCount(0)
// axleDevice.ResetCountPulse()
// axleRuntime.DoingPdrst = false
// //清除故障
// if axleSectionEntry.HasComponent(component.AxleSectionFaultTag) {
// axleSectionEntry.RemoveComponent(component.AxleSectionFaultTag)
// }
// }
//}
//
//// 计轴预复位
//func (s *FaDcAxleDeviceSystem) calculatePdrst(axleSectionEntry *ecs.Entry, sectionState *component.PhysicalSectionState, axleDevice *component.AxlePhysicalSection, axleRuntime *component.AxleDeviceRuntime) {
// isFault := axleSectionEntry.HasComponent(component.AxleSectionFaultTag)
// if axleRuntime.Pdrst && !axleRuntime.Rjo && !axleRuntime.Rjt && !axleRuntime.DoingPdrst && isFault { //预复位且没有拒绝原因
// axleDevice.UpdateCount(0)
// axleDevice.ResetCountPulse()
// axleRuntime.DoingPdrst = true
// }
// //压道车通过该计轴区段,完成计轴预复位
// if axleRuntime.DoingPdrst && isFault && axleDevice.IsCount010Pulse() {
// axleRuntime.DoingPdrst = false
// //清除故障
// axleSectionEntry.RemoveComponent(component.AxleSectionFaultTag)
// }
//}
//
//// 复位回复运算
//func (s *FaDcAxleDeviceSystem) calculateHf(sectionFault bool, axleSectionEntry *ecs.Entry, sectionState *component.PhysicalSectionState, axleDevice *component.AxlePhysicalSection, axleRuntime *component.AxleDeviceRuntime) {
// axleRuntime.Rac = axleRuntime.Drst || axleRuntime.Pdrst
// axleRuntime.Rjo = axleRuntime.Rac && !sectionState.Occ && !axleRuntime.DoingPdrst //空闲拒绝复位(排除预复位过程中)
// axleRuntime.Rjt = false // 技术原因拒绝复位
//}

View File

@ -2,68 +2,67 @@ package device_sys
import (
"fmt"
"log/slog"
"strings"
"joylink.club/ecs"
"joylink.club/ecs/filter"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/entity"
"joylink.club/rtsssimulation/repository"
"joylink.club/rtsssimulation/repository/model/proto"
"log/slog"
"strings"
)
// SectionDetectSystem 区段检测系统
type SectionDetectSystem struct {
trainQuery *ecs.Query
axleSectionQuery *ecs.Query
}
//// SectionDetectSystem 区段检测系统
//type SectionDetectSystem struct {
// trainQuery *ecs.Query
// axleSectionQuery *ecs.Query
//}
//
//func NewSectionDetectSystem() *SectionDetectSystem {
// return &SectionDetectSystem{trainQuery: ecs.NewQuery(filter.Contains(component.UidType, component.TrainPositionInfoType)),
// axleSectionQuery: ecs.NewQuery(filter.Contains(component.UidType, component.AxlePhysicalSectionType))}
//}
//func (s *SectionDetectSystem) Update(w ecs.World) {
// //key-sectionId,统计区段上有车的情况
// sectionTrainMap := make(map[string]*trainCount)
// //所有列车
// s.trainQuery.Each(w, func(entry *ecs.Entry) {
// tp := component.TrainPositionInfoType.Get(entry)
// //fmt.Println("============>>>>>>列车位置信息:", tp.ToString())
// trainSectionIds := DoSearchTrainOccupiedSections(w, tp)
// //fmt.Println("============>>>>>>列车所在物理区段:", trainSectionIds)
// for _, sectionId := range trainSectionIds { //车所在区段
// tc, find := sectionTrainMap[sectionId]
// if !find {
// tc = newTrainCount()
// sectionTrainMap[sectionId] = tc
// }
// tc.add()
// }
// })
// //计轴区段
// s.axleSectionQuery.Each(w, func(entry *ecs.Entry) {
// axleSectionId := component.UidType.Get(entry).Id
// axleSection := component.AxlePhysicalSectionType.Get(entry)
// tc, find := sectionTrainMap[axleSectionId]
// if find {
// axleSection.UpdateCount(int(tc.count))
// } else {
// axleSection.UpdateCount(0)
// }
// })
//}
//
//type trainCount struct {
// count int8
//}
//
//func newTrainCount() *trainCount {
// return &trainCount{count: 0}
//}
//func (c *trainCount) add() {
// c.count++
//}
func NewSectionDetectSystem() *SectionDetectSystem {
return &SectionDetectSystem{trainQuery: ecs.NewQuery(filter.Contains(component.UidType, component.TrainPositionInfoType)),
axleSectionQuery: ecs.NewQuery(filter.Contains(component.UidType, component.AxlePhysicalSectionType))}
}
func (s *SectionDetectSystem) Update(w ecs.World) {
//key-sectionId,统计区段上有车的情况
sectionTrainMap := make(map[string]*trainCount)
//所有列车
s.trainQuery.Each(w, func(entry *ecs.Entry) {
tp := component.TrainPositionInfoType.Get(entry)
//fmt.Println("============>>>>>>列车位置信息:", tp.ToString())
trainSectionIds := DoSearchTrainOccupiedSections(w, tp)
//fmt.Println("============>>>>>>列车所在物理区段:", trainSectionIds)
for _, sectionId := range trainSectionIds { //车所在区段
tc, find := sectionTrainMap[sectionId]
if !find {
tc = newTrainCount()
sectionTrainMap[sectionId] = tc
}
tc.add()
}
})
//计轴区段
s.axleSectionQuery.Each(w, func(entry *ecs.Entry) {
axleSectionId := component.UidType.Get(entry).Id
axleSection := component.AxlePhysicalSectionType.Get(entry)
tc, find := sectionTrainMap[axleSectionId]
if find {
axleSection.UpdateCount(int(tc.count))
} else {
axleSection.UpdateCount(0)
}
})
}
type trainCount struct {
count int8
}
func newTrainCount() *trainCount {
return &trainCount{count: 0}
}
func (c *trainCount) add() {
c.count++
}
func DoSearchTrainOccupiedSections(w ecs.World, tp *component.TrainPositionInfo) []string {
wd := entity.GetWorldData(w)
curLink := wd.Repo.FindLink(tp.HeadLink)
@ -80,8 +79,7 @@ func DoSearchTrainOccupiedSections(w ecs.World, tp *component.TrainPositionInfo)
return stp.trainSections()
}
/////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////
type stpContext struct {
w ecs.World
trainLen int64 //列车长度