2023-10-26 17:16:07 +08:00
|
|
|
package ts
|
2023-07-31 08:41:42 +08:00
|
|
|
|
|
|
|
import (
|
2023-11-03 17:27:37 +08:00
|
|
|
"fmt"
|
2024-09-05 09:21:49 +08:00
|
|
|
"joylink.club/bj-rtsts-server/service"
|
2024-01-26 17:57:35 +08:00
|
|
|
"joylink.club/bj-rtsts-server/third_party/acc"
|
2024-07-04 13:59:39 +08:00
|
|
|
axleBeijing12 "joylink.club/bj-rtsts-server/third_party/axle_device/beijing12"
|
2024-05-29 17:20:51 +08:00
|
|
|
"joylink.club/bj-rtsts-server/third_party/interlock/beijing11"
|
2024-05-13 13:17:16 +08:00
|
|
|
"joylink.club/bj-rtsts-server/third_party/interlock/beijing12"
|
2024-01-24 17:12:34 +08:00
|
|
|
"joylink.club/bj-rtsts-server/third_party/radar"
|
2024-04-09 08:55:33 +08:00
|
|
|
"joylink.club/bj-rtsts-server/third_party/train_pc_sim"
|
2024-09-18 11:40:20 +08:00
|
|
|
"joylink.club/rtsssimulation/fi"
|
2023-10-26 18:00:17 +08:00
|
|
|
"log/slog"
|
|
|
|
"runtime"
|
2023-08-10 14:18:55 +08:00
|
|
|
"strconv"
|
|
|
|
"sync"
|
2024-09-18 11:40:20 +08:00
|
|
|
"time"
|
2023-08-10 14:18:55 +08:00
|
|
|
|
2023-12-13 11:22:30 +08:00
|
|
|
"joylink.club/bj-rtsts-server/third_party/can_btm"
|
|
|
|
cidcmodbus "joylink.club/bj-rtsts-server/third_party/cidc_modbus"
|
|
|
|
|
2023-11-17 16:22:22 +08:00
|
|
|
"joylink.club/bj-rtsts-server/third_party/electrical_machinery"
|
2023-11-17 17:01:12 +08:00
|
|
|
|
2023-10-26 16:41:18 +08:00
|
|
|
"joylink.club/bj-rtsts-server/message_server"
|
2023-11-17 17:02:50 +08:00
|
|
|
"joylink.club/bj-rtsts-server/mqtt"
|
2023-10-20 15:08:47 +08:00
|
|
|
"joylink.club/bj-rtsts-server/sys_error"
|
2023-10-26 18:00:17 +08:00
|
|
|
"joylink.club/bj-rtsts-server/third_party/dynamics"
|
|
|
|
"joylink.club/bj-rtsts-server/third_party/semi_physical_train"
|
2023-10-26 17:16:07 +08:00
|
|
|
"joylink.club/bj-rtsts-server/ts/simulation/wayside/memory"
|
2023-07-31 08:41:42 +08:00
|
|
|
|
2023-08-01 14:54:11 +08:00
|
|
|
"joylink.club/bj-rtsts-server/dto"
|
2023-10-26 18:00:17 +08:00
|
|
|
rtss_simulation "joylink.club/rtsssimulation"
|
2023-07-31 08:41:42 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
// 仿真存储集合
|
2023-08-01 14:54:11 +08:00
|
|
|
var simulationMap sync.Map
|
2023-07-31 08:41:42 +08:00
|
|
|
|
2023-08-30 18:05:11 +08:00
|
|
|
// 创建前检查
|
|
|
|
func IsExistSimulation() bool {
|
|
|
|
i := 0
|
|
|
|
simulationMap.Range(func(_, _ any) bool {
|
|
|
|
i++
|
|
|
|
return true
|
|
|
|
})
|
|
|
|
return i > 0
|
|
|
|
}
|
|
|
|
|
2023-07-31 08:41:42 +08:00
|
|
|
// 创建仿真对象
|
2023-10-26 18:09:09 +08:00
|
|
|
func CreateSimulation(projectId int32, mapIds []int32, runConfig *dto.ProjectRunConfigDto) (string, error) {
|
2023-09-19 11:02:50 +08:00
|
|
|
simulationId := createSimulationId(projectId)
|
2023-08-01 14:54:11 +08:00
|
|
|
_, e := simulationMap.Load(simulationId)
|
2023-09-01 10:25:27 +08:00
|
|
|
if !e && IsExistSimulation() {
|
2023-10-20 15:08:47 +08:00
|
|
|
return "", sys_error.New("一套环境同时只能运行一个仿真")
|
2023-09-01 10:25:27 +08:00
|
|
|
}
|
2023-08-01 14:54:11 +08:00
|
|
|
if !e {
|
2024-09-05 09:21:49 +08:00
|
|
|
project := service.QueryProject(projectId)
|
2023-10-26 15:06:26 +08:00
|
|
|
verifySimulation, err := memory.CreateSimulation(projectId, mapIds, runConfig)
|
2024-08-05 16:32:21 +08:00
|
|
|
|
2023-09-20 15:14:40 +08:00
|
|
|
if err != nil {
|
2023-10-20 15:08:47 +08:00
|
|
|
return "", err
|
2023-09-19 11:02:50 +08:00
|
|
|
}
|
2023-09-20 15:14:40 +08:00
|
|
|
verifySimulation.SimulationId = simulationId
|
2024-09-18 11:40:20 +08:00
|
|
|
verifySimulation.ProjectCode = project.Code
|
2023-10-26 18:00:17 +08:00
|
|
|
// world构建
|
|
|
|
err = initWorld(verifySimulation)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
2024-09-18 11:40:20 +08:00
|
|
|
// verifySimulation.Start()
|
|
|
|
// 全部成功,启动仿真
|
|
|
|
verifySimulation.World.StartUp()
|
|
|
|
// 初始化设备状态
|
|
|
|
initDeviceStatus(verifySimulation)
|
|
|
|
// 启动仿真消息服务
|
|
|
|
message_server.Start(verifySimulation)
|
2023-10-26 18:00:17 +08:00
|
|
|
// 第三方服务处理
|
|
|
|
err = runThirdParty(verifySimulation)
|
|
|
|
if err != nil {
|
2023-12-13 11:22:30 +08:00
|
|
|
verifySimulation.World.Close()
|
2023-10-26 18:00:17 +08:00
|
|
|
return "", err
|
|
|
|
}
|
2023-10-20 15:08:47 +08:00
|
|
|
simulationMap.Store(simulationId, verifySimulation)
|
2023-07-31 08:41:42 +08:00
|
|
|
}
|
2023-10-20 15:08:47 +08:00
|
|
|
return simulationId, nil
|
2023-07-31 08:41:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// 删除仿真对象
|
|
|
|
func DestroySimulation(simulationId string) {
|
2023-09-21 14:54:27 +08:00
|
|
|
s, e := simulationMap.Load(simulationId)
|
|
|
|
if !e {
|
|
|
|
return
|
|
|
|
}
|
2023-08-25 17:49:09 +08:00
|
|
|
simulationMap.Delete(simulationId)
|
2023-10-26 15:06:26 +08:00
|
|
|
simulationInfo := s.(*memory.VerifySimulation)
|
2024-01-23 09:37:31 +08:00
|
|
|
// simulationInfo.Destroy()
|
2023-10-26 18:00:17 +08:00
|
|
|
// 停止ecs world
|
|
|
|
simulationInfo.World.Close()
|
2024-01-23 09:41:54 +08:00
|
|
|
message_server.Close(simulationInfo)
|
2024-01-24 13:25:00 +08:00
|
|
|
// 确保发布销毁消息
|
2024-01-23 09:41:54 +08:00
|
|
|
message_server.PubSimulationDestroyMsg(simulationId)
|
2023-10-26 18:00:17 +08:00
|
|
|
// 停止第三方
|
|
|
|
stopThirdParty(simulationInfo)
|
|
|
|
}
|
|
|
|
|
2024-09-18 11:40:20 +08:00
|
|
|
func initDeviceStatus(simulation *memory.VerifySimulation) {
|
|
|
|
for _, turnout := range simulation.Repo.TurnoutList() {
|
|
|
|
err := fi.DriveTurnoutDCOn(simulation.World, turnout.Id())
|
|
|
|
if err != nil {
|
|
|
|
slog.Error("初始驱动道岔到定位失败", "error", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
time.Sleep(200 * time.Millisecond)
|
|
|
|
for _, turnout := range simulation.Repo.TurnoutList() {
|
|
|
|
err := fi.DriveTurnoutDCOff(simulation.World, turnout.Id())
|
|
|
|
if err != nil {
|
|
|
|
slog.Error("取消驱动道岔到定位失败", "error", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-26 18:00:17 +08:00
|
|
|
// 创建world
|
|
|
|
func initWorld(s *memory.VerifySimulation) error {
|
|
|
|
//创建仿真
|
|
|
|
w, err := rtss_simulation.NewSimulation(s.Repo)
|
|
|
|
if err != nil {
|
2023-11-03 17:27:37 +08:00
|
|
|
return sys_error.New(fmt.Sprintf("仿真创建失败: %s", err), err)
|
2023-10-26 18:00:17 +08:00
|
|
|
}
|
|
|
|
s.World = w
|
|
|
|
// 保证World关闭
|
|
|
|
runtime.SetFinalizer(s, func(verifySimulation *memory.VerifySimulation) {
|
|
|
|
slog.Info("---关闭仿真World---")
|
|
|
|
verifySimulation.World.Close()
|
|
|
|
})
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// 运行仿真第三方模块
|
|
|
|
func runThirdParty(s *memory.VerifySimulation) error {
|
|
|
|
// 动力学启动
|
|
|
|
err := dynamics.Default().Start(s)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
// 半实物启动
|
|
|
|
semi_physical_train.Default().Start(s)
|
|
|
|
// 联锁启动
|
2024-08-08 13:23:25 +08:00
|
|
|
for _, c := range s.GetRunConfig().Interlocks {
|
2024-05-29 17:20:51 +08:00
|
|
|
switch c.Line {
|
|
|
|
case "11":
|
2024-06-12 17:49:02 +08:00
|
|
|
beijing11.Start(c, s)
|
2024-05-29 17:20:51 +08:00
|
|
|
default:
|
2024-07-29 13:53:46 +08:00
|
|
|
beijing12.Start(c, s, s.Repo.TransponderList())
|
2024-05-29 17:20:51 +08:00
|
|
|
}
|
2023-10-31 15:23:29 +08:00
|
|
|
}
|
2023-11-09 13:05:29 +08:00
|
|
|
// 计轴RSSP启动
|
2024-07-04 13:59:39 +08:00
|
|
|
axleBeijing12.Start(s)
|
|
|
|
//obsolete.StartLineAllRsspAxleServices(s)
|
2023-11-17 16:22:22 +08:00
|
|
|
// 电机UDP启动
|
|
|
|
electrical_machinery.Default().Start(s)
|
2023-11-24 15:20:05 +08:00
|
|
|
// 车载BTM启动
|
|
|
|
can_btm.Default().Start(s)
|
2023-12-13 11:22:30 +08:00
|
|
|
// 联锁驱采Modbus服务启动
|
2023-12-13 11:24:22 +08:00
|
|
|
err = cidcmodbus.Start(s)
|
2023-12-13 11:22:30 +08:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2024-01-24 17:12:34 +08:00
|
|
|
//列车雷达发送vobc
|
|
|
|
radar.Default().Start(s)
|
2024-01-26 17:57:35 +08:00
|
|
|
//列车加速计发送vobc
|
|
|
|
acc.Default().Start(s)
|
2024-04-29 13:58:14 +08:00
|
|
|
train_pc_sim.Default().Start(s)
|
2024-05-29 13:34:50 +08:00
|
|
|
//btm vobc
|
2024-09-05 09:21:49 +08:00
|
|
|
semi_physical_train.BtmDefault().Start(s)
|
2023-10-26 18:00:17 +08:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// 停止仿真
|
|
|
|
func stopThirdParty(s *memory.VerifySimulation) {
|
|
|
|
// 停止半实物
|
|
|
|
semi_physical_train.Default().Stop()
|
2024-08-15 14:54:16 +08:00
|
|
|
// 车载BTM停止
|
|
|
|
can_btm.Default().Stop()
|
|
|
|
// 联锁驱采Modbus服务停止
|
|
|
|
cidcmodbus.Stop()
|
|
|
|
// 雷达服务停止
|
|
|
|
radar.Default().Stop()
|
|
|
|
// 加速计服务停止
|
|
|
|
acc.Default().Stop()
|
|
|
|
//列车PC仿真停止
|
|
|
|
train_pc_sim.Default().Stop()
|
|
|
|
|
2024-09-05 09:21:49 +08:00
|
|
|
semi_physical_train.BtmDefault().Stop()
|
2024-08-15 14:54:16 +08:00
|
|
|
// 停止动力学接口功能
|
|
|
|
dynamics.Default().Stop()
|
2023-10-26 18:00:17 +08:00
|
|
|
// 联锁启动
|
2024-08-08 13:23:25 +08:00
|
|
|
for _, c := range s.GetRunConfig().Interlocks {
|
2024-05-29 17:20:51 +08:00
|
|
|
switch c.Line {
|
|
|
|
case "11":
|
2024-08-07 14:53:57 +08:00
|
|
|
beijing11.Stop(c.Code)
|
2024-05-29 17:20:51 +08:00
|
|
|
default:
|
2024-06-21 15:53:17 +08:00
|
|
|
beijing12.Stop(c)
|
2024-05-29 17:20:51 +08:00
|
|
|
}
|
2023-10-31 15:23:29 +08:00
|
|
|
}
|
2023-11-10 10:54:44 +08:00
|
|
|
//计轴RSSP启动销毁
|
2024-07-04 13:59:39 +08:00
|
|
|
axleBeijing12.Stop(s)
|
|
|
|
//obsolete.StopLineAllRsspAxleServices()
|
2023-11-17 16:22:22 +08:00
|
|
|
// 电机UDP停止
|
|
|
|
electrical_machinery.Default().Stop()
|
2024-05-29 13:34:50 +08:00
|
|
|
|
2023-07-31 08:41:42 +08:00
|
|
|
}
|
|
|
|
|
2023-09-19 11:02:50 +08:00
|
|
|
func createSimulationId(projectId int32) string {
|
2023-11-17 17:01:12 +08:00
|
|
|
// MQTT客户端id+项目
|
|
|
|
return mqtt.GetClientId() + "_" + strconv.Itoa(int(projectId))
|
2023-07-31 08:41:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// 获取仿真列表
|
2023-08-30 13:25:57 +08:00
|
|
|
func ListAllSimulations() []*dto.SimulationInfoRspDto {
|
2023-08-31 16:16:18 +08:00
|
|
|
var simArr []*dto.SimulationInfoRspDto
|
2023-08-25 15:35:00 +08:00
|
|
|
simulationMap.Range(func(_, v any) bool {
|
2023-08-01 14:54:11 +08:00
|
|
|
s := v.(*memory.VerifySimulation)
|
2023-08-30 13:25:57 +08:00
|
|
|
simArr = append(simArr, &dto.SimulationInfoRspDto{
|
2023-10-27 09:12:40 +08:00
|
|
|
SimulationId: s.SimulationId,
|
|
|
|
MapId: s.MapIds[0],
|
|
|
|
MapIds: s.MapIds,
|
|
|
|
ProjectId: s.ProjectId,
|
|
|
|
ProjectRunConfigId: s.GetRunConfigId(),
|
2023-08-01 14:54:11 +08:00
|
|
|
})
|
|
|
|
return true
|
|
|
|
})
|
|
|
|
return simArr
|
2023-07-31 08:41:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// 根据仿真id查找仿真实例
|
2023-08-01 14:54:11 +08:00
|
|
|
func FindSimulation(simulationId string) *memory.VerifySimulation {
|
|
|
|
m, e := simulationMap.Load(simulationId)
|
|
|
|
if e {
|
|
|
|
return m.(*memory.VerifySimulation)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|