[新增]计轴区段的模型、ecs实体、ecs系统、发给前端的状态

This commit is contained in:
thesai 2024-08-12 18:57:36 +08:00
parent 51702238da
commit 73e7f83cfa
16 changed files with 1601 additions and 1293 deletions

View File

@ -0,0 +1,11 @@
package component
import "joylink.club/ecs"
var (
AxleCountingSectionStateType = ecs.NewComponentType[AxleCountingSectionState]()
)
type AxleCountingSectionState struct {
Occupied bool
}

View File

@ -1,134 +0,0 @@
package component
import "joylink.club/ecs"
var (
AxleSectionTag = ecs.NewTag()
AxleSectionCircuitType = ecs.NewComponentType[AxleSectionCircuit]()
AxleManagerType = ecs.NewComponentType[AxleManager]()
)
var AxleSectionForceOccupied = ecs.NewTag() //区段强制占用(故障占用)
// 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
}
////计轴设备,管理联锁集中站内的所有计轴区段
////计轴直接复位:计轴的轮对计数清零,区段转换为空闲状态
////计轴预复位:将计轴的轮对计数清零,但是区段不会立即变成空闲区段,而是处于一种“占用”状态,在压道车通过之后确认区段空闲且计轴正常后,区段转换为空闲状态
////
////当CI系统给计轴设备发送计轴直接复零/预复零命令时,连续发送一定时间(具体发送时间调试后确定)的复零/预复零命令。
////当RACRJORJT任意一个不为0时终止发送复零/预复零命令。
//
//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

@ -0,0 +1,27 @@
package component
import "joylink.club/ecs"
var (
PhysicalSectionTag = ecs.NewTag()
PhysicalSectionCircuitType = ecs.NewComponentType[PhysicalSectionCircuit]()
PhysicalSectionManagerType = ecs.NewComponentType[PhysicalSectionManager]()
)
var PhysicalSectionForceOccupied = ecs.NewTag() //区段强制占用(故障占用)
// PhysicalSectionManager 计轴管理器。我自己起的名字,计轴逻辑的载体
type PhysicalSectionManager struct {
Count int //轴数(简化版)。目前此轴数计数只与区段上有无列车有关,故障占用等状态不会影响此计数
Occupied bool //占用
PDRST bool //预复位
//RAC bool //计轴复位反馈。主要指计轴设备发送给CI系统的直接复零/预复零命令反馈表示计轴设备已收到CI系统发送的直接复零/预复零命令。
//RJO bool //运营原因拒绝直接复位/预复位。如区段空闲时下发复位命令;或车轮压住传感器时收到复位命令。
//RJT bool //技术原因拒绝直接复位/预复位。主要指计轴相关设备故障时收到复位命令如车轮传感器的导线断开、AEB之间的通信故障等。
}
// PhysicalSectionCircuit 计轴区段电路
type PhysicalSectionCircuit struct {
GJ *ecs.Entry
}

View File

@ -0,0 +1,20 @@
package entity
import (
"joylink.club/ecs"
"joylink.club/rtsssimulation/component"
)
var AxleCountingSectionBaseComponentTypes = []ecs.IComponentType{component.UidType, component.AxleCountingSectionStateType}
// LoadPhysicalSections 加载计轴区段
func LoadAxleCountingSections(w ecs.World) error {
wd := GetWorldData(w)
sections := wd.Repo.AxleCountingSectionList()
for _, section := range sections {
entry := w.Entry(w.Create(AxleCountingSectionBaseComponentTypes...))
component.UidType.SetValue(entry, component.Uid{Id: section.Id()})
wd.EntityMap[section.Id()] = entry
}
return nil
}

View File

@ -36,8 +36,13 @@ func Load(w ecs.World, repo *repository.Repository) error {
if err != nil {
return err
}
// 加载物理区段相关实体
err = LoadPhysicalSections(w)
if err != nil {
return err
}
// 加载计轴区段相关实体
err = LoadAxlePhysicalSections(w)
err = LoadAxleCountingSections(w)
if err != nil {
return err
}

View File

@ -7,23 +7,23 @@ import (
"unsafe"
)
var AxleSectionBaseComponentTypes = []ecs.IComponentType{component.UidType, component.AxleSectionTag, component.AxleManagerType}
var PhysicalSectionBaseComponentTypes = []ecs.IComponentType{component.UidType, component.PhysicalSectionTag, component.PhysicalSectionManagerType}
// LoadAxlePhysicalSections 加载计轴区段
func LoadAxlePhysicalSections(w ecs.World) error {
// LoadPhysicalSections 加载计轴区段
func LoadPhysicalSections(w ecs.World) error {
wd := GetWorldData(w)
sections := wd.Repo.PhysicalSectionList()
for _, section := range sections {
if is, err := section.IsAxleSection(); err == nil && is {
entry := w.Entry(w.Create(AxleSectionBaseComponentTypes...))
entry := w.Entry(w.Create(PhysicalSectionBaseComponentTypes...))
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, wd.EntityMap)
circuit := &component.AxleSectionCircuit{GJ: gjEntry}
entry.AddComponent(component.AxleSectionCircuitType, unsafe.Pointer(circuit))
circuit := &component.PhysicalSectionCircuit{GJ: gjEntry}
entry.AddComponent(component.PhysicalSectionCircuitType, unsafe.Pointer(circuit))
}
}
}

View File

@ -22,12 +22,12 @@ func AxleSectionFaultOccDrive(w ecs.World, sectionId string, set bool) error {
return ecs.NewErrResult(fmt.Errorf("区段[%s]实体不存在", sectionId))
}
if set { //计轴故障设置
if !sectionEntry.HasComponent(component.AxleSectionForceOccupied) {
sectionEntry.AddComponent(component.AxleSectionForceOccupied)
if !sectionEntry.HasComponent(component.PhysicalSectionForceOccupied) {
sectionEntry.AddComponent(component.PhysicalSectionForceOccupied)
}
} else { //计轴故障取消
if sectionEntry.HasComponent(component.AxleSectionForceOccupied) {
sectionEntry.RemoveComponent(component.AxleSectionForceOccupied)
if sectionEntry.HasComponent(component.PhysicalSectionForceOccupied) {
sectionEntry.RemoveComponent(component.PhysicalSectionForceOccupied)
}
}
return ecs.NewOkEmptyResult()
@ -43,12 +43,12 @@ func AxleSectionDrstDrive(w ecs.World, sectionId string) (*AxleSectionState, err
if entry == nil {
return ecs.NewResult[*AxleSectionState](nil, fmt.Errorf("区段[%s]实体不存在", sectionId))
}
axleManager := component.AxleManagerType.Get(entry)
axleManager := component.PhysicalSectionManagerType.Get(entry)
state := &AxleSectionState{}
if axleManager.Count != 0 {
state.Rjo = true
} else {
entry.RemoveComponent(component.AxleSectionForceOccupied)
entry.RemoveComponent(component.PhysicalSectionForceOccupied)
state.Rac = true
}
return ecs.NewOkResult(state)
@ -64,7 +64,7 @@ func AxleSectionPdrstDrive(w ecs.World, sectionId string) (*AxleSectionState, er
if entry == nil {
return ecs.NewResult[*AxleSectionState](nil, fmt.Errorf("区段[%s]实体不存在", sectionId))
}
axleManager := component.AxleManagerType.Get(entry)
axleManager := component.PhysicalSectionManagerType.Get(entry)
state := &AxleSectionState{}
if axleManager.Count != 0 {
state.Rjo = true
@ -88,7 +88,7 @@ func FindAxleSectionsStatus(w ecs.World, sectionIds []string) ([]*AxleSectionSta
esb.WriteString(fmt.Sprintf("%s,", sectionId))
continue
}
axleManager := component.AxleManagerType.Get(entry)
axleManager := component.PhysicalSectionManagerType.Get(entry)
msg = append(msg, &AxleSectionState{
Id: sectionId,
Clr: !axleManager.Occupied,

View File

@ -33,6 +33,7 @@ message Repository {
repeated CkmPsl ckmPsls = 26;
repeated Esb esbs = 27;
repeated Spks spkss = 28;
repeated AxleCountingSection axleCountingSections = 29; //
//ISCS [300,500]
//ISCS管线
repeated Pipe pipes = 300;
@ -102,6 +103,13 @@ message PhysicalSection {
repeated ElectronicComponentGroup electronicComponentGroups = 6;
}
//
message AxleCountingSection {
string id = 1;
repeated string axleCountingIds = 2;
repeated TurnoutAndPos turnoutAndPos = 3;
}
//
message CheckPoint{
string id = 1;
@ -117,6 +125,11 @@ message Turnout {
ZDJ9_Single = 1;
ZDJ9_Double = 2;
}
enum Pos {
Pos_Unknown = 0;
Pos_N = 1; //
Pos_R = 2; //
}
string id = 1;
Kilometer km = 2;
DevicePort aDevicePort = 3;
@ -198,6 +211,12 @@ message DevicePort {
Port port = 3;
}
//
message TurnoutAndPos {
string turnoutId = 1;
Turnout.Pos pos = 2;
}
enum DeviceType {
DeviceType_Unknown = 0;
DeviceType_PhysicalSection = 1;
@ -234,6 +253,7 @@ enum DeviceType {
DeviceType_LS = 28; //
DeviceType_Esb = 29; //
DeviceType_Spks = 30; //
DeviceTYpe_AxleCountingSection = 31; //
//--------ISCS [300,500]------
//ISCS门磁

View File

@ -0,0 +1,29 @@
package repository
import "joylink.club/rtsssimulation/repository/model/proto"
type AxleCountingSection struct {
Identity
//axleCountingList []CheckPoint //暂时用不上,先不要了
turnoutAndPosList []*proto.TurnoutAndPos
physicalSection *PhysicalSection
}
func NewAxleCountingSection(id string, turnoutAndPosList []*proto.TurnoutAndPos) *AxleCountingSection {
return &AxleCountingSection{
Identity: identity{
id: id,
deviceType: proto.DeviceType_DeviceTYpe_AxleCountingSection,
},
turnoutAndPosList: turnoutAndPosList,
}
}
func (a *AxleCountingSection) TurnoutAndPosList() []*proto.TurnoutAndPos {
return a.turnoutAndPosList
}
func (a *AxleCountingSection) PhysicalSection() *PhysicalSection {
return a.physicalSection
}

File diff suppressed because it is too large Load Diff

View File

@ -12,6 +12,7 @@ type Repository struct {
version string
coordinate *MapCoordinate // 基准坐标系类型,在列车画图时统一坐标系
physicalSectionMap map[string]*PhysicalSection
axleCountingSectionMap map[string]*AxleCountingSection
checkPointMap map[string]*CheckPoint
turnoutMap map[string]*Turnout
signalMap map[string]*Signal
@ -65,6 +66,7 @@ func newRepository(id string, version string) *Repository {
id: id,
version: version,
physicalSectionMap: make(map[string]*PhysicalSection),
axleCountingSectionMap: make(map[string]*AxleCountingSection),
checkPointMap: make(map[string]*CheckPoint),
turnoutMap: make(map[string]*Turnout),
signalMap: make(map[string]*Signal),
@ -216,6 +218,13 @@ func (repo *Repository) PhysicalSectionList() []*PhysicalSection {
}
return list
}
func (repo *Repository) AxleCountingSectionList() []*AxleCountingSection {
var list []*AxleCountingSection
for _, model := range repo.axleCountingSectionMap {
list = append(list, model)
}
return list
}
func (repo *Repository) CheckPointList() []*CheckPoint {
var list []*CheckPoint
for _, model := range repo.checkPointMap {
@ -466,6 +475,10 @@ func (repo *Repository) FindPhysicalSection(id string) *PhysicalSection {
return repo.physicalSectionMap[id]
}
func (repo *Repository) FindAxleCountingSection(id string) *AxleCountingSection {
return repo.axleCountingSectionMap[id]
}
func (repo *Repository) FindRelay(id string) *Relay {
return repo.relayMap[id]
}

View File

@ -67,6 +67,10 @@ func buildModels(source *proto.Repository, repository *Repository) error {
m := NewPhysicalSection(protoData.Id)
repository.physicalSectionMap[m.Id()] = m
}
for _, protoData := range source.AxleCountingSections {
m := NewAxleCountingSection(protoData.Id, protoData.TurnoutAndPos)
repository.axleCountingSectionMap[m.Id()] = m
}
for _, protoData := range source.CheckPoints {
m := NewCheckPoint(protoData.Id, protoData.Km, protoData.Type)
repository.checkPointMap[m.Id()] = m
@ -174,6 +178,10 @@ func buildModelRelationship(source *proto.Repository, repository *Repository) er
if err != nil {
return err
}
err = buildAxleCountingSectionRelationShip(source, repository)
if err != nil {
return err
}
err = buildTurnoutRelationShip(source, repository)
if err != nil {
return err
@ -230,6 +238,49 @@ func buildModelRelationship(source *proto.Repository, repository *Repository) er
return err
}
func buildAxleCountingSectionRelationShip(source *proto.Repository, repository *Repository) error {
turnout_physicalSection_map := make(map[string]*PhysicalSection)
for _, physicalSection := range repository.physicalSectionMap {
for _, turnout := range physicalSection.turnouts {
turnout_physicalSection_map[turnout.Id()] = physicalSection
}
}
for _, protoData := range source.AxleCountingSections {
axleCountingSection := repository.axleCountingSectionMap[protoData.Id]
if len(protoData.TurnoutAndPos) != 0 {
axleCountingSection.physicalSection = turnout_physicalSection_map[protoData.TurnoutAndPos[0].TurnoutId]
} else {
commonPhysicalSectionMap := make(map[*PhysicalSection]int)
for _, axleCountingId := range protoData.AxleCountingIds {
for _, dp := range repository.checkPointMap[axleCountingId].devicePorts {
physicalSection, ok := dp.Device().(*PhysicalSection)
if ok {
commonPhysicalSectionMap[physicalSection]++
}
}
}
for physicalSection, i := range commonPhysicalSectionMap {
if i > 1 {
axleCountingSection.physicalSection = physicalSection
break
}
}
if axleCountingSection.physicalSection == nil { //轨道尽头的区段
for section, _ := range commonPhysicalSectionMap {
if len(section.checkPoints) == 1 {
axleCountingSection.physicalSection = section
break
}
}
}
}
if axleCountingSection.physicalSection == nil {
return fmt.Errorf("计轴区段[%s]找不到对应的物理区段", protoData.Id)
}
}
return nil
}
func buildSpksRelationship(source *proto.Repository, repository *Repository) error {
for _, protoData := range source.Spkss {
platform := repository.platformMap[protoData.PlatformId]

View File

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

View File

@ -0,0 +1,30 @@
package device_sys
import (
"github.com/yohamta/donburi"
"joylink.club/ecs"
"joylink.club/ecs/filter"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/entity"
)
type AxleCountingSectionSystem struct {
axleCountingSectionQuery *ecs.Query
}
func NewAxleCountingSectionSystem() *AxleCountingSectionSystem {
return &AxleCountingSectionSystem{
axleCountingSectionQuery: ecs.NewQuery(filter.Contains(entity.AxleCountingSectionBaseComponentTypes...)),
}
}
func (a *AxleCountingSectionSystem) Update(w ecs.World) {
a.axleCountingSectionQuery.Each(w, func(entry *donburi.Entry) {
wd := entity.GetWorldData(w)
uid := component.UidType.Get(entry).Id
section := wd.Repo.FindAxleCountingSection(uid)
physicalSectionEntry := wd.EntityMap[section.PhysicalSection().Id()]
occupied := component.PhysicalSectionManagerType.Get(physicalSectionEntry).Occupied
component.AxleCountingSectionStateType.Get(entry).Occupied = occupied
})
}

View File

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

View File

@ -14,12 +14,12 @@ import (
//// SectionDetectSystem 区段检测系统
//type SectionDetectSystem struct {
// trainQuery *ecs.Query
// axleSectionQuery *ecs.Query
// axleCountingSectionQuery *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))}
// axleCountingSectionQuery: ecs.NewQuery(filter.Contains(component.UidType, component.AxlePhysicalSectionType))}
//}
//func (s *SectionDetectSystem) Update(w ecs.World) {
// //key-sectionId,统计区段上有车的情况
@ -40,7 +40,7 @@ import (
// }
// })
// //计轴区段
// s.axleSectionQuery.Each(w, func(entry *ecs.Entry) {
// s.axleCountingSectionQuery.Each(w, func(entry *ecs.Entry) {
// axleSectionId := component.UidType.Get(entry).Id
// axleSection := component.AxlePhysicalSectionType.Get(entry)
// tc, find := sectionTrainMap[axleSectionId]