From 2463edd99642a156e846b1e9d418d3a7028f5a09 Mon Sep 17 00:00:00 2001 From: tiger_zhou Date: Wed, 25 Sep 2024 11:19:18 +0800 Subject: [PATCH] =?UTF-8?q?=E5=81=9C=E8=BD=A6=E7=82=B9=E6=9E=84=E5=BB=BApr?= =?UTF-8?q?oto?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/simulation.go | 4 +- third_party/balisecodec/codec.go | 7 +- third_party/balisecodec/decode.go | 7 +- .../{btm_vobc.go => balise_vobc.go} | 9 ++- .../{btm_vobc_test.go => balise_vobc_test.go} | 0 .../semi_physical_train.go | 8 +- third_party/train_pc_sim/train_pc_sim.go | 80 +++++++++---------- .../wayside/memory/wayside_memory_train.go | 27 +++---- .../wayside/memory/wayside_simulation.go | 44 +++------- .../wayside_simulation_semi_physical.go | 50 ++++++++++++ ts/test_simulation_manage.go | 3 +- 11 files changed, 130 insertions(+), 109 deletions(-) rename third_party/semi_physical_train/{btm_vobc.go => balise_vobc.go} (97%) rename third_party/semi_physical_train/{btm_vobc_test.go => balise_vobc_test.go} (100%) create mode 100644 ts/simulation/wayside/memory/wayside_simulation_semi_physical.go diff --git a/api/simulation.go b/api/simulation.go index bc405b2..8d641d2 100644 --- a/api/simulation.go +++ b/api/simulation.go @@ -420,7 +420,7 @@ func removeAllTrain(c *gin.Context) { } slog.Debug("ATS测试仿真-移除所有列车,请求:", rt) simulation := checkDeviceDataAndReturn(rt.SimulationId) - memory.RemoveAllTrain(simulation) + memory.RemoveAllTrain(simulation, false) //TODO 后续调用列车删除操作 c.JSON(http.StatusOK, "ok") } @@ -448,7 +448,7 @@ func removeTrain(c *gin.Context) { } slog.Debug("ATS测试仿真-移除列车,请求:", rt) simulation := checkDeviceDataAndReturn(rt.SimulationId) - memory.RemoveTrainState(simulation, rt.TrainId) + memory.RemoveTrainState(simulation, rt.TrainId, false) //TODO 后续调用列车删除操作 c.JSON(http.StatusOK, "ok") } diff --git a/third_party/balisecodec/codec.go b/third_party/balisecodec/codec.go index 453f00b..7fb0b19 100644 --- a/third_party/balisecodec/codec.go +++ b/third_party/balisecodec/codec.go @@ -4,7 +4,6 @@ import ( "encoding/hex" "fmt" "log/slog" - "strconv" ) // 应答器数据编解码器 @@ -84,8 +83,8 @@ func checkCb(bits1023 []byte) error { cb := getRange(bits1023, 109, 107) for i, v := range cb { n := 109 - i - name := "b" + strconv.Itoa(109-i) - slog.Info("cb", name, v) + //name := "b" + strconv.Itoa(109-i) + //slog.Info("cb", name, v) if n == 109 && v == 1 { return buildError("控制位cb错误,b109应该为0,实际为1") } else if n == 108 && v == 1 { @@ -131,7 +130,7 @@ func calculateS(sb []byte) uint32 { B := ToValLeftMsb(sb) const A uint64 = 2801775573 S := uint32((A * uint64(B)) % (1 << 32)) - slog.Info("由12位加扰位计算得到整数S", "B", B, "S", S, "Sb", fmt.Sprintf("%032b", S)) + //slog.Info("由12位加扰位计算得到整数S", "B", B, "S", S, "Sb", fmt.Sprintf("%032b", S)) return S } diff --git a/third_party/balisecodec/decode.go b/third_party/balisecodec/decode.go index c362a62..8b85008 100644 --- a/third_party/balisecodec/decode.go +++ b/third_party/balisecodec/decode.go @@ -1,10 +1,5 @@ package balisecodec -import ( - "fmt" - "log/slog" -) - // 将830位的二进制数组以10位为单位组成一个左边为最高有效位(MSB)的无符号整数数组,除了第一个10位值,其余值求和,然后循环2的10次方次与其他值求和结果相加后模2的10次方,若结果和第一个10位值相同,则结束,此值即为原始的第一个10位值,将此值替换为第一个10位二进制数组,依然是左边为MSB func revertFirst10Bits(b []byte) []byte { if len(b) != 830 { @@ -37,7 +32,7 @@ func revertFirst10Bits(b []byte) []byte { break } } - slog.Info("还原第一个10位值", "sum", sum, "bits[0]", w10s[0], "bits[0]b", fmt.Sprintf("%010b", w10s[0])) + //slog.Info("还原第一个10位值", "sum", sum, "bits[0]", w10s[0], "bits[0]b", fmt.Sprintf("%010b", w10s[0])) bits := make([]byte, 830) // 将整个10位数组转换为二进制数组,依然是MSB u0bits := ToBitsLeftMsb(int(w10s[0]), 10) diff --git a/third_party/semi_physical_train/btm_vobc.go b/third_party/semi_physical_train/balise_vobc.go similarity index 97% rename from third_party/semi_physical_train/btm_vobc.go rename to third_party/semi_physical_train/balise_vobc.go index 39b5fb6..18225cf 100644 --- a/third_party/semi_physical_train/btm_vobc.go +++ b/third_party/semi_physical_train/balise_vobc.go @@ -20,10 +20,11 @@ import ( ) type BtmVobcManage interface { + SemiPhysicalBaseManager GetBtmVobcConfig() config.BtmVobcConfig - GetAllTrain() []*state_proto.TrainState - GetConnVobcTrain() *state_proto.TrainState + //GetAllTrain() []*state_proto.TrainState + } type BtmVobcService interface { Start(btmVobcManage BtmVobcManage) @@ -57,13 +58,13 @@ func BtmDefault() BtmVobcService { func (b *BtmVobcClient) Start(btmVobcManage BtmVobcManage) { cfg := btmVobcManage.GetBtmVobcConfig() if !cfg.Open { - slog.Info("11号线 btm vobc配置未开启...") + slog.Info("11号线 btm 配置未开启...") return } udpServer := udp.NewServer(fmt.Sprintf("%v:%d", cfg.LocalUdpIp, cfg.LocalUdpPort), b.handleBtmVobcFrames) err := udpServer.Listen() if err != nil { - slog.Error("11号线 btm VOBC 服务启动失败...") + slog.Error("11号线 btm 服务启动失败...") return } // diff --git a/third_party/semi_physical_train/btm_vobc_test.go b/third_party/semi_physical_train/balise_vobc_test.go similarity index 100% rename from third_party/semi_physical_train/btm_vobc_test.go rename to third_party/semi_physical_train/balise_vobc_test.go diff --git a/third_party/semi_physical_train/semi_physical_train.go b/third_party/semi_physical_train/semi_physical_train.go index 3846ee2..8b718e7 100644 --- a/third_party/semi_physical_train/semi_physical_train.go +++ b/third_party/semi_physical_train/semi_physical_train.go @@ -2,6 +2,7 @@ package semi_physical_train import ( "fmt" + "joylink.club/bj-rtsts-server/dto/state_proto" "sync" "joylink.club/bj-rtsts-server/config" @@ -20,10 +21,14 @@ type SemiPhysicalTrain interface { // 发送列车控制消息 SendTrainControlMessage(info *message.DynamicsTrainInfo) } - +type SemiPhysicalBaseManager interface { + GetConnVobcTrain() *state_proto.TrainState +} type SemiPhysicalMessageManager interface { + SemiPhysicalBaseManager // 处理半实物仿真列车控制消息 HandleSemiPhysicalTrainControlMsg(b []byte) + HandleSemiPhysicalTrainControlMsg2(b []byte) // 获取半实物启动参数 GetSemiPhysicalRunConfig() *config.VobcConfig } @@ -88,6 +93,7 @@ func (s *semiPhysicalTrainImpl) Start(manager SemiPhysicalMessageManager) { } func (s *semiPhysicalTrainImpl) Stop() { + initMutex.Lock() defer initMutex.Unlock() s.udpDelayRecorder.Stop() diff --git a/third_party/train_pc_sim/train_pc_sim.go b/third_party/train_pc_sim/train_pc_sim.go index 35f1ae0..04ebff6 100644 --- a/third_party/train_pc_sim/train_pc_sim.go +++ b/third_party/train_pc_sim/train_pc_sim.go @@ -126,7 +126,7 @@ func (d *trainPcSimService) findTrainConnForPort2(sta *state_proto.TrainState, t return rd, nil } } - return nil, fmt.Errorf("") + return nil, fmt.Errorf("未找到对应端口的列车 对应的端口:%v", trainClientPort.String()) } func (d *trainPcSimService) findTrainAllConn(sta *state_proto.TrainState) []*TrainPcReciverData { @@ -178,14 +178,13 @@ func (d *trainPcSimService) TrainPluseCount(sta *state_proto.TrainState, h1, h2, return default: } - + //slog.Info(fmt.Sprintf("接受列车速度:%v", h1)) for _, sd := range d.findTrainAllConn(sta) { if sd.speedPlace != nil { sd.speedPlace.PulseCount1 += sta.DynamicState.Displacement } } for _, pc := range sta.PulseCountMap { - if sta.TrainRunUp { if sta.TrainEndsA.SpeedSensorEnableA || sta.TrainEndsA.SpeedSensorEnableB { pc.PulseCount1 = pluseCountSpeed(sta.WheelDiameter, h1) @@ -259,7 +258,6 @@ func (d *trainPcSimService) initConn2(clientKey string) error { return sys_error.New(fmt.Sprintf("配置:%v 端口B连接失败", clientKey)) } if rd1.success { - //rd1.aPort = true rd1.RealTrainPort = state_proto.TrainState_PORT_A } if rd2.success { @@ -279,7 +277,6 @@ func (d *trainPcSimService) connServer(open bool, ip string, port uint32, rd *Tr return nil } addr := fmt.Sprintf("%v:%v", ip, port) - //slog.Info(addr, "连接.,...") client2, err := tcp.StartTcpClient(addr, rd.receiverDataHandle, rd.readError) if err != nil { return sys_error.New(fmt.Sprintf("车载atp连接失败,add:%v ,message:%v", addr, err)) @@ -356,22 +353,18 @@ func (d *trainPcSimService) CreateOrRemoveTrain(train *state_proto.TrainState, i } msg := &message.TrainPcSimBaseMessage{Data: data, Type: message.RECIVE_TRAIN_CREATE_REMOVE} rds := d.newPcSimclientMap3[clientKey] - if rds != nil { - for index, rd := range rds { - if rd != nil && rd.success { - slog.Info(fmt.Sprintf("index%v---rd client:%v clientnil :%v", index, rd.tcpClient, rd.tcpClient == nil)) - initTrainErr := d.initTrain(rd, train, isCreate, msg) - if !isCreate { - d.newCloseConn(clientKey) - } - if initTrainErr != nil { - return initTrainErr - } + for index, rd := range rds { + slog.Info(fmt.Sprintf("index%v---rd client:%v clientnil :%v,succ:%v", index, rd.tcpClient, rd.tcpClient == nil, rd.success)) + if rd != nil && rd.success { + initTrainErr := d.initTrain(rd, train, isCreate, msg) + if initTrainErr != nil { + return initTrainErr } - } } - + if !isCreate { + d.newCloseConn(clientKey) + } return nil } func (d *trainPcSimService) initTrain(rd *TrainPcReciverData, train *state_proto.TrainState, isCreate bool, trains *message.TrainPcSimBaseMessage) error { @@ -424,32 +417,35 @@ func (d *trainPcSimService) sendTrainLocationAndSpeedTask(ctx context.Context) { trains := d.trainPcSimManage.GetConnTrain2() for _, train := range trains { - if train.ConnState.Conn { - for numKey, pc := range train.PulseCountMap { - trainPort := state_proto.TrainState_TrainPort(numKey) - trainClient, _ := d.findTrainConnForPort2(train, trainPort) - if trainClient == nil { + for numKey, pc := range train.PulseCountMap { + trainPort := state_proto.TrainState_TrainPort(numKey) + trainClient, _ := d.findTrainConnForPort2(train, trainPort) + if trainClient == nil { + continue + } + if trainClient.success { + if trainClient.speedPlace == nil || trainClient.tcpClient == nil { + slog.Error(fmt.Sprintf("pc仿真速度位置脉冲对象为空 列车id:%v", train.Id)) continue } - if trainClient.success { - if trainClient.speedPlace == nil || trainClient.tcpClient == nil { - slog.Error(fmt.Sprintf("pc仿真速度位置脉冲对象为空 列车id:%v", train.Id)) - continue - } - if trainClient.ConnError() { - continue - } - s1, speed := d.pluseSpeed(pc, train.WheelDiameter) - runDir := d.trainDirection(speed, train, trainClient.RealTrainPort) - disPluse := pluseCountSpeed(train.WheelDiameter, trainClient.speedPlace.PulseCount1) - data := trainClient.speedPlace.Encode(runDir, s1, disPluse) - bm := &message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_LOCATION_INFO, Data: data} - dataCode := bm.Encode() - //slog.Info(fmt.Sprintf("发送列车速度位置,列车:%v,列车服务端:%v,列车速度:%v,计数脉冲: %v,累计里程: %v ,发送数据:%X", train.Id, trainClient.RealTrainPort.String(), speed, s1, trainClient.speedPlace.PulseCount1, dataCode)) - err := trainClient.tcpClient.Send(dataCode) - if err != nil { - slog.Error(fmt.Sprintf("发送列车速度位置失败,列车:%v,发送数据:%v", train.Id, hex.EncodeToString(dataCode))) - } + if trainClient.ConnError() { + continue + } + /*ds := &strings.Builder{} + for i, s := range pc.PulseCount3 { + ds.WriteString(fmt.Sprintf("i:%v,s:%v ", i, s)) + } + slog.Info(fmt.Sprintf("列车速度统计 列车id:%v 列车方向:%v ,列车速度信息:%v", train.Id, trainClient.RealTrainPort.String(), ds.String()))*/ + s1, speed := d.pluseSpeed(pc, train.WheelDiameter) + runDir := d.trainDirection(speed, train, trainClient.RealTrainPort) + disPluse := pluseCountSpeed(train.WheelDiameter, trainClient.speedPlace.PulseCount1) + data := trainClient.speedPlace.Encode(runDir, s1, disPluse) + bm := &message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_LOCATION_INFO, Data: data} + dataCode := bm.Encode() + //slog.Info(fmt.Sprintf("发送列车速度位置,列车:%v,列车服务端:%v,列车速度:%v,计数脉冲: %v,累计里程: %v ,发送数据:%X", train.Id, trainClient.RealTrainPort.String(), speed, s1, trainClient.speedPlace.PulseCount1, dataCode)) + err := trainClient.tcpClient.Send(dataCode) + if err != nil { + slog.Error(fmt.Sprintf("发送列车速度位置失败,列车:%v,发送数据:%v", train.Id, hex.EncodeToString(dataCode))) } } } diff --git a/ts/simulation/wayside/memory/wayside_memory_train.go b/ts/simulation/wayside/memory/wayside_memory_train.go index a7c3752..9ca2d08 100644 --- a/ts/simulation/wayside/memory/wayside_memory_train.go +++ b/ts/simulation/wayside/memory/wayside_memory_train.go @@ -337,6 +337,8 @@ func UpdateTrainStateByDynamics(vs *VerifySimulation, trainId string, info *mess } //slog.Debug("车尾位置", tailDeviceId, "偏移", tailDeviceOffset, "所在设备端", tailDevicePort) // 修改world中的列车位置 + + slog.Debug("处理动力学转换后的消息", "number", info.Number, "up", info.Up, "Link", info.Link, "车头位置", id, "偏移", offset, "车尾位置:", tailDeviceId, "车尾偏移:", tailOffset, "车头linkOffset:", outLinkOffset, "车位linkOffset:", tailLinkOffset) handleTrainPositionFromDynamic(vs, info, sta, outLinkId, outLinkOffset, tailLinkId, tailLinkOffset) //修改列车激活方向 updateTrainActiveDirFromDynamic(vs, info, sta, id, port, trainHeadActUp) @@ -460,7 +462,7 @@ func pluseCount(sta *state_proto.TrainState, h1, h2, t1, t2 float32) { train_pc_sim.Default().TrainPluseCount(sta, h1, h2, t1, t2) } -func RemoveAllTrain(vs *VerifySimulation) { +func RemoveAllTrain(vs *VerifySimulation, realRemove bool) { allTrainMap := &vs.Memory.Status.TrainStateMap if allTrainMap == nil { slog.Info("当前没有列车不能执行") @@ -468,7 +470,7 @@ func RemoveAllTrain(vs *VerifySimulation) { } allTrainMap.Range(func(k any, t any) bool { id := k.(string) - RemoveTrainState(vs, id) + RemoveTrainState(vs, id, realRemove) return true }) } @@ -500,18 +502,22 @@ func removeTrain(vs *VerifySimulation, trainId string, train *state_proto.TrainS return fi.RemoveTrainFromWorld(vs.World, trainId) } -func RemoveTrainState(vs *VerifySimulation, id string) { +func RemoveTrainState(vs *VerifySimulation, id string, realRemove bool) { 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) + if realRemove { + allTrainMap.Delete(id) + } else { + allTrainMap.Store(id, t) + + } } else { panic(fmt.Sprintf("列车【%s】不存在", id)) } @@ -525,14 +531,3 @@ func calcTrailTailOffset(headerOffset, length int64, up bool) (calctailOffset in } 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 -} diff --git a/ts/simulation/wayside/memory/wayside_simulation.go b/ts/simulation/wayside/memory/wayside_simulation.go index cbdea69..516334e 100644 --- a/ts/simulation/wayside/memory/wayside_simulation.go +++ b/ts/simulation/wayside/memory/wayside_simulation.go @@ -380,34 +380,6 @@ func speedParse(speed float32) int32 { return int32(math.Abs(float64(speed * 3.6 * 100))) } -// 处理半实物仿真列车控制消息 -func (s *VerifySimulation) HandleSemiPhysicalTrainControlMsg(b []byte) { - s.Memory.Status.TrainStateMap.Range(func(_, value any) bool { - train := value.(*state_proto.TrainState) - if !train.Show { // 下线列车 - return true - } - connState := train.ConnState - if connState.Conn == true && connState.ConnType == state_proto.TrainConnState_VOBC { - /*trainId, err := strconv.Atoi(train.Id) - if err != nil { - panic(dto.ErrorDto{Code: dto.ArgumentParseError, Message: err.Error()}) - }*/ - // 存放至列车中 - //接收半实物列车控制不单独发送动力学,由动力学统一发送 - //d := append(b, uint8(trainId)) - //dynamics.Default().SendTrainControlMessage(d) - controlMessage := &message.TrainControlMsg{} - controlMessage.Decode(b) - controlMessage.TrainId = train.Id - controlMessage.FromVobc = true - train.VobcState = controlMessage.ControlInfo - - return false - } - return true - }) -} func (s *VerifySimulation) CollectTrainControlState() []message.TrainControlMsg { cms := make([]message.TrainControlMsg, 0) s.Memory.Status.TrainStateMap.Range(func(_, value any) bool { @@ -426,11 +398,6 @@ func (s *VerifySimulation) CollectTrainControlState() []message.TrainControlMsg return cms } -// 获取半实物运行配置信息 -func (s *VerifySimulation) GetSemiPhysicalRunConfig() *config.VobcConfig { - return &s.runConfig.Vobc -} - // 处理接到的联锁消息 func (s *VerifySimulation) HandleInterlockDriverInfo(code string, driveBytes []byte) { wd := entity.GetWorldData(s.World) @@ -1151,6 +1118,17 @@ func fillProtoRepository(repo *proto.Repository, storage *data_proto.RtssGraphic } repo.CheckPoints = append(repo.CheckPoints, cp) } + //列车停车点 + for _, sp := range storage.StopPositions { + id := GetMapElementId(sp.Common) + psp := &proto.StopPosition{Id: id, Km: convertKm(sp.KilometerSystem)} + + switch sp.GetRefDev().DeviceType { + case data_proto.RelatedRef_Section: + psp.SectionId = uidsMap.PhysicalSectionIds[sp.GetRefDev().Id].Uid + } + repo.StopPosition = append(repo.StopPosition, psp) + } //物理区段 for _, data := range storage.Section { var turnoutUids []string diff --git a/ts/simulation/wayside/memory/wayside_simulation_semi_physical.go b/ts/simulation/wayside/memory/wayside_simulation_semi_physical.go new file mode 100644 index 0000000..91595f1 --- /dev/null +++ b/ts/simulation/wayside/memory/wayside_simulation_semi_physical.go @@ -0,0 +1,50 @@ +package memory + +import ( + "joylink.club/bj-rtsts-server/config" + "joylink.club/bj-rtsts-server/dto/state_proto" + "joylink.club/bj-rtsts-server/third_party/message" +) + +// 获取半实物运行配置信息 +func (s *VerifySimulation) GetSemiPhysicalRunConfig() *config.VobcConfig { + return &s.runConfig.Vobc +} + +// 处理半实物仿真列车控制消息 +func (s *VerifySimulation) HandleSemiPhysicalTrainControlMsg(b []byte) { + s.Memory.Status.TrainStateMap.Range(func(_, value any) bool { + train := value.(*state_proto.TrainState) + if !train.Show { // 下线列车 + return true + } + connState := train.ConnState + if connState.Conn == true && connState.ConnType == state_proto.TrainConnState_VOBC { + /*trainId, err := strconv.Atoi(train.Id) + if err != nil { + panic(dto.ErrorDto{Code: dto.ArgumentParseError, Message: err.Error()}) + }*/ + // 存放至列车中 + //接收半实物列车控制不单独发送动力学,由动力学统一发送 + //d := append(b, uint8(trainId)) + //dynamics.Default().SendTrainControlMessage(d) + controlMessage := &message.TrainControlMsg{} + controlMessage.Decode(b) + controlMessage.TrainId = train.Id + controlMessage.FromVobc = true + train.VobcState = controlMessage.ControlInfo + + return false + } + return true + }) +} + +// 处理半实物仿真列车控制消息 +func (s *VerifySimulation) HandleSemiPhysicalTrainControlMsg2(b []byte) { + //train := s.GetConnVobcTrain() + +} +func aaByte1() { + +} diff --git a/ts/test_simulation_manage.go b/ts/test_simulation_manage.go index aac934c..b4163c5 100644 --- a/ts/test_simulation_manage.go +++ b/ts/test_simulation_manage.go @@ -90,8 +90,9 @@ func DestroySimulation(simulationId string) { if !e { return } - simulationMap.Delete(simulationId) simulationInfo := s.(*memory.VerifySimulation) + memory.RemoveAllTrain(simulationInfo, true) + simulationMap.Delete(simulationId) // simulationInfo.Destroy() // 停止ecs world simulationInfo.World.Close()