rts-sim-testing-service/ts/simulation/wayside/memory/wayside_memory_train.go
tiger_zhou f9ffa1cf10 折返
2024-09-10 15:37:40 +08:00

531 lines
20 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 memory
import (
"fmt"
"joylink.club/bj-rtsts-server/dto/common_proto"
"joylink.club/bj-rtsts-server/service"
"joylink.club/bj-rtsts-server/third_party/can_btm"
"joylink.club/bj-rtsts-server/third_party/train_pc_sim"
"log/slog"
"reflect"
"strconv"
"time"
"joylink.club/bj-rtsts-server/dto"
"joylink.club/bj-rtsts-server/sys_error"
"joylink.club/bj-rtsts-server/third_party/dynamics"
"joylink.club/bj-rtsts-server/third_party/message"
"joylink.club/rtsssimulation/fi"
"joylink.club/bj-rtsts-server/dto/data_proto"
"joylink.club/bj-rtsts-server/dto/state_proto"
)
const (
//列车总质量(吨)
DEFULAT_TRAIN_LOAD = 160
//通号最大制动力是-1.21
//DEFAULT_BRAKE_FORCE = 1.21
//通号最大加速度是0.97
//DEFAULT_TRAIN_TRACTION_ACC = 0.97 //加速度
//DEFAULT_TRAIN_STARTED_SPEED float64 = 80 / 3.6 //列车起步速度单位 米/秒
)
func CreateMsgTrainConfig(trainId int, trainLen int64, configTrainData dto.ConfigTrainData) *message.TrainOperationConfig {
return &message.TrainOperationConfig{TrainIndex: trainId, Length: int(trainLen),
DavisParamA: configTrainData.DavisParamA, DavisParamB: configTrainData.DavisParamB,
DavisParamC: configTrainData.DavisParamC, CurveResistanceParamR1: configTrainData.CurveResistanceParamR1,
CurveResistanceParamR2: configTrainData.CurveResistanceParamR2, CurveResistanceParamR3: configTrainData.CurveResistanceParamR3,
CurveResistanceParamR4: configTrainData.CurveResistanceParamR4, RevolvingMassParam: configTrainData.RevolvingMassParam,
Jump: configTrainData.Jump, Slide: configTrainData.Slide,
SlipA: configTrainData.SlipA, SlipR: configTrainData.SlipR, SlipD: int(configTrainData.SlipD),
IdlingA: configTrainData.IdlingA, IdlingR: configTrainData.IdlingR, IdlingD: int(configTrainData.IdlingD),
StopSign: int(configTrainData.StopSign)}
}
// 增加列车状态
func AddTrainStateNew(vs *VerifySimulation, status *state_proto.TrainState, configTrainData dto.ConfigTrainData, trainEndsA dto.ConfigTrainEnds,
trainEndsB dto.ConfigTrainEnds, mapId int32) *sys_error.BusinessError {
allTrainMap := &vs.Memory.Status.TrainStateMap
value, ok := allTrainMap.Load(status.Id)
if ok {
trainState := value.(*state_proto.TrainState)
if trainState.Show {
return sys_error.New(fmt.Sprintf("列车【%s】已存在", status.Id))
}
}
//向动力学发送初始化请求
trainIndex, _ := strconv.ParseUint(status.Id, 10, 16)
// 映射link、偏移量、运行方向
var uid string
if status.DevicePort == "" {
uid = QueryUidByMidAndComId(mapId, status.HeadDeviceId, &data_proto.Section{})
} else {
uid = QueryUidByMidAndComId(mapId, status.HeadDeviceId, &data_proto.Turnout{})
}
// 车头所在link、link上的偏移
linkId, loffset := QueryLinkAndOffsetByDevice(vs.Repo, uid, status.DevicePort, status.HeadOffset)
// link上的运行方向、设备上的运行方向
up, pointTo := QueryUpAndABByDevice(vs.Repo, uid, status.DevicePort, status.TrainRunUp)
// 车头所在公里标
kilometer := CalcTrainKilometer(vs.Repo, uid, status.DevicePort, status.TrainRunUp, status.HeadOffset)
// 车尾相对车头link的偏移量
calctailOffset := calcTrailTailOffset(loffset, status.TrainLength, up)
// 车尾位置
tailLink, tailDeviceId, tailDevicePort, tailLOffset, tailDeviceOffset, _, e1 := CalcInitializeLink(vs, linkId, calctailOffset, up)
if e1 != nil {
panic(sys_error.New("添加列车失败,列车车尾占用位置计算出错", e1))
}
status.Up = up
status.DriftTo = pointTo
status.TrainKilometer = kilometer.Value
status.DynamicState = &state_proto.TrainDynamicState{
HeadLinkId: linkId,
HeadLinkOffset: loffset,
TailLinkId: tailLink,
TailLinkOffset: tailLOffset,
RunningUp: status.Up,
//RunningUp: status.TrainRunUp,
}
status.TailDeviceId = vs.GetComIdByUid(tailDeviceId)
status.TailOffset = tailDeviceOffset
status.TailDevicePort = tailDevicePort
status.BtmBaliseCacheA = &state_proto.TrainBtmCache{BaliseList: make([]*state_proto.BTMState, 3)}
status.BtmBaliseCacheB = &state_proto.TrainBtmCache{BaliseList: make([]*state_proto.BTMState, 3)}
//初始化列车参数状态
createOrUpdateStateDynamicConfig(status, configTrainData, trainEndsA, trainEndsB)
tl := status.TrainLoad * 100
if tl <= 0 {
tl = DEFULAT_TRAIN_LOAD * 100
}
vobc, _ := initTrainVobc(int64(tl), status.TrainRunUp, status.TrainMaxBrake)
status.VobcState = vobc
status.Tcc = initTrainTcc(vs)
//status.VobcBtm = &state_proto.VobcBtmState{TelegramState: make([]*state_proto.VobcBtmState_TelegramState, 3), History: make(map[uint32]*state_proto.VobcBtmState_VobcBtmHistoryState)}
linkIdInt, _ := strconv.Atoi(linkId)
err := dynamics.Default().RequestAddTrain(&message.InitTrainInfo{
TrainIndex: uint16(trainIndex),
LinkIndex: uint16(linkIdInt),
LinkOffset: uint32(loffset),
Speed: status.Speed / 3.6,
Up: status.Up,
TrainOperationConfig: CreateMsgTrainConfig(int(trainIndex), status.TrainLength, configTrainData),
})
if err != nil {
panic(dto.ErrorDto{Code: dto.DynamicsError, Message: err.Error()})
}
// world中加车
fi.AddTrainToWorld(vs.World, status.Id)
fi.UpdateTrainPositionFromDynamics(vs.World, fi.TrainPositionInfo{
TrainId: status.Id,
Up: status.Up,
Len: uint32(status.TrainLength),
HeadLink: linkId,
HeadLinkOffset: uint32(loffset),
TailLink: tailLink,
TailLinkOffset: uint32(tailLOffset),
})
// 将信息合并到当前设备状态中
allTrainMap.Store(status.Id, status)
return nil
}
// 列车连接类型更新
func TrainConnTypeUpdate(vs *VerifySimulation, ct *dto.TrainConnThirdDto) {
allTrainMap := &vs.Memory.Status.TrainStateMap
data, ok := allTrainMap.Load(ct.Id)
if !ok {
panic(sys_error.New(fmt.Sprintf("列车【%s】不存在", ct.Id)))
}
train := data.(*state_proto.TrainState)
if train.DynamicState.Speed != 0 {
panic(sys_error.New(fmt.Sprintf("列车[%s]需要停稳才能连接半实物", train.Id)))
}
if ct.ConnType != state_proto.TrainConnState_NONE {
//列车连接 半实物或车载pc仿真
allTrainMap.Range(func(k, v any) bool {
tmpTrain := v.(*state_proto.TrainState)
connState := tmpTrain.ConnState
if connState.Conn {
connTypeName := "半实物"
if connState.ConnType == state_proto.TrainConnState_PC_SIM && connState.TypeName == ct.TypeName {
connTypeName = fmt.Sprintf("车载pc仿真-%v", ct.TypeName)
}
panic(sys_error.New(fmt.Sprintf("列车[%s]已经连接 [%v],此列车无法连接", k, connTypeName)))
return false
}
return true
})
}
train.ConnState.Conn = true
train.ConnState.ConnType = ct.ConnType
train.ConnState.TypeName = ct.TypeName
if ct.ConnType == state_proto.TrainConnState_PC_SIM {
//train.Tcc.LineInitTimeStamp12 = 0
train.Tcc.LineInitTimeStamp12PortA = 0
train.Tcc.LineInitTimeStamp12PortB = 0
err := TrainPcSimConnOrRemoveHandle(train, true)
if err != nil {
train.ConnState.Conn = false
train.ConnState.ConnType = state_proto.TrainConnState_NONE
panic(sys_error.New(err.Error()))
}
//train_pc_sim.Default().SendDriverActive(train)
}
}
// 列车断开三方连接
func TrainUnConn(vs *VerifySimulation, trainId string) {
allTrainMap := &vs.Memory.Status.TrainStateMap
data, ok := allTrainMap.Load(trainId)
if !ok {
panic(sys_error.New(fmt.Sprintf("列车【%s】不存在", trainId)))
}
train := data.(*state_proto.TrainState)
err := TrainPcSimConnOrRemoveHandle(train, false)
if err != nil {
panic(sys_error.New("未连接车载PC仿真无法断开连接"))
}
defer func() {
train.ConnState.Conn = false
train.ConnState.ConnType = state_proto.TrainConnState_NONE
train.ConnState.TypeName = ""
}()
}
func createOrUpdateStateDynamicConfig(trainState *state_proto.TrainState, configTrainData dto.ConfigTrainData, trainEndsA dto.ConfigTrainEnds,
trainEndsB dto.ConfigTrainEnds) {
trainState.TrainDynamicConfig = service.TrainConfigToProtoConvert(&configTrainData)
if trainState.TrainDynamicConfig != nil {
copyTrainEnds(trainState, "TrainEndsA", trainEndsA)
copyTrainEnds(trainState, "TrainEndsB", trainEndsB)
}
}
func copyTrainEnds(trainState *state_proto.TrainState, fieldName string, configData dto.ConfigTrainEnds) {
fieldVal := reflect.ValueOf(trainState).Elem().FieldByName(fieldName)
endsVal := fieldVal.Interface().(*common_proto.TrainEndsState)
if endsVal == nil {
endsVal = &common_proto.TrainEndsState{}
fieldVal.Set(reflect.ValueOf(endsVal))
}
endsVal.SpeedSensorEnableA = configData.SpeedSensorEnableA
endsVal.SpeedSensorEnableB = configData.SpeedSensorEnableB
endsVal.AccOutSpeed = configData.AccOutSpeed
endsVal.RadarEnable = configData.RadarEnable
endsVal.RadarCheckTime = configData.RadarCheckTime
endsVal.RadarCheckSpeedDiff = configData.RadarCheckSpeedDiff
endsVal.RadarOutSpeed = configData.RadarOutSpeed
endsVal.AccEnable = configData.AccEnable
endsVal.AccCheckSpeedDiff = configData.AccCheckSpeedDiff
endsVal.AccCheckTime = configData.AccCheckTime
}
func UpdateConfigTrain(vs *VerifySimulation, ct *dto.ConfigTrainReqDto) {
allTrainMap := &vs.Memory.Status.TrainStateMap
data, ok := allTrainMap.Load(strconv.Itoa(ct.TrainId))
if !ok {
panic(sys_error.New(fmt.Sprintf("列车【%s】不存在", ct.TrainId)))
}
trainState, ok := data.(*state_proto.TrainState)
if !ok {
panic(sys_error.New(fmt.Sprintf("列车参数修改断言:列车【%s】不存在", ct.TrainId)))
}
createOrUpdateStateDynamicConfig(trainState, ct.ConfigData, ct.TrainEndsA, ct.TrainEndsB)
trainState.TrainLength = ct.Length
trainState.WheelDiameter = ct.WheelDiameter
requestDynamicConfig(ct)
trainState.TrainEndsA.RadarCheckTimeOverAt = 0
trainState.TrainEndsB.RadarCheckTimeOverAt = 0
trainState.TrainEndsA.AccCheckTimeOverAt = 0
trainState.TrainEndsB.AccCheckTimeOverAt = 0
if ct.TrainEndsA.RadarCheckTime > 0 {
timeAt := time.Now().Add(time.Second * time.Duration(ct.TrainEndsA.RadarCheckTime)).Unix()
trainState.TrainEndsA.RadarCheckTimeOverAt = timeAt
}
if ct.TrainEndsB.RadarCheckTime > 0 {
timeAt := time.Now().Add(time.Second * time.Duration(ct.TrainEndsB.RadarCheckTime)).Unix()
trainState.TrainEndsB.RadarCheckTimeOverAt = timeAt
}
if ct.TrainEndsA.AccCheckTime > 0 {
timeAt := time.Now().Add(time.Second * time.Duration(ct.TrainEndsA.AccCheckTime)).Unix()
trainState.TrainEndsA.AccCheckTimeOverAt = timeAt
}
if ct.TrainEndsB.AccCheckTime > 0 {
timeAt := time.Now().Add(time.Second * time.Duration(ct.TrainEndsB.AccCheckTime)).Unix()
trainState.TrainEndsB.AccCheckTimeOverAt = timeAt
}
}
func requestDynamicConfig(ct *dto.ConfigTrainReqDto) {
msg := CreateMsgTrainConfig(ct.TrainId, ct.Length, ct.ConfigData)
err2 := dynamics.Default().TrainOperationConfig(msg)
err := err2
if err != nil {
slog.Error("列车参数变更请求动力学失败", err)
panic(sys_error.New(fmt.Sprintf("列车参数变更请求动力学失败")))
}
}
// 修改列车信息
func UpdateTrainInfo(vs *VerifySimulation, status *state_proto.TrainState) *state_proto.TrainState {
allTrainMap := &vs.Memory.Status.TrainStateMap
data, ok := allTrainMap.Load(status.Id)
if !ok {
panic(sys_error.New(fmt.Sprintf("列车【%s】不存在", status.Id)))
}
sta := data.(*state_proto.TrainState)
sta.TrainLength = status.TrainLength
sta.WheelDiameter = status.WheelDiameter
return sta
}
// 根据动力学发来的信息修改列车状态
func UpdateTrainStateByDynamics(vs *VerifySimulation, trainId string, info *message.DynamicsTrainInfo) *state_proto.TrainState {
data, ok := vs.Memory.Status.TrainStateMap.Load(trainId)
if !ok {
panic(sys_error.New(fmt.Sprintf("动力学传输数据:列车【%s】不存在", trainId)))
}
sta := data.(*state_proto.TrainState)
if !sta.Show {
return sta
}
delayTime := time.Now().UnixMilli() - sta.VobcState.UpdateTime
sta.ControlDelayTime = (int64(sta.VobcState.LifeSignal)-int64(info.VobcLifeSignal))*20 + delayTime
//slog.Debug("收到动力学原始消息", "Number", info.Number, "Link", info.Link, "LinkOffset", info.LinkOffset)
inLinkId, inLinkOffset := strconv.Itoa(int(info.Link)), int64(info.LinkOffset)
outLinkId, id, port, outLinkOffset, offset, kilometer, e1 := CalcInitializeLink(vs, inLinkId, inLinkOffset, info.Up)
if e1 != nil {
panic(sys_error.New("动力学传输数据:列车车头位置计算出错", e1))
}
//runDirection 指定的是link方向
//pointTO 指的是是否ab或是否到岔心
_, pointTo := QueryDirectionAndABByDevice(vs.Repo, id, port, info.Up)
//slog.Debug("处理动力学转换后的消息", "number", info.Number, "up", info.Up, "Link", info.Link, "车头位置", id, "偏移", offset, "是否上行", true, "是否ab", pointTo, "t1Dir:", info.TrainActToMax, "t2Dir:", info.TrainActToMin)
trainHeadActUp := true
if info.TrainActToMax || info.TrainActToMin {
if info.TrainActToMin {
trainHeadActUp = false
}
}
// 车尾相对车头link的偏移量
//calctailOffset := calcTrailTailOffset(outLinkOffset, int64(info.Len), info.Up)
calctailOffset := calcTrailTailOffset(outLinkOffset, int64(info.Len), trainHeadActUp)
tailLinkId, tailDeviceId, tailDevicePort, tailLinkOffset, tailOffset, _, e2 := CalcInitializeLink(vs, outLinkId, calctailOffset, !info.Up)
tailUp, _ := QueryUpAndABByDevice(vs.Repo, tailDeviceId, tailDevicePort, sta.TrainRunUp)
if e2 != nil {
panic(sys_error.New("动力学传输数据:列车车尾位置计算出错", e2))
}
//slog.Debug("车尾位置", tailDeviceId, "偏移", tailDeviceOffset, "所在设备端", tailDevicePort)
// 修改world中的列车位置
handleTrainPositionFromDynamic(vs, info, sta, outLinkId, outLinkOffset, tailLinkId, tailLinkOffset)
//修改列车激活方向
updateTrainActiveDirFromDynamic(vs, info, sta, id, port, trainHeadActUp)
if sta.OldLinkOffset == 0 {
sta.OldLinkOffset = outLinkOffset
sta.OldLink = outLinkId
}
if sta.OldTailLinkOffset == 0 {
sta.OldTailLinkOffset = tailLinkOffset
sta.OldTailLink = tailLinkId
}
updateTrainBtmPosition(vs, info, sta, outLinkId, outLinkOffset, tailUp, tailLinkId, tailLinkOffset)
//slog.Info(fmt.Sprintf("动力学,当前速度(米/秒):%v,加速度:%v,位移距离:%v", info.Speed, info.Acceleration, info.Displacement))
if sta.OldLink != outLinkId {
sta.OldLink = outLinkId
}
if sta.OldLinkOffset != outLinkOffset {
sta.OldLinkOffset = outLinkOffset
}
sta.HeadDeviceId = vs.GetComIdByUid(id)
sta.DevicePort = port
sta.HeadOffset = offset
sta.DriftTo = pointTo
sta.TrainKilometer = kilometer.Value
sta.TailDeviceId = vs.GetComIdByUid(tailDeviceId)
sta.TailOffset = tailOffset
sta.TailDevicePort = tailDevicePort
// 赋值动力学信息
sta.DynamicState.Heartbeat = int32(info.LifeSignal)
sta.DynamicState.HeadLinkId = outLinkId
sta.DynamicState.HeadLinkOffset = outLinkOffset
sta.DynamicState.TailLinkId = tailLinkId
sta.DynamicState.TailLinkOffset = tailLinkOffset
sta.DynamicState.Slope = int32(info.Slope)
sta.DynamicState.Upslope = info.UpSlope
sta.DynamicState.RunningUp = info.Up
sta.DynamicState.RunningResistanceSum = float32(info.TotalResistance) / 1000
sta.DynamicState.AirResistance = float32(info.AirResistance) / 1000
sta.DynamicState.RampResistance = float32(info.SlopeResistance) / 1000
sta.DynamicState.CurveResistance = float32(info.CurveResistance) / 1000
sta.DynamicState.Speed = speedParse(info.Speed)
sta.DynamicState.HeadSensorSpeed1 = speedParse(info.HeadSpeed1)
sta.DynamicState.HeadSensorSpeed2 = speedParse(info.HeadSpeed2)
sta.DynamicState.TailSensorSpeed1 = speedParse(info.TailSpeed1)
sta.DynamicState.TailSensorSpeed2 = speedParse(info.TailSpeed2)
sta.DynamicState.HeadRadarSpeed = speedParse(info.HeadRadarSpeed)
sta.DynamicState.TailRadarSpeed = speedParse(info.TailRadarSpeed)
sta.DynamicState.Acceleration = info.Acceleration
sta.DynamicState.Displacement = info.Displacement
//slog.Info(fmt.Sprintf("动力学返回速度:%v,位移:%v,加速度:%vtime:%v", info.Speed, info.Displacement, info.Acceleration, time.Now().UnixMilli()))
pluseCount(sta, info.HeadSpeed1, info.HeadSpeed2, info.TailSpeed1, info.TailSpeed2)
return sta
}
// 根据动力学列车激活端方向,返回前端列车激活端
// 道岔 1是端口到岔心 2是岔心到端口
// 区段 1是a-b 2是b-a
func updateTrainActiveDirFromDynamic(vs *VerifySimulation, info *message.DynamicsTrainInfo, sta *state_proto.TrainState, id, port string, trainHeadActUp bool) {
sta.TrainActiveDirection = 0
if info.TrainActToMax || info.TrainActToMin {
_, pointTo2 := QueryDirectionAndABByDevice(vs.Repo, id, port, trainHeadActUp)
pt := pointTo2
if pt {
sta.TrainActiveDirection = 1
} else {
sta.TrainActiveDirection = 2
}
}
}
// 根据列车位置修改列车应答器
func updateTrainBtmPosition(vs *VerifySimulation, info *message.DynamicsTrainInfo, sta *state_proto.TrainState, outLinkId string, outLinkOffset int64, tailUp bool, tailLinkId string, tailLinkOffset int64) {
// 更新BTM中列车位置信息
//isup := sta.TrainActiveDirection == 1
can_btm.Default().HandleTrainHeadPositionInfoForTrain(vs.World, sta, &fi.TrainHeadPositionInfo{
TrainId: sta.Id,
Up: info.Up,
Link: outLinkId,
LinkOffset: outLinkOffset,
Speed: info.Speed,
Acceleration: info.Acceleration,
OldLinkOffset: sta.OldLinkOffset,
OldLink: sta.OldLink,
TailUp: tailUp,
TailLink: tailLinkId,
TailLinkOffset: tailLinkOffset,
OldTailLink: sta.OldTailLink,
OldTailLinkOffset: sta.OldTailLinkOffset,
IsLine12: can_btm.IsLine12(sta),
})
}
// 根据动力学修改列车位置
func handleTrainPositionFromDynamic(vs *VerifySimulation, info *message.DynamicsTrainInfo, sta *state_proto.TrainState, outLinkId string, outLinkOffset int64, tailLinkId string, tailLinkOffset int64) {
fi.UpdateTrainPositionFromDynamics(vs.World, fi.TrainPositionInfo{
TrainId: sta.Id,
Up: info.Up,
Len: info.Len,
HeadLink: outLinkId,
HeadLinkOffset: uint32(outLinkOffset),
TailLink: tailLinkId,
TailLinkOffset: uint32(tailLinkOffset),
})
}
func pluseCount(sta *state_proto.TrainState, h1, h2, t1, t2 float32) {
if sta.PluseCount == nil {
return
}
train_pc_sim.Default().TrainPluseCount(sta, h1, h2, t1, t2)
}
func RemoveAllTrain(vs *VerifySimulation) {
allTrainMap := &vs.Memory.Status.TrainStateMap
if allTrainMap == nil {
slog.Info("当前没有列车不能执行")
return
}
allTrainMap.Range(func(k any, t any) bool {
id := k.(string)
RemoveTrainState(vs, id)
return true
})
}
func removeTrain(vs *VerifySimulation, trainId string, train *state_proto.TrainState) error {
trainIndex, _ := strconv.ParseUint(trainId, 10, 16)
err := dynamics.Default().RequestRemoveTrain(&message.RemoveTrainReq{
TrainIndex: uint16(trainIndex),
})
if err != nil {
slog.Warn("列车移除失败,动力学请求失败", err)
}
thirdConn := train.ConnState
if thirdConn.Conn {
thirdConn.Conn = false
err = TrainPcSimConnOrRemoveHandle(train, false)
thirdConn.ConnType = state_proto.TrainConnState_NONE
thirdConn.TypeName = ""
}
if train.VobcState != nil {
vobc := train.VobcState
vobc.TractionStatus = false
vobc.BrakingStatus = true
vobc.TractionForce = 0
vobc.BrakeForce = trainBraking(train.TrainLoad, 100, train.TrainMaxBrake) / 1000 * 100
}
train.Show = false
return fi.RemoveTrainFromWorld(vs.World, trainId)
}
func RemoveTrainState(vs *VerifySimulation, id string) {
allTrainMap := &vs.Memory.Status.TrainStateMap
d, ok := allTrainMap.Load(id)
if ok {
t := d.(*state_proto.TrainState)
err := removeTrain(vs, id, t)
t.VobcState.VobcBtmInfo = nil
//clearTrainVobcBtmState(vs, id)
if err != nil {
panic(dto.ErrorDto{Code: dto.DynamicsError, Message: err.Error()})
}
allTrainMap.Store(id, t)
} else {
panic(fmt.Sprintf("列车【%s】不存在", id))
}
}
func calcTrailTailOffset(headerOffset, length int64, up bool) (calctailOffset int64) {
if up {
calctailOffset = headerOffset - length
} else {
calctailOffset = headerOffset + length
}
return
}
func clearTrainVobcBtmState(vs *VerifySimulation, id string) {
//allTrainMap := &vs.Memory.Status.TrainStateMap
//d, ok := allTrainMap.Load(id)
//if !ok {
// slog.Error(fmt.Sprintf("vobc btm 清空操作 列车【%s】不存在", id))
// return
//}
//t := d.(*state_proto.TrainState)
//t.VobcBtm.History = nil
}