This commit is contained in:
xzb 2023-12-29 17:01:01 +08:00
commit 2803f32329
35 changed files with 564 additions and 85 deletions

View File

@ -1,33 +0,0 @@
package repo
// type repoManager struct {
// repoMap map[string]CgRepo
// lock sync.Mutex
// }
// var defaultManager = &repoManager{
// repoMap: make(map[string]CgRepo),
// }
// // 获取或构建模型仓库
// func GetOrBuildRepo(id string, dc func(errRecord *ErrorRecord) *dto.CgRepo) (CgRepo, *ErrorRecord) {
// manager := defaultManager
// manager.lock.Lock()
// defer manager.lock.Unlock()
// r, ok := manager.repoMap[id]
// errRecord := NewErrorRecord()
// if !ok {
// // 所需protobuf数据转换
// msgs := dc(errRecord)
// // 数据转换出错直接返回
// if errRecord.HasError() {
// return nil, errRecord
// }
// // 构建模型Repo
// r, errRecord = BuildFrom(msgs)
// if r != nil {
// manager.repoMap[id] = r
// }
// }
// return r, errRecord
// }

View File

@ -1,11 +0,0 @@
package model
// 继电器位置
type RelayPosition int
const (
// 继电器位置-后(表示落下/反位)
RelayPosition_H RelayPosition = 0
// 继电器位置-前(表示吸起/定位)
RelayPosition_Q RelayPosition = 1
)

View File

@ -0,0 +1,168 @@
package component
import (
"time"
"joylink.club/ecs"
)
// 控制模式
type ControlMode uint8
const (
ControlMode_None ControlMode = iota // 交出未被接收
ControlMode_Center // 中控
ControlMode_Local // 站控/自律站控
ControlMode_Emergency // 紧急站控
ControlMode_Interlock // 联锁控/非常站控
)
// 控制模式
type ControlState struct {
Model ControlMode // 当前控制模式
}
var ControlStateType = ecs.NewComponentType[ControlState]() // 控制模式
// 限速组件
type SpeedLimit struct {
Val float32 // 限速值
}
var SpeedLimitType = ecs.NewComponentType[SpeedLimit]() // 限速组件
// 占用类型
type OccupiedType uint8
const (
Occupied_Ct OccupiedType = iota // 通信车占用
Occupied_Nct // 非通信车占用
Occupied_Fault // 故障占用
)
// 占用状态
type OccupiedStatus struct {
Type OccupiedType
}
var OccupiedStatusType = ecs.NewComponentType[OccupiedStatus]() // 占用状态组件
// 进路锁闭状态
type RouteLock struct {
Route *ecs.Entry
}
var RouteLockType = ecs.NewComponentType[RouteLock]()
// 故障锁闭状态
type FaultLock struct {
Fault any // 故障信息
}
var FaultLockType = ecs.NewComponentType[FaultLock]() // 故障锁闭状态组件
// 封锁状态
type BlockadeStatus struct {
}
var BlockadeStatusType = ecs.NewComponentType[BlockadeStatus]() // 封锁状态组件
// 解锁状态
type UnLockStatus struct {
Delay bool // 延迟状态
DelayTime time.Duration // 延迟解锁时间
TriggerDevice *ecs.Entry // 触发解锁设备
}
var UnLockStatusType = ecs.NewComponentType[UnLockStatus]() // 解锁状态组件
// 关闭状态
type ClosedStatus struct {
}
var ClosedStatusType = ecs.NewComponentType[ClosedStatus]() // 关闭状态组件
// 站台跳停状态
type PlatformSkipStatus struct {
AllSkip bool // 全部跳停
Trains []*ecs.Entry // 跳停列车
}
var PlatformSkipStatusType = ecs.NewComponentType[PlatformSkipStatus]() // 站台跳停状态
// 站台停靠发车状态
type PlatformParkStatus struct {
Park bool // 列车停靠状态
ParkTime time.Duration // 停靠时间
Depart bool // 列车发车状态
}
var PlatformParkStatusType = ecs.NewComponentType[PlatformParkStatus]() // 站台停靠发车状态
// 扣车状态
type PlatformHoldStatus struct {
}
var PlatformHoldStatusType = ecs.NewComponentType[PlatformHoldStatus]() // 扣车状态组件
// 信号机状态
type SignalStatus struct {
ApproachLock bool // 接近锁闭
OverlapLock bool // 延续保护锁闭
}
var SignalStatusType = ecs.NewComponentType[SignalStatus]() // 信号机状态组件
// 进路状态
type RouteStatus struct {
AtsControl bool // ats自动控制
Setting bool // 进路是否排列中
Lock bool // 已锁闭
}
var RouteStatusType = ecs.NewComponentType[RouteStatus]() // 进路状态组件
// 列车运行级别
type TrainRunLevel uint8
const (
TrainRunLevel_CBTC TrainRunLevel = iota // cbtc级别
TrainRunLevel_ITC // 点式通信
TrainRunLevel_IL // 联锁级
)
// 列车运行模式
type DriveMode uint8
const (
DriveMode_AM DriveMode = iota // 列车自动驾驶模式
DriveMode_CM // ATP防护下的人工驾驶模式
DriveMode_RM // 限制人工驾驶模式
DriveMode_NRM // 无限制人工驾驶模式
)
// 位置:目标位置、占用位置
type DevicePosition struct {
Device *ecs.Entry // 设备
Offset int64 // 在设备上的相对a位置偏移
Direction bool // 从a到b为true;从b到a为false
}
var DevicePositionType = ecs.NewComponentType[DevicePosition]()
// 列车运行状态
type TrainRunStatus struct {
RunLevel TrainRunLevel // 列车运行级别
DriveMode DriveMode // 驾驶模式
Speed float32 // 运行速度
SpeedMax float32 // 最大速度
HeadPosition *DevicePosition // 车头位置
TailPosition *DevicePosition // 车尾位置
Hold bool // 扣车
}
var TrainRunStatusType = ecs.NewComponentType[TrainRunStatus]() // 列车位置状态组件
var (
TrainSpeedMax float32 = 80 / 3.6
)

View File

@ -0,0 +1,42 @@
package singleton
import (
"joylink.club/ecs"
"joylink.club/ecs/filter"
"joylink.club/rtsssimulation/modelrepo"
)
// 加载并初始化单例组件
func LoadSingletons(w ecs.World, r modelrepo.Repo) {
loadWorldRepo(w, r)
loadWorldTime(w)
loadUidEntityIndex(w)
}
var worldRepoQuery = ecs.NewQuery(filter.Contains(WorldRepoType))
var worldTimeQuery = ecs.NewQuery(filter.Contains(WorldTimeType))
var uidEntityIndexQuery = ecs.NewQuery(filter.Contains(EntityUidIndexType))
func GetWorldTime(w ecs.World) *WorldTime {
entry, _ := worldTimeQuery.First(w)
if entry == nil {
panic("不存在世界时间组件")
}
return WorldTimeType.Get(entry)
}
func GetWorldRepo(w ecs.World) *WorldRepo {
entry, _ := worldRepoQuery.First(w)
if entry == nil {
panic("不存在世界数据组件")
}
return WorldRepoType.Get(entry)
}
func GetEntityUidIndex(w ecs.World) *EntityUidIndex {
entry, _ := uidEntityIndexQuery.First(w)
if entry == nil {
panic("不存在UidEntityIndex组件")
}
return EntityUidIndexType.Get(entry)
}

View File

@ -0,0 +1,19 @@
package singleton
import (
"joylink.club/ecs"
"joylink.club/rtsssimulation/modelrepo"
)
var WorldRepoType = ecs.NewComponentType[WorldRepo]()
type WorldRepo struct {
r modelrepo.Repo
}
func loadWorldRepo(w ecs.World, r modelrepo.Repo) {
entry := w.Entry(w.Create(WorldRepoType))
WorldRepoType.Set(entry, &WorldRepo{
r: r,
})
}

View File

@ -0,0 +1,34 @@
package singleton
import (
"sync"
"joylink.club/ecs"
)
var EntityUidIndexType = ecs.NewComponentType[EntityUidIndex]()
// 对象实体Uid索引
type EntityUidIndex struct {
mu sync.RWMutex
entityMap map[string]ecs.Entity
}
func (idx *EntityUidIndex) Add(uid string, entity ecs.Entity) {
idx.mu.Lock()
defer idx.mu.Unlock()
idx.entityMap[uid] = entity
}
func (idx *EntityUidIndex) Get(uid string) ecs.Entity {
idx.mu.RLock()
defer idx.mu.RUnlock()
return idx.entityMap[uid]
}
func loadUidEntityIndex(w ecs.World) {
entry := w.Entry(w.Create(EntityUidIndexType))
EntityUidIndexType.Set(entry, &EntityUidIndex{
entityMap: make(map[string]ecs.Entity, 512),
})
}

View File

@ -0,0 +1,37 @@
package singleton
import (
"time"
"joylink.club/ecs"
)
var WorldTimeType = ecs.NewComponentType[WorldTime]()
type WorldTime struct {
time int64
}
func (w *WorldTime) SetTime(t time.Time) {
w.time = t.UnixMilli()
}
// 增加时间
func (w *WorldTime) Run(ms int) {
w.time += int64(ms)
}
// 获取时间
func (w *WorldTime) GetTime() time.Time {
return time.UnixMilli(w.time)
}
// 获取时间戳
func (w *WorldTime) GetMilli() int64 {
return w.time
}
func loadWorldTime(w ecs.World) {
entry := w.Entry(w.Create(WorldTimeType))
WorldTimeType.Set(entry, &WorldTime{time: time.Now().UnixMilli()})
}

22
entity/cg_load.go Normal file
View File

@ -0,0 +1,22 @@
package entity
import (
"joylink.club/ecs"
"joylink.club/rtsssimulation/component/singleton"
"joylink.club/rtsssimulation/modelrepo"
"joylink.club/rtsssimulation/modelrepo/model"
)
// 加载城轨仿真实体
func LoadCg(w ecs.World, repo modelrepo.Repo) error {
singleton.LoadSingletons(w, repo)
for _, s := range repo.GetEcses() {
// 加载道岔实体
loadTurnouts(w, s.GetTurnouts())
}
return nil
}
func loadTurnouts(w ecs.World, turnout []model.Turnout) {
panic("unimplemented")
}

14
init.go
View File

@ -3,6 +3,7 @@ package rtss_simulation
import ( import (
"joylink.club/ecs" "joylink.club/ecs"
"joylink.club/rtsssimulation/entity" "joylink.club/rtsssimulation/entity"
"joylink.club/rtsssimulation/modelrepo"
"joylink.club/rtsssimulation/repository" "joylink.club/rtsssimulation/repository"
"joylink.club/rtsssimulation/sys" "joylink.club/rtsssimulation/sys"
) )
@ -19,3 +20,16 @@ func NewSimulation(repo *repository.Repository) (ecs.World, error) {
err := entity.Load(w, repo) err := entity.Load(w, repo)
return w, err return w, err
} }
// 加载城轨仿真
func LoadCgSimulation(repo modelrepo.Repo) (ecs.World, error) {
w := ecs.NewWorld(RtssSimulationTick)
// 加载组件实体
err := entity.LoadCg(w, repo)
if err != nil {
return nil, err
}
// 加载系统
sys.BindSystem(w)
return w, err
}

@ -1 +1 @@
Subproject commit bd947baa4edadb6b7bd059f6e324fb20f8171f8f Subproject commit e83feb89dd84e3456aafebb7d6dbe179675344e8

View File

@ -1,4 +1,4 @@
package repo package modelrepo
import "testing" import "testing"

View File

@ -1,4 +1,4 @@
package repo package modelrepo
// 构建错误记录 // 构建错误记录
type ErrorRecord struct { type ErrorRecord struct {

View File

@ -1,4 +1,4 @@
package repo package modelrepo
import ( import (
"fmt" "fmt"
@ -6,7 +6,7 @@ import (
"strconv" "strconv"
"strings" "strings"
"joylink.club/rtsssimulation/cgrepo/dto" "joylink.club/rtsssimulation/modelrepo/dto"
) )
// 城轨uid // 城轨uid

57
modelrepo/manage.go Normal file
View File

@ -0,0 +1,57 @@
package modelrepo
import "sync"
// Repo管理
type repoManager struct {
repoMap map[string]Repo
lock sync.Mutex
}
var defaultManager = &repoManager{
repoMap: make(map[string]Repo),
}
// 获取Repo
func GetRepo(id string) Repo {
manager := defaultManager
manager.lock.Lock()
defer manager.lock.Unlock()
r, ok := manager.repoMap[id]
if !ok {
return nil
}
return r
}
// 保存Repo
func SaveRepo(r Repo) {
manager := defaultManager
manager.lock.Lock()
defer manager.lock.Unlock()
manager.repoMap[r.Id()] = r
}
// 移除Repo
func RemoveRepo(id string) {
manager := defaultManager
manager.lock.Lock()
defer manager.lock.Unlock()
delete(manager.repoMap, id)
}
// 获取或构建Repo,若存在则返回已存在的,若不存在则构建保存并返回
func GetOrBuildRepo(id string, builder func() (Repo, error)) (Repo, error) {
r := GetRepo(id)
if r == nil {
// 构建模型Repo
r, err := builder()
// 构建出错直接返回
if err != nil {
return nil, err
}
// 保存
SaveRepo(r)
}
return r, nil
}

View File

@ -0,0 +1,22 @@
package model
// 开关
type PowerSwitch interface {
Model
// 编号
Code()
}
// 信号状态表示灯
type Lamp interface {
Model
// 编号
Code()
}
// 蜂鸣器/报警电铃
type Buzzer interface {
Model
// 编号
Code()
}

12
modelrepo/model/ibp.go Normal file
View File

@ -0,0 +1,12 @@
package model
// IBP盘(综合后备盘)
type Ibp interface {
Model
// 获取所有开关
GetPowerSwitches() []PowerSwitch
// 获取所有信号状态表示灯
GetLamps() []Lamp
// 获取所有蜂鸣器
GetBuzzer() []Buzzer
}

View File

@ -1,6 +1,6 @@
package model package model
// 站台屏蔽门 // 站台屏蔽门
type PSD interface { type Psd interface {
Model Model
} }

32
modelrepo/model/relay.go Normal file
View File

@ -0,0 +1,32 @@
package model
// 继电器位置
type Relay_Position int
const (
// 继电器位置-后(表示落下/反位)
RelayPos_H Relay_Position = 0
// 继电器位置-前(表示吸起/定位)
RelayPos_Q Relay_Position = 1
)
// 继电器型号
type Relay_Model int
const (
RelayModel_JPXC_1000 Relay_Model = 1
RelayModel_JPXC_1700 Relay_Model = 2
RelayModel_JWJXC_480 Relay_Model = 3
RelayModel_JWJXC_H125_80 Relay_Model = 4
RelayModel_JWXC_1700 Relay_Model = 5
RelayModel_JWXC_H340 Relay_Model = 6
RelayModel_JYJXC_160_260 Relay_Model = 7
RelayModel_JZXC_H18 Relay_Model = 8
)
// 继电器
type Relay interface {
Model
Code()
Model() Relay_Model
}

View File

@ -7,21 +7,23 @@ type Station interface {
Name() string Name() string
// 是否设备集中站 // 是否设备集中站
IsEcs() bool IsEcs() bool
// 获取IBP
GetIbp() Ibp
} }
// 设备集中站 // 设备集中站(Equipment centralized station)
type Ecs interface { type EcStation interface {
Station Station
// 获取所有道岔 // 获取所有道岔
Turnouts() []Turnout GetTurnouts() []Turnout
// 获取所有信号机 // 获取所有信号机
Signals() []Signal GetSignals() []Signal
// 获取所有站台屏蔽门 // 获取所有站台屏蔽门
PSDs() []PSD GetPsds() []Psd
// 获取所有物理检测区段 // 获取所有物理检测区段
PhysicalSections() []PhysicalSection GetPhysicalSections() []PhysicalSection
// 获取联锁驱采表 // 获取联锁驱采表
CiQCTable() GetCiQCTable()
} }
// 联锁驱采表 // 联锁驱采表
@ -42,5 +44,5 @@ type CiCJPos interface {
// 继电器uid // 继电器uid
RelayId() string RelayId() string
// 继电器位置 // 继电器位置
Pos() RelayPosition Pos() Relay_Position
} }

View File

@ -16,9 +16,9 @@ const (
type Turnout_Port int type Turnout_Port int
const ( const (
TPort_A Turnout_Port = 0 TPort_A Turnout_Port = 1
TPort_B Turnout_Port = 1 TPort_B Turnout_Port = 2
TPort_C Turnout_Port = 2 TPort_C Turnout_Port = 3
) )
// 道岔牵引类型 // 道岔牵引类型
@ -26,9 +26,9 @@ type TurnoutTractionType int
const ( const (
// ZDJ9单机牵引 // ZDJ9单机牵引
TTT_ZDJ9_1 TurnoutTractionType = 0 TTT_ZDJ9_1 TurnoutTractionType = 1
// ZDJ9双机牵引 // ZDJ9双机牵引
TTT_ZDJ9_2 TurnoutTractionType = 1 TTT_ZDJ9_2 TurnoutTractionType = 2
) )
// 道岔 // 道岔

View File

@ -3,8 +3,8 @@ package modelimpl
import ( import (
"sync/atomic" "sync/atomic"
"joylink.club/rtsssimulation/cgrepo/dto" "joylink.club/rtsssimulation/modelrepo/dto"
"joylink.club/rtsssimulation/cgrepo/model" "joylink.club/rtsssimulation/modelrepo/model"
) )
// link生成uid基础值 // link生成uid基础值

View File

@ -1,7 +1,7 @@
package modelimpl package modelimpl
import ( import (
"joylink.club/rtsssimulation/cgrepo/model" "joylink.club/rtsssimulation/modelrepo/model"
) )
type PhysicalSection struct { type PhysicalSection struct {

View File

@ -1,6 +1,6 @@
package modelimpl package modelimpl
import "joylink.club/rtsssimulation/cgrepo/model" import "joylink.club/rtsssimulation/modelrepo/model"
var _turnout model.Turnout = (*Turnout)(nil) var _turnout model.Turnout = (*Turnout)(nil)

View File

@ -1,14 +1,18 @@
package repo package modelrepo
import "joylink.club/rtsssimulation/cgrepo/model" import "joylink.club/rtsssimulation/modelrepo/model"
type CgRepo interface { type Repo interface {
// 模型仓库id // 模型仓库id
Id() string Id() string
// 获取所有设备集中站
GetEcses() []model.EcStation
// 获取所有道岔 // 获取所有道岔
Turnouts() []model.Turnout GetTurnouts() []model.Turnout
// 通过uid查询模型对象 // 获取所有信号机
FindByUid(uid string) model.Model GetSignals() []model.Signal
// 获取所有站台屏蔽门
GetPsds() []model.Psd
} }
type IdMap interface { type IdMap interface {
@ -27,7 +31,7 @@ type IdMap interface {
// turnoutMap map[string]*impl.Turnout // 道岔map,key为uid // turnoutMap map[string]*impl.Turnout // 道岔map,key为uid
// } // }
// func BuildFrom(msgs *dto.CgRepo) (CgRepo, *ErrorRecord) { // func BuildFrom(msgs *dto.modelrepo) (modelrepo, *ErrorRecord) {
// errRecord := NewErrorRecord() // errRecord := NewErrorRecord()
// idMapping := BuildIdMapping(msgs, errRecord) // idMapping := BuildIdMapping(msgs, errRecord)
// if errRecord.HasError() { // if errRecord.HasError() {

View File

@ -5,7 +5,7 @@ package message;
option go_package = "./repo/dto"; option go_package = "./repo/dto";
// //
message CgRepo { message modelrepo {
string id = 1; string id = 1;
// 线 // 线
repeated Line lines = 2; repeated Line lines = 2;

View File

@ -27,6 +27,7 @@ message Repository {
string mainCoordinateSystem = 20; string mainCoordinateSystem = 20;
repeated Key Keys = 21; repeated Key Keys = 21;
repeated CentralizedStationRef CentralizedStationRefs = 22; repeated CentralizedStationRef CentralizedStationRefs = 22;
repeated Route routes = 23;
//ISCS [300,500] //ISCS [300,500]
//ISCS管线 //ISCS管线
repeated Pipe pipes = 300; repeated Pipe pipes = 300;
@ -501,10 +502,16 @@ message Mkx {
} }
// //
message Platform { message Platform {
enum PlatformDirection {
Unknown = 0;
Up = 1; //
Down = 2; //
}
string id = 1; string id = 1;
string code = 2; string code = 2;
string stationId = 3; string stationId = 3;
string physicalSectionId = 4; string physicalSectionId = 4;
PlatformDirection direction = 5;
} }
// //
@ -558,6 +565,29 @@ message CiSectionCodePoint{
string sectionId = 2;//id string sectionId = 2;//id
} }
//
message Route {
enum RouteType {
RECEIVING = 0;
DEPARTURE = 1;
SHUNTING = 2;
PASS = 3;
LONG_SHUNTING = 4;
}
string id = 1;
string name = 2;
//
string startId = 3;
//
string destinationId = 4;
// ID
repeated string deviceIds = 5;
// ID
repeated string conflictingRouteIds = 6;
//
RouteType routeType = 7;
}
//////////////////////////ISCS/////////////////////////////////// //////////////////////////ISCS///////////////////////////////////
@ -737,3 +767,4 @@ message GasEnvironment{
string id = 1; string id = 1;
string code = 2; string code = 2;
} }

View File

@ -0,0 +1,33 @@
package cbtc_sys
import (
"github.com/yohamta/donburi"
"joylink.club/ecs"
"joylink.club/ecs/filter"
"joylink.club/rtsssimulation/component"
)
// 列车运行控制组件,给列车增加限制组件
type TrainRunControlSys struct {
trainQuery *ecs.Query
}
func NewTrainRunControlSys() *TrainRunControlSys {
return &TrainRunControlSys{
trainQuery: ecs.NewQuery(filter.Contains(component.TrainRunStatusType)),
}
}
func (sls *TrainRunControlSys) Update(w ecs.World) {
sls.trainQuery.Each(w, func(e *donburi.Entry) {
runStatus := component.TrainRunStatusType.Get(e)
headDevice := runStatus.HeadPosition.Device
// 限速赋值
if headDevice.HasComponent(component.SpeedLimitType) { // 车头所在设备有限速组件
speedLimit := component.SpeedLimitType.Get(headDevice)
runStatus.SpeedMax = speedLimit.Val
} else {
runStatus.SpeedMax = component.TrainSpeedMax
}
})
}

View File

@ -2,25 +2,19 @@ package sys
import ( import (
"joylink.club/ecs" "joylink.club/ecs"
"joylink.club/ecs/filter" "joylink.club/rtsssimulation/component/singleton"
"joylink.club/rtsssimulation/component"
) )
// 世界世界更新系统 // 世界时间更新系统
type WorldTimeSys struct { type WorldTimeSys struct {
query *ecs.Query
} }
func NewWorldTimeSys() *WorldTimeSys { func NewWorldTimeSys() *WorldTimeSys {
return &WorldTimeSys{ return &WorldTimeSys{}
query: ecs.NewQuery(filter.Contains(component.WorldDataType)),
}
} }
func (s *WorldTimeSys) Update(w ecs.World) { func (s *WorldTimeSys) Update(w ecs.World) {
entry, _ := s.query.First(w) singleton.GetWorldTime(w).Run(w.Tick())
data := component.WorldDataType.Get(entry)
data.Time += int64(w.Tick())
// t := time.UnixMilli(data.Time) // t := time.UnixMilli(data.Time)
// fmt.Println(t) // fmt.Println(t)
} }