rts-sim-testing-service/ts/simulation/wayside/memory/wayside_memory_train.go

419 lines
16 KiB
Go
Raw Normal View History

package memory
import (
"fmt"
2024-01-17 17:02:17 +08:00
"joylink.club/bj-rtsts-server/dto/common_proto"
"joylink.club/bj-rtsts-server/service"
2023-12-05 09:37:34 +08:00
"joylink.club/bj-rtsts-server/third_party/can_btm"
"log/slog"
2024-01-17 13:09:45 +08:00
"reflect"
"strconv"
"time"
"joylink.club/bj-rtsts-server/dto"
2023-11-09 17:54:31 +08:00
"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"
)
2024-01-17 15:53:14 +08:00
func CreateMsgTrainConfig(trainId int, trainLen int64, configTrainData dto.ConfigTrainData) *message.TrainOperationConfig {
return &message.TrainOperationConfig{TrainIndex: trainId, Length: int(trainLen),
2024-01-18 17:17:48 +08:00
DavisParamA: configTrainData.DavisParamA, DavisParamB: configTrainData.DavisParamB,
DavisParamC: configTrainData.DavisParamC, CurveResistanceParamR1: configTrainData.CurveResistanceParamR1,
2024-01-17 15:53:14 +08:00
CurveResistanceParamR2: configTrainData.CurveResistanceParamR2, CurveResistanceParamR3: configTrainData.CurveResistanceParamR3,
CurveResistanceParamR4: configTrainData.CurveResistanceParamR4, RevolvingMassParam: configTrainData.RevolvingMassParam,
2024-01-29 14:22:12 +08:00
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),
2024-01-17 15:53:14 +08:00
StopSign: int(configTrainData.StopSign)}
}
// 增加列车状态
2024-01-17 17:02:17 +08:00
func AddTrainStateNew(vs *VerifySimulation, status *state_proto.TrainState, configTrainData dto.ConfigTrainData, trainEndsA dto.ConfigTrainEnds,
trainEndsB dto.ConfigTrainEnds, mapId int32) *sys_error.BusinessError {
2024-01-17 15:53:14 +08:00
allTrainMap := &vs.Memory.Status.TrainStateMap
value, ok := allTrainMap.Load(status.Id)
2024-01-17 15:53:14 +08:00
if ok {
trainState := value.(*state_proto.TrainState)
if trainState.Show {
return sys_error.New(fmt.Sprintf("列车【%s】已存在", status.Id))
}
2024-01-17 15:53:14 +08:00
}
// 显示状态
status.Show = true
//向动力学发送初始化请求
trainIndex, _ := strconv.ParseUint(status.Id, 10, 16)
slog.Debug("添加列车", "trainIndex", trainIndex, "HeadDeviceId", status.HeadDeviceId, "HeadOffset", status.HeadOffset)
// 映射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.RunDirection)
// 车头所在公里标
kilometer := CalcTrainKilometer(vs.Repo, uid, status.DevicePort, status.RunDirection, status.HeadOffset)
// 车尾相对车头link的偏移量
calctailOffset := calcTrailTailOffset(loffset, status.TrainLength, up)
// 车尾位置
tailLink, tailDeviceId, tailDevicePort, tailLOffset, tailDeviceOffset, _, e1 := CalcInitializeLink(vs, linkId, calctailOffset, up)
2024-01-17 15:53:14 +08:00
if e1 != nil {
panic(sys_error.New("添加列车失败,列车车尾占用位置计算出错", e1))
}
status.Up = up
status.PointTo = pointTo
status.TrainKilometer = kilometer.Value
status.DynamicState = &state_proto.TrainDynamicState{
HeadLinkId: linkId,
HeadLinkOffset: loffset,
TailLinkId: tailLink,
TailLinkOffset: tailLOffset,
RunningUp: up,
}
status.TailDeviceId = vs.GetComIdByUid(tailDeviceId)
status.TailOffset = tailDeviceOffset
status.TailDevicePort = tailDevicePort
2024-01-17 15:53:14 +08:00
//初始化列车参数状态
2024-01-17 17:02:17 +08:00
createOrUpdateStateDynamicConfig(status, configTrainData, trainEndsA, trainEndsB)
2024-01-17 15:53:14 +08:00
status.VobcState = &state_proto.TrainVobcState{}
slog.Debug("列车初始化", "trainIndex", trainIndex, "linkId", linkId, "loffset", loffset)
linkIdInt, _ := strconv.Atoi(linkId)
err := dynamics.Default().RequestAddTrain(&message.InitTrainInfo{
TrainIndex: uint16(trainIndex),
LinkIndex: uint16(linkIdInt),
LinkOffset: uint32(loffset),
Speed: status.Speed / 3.6,
2024-01-17 15:53:14 +08:00
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
2024-01-17 15:53:14 +08:00
}
// 增加列车状态
2024-01-17 15:53:14 +08:00
/*func AddTrainState(vs *VerifySimulation, status *state_proto.TrainState, mapId int32) *state_proto.TrainState {
2023-09-12 10:00:13 +08:00
allTrainMap := &vs.Memory.Status.TrainStateMap
_, ok := allTrainMap.Load(status.Id)
if ok {
panic(fmt.Sprintf("列车【%s】已存在", status.Id))
}
2023-08-02 15:50:46 +08:00
// 显示状态
status.Show = true
//向动力学发送初始化请求
trainIndex, _ := strconv.ParseUint(status.Id, 10, 16)
2023-11-08 11:02:41 +08:00
slog.Debug("添加列车", "trainIndex", trainIndex, "HeadDeviceId", status.HeadDeviceId, "HeadOffset", status.HeadOffset)
2023-08-14 16:27:03 +08:00
// 映射link、偏移量、运行方向
2023-11-08 11:02:41 +08:00
var uid string
if status.DevicePort == "" {
uid = QueryUidByMidAndComId(mapId, status.HeadDeviceId, &data_proto.Section{})
2023-11-08 11:02:41 +08:00
} else {
uid = QueryUidByMidAndComId(mapId, status.HeadDeviceId, &data_proto.Turnout{})
2023-11-08 11:02:41 +08:00
}
// 车头所在link、link上的偏移
linkId, loffset := QueryLinkAndOffsetByDevice(vs.Repo, uid, status.DevicePort, status.HeadOffset)
// link上的运行方向、设备上的运行方向
up, pointTo := QueryUpAndABByDevice(vs.Repo, uid, status.DevicePort, status.RunDirection)
// 车头所在公里标
kilometer := CalcTrainKilometer(vs.Repo, uid, status.DevicePort, status.RunDirection, status.HeadOffset)
// 车尾相对车头link的偏移量
2023-11-10 09:28:27 +08:00
calctailOffset := calcTrailTailOffset(loffset, status.TrainLength, up)
2023-11-08 11:02:41 +08:00
// 车尾位置
2023-11-10 10:54:35 +08:00
tailLink, _, _, tailLOffset, _, _, e1 := CalcInitializeLink(vs, linkId, calctailOffset, up)
2023-11-09 17:54:31 +08:00
if e1 != nil {
panic(sys_error.New("添加列车失败,列车车尾占用位置计算出错", e1))
}
2023-08-14 16:27:03 +08:00
status.Up = up
2023-08-15 10:18:39 +08:00
status.PointTo = pointTo
2023-11-08 11:02:41 +08:00
status.TrainKilometer = kilometer.Value
status.DynamicState = &state_proto.TrainDynamicState{
2023-11-08 11:02:41 +08:00
HeadLinkId: linkId,
HeadLinkOffset: loffset,
TailLinkId: tailLink,
TailLinkOffset: tailLOffset,
RunningUp: up,
}
status.VobcState = &state_proto.TrainVobcState{}
2023-11-08 11:02:41 +08:00
slog.Debug("列车初始化", "trainIndex", trainIndex, "linkId", linkId, "loffset", loffset)
linkIdInt, _ := strconv.Atoi(linkId)
err := dynamics.Default().RequestAddTrain(&message.InitTrainInfo{
TrainIndex: uint16(trainIndex),
2023-11-08 11:02:41 +08:00
LinkIndex: uint16(linkIdInt),
LinkOffset: uint32(loffset),
Speed: uint16(math.Round(float64(status.Speed * 10))),
Up: status.Up,
2023-11-10 09:28:27 +08:00
TrainLength: uint32(status.TrainLength),
})
if err != nil {
panic(dto.ErrorDto{Code: dto.DynamicsError, Message: err.Error()})
}
// world中加车
fi.AddTrainToWorld(vs.World, status.Id)
2023-11-10 10:54:35 +08:00
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 status
2024-01-17 15:53:14 +08:00
}*/
2023-08-01 17:45:26 +08:00
2024-01-17 17:02:17 +08:00
func createOrUpdateStateDynamicConfig(trainState *state_proto.TrainState, configTrainData dto.ConfigTrainData, trainEndsA dto.ConfigTrainEnds,
trainEndsB dto.ConfigTrainEnds) {
2024-01-18 10:48:04 +08:00
trainState.TrainDynamicConfig = service.TrainConfigToProtoConvert(&configTrainData)
2024-01-22 17:46:26 +08:00
if trainState.TrainDynamicConfig != nil {
2024-01-18 13:57:57 +08:00
copyTrainEnds(trainState, "TrainEndsA", trainEndsA)
copyTrainEnds(trainState, "TrainEndsB", trainEndsB)
2024-01-16 17:53:54 +08:00
}
2024-01-17 13:09:45 +08:00
}
2024-01-17 17:02:17 +08:00
func copyTrainEnds(trainState *state_proto.TrainState, fieldName string, configData dto.ConfigTrainEnds) {
2024-01-17 13:09:45 +08:00
fieldVal := reflect.ValueOf(trainState).Elem().FieldByName(fieldName)
2024-01-17 17:02:17 +08:00
endsVal := fieldVal.Interface().(*common_proto.TrainEndsState)
2024-01-17 13:09:45 +08:00
if endsVal == nil {
2024-01-17 17:02:17 +08:00
endsVal = &common_proto.TrainEndsState{}
2024-01-17 13:09:45 +08:00
fieldVal.Set(reflect.ValueOf(endsVal))
}
2024-01-17 15:53:14 +08:00
endsVal.SpeedSensorEnableA = configData.SpeedSensorEnableA
2024-01-18 13:57:57 +08:00
endsVal.SpeedSensorEnableB = configData.SpeedSensorEnableB
2024-01-17 13:09:45 +08:00
endsVal.RadarEnable = configData.RadarEnable
2024-01-18 16:33:27 +08:00
endsVal.RadarCheckSpeedDiff = configData.RadarCheckSpeedDiff
2024-01-17 13:09:45 +08:00
endsVal.RadarCheckTime = configData.RadarCheckTime
2024-01-26 17:57:35 +08:00
endsVal.AccEnable = configData.AccEnable
endsVal.AccCheckSpeedDiff = configData.AccCheckSpeedDiff
endsVal.AccCheckTime = configData.AccCheckTime
2024-01-16 17:53:54 +08:00
}
2024-01-17 15:53:14 +08:00
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)))
}
2024-01-17 17:02:17 +08:00
createOrUpdateStateDynamicConfig(trainState, ct.ConfigData, ct.TrainEndsA, ct.TrainEndsB)
2024-01-17 15:53:14 +08:00
trainState.TrainLength = ct.Length
trainState.WheelDiameter = ct.WheelDiameter
2024-01-18 17:17:48 +08:00
requestDynamicConfig(ct)
2024-01-17 15:53:14 +08:00
}
2024-01-16 17:53:54 +08:00
2024-01-17 13:09:45 +08:00
func requestDynamicConfig(ct *dto.ConfigTrainReqDto) {
2024-01-17 15:53:14 +08:00
msg := CreateMsgTrainConfig(ct.TrainId, ct.Length, ct.ConfigData)
2024-01-17 13:09:45 +08:00
err2 := dynamics.Default().TrainOperationConfig(msg)
err := err2
2024-01-16 17:53:54 +08:00
if err != nil {
slog.Error("列车参数变更请求动力学失败", err)
panic(sys_error.New(fmt.Sprintf("列车参数变更请求动力学失败")))
}
}
2023-11-13 15:57:32 +08:00
// 修改列车信息
func UpdateTrainInfo(vs *VerifySimulation, status *state_proto.TrainState) *state_proto.TrainState {
2023-11-13 15:57:32 +08:00
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)
2023-11-13 15:57:32 +08:00
sta.TrainLength = status.TrainLength
sta.WheelDiameter = status.WheelDiameter
return sta
2023-11-13 15:57:32 +08:00
}
// 根据动力学发来的信息修改列车状态
func UpdateTrainStateByDynamics(vs *VerifySimulation, trainId string, info *message.DynamicsTrainInfo) *state_proto.TrainState {
data, ok := vs.Memory.Status.TrainStateMap.Load(trainId)
2023-08-01 17:45:26 +08:00
if !ok {
2023-11-09 17:54:31 +08:00
panic(sys_error.New(fmt.Sprintf("动力学传输数据:列车【%s】不存在", trainId)))
}
sta := data.(*state_proto.TrainState)
delayTime := time.Now().UnixMilli() - sta.VobcState.UpdateTime
sta.ControlDelayTime = (int64(sta.VobcState.LifeSignal)-int64(info.VobcLifeSignal))*20 + delayTime
2023-11-28 13:30:10 +08:00
//slog.Debug("收到动力学原始消息", "Number", info.Number, "Link", info.Link, "LinkOffset", info.LinkOffset)
inLinkId, inLinkOffset := strconv.Itoa(int(info.Link)), int64(info.LinkOffset)
2023-11-09 17:54:31 +08:00
outLinkId, id, port, outLinkOffset, offset, kilometer, e1 := CalcInitializeLink(vs, inLinkId, inLinkOffset, info.Up)
if e1 != nil {
panic(sys_error.New("动力学传输数据:列车车头位置计算出错", e1))
}
runDirection, pointTo := QueryDirectionAndABByDevice(vs.Repo, id, port, info.Up)
2023-11-28 13:30:10 +08:00
//slog.Debug("处理动力学转换后的消息", "number", info.Number, "车头位置", id, "偏移", offset, "是否上行", runDirection, "是否ab", pointTo)
// 车尾相对车头link的偏移量
2023-11-09 17:54:31 +08:00
calctailOffset := calcTrailTailOffset(outLinkOffset, int64(info.Len), info.Up)
tailLinkId, tailDeviceId, tailDevicePort, tailLinkOffset, tailOffset, _, e2 := CalcInitializeLink(vs, outLinkId, calctailOffset, info.Up)
2023-11-09 17:54:31 +08:00
if e2 != nil {
panic(sys_error.New("动力学传输数据:列车车尾位置计算出错", e2))
}
2023-11-28 13:30:10 +08:00
//slog.Debug("车尾位置", tailDeviceId, "偏移", tailDeviceOffset, "所在设备端", tailDevicePort)
2023-12-05 09:37:34 +08:00
// 更新BTM中列车位置信息
can_btm.Default().HandleTrainHeadPositionInfo(vs.World, &fi.TrainHeadPositionInfo{
TrainId: trainId,
Up: info.Up,
Link: outLinkId,
LinkOffset: outLinkOffset,
Speed: info.Speed,
Acceleration: info.Acceleration,
})
state := can_btm.Default().GetState()
sta.BtmState = &state
2023-11-10 10:54:35 +08:00
// 修改world中的列车位置
fi.UpdateTrainPositionFromDynamics(vs.World, fi.TrainPositionInfo{
TrainId: trainId,
Up: info.Up,
Len: info.Len,
HeadLink: outLinkId,
HeadLinkOffset: uint32(outLinkOffset),
TailLink: tailLinkId,
TailLinkOffset: uint32(tailLinkOffset),
})
sta.HeadDeviceId = vs.GetComIdByUid(id)
sta.DevicePort = port
sta.HeadOffset = offset
sta.PointTo = pointTo
sta.TrainKilometer = kilometer.Value
sta.RunDirection = runDirection
//判定车头方向
sta.HeadDirection = runDirection
if sta.VobcState != nil {
if sta.VobcState.DirectionForward {
sta.HeadDirection = runDirection
} else if sta.VobcState.DirectionBackward {
sta.HeadDirection = !runDirection
}
2023-08-01 17:45:26 +08:00
}
if info.Speed < 0 {
sta.RunDirection = !sta.RunDirection
}
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
2024-01-26 17:57:35 +08:00
sta.DynamicState.Displacement = int32(info.Displacement)
return sta
}
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)
//train := t.(*state_proto.TrainState)
//err := removeTrain(vs, train.Id, train)
//if err != nil {
// slog.Error("列车id:", train.Id, "移除失败,原因:", err.Error())
//}
//allTrainMap.Store(train.Id, t)
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 {
return err
}
train.Show = false
return fi.RemoveTrainFromWorld(vs.World, trainId)
}
// 删除列车状态
/*func RemoveTrainState(vs *VerifySimulation, id string) {
2023-09-12 10:00:13 +08:00
allTrainMap := &vs.Memory.Status.TrainStateMap
2023-08-02 15:50:46 +08:00
d, ok := allTrainMap.Load(id)
if ok {
t := d.(*state_proto.TrainState)
trainIndex, _ := strconv.ParseUint(id, 10, 16)
err := dynamics.Default().RequestRemoveTrain(&message.RemoveTrainReq{
TrainIndex: uint16(trainIndex),
})
if err != nil {
panic(dto.ErrorDto{Code: dto.DynamicsError, Message: err.Error()})
}
// 从仿真内存中移除列车
2023-08-02 15:50:46 +08:00
t.Show = false
// 移除车
fi.RemoveTrainFromWorld(vs.World, id)
2023-08-02 15:50:46 +08:00
allTrainMap.Store(id, t)
} else {
panic(fmt.Sprintf("列车【%s】不存在", id))
}
}*/
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)
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
}