rts-sim-module/fi/train.go
2023-11-29 17:28:33 +08:00

171 lines
5.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package fi
import (
"fmt"
"joylink.club/ecs"
"joylink.club/ecs/filter"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/entity"
"joylink.club/rtsssimulation/sys/device_sys"
)
// AddTrainToWorld 添加列车
func AddTrainToWorld(w ecs.World, trainId string) error {
result := <-ecs.Request[ecs.EmptyType](w, func() ecs.Result[ecs.EmptyType] {
wd := entity.GetWorldData(w)
_, find := wd.EntityMap[trainId]
if !find {
entity.NewTrainWithBtmEntity(w, trainId)
}
return ecs.NewOkEmptyResult()
})
return result.Err
}
// RemoveTrainFromWorld 移除列车
func RemoveTrainFromWorld(w ecs.World, trainId string) error {
result := <-ecs.Request[ecs.EmptyType](w, func() ecs.Result[ecs.EmptyType] {
wd := entity.GetWorldData(w)
te, find := wd.EntityMap[trainId]
if find {
te.Remove()
delete(wd.EntityMap, trainId)
}
return ecs.NewOkEmptyResult()
})
return result.Err
}
// UpdateTrainPositionFromDynamics 更新列车所在的物理区段
func UpdateTrainPositionFromDynamics(w ecs.World, tpi TrainPositionInfo) error {
result := <-ecs.Request[ecs.EmptyType](w, func() ecs.Result[ecs.EmptyType] {
wd := entity.GetWorldData(w)
te, find := wd.EntityMap[tpi.TrainId]
if find {
train := component.TrainPositionInfoType.Get(te)
//
lastTrainHeadPos := &device_sys.TrainHeadPosition{Up: train.Up, HeadLink: train.HeadLink, HeadLinkOffset: train.HeadLinkOffset}
//
train.Up = tpi.Up
train.Len = int64(tpi.Len)
train.HeadLink = tpi.HeadLink
train.HeadLinkOffset = int64(tpi.HeadLinkOffset)
train.TailLink = tpi.TailLink
train.TailLinkOffset = int64(tpi.TailLinkOffset)
//列车车头移动范围
curTrainHeadPos := &device_sys.TrainHeadPosition{Up: train.Up, HeadLink: train.HeadLink, HeadLinkOffset: train.HeadLinkOffset}
//根据列车位置探测应答器
device_sys.NewBaliseDetection().DetectBalise(w, te, lastTrainHeadPos, curTrainHeadPos)
//
return ecs.NewOkEmptyResult()
} else {
return ecs.NewErrResult(fmt.Errorf("列车[%s]实体不存在", tpi.TrainId))
}
})
return result.Err
}
// FindTrainBaliseBtmStatus 获取车载BTM的相关状态信息
func FindTrainBaliseBtmStatus(w ecs.World) (*TrainBtmStatus, error) {
result := <-ecs.Request[*TrainBtmStatus](w, func() ecs.Result[*TrainBtmStatus] {
//获取当前关联CANET设备的列车
canetTrain := findCanetTrain(w)
if canetTrain == nil {
return ecs.NewResult[*TrainBtmStatus](nil, fmt.Errorf("系统中当前不存在与CANET设备关联的列车实体"))
}
//
trainId := component.UidType.Get(canetTrain).Id
btm := component.TrainBtmType.Get(canetTrain)
btmStatus := &TrainBtmStatus{
TrainId: trainId,
PowerAmplifierOn: btm.PowerAmplifierSwitch,
PowerAmplifierFault: false,
AboveBalise: btm.AboveBalise,
AntennaFault: false,
BaliseCounter: btm.BaliseCounter,
MessageCounter: btm.MessageCounter,
}
return ecs.NewOkResult(btmStatus)
})
return result.Val, result.Err
}
// TrainBalisePowerAmplifierSwitch 车载应答器天线功率放大器开关控制
func TrainBalisePowerAmplifierSwitch(w ecs.World, turnOn bool) error {
result := <-ecs.Request[ecs.EmptyType](w, func() ecs.Result[ecs.EmptyType] {
//获取当前关联CANET设备的列车
canetTrain := findCanetTrain(w)
if canetTrain == nil {
return ecs.NewErrResult(fmt.Errorf("系统中当前不存在与CANET设备关联的列车实体"))
}
//
train := component.TrainBtmType.Get(canetTrain)
train.PowerAmplifierSwitch = turnOn
return ecs.NewOkEmptyResult()
})
return result.Err
}
// GetScannedBaliseTelegram 获取扫描到的应答器报文
func GetScannedBaliseTelegram(w ecs.World) (*component.TrainBaliseTelegram, error) {
result := <-ecs.Request[*component.TrainBaliseTelegram](w, func() ecs.Result[*component.TrainBaliseTelegram] {
//获取当前关联CANET设备的列车
canetTrain := findCanetTrain(w)
if canetTrain == nil {
return ecs.NewResult[*component.TrainBaliseTelegram](nil, fmt.Errorf("系统中当前不存在与CANET设备关联的列车实体"))
}
//
train := component.TrainBtmType.Get(canetTrain)
tbt := train.FindScannedBalises()
if tbt != nil {
return ecs.NewOkResult(tbt)
} else {
return ecs.NewResult[*component.TrainBaliseTelegram](nil, fmt.Errorf("此刻没有要发送的应答器报文"))
}
})
return result.Val, result.Err
}
var trainQuery = ecs.NewQuery(filter.Contains(component.UidType, component.TrainPositionInfoType, component.TrainBtmType))
// 获取当前关联CANET设备的列车
func findCanetTrain(w ecs.World) *ecs.Entry {
var canetTrain *ecs.Entry = nil
trainQuery.Each(w, func(entry *ecs.Entry) { //目前默认取第一辆
if canetTrain == nil {
canetTrain = entry
}
})
return canetTrain
}
// /////////////////////////////////////////////////////////////////////////////////////////
type TrainBtmStatus struct {
TrainId string
PowerAmplifierOn bool //BTM功率放大器是否开启
PowerAmplifierFault bool //BTM功率放大器是否有故障
AntennaFault bool //BTM应答器天线是否有故障
AboveBalise bool //BTM当前是否在应答器上方
BaliseCounter int //应答器计数(每过一个应答器加一,在同一个应答器内不变)
MessageCounter int //报文计数器(每解出一个应答器报文加一)
}
type TrainPositionInfo struct {
//列车id
TrainId string
//列车头当前运行方向true偏移量增大/false减小方向
Up bool
//列车长度 mm
Len uint32
//列车所在轨道link
HeadLink string
//列车所在link偏移量mm
HeadLinkOffset uint32
//列车所在轨道link
TailLink string
//列车所在link偏移量mm
TailLinkOffset uint32
}